lra-constraints.c (valid_address_p): Move earlier in file.
gcc/ * lra-constraints.c (valid_address_p): Move earlier in file. (address_eliminator): New structure. (satisfies_memory_constraint_p): New function. (satisfies_address_constraint_p): Likewise. (process_alt_operands, process_address, curr_insn_transform): Use them. From-SVN: r211242
This commit is contained in:
parent
0c3317563e
commit
a953491ef2
|
@ -1,3 +1,11 @@
|
||||||
|
2014-06-04 Richard Sandiford <rdsandiford@googlemail.com>
|
||||||
|
|
||||||
|
* lra-constraints.c (valid_address_p): Move earlier in file.
|
||||||
|
(address_eliminator): New structure.
|
||||||
|
(satisfies_memory_constraint_p): New function.
|
||||||
|
(satisfies_address_constraint_p): Likewise.
|
||||||
|
(process_alt_operands, process_address, curr_insn_transform): Use them.
|
||||||
|
|
||||||
2014-06-04 Richard Sandiford <rdsandiford@googlemail.com>
|
2014-06-04 Richard Sandiford <rdsandiford@googlemail.com>
|
||||||
|
|
||||||
* lra-int.h (lra_static_insn_data): Make operand_alternative a
|
* lra-int.h (lra_static_insn_data): Make operand_alternative a
|
||||||
|
|
|
@ -317,6 +317,118 @@ in_mem_p (int regno)
|
||||||
return get_reg_class (regno) == NO_REGS;
|
return get_reg_class (regno) == NO_REGS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Return 1 if ADDR is a valid memory address for mode MODE in address
|
||||||
|
space AS, and check that each pseudo has the proper kind of hard
|
||||||
|
reg. */
|
||||||
|
static int
|
||||||
|
valid_address_p (enum machine_mode mode ATTRIBUTE_UNUSED,
|
||||||
|
rtx addr, addr_space_t as)
|
||||||
|
{
|
||||||
|
#ifdef GO_IF_LEGITIMATE_ADDRESS
|
||||||
|
lra_assert (ADDR_SPACE_GENERIC_P (as));
|
||||||
|
GO_IF_LEGITIMATE_ADDRESS (mode, addr, win);
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
win:
|
||||||
|
return 1;
|
||||||
|
#else
|
||||||
|
return targetm.addr_space.legitimate_address_p (mode, addr, 0, as);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
/* Temporarily eliminates registers in an address (for the lifetime of
|
||||||
|
the object). */
|
||||||
|
class address_eliminator {
|
||||||
|
public:
|
||||||
|
address_eliminator (struct address_info *ad);
|
||||||
|
~address_eliminator ();
|
||||||
|
|
||||||
|
private:
|
||||||
|
struct address_info *m_ad;
|
||||||
|
rtx *m_base_loc;
|
||||||
|
rtx m_base_reg;
|
||||||
|
rtx *m_index_loc;
|
||||||
|
rtx m_index_reg;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
address_eliminator::address_eliminator (struct address_info *ad)
|
||||||
|
: m_ad (ad),
|
||||||
|
m_base_loc (strip_subreg (ad->base_term)),
|
||||||
|
m_base_reg (NULL_RTX),
|
||||||
|
m_index_loc (strip_subreg (ad->index_term)),
|
||||||
|
m_index_reg (NULL_RTX)
|
||||||
|
{
|
||||||
|
if (m_base_loc != NULL)
|
||||||
|
{
|
||||||
|
m_base_reg = *m_base_loc;
|
||||||
|
lra_eliminate_reg_if_possible (m_base_loc);
|
||||||
|
if (m_ad->base_term2 != NULL)
|
||||||
|
*m_ad->base_term2 = *m_ad->base_term;
|
||||||
|
}
|
||||||
|
if (m_index_loc != NULL)
|
||||||
|
{
|
||||||
|
m_index_reg = *m_index_loc;
|
||||||
|
lra_eliminate_reg_if_possible (m_index_loc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
address_eliminator::~address_eliminator ()
|
||||||
|
{
|
||||||
|
if (m_base_loc && *m_base_loc != m_base_reg)
|
||||||
|
{
|
||||||
|
*m_base_loc = m_base_reg;
|
||||||
|
if (m_ad->base_term2 != NULL)
|
||||||
|
*m_ad->base_term2 = *m_ad->base_term;
|
||||||
|
}
|
||||||
|
if (m_index_loc && *m_index_loc != m_index_reg)
|
||||||
|
*m_index_loc = m_index_reg;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return true if the eliminated form of AD is a legitimate target address. */
|
||||||
|
static bool
|
||||||
|
valid_address_p (struct address_info *ad)
|
||||||
|
{
|
||||||
|
address_eliminator eliminator (ad);
|
||||||
|
return valid_address_p (ad->mode, *ad->outer, ad->as);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef EXTRA_CONSTRAINT_STR
|
||||||
|
/* Return true if the eliminated form of memory reference OP satisfies
|
||||||
|
extra memory constraint CONSTRAINT. */
|
||||||
|
static bool
|
||||||
|
satisfies_memory_constraint_p (rtx op, const char *constraint)
|
||||||
|
{
|
||||||
|
struct address_info ad;
|
||||||
|
|
||||||
|
decompose_mem_address (&ad, op);
|
||||||
|
address_eliminator eliminator (&ad);
|
||||||
|
return EXTRA_CONSTRAINT_STR (op, *constraint, constraint);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return true if the eliminated form of address AD satisfies extra
|
||||||
|
address constraint CONSTRAINT. */
|
||||||
|
static bool
|
||||||
|
satisfies_address_constraint_p (struct address_info *ad,
|
||||||
|
const char *constraint)
|
||||||
|
{
|
||||||
|
address_eliminator eliminator (ad);
|
||||||
|
return EXTRA_CONSTRAINT_STR (*ad->outer, *constraint, constraint);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return true if the eliminated form of address OP satisfies extra
|
||||||
|
address constraint CONSTRAINT. */
|
||||||
|
static bool
|
||||||
|
satisfies_address_constraint_p (rtx op, const char *constraint)
|
||||||
|
{
|
||||||
|
struct address_info ad;
|
||||||
|
|
||||||
|
decompose_lea_address (&ad, &op);
|
||||||
|
return satisfies_address_constraint_p (&ad, constraint);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Initiate equivalences for LRA. As we keep original equivalences
|
/* Initiate equivalences for LRA. As we keep original equivalences
|
||||||
before any elimination, we need to make copies otherwise any change
|
before any elimination, we need to make copies otherwise any change
|
||||||
in insns might change the equivalences. */
|
in insns might change the equivalences. */
|
||||||
|
@ -1938,7 +2050,8 @@ process_alt_operands (int only_alternative)
|
||||||
#ifdef EXTRA_CONSTRAINT_STR
|
#ifdef EXTRA_CONSTRAINT_STR
|
||||||
if (EXTRA_MEMORY_CONSTRAINT (c, p))
|
if (EXTRA_MEMORY_CONSTRAINT (c, p))
|
||||||
{
|
{
|
||||||
if (EXTRA_CONSTRAINT_STR (op, c, p))
|
if (MEM_P (op)
|
||||||
|
&& satisfies_memory_constraint_p (op, p))
|
||||||
win = true;
|
win = true;
|
||||||
else if (spilled_pseudo_p (op))
|
else if (spilled_pseudo_p (op))
|
||||||
win = true;
|
win = true;
|
||||||
|
@ -1957,7 +2070,7 @@ process_alt_operands (int only_alternative)
|
||||||
}
|
}
|
||||||
if (EXTRA_ADDRESS_CONSTRAINT (c, p))
|
if (EXTRA_ADDRESS_CONSTRAINT (c, p))
|
||||||
{
|
{
|
||||||
if (EXTRA_CONSTRAINT_STR (op, c, p))
|
if (satisfies_address_constraint_p (op, p))
|
||||||
win = true;
|
win = true;
|
||||||
|
|
||||||
/* If we didn't already win, we can reload
|
/* If we didn't already win, we can reload
|
||||||
|
@ -2573,60 +2686,6 @@ process_alt_operands (int only_alternative)
|
||||||
return ok_p;
|
return ok_p;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return 1 if ADDR is a valid memory address for mode MODE in address
|
|
||||||
space AS, and check that each pseudo has the proper kind of hard
|
|
||||||
reg. */
|
|
||||||
static int
|
|
||||||
valid_address_p (enum machine_mode mode ATTRIBUTE_UNUSED,
|
|
||||||
rtx addr, addr_space_t as)
|
|
||||||
{
|
|
||||||
#ifdef GO_IF_LEGITIMATE_ADDRESS
|
|
||||||
lra_assert (ADDR_SPACE_GENERIC_P (as));
|
|
||||||
GO_IF_LEGITIMATE_ADDRESS (mode, addr, win);
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
win:
|
|
||||||
return 1;
|
|
||||||
#else
|
|
||||||
return targetm.addr_space.legitimate_address_p (mode, addr, 0, as);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Return whether address AD is valid. */
|
|
||||||
|
|
||||||
static bool
|
|
||||||
valid_address_p (struct address_info *ad)
|
|
||||||
{
|
|
||||||
/* Some ports do not check displacements for eliminable registers,
|
|
||||||
so we replace them temporarily with the elimination target. */
|
|
||||||
rtx saved_base_reg = NULL_RTX;
|
|
||||||
rtx saved_index_reg = NULL_RTX;
|
|
||||||
rtx *base_term = strip_subreg (ad->base_term);
|
|
||||||
rtx *index_term = strip_subreg (ad->index_term);
|
|
||||||
if (base_term != NULL)
|
|
||||||
{
|
|
||||||
saved_base_reg = *base_term;
|
|
||||||
lra_eliminate_reg_if_possible (base_term);
|
|
||||||
if (ad->base_term2 != NULL)
|
|
||||||
*ad->base_term2 = *ad->base_term;
|
|
||||||
}
|
|
||||||
if (index_term != NULL)
|
|
||||||
{
|
|
||||||
saved_index_reg = *index_term;
|
|
||||||
lra_eliminate_reg_if_possible (index_term);
|
|
||||||
}
|
|
||||||
bool ok_p = valid_address_p (ad->mode, *ad->outer, ad->as);
|
|
||||||
if (saved_base_reg != NULL_RTX)
|
|
||||||
{
|
|
||||||
*base_term = saved_base_reg;
|
|
||||||
if (ad->base_term2 != NULL)
|
|
||||||
*ad->base_term2 = *ad->base_term;
|
|
||||||
}
|
|
||||||
if (saved_index_reg != NULL_RTX)
|
|
||||||
*index_term = saved_index_reg;
|
|
||||||
return ok_p;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Make reload base reg + disp from address AD. Return the new pseudo. */
|
/* Make reload base reg + disp from address AD. Return the new pseudo. */
|
||||||
static rtx
|
static rtx
|
||||||
base_plus_disp_to_reg (struct address_info *ad)
|
base_plus_disp_to_reg (struct address_info *ad)
|
||||||
|
@ -2834,7 +2893,7 @@ process_address_1 (int nop, rtx *before, rtx *after)
|
||||||
EXTRA_CONSTRAINT_STR for the validation. */
|
EXTRA_CONSTRAINT_STR for the validation. */
|
||||||
if (constraint[0] != 'p'
|
if (constraint[0] != 'p'
|
||||||
&& EXTRA_ADDRESS_CONSTRAINT (constraint[0], constraint)
|
&& EXTRA_ADDRESS_CONSTRAINT (constraint[0], constraint)
|
||||||
&& EXTRA_CONSTRAINT_STR (op, constraint[0], constraint))
|
&& satisfies_address_constraint_p (&ad, constraint))
|
||||||
return change_p;
|
return change_p;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -3553,7 +3612,7 @@ curr_insn_transform (void)
|
||||||
break;
|
break;
|
||||||
#ifdef EXTRA_CONSTRAINT_STR
|
#ifdef EXTRA_CONSTRAINT_STR
|
||||||
if (EXTRA_MEMORY_CONSTRAINT (c, constraint)
|
if (EXTRA_MEMORY_CONSTRAINT (c, constraint)
|
||||||
&& EXTRA_CONSTRAINT_STR (tem, c, constraint))
|
&& satisfies_memory_constraint_p (tem, constraint))
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue