aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJ"orn Rennecke <amylaar@cygnus.co.uk>1998-05-01 17:40:53 +0000
committerJoern Rennecke <amylaar@gcc.gnu.org>1998-05-01 18:40:53 +0100
commitb60a8416357bb6e8166547bef7bc67c56f104557 (patch)
treeffd76e0f0eda23e68b7a122b84484b965f5142b4 /gcc
parentbd64e40c54cbc7a94acf291e2011346caa637b6e (diff)
downloadgcc-b60a8416357bb6e8166547bef7bc67c56f104557.zip
gcc-b60a8416357bb6e8166547bef7bc67c56f104557.tar.gz
gcc-b60a8416357bb6e8166547bef7bc67c56f104557.tar.bz2
reload.c (find_reloads): Emit USEs to mark where a pseudo is reloaced with the MEM of its stack slot.
* 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. From-SVN: r19508
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog11
-rw-r--r--gcc/reload.c45
-rw-r--r--gcc/reload1.c101
-rw-r--r--gcc/rtl.texi4
4 files changed, 120 insertions, 41 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 0d0fb27..21f6017 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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.
diff --git a/gcc/reload.c b/gcc/reload.c
index 333b1ea..5f02f2c 100644
--- a/gcc/reload.c
+++ b/gcc/reload.c
@@ -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);
diff --git a/gcc/reload1.c b/gcc/reload1.c
index e1f56d2..c8fb2ef 100644
--- a/gcc/reload1.c
+++ b/gcc/reload1.c
@@ -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])
diff --git a/gcc/rtl.texi b/gcc/rtl.texi
index a715b8a..0127fce 100644
--- a/gcc/rtl.texi
+++ b/gcc/rtl.texi
@@ -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