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
This commit is contained in:
parent
3f5783ea1b
commit
5a107a0f0c
|
@ -1,3 +1,17 @@
|
|||
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.
|
||||
|
|
34
gcc/ira.c
34
gcc/ira.c
|
@ -2188,7 +2188,7 @@ ira_update_equiv_info_by_shuffle_insn (int to_regno, int from_regno, rtx insns)
|
|||
&& (! ira_reg_equiv[to_regno].defined_p
|
||||
|| ((x = ira_reg_equiv[to_regno].memory) != NULL_RTX
|
||||
&& ! MEM_READONLY_P (x))))
|
||||
return;
|
||||
return;
|
||||
insn = insns;
|
||||
if (NEXT_INSN (insn) != NULL_RTX)
|
||||
{
|
||||
|
@ -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);
|
||||
{
|
||||
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
|
||||
of range.
|
||||
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
|
||||
|
@ -2478,11 +2476,11 @@ process_address (int nop, rtx *before, rtx *after)
|
|||
/* There are three cases where the shape of *AD.INNER may now be invalid:
|
||||
|
||||
1) the original address was valid, but either elimination or
|
||||
equiv_address_substitution was applied and that made
|
||||
the address invalid.
|
||||
equiv_address_substitution was applied and that made
|
||||
the address invalid.
|
||||
|
||||
2) the address is an invalid symbolic address created by
|
||||
force_const_to_mem.
|
||||
force_const_to_mem.
|
||||
|
||||
3) the address is a frame address with an invalid offset.
|
||||
|
||||
|
@ -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,11 +3698,23 @@ 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
|
||||
during insn transformations.
|
||||
|
||||
|
||||
As an example, let suppose that a pseudo got
|
||||
hard register and on the 1st pass was not
|
||||
changed to equivalent constant. We generate an
|
||||
|
|
|
@ -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 < ®_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))
|
||||
goto lra_eliminate_done;
|
||||
}
|
||||
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");
|
||||
|
|
Loading…
Reference in New Issue