> It also constrains some optimizations like reordering.
Ha! As if C compilers really cared about correctness. This is why type-punning and aliasing memory through different typed pointers is fraught with peril, often UB. It's so C compilers can cheat and use type-based alias analysis, breaking programs that have "UB" but would work absolutely fine if the compiler wasn't so aggressive.
In general, almost all arguments between language design and optimization for C/C++ are settled with "let's not think too hard about how to help users; go ahead and optimize this and make it their fault (UB) when they observe the hard cases". It's so rude.
This is roughly what happens, but you shouldn't attribute this to rudeness. Compiler users also demand performance. They compare implementations (and languages) and point out when such-and-such is X% slower. They file bugs about "missed" optimizations and "unnecessary" instructions.
C is especially awkward here, because compilers are expected to precisely conform the C specification, but at the same time C users don't actually want to program for the abstract machine from the C specification (the one that can't overflow signed integers or shift by a full int width). C users expect their programs to actually behave like programs for a particular hardware they target, without any overhead or discrepancy from "emulating" the imaginary C-spec machine. In face of such conflicting requirements, C compilers will always be forced to balance performance, predictability, conformance, and compatibility.
You make some good points. C was often used in the situation where "Hey, we just built this enormous supercomputer for LLNL, let's make this C program run as fast as possible on this one machine. Compiler team, please do everything possible to get the maximum performane out of this machine." I feel like a lot has followed from this repeating dozens of times over the past few decades. Performance has been the #1 priority, above all else, and it shows.
Not sure if the S-1 is a good example — IIRC it still had a 36-bit word and was mainly intended for pl1 and lisp (I only really saw it from the S-1 Lisp side). Was there evening a C for it? It would have been as bad as running C on a Cray YMP (which I mention above)
Ha! As if C compilers really cared about correctness. This is why type-punning and aliasing memory through different typed pointers is fraught with peril, often UB. It's so C compilers can cheat and use type-based alias analysis, breaking programs that have "UB" but would work absolutely fine if the compiler wasn't so aggressive.
In general, almost all arguments between language design and optimization for C/C++ are settled with "let's not think too hard about how to help users; go ahead and optimize this and make it their fault (UB) when they observe the hard cases". It's so rude.