Commit 41203287 by Bernd Schmidt Committed by Bernd Schmidt

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
parent 0836b77f
......@@ -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.
......
......@@ -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))
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment