mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-03-24 04:10:29 +08:00
Improve reload code generation by ignoring init insns for reloads.
* reload1.c (remove_init_insns, will_delete_init_insn_p): New static functions. (reload, calculate_needs_all_insns, reload_as_needed): Use them. From-SVN: r210685
This commit is contained in:
parent
0836b77f3d
commit
4120328793
@ -198,6 +198,10 @@
|
||||
|
||||
2014-05-19 Bernd Schmidt <bernds@codesourcery.com>
|
||||
|
||||
* reload1.c (remove_init_insns, will_delete_init_insn_p): New static
|
||||
functions.
|
||||
(reload, calculate_needs_all_insns, reload_as_needed): Use them.
|
||||
|
||||
* simplify-rtx.c (simplify_unary_operation_1): Use CONST_INT_P in
|
||||
shift simplification where it was intended.
|
||||
|
||||
|
101
gcc/reload1.c
101
gcc/reload1.c
@ -686,6 +686,65 @@ static int failure;
|
||||
/* Temporary array of pseudo-register number. */
|
||||
static int *temp_pseudo_reg_arr;
|
||||
|
||||
/* If a pseudo has no hard reg, delete the insns that made the equivalence.
|
||||
If that insn didn't set the register (i.e., it copied the register to
|
||||
memory), just delete that insn instead of the equivalencing insn plus
|
||||
anything now dead. If we call delete_dead_insn on that insn, we may
|
||||
delete the insn that actually sets the register if the register dies
|
||||
there and that is incorrect. */
|
||||
static void
|
||||
remove_init_insns ()
|
||||
{
|
||||
for (int i = FIRST_PSEUDO_REGISTER; i < max_regno; i++)
|
||||
{
|
||||
if (reg_renumber[i] < 0 && reg_equiv_init (i) != 0)
|
||||
{
|
||||
rtx list;
|
||||
for (list = reg_equiv_init (i); list; list = XEXP (list, 1))
|
||||
{
|
||||
rtx equiv_insn = XEXP (list, 0);
|
||||
|
||||
/* If we already deleted the insn or if it may trap, we can't
|
||||
delete it. The latter case shouldn't happen, but can
|
||||
if an insn has a variable address, gets a REG_EH_REGION
|
||||
note added to it, and then gets converted into a load
|
||||
from a constant address. */
|
||||
if (NOTE_P (equiv_insn)
|
||||
|| can_throw_internal (equiv_insn))
|
||||
;
|
||||
else if (reg_set_p (regno_reg_rtx[i], PATTERN (equiv_insn)))
|
||||
delete_dead_insn (equiv_insn);
|
||||
else
|
||||
SET_INSN_DELETED (equiv_insn);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Return true if remove_init_insns will delete INSN. */
|
||||
static bool
|
||||
will_delete_init_insn_p (rtx insn)
|
||||
{
|
||||
rtx set = single_set (insn);
|
||||
if (!set || !REG_P (SET_DEST (set)))
|
||||
return false;
|
||||
unsigned regno = REGNO (SET_DEST (set));
|
||||
|
||||
if (can_throw_internal (insn))
|
||||
return false;
|
||||
|
||||
if (regno < FIRST_PSEUDO_REGISTER || reg_renumber[regno] >= 0)
|
||||
return false;
|
||||
|
||||
for (rtx list = reg_equiv_init (regno); list; list = XEXP (list, 1))
|
||||
{
|
||||
rtx equiv_insn = XEXP (list, 0);
|
||||
if (equiv_insn == insn)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Main entry point for the reload pass.
|
||||
|
||||
FIRST is the first insn of the function being compiled.
|
||||
@ -993,37 +1052,7 @@ reload (rtx first, int global)
|
||||
if (ep->can_eliminate)
|
||||
mark_elimination (ep->from, ep->to);
|
||||
|
||||
/* If a pseudo has no hard reg, delete the insns that made the equivalence.
|
||||
If that insn didn't set the register (i.e., it copied the register to
|
||||
memory), just delete that insn instead of the equivalencing insn plus
|
||||
anything now dead. If we call delete_dead_insn on that insn, we may
|
||||
delete the insn that actually sets the register if the register dies
|
||||
there and that is incorrect. */
|
||||
|
||||
for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++)
|
||||
{
|
||||
if (reg_renumber[i] < 0 && reg_equiv_init (i) != 0)
|
||||
{
|
||||
rtx list;
|
||||
for (list = reg_equiv_init (i); list; list = XEXP (list, 1))
|
||||
{
|
||||
rtx equiv_insn = XEXP (list, 0);
|
||||
|
||||
/* If we already deleted the insn or if it may trap, we can't
|
||||
delete it. The latter case shouldn't happen, but can
|
||||
if an insn has a variable address, gets a REG_EH_REGION
|
||||
note added to it, and then gets converted into a load
|
||||
from a constant address. */
|
||||
if (NOTE_P (equiv_insn)
|
||||
|| can_throw_internal (equiv_insn))
|
||||
;
|
||||
else if (reg_set_p (regno_reg_rtx[i], PATTERN (equiv_insn)))
|
||||
delete_dead_insn (equiv_insn);
|
||||
else
|
||||
SET_INSN_DELETED (equiv_insn);
|
||||
}
|
||||
}
|
||||
}
|
||||
remove_init_insns ();
|
||||
|
||||
/* Use the reload registers where necessary
|
||||
by generating move instructions to move the must-be-register
|
||||
@ -1484,14 +1513,9 @@ calculate_needs_all_insns (int 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 && REG_P (SET_DEST (set))
|
||||
&& reg_renumber[REGNO (SET_DEST (set))] < 0
|
||||
&& (reg_equiv_constant (REGNO (SET_DEST (set)))
|
||||
|| (reg_equiv_invariant (REGNO (SET_DEST (set)))))
|
||||
&& reg_equiv_init (REGNO (SET_DEST (set))))
|
||||
if (will_delete_init_insn_p (insn))
|
||||
continue;
|
||||
|
||||
/* If needed, eliminate any eliminable registers. */
|
||||
@ -4586,6 +4610,9 @@ reload_as_needed (int live_known)
|
||||
rtx old_prev = PREV_INSN (insn);
|
||||
#endif
|
||||
|
||||
if (will_delete_init_insn_p (insn))
|
||||
continue;
|
||||
|
||||
/* If we pass a label, copy the offsets from the label information
|
||||
into the current offsets of each elimination. */
|
||||
if (LABEL_P (insn))
|
||||
|
Loading…
x
Reference in New Issue
Block a user