One of the questions that I asked some time ago had undefined behavior, so compiler optimization was actually causing the program to break.
But if there is no undefi
Just happened to me. The code generated by swig for interfacing Java is correct but won't work with -O2 on gcc.
The reason is that you develop one application (debug build) and your customers run completely different application (release build). If testing resources are low and/or compiler used is not very popular, I would disable optimization for release builds.
MS publishes numerous hotfixes for optimization bugs in their MSVC x86 compiler. Fortunately, I've never encountered one in real life. But this was not the case with other compilers. SH4 compiler in MS Embedded Visual C++ was very buggy.
There is an example, why sometimes is dangerous using optimization flag and our tests should cover most of the code to notice such an error.
Using clang (because in gcc even without optimization flag, makes some iptimizations and the output is corrupted):
File: a.cpp
#include <stdio.h>
int puts(const char *str) {
fputs("Hello, world!\n", stdout);
return 1;
}
int main() {
printf("Goodbye!\n");
return 0;
}
Without -Ox flag:
> clang --output withoutOptimization a.cpp; ./withoutOptimization
> Goodbye!
With -Ox flag:
> clang --output withO1 -O1 a.cpp; ./withO1
> Hello, world!
Simple. Compiler optimization bugs.
One example is short-circuit boolean evaluation. Something like:
if (someFunc() && otherFunc()) {
...
}
A 'smart' compiler might realize that someFunc will always return false for some reason, making the entire statement evaluate to false, and decide to not call otherFunc to save CPU time. But if otherFunc contains some code that directly affects program execution (maybe it resets a global flag or something), it now won't perform that step and you program enters an unknown state.
In case 2, imagine some OS code that deliberately changes pointer types. The optimizer can assume that objects of the wrong type could not be referenced and generate code that aliases changing memory values in registers and gets the "wrong"1 answer.
Case 3 is an interesting concern. Sometimes optimizers make code smaller but sometimes they make it bigger. Most programs are not the least bit CPU-bound and even for the ones that are, only 10% or less of the code is actually computationally-intensive. If there is any downside at all to the optimizer then it is only a win for less than 10% of a program.
If the generated code is larger, then it will be less cache-friendly. This might be worth it for a matrix algebra library with O(n3) algorithms in tiny little loops. But for something with more typical time complexity, overflowing the cache might actually make the program slower. Optimizers can be tuned for all this stuff, typically, but if the program is a web application, say, it would certainly be more developer-friendly if the compiler would just do the all-purpose things and allow the developer to just not open the fancy-tricks Pandora's box.
1. Such programs are usually not standard-conforming so the optimizer is technically "correct", but still not doing what the developer intended.