On December 31, 2020 10:31:00 AM GMT+01:00, Jakub Jelinek <ja...@redhat.com> 
wrote:
>Hi!
>
>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?)

The mpz use predates wide int and double int wasn't enough. 

 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).
>
>Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

Ok. 

Richard. 

>2020-12-31  Jakub Jelinek  <ja...@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.
>
>--- gcc/wide-int.cc.jj 2020-12-30 10:31:33.402981204 +0100
>+++ gcc/wide-int.cc    2020-12-30 10:44:57.628947066 +0100
>@@ -230,6 +230,20 @@ wi::to_mpz (const wide_int_ref &x, mpz_t
>  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);
> }
>--- gcc/testsuite/gcc.c-torture/execute/pr98474.c.jj   2020-12-30
>10:53:31.847166586 +0100
>+++ gcc/testsuite/gcc.c-torture/execute/pr98474.c      2020-12-30
>10:55:52.542584936 +0100
>@@ -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;
>+}
>
>       Jakub

Reply via email to