re PR rtl-optimization/78546 (wrong code at -O2 and above)
authorJakub Jelinek <jakub@redhat.com>
Mon, 28 Nov 2016 19:15:51 +0000 (20:15 +0100)
committerJakub Jelinek <jakub@gcc.gnu.org>
Mon, 28 Nov 2016 19:15:51 +0000 (20:15 +0100)
PR rtl-optimization/78546
* simplify-rtx.c (neg_const_int): When negating most negative
number in mode wider than HOST_BITS_PER_WIDE_INT, use
simplify_const_unary_operation to produce CONST_DOUBLE or
CONST_WIDE_INT.
(simplify_plus_minus): Hanlde the case where neg_const_int
doesn't return a CONST_INT.

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

From-SVN: r242929

gcc/ChangeLog
gcc/simplify-rtx.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/torture/pr78546-1.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/torture/pr78546-2.c [new file with mode: 0644]

index 41dcb5d6ca5678953c793c51da521831f2eb81fc..40ef344df1839642cd03d2a7f47674f113faf34c 100644 (file)
@@ -1,3 +1,13 @@
+2016-11-28  Jakub Jelinek  <jakub@redhat.com>
+
+       PR rtl-optimization/78546
+       * simplify-rtx.c (neg_const_int): When negating most negative
+       number in mode wider than HOST_BITS_PER_WIDE_INT, use
+       simplify_const_unary_operation to produce CONST_DOUBLE or
+       CONST_WIDE_INT.
+       (simplify_plus_minus): Hanlde the case where neg_const_int
+       doesn't return a CONST_INT.
+
 2016-11-28  Markus Trippelsdorf  <markus@trippelsdorf.de>
 
        PR target/78556
index f6131d48130c7d5ed35f43d206ad794b5207aad9..83fb37d853524ca6206ea2e9a2899d66394ede60 100644 (file)
@@ -56,12 +56,17 @@ static rtx simplify_unary_operation_1 (enum rtx_code, machine_mode, rtx);
 static rtx simplify_binary_operation_1 (enum rtx_code, machine_mode,
                                        rtx, rtx, rtx, rtx);
 \f
-/* Negate a CONST_INT rtx, truncating (because a conversion from a
-   maximally negative number can overflow).  */
+/* Negate a CONST_INT rtx.  */
 static rtx
 neg_const_int (machine_mode mode, const_rtx i)
 {
-  return gen_int_mode (-(unsigned HOST_WIDE_INT) INTVAL (i), mode);
+  unsigned HOST_WIDE_INT val = -UINTVAL (i);
+  
+  if (GET_MODE_PRECISION (mode) > HOST_BITS_PER_WIDE_INT
+      && val == UINTVAL (i))
+    return simplify_const_unary_operation (NEG, mode, CONST_CAST_RTX (i),
+                                          mode);
+  return gen_int_mode (val, mode);
 }
 
 /* Test whether expression, X, is an immediate constant that represents
@@ -4507,9 +4512,12 @@ simplify_plus_minus (enum rtx_code code, machine_mode mode, rtx op0,
       rtx value = ops[n_ops - 1].op;
       if (ops[n_ops - 1].neg ^ ops[n_ops - 2].neg)
        value = neg_const_int (mode, value);
-      ops[n_ops - 2].op = plus_constant (mode, ops[n_ops - 2].op,
-                                        INTVAL (value));
-      n_ops--;
+      if (CONST_INT_P (value))
+       {
+         ops[n_ops - 2].op = plus_constant (mode, ops[n_ops - 2].op,
+                                            INTVAL (value));
+         n_ops--;
+       }
     }
 
   /* Put a non-negated operand first, if possible.  */
index 48ccdd969bbc98e96f036edd6b01342024c14bfa..04a6840299df6fc9367ca72c50d7084212909838 100644 (file)
@@ -1,5 +1,9 @@
 2016-11-28  Jakub Jelinek  <jakub@redhat.com>
 
+       PR rtl-optimization/78546
+       * gcc.dg/torture/pr78546-1.c: New test.
+       * gcc.dg/torture/pr78546-2.c: New test.
+
        PR fortran/78298
        * gfortran.dg/gomp/pr78298.f90: New test.
 
diff --git a/gcc/testsuite/gcc.dg/torture/pr78546-1.c b/gcc/testsuite/gcc.dg/torture/pr78546-1.c
new file mode 100644 (file)
index 0000000..9cae5b1
--- /dev/null
@@ -0,0 +1,22 @@
+/* PR rtl-optimization/78546 */
+/* { dg-do run { target int128 } } */
+
+typedef unsigned __int128 u128;
+u128 b;
+
+static inline u128
+foo (u128 p1)
+{
+  p1 += ~b;
+  return -p1;
+}
+
+int
+main ()
+{
+  asm volatile ("" : : : "memory");
+  u128 x = foo (~0x7fffffffffffffffLL);
+  if (x != 0x8000000000000001ULL)
+    __builtin_abort ();
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pr78546-2.c b/gcc/testsuite/gcc.dg/torture/pr78546-2.c
new file mode 100644 (file)
index 0000000..afec5b5
--- /dev/null
@@ -0,0 +1,16 @@
+/* PR rtl-optimization/78546 */
+/* { dg-do run { target int128 } } */
+
+typedef unsigned __int128 u128;
+u128 b;
+
+int
+main ()
+{
+  asm volatile ("" : : : "memory");
+  u128 x = ((u128) ~0x7fffffffffffffffLL) - b;
+  u128 y = 1 - x;
+  if (y != 0x8000000000000001ULL)
+    __builtin_abort ();
+  return 0;
+}