Data races are undefined behavior in the C/C++ legalese sense of compilers are not required to preserve the semantics of the abstract machine when they occur.
Where this behavior is useful would be situations like traps: if you've got a potentially-trapping instruction (say, division) whose result isn't used, you can delete that instruction even if you can't prove that it never traps. The problem that arose more recently is that compilers began to feed these assumptions into their value analysis (oh look, you said int a = b / c, therefore c ≠ 0), and turning these into code-chomping bits.
Data races are the kind of undefined behavior that are too hard to constrain by specification. While the hardware semantics of data races are simple enough to specify (basically memory_order_relaxed with word tearing), mapping source-level reads/writes to hardware loads and stores isn't easy. Java tried and still got it wrong.
You don't have to worry about the "the compiler proved a data race happened and turned my program garbage" happening, at least any time in the next decade or so. The compiler would have to be able to identify which code fragments must be running concurrently in different threads without appropriate happens-before links, which is beyond the capabilities of anything someone will put even in a -O3 compiler flag.
Where this behavior is useful would be situations like traps: if you've got a potentially-trapping instruction (say, division) whose result isn't used, you can delete that instruction even if you can't prove that it never traps. The problem that arose more recently is that compilers began to feed these assumptions into their value analysis (oh look, you said int a = b / c, therefore c ≠ 0), and turning these into code-chomping bits.
Data races are the kind of undefined behavior that are too hard to constrain by specification. While the hardware semantics of data races are simple enough to specify (basically memory_order_relaxed with word tearing), mapping source-level reads/writes to hardware loads and stores isn't easy. Java tried and still got it wrong.
You don't have to worry about the "the compiler proved a data race happened and turned my program garbage" happening, at least any time in the next decade or so. The compiler would have to be able to identify which code fragments must be running concurrently in different threads without appropriate happens-before links, which is beyond the capabilities of anything someone will put even in a -O3 compiler flag.