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
This commit is contained in:
parent
bd64e40c54
commit
b60a841635
|
@ -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.
|
||||
|
|
45
gcc/reload.c
45
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);
|
||||
|
|
101
gcc/reload1.c
101
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])
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue