OSDN Git Service

(eliminate_regs): Add STORING arg.
authorkenner <kenner@138bc75d-0d04-0410-961f-82ee72b054a4>
Sat, 15 Mar 1997 12:14:27 +0000 (12:14 +0000)
committerkenner <kenner@138bc75d-0d04-0410-961f-82ee72b054a4>
Sat, 15 Mar 1997 12:14:27 +0000 (12:14 +0000)
(eliminate_regs, case SET): Pass that we are storing to recursive call.
(eliminate_regs, case SUBREG): If storing and same number of words, use
larger mode.

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

gcc/reload1.c

index 30f97c4..ad0f8f8 100644 (file)
@@ -946,7 +946,7 @@ reload (first, global, dumpfile)
       for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++)
        if (reg_renumber[i] < 0 && reg_equiv_memory_loc[i])
          {
-           rtx x = eliminate_regs (reg_equiv_memory_loc[i], 0, NULL_RTX);
+           rtx x = eliminate_regs (reg_equiv_memory_loc[i], 0, NULL_RTX, 0);
 
            if (strict_memory_address_p (GET_MODE (regno_reg_rtx[i]),
                                         XEXP (x, 0)))
@@ -2759,10 +2759,11 @@ static struct rtvec_def *old_asm_operands_vec, *new_asm_operands_vec;
    the proper thing.  */
 
 rtx
-eliminate_regs (x, mem_mode, insn)
+eliminate_regs (x, mem_mode, insn, storing)
      rtx x;
      enum machine_mode mem_mode;
      rtx insn;
+     int storing;
 {
   enum rtx_code code = GET_CODE (x);
   struct elim_table *ep;
@@ -2819,7 +2820,7 @@ eliminate_regs (x, mem_mode, insn)
             reference to the pseudo.  Ensure we make a copy of the
             address in case it is shared.  */
          new = eliminate_regs (reg_equiv_memory_loc[regno],
-                               mem_mode, insn);
+                               mem_mode, insn, 0);
          if (new != reg_equiv_memory_loc[regno])
            {
              cannot_omit_stores[regno] = 1;
@@ -2881,8 +2882,8 @@ eliminate_regs (x, mem_mode, insn)
         reload.  This is the desired action.  */
 
       {
-       rtx new0 = eliminate_regs (XEXP (x, 0), mem_mode, insn);
-       rtx new1 = eliminate_regs (XEXP (x, 1), mem_mode, insn);
+       rtx new0 = eliminate_regs (XEXP (x, 0), mem_mode, insn, 0);
+       rtx new1 = eliminate_regs (XEXP (x, 1), mem_mode, insn, 0);
 
        if (new0 != XEXP (x, 0) || new1 != XEXP (x, 1))
          {
@@ -2953,9 +2954,9 @@ eliminate_regs (x, mem_mode, insn)
     case GE:       case GT:       case GEU:    case GTU:
     case LE:       case LT:       case LEU:    case LTU:
       {
-       rtx new0 = eliminate_regs (XEXP (x, 0), mem_mode, insn);
+       rtx new0 = eliminate_regs (XEXP (x, 0), mem_mode, insn, 0);
        rtx new1
-         = XEXP (x, 1) ? eliminate_regs (XEXP (x, 1), mem_mode, insn) : 0;
+         = XEXP (x, 1) ? eliminate_regs (XEXP (x, 1), mem_mode, insn, 0) : 0;
 
        if (new0 != XEXP (x, 0) || new1 != XEXP (x, 1))
          return gen_rtx (code, GET_MODE (x), new0, new1);
@@ -2966,7 +2967,7 @@ eliminate_regs (x, mem_mode, insn)
       /* If we have something in XEXP (x, 0), the usual case, eliminate it.  */
       if (XEXP (x, 0))
        {
-         new = eliminate_regs (XEXP (x, 0), mem_mode, insn);
+         new = eliminate_regs (XEXP (x, 0), mem_mode, insn, 0);
          if (new != XEXP (x, 0))
            x = gen_rtx (EXPR_LIST, REG_NOTE_KIND (x), new, XEXP (x, 1));
        }
@@ -2979,7 +2980,7 @@ eliminate_regs (x, mem_mode, insn)
         strictly needed, but it simplifies the code.  */
       if (XEXP (x, 1))
        {
-         new = eliminate_regs (XEXP (x, 1), mem_mode, insn);
+         new = eliminate_regs (XEXP (x, 1), mem_mode, insn, 0);
          if (new != XEXP (x, 1))
            return gen_rtx (GET_CODE (x), GET_MODE (x), XEXP (x, 0), new);
        }
@@ -3015,7 +3016,7 @@ eliminate_regs (x, mem_mode, insn)
     case ABS:
     case SQRT:
     case FFS:
-      new = eliminate_regs (XEXP (x, 0), mem_mode, insn);
+      new = eliminate_regs (XEXP (x, 0), mem_mode, insn, 0);
       if (new != XEXP (x, 0))
        return gen_rtx (code, GET_MODE (x), new);
       return x;
@@ -3034,7 +3035,7 @@ eliminate_regs (x, mem_mode, insn)
          && reg_equiv_memory_loc[REGNO (SUBREG_REG (x))] != 0)
        {
          new = eliminate_regs (reg_equiv_memory_loc[REGNO (SUBREG_REG (x))],
-                               mem_mode, insn);
+                               mem_mode, insn, 0);
 
          /* If we didn't change anything, we must retain the pseudo.  */
          if (new == reg_equiv_memory_loc[REGNO (SUBREG_REG (x))])
@@ -3054,27 +3055,37 @@ eliminate_regs (x, mem_mode, insn)
            }
        }
       else
-       new = eliminate_regs (SUBREG_REG (x), mem_mode, insn);
+       new = eliminate_regs (SUBREG_REG (x), mem_mode, insn, 0);
 
       if (new != XEXP (x, 0))
        {
-         if (GET_CODE (new) == MEM
-             && (GET_MODE_SIZE (GET_MODE (x))
-                 <= GET_MODE_SIZE (GET_MODE (new)))
+         int x_size = GET_MODE_SIZE (GET_MODE (x));
+         int new_size = GET_MODE_SIZE (GET_MODE (new));
+
+         /* When asked to spill a partial word subreg, we need to go
+            ahead and spill the whole thing against the possibility
+            that we reload the whole reg and find garbage at the top.  */
+         if (storing
+             && GET_CODE (new) == MEM
+             && x_size < new_size
+             && ((x_size + UNITS_PER_WORD-1) / UNITS_PER_WORD
+                 == (new_size + UNITS_PER_WORD-1) / UNITS_PER_WORD))
+           return new;
+         else if (GET_CODE (new) == MEM
+                  && x_size <= new_size
 #ifdef LOAD_EXTEND_OP
-             /* On these machines we will be reloading what is
-                inside the SUBREG if it originally was a pseudo and
-                the inner and outer modes are both a word or
-                smaller.  So leave the SUBREG then.  */
-             && ! (GET_CODE (SUBREG_REG (x)) == REG
-                   && GET_MODE_SIZE (GET_MODE (x)) <= UNITS_PER_WORD
-                   && GET_MODE_SIZE (GET_MODE (new)) <= UNITS_PER_WORD
-                   && (GET_MODE_SIZE (GET_MODE (x))
-                       > GET_MODE_SIZE (GET_MODE (new)))
-                   && INTEGRAL_MODE_P (GET_MODE (new))
-                   && LOAD_EXTEND_OP (GET_MODE (new)) != NIL)
+                  /* On these machines we will be reloading what is
+                     inside the SUBREG if it originally was a pseudo and
+                     the inner and outer modes are both a word or
+                     smaller.  So leave the SUBREG then.  */
+                  && ! (GET_CODE (SUBREG_REG (x)) == REG
+                        && x_size <= UNITS_PER_WORD
+                        && new_size <= UNITS_PER_WORD
+                        && x_size > new_size
+                        && INTEGRAL_MODE_P (GET_MODE (new))
+                        && LOAD_EXTEND_OP (GET_MODE (new)) != NIL)
 #endif
-             )
+                  )
            {
              int offset = SUBREG_WORD (x) * UNITS_PER_WORD;
              enum machine_mode mode = GET_MODE (x);
@@ -3102,7 +3113,7 @@ eliminate_regs (x, mem_mode, insn)
        if (ep->from_rtx == XEXP (x, 0))
          ep->can_eliminate = 0;
 
-      new = eliminate_regs (XEXP (x, 0), mem_mode, insn);
+      new = eliminate_regs (XEXP (x, 0), mem_mode, insn, 0);
       if (new != XEXP (x, 0))
        return gen_rtx (code, GET_MODE (x), new);
       return x;
@@ -3115,7 +3126,7 @@ eliminate_regs (x, mem_mode, insn)
        if (ep->to_rtx == XEXP (x, 0))
          ep->can_eliminate = 0;
 
-      new = eliminate_regs (XEXP (x, 0), mem_mode, insn);
+      new = eliminate_regs (XEXP (x, 0), mem_mode, insn, 0);
       if (new != XEXP (x, 0))
        return gen_rtx (code, GET_MODE (x), new);
       return x;
@@ -3133,7 +3144,7 @@ eliminate_regs (x, mem_mode, insn)
            temp_vec = (rtx *) alloca (XVECLEN (x, 3) * sizeof (rtx));
            for (i = 0; i < ASM_OPERANDS_INPUT_LENGTH (x); i++)
              temp_vec[i] = eliminate_regs (ASM_OPERANDS_INPUT (x, i),
-                                           mem_mode, insn);
+                                           mem_mode, insn, 0);
 
            for (i = 0; i < ASM_OPERANDS_INPUT_LENGTH (x); i++)
              if (temp_vec[i] != ASM_OPERANDS_INPUT (x, i))
@@ -3204,8 +3215,8 @@ eliminate_regs (x, mem_mode, insn)
 
       /* Now avoid the loop below in this common case.  */
       {
-       rtx new0 = eliminate_regs (SET_DEST (x), 0, insn);
-       rtx new1 = eliminate_regs (SET_SRC (x), 0, insn);
+       rtx new0 = eliminate_regs (SET_DEST (x), 0, insn, 1);
+       rtx new1 = eliminate_regs (SET_SRC (x), 0, insn, 0);
 
        /* If SET_DEST changed from a REG to a MEM and INSN is an insn,
           write a CLOBBER insn.  */
@@ -3224,7 +3235,7 @@ eliminate_regs (x, mem_mode, insn)
       /* Our only special processing is to pass the mode of the MEM to our
         recursive call and copy the flags.  While we are here, handle this
         case more efficiently.  */
-      new = eliminate_regs (XEXP (x, 0), GET_MODE (x), insn);
+      new = eliminate_regs (XEXP (x, 0), GET_MODE (x), insn, 0);
       if (new != XEXP (x, 0))
        {
          new = gen_rtx (MEM, GET_MODE (x), new);
@@ -3244,7 +3255,7 @@ eliminate_regs (x, mem_mode, insn)
     {
       if (*fmt == 'e')
        {
-         new = eliminate_regs (XEXP (x, i), mem_mode, insn);
+         new = eliminate_regs (XEXP (x, i), mem_mode, insn, 0);
          if (new != XEXP (x, i) && ! copied)
            {
              rtx new_x = rtx_alloc (code);
@@ -3261,7 +3272,7 @@ eliminate_regs (x, mem_mode, insn)
          int copied_vec = 0;
          for (j = 0; j < XVECLEN (x, i); j++)
            {
-             new = eliminate_regs (XVECEXP (x, i, j), mem_mode, insn);
+             new = eliminate_regs (XVECEXP (x, i, j), mem_mode, insn, 0);
              if (new != XVECEXP (x, i, j) && ! copied_vec)
                {
                  rtvec new_v = gen_rtvec_vv (XVECLEN (x, i),
@@ -3439,7 +3450,7 @@ eliminate_regs_in_insn (insn, replace)
      but now can do this as a load-address.  This saves an insn in this
      common case.  */
 
-  new_body = eliminate_regs (old_body, 0, replace ? insn : NULL_RTX);
+  new_body = eliminate_regs (old_body, 0, replace ? insn : NULL_RTX, 0);
   if (new_body != old_body)
     {
       /* If we aren't replacing things permanently and we changed something,
@@ -3528,7 +3539,7 @@ eliminate_regs_in_insn (insn, replace)
      of spill registers to be needed in the final reload pass than in
      the pre-passes.  */
   if (val && REG_NOTES (insn) != 0)
-    REG_NOTES (insn) = eliminate_regs (REG_NOTES (insn), 0, REG_NOTES (insn));
+    REG_NOTES (insn) = eliminate_regs (REG_NOTES (insn), 0, REG_NOTES (insn), 0);
 
   if (! replace)
     pop_obstacks ();
@@ -4006,7 +4017,8 @@ reload_as_needed (first, live_known)
              && GET_CODE (XEXP (PATTERN (insn), 0)) == MEM)
            XEXP (XEXP (PATTERN (insn), 0), 0)
              = eliminate_regs (XEXP (XEXP (PATTERN (insn), 0), 0),
-                               GET_MODE (XEXP (PATTERN (insn), 0)), NULL_RTX);
+                               GET_MODE (XEXP (PATTERN (insn), 0)),
+                               NULL_RTX, 0);
 
          /* If we need to do register elimination processing, do so.
             This might delete the insn, in which case we are done.  */