Commit 5a107a0f by Vladimir Makarov Committed by Vladimir Makarov

ira.c (update_equiv_regs): Add insn having equiv memory even if it is not lhs of the insn.

2013-05-07  Vladimir Makarov  <vmakarov@redhat.com>

	* ira.c (update_equiv_regs): Add insn having equiv memory even if
	it is not lhs of the insn.
	(setup_reg_equiv): Remove insn having equiv memory which it is not
	lhs of the insn.
	* lra-constraints.c (process_address): Try to improve generation
	code for address base + disp.
	(lra_constraints): Make correct the code for checking insn setting
	up backward equivalence.  Remove insn only if it is in the init
	insn list.
	* lra-eliminations.c (update_reg_eliminate): Change return value.
	(lra_eliminate): Use the result.

From-SVN: r198695
parent 3f5783ea
2013-05-07 Vladimir Makarov <vmakarov@redhat.com>
* ira.c (update_equiv_regs): Add insn having equiv memory even if
it is not lhs of the insn.
(setup_reg_equiv): Remove insn having equiv memory which it is not
lhs of the insn.
* lra-constraints.c (process_address): Try to improve generation
code for address base + disp.
(lra_constraints): Make correct the code for checking insn setting
up backward equivalence. Remove insn only if it is in the init
insn list.
* lra-eliminations.c (update_reg_eliminate): Change return value.
(lra_eliminate): Use the result.
2013-05-07 Uros Bizjak <ubizjak@gmail.com>
* config/i386/sse.md (ssescalarnummask): New mode attribute.
......
......@@ -2971,8 +2971,12 @@ update_equiv_regs (void)
register. */
reg_equiv[regno].is_arg_equivalence = 1;
/* Record for reload that this is an equivalencing insn. */
if (rtx_equal_p (src, XEXP (note, 0)))
/* The insn result can have equivalence memory although
the equivalence is not set up by the insn. We add
this insn to init insns as it is a flag for now that
regno has an equivalence. We will remove the insn
from init insn list later. */
if (rtx_equal_p (src, XEXP (note, 0)) || MEM_P (XEXP (note, 0)))
ira_reg_equiv[regno].init_insns
= gen_rtx_INSN_LIST (VOIDmode, insn,
ira_reg_equiv[regno].init_insns);
......@@ -3368,11 +3372,14 @@ static void
setup_reg_equiv (void)
{
int i;
rtx elem, insn, set, x;
rtx elem, prev_elem, next_elem, insn, set, x;
for (i = FIRST_PSEUDO_REGISTER; i < ira_reg_equiv_len; i++)
for (elem = ira_reg_equiv[i].init_insns; elem; elem = XEXP (elem, 1))
for (prev_elem = NULL, elem = ira_reg_equiv[i].init_insns;
elem;
prev_elem = elem, elem = next_elem)
{
next_elem = XEXP (elem, 1);
insn = XEXP (elem, 0);
set = single_set (insn);
......@@ -3381,7 +3388,22 @@ setup_reg_equiv (void)
if (set != 0 && (REG_P (SET_DEST (set)) || REG_P (SET_SRC (set))))
{
if ((x = find_reg_note (insn, REG_EQUIV, NULL_RTX)) != NULL)
{
x = XEXP (x, 0);
if (REG_P (SET_DEST (set))
&& REGNO (SET_DEST (set)) == (unsigned int) i
&& ! rtx_equal_p (SET_SRC (set), x) && MEM_P (x))
{
/* This insn reporting the equivalence but
actually not setting it. Remove it from the
list. */
if (prev_elem == NULL)
ira_reg_equiv[i].init_insns = next_elem;
else
XEXP (prev_elem, 1) = next_elem;
elem = prev_elem;
}
}
else if (REG_P (SET_DEST (set))
&& REGNO (SET_DEST (set)) == (unsigned int) i)
x = SET_SRC (set);
......
......@@ -1680,14 +1680,13 @@ process_alt_operands (int only_alternative)
case 'G':
case 'H':
if (GET_CODE (op) == CONST_DOUBLE
if (CONST_DOUBLE_AS_FLOAT_P (op)
&& CONST_DOUBLE_OK_FOR_CONSTRAINT_P (op, c, p))
win = true;
break;
case 's':
if (CONST_INT_P (op)
|| (GET_CODE (op) == CONST_DOUBLE && mode == VOIDmode))
if (CONST_SCALAR_INT_P (op))
break;
case 'i':
......@@ -1696,8 +1695,7 @@ process_alt_operands (int only_alternative)
break;
case 'n':
if (CONST_INT_P (op)
|| (GET_CODE (op) == CONST_DOUBLE && mode == VOIDmode))
if (CONST_SCALAR_INT_P (op))
win = true;
break;
......@@ -2411,18 +2409,18 @@ equiv_address_substitution (struct address_info *ad)
/* Major function to make reloads for an address in operand NOP.
The supported cases are:
1) an address that existed before LRA started, at which point it must
have been valid. These addresses are subject to elimination and
may have become invalid due to the elimination offset being out
1) an address that existed before LRA started, at which point it
must have been valid. These addresses are subject to elimination
and may have become invalid due to the elimination offset being out
of range.
2) an address created by forcing a constant to memory (force_const_to_mem).
The initial form of these addresses might not be valid, and it is this
function's job to make them valid.
2) an address created by forcing a constant to memory
(force_const_to_mem). The initial form of these addresses might
not be valid, and it is this function's job to make them valid.
3) a frame address formed from a register and a (possibly zero)
constant offset. As above, these addresses might not be valid
and this function must make them so.
constant offset. As above, these addresses might not be valid and
this function must make them so.
Add reloads to the lists *BEFORE and *AFTER. We might need to add
reloads to *AFTER because of inc/dec, {pre, post} modify in the
......@@ -2564,13 +2562,43 @@ process_address (int nop, rtx *before, rtx *after)
}
else if (ad.index == NULL)
{
int regno;
enum reg_class cl;
rtx set, insns, last_insn;
/* base + disp => new base, cases (1) and (3) above. */
/* Another option would be to reload the displacement into an
index register. However, postreload has code to optimize
address reloads that have the same base and different
displacements, so reloading into an index register would
not necessarily be a win. */
start_sequence ();
new_reg = base_plus_disp_to_reg (&ad);
insns = get_insns ();
last_insn = get_last_insn ();
/* If we generated at least two insns, try last insn source as
an address. If we succeed, we generate one less insn. */
if (last_insn != insns && (set = single_set (last_insn)) != NULL_RTX
&& GET_CODE (SET_SRC (set)) == PLUS
&& REG_P (XEXP (SET_SRC (set), 0))
&& CONSTANT_P (XEXP (SET_SRC (set), 1)))
{
*ad.inner = SET_SRC (set);
if (valid_address_p (ad.mode, *ad.outer, ad.as))
{
*ad.base_term = XEXP (SET_SRC (set), 0);
*ad.disp_term = XEXP (SET_SRC (set), 1);
cl = base_reg_class (ad.mode, ad.as, ad.base_outer_code,
get_index_code (&ad));
regno = REGNO (*ad.base_term);
if (regno >= FIRST_PSEUDO_REGISTER
&& cl != lra_get_allocno_class (regno))
change_class (regno, cl, " Change", true);
new_reg = SET_SRC (set);
delete_insns_since (PREV_INSN (last_insn));
}
}
end_sequence ();
emit_insn (insns);
*ad.inner = new_reg;
}
else
......@@ -3560,7 +3588,7 @@ lra_constraints (bool first_p)
else if ((x = get_equiv_substitution (reg)) != reg)
{
bool pseudo_p = contains_reg_p (x, false, false);
rtx set, insn;
rtx set, insns;
/* After RTL transformation, we can not guarantee that
pseudo in the substitution was not reloaded which might
......@@ -3592,11 +3620,12 @@ lra_constraints (bool first_p)
removed the insn. When the equiv can be a
constant, the right hand side of the init insn can
be a pseudo. */
|| (! ((insn = ira_reg_equiv[i].init_insns) != NULL_RTX
&& INSN_P (insn)
&& (set = single_set (insn)) != NULL_RTX
&& REG_P (SET_DEST (set))
&& (int) REGNO (SET_DEST (set)) == i)
|| (! ((insns = ira_reg_equiv[i].init_insns) != NULL_RTX
&& INSN_P (XEXP (insns, 0))
&& XEXP (insns, 1) == NULL_RTX
&& (set = single_set (XEXP (insns, 0))) != NULL_RTX
&& REG_P (SET_SRC (set))
&& (int) REGNO (SET_SRC (set)) == i)
&& init_insn_rhs_dead_pseudo_p (i))
/* Prevent access beyond equivalent memory for
paradoxical subregs. */
......@@ -3669,6 +3698,18 @@ lra_constraints (bool first_p)
dest_reg = SUBREG_REG (dest_reg);
if ((REG_P (dest_reg)
&& (x = get_equiv_substitution (dest_reg)) != dest_reg
/* Check that this is actually an insn setting up
the equivalence. */
&& (in_list_p (curr_insn,
ira_reg_equiv
[REGNO (dest_reg)].init_insns)
/* Init insns may contain not all insns setting
up equivalence as we have live range
splitting. So here we use another condition
to check insn setting up the equivalence
which should be removed, e.g. in case when
the equivalence is a constant. */
|| ! MEM_P (x))
/* Remove insns which set up a pseudo whose value
can not be changed. Such insns might be not in
init_insns because we don't update equiv data
......
......@@ -1042,11 +1042,12 @@ spill_pseudos (HARD_REG_SET set)
registers. Spill pseudos assigned to registers which became
uneliminable, update LRA_NO_ALLOC_REGS and ELIMINABLE_REG_SET. Add
insns to INSNS_WITH_CHANGED_OFFSETS containing eliminable hard
registers whose offsets should be changed. */
static void
registers whose offsets should be changed. Return true if any
elimination offset changed. */
static bool
update_reg_eliminate (bitmap insns_with_changed_offsets)
{
bool prev;
bool prev, result;
struct elim_table *ep, *ep1;
HARD_REG_SET temp_hard_reg_set;
......@@ -1122,6 +1123,7 @@ update_reg_eliminate (bitmap insns_with_changed_offsets)
AND_COMPL_HARD_REG_SET (eliminable_regset, temp_hard_reg_set);
spill_pseudos (temp_hard_reg_set);
setup_elimination_map ();
result = false;
for (ep = reg_eliminate; ep < &reg_eliminate[NUM_ELIMINABLE_REGS]; ep++)
if (elimination_map[ep->from] == ep && ep->previous_offset != ep->offset)
{
......@@ -1132,7 +1134,9 @@ update_reg_eliminate (bitmap insns_with_changed_offsets)
changed. */
lra_update_reg_val_offset (lra_reg_info[ep->from].val,
ep->offset - ep->previous_offset);
result = true;
}
return result;
}
/* Initialize the table of hard registers to eliminate.
......@@ -1273,12 +1277,8 @@ lra_eliminate (bool final_p)
bitmap_ior_into (&insns_with_changed_offsets,
&lra_reg_info[ep->from].insn_bitmap);
}
else
{
update_reg_eliminate (&insns_with_changed_offsets);
if (bitmap_empty_p (&insns_with_changed_offsets))
else if (! update_reg_eliminate (&insns_with_changed_offsets))
goto lra_eliminate_done;
}
if (lra_dump_file != NULL)
{
fprintf (lra_dump_file, "New elimination table:\n");
......
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