* loop.c (record_giv): Avoid simplifying MULT to ASHIFT.
authorrth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 7 Sep 2001 18:14:32 +0000 (18:14 +0000)
committerrth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 7 Sep 2001 18:14:32 +0000 (18:14 +0000)
        (express_from_1): Wrap lines.
        * rtlanal.c (commutative_operand_precedence): Rename from
        operand_preference; export.
        * rtl.h: Declare it.
        * simplify-rtx.c (simplify_gen_binary): Tidy +/- const_int handling.
        (simplify_binary_operation): Invoke simplify_plus_minus on
        (CONST (PLUS ...)) as well.
        (struct simplify_plus_minus_op_data): New.
        (simplify_plus_minus_op_data_cmp): New.
        (simplify_plus_minus): Use them.  Avoid infinite recursion with
        simplify_binary_operation wrt CONST.

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

gcc/ChangeLog
gcc/loop.c
gcc/rtl.h
gcc/rtlanal.c
gcc/simplify-rtx.c

index 0403c8f..c3e93f6 100644 (file)
@@ -1,3 +1,18 @@
+2001-09-07  Richard Henderson  <rth@redhat.com>
+
+       * loop.c (record_giv): Avoid simplifying MULT to ASHIFT.
+       (express_from_1): Wrap lines.
+       * rtlanal.c (commutative_operand_precedence): Rename from
+       operand_preference; export.
+       * rtl.h: Declare it.
+       * simplify-rtx.c (simplify_gen_binary): Tidy +/- const_int handling.
+       (simplify_binary_operation): Invoke simplify_plus_minus on
+       (CONST (PLUS ...)) as well.
+       (struct simplify_plus_minus_op_data): New.
+       (simplify_plus_minus_op_data_cmp): New.
+       (simplify_plus_minus): Use them.  Avoid infinite recursion with
+       simplify_binary_operation wrt CONST.
+
 Fri Sep  7 11:52:30 2001   Kazu Hirata  <kazu@hxi.com>
 
        * h8300-protos.h (general_operand_dst_push): Remove.
index e72f421..990826a 100644 (file)
@@ -4922,9 +4922,12 @@ record_giv (loop, v, insn, src_reg, dest_reg, mult_val, add_val, ext_val,
   rtx set = single_set (insn);
   rtx temp;
 
-  /* Attempt to prove constantness of the values.  */
+  /* Attempt to prove constantness of the values.  Don't let simplity_rtx
+     undo the MULT canonicalization that we performed earlier.  */
   temp = simplify_rtx (add_val);
-  if (temp)
+  if (temp
+      && ! (GET_CODE (add_val) == MULT
+           && GET_CODE (temp) == ASHIFT))
     add_val = temp;
 
   v->insn = insn;
@@ -6371,7 +6374,10 @@ express_from_1 (a, b, mult)
     }
   else if (CONSTANT_P (a))
     {
-      return simplify_gen_binary (MINUS, GET_MODE (b) != VOIDmode ? GET_MODE (b) : GET_MODE (a), b, a);
+      enum machine_mode mode_a = GET_MODE (a);
+      enum machine_mode mode_b = GET_MODE (b);
+      enum machine_mode mode = mode_b == VOIDmode ? mode_a : mode_b;
+      return simplify_gen_binary (MINUS, mode, b, a);
     }
   else if (GET_CODE (b) == PLUS)
     {
index 3a0a019..75204b6 100644 (file)
--- a/gcc/rtl.h
+++ b/gcc/rtl.h
@@ -1374,6 +1374,7 @@ extern int reg_used_between_p             PARAMS ((rtx, rtx, rtx));
 extern int reg_referenced_between_p    PARAMS ((rtx, rtx, rtx));
 extern int reg_set_between_p           PARAMS ((rtx, rtx, rtx));
 extern int regs_set_between_p          PARAMS ((rtx, rtx, rtx));
+extern int commutative_operand_precedence PARAMS ((rtx));
 extern int swap_commutative_operands_p PARAMS ((rtx, rtx));
 extern int modified_between_p          PARAMS ((rtx, rtx, rtx));
 extern int no_labels_between_p         PARAMS ((rtx, rtx));
index 5ac2c74..9c8830d 100644 (file)
@@ -30,7 +30,6 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 static void set_of_1           PARAMS ((rtx, rtx, void *));
 static void insn_dependent_p_1 PARAMS ((rtx, rtx, void *));
 static int computed_jump_p_1   PARAMS ((rtx));
-static int operand_preference  PARAMS ((rtx));
 static void parms_set          PARAMS ((rtx, rtx, void *));
 
 /* Bit flags that specify the machine subtype we are compiling for.
@@ -2558,8 +2557,8 @@ regno_use_in (regno, x)
    We use negative values to indicate a preference for the first operand
    and positive values for the second operand.  */
 
-static int
-operand_preference (op)
+int
+commutative_operand_precedence (op)
      rtx op;
 {
   /* Constants always come the second operand.  Prefer "nice" constants.  */
@@ -2597,7 +2596,8 @@ int
 swap_commutative_operands_p (x, y)
      rtx x, y;
 {
-  return operand_preference (x) < operand_preference (y);
+  return (commutative_operand_precedence (x)
+         < commutative_operand_precedence (y));
 }
 
 /* Return 1 if X is an autoincrement side effect and the register is
index ea1cc6d..5e869bd 100644 (file)
@@ -95,6 +95,8 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #define HWI_SIGN_EXTEND(low) \
  ((((HOST_WIDE_INT) low) < 0) ? ((HOST_WIDE_INT) -1) : ((HOST_WIDE_INT) 0))
 
+static int simplify_plus_minus_op_data_cmp PARAMS ((const void *,
+                                                   const void *));
 static rtx simplify_plus_minus         PARAMS ((enum rtx_code,
                                                 enum machine_mode, rtx, rtx));
 static void check_fold_consts          PARAMS ((PTR));
@@ -130,12 +132,15 @@ simplify_gen_binary (code, mode, op0, op1)
   /* Handle addition and subtraction of CONST_INT specially.  Otherwise,
      just form the operation.  */
 
-  if (code == PLUS && GET_CODE (op1) == CONST_INT
-      && GET_MODE (op0) != VOIDmode)
-    return plus_constant (op0, INTVAL (op1));
-  else if (code == MINUS && GET_CODE (op1) == CONST_INT
-          && GET_MODE (op0) != VOIDmode)
-    return plus_constant (op0, - INTVAL (op1));
+  if (GET_CODE (op1) == CONST_INT
+      && GET_MODE (op0) != VOIDmode
+      && (code == PLUS || code == MINUS))
+    {
+      HOST_WIDE_INT value = INTVAL (op1);
+      if (code == MINUS)
+       value = -value;
+      return plus_constant (op0, value);
+    }
   else
     return gen_rtx_fmt_ee (code, mode, op0, op1);
 }
@@ -1124,7 +1129,11 @@ simplify_binary_operation (code, mode, op0, op1)
 
          if (INTEGRAL_MODE_P (mode)
              && (GET_CODE (op0) == PLUS || GET_CODE (op0) == MINUS
-                 || GET_CODE (op1) == PLUS || GET_CODE (op1) == MINUS)
+                 || GET_CODE (op1) == PLUS || GET_CODE (op1) == MINUS
+                 || (GET_CODE (op0) == CONST
+                     && GET_CODE (XEXP (op0, 0)) == PLUS)
+                 || (GET_CODE (op1) == CONST
+                     && GET_CODE (XEXP (op1, 0)) == PLUS))
              && (tem = simplify_plus_minus (code, mode, op0, op1)) != 0)
            return tem;
          break;
@@ -1162,8 +1171,8 @@ simplify_binary_operation (code, mode, op0, op1)
 #endif
                return xop00;
            }
-
          break;              
+
        case MINUS:
          /* None of these optimizations can be done for IEEE
             floating point.  */
@@ -1257,7 +1266,11 @@ simplify_binary_operation (code, mode, op0, op1)
 
          if (INTEGRAL_MODE_P (mode)
              && (GET_CODE (op0) == PLUS || GET_CODE (op0) == MINUS
-                 || GET_CODE (op1) == PLUS || GET_CODE (op1) == MINUS)
+                 || GET_CODE (op1) == PLUS || GET_CODE (op1) == MINUS
+                 || (GET_CODE (op0) == CONST
+                     && GET_CODE (XEXP (op0, 0)) == PLUS)
+                 || (GET_CODE (op1) == CONST
+                     && GET_CODE (XEXP (op1, 0)) == PLUS))
              && (tem = simplify_plus_minus (code, mode, op0, op1)) != 0)
            return tem;
 
@@ -1680,17 +1693,34 @@ simplify_binary_operation (code, mode, op0, op1)
    and do all possible simplifications until no more changes occur.  Then
    we rebuild the operation.  */
 
+struct simplify_plus_minus_op_data
+{
+  rtx op;
+  int neg;
+};
+
+static int
+simplify_plus_minus_op_data_cmp (p1, p2)
+     const void *p1;
+     const void *p2;
+{
+  const struct simplify_plus_minus_op_data *d1 = p1;
+  const struct simplify_plus_minus_op_data *d2 = p2;
+
+  return (commutative_operand_precedence (d2->op)
+         - commutative_operand_precedence (d1->op));
+}
+
 static rtx
 simplify_plus_minus (code, mode, op0, op1)
      enum rtx_code code;
      enum machine_mode mode;
      rtx op0, op1;
 {
-  rtx ops[8];
-  int negs[8];
+  struct simplify_plus_minus_op_data ops[8];
   rtx result, tem;
-  int n_ops = 2, input_ops = 2, input_consts = 0, n_consts = 0;
-  int first = 1, negate = 0, changed;
+  int n_ops = 2, input_ops = 2, input_consts = 0, n_consts;
+  int first, negate, changed;
   int i, j;
 
   memset ((char *) ops, 0, sizeof ops);
@@ -1699,153 +1729,204 @@ simplify_plus_minus (code, mode, op0, op1)
      changed.  If we run out of room in our array, give up; this should
      almost never happen.  */
 
-  ops[0] = op0, ops[1] = op1, negs[0] = 0, negs[1] = (code == MINUS);
+  ops[0].op = op0;
+  ops[0].neg = 0;
+  ops[1].op = op1;
+  ops[1].neg = (code == MINUS);
 
-  changed = 1;
-  while (changed)
+  do
     {
       changed = 0;
 
       for (i = 0; i < n_ops; i++)
-       switch (GET_CODE (ops[i]))
-         {
-         case PLUS:
-         case MINUS:
-           if (n_ops == 7)
-             return 0;
-
-           ops[n_ops] = XEXP (ops[i], 1);
-           negs[n_ops++] = GET_CODE (ops[i]) == MINUS ? !negs[i] : negs[i];
-           ops[i] = XEXP (ops[i], 0);
-           input_ops++;
-           changed = 1;
-           break;
-
-         case NEG:
-           ops[i] = XEXP (ops[i], 0);
-           negs[i] = ! negs[i];
-           changed = 1;
-           break;
+       {
+         rtx this_op = ops[i].op;
+         int this_neg = ops[i].neg;
+         enum rtx_code this_code = GET_CODE (this_op);
 
-         case CONST:
-           ops[i] = XEXP (ops[i], 0);
-           input_consts++;
-           changed = 1;
-           break;
+         switch (this_code)
+           {
+           case PLUS:
+           case MINUS:
+             if (n_ops == 7)
+               return 0;
 
-         case NOT:
-           /* ~a -> (-a - 1) */
-           if (n_ops != 7)
-             {
-               ops[n_ops] = constm1_rtx;
-               negs[n_ops++] = negs[i];
-               ops[i] = XEXP (ops[i], 0);
-               negs[i] = ! negs[i];
-               changed = 1;
-             }
-           break;
+             ops[n_ops].op = XEXP (this_op, 1);
+             ops[n_ops].neg = (this_code == MINUS) ^ this_neg;
+             n_ops++;
+
+             ops[i].op = XEXP (this_op, 0);
+             input_ops++;
+             changed = 1;
+             break;
+
+           case NEG:
+             ops[i].op = XEXP (this_op, 0);
+             ops[i].neg = ! this_neg;
+             changed = 1;
+             break;
+
+           case CONST:
+             ops[i].op = XEXP (this_op, 0);
+             input_consts++;
+             changed = 1;
+             break;
+
+           case NOT:
+             /* ~a -> (-a - 1) */
+             if (n_ops != 7)
+               {
+                 ops[n_ops].op = constm1_rtx;
+                 ops[n_ops].neg = this_neg;
+                 ops[i].op = XEXP (this_op, 0);
+                 ops[i].neg = !this_neg;
+                 changed = 1;
+               }
+             break;
 
-         case CONST_INT:
-           if (negs[i])
-             ops[i] = GEN_INT (- INTVAL (ops[i])), negs[i] = 0, changed = 1;
-           break;
+           case CONST_INT:
+             if (this_neg)
+               {
+                 ops[i].op = GEN_INT (- INTVAL (this_op));
+                 ops[i].neg = 0;
+                 changed = 1;
+               }
+             break;
 
-         default:
-           break;
-         }
+           default:
+             break;
+           }
+       }
     }
+  while (changed);
 
   /* If we only have two operands, we can't do anything.  */
   if (n_ops <= 2)
-    return 0;
+    return NULL_RTX;
 
   /* Now simplify each pair of operands until nothing changes.  The first
      time through just simplify constants against each other.  */
 
-  changed = 1;
-  while (changed)
+  first = 1;
+  do
     {
       changed = first;
 
       for (i = 0; i < n_ops - 1; i++)
        for (j = i + 1; j < n_ops; j++)
-         if (ops[i] != 0 && ops[j] != 0
-             && (! first || (CONSTANT_P (ops[i]) && CONSTANT_P (ops[j]))))
-           {
-             rtx lhs = ops[i], rhs = ops[j];
-             enum rtx_code ncode = PLUS;
-
-             if (negs[i] && ! negs[j])
-               lhs = ops[j], rhs = ops[i], ncode = MINUS;
-             else if (! negs[i] && negs[j])
-               ncode = MINUS;
-
-             tem = simplify_binary_operation (ncode, mode, lhs, rhs);
-             if (tem)
-               {
-                 ops[i] = tem, ops[j] = 0;
-                 negs[i] = negs[i] && negs[j];
-                 if (GET_CODE (tem) == NEG)
-                   ops[i] = XEXP (tem, 0), negs[i] = ! negs[i];
+         {
+           rtx lhs = ops[i].op, rhs = ops[j].op;
+           int lneg = ops[i].neg, rneg = ops[j].neg;
 
-                 if (GET_CODE (ops[i]) == CONST_INT && negs[i])
-                   ops[i] = GEN_INT (- INTVAL (ops[i])), negs[i] = 0;
-                 changed = 1;
-               }
-           }
+           if (lhs != 0 && rhs != 0
+               && (! first || (CONSTANT_P (lhs) && CONSTANT_P (rhs))))
+             {
+               enum rtx_code ncode = PLUS;
+
+               if (lneg != rneg)
+                 {
+                   ncode = MINUS;
+                   if (lneg)
+                     tem = lhs, lhs = rhs, rhs = tem;
+                 }
+               else if (swap_commutative_operands_p (lhs, rhs))
+                 tem = lhs, lhs = rhs, rhs = tem;
+
+               tem = simplify_binary_operation (ncode, mode, lhs, rhs);
+
+               /* Reject "simplifications" that just wrap the two 
+                  arguments in a CONST.  Failure to do so can result
+                  in infinite recursion with simplify_binary_operation
+                  when it calls us to simplify CONST operations.  */
+               if (tem
+                   && ! (GET_CODE (tem) == CONST
+                         && GET_CODE (XEXP (tem, 0)) == ncode
+                         && XEXP (XEXP (tem, 0), 0) == lhs
+                         && XEXP (XEXP (tem, 0), 1) == rhs))
+                 {
+                   lneg &= rneg;
+                   if (GET_CODE (tem) == NEG)
+                     tem = XEXP (tem, 0), lneg = !lneg;
+                   if (GET_CODE (tem) == CONST_INT && lneg)
+                     tem = GEN_INT (- INTVAL (tem)), lneg = 0;
+
+                   ops[i].op = tem;
+                   ops[i].neg = lneg;
+                   ops[j].op = NULL_RTX;
+                   changed = 1;
+                 }
+             }
+         }
 
       first = 0;
     }
+  while (changed);
 
-  /* Pack all the operands to the lower-numbered entries and give up if
-     we didn't reduce the number of operands we had.  Make sure we
-     count a CONST as two operands.  If we have the same number of
-     operands, but have made more CONSTs than we had, this is also
-     an improvement, so accept it.  */
-
+  /* Pack all the operands to the lower-numbered entries.  */
   for (i = 0, j = 0; j < n_ops; j++)
-    if (ops[j] != 0)
-      {
-       ops[i] = ops[j], negs[i++] = negs[j];
-       if (GET_CODE (ops[j]) == CONST)
-         n_consts++;
-      }
+    if (ops[j].op)
+      ops[i++] = ops[j];
+  n_ops = i;
 
-  if (i + n_consts > input_ops
-      || (i + n_consts == input_ops && n_consts <= input_consts))
-    return 0;
+  /* Sort the operations based on swap_commutative_operands_p.  */
+  qsort (ops, n_ops, sizeof (*ops), simplify_plus_minus_op_data_cmp);
 
-  n_ops = i;
+  /* 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
+     one CONST_INT, and the sort will have ensured that it is last
+     in the array and that any other constant will be next-to-last.  */
 
-  /* If we have a CONST_INT, put it last.  */
-  for (i = 0; i < n_ops - 1; i++)
-    if (GET_CODE (ops[i]) == CONST_INT)
-      {
-       tem = ops[n_ops - 1], ops[n_ops - 1] = ops[i] , ops[i] = tem;
-       j = negs[n_ops - 1], negs[n_ops - 1] = negs[i], negs[i] = j;
-      }
+  if (n_ops > 1
+      && GET_CODE (ops[n_ops - 1].op) == CONST_INT
+      && CONSTANT_P (ops[n_ops - 2].op))
+    {
+      HOST_WIDE_INT value = INTVAL (ops[n_ops - 1].op);
+      if (ops[n_ops - 1].neg)
+       value = -value;
+      ops[n_ops - 2].op = plus_constant (ops[n_ops - 2].op, value);
+      n_ops--;
+    }
+
+  /* Count the number of CONSTs that we generated.  */
+  n_consts = 0;
+  for (i = 0; i < n_ops; i++)
+    if (GET_CODE (ops[i].op) == CONST)
+      n_consts++;
+
+  /* Give up if we didn't reduce the number of operands we had.  Make
+     sure we count a CONST as two operands.  If we have the same
+     number of operands, but have made more CONSTs than before, this
+     is also an improvement, so accept it.  */
+  if (n_ops + n_consts > input_ops
+      || (n_ops + n_consts == input_ops && n_consts <= input_consts))
+    return NULL_RTX;
 
   /* Put a non-negated operand first.  If there aren't any, make all
      operands positive and negate the whole thing later.  */
-  for (i = 0; i < n_ops && negs[i]; i++)
-    ;
 
+  negate = 0;
+  for (i = 0; i < n_ops && ops[i].neg; i++)
+    continue;
   if (i == n_ops)
     {
       for (i = 0; i < n_ops; i++)
-       negs[i] = 0;
+       ops[i].neg = 0;
       negate = 1;
     }
   else if (i != 0)
     {
-      tem = ops[0], ops[0] = ops[i], ops[i] = tem;
-      j = negs[0], negs[0] = negs[i], negs[i] = j;
+      tem = ops[0].op;
+      ops[0] = ops[i];
+      ops[i].op = tem;
+      ops[i].neg = 1;
     }
 
   /* Now make the result by performing the requested operations.  */
-  result = ops[0];
+  result = ops[0].op;
   for (i = 1; i < n_ops; i++)
-    result = simplify_gen_binary (negs[i] ? MINUS : PLUS, mode, result, ops[i]);
+    result = gen_rtx_fmt_ee (ops[i].neg ? MINUS : PLUS,
+                            mode, result, ops[i].op);
 
   return negate ? gen_rtx_NEG (mode, result) : result;
 }