4 ms·
Is there an example of actually helpful and practical enabled-by-undefined-behavior optimization in C/C++? All I can remember are discussions of its pitfalls, l
by rini17 7y ago
Is there an example of actually helpful and practical enabled-by-undefined-behavior optimization in C/C++? All I can remember are discussions of its pitfalls, like this.
- steveklabnik 7y agoOne classic helpful example that gets brought up is integer overflow and loops. Because overflow is undefined in C and C++, the loop doesn’t need to check for it on each iteration.
- mhh__ 7y agohttps://d.godbolt.org/z/_r6C9N https://d.godbolt.org/z/_r6C9N Example of an Integer overflow based optimization
- rini17 7y agoThis is considered a practical example? Regardless, checking a register or hot value already in cache against a constant is free on modern CPUs.
- mhh__ 7y agoIt's not a practical example but it's relatively non trivial e.g. some otherwise good compilers can't figure that one out.
- andreareina 7y agoWait, how does that work? Without overflow, how does the compiler prove that eventually x == 7?
- cryptonector 7y agoIf x <= 7 then the answer will be 420, but if x > 7 then behavior is undefined because x will overflow, and x is signed, and signed integer overflow is UB in C, so the compiler is free to, for example, conclude that blazeit() is never called with x > 7, thus it can prove that blazeit() always returns 420. Besides, if the compiler chooses to implement signed integer overflow much like unsigned integer overflow, then x will eventually come around to 7 anyways, so the answer must be 420.
- rini17 7y agoThen later, after some minor unrelated change, compiler stops optimizing and it suddenly starts overflowing the stack. How can anyone put up with that?
- mhh__ 7y agoIf you rely on an optimization like this, that's not a code smell as much as a code-sewer: This is one of those optimizations that a very clever compiler might be able to do interprocedurally give a certain input for example.
- cryptonector 7y agoI expect the compiler would optimize the tail recursion into a loop, so the likely worst case is not that you blow the stack but that you spin for a while.
- rini17 7y agoNot really, any expectations here are unsupported by C standards. Compiler is, by spec, allowed to do anything here.
- mhh__ 7y agoThe loop (and function) terminates when x == 7, and the compiler can show that x will be 7 at some point i.e. it knows it's on a system with overflowing integers
- jcelerier 7y agothis whole series is nice about that: http://blog.llvm.org/2011/05/what-every-c-programmer-should-know_14.html http://blog.llvm.org/2011/05/what-every-c-programmer-should-...
- pcwalton 7y agoHere's a good gist describing important loop optimizations that this enables: https://gist.github.com/rygorous/e0f055bfb74e3d5f0af20690759de5a7 https://gist.github.com/rygorous/e0f055bfb74e3d5f0af20690759...
- ralfjung 7y agoI added a few sentences about that to the post: > In the case of our example, the program actually compares such an “unobservable” bit pattern with a constant, so the compiler constant-folds the result to whatever it pleases. Because the value is allowed to be “unstable”, the compiler does not have to make a “consistent choice” for the two comparisons, which would make such optimizations much less applicable. So, one time we “look” at x the compiler can pretend it is at least 150, and then when we look at it again it is at most 120, even though x did not change. Also see http://nondot.org/sabre/LLVMNotes/UndefinedValue.txt http://nondot.org/sabre/LLVMNotes/UndefinedValue.txt.