Fix PR66178, ICE due to misexpansion of constant expressions involving labels.
authorbernds <bernds@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 21 Jan 2016 18:10:03 +0000 (18:10 +0000)
committerbernds <bernds@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 21 Jan 2016 18:10:03 +0000 (18:10 +0000)
PR middle-end/66178
* expr.c (expand_expr_real_2) [PLUS_EXPR, MINUS_EXPR]: Don't
drop EXPAND_INITIALIZER.
* rtl.h (contains_symbolic_reference_p): Declare.
* rtlanal.c (contains_symbolic_reference_p): New function.
* simplify-rtx.c (simplify_binary_operation_1): Don't turn
a subtraction into a NOT if symbolic constants are involved.

testsuite/
PR middle-end/66178
gcc.dg/torture/pr66178.c: New test.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@232689 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/expr.c
gcc/rtl.h
gcc/rtlanal.c
gcc/simplify-rtx.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/torture/pr66178.c [new file with mode: 0644]

index ab7dc3a..124708b 100644 (file)
@@ -1,3 +1,13 @@
+2016-01-21  Bernd Schmidt  <bschmidt@redhat.com>
+
+       PR middle-end/66178
+       * expr.c (expand_expr_real_2) [PLUS_EXPR, MINUS_EXPR]: Don't
+       drop EXPAND_INITIALIZER.
+       * rtl.h (contains_symbolic_reference_p): Declare.
+       * rtlanal.c (contains_symbolic_reference_p): New function.
+       * simplify-rtx.c (simplify_binary_operation_1): Don't turn
+       a subtraction into a NOT if symbolic constants are involved.
+
 2016-01-21  Anton Blanchard  <anton@samba.org>
            Bill Schmidt  <wschmidt@linux.vnet.ibm.com>
 
index 8123cc2..0ce5936 100644 (file)
@@ -8381,11 +8381,11 @@ expand_expr_real_2 (sepops ops, rtx target, machine_mode tmode,
         if it's all in the wrong mode to form part of an address.
         And force_operand won't know whether to sign-extend or
         zero-extend.  */
-      if ((modifier != EXPAND_SUM && modifier != EXPAND_INITIALIZER)
-         || mode != ptr_mode)
+      if (modifier != EXPAND_INITIALIZER
+         && (modifier != EXPAND_SUM || mode != ptr_mode))
        {
          expand_operands (treeop0, treeop1,
-                          subtarget, &op0, &op1, EXPAND_NORMAL);
+                          subtarget, &op0, &op1, modifier);
          if (op0 == const0_rtx)
            return op1;
          if (op1 == const0_rtx)
@@ -8424,8 +8424,8 @@ expand_expr_real_2 (sepops ops, rtx target, machine_mode tmode,
         if it's all in the wrong mode to form part of an address.
         And force_operand won't know whether to sign-extend or
         zero-extend.  */
-      if ((modifier != EXPAND_SUM && modifier != EXPAND_INITIALIZER)
-         || mode != ptr_mode)
+      if (modifier != EXPAND_INITIALIZER
+         && (modifier != EXPAND_SUM || mode != ptr_mode))
        goto binop;
 
       expand_operands (treeop0, treeop1,
index 515fdee..2f5be5f 100644 (file)
--- a/gcc/rtl.h
+++ b/gcc/rtl.h
@@ -2931,6 +2931,7 @@ extern void set_insn_deleted (rtx);
 
 extern rtx single_set_2 (const rtx_insn *, const_rtx);
 extern bool contains_symbol_ref_p (const_rtx);
+extern bool contains_symbolic_reference_p (const_rtx);
 
 /* Handle the cheap and common cases inline for performance.  */
 
index 0e0d097..71dfd33 100644 (file)
@@ -6243,6 +6243,19 @@ contains_symbol_ref_p (const_rtx x)
   return false;
 }
 
+/* Return true if RTL X contains a SYMBOL_REF or LABEL_REF.  */
+
+bool
+contains_symbolic_reference_p (const_rtx x)
+{
+  subrtx_iterator::array_type array;
+  FOR_EACH_SUBRTX (iter, array, x, ALL)
+    if (SYMBOL_REF_P (*iter) || GET_CODE (*iter) == LABEL_REF)
+      return true;
+
+  return false;
+}
+
 /* Return true if X contains a thread-local symbol.  */
 
 bool
index 1e6e46d..39049e5 100644 (file)
@@ -2277,8 +2277,11 @@ simplify_binary_operation_1 (enum rtx_code code, machine_mode mode,
       if (!HONOR_SIGNED_ZEROS (mode) && trueop0 == CONST0_RTX (mode))
        return simplify_gen_unary (NEG, mode, op1, mode);
 
-      /* (-1 - a) is ~a.  */
-      if (trueop0 == constm1_rtx)
+      /* (-1 - a) is ~a, unless the expression avoids symbolic constants,
+        in which case not retaining additions and subtractions could
+        cause invalid assembly to be produced.  */
+      if (trueop0 == constm1_rtx
+         && !contains_symbolic_reference_p (op1))
        return simplify_gen_unary (NOT, mode, op1, mode);
 
       /* Subtracting 0 has no effect unless the mode has signed zeros
index 35fb4fc..4ec1b30 100644 (file)
@@ -1,3 +1,8 @@
+2016-01-21  Bernd Schmidt  <bschmidt@redhat.com>
+
+       PR middle-end/66178
+       * gcc.dg/torture/pr66178.c: New test.
+
 2016-01-21  Anton Blanchard  <anton@samba.org>
            Bill Schmidt  <wschmidt@linux.vnet.ibm.com>
 
diff --git a/gcc/testsuite/gcc.dg/torture/pr66178.c b/gcc/testsuite/gcc.dg/torture/pr66178.c
new file mode 100644 (file)
index 0000000..ebc626c
--- /dev/null
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+int test(void)
+{
+    static int a =  ((char *)&&l1-(char *)&&l2)-1;
+l1:
+l2:
+    return a;
+}
+
+int test2(void)
+{
+    static int a =  ((char *)&&l2-(char *)&&l3)+((char *)&&l1-(char *)&&l2);
+l1:
+l2:
+l3:
+    return a;
+}