re PR middle-end/69546 (wrong code with -O and simple int128 arithmetics)
authorJakub Jelinek <jakub@redhat.com>
Sat, 30 Jan 2016 18:04:13 +0000 (19:04 +0100)
committerJakub Jelinek <jakub@gcc.gnu.org>
Sat, 30 Jan 2016 18:04:13 +0000 (19:04 +0100)
PR tree-optimization/69546
* wide-int.cc (wi::divmod_internal): For unsigned division
where both operands fit into uhwi, if o1 is 1 and o0 has
msb set, if divident_prec is larger than bits per hwi,
clear another quotient word and return 2 instead of 1.
Similarly for remainder with msb in HWI set, if dividend_prec
is larger than bits per hwi.

* gcc.dg/torture/pr69546.c: New test.

From-SVN: r233012

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/torture/pr69546-1.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/torture/pr69546-2.c [new file with mode: 0644]
gcc/wide-int.cc

index 1d60690d27c56a7a6a07dc028caa0649e3e4ef1d..0d405cdcbd51533e897639cf235813c04df7cf23 100644 (file)
@@ -1,3 +1,13 @@
+2016-01-30  Jakub Jelinek  <jakub@redhat.com>
+
+       PR tree-optimization/69546
+       * wide-int.cc (wi::divmod_internal): For unsigned division
+       where both operands fit into uhwi, if o1 is 1 and o0 has
+       msb set, if divident_prec is larger than bits per hwi,
+       clear another quotient word and return 2 instead of 1.
+       Similarly for remainder with msb in HWI set, if dividend_prec
+       is larger than bits per hwi.
+
 2016-01-29  Martin Jambor  <mjambor@suse.cz>
 
        * hsa-gen.c (get_memory_order_name): Mask with MEMMODEL_BASE_MASK.
index df468e11db8d0cb25bada8eb8483b249085f18c6..63a4bfa16f928e50bc88df9dffba384860e22006 100644 (file)
@@ -1,3 +1,8 @@
+2016-01-30  Jakub Jelinek  <jakub@redhat.com>
+
+       PR tree-optimization/69546
+       * gcc.dg/torture/pr69546.c: New test.
+
 2016-01-30  Paul Thomas  <pault@gcc.gnu.org>
 
        PR fortran/69566
diff --git a/gcc/testsuite/gcc.dg/torture/pr69546-1.c b/gcc/testsuite/gcc.dg/torture/pr69546-1.c
new file mode 100644 (file)
index 0000000..39db179
--- /dev/null
@@ -0,0 +1,26 @@
+/* PR tree-optimization/69546 */
+/* { dg-do run { target int128 } } */
+
+unsigned __int128 __attribute__ ((noinline, noclone))
+foo (unsigned long long x)
+{
+  unsigned __int128 y = ~0ULL;
+  x >>= 63;
+  return y / (x | 1);
+}
+
+unsigned __int128 __attribute__ ((noinline, noclone))
+bar (unsigned long long x)
+{
+  unsigned __int128 y = ~33ULL;
+  x >>= 63;
+  return y / (x | 1);
+}
+
+int
+main ()
+{
+  if (foo (1) != ~0ULL || bar (17) != ~33ULL)
+    __builtin_abort ();
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pr69546-2.c b/gcc/testsuite/gcc.dg/torture/pr69546-2.c
new file mode 100644 (file)
index 0000000..f004310
--- /dev/null
@@ -0,0 +1,18 @@
+/* PR tree-optimization/69546 */
+/* { dg-do run { target int128 } } */
+
+unsigned __int128
+foo (void)
+{
+  unsigned __int128 a = 0xfffffffffffffffeULL;
+  unsigned __int128 b = 0xffffffffffffffffULL;
+  return a % b;
+}
+
+int
+main ()
+{
+  if (foo () != 0xfffffffffffffffeULL)
+    __builtin_abort ();
+  return 0;
+}
index 195ac26fa561759f4edad0e9cc3f7cef53660475..5fcec2ee790ddfc29a401d42c5f2c0f815709d7b 100644 (file)
@@ -1788,15 +1788,32 @@ wi::divmod_internal (HOST_WIDE_INT *quotient, unsigned int *remainder_len,
     {
       unsigned HOST_WIDE_INT o0 = dividend.to_uhwi ();
       unsigned HOST_WIDE_INT o1 = divisor.to_uhwi ();
+      unsigned int quotient_len = 1;
 
       if (quotient)
-       quotient[0] = o0 / o1;
+       {
+         quotient[0] = o0 / o1;
+         if (o1 == 1
+             && (HOST_WIDE_INT) o0 < 0
+             && dividend_prec > HOST_BITS_PER_WIDE_INT)
+           {
+             quotient[1] = 0;
+             quotient_len = 2;
+           }
+       }
       if (remainder)
        {
          remainder[0] = o0 % o1;
-         *remainder_len = 1;
+         if ((HOST_WIDE_INT) remainder[0] < 0
+             && dividend_prec > HOST_BITS_PER_WIDE_INT)
+           {
+             remainder[1] = 0;
+             *remainder_len = 2;
+           }
+         else
+           *remainder_len = 1;
        }
-      return 1;
+      return quotient_len;
     }
 
   /* Make the divisor and dividend positive and remember what we