5 ms·
Global optimizations mostly do not rely on UB in order to get speed-ups, so this is not an A:B test of the value of UB.
by pizlonator 10y ago
Global optimizations mostly do not rely on UB in order to get speed-ups, so this is not an A:B test of the value of UB.
- dbaupp 10y agoI think the parent meant (global (optimisation flags)), not ((global optimisation) flags). Of course, some optimisations don't rely on UB, the difference between the unoptimised and optimised code won't be entirely based on UB (a more reasonable comparison for one single type of UB would be passing -fwrapv vs. not, to stop the compiler thinking signed integers never wrap).
- DannyBee 10y ago"Global optimizations mostly do not rely on UB in order to get speed-ups, so this is not an A:B test of the value of UB. " [Citation needed] They most certainly do rely on UB to move statements past other statements, to delete dead code, etc. If you want a source: I've written all or parts of gcc's statement sinking, partial redundancy elimination, dead store elimination, alias analysis, etc. Same with LLVM. They all rely on UB being UB to be able to do their work effectively. You could never, for example, hoist a load if it wasn't UB to dereference a null pointer, unless you could prove it was non-null (and you mostly can't). You'd have to insert null checks everywhere, like java, and then try to get rid of them. You could never move anything past (up or down) an external function call if you didn't rely on UB. I could go on, but it's pretty silly. Random assertions about "optimizations taking advantage of UB don't gain performance" simply are not in accord with reality. If it wasn't true, we'd just make programming languages with no UB. It's not like compiler writers are just lazy.
- kazinator 10y agoOptimizations rely on the (often and easily wrong) assumption that the program hasn't invoked any UB.
- millstone 10y agoUnoptimized programs rely on this too. That's why stack buffer overflows are a thing.
- the_why_of_y 10y agoAlso, use-after-free is UB. I have yet to hear the argument that "unoptimized C" means using a conservative garbage collector, and a free(3) that isn't a no-op is an "optimization".
- kazinator 10y agoThe issue with UB and optimizations is that sometimes programs rely on UB deliberately. The code is actually tested in every way, and it works fine for years. Then a compiler update deliberately breaks it, oops; the optimizer now assumes that it can do anything it wants if that UB occurs.
- the_why_of_y 10y agoWell, UB is, by definition, non-portable code. Nobody who knows C should be surprised that a different compiler produces different results on such code. Or even the same compiler, targeting a different architecture. Or even the same compiler, targeting the same architecture, with different flags.
- kazinator 10y agoA lot of UB is quite portable, like, oh, converting between void * and function pointers, for instance.
- pcwalton 10y ago> If it wasn't true, we'd just make programming languages with no UB. It's not like compiler writers are just lazy. Well, we do make programming languages with no undefined behavior. :) It's just that C and C++ need UB. For instance, all your examples are things that Rust and Swift can statically prove without resorting to UB in the language semantics. Null pointer assumptions become precise with nullable types. Optimizations around opaque calls can be made sound with static knowledge of aliasing and type safety (most importantly, TBAA is a sound analysis if your language is memory safe). Signed overflow UB is less important to optimize around if programmers use proper iterator constructs so the compiler can soundly determine trip count. And so forth. (I'm sure you know all of this, just stating for the record.)
- flamedoge 10y ago'global' is usually just stitching together larger IR stream.. There is no reason not to include dependence on UB for any global opt.