OSDN Git Service

* reload.c (find_reloads): Emit USEs to mark where a pseudo
authoramylaar <amylaar@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 1 May 1998 17:40:53 +0000 (17:40 +0000)
committeramylaar <amylaar@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 1 May 1998 17:40:53 +0000 (17:40 +0000)
is reloaced with the MEM of its stack slot.
* reload1.c (cannot_omit_stores): Delete.
(reload): Don't initialize it.
Don't apply avoid_return_reg logic to USEs.
When done, remove USEs that have a REG_EQUAL note on them.
(emit_reload_insns): Handle case where we have inherited a MEM.
(delete_output_reload): Don't use cannot_omit_stores.

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

gcc/ChangeLog
gcc/reload.c
gcc/reload1.c
gcc/rtl.texi

index 0d0fb27..21f6017 100644 (file)
@@ -1,3 +1,14 @@
+Sat May  2 01:37:29 1998  J"orn Rennecke <amylaar@cygnus.co.uk>
+
+       * reload.c (find_reloads): Emit USEs to mark where a pseudo
+       is reloaced with the MEM of its stack slot.
+       * reload1.c (cannot_omit_stores): Delete.
+       (reload): Don't initialize it.
+       Don't apply avoid_return_reg logic to USEs.
+       When done, remove USEs that have a REG_EQUAL note on them.
+       (emit_reload_insns): Handle case where we have inherited a MEM.
+       (delete_output_reload): Don't use cannot_omit_stores.
+
 Thu Apr 30 18:59:03 1998  Jim Wilson  <wilson@cygnus.com>
 
        * Makefile.in (cpp.info, gcc.info): Put -o option before input file.
index 333b1ea..5f02f2c 100644 (file)
@@ -2577,11 +2577,29 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
          substed_operand[i] = recog_operand[i] = *recog_operand_loc[i];
        }
       else if (code == SUBREG)
-       substed_operand[i] = recog_operand[i] = *recog_operand_loc[i]
-         = find_reloads_toplev (recog_operand[i], i, address_type[i],
-                                ind_levels,
-                                set != 0
-                                && &SET_DEST (set) == recog_operand_loc[i]);
+       {
+         rtx reg = SUBREG_REG (recog_operand[i]);
+         rtx op
+           = find_reloads_toplev (recog_operand[i], i, address_type[i],
+                                  ind_levels,
+                                  set != 0
+                                  && &SET_DEST (set) == recog_operand_loc[i]);
+
+         /* If we made a MEM to load (a part of) the stackslot of a pseudo
+            that didn't get a hard register, emit a USE with a REG_EQUAL
+            note in front so that we might inherit a previous, possibly
+            wider reload.  */
+            
+         if (GET_CODE (op) == MEM
+             && GET_CODE (reg) == REG
+             && (GET_MODE_SIZE (GET_MODE (reg))
+                 >= GET_MODE_SIZE (GET_MODE (op))))
+            REG_NOTES (emit_insn_before (gen_rtx_USE (VOIDmode, reg), insn))
+              = gen_rtx_EXPR_LIST (REG_EQUAL,
+                                  reg_equiv_memory_loc[REGNO (reg)], NULL_RTX);
+
+         substed_operand[i] = recog_operand[i] = *recog_operand_loc[i] = op;
+       }
       else if (code == PLUS || GET_RTX_CLASS (code) == '1')
        /* We can get a PLUS as an "operand" as a result of register
           elimination.  See eliminate_regs and gen_reload.  We handle
@@ -2621,16 +2639,13 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
              if (rtx_varies_p (address))
                address = copy_rtx (address);
 
-             /* If this is an output operand, we must output a CLOBBER
-                after INSN so find_equiv_reg knows REGNO is being written. 
-                Mark this insn specially, do we can put our output reloads
-                after it.  */
-
-             if (modified[i] != RELOAD_READ)
-               PUT_MODE (emit_insn_after (gen_rtx_CLOBBER (VOIDmode,
-                                                           recog_operand[i]),
-                                          insn),
-                         DImode);
+             /* Emit a USE that shows what register is being used/modified.  */
+             REG_NOTES (emit_insn_before (gen_rtx_USE (VOIDmode,
+                                                       recog_operand[i]),
+                                          insn))
+               = gen_rtx_EXPR_LIST (REG_EQUAL,
+                                    reg_equiv_memory_loc[regno],
+                                    NULL_RTX);
 
              *recog_operand_loc[i] = recog_operand[i]
                = gen_rtx_MEM (GET_MODE (recog_operand[i]), address);
index e1f56d2..c8fb2ef 100644 (file)
@@ -204,12 +204,6 @@ static HARD_REG_SET counted_for_groups;
    as part of a group, even if it seems to be otherwise ok.  */
 static HARD_REG_SET counted_for_nongroups;
 
-/* Indexed by pseudo reg number N,
-   says may not delete stores into the real (memory) home of pseudo N.
-   This is set if we already substituted a memory equivalent in some uses,
-   which happens when we have to eliminate the fp from it.  */
-static char *cannot_omit_stores;
-
 /* Nonzero if indirect addressing is supported on the machine; this means
    that spilling (REG n) does not require reloading it into a register in
    order to do (MEM (REG n)) or (MEM (PLUS (REG n) (CONST_INT c))).  The
@@ -634,8 +628,6 @@ reload (first, global, dumpfile)
   bzero ((char *) reg_equiv_address, max_regno * sizeof (rtx));
   reg_max_ref_width = (int *) alloca (max_regno * sizeof (int));
   bzero ((char *) reg_max_ref_width, max_regno * sizeof (int));
-  cannot_omit_stores = (char *) alloca (max_regno);
-  bzero (cannot_omit_stores, max_regno);
 
   if (SMALL_REGISTER_CLASSES)
     CLEAR_HARD_REG_SET (forbidden_regs);
@@ -1111,7 +1103,8 @@ reload (first, global, dumpfile)
                }
              else if (SMALL_REGISTER_CLASSES && after_call != 0
                       && !(GET_CODE (PATTERN (insn)) == SET
-                           && SET_DEST (PATTERN (insn)) == stack_pointer_rtx))
+                           && SET_DEST (PATTERN (insn)) == stack_pointer_rtx)
+                      && GET_CODE (PATTERN (insn)) != USE)
                {
                  if (reg_referenced_p (after_call, PATTERN (insn)))
                    avoid_return_reg = after_call;
@@ -2131,16 +2124,26 @@ reload (first, global, dumpfile)
        }
     }
 
-#ifdef PRESERVE_DEATH_INFO_REGNO_P
-  /* Make a pass over all the insns and remove death notes for things that
-     are no longer registers or no longer die in the insn (e.g., an input
-     and output pseudo being tied).  */
+  /* Make a pass over all the insns and delete all USEs which we inserted
+     only to tag a REG_EQUAL note on them; if PRESERVE_DEATH_INFO_REGNO_P
+     is defined, also remove death notes for things that are no longer
+     registers or no longer die in the insn (e.g., an input and output
+     pseudo being tied).  */
 
   for (insn = first; insn; insn = NEXT_INSN (insn))
     if (GET_RTX_CLASS (GET_CODE (insn)) == 'i')
       {
        rtx note, next;
 
+       if (GET_CODE (insn) == USE
+           && find_reg_note (insn, REG_EQUAL, NULL_RTX))
+         {
+           PUT_CODE (insn, NOTE);
+           NOTE_SOURCE_FILE (insn) = 0;
+           NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
+           continue;
+         }
+#ifdef PRESERVE_DEATH_INFO_REGNO_P
        for (note = REG_NOTES (insn); note; note = next)
          {
            next = XEXP (note, 1);
@@ -2149,8 +2152,8 @@ reload (first, global, dumpfile)
                    || reg_set_p (XEXP (note, 0), PATTERN (insn))))
              remove_note (insn, note);
          }
-      }
 #endif
+      }
 
   /* If we are doing stack checking, give a warning if this function's
      frame size is larger than we expect.  */
@@ -2884,7 +2887,10 @@ eliminate_regs (x, mem_mode, insn)
          new = eliminate_regs (reg_equiv_memory_loc[regno], mem_mode, insn);
          if (new != reg_equiv_memory_loc[regno])
            {
-             cannot_omit_stores[regno] = 1;
+             if (insn != 0 && GET_CODE (insn) != EXPR_LIST
+                 && GET_CODE (insn) != INSN_LIST)
+               REG_NOTES (emit_insn_before (gen_rtx_USE (VOIDmode, x), insn))
+                 = gen_rtx_EXPR_LIST (REG_EQUAL, new, NULL_RTX);
              return copy_rtx (new);
            }
        }
@@ -3103,16 +3109,17 @@ eliminate_regs (x, mem_mode, insn)
            new = SUBREG_REG (x);
          else
            {
-             /* Otherwise, ensure NEW isn't shared in case we have to reload
-                it.  */
-             new = copy_rtx (new);
-
              /* In this case, we must show that the pseudo is used in this
                 insn so that delete_output_reload will do the right thing.  */
              if (insn != 0 && GET_CODE (insn) != EXPR_LIST
                  && GET_CODE (insn) != INSN_LIST)
-               emit_insn_before (gen_rtx_USE (VOIDmode, SUBREG_REG (x)),
-                                 insn);
+               REG_NOTES (emit_insn_before (gen_rtx_USE (VOIDmode,
+                                                         SUBREG_REG (x)),
+                                                         insn))
+                 = gen_rtx_EXPR_LIST (REG_EQUAL, new, NULL_RTX);
+
+             /* Ensure NEW isn't shared in case we have to reload it.  */
+             new = copy_rtx (new);
            }
        }
       else
@@ -4056,7 +4063,8 @@ reload_as_needed (first, live_known)
            }
          else if (SMALL_REGISTER_CLASSES && after_call != 0
                   && !(GET_CODE (PATTERN (insn)) == SET
-                       && SET_DEST (PATTERN (insn)) == stack_pointer_rtx))
+                       && SET_DEST (PATTERN (insn)) == stack_pointer_rtx)
+                  && GET_CODE (PATTERN (insn)) != USE)
            {
              if (reg_referenced_p (after_call, PATTERN (insn)))
                avoid_return_reg = after_call;
@@ -5465,6 +5473,7 @@ choose_reload_regs (insn, avoid_return_reg)
            {
              register int regno = -1;
              enum machine_mode mode;
+             rtx in, use_insn = 0;
 
              if (reload_in[r] == 0)
                ;
@@ -5478,6 +5487,34 @@ choose_reload_regs (insn, avoid_return_reg)
                  regno = REGNO (reload_in_reg[r]);
                  mode = GET_MODE (reload_in_reg[r]);
                }
+             else if (GET_CODE (reload_in[r]) == MEM)
+               {
+                 rtx prev = prev_nonnote_insn (insn), note;
+
+                 if (prev && GET_CODE (prev) == INSN
+                     && GET_CODE (PATTERN (prev)) == USE
+                     && GET_CODE (XEXP (PATTERN (prev), 0)) == REG
+                     && (REGNO (XEXP (PATTERN (prev), 0))
+                         >= FIRST_PSEUDO_REGISTER)
+                     && (note = find_reg_note (prev, REG_EQUAL, NULL_RTX))
+                     && GET_CODE (XEXP (note, 0)) == MEM)
+                   {
+                     rtx addr = XEXP (XEXP (note, 0), 0);
+                     int size_diff
+                       = (GET_MODE_SIZE (GET_MODE (addr))
+                          - GET_MODE_SIZE (GET_MODE (reload_in[r])));
+                     if (size_diff >= 0
+                         && rtx_equal_p ((BYTES_BIG_ENDIAN
+                                          ? plus_constant (addr, size_diff)
+                                          : addr),
+                                         XEXP (reload_in[r], 0)))
+                       {
+                         regno = REGNO (XEXP (PATTERN (prev), 0));
+                         mode = GET_MODE (reload_in[r]);
+                         use_insn = prev;
+                       }
+                   }
+               }
 #if 0
              /* This won't work, since REGNO can be a pseudo reg number.
                 Also, it takes much more hair to keep track of all the things
@@ -5995,6 +6032,7 @@ emit_reload_insns (insn)
       register rtx old;
       rtx oldequiv_reg = 0;
       rtx this_reload_insn = 0;
+      int expect_occurrences = 1;
 
       if (reload_spill_index[j] >= 0)
        new_spill_reg_store[reload_spill_index[j]] = 0;
@@ -6428,6 +6466,19 @@ emit_reload_insns (insn)
          end_sequence ();
        }
 
+      /* When inheriting a wider reload, we have a MEM in reload_in[j],
+        e.g. inheriting a SImode output reload for
+        (mem:HI (plus:SI (reg:SI 14 fp) (const_int 10)))  */
+      if (optimize && reload_inherited[j] && reload_in[j]
+         && GET_CODE (reload_in[j]) == MEM
+         && reload_spill_index[j] >= 0
+         && TEST_HARD_REG_BIT (reg_reloaded_valid, reload_spill_index[j]))
+       {
+         expect_occurrences
+           = count_occurrences (PATTERN (insn), reload_in[j]) == 1 ? 0 : -1;
+         reload_in[j]
+           = regno_reg_rtx[reg_reloaded_contents[reload_spill_index[j]]];
+       }
       /* Add a note saying the input reload reg
         dies in this insn, if anyone cares.  */
 #ifdef PRESERVE_DEATH_INFO_REGNO_P
@@ -6561,7 +6612,8 @@ emit_reload_insns (insn)
          && dead_or_set_p (insn, reload_in[j])
          /* This is unsafe if operand occurs more than once in current
             insn.  Perhaps some occurrences weren't reloaded.  */
-         && count_occurrences (PATTERN (insn), reload_in[j]) == 1)
+         && (count_occurrences (PATTERN (insn), reload_in[j])
+             == expect_occurrences))
        delete_output_reload (insn, j,
                              spill_reg_store[reload_spill_index[j]]);
 
@@ -7296,9 +7348,6 @@ delete_output_reload (insn, j, output_reload_insn)
        return;
     }
 
-  if (cannot_omit_stores[REGNO (reg)])
-    return;
-
   /* If this insn will store in the pseudo again,
      the previous store can be removed.  */
   if (reload_out[j] == reload_in[j])
index a715b8a..0127fce 100644 (file)
@@ -1892,6 +1892,10 @@ it may not be apparent why this is so.  Therefore, the compiler will
 not attempt to delete previous instructions whose only effect is to
 store a value in @var{x}.  @var{x} must be a @code{reg} expression.
 
+During the reload phase, an insn that has a @code{use} as pattern
+can carry a reg_equal note.  These @code{use} insns will be deleted
+before the reload phase exits.
+
 During the delayed branch scheduling phase, @var{x} may be an insn.
 This indicates that @var{x} previously was located at this place in the
 code and its data dependencies need to be taken into account.  These