#include <iostream> unsigned Msb(uint64_t x) { return 63 - __builtin_clzl(x); } template<typename T> void f(T r, T p) { if (p > r) { auto d = p - r; unsigned k = Msb(sizeof(T) == 4 ? unsigned(d) : d); std::cout << sizeof(T) << " k=" << k << "\n"; } } int main() { int data[] = {-1610499096,2086724600}; f(data[0],data[1]); } When compiled with "g++ -O2" the output is "4 k=63". Apparently before calling Msb(), g++ sign-extended unsigned(d). static_cast<unsigend>(d) yields the same result. However, "g++ -O0" is correct (k=31), so are earlier versions of g++ such as 4.8.5 and 5.3.1.
The code is undefined and can be detected with -fsanitize=undefined: /app/example.cpp:15:14: runtime error: signed integer overflow: 2086724600 - -1610499096 cannot be represented in type 'int'
(In reply to Andrew Pinski from comment #1) > The code is undefined and can be detected with -fsanitize=undefined: > > /app/example.cpp:15:14: runtime error: signed integer overflow: 2086724600 - > -1610499096 cannot be represented in type 'int' I'm only interested in the lower 32 bits, hence the unsigned(d).
The code is undefined as the subtraction is done in the int type. You either need to use -fwrapv or cast to an unsigned type before doing the subtraction.