I had to code some checking routines and they appear to behave differently if one uses -O0, -O1, -O2 or -O3.
Below I created a minimal example that works fine for -O0 and -O1. But using -O2 or -O3 the behavior changed. In the -O0 and -O1 case, the for-loop increments the integer and the first time it gets to the maximum, the overflow happens and the check routine triggers. In the other case the for-loop never breaks, although the integer gets negative.
#include <iostream>
inline bool check(const int i) {
if (i < 0)
return false;
else
return true;
}
int main() {
for (int i = 0;; i += 50000000) {
std::cout << i << std::endl;
const bool succ = check(i);
if (succ == false) {
std::cout << "Overflow: " << i << std::endl;
break;
}
}
return 0;
}
Why is the compiler allowed to optimize this away?
Trying with gcc, clang and icc, only the icc does it correct in all optimization variants the other two did not.
Signed integer overflow gives undefined behavior. Thus, the compiler has free reign to implement this case as they like.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With