We have some self tests failing on GCC compile farm host gcc110. Its a POWER7 machine running Fedora 20. When I run the program below with the default compiler, GCC 4.8, I arrive at the wrong result. The program rounds the first number up to the second number. The result below should be the pair (1,8), not (1,7): gcc1-power7]$ ./test.exe 00000000000000000000000000000001 00000000000000000000000000000007 Using GCC 7.1 in /opt on gcc110 produces the expected result. Running on other machines, like x86_64 produces the expected result. Changing optimization levels does not help the problem under GCC 4.8. The GCC bugzilla is timing out, so I'm having trouble searching it. Does anyone know what the issue is, and is there a way to work around it? ========== Command line: g++ -g2 -O5 -Wall -Wextra test.cxx -o test.exe Test program: $ cat test.cxx #include <iostream> #include <iomanip> #include <limits> #include <stdexcept> #include <stdint.h> #include <assert.h> using namespace std; #if (__SIZEOF_INT128__ >= 16) # define INT128_AVAILABLE 1 typedef __uint128_t word128; #endif template<class T> T NumericLimitsMax() { assert(std::numeric_limits<T>::is_specialized); return (std::numeric_limits<T>::max)(); }; template <class T> inline bool IsPowerOf2(const T &value) { return value > 0 && (value & (value-1)) == 0; } template <class T1, class T2> inline T2 ModPowerOf2(const T1 &a, const T2 &b) { return T2(a) & (b-1); } template <class T1, class T2> inline T1 RoundDownToMultipleOf(const T1 &n, const T2 &m) { assert(!std::numeric_limits<T1>::is_signed || n > 0); assert(!std::numeric_limits<T2>::is_signed || m > 0); if (IsPowerOf2(m)) return n - ModPowerOf2(n, m); else return n - n%m; } template <class T1, class T2> inline T1 RoundUpToMultipleOf(const T1 &n, const T2 &m) { // Overflow detection omitted return RoundDownToMultipleOf(T1(n+m-1), m); } inline ostream& operator<<(ostream& stm, const word128& val) { uint64_t h = (uint64_t)(val >> 64U); uint64_t l = (uint64_t)val; stm << hex << setfill('0') << setw(16) << h; stm << hex << setfill('0') << setw(16) << l; return stm; } int main(int argc, char* argv[]) { word128 x = 1, b = 8; cout << hex << x << endl; cout << RoundUpToMultipleOf(x, b) << endl; return 0; }