Commit 67bb0206 by Bernd Schmidt Committed by Bernd Schmidt

postreload.c (last_label_ruid, [...]): New static variables.

	* postreload.c (last_label_ruid, first_index_reg, last_index_reg):
	New static variables.
	(reload_combine_recognize_pattern): New static function, broken out
	of reload_combine.
	(reload_combine): Use it.  Only initialize first_index_reg and
	last_index_reg once.

From-SVN: r162228
parent c5f77dcb
2010-07-15 Bernd Schmidt <bernds@codesourcery.com>
* postreload.c (last_label_ruid, first_index_reg, last_index_reg):
New static variables.
(reload_combine_recognize_pattern): New static function, broken out
of reload_combine.
(reload_combine): Use it. Only initialize first_index_reg and
last_index_reg once.
2010-07-15 Richard Henderson <rth@redhat.com> 2010-07-15 Richard Henderson <rth@redhat.com>
* cgraphunit.c (cgraph_build_static_cdtor): Clear current_function_decl * cgraphunit.c (cgraph_build_static_cdtor): Clear current_function_decl
......
...@@ -691,96 +691,27 @@ static struct ...@@ -691,96 +691,27 @@ static struct
and the store_ruid / use_ruid fields in reg_state. */ and the store_ruid / use_ruid fields in reg_state. */
static int reload_combine_ruid; static int reload_combine_ruid;
#define LABEL_LIVE(LABEL) \ /* The RUID of the last label we encountered in reload_combine. */
(label_live[CODE_LABEL_NUMBER (LABEL) - min_labelno]) static int last_label_ruid;
static void
reload_combine (void)
{
rtx insn, set;
int first_index_reg = -1;
int last_index_reg = 0;
int i;
basic_block bb;
unsigned int r;
int last_label_ruid;
int min_labelno, n_labels;
HARD_REG_SET ever_live_at_start, *label_live;
/* If reg+reg can be used in offsetable memory addresses, the main chunk of
reload has already used it where appropriate, so there is no use in
trying to generate it now. */
if (double_reg_address_ok && INDEX_REG_CLASS != NO_REGS)
return;
/* To avoid wasting too much time later searching for an index register,
determine the minimum and maximum index register numbers. */
for (r = 0; r < FIRST_PSEUDO_REGISTER; r++)
if (TEST_HARD_REG_BIT (reg_class_contents[INDEX_REG_CLASS], r))
{
if (first_index_reg == -1)
first_index_reg = r;
last_index_reg = r;
}
/* If no index register is available, we can quit now. */
if (first_index_reg == -1)
return;
/* Set up LABEL_LIVE and EVER_LIVE_AT_START. The register lifetime
information is a bit fuzzy immediately after reload, but it's
still good enough to determine which registers are live at a jump
destination. */
min_labelno = get_first_label_num ();
n_labels = max_label_num () - min_labelno;
label_live = XNEWVEC (HARD_REG_SET, n_labels);
CLEAR_HARD_REG_SET (ever_live_at_start);
FOR_EACH_BB_REVERSE (bb)
{
insn = BB_HEAD (bb);
if (LABEL_P (insn))
{
HARD_REG_SET live;
bitmap live_in = df_get_live_in (bb);
REG_SET_TO_HARD_REG_SET (live, live_in); /* The register numbers of the first and last index register. A value of
compute_use_by_pseudos (&live, live_in); -1 in LAST_INDEX_REG indicates that we've previously computed these
COPY_HARD_REG_SET (LABEL_LIVE (insn), live); values and found no suitable index registers. */
IOR_HARD_REG_SET (ever_live_at_start, live); static int first_index_reg = -1;
} static int last_index_reg;
}
/* Initialize last_label_ruid, reload_combine_ruid and reg_state. */ #define LABEL_LIVE(LABEL) \
last_label_ruid = reload_combine_ruid = 0; (label_live[CODE_LABEL_NUMBER (LABEL) - min_labelno])
for (r = 0; r < FIRST_PSEUDO_REGISTER; r++)
{
reg_state[r].store_ruid = reload_combine_ruid;
if (fixed_regs[r])
reg_state[r].use_index = -1;
else
reg_state[r].use_index = RELOAD_COMBINE_MAX_USES;
}
for (insn = get_last_insn (); insn; insn = PREV_INSN (insn))
{
rtx note;
/* We cannot do our optimization across labels. Invalidating all the use
information we have would be costly, so we just note where the label
is and then later disable any optimization that would cross it. */
if (LABEL_P (insn))
last_label_ruid = reload_combine_ruid;
else if (BARRIER_P (insn))
for (r = 0; r < FIRST_PSEUDO_REGISTER; r++)
if (! fixed_regs[r])
reg_state[r].use_index = RELOAD_COMBINE_MAX_USES;
if (! INSN_P (insn)) /* Called by reload_combine when scanning INSN. Try to detect a pattern we
continue; can handle and improve. Return true if no further processing is needed on
INSN; false if it wasn't recognized and should be handled normally. */
reload_combine_ruid++; static bool
reload_combine_recognize_pattern (rtx insn)
{
rtx set, reg, src;
unsigned int regno;
/* Look for (set (REGX) (CONST_INT)) /* Look for (set (REGX) (CONST_INT))
(set (REGX) (PLUS (REGX) (REGY))) (set (REGX) (PLUS (REGX) (REGY)))
...@@ -796,25 +727,29 @@ reload_combine (void) ...@@ -796,25 +727,29 @@ reload_combine (void)
Also, explicitly check that REGX != REGY; our life information Also, explicitly check that REGX != REGY; our life information
does not yet show whether REGY changes in this insn. */ does not yet show whether REGY changes in this insn. */
set = single_set (insn); set = single_set (insn);
if (set != NULL_RTX if (set == NULL_RTX)
&& REG_P (SET_DEST (set)) return false;
&& (hard_regno_nregs[REGNO (SET_DEST (set))]
[GET_MODE (SET_DEST (set))] reg = SET_DEST (set);
== 1) src = SET_SRC (set);
&& GET_CODE (SET_SRC (set)) == PLUS if (!REG_P (reg)
&& REG_P (XEXP (SET_SRC (set), 1)) || hard_regno_nregs[REGNO (reg)][GET_MODE (reg)] != 1)
&& rtx_equal_p (XEXP (SET_SRC (set), 0), SET_DEST (set)) return false;
&& !rtx_equal_p (XEXP (SET_SRC (set), 1), SET_DEST (set))
&& last_label_ruid < reg_state[REGNO (SET_DEST (set))].use_ruid) regno = REGNO (reg);
{
rtx reg = SET_DEST (set); if (GET_CODE (src) == PLUS
rtx plus = SET_SRC (set); && REG_P (XEXP (src, 1))
rtx base = XEXP (plus, 1); && rtx_equal_p (XEXP (src, 0), reg)
&& !rtx_equal_p (XEXP (src, 1), reg)
&& last_label_ruid < reg_state[regno].use_ruid)
{
rtx base = XEXP (src, 1);
rtx prev = prev_nonnote_insn (insn); rtx prev = prev_nonnote_insn (insn);
rtx prev_set = prev ? single_set (prev) : NULL_RTX; rtx prev_set = prev ? single_set (prev) : NULL_RTX;
unsigned int regno = REGNO (reg);
rtx index_reg = NULL_RTX; rtx index_reg = NULL_RTX;
rtx reg_sum = NULL_RTX; rtx reg_sum = NULL_RTX;
int i;
/* Now we need to set INDEX_REG to an index register (denoted as /* Now we need to set INDEX_REG to an index register (denoted as
REGZ in the illustration above) and REG_SUM to the expression REGZ in the illustration above) and REG_SUM to the expression
...@@ -826,7 +761,7 @@ reload_combine (void) ...@@ -826,7 +761,7 @@ reload_combine (void)
REGNO (base))) REGNO (base)))
{ {
index_reg = reg; index_reg = reg;
reg_sum = plus; reg_sum = src;
} }
else else
{ {
...@@ -836,8 +771,7 @@ reload_combine (void) ...@@ -836,8 +771,7 @@ reload_combine (void)
two registers. */ two registers. */
for (i = first_index_reg; i <= last_index_reg; i++) for (i = first_index_reg; i <= last_index_reg; i++)
{ {
if (TEST_HARD_REG_BIT (reg_class_contents[INDEX_REG_CLASS], if (TEST_HARD_REG_BIT (reg_class_contents[INDEX_REG_CLASS], i)
i)
&& reg_state[i].use_index == RELOAD_COMBINE_MAX_USES && reg_state[i].use_index == RELOAD_COMBINE_MAX_USES
&& reg_state[i].store_ruid <= reg_state[regno].use_ruid && reg_state[i].store_ruid <= reg_state[regno].use_ruid
&& hard_regno_nregs[i][GET_MODE (reg)] == 1) && hard_regno_nregs[i][GET_MODE (reg)] == 1)
...@@ -860,8 +794,6 @@ reload_combine (void) ...@@ -860,8 +794,6 @@ reload_combine (void)
&& (reg_state[REGNO (base)].store_ruid && (reg_state[REGNO (base)].store_ruid
<= reg_state[regno].use_ruid)) <= reg_state[regno].use_ruid))
{ {
int i;
/* Change destination register and, if necessary, the constant /* Change destination register and, if necessary, the constant
value in PREV, the constant loading instruction. */ value in PREV, the constant loading instruction. */
validate_change (prev, &SET_DEST (prev_set), index_reg, 1); validate_change (prev, &SET_DEST (prev_set), index_reg, 1);
...@@ -908,11 +840,110 @@ reload_combine (void) ...@@ -908,11 +840,110 @@ reload_combine (void)
reg_state[regno].use_index = RELOAD_COMBINE_MAX_USES; reg_state[regno].use_index = RELOAD_COMBINE_MAX_USES;
reg_state[REGNO (index_reg)].store_ruid reg_state[REGNO (index_reg)].store_ruid
= reload_combine_ruid; = reload_combine_ruid;
continue; return true;
}
}
}
return false;
}
static void
reload_combine (void)
{
rtx insn;
int i;
basic_block bb;
unsigned int r;
int min_labelno, n_labels;
HARD_REG_SET ever_live_at_start, *label_live;
/* To avoid wasting too much time later searching for an index register,
determine the minimum and maximum index register numbers. */
if (INDEX_REG_CLASS == NO_REGS)
last_index_reg = -1;
else if (first_index_reg == -1 && last_index_reg == 0)
{
for (r = 0; r < FIRST_PSEUDO_REGISTER; r++)
if (TEST_HARD_REG_BIT (reg_class_contents[INDEX_REG_CLASS], r))
{
if (first_index_reg == -1)
first_index_reg = r;
last_index_reg = r;
}
/* If no index register is available, we can quit now. Set LAST_INDEX_REG
to -1 so we'll know to quit early the next time we get here. */
if (first_index_reg == -1)
{
last_index_reg = -1;
return;
}
}
/* If reg+reg can be used in offsetable memory addresses, the main chunk of
reload has already used it where appropriate, so there is no use in
trying to generate it now. */
if (double_reg_address_ok || last_index_reg == -1)
return;
/* Set up LABEL_LIVE and EVER_LIVE_AT_START. The register lifetime
information is a bit fuzzy immediately after reload, but it's
still good enough to determine which registers are live at a jump
destination. */
min_labelno = get_first_label_num ();
n_labels = max_label_num () - min_labelno;
label_live = XNEWVEC (HARD_REG_SET, n_labels);
CLEAR_HARD_REG_SET (ever_live_at_start);
FOR_EACH_BB_REVERSE (bb)
{
insn = BB_HEAD (bb);
if (LABEL_P (insn))
{
HARD_REG_SET live;
bitmap live_in = df_get_live_in (bb);
REG_SET_TO_HARD_REG_SET (live, live_in);
compute_use_by_pseudos (&live, live_in);
COPY_HARD_REG_SET (LABEL_LIVE (insn), live);
IOR_HARD_REG_SET (ever_live_at_start, live);
} }
} }
/* Initialize last_label_ruid, reload_combine_ruid and reg_state. */
last_label_ruid = reload_combine_ruid = 0;
for (r = 0; r < FIRST_PSEUDO_REGISTER; r++)
{
reg_state[r].store_ruid = reload_combine_ruid;
if (fixed_regs[r])
reg_state[r].use_index = -1;
else
reg_state[r].use_index = RELOAD_COMBINE_MAX_USES;
} }
for (insn = get_last_insn (); insn; insn = PREV_INSN (insn))
{
rtx note;
/* We cannot do our optimization across labels. Invalidating all the use
information we have would be costly, so we just note where the label
is and then later disable any optimization that would cross it. */
if (LABEL_P (insn))
last_label_ruid = reload_combine_ruid;
else if (BARRIER_P (insn))
for (r = 0; r < FIRST_PSEUDO_REGISTER; r++)
if (! fixed_regs[r])
reg_state[r].use_index = RELOAD_COMBINE_MAX_USES;
if (! INSN_P (insn))
continue;
reload_combine_ruid++;
if (reload_combine_recognize_pattern (insn))
continue;
note_stores (PATTERN (insn), reload_combine_note_store, NULL); note_stores (PATTERN (insn), reload_combine_note_store, NULL);
if (CALL_P (insn)) if (CALL_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