I encountered a problem where g++ optimized out something it should not have. I reduced the problem to the following example:
I have a static lib with a function *bool my_magic_function(int x)**, which decrements x by 1 if it can, otherwise (x == INT_MIN), it returns false and does not touch the original value.
If I use the function in a debug build, then it works as expected. But in release build the check is optimized away. Platform:
On RHEL 9.3 with g++ (GCC) 11.4.1 20230605 -> Problem present
Ubuntu 22.04 g++ 11.4.0 g++ or 10.5.0 g++ -> Problem present
Ubuntu 22.04 g++ 9.5.0 -> Code works as expected in release too.
Here is a minimal example with a static lib and a simple main.cpp using the function:
almalib.h:
bool my_magic_function(int* x);
almalib.cc:
#include "almalib.h"
#include <cstring>
#include <limits>
bool my_magic_function(int* x) {
int cp_new;
// integer overflow is undefined, so lets make sure it becomes int max
if (*x == std::numeric_limits<int>::lowest()) {
cp_new = std::numeric_limits<int>::max();
} else {
cp_new = *x - 1;
}
if (cp_new < *x) {
*x = cp_new;
return true;
}
return false;
}
main.cpp
#include "almalib.h"
#include <iostream>
#include <limits>
int main()
{
for (int x : {0, std::numeric_limits<int>::lowest()})
{
int x2 = x;
std::cerr << "Res for " << x << " " << (my_magic_function(&x2) ? "OK" : "NOT_OK") << " val: " << x2 << std::endl;
}
}
Compile:
g++ -c almalib.cc -o almalib.o
ar crf libalma.a almalib.o
g++ main.cpp -o run -L. -lalma
g++ -c almalib.cc -O3 -o almalibR.o
ar crf libalmaR.a almalibR.o
g++ main.cpp -O3 -o runR -L. -lalmaR
outout for Debug (./run):
Res for 0 OK val: -1
Res for -2147483648 NOT_OK val: -2147483648
output for Release (./runR):
Res for 0 OK val: -1
Res for -2147483648 OK val: 2147483647
going through the generated assembly with gdb, my_magic_function is reduced to 3 lines:
0x401320 <_Z17my_magic_functionPi> subl $0x1,(%rdi)
0x401323 <_Z17my_magic_functionPi+3> mov $0x1,%eax
0x401328 <_Z17my_magic_functionPi+8> ret
My questions are:
- Is this a known issue?
- What are my options to prevent it from happening? (I can trivially rewrite the example function, but not the original problem). Are there any compiler hints, or should I disable a certain optimalization type?