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:
Richard Sandiford 2014-06-04 17:44:09 +00:00 committed by Richard Sandiford
parent 0c3317563e
commit a953491ef2
2 changed files with 125 additions and 58 deletions

View File

@ -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

View File

@ -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
} }