Word arounds for incorrect result with uint128_t on PPC64?

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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;
}



[Index of Archives]     [Linux C Programming]     [Linux Kernel]     [eCos]     [Fedora Development]     [Fedora Announce]     [Autoconf]     [The DWARVES Debugging Tools]     [Yosemite Campsites]     [Yosemite News]     [Linux GCC]

  Powered by Linux