mirror of
https://gcc.gnu.org/git/gcc.git
synced 2025-01-24 13:24:33 +08:00
wide-int: Fix wi::to_mpz [PR98474]
The following testcase is miscompiled, because niter analysis miscomputes the number of iterations to 0. The problem is that niter analysis uses mpz_t (wonder why, wouldn't widest_int do the same job?) and when wi::to_mpz is called e.g. on the TYPE_MAX_VALUE of __uint128_t, it initializes the mpz_t result with wrong value. wi::to_mpz has code to handle negative wide_ints in signed types by inverting all bits, importing to mpz and complementing it, which is fine, but doesn't handle correctly the case when the wide_int's len (times HOST_BITS_PER_WIDE_INT) is smaller than precision when wi::neg_p. E.g. the 0xffffffffffffffffffffffffffffffff TYPE_MAX_VALUE is represented in wide_int as 0xffffffffffffffff len 1, and wi::to_mpz would create 0xffffffffffffffff mpz_t value from that. This patch handles it by adding the needed -1 host wide int words (and has also code to deal with precision that aren't multiple of HOST_BITS_PER_WIDE_INT). 2020-12-31 Jakub Jelinek <jakub@redhat.com> PR tree-optimization/98474 * wide-int.cc (wi::to_mpz): If wide_int has MSB set, but type is unsigned and excess negative, append set bits after len until precision. * gcc.c-torture/execute/pr98474.c: New test.
This commit is contained in:
parent
a9ec9902d7
commit
9e603837f7
30
gcc/testsuite/gcc.c-torture/execute/pr98474.c
Normal file
30
gcc/testsuite/gcc.c-torture/execute/pr98474.c
Normal file
@ -0,0 +1,30 @@
|
||||
/* PR tree-optimization/98474 */
|
||||
|
||||
#ifdef __SIZEOF_INT128__
|
||||
typedef __uint128_t T;
|
||||
#define N (__SIZEOF_INT128__ * __CHAR_BIT__ / 2)
|
||||
#else
|
||||
typedef unsigned long long T;
|
||||
#define N (__SIZEOF_LONG_LONG__ * __CHAR_BIT__ / 2)
|
||||
#endif
|
||||
|
||||
__attribute__ ((noipa)) void
|
||||
foo (T *x)
|
||||
{
|
||||
*x += ((T) 1) << (N + 1);
|
||||
}
|
||||
|
||||
int
|
||||
main ()
|
||||
{
|
||||
T a = ((T) 1) << (N + 1);
|
||||
T b = a;
|
||||
T n;
|
||||
foo (&b);
|
||||
n = b;
|
||||
while (n >= a)
|
||||
n -= a;
|
||||
if ((int) (n >> N) != 0)
|
||||
__builtin_abort ();
|
||||
return 0;
|
||||
}
|
@ -230,6 +230,20 @@ wi::to_mpz (const wide_int_ref &x, mpz_t result, signop sgn)
|
||||
t[len - 1] = (unsigned HOST_WIDE_INT) v[len - 1] << excess >> excess;
|
||||
mpz_import (result, len, -1, sizeof (HOST_WIDE_INT), 0, 0, t);
|
||||
}
|
||||
else if (excess < 0 && wi::neg_p (x))
|
||||
{
|
||||
int extra
|
||||
= (-excess + HOST_BITS_PER_WIDE_INT - 1) / HOST_BITS_PER_WIDE_INT;
|
||||
HOST_WIDE_INT *t = XALLOCAVEC (HOST_WIDE_INT, len + extra);
|
||||
for (int i = 0; i < len; i++)
|
||||
t[i] = v[i];
|
||||
for (int i = 0; i < extra; i++)
|
||||
t[len + i] = -1;
|
||||
excess = (-excess) % HOST_BITS_PER_WIDE_INT;
|
||||
if (excess)
|
||||
t[len + extra - 1] = (HOST_WIDE_INT_1U << excess) - 1;
|
||||
mpz_import (result, len + extra, -1, sizeof (HOST_WIDE_INT), 0, 0, t);
|
||||
}
|
||||
else
|
||||
mpz_import (result, len, -1, sizeof (HOST_WIDE_INT), 0, 0, v);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user