Word arounds for incorrect result with uint128_t on PPC64?
Jeffrey Walton
noloader@gmail.com
Sat May 13 04:34:00 GMT 2017
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;
}
More information about the Gcc-help
mailing list