This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
RFA: Make LRA temporarily eliminate addresses before testing constraints
- From: Richard Sandiford <rdsandiford at googlemail dot com>
- To: Matthew Fortune <Matthew dot Fortune at imgtec dot com>
- Cc: Vladimir Makarov <vmakarov at redhat dot com>, Robert Suchanek <Robert dot Suchanek at imgtec dot com>, "gcc-patches\ at gcc dot gnu dot org" <gcc-patches at gcc dot gnu dot org>, Kyrill Tkachov <kyrylo dot tkachov at arm dot com>
- Date: Mon, 02 Jun 2014 20:36:57 +0100
- Subject: RFA: Make LRA temporarily eliminate addresses before testing constraints
- Authentication-results: sourceware.org; auth=none
- References: <B5E67142681B53468FAF6B7C313565623D3DD70C at KLMAIL01 dot kl dot imgtec dot org> <87d2h51dm6 dot fsf at talisman dot default> <B5E67142681B53468FAF6B7C313565623D3E3FED at KLMAIL01 dot kl dot imgtec dot org> <87d2gqfb7t dot fsf at talisman dot default> <B5E67142681B53468FAF6B7C313565623D3E4420 at KLMAIL01 dot kl dot imgtec dot org> <87ob02jodp dot fsf at talisman dot default> <B5E67142681B53468FAF6B7C313565623D3E460A at KLMAIL01 dot kl dot imgtec dot org> <87fvl6hnw2 dot fsf at talisman dot default> <5357D588 dot 6000202 at redhat dot com> <87tx967jnq dot fsf at talisman dot default> <5368EC5F dot 3010006 at arm dot com> <87mweuww37 dot fsf at talisman dot default> <6D39441BF12EF246A7ABCE6654B0235352881A at LEMAIL01 dot le dot imgtec dot org> <87vbtd1njm dot fsf at talisman dot default> <871tvqnai3 dot fsf at talisman dot default>
Ping. Imagination's copyright assignment has now gone through and so
in principle we're ready for the MIPS LRA switch to go in. We need
this LRA patch as a prequisite though.
Robert: you also had an LRA change, but is it still needed after this one?
If so, could you repost it and explain the case it handles?
Thanks,
Richard
Richard Sandiford <rdsandiford@googlemail.com> writes:
> Richard Sandiford <rdsandiford@googlemail.com> writes:
>> I think a cleaner way of doing it would be to have helper functions
>> that switch in and out of the eliminated form, storing the old form
>> in fields of a new structure (either separate from address_info,
>> or a local inheritance of it). We probably also want to have arrays
>> of address_infos, one for each operand, so that we don't analyse the
>> same address too many times during the same insn.
>
> In the end maintaining the array of address_infos seemed like too much
> work. It was hard to keep it up-to-date with various other changes
> that can be made, including swapping commutative operands, to the point
> where it wasn't obvious whether it was really an optimisation or not.
>
> Here's a patch that does the first. Tested on x86_64-linux-gnu.
> This time I also compared the assembly output for gcc.dg, g++.dg
> and gcc.c-torture at -O2 on:
>
> arch64-linux-gnu arm-eabi mipsisa64-sde-elf s390x-linux-gnu
> powerpc64-linux-gnu x86_64-linux-gnu
>
> s390x in particular is very good at exposing problems with this code.
> (It caught bugs in the aborted attempt to keep an array of address_infos.)
>
> OK to install?
>
> Thanks,
> Richard
>
>
> 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.
>
> Index: gcc/lra-constraints.c
> ===================================================================
> --- gcc/lra-constraints.c 2014-05-17 17:49:19.071639652 +0100
> +++ gcc/lra-constraints.c 2014-05-18 20:36:17.499181467 +0100
> @@ -317,6 +317,118 @@ in_mem_p (int regno)
> 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 address 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
> before any elimination, we need to make copies otherwise any change
> in insns might change the equivalences. */
> @@ -1941,7 +2053,8 @@ process_alt_operands (int only_alternati
> #ifdef EXTRA_CONSTRAINT_STR
> 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;
> else if (spilled_pseudo_p (op))
> win = true;
> @@ -1960,7 +2073,7 @@ process_alt_operands (int only_alternati
> }
> if (EXTRA_ADDRESS_CONSTRAINT (c, p))
> {
> - if (EXTRA_CONSTRAINT_STR (op, c, p))
> + if (satisfies_address_constraint_p (op, p))
> win = true;
>
> /* If we didn't already win, we can reload
> @@ -2576,60 +2689,6 @@ process_alt_operands (int only_alternati
> 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. */
> static rtx
> base_plus_disp_to_reg (struct address_info *ad)
> @@ -2832,7 +2891,7 @@ process_address (int nop, rtx *before, r
> EXTRA_CONSTRAINT_STR for the validation. */
> if (constraint[0] != 'p'
> && EXTRA_ADDRESS_CONSTRAINT (constraint[0], constraint)
> - && EXTRA_CONSTRAINT_STR (op, constraint[0], constraint))
> + && satisfies_address_constraint_p (&ad, constraint))
> return change_p;
> #endif
>
> @@ -3539,7 +3598,7 @@ curr_insn_transform (void)
> break;
> #ifdef EXTRA_CONSTRAINT_STR
> if (EXTRA_MEMORY_CONSTRAINT (c, constraint)
> - && EXTRA_CONSTRAINT_STR (tem, c, constraint))
> + && satisfies_memory_constraint_p (tem, constraint))
> break;
> #endif
> }