re PR rtl-optimization/12260 (ICE in output_operand: invalid expression as operand)
authorRoger Sayle <roger@eyesopen.com>
Sat, 11 Oct 2003 21:06:19 +0000 (21:06 +0000)
committerRoger Sayle <sayle@gcc.gnu.org>
Sat, 11 Oct 2003 21:06:19 +0000 (21:06 +0000)
PR optimization/12260
* simplify-rtx.c (simplify_unary_operation): Simplify all unary
operations through CONST nodes.  Optimize (neg (plus X C)) as
(minus -C X) for constant values C.
(simplify_binary_operation): Optimize (minus (neg X) C) as
(minus -C X) for constant values C.
(simplify_plus_minus): Avoid creating (neg (const (plus X C)),
instead create (minus -C X).

* gcc.c-torture/compile/20031011-2.c: New test case.

From-SVN: r72379

gcc/ChangeLog
gcc/simplify-rtx.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.c-torture/compile/20031011-2.c [new file with mode: 0644]

index 38bd51f1da92b2586cda00cd65cfe90a3a54b9c2..4251bf3a741ff062220b4b10f9b5228d4f8c7fd5 100644 (file)
@@ -1,3 +1,14 @@
+2003-10-11  Roger Sayle  <roger@eyesopen.com>
+
+       PR optimization/12260
+       * simplify-rtx.c (simplify_unary_operation): Simplify all unary
+       operations through CONST nodes.  Optimize (neg (plus X C)) as
+       (minus -C X) for constant values C.
+       (simplify_binary_operation): Optimize (minus (neg X) C) as
+       (minus -C X) for constant values C.
+       (simplify_plus_minus): Avoid creating (neg (const (plus X C)),
+       instead create (minus -C X).
+
 2003-10-11  Roger Sayle  <roger@eyesopen.com>
 
        * expr.c (expand_expr <PLUS_EXPR>): Let expand_operands call
index 0e8646313b1c1d8ffaf27230e24071734bd900ca..22ba167d80e8aaa4279bf25db9ba512e099cef8d 100644 (file)
@@ -407,6 +407,8 @@ simplify_unary_operation (enum rtx_code code, enum machine_mode mode,
          return gen_rtx_CONST_VECTOR (mode, v);
        }
     }
+  else if (GET_CODE (op) == CONST)
+    return simplify_unary_operation (code, mode, XEXP (op, 0), op_mode);
 
   if (VECTOR_MODE_P (mode) && GET_CODE (trueop) == CONST_VECTOR)
     {
@@ -971,11 +973,22 @@ simplify_unary_operation (enum rtx_code code, enum machine_mode mode,
            return simplify_gen_binary (MINUS, mode, XEXP (op, 1),
                                        XEXP (op, 0));
 
-         /* (neg (plus A B)) is canonicalized to (minus (neg A) B).  */
          if (GET_CODE (op) == PLUS
              && !HONOR_SIGNED_ZEROS (mode)
              && !HONOR_SIGN_DEPENDENT_ROUNDING (mode))
            {
+             /* (neg (plus A C)) is simplified to (minus -C A).  */
+             if (GET_CODE (XEXP (op, 1)) == CONST_INT
+                 || GET_CODE (XEXP (op, 1)) == CONST_DOUBLE)
+               {
+                 temp = simplify_unary_operation (NEG, mode, XEXP (op, 1),
+                                                  mode);
+                 if (temp)
+                   return simplify_gen_binary (MINUS, mode, temp,
+                                               XEXP (op, 0));
+               }
+
+             /* (neg (plus A B)) is canonicalized to (minus (neg A) B).  */
              temp = simplify_gen_unary (NEG, mode, XEXP (op, 0), mode);
              return simplify_gen_binary (MINUS, mode, temp, XEXP (op, 1));
            }
@@ -1572,6 +1585,16 @@ simplify_binary_operation (enum rtx_code code, enum machine_mode mode,
          if (GET_CODE (op1) == NEG)
            return simplify_gen_binary (PLUS, mode, op0, XEXP (op1, 0));
 
+         /* (-x - c) may be simplified as (-c - x).  */
+         if (GET_CODE (op0) == NEG
+             && (GET_CODE (op1) == CONST_INT
+                 || GET_CODE (op1) == CONST_DOUBLE))
+           {
+             tem = simplify_unary_operation (NEG, mode, op1, mode);
+             if (tem)
+               return simplify_gen_binary (MINUS, mode, tem, XEXP (op0, 0));
+           }
+
          /* If one of the operands is a PLUS or a MINUS, see if we can
             simplify this by the associative law.
             Don't use the associative law for floating point.
@@ -2375,6 +2398,13 @@ simplify_plus_minus (enum rtx_code code, enum machine_mode mode, rtx op0,
   /* Sort the operations based on swap_commutative_operands_p.  */
   qsort (ops, n_ops, sizeof (*ops), simplify_plus_minus_op_data_cmp);
 
+  /* Create (minus -C X) instead of (neg (const (plus X C))).  */
+  if (n_ops == 2
+      && GET_CODE (ops[1].op) == CONST_INT
+      && CONSTANT_P (ops[0].op)
+      && ops[0].neg)
+    return gen_rtx_fmt_ee (MINUS, mode, ops[1].op, ops[0].op);
+  
   /* We suppressed creation of trivial CONST expressions in the
      combination loop to avoid recursion.  Create one manually now.
      The combination loop should have ensured that there is exactly
index 331794d7a0f5eb143022aab4756b30486c5e3ea1..ad9bafce35c0c927db38bd4086dba81957daf1a4 100644 (file)
@@ -1,3 +1,8 @@
+2003-10-11  Roger Sayle  <roger@eyesopen.com>
+
+       PR optimization/12260
+       * gcc.c-torture/compile/20031011-2.c: New test case.
+
 2003-10-11  Roger Sayle  <roger@eyesopen.com>
 
        * gcc.c-torture/execute/20031011-1.c: New testcase.
diff --git a/gcc/testsuite/gcc.c-torture/compile/20031011-2.c b/gcc/testsuite/gcc.c-torture/compile/20031011-2.c
new file mode 100644 (file)
index 0000000..0268455
--- /dev/null
@@ -0,0 +1,15 @@
+/* PR optimization/12260.  */
+
+extern int f(void);
+extern int g(int);
+
+static char buf[512];
+void h(int l) {
+    while (l) {
+        char *op = buf;
+        if (f() == 0)
+            break;
+        if (g(op - buf + 1))
+            break;
+    }
+}