emit-rtl.c (offset_address): Use simplify_gen_binary rather than gen_rtx_PLUS to...
authorRichard Henderson <rth@redhat.com>
Thu, 21 Feb 2002 23:06:16 +0000 (15:06 -0800)
committerRichard Henderson <rth@gcc.gnu.org>
Thu, 21 Feb 2002 23:06:16 +0000 (15:06 -0800)
        * emit-rtl.c (offset_address): Use simplify_gen_binary rather
        than gen_rtx_PLUS to form the sum.
        * explow.c (force_reg): Rearrange to not allocate new pseudo
        when force_operand returns a register.
        * expr.c (expand_assignment): Allow offset_rtx expansion to
        return a sum.  Do not force addresses into registers.
        (expand_expr): Likewise.
        * simplify-rtx.c (simplify_gen_binary): Use simplify_plus_minus
        to canonicalize arithmetic that didn't simpify.
        (simplify_plus_minus): New argument force; update
        all callers.  Don't split CONST unless we can do something with it,
        and wouldn't lose the constness of the operands.

        * config/i386/i386.c (legitimize_pic_address): Recognize UNSPECs
        that we generated earlier.

From-SVN: r49945

gcc/ChangeLog
gcc/config/i386/i386.c
gcc/emit-rtl.c
gcc/explow.c
gcc/expr.c
gcc/simplify-rtx.c

index c7878d70e65f92cbcf7cdadee60774e7d456ce42..8a8dcac21e7050a586815fe3ea7c8c1993531e65 100644 (file)
@@ -1,3 +1,21 @@
+2002-02-21  Richard Henderson  <rth@redhat.com>
+
+       * emit-rtl.c (offset_address): Use simplify_gen_binary rather
+       than gen_rtx_PLUS to form the sum.
+       * explow.c (force_reg): Rearrange to not allocate new pseudo
+       when force_operand returns a register.
+       * expr.c (expand_assignment): Allow offset_rtx expansion to
+       return a sum.  Do not force addresses into registers.
+       (expand_expr): Likewise.
+       * simplify-rtx.c (simplify_gen_binary): Use simplify_plus_minus
+       to canonicalize arithmetic that didn't simpify.
+       (simplify_plus_minus): New argument force; update
+       all callers.  Don't split CONST unless we can do something with it,
+       and wouldn't lose the constness of the operands.
+
+       * config/i386/i386.c (legitimize_pic_address): Recognize UNSPECs
+       that we generated earlier.
+
 2002-02-21  Tom Tromey  <tromey@redhat.com>
 
        * dwarf2out.c (DWARF_LINE_MIN_INSTR_LENGTH): Removed.
index fd84c07239eb9f7913ef89c6e989b8f442e00988..009b5d8511bc02c6b63d164bea3f4b0b92f60e6d 100644 (file)
@@ -4986,11 +4986,15 @@ legitimize_pic_address (orig, reg)
       if (GET_CODE (addr) == CONST)
        {
          addr = XEXP (addr, 0);
-         if (GET_CODE (addr) == UNSPEC)
-           {
-             /* Check that the unspec is one of the ones we generate?  */
-           }
-         else if (GET_CODE (addr) != PLUS)
+
+         /* We must match stuff we generate before.  Assume the only
+            unspecs that can get here are ours.  Not that we could do
+            anything with them anyway...  */
+         if (GET_CODE (addr) == UNSPEC
+             || (GET_CODE (addr) == PLUS
+                 && GET_CODE (XEXP (addr, 0)) == UNSPEC))
+           return orig;
+         if (GET_CODE (addr) != PLUS)
            abort ();
        }
       if (GET_CODE (addr) == PLUS)
index 82dd61a5f64fcaca9d4e63351533a41180de0890..836fbf5385ab1a29a7bef285dc16d081e3e5865e 100644 (file)
@@ -2047,9 +2047,26 @@ offset_address (memref, offset, pow2)
      rtx offset;
      HOST_WIDE_INT pow2;
 {
-  rtx new = change_address_1 (memref, VOIDmode,
-                             gen_rtx_PLUS (Pmode, XEXP (memref, 0),
-                                           force_reg (Pmode, offset)), 1);
+  rtx new, addr = XEXP (memref, 0);
+
+  new = simplify_gen_binary (PLUS, Pmode, addr, offset);
+
+  /* At this point we don't know _why_ the address is invalid.  It 
+     could have secondary memory refereces, multiplies or anything.
+
+     However, if we did go and rearrange things, we can wind up not
+     being able to recognize the magic around pic_offset_table_rtx.
+     This stuff is fragile, and is yet another example of why it is
+     bad to expose PIC machinery too early.  */
+  if (! memory_address_p (GET_MODE (memref), new)
+      && GET_CODE (addr) == PLUS
+      && XEXP (addr, 0) == pic_offset_table_rtx)
+    {
+      addr = force_reg (GET_MODE (addr), addr);
+      new = simplify_gen_binary (PLUS, Pmode, addr, offset);
+    }
+
+  new = change_address_1 (memref, VOIDmode, new, 1);
 
   /* Update the alignment to reflect the offset.  Reset the offset, which
      we don't know.  */
index a72a03be64c709385e2bd87d225fecc56accac57..7a770ee897cfa04e17f37d2b566b81e4e432af54 100644 (file)
@@ -732,12 +732,23 @@ force_reg (mode, x)
   if (GET_CODE (x) == REG)
     return x;
 
-  temp = gen_reg_rtx (mode);
-
-  if (! general_operand (x, mode))
-    x = force_operand (x, NULL_RTX);
-
-  insn = emit_move_insn (temp, x);
+  if (general_operand (x, mode))
+    {
+      temp = gen_reg_rtx (mode);
+      insn = emit_move_insn (temp, x);
+    }
+  else
+    {
+      temp = force_operand (x, NULL_RTX);
+      if (GET_CODE (temp) == REG)
+       insn = get_last_insn ();
+      else
+       {
+         rtx temp2 = gen_reg_rtx (mode);
+         insn = emit_move_insn (temp2, temp);
+         temp = temp2;
+       }
+    }
 
   /* Let optimizers know that TEMP's value never changes
      and that X can be substituted for it.  Don't get confused
@@ -746,6 +757,7 @@ force_reg (mode, x)
       && (set = single_set (insn)) != 0
       && SET_DEST (set) == temp)
     set_unique_reg_note (insn, REG_EQUAL, x);
+
   return temp;
 }
 
index a903b14ebb9b503bb98ad43e175bfa8bb0c3de7c..b7304350b7f648efb20f6609b82e2a3ada1816e8 100644 (file)
@@ -3659,7 +3659,7 @@ expand_assignment (to, from, want_value, suggest_reg)
 
       if (offset != 0)
        {
-         rtx offset_rtx = expand_expr (offset, NULL_RTX, VOIDmode, 0);
+         rtx offset_rtx = expand_expr (offset, NULL_RTX, VOIDmode, EXPAND_SUM);
 
          if (GET_CODE (to_rtx) != MEM)
            abort ();
@@ -3682,15 +3682,7 @@ expand_assignment (to, from, want_value, suggest_reg)
              && (bitsize % GET_MODE_ALIGNMENT (mode1)) == 0
              && MEM_ALIGN (to_rtx) == GET_MODE_ALIGNMENT (mode1))
            {
-             rtx temp
-               = adjust_address (to_rtx, mode1, bitpos / BITS_PER_UNIT);
-
-             if (GET_CODE (XEXP (temp, 0)) == REG)
-               to_rtx = temp;
-             else
-               to_rtx = (replace_equiv_address
-                         (to_rtx, force_reg (GET_MODE (XEXP (temp, 0)),
-                                             XEXP (temp, 0))));
+             to_rtx = adjust_address (to_rtx, mode1, bitpos / BITS_PER_UNIT);
              bitpos = 0;
            }
 
@@ -6852,7 +6844,7 @@ expand_expr (exp, target, tmode, modifier)
 
        if (offset != 0)
          {
-           rtx offset_rtx = expand_expr (offset, NULL_RTX, VOIDmode, 0);
+           rtx offset_rtx = expand_expr (offset, NULL_RTX, VOIDmode, EXPAND_SUM);
 
            /* If this object is in a register, put it into memory.
               This case can't occur in C, but can in Ada if we have
@@ -6902,15 +6894,7 @@ expand_expr (exp, target, tmode, modifier)
                && (bitsize % GET_MODE_ALIGNMENT (mode1)) == 0
                && MEM_ALIGN (op0) == GET_MODE_ALIGNMENT (mode1))
              {
-               rtx temp = adjust_address (op0, mode1, bitpos / BITS_PER_UNIT);
-
-               if (GET_CODE (XEXP (temp, 0)) == REG)
-                 op0 = temp;
-               else
-                 op0 = (replace_equiv_address
-                        (op0,
-                         force_reg (GET_MODE (XEXP (temp, 0)),
-                                    XEXP (temp, 0))));
+               op0 = adjust_address (op0, mode1, bitpos / BITS_PER_UNIT);
                bitpos = 0;
              }
 
index 84b8cb240cebcb38dfe2b92e496d7d010c3200d0..55cbfc6fbbe32b7775508837616faac59d1cd210 100644 (file)
@@ -99,7 +99,8 @@ static rtx neg_const_int PARAMS ((enum machine_mode, rtx));
 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));
+                                                enum machine_mode, rtx,
+                                                rtx, int));
 static void check_fold_consts          PARAMS ((PTR));
 #if ! defined (REAL_IS_NOT_DOUBLE) || defined (REAL_ARITHMETIC)
 static void simplify_unary_real                PARAMS ((PTR));
@@ -137,21 +138,14 @@ simplify_gen_binary (code, mode, op0, op1)
 
   /* If this simplifies, do it.  */
   tem = simplify_binary_operation (code, mode, op0, op1);
-
   if (tem)
     return tem;
 
-  /* Handle addition and subtraction of CONST_INT specially.  Otherwise,
-     just form the operation.  */
+  /* Handle addition and subtraction specially.  Otherwise, just form
+     the operation.  */
 
-  if (GET_CODE (op1) == CONST_INT
-      && GET_MODE (op0) != VOIDmode
-      && (code == PLUS || code == MINUS))
-    {
-      if (code == MINUS)
-       op1 = neg_const_int (mode, op1);
-      return plus_constant (op0, INTVAL (op1));
-    }
+  if (code == PLUS || code == MINUS)
+    return simplify_plus_minus (code, mode, op0, op1, 1);
   else
     return gen_rtx_fmt_ee (code, mode, op0, op1);
 }
@@ -1152,7 +1146,7 @@ simplify_binary_operation (code, mode, op0, op1)
                      && 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)
+             && (tem = simplify_plus_minus (code, mode, op0, op1, 0)) != 0)
            return tem;
          break;
 
@@ -1289,7 +1283,7 @@ simplify_binary_operation (code, mode, op0, op1)
                      && 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)
+             && (tem = simplify_plus_minus (code, mode, op0, op1, 0)) != 0)
            return tem;
 
          /* Don't let a relocatable value get a negative coeff.  */
@@ -1728,7 +1722,10 @@ simplify_binary_operation (code, mode, op0, op1)
 
    Rather than test for specific case, we do this by a brute-force method
    and do all possible simplifications until no more changes occur.  Then
-   we rebuild the operation.  */
+   we rebuild the operation. 
+
+   If FORCE is true, then always generate the rtx.  This is used to 
+   canonicalize stuff emitted from simplify_gen_binary.  */
 
 struct simplify_plus_minus_op_data
 {
@@ -1749,10 +1746,11 @@ simplify_plus_minus_op_data_cmp (p1, p2)
 }
 
 static rtx
-simplify_plus_minus (code, mode, op0, op1)
+simplify_plus_minus (code, mode, op0, op1, force)
      enum rtx_code code;
      enum machine_mode mode;
      rtx op0, op1;
+     int force;
 {
   struct simplify_plus_minus_op_data ops[8];
   rtx result, tem;
@@ -1786,7 +1784,11 @@ simplify_plus_minus (code, mode, op0, op1)
            case PLUS:
            case MINUS:
              if (n_ops == 7)
-               return 0;
+               {
+                 if (force)
+                   abort ();
+                 return NULL_RTX;
+               }
 
              ops[n_ops].op = XEXP (this_op, 1);
              ops[n_ops].neg = (this_code == MINUS) ^ this_neg;
@@ -1804,9 +1806,18 @@ simplify_plus_minus (code, mode, op0, op1)
              break;
 
            case CONST:
-             ops[i].op = XEXP (this_op, 0);
-             input_consts++;
-             changed = 1;
+             if (n_ops < 7
+                 && GET_CODE (XEXP (this_op, 0)) == PLUS
+                 && CONSTANT_P (XEXP (XEXP (this_op, 0), 0))
+                 && CONSTANT_P (XEXP (XEXP (this_op, 0), 1)))
+               {
+                 ops[i].op = XEXP (XEXP (this_op, 0), 0);
+                 ops[n_ops].op = XEXP (XEXP (this_op, 0), 1);
+                 ops[n_ops].neg = this_neg;
+                 n_ops++;
+                 input_consts++;
+                 changed = 1;
+               }
              break;
 
            case NOT:
@@ -1838,9 +1849,14 @@ simplify_plus_minus (code, mode, op0, op1)
   while (changed);
 
   /* If we only have two operands, we can't do anything.  */
-  if (n_ops <= 2)
+  if (n_ops <= 2 && !force)
     return NULL_RTX;
 
+  /* Count the number of CONSTs we didn't split above.  */
+  for (i = 0; i < n_ops; i++)
+    if (GET_CODE (ops[i].op) == CONST)
+      input_consts++;
+
   /* Now simplify each pair of operands until nothing changes.  The first
      time through just simplify constants against each other.  */
 
@@ -1941,8 +1957,9 @@ simplify_plus_minus (code, mode, op0, op1)
      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))
+  if (!force
+      && (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