https://gcc.gnu.org/bugzilla/show_bug.cgi?id=106542
Bug ID: 106542 Summary: -O2 sign-extended uint32 to uint64 Product: gcc Version: 9.3.1 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: wuz73 at hotmail dot com Target Milestone: --- #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.