This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

RFA: Make LRA temporarily eliminate addresses before testing constraints


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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]