you don't need UB for invariant optimization. What UB permits the compiler to do is INCORRECTLY assume invariance. This permits the compiler to "optimize" badly written C code in a way that silently changes its function - which I don't call an optimization.
I've done benchmarks and see no performance improvement with a small loop body. If there is a minor improvement on a trivial loop - that's not much gain.
Actually, it's even more ridiculous than that. Reading with a char * is UB. Reading with an unsigned char is not. Why? Because the C90 standard made it impossible to write memcpy in C so the committee added a hack for unsigned char .
What a great story. I'm shocked, shocked by the commercialization of art. Jeff Koons should now create Balloon Fearless Girl on Trump tower to close the circle.
But he created this false dichotomy: either GOSPLAN+ or free markets (which included government actions he didn't want to call "planning"). Government provided medical care is not equivalent to Gulag Archipelago and it can also be price sensitive.
Hayek was an absolute fabulist and quite dishonest too. His arguments against central planning rely on a sleight of hand where any government planning is identified with something like GOSPLAN under Stalin. How people using the internet, created by DARPA and NSF can fall for that is beyond me. Clearly, governments can plan well or badly. For that matter private corporations can plan well or badly - IBM and Intel have centralized planning on an immense scale.
I can't think of Hayek without being reminded of his claim that personal freedom in Pinochet's torture state was greater than that under the previous government where people were not getting their eyeballs pulled out and genitals shocked for disagreeing with the State.
That's a different question and I think the answer to that is obviously complex, but a lot of it is luck. If the Dutch and Portugese had shown up in the Indian ocean while Ming were still engaged, they would have had a rude shock. Otherwise, historians have looked at factors like the location of iron in China (further from population centers) and timing of major epidemics. One really interesting book is
Go to any major European city. Look at all the loot in the museums. Figure it out.
Mea culpa - too snarky. But there is a lot of research in this field and way too much self congratulatory material. A look at the Opium Wars should be enough to convince that more guns goes a long way to an explanation. Also Graeber's "Debt" gives some sense of how Europe managed to construct an economy that produced a desperation for loot that was quite remarkable.
So the standard does not require the compiler to e.g. remove the "redundant" check for null or assume that signed integers don't cycle values on overflow, but _permits_ the compiler to do so. Thus, we have two problems: a poorly thought out standard which permits dangerous compiler behavior and poorly thought out compiler that jumps at the chance.
In the referenced case the introduced error involved a reference to a null pointer but there was still no exploitable security hole. The exploit was enabled when the compiler removed an explicit check. The null dereference was an error, but it was not a security issue on its own.
The compiler converted a buggy program that was prevented from opening a security hole by defense in depth into a program with a security hole. It transformed a careless error into a systemic error, all in the cause of a micro-optimization that didn't.
C is not Haskell or Java. The C programmer may intend to interact with actual hardware and is not required to interact with some abstract machine. The standard can reflect this or it can attempt to convert C into a poorly designed high level language. Dereferencing the null pointer should be implementation dependent, but the compiler should be required to either detect and flag this as an error or compile it into the machine operations indicated. The actual execution in the second case may depend on the environment.
I didn't make it up in my head - I observed it in working code. Widely used working code. And the compiler is not at all forced to assume x is not null. The standard leaves it to the compiler writer to handle the case. Could the compiler perform sophisticated static analysis and reject the code under the standard? Yes. Could the compiler simply compile the code as written ? Yes. Could the compiler abuse the vagueness of the standard to produce an "optimization" that implements something the programmer specifically did not implement? I suppose. But that's poor engineering.
I'm sorry, but that is not what the current standard, no matter its weaknesses, requires. The standard says that dereferencing a null pointer results in undefined behavior. The compiler writer chose to (a) deduce that the pointer dereference was not an oversight and (b) then produce a pointless "optimization" that compounded the error. Compiling the dereference to a move instruction is perfectly compatible with the standard.
Actually that's not correct. The standard says the behavior is up to the compiler. The compiler author took that as a license to produce a non truth preserving transformation of the code. The actual current clang behavior also satisfies the standard as written.