public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc r8-10872] wide-int: Fix wi::to_mpz [PR98474]
@ 2021-04-22 16:49 Jakub Jelinek
  0 siblings, 0 replies; only message in thread
From: Jakub Jelinek @ 2021-04-22 16:49 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:8cbe9fc12453026f7efc02dad569c6270d595427

commit r8-10872-g8cbe9fc12453026f7efc02dad569c6270d595427
Author: Jakub Jelinek <jakub@redhat.com>
Date:   Thu Dec 31 11:06:56 2020 +0100

    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.
    
    (cherry picked from commit a4d191d08c6acb24034af4182b3524e6ef97546c)

Diff:
---
 gcc/testsuite/gcc.c-torture/execute/pr98474.c | 30 +++++++++++++++++++++++++++
 gcc/wide-int.cc                               | 14 +++++++++++++
 2 files changed, 44 insertions(+)

diff --git a/gcc/testsuite/gcc.c-torture/execute/pr98474.c b/gcc/testsuite/gcc.c-torture/execute/pr98474.c
new file mode 100644
index 00000000000..8c287994580
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/pr98474.c
@@ -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;
+}
diff --git a/gcc/wide-int.cc b/gcc/wide-int.cc
index d686d7dfbe5..eb5eec4a4a6 100644
--- a/gcc/wide-int.cc
+++ b/gcc/wide-int.cc
@@ -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);
 }


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2021-04-22 16:49 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-04-22 16:49 [gcc r8-10872] wide-int: Fix wi::to_mpz [PR98474] Jakub Jelinek

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).