re PR target/82274 (__builtin_mul_overflow fails to detect overflow for int64_t when...
authorJakub Jelinek <jakub@redhat.com>
Fri, 13 Oct 2017 17:19:12 +0000 (19:19 +0200)
committerJakub Jelinek <jakub@gcc.gnu.org>
Fri, 13 Oct 2017 17:19:12 +0000 (19:19 +0200)
PR target/82274
* internal-fn.c (expand_mul_overflow): If both operands have
the same highpart of -1 or 0 and the topmost bit of lowpart
is different, overflow is if res <= 0 rather than res < 0.

* libgcc2.c (__mulvDI3): If both operands have
the same highpart of -1 and the topmost bit of lowpart is 0,
multiplication overflows even if both lowparts are 0.

* gcc.dg/pr82274-1.c: New test.
* gcc.dg/pr82274-2.c: New test.

From-SVN: r253734

gcc/ChangeLog
gcc/internal-fn.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/pr82274-1.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/pr82274-2.c [new file with mode: 0644]
libgcc/ChangeLog
libgcc/libgcc2.c

index 00be94fe3494a47cc924567d81f9cae25d6bb07c..b593718fa6ff1ffa2ea2a87af15b2e16e082423b 100644 (file)
@@ -1,3 +1,10 @@
+2017-10-13  Jakub Jelinek  <jakub@redhat.com>
+
+       PR target/82274
+       * internal-fn.c (expand_mul_overflow): If both operands have
+       the same highpart of -1 or 0 and the topmost bit of lowpart
+       is different, overflow is if res <= 0 rather than res < 0.
+
 2017-10-13  Pat Haugen  <pthaugen@us.ibm.com>
 
        * config/rs6000/rs6000.c (rs6000_builtin_vectorization_cost): Remove
index d9e243e154729aab97450e6c9b278954bad89ef1..ce9e8bb75e988b502714e335bd13293f4fbdc060 100644 (file)
@@ -1770,8 +1770,8 @@ expand_mul_overflow (location_t loc, tree lhs, tree arg0, tree arg1,
                }
 
              /* At this point hipart{0,1} are both in [-1, 0].  If they are
-                the same, overflow happened if res is negative, if they are
-                different, overflow happened if res is positive.  */
+                the same, overflow happened if res is non-positive, if they
+                are different, overflow happened if res is positive.  */
              if (op0_sign != 1 && op1_sign != 1 && op0_sign != op1_sign)
                emit_jump (hipart_different);
              else if (op0_sign == 1 || op1_sign == 1)
@@ -1779,7 +1779,7 @@ expand_mul_overflow (location_t loc, tree lhs, tree arg0, tree arg1,
                                         NULL_RTX, NULL, hipart_different,
                                         profile_probability::even ());
 
-             do_compare_rtx_and_jump (res, const0_rtx, LT, false, mode,
+             do_compare_rtx_and_jump (res, const0_rtx, LE, false, mode,
                                       NULL_RTX, NULL, do_error,
                                       profile_probability::very_unlikely ());
              emit_jump (done_label);
index f3dbf5d9286a2a3fa6ee44aea29ac47d4cdaa54f..d23143ad4964d5edfe4cf2fa48484fdbf3ebedf3 100644 (file)
@@ -1,3 +1,9 @@
+2017-10-13  Jakub Jelinek  <jakub@redhat.com>
+
+       PR target/82274
+       * gcc.dg/pr82274-1.c: New test.
+       * gcc.dg/pr82274-2.c: New test.
+
 2017-10-13  Paolo Carlini  <paolo.carlini@oracle.com>
 
        PR c++/80873
diff --git a/gcc/testsuite/gcc.dg/pr82274-1.c b/gcc/testsuite/gcc.dg/pr82274-1.c
new file mode 100644 (file)
index 0000000..f96b733
--- /dev/null
@@ -0,0 +1,16 @@
+/* PR target/82274 */
+/* { dg-do run } */
+/* { dg-shouldfail "trapv" } */
+/* { dg-options "-ftrapv" } */
+
+int
+main ()
+{
+#ifdef __SIZEOF_INT128__
+  volatile __int128 m = -(((__int128) 1) << (__CHAR_BIT__ * __SIZEOF_INT128__ / 2));
+#else
+  volatile long long m = -(1LL << (__CHAR_BIT__ * __SIZEOF_LONG_LONG__ / 2));
+#endif
+  m = m * m;
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/pr82274-2.c b/gcc/testsuite/gcc.dg/pr82274-2.c
new file mode 100644 (file)
index 0000000..a9643b5
--- /dev/null
@@ -0,0 +1,26 @@
+/* PR target/82274 */
+/* { dg-do run } */
+/* { dg-options "-O2" } */
+
+int
+main ()
+{
+#ifdef __SIZEOF_INT128__
+  __int128 m = -(((__int128) 1) << (__CHAR_BIT__ * __SIZEOF_INT128__ / 2));
+  volatile __int128 mv = m;
+  __int128 r;
+#else
+  long long m = -(1LL << (__CHAR_BIT__ * __SIZEOF_LONG_LONG__ / 2));
+  volatile long long mv = m;
+  long long r;
+#endif
+  if (!__builtin_mul_overflow (mv, mv, &r))
+    __builtin_abort ();
+  if (!__builtin_mul_overflow_p (mv, mv, r))
+    __builtin_abort ();
+  if (!__builtin_mul_overflow (m, m, &r))
+    __builtin_abort ();
+  if (!__builtin_mul_overflow_p (m, m, r))
+    __builtin_abort ();
+  return 0;
+}
index 7b1ffb1a0ccb683a9de0038b00436dd786266890..2360b75ac8d13f42c17ac3ab97755cc1e03ca699 100644 (file)
@@ -1,3 +1,10 @@
+2017-10-13  Jakub Jelinek  <jakub@redhat.com>
+
+       PR target/82274
+       * libgcc2.c (__mulvDI3): If both operands have
+       the same highpart of -1 and the topmost bit of lowpart is 0,
+       multiplication overflows even if both lowparts are 0.
+
 2017-09-28  James Bowman  <james.bowman@ftdichip.com>
 
        * config/ft32/crti-hw.S: Add watchdog vector, FT930 IRQ support.
index 5d3c69f16aae12980eb591fe3465b1c784c2c48e..83f865a04dba41dadebcd23d3a957b9dff656801 100644 (file)
@@ -375,7 +375,8 @@ __mulvDI3 (DWtype u, DWtype v)
                }
              else
                {
-                 if (uu.s.high == (Wtype) -1 && vv.s.high == (Wtype) - 1)
+                 if ((uu.s.high & vv.s.high) == (Wtype) -1
+                     && (uu.s.low | vv.s.low) != 0)
                    {
                      DWunion ww = {.ll = (UDWtype) (UWtype) uu.s.low
                                    * (UDWtype) (UWtype) vv.s.low};