* local-alloc.c (function_invariant_p): New function.
authoramylaar <amylaar@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 1 Dec 1998 10:00:11 +0000 (10:00 +0000)
committeramylaar <amylaar@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 1 Dec 1998 10:00:11 +0000 (10:00 +0000)
(update_equiv_regs): Use function_invariant_p instead of CONSTANT_P
to decide if an equivalence should be recorded.
* reload1.c (num_eliminable_invariants): New static variable.
(reload): Set it.  Use function_invariant_p instead of CONSTANT_P
to decide if an equivalence should be recorded.
Unshare PLUS.
(calculate_needs_all_insns): Skip insns that only set an equivalence.
Take num_eliminable_invariants into account when deciding
if register elimination should be done.
(reload_as_needed): Take num_eliminable_invariants into account
when deciding if register elimination should be done.
(eliminate_regs): Handle non-constant reg_equiv_constant.
* rtl.h (function_invariant_p): Declare.

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

gcc/ChangeLog
gcc/local-alloc.c
gcc/reload1.c
gcc/rtl.h

index 74a9a59..ee4b9ff 100644 (file)
@@ -1,3 +1,20 @@
+Tue Dec  1 17:58:26 1998  J"orn Rennecke <amylaar@cygnus.co.uk>
+
+       * local-alloc.c (function_invariant_p): New function.
+       (update_equiv_regs): Use function_invariant_p instead of CONSTANT_P
+       to decide if an equivalence should be recorded.
+       * reload1.c (num_eliminable_invariants): New static variable.
+       (reload): Set it.  Use function_invariant_p instead of CONSTANT_P
+       to decide if an equivalence should be recorded.
+       Unshare PLUS.
+       (calculate_needs_all_insns): Skip insns that only set an equivalence.
+       Take num_eliminable_invariants into account when deciding
+       if register elimination should be done.
+       (reload_as_needed): Take num_eliminable_invariants into account
+       when deciding if register elimination should be done.
+       (eliminate_regs): Handle non-constant reg_equiv_constant.
+       * rtl.h (function_invariant_p): Declare.
+
 Mon Nov 30 02:00:08 PST 1998 Jeff Law  (law@cygnus.com)
 
        * version.c: Bump for snapshot.
index e8110ac..f112713 100644 (file)
@@ -630,6 +630,22 @@ memref_used_between_p (memref, start, end)
   return 0;
 }
 \f
+/* Return nonzero if the rtx X is invariant over the current function.  */
+int
+function_invariant_p (x)
+     rtx x;
+{
+  if (CONSTANT_P (x))
+    return 1;
+  if (x == frame_pointer_rtx || x == arg_pointer_rtx)
+    return 1;
+  if (GET_CODE (x) == PLUS
+      && (XEXP (x, 0) == frame_pointer_rtx || XEXP (x, 0) == arg_pointer_rtx)
+      && CONSTANT_P (XEXP (x, 1)))
+    return 1;
+  return 0;
+}
+
 /* Find registers that are equivalent to a single value throughout the
    compilation (either because they can be referenced in memory or are set once
    from a single constant).  Lower their priority for a register.
@@ -798,7 +814,7 @@ update_equiv_regs ()
 
       if (REG_N_SETS (regno) != 1
          && (! note
-             || ! CONSTANT_P (XEXP (note, 0))
+             || ! function_invariant_p (XEXP (note, 0))
              || (reg_equiv_replacement[regno]
                  && ! rtx_equal_p (XEXP (note, 0),
                                    reg_equiv_replacement[regno]))))
@@ -812,7 +828,7 @@ update_equiv_regs ()
 
       /* If this register is known to be equal to a constant, record that
         it is always equivalent to the constant.  */
-      if (note && CONSTANT_P (XEXP (note, 0)))
+      if (note && function_invariant_p (XEXP (note, 0)))
        PUT_MODE (note, (enum machine_mode) REG_EQUIV);
 
       /* If this insn introduces a "constant" register, decrease the priority
index e4dee18..08f5375 100644 (file)
@@ -338,6 +338,9 @@ int num_not_at_initial_offset;
 
 /* Count the number of registers that we may be able to eliminate.  */
 static int num_eliminable;
+/* And the number of registers that are equivalent to a constant that
+   can be eliminated to frame_pointer / arg_pointer + constant.  */
+static int num_eliminable_invariants;
 
 /* For each label, we record the offset of each elimination.  If we reach
    a label by more than one path and an offset differs, we cannot do the
@@ -659,6 +662,7 @@ reload (first, global, dumpfile)
      Also look for a "constant" NOTE_INSN_SETJMP.  This means that all
      caller-saved registers must be marked live.  */
 
+  num_eliminable_invariants = 0;
   for (insn = first; insn; insn = NEXT_INSN (insn))
     {
       rtx set = single_set (insn);
@@ -674,7 +678,8 @@ reload (first, global, dumpfile)
          rtx note = find_reg_note (insn, REG_EQUIV, NULL_RTX);
          if (note
 #ifdef LEGITIMATE_PIC_OPERAND_P
-             && (! CONSTANT_P (XEXP (note, 0)) || ! flag_pic
+             && (! function_invariant_p (XEXP (note, 0))
+                 || ! flag_pic
                  || LEGITIMATE_PIC_OPERAND_P (XEXP (note, 0)))
 #endif
              )
@@ -692,9 +697,22 @@ reload (first, global, dumpfile)
 
                      reg_equiv_memory_loc[i] = x;
                    }
-                 else if (CONSTANT_P (x))
+                 else if (function_invariant_p (x))
                    {
-                     if (LEGITIMATE_CONSTANT_P (x))
+                     if (GET_CODE (x) == PLUS)
+                       {
+                         /* This is PLUS of frame pointer and a constant,
+                            and might be shared.  Unshare it.  */
+                         reg_equiv_constant[i] = copy_rtx (x);
+                         num_eliminable_invariants++;
+                       }
+                     else if (x == frame_pointer_rtx
+                              || x == arg_pointer_rtx)
+                       {
+                         reg_equiv_constant[i] = x;
+                         num_eliminable_invariants++;
+                       }
+                     else if (LEGITIMATE_CONSTANT_P (x))
                        reg_equiv_constant[i] = x;
                      else
                        reg_equiv_memory_loc[i]
@@ -1335,9 +1353,16 @@ calculate_needs_all_insns (global)
          rtx old_notes = REG_NOTES (insn);
          int did_elimination = 0;
          int operands_changed = 0;
+         rtx set = single_set (insn);
+
+         /* Skip insns that only set an equivalence.  */
+         if (set && GET_CODE (SET_DEST (set)) == REG
+             && reg_renumber[REGNO (SET_DEST (set))] < 0
+             && reg_equiv_constant[REGNO (SET_DEST (set))])
+           continue;
 
          /* If needed, eliminate any eliminable registers.  */
-         if (num_eliminable)
+         if (num_eliminable || num_eliminable_invariants)
            did_elimination = eliminate_regs_in_insn (insn, 0);
 
          /* Analyze the instruction.  */
@@ -2698,6 +2723,11 @@ eliminate_regs (x, mem_mode, insn)
              }
 
        }
+      else if (reg_renumber[regno] < 0 && reg_equiv_constant
+              && reg_equiv_constant[regno]
+              && ! CONSTANT_P (reg_equiv_constant[regno]))
+       return eliminate_regs (copy_rtx (reg_equiv_constant[regno]),
+                              mem_mode, insn);
       return x;
 
     case PLUS:
@@ -4163,7 +4193,7 @@ reload_as_needed (live_known)
 
          /* If we need to do register elimination processing, do so.
             This might delete the insn, in which case we are done.  */
-         if (num_eliminable && chain->need_elim)
+         if ((num_eliminable || num_eliminable_invariants) && chain->need_elim)
            {
              eliminate_regs_in_insn (insn, 1);
              if (GET_CODE (insn) == NOTE)
index bf9a603..93e7842 100644 (file)
--- a/gcc/rtl.h
+++ b/gcc/rtl.h
@@ -1440,6 +1440,7 @@ extern void init_optabs                   PROTO ((void));
 extern void dump_local_alloc           PROTO ((FILE *));
 #endif
 extern void local_alloc                        PROTO ((void));
+extern int function_invariant_p                PROTO ((rtx));
 
 /* In reload1.c */
 extern void reload_cse_regs            PROTO ((rtx));