On Fri, Aug 8, 2014 at 8:51 PM, Andrew Pinski <apin...@cavium.com> wrote:
> This patch fixes the original problem that HJL was having with x32 in
> PR 47727, it is more constraint than HJL's patch only care about what
> is happening inside a CONST;  if we allow it for other cases,
> the RTL and generated code is incorrect as it does not have the needed
> zero extend.  This allows ILP32 to work correctlya and allows &a + 2 to
> be still generated correctly when doing a convert_memory_address_addr_space.
>
>
> OK?  Bootstrapped and tested on x86_64-linux-gnu (though not with x32 but
> visually looked at the failing testcase with a much older compiler).
> Also tested on aarch64-linux-gnu with no regressions and also fixing ld.so
> for ILP32.

Ping?

>
> Thanks,
> Andrew Pinski
>
> ChangeLog:
>         * explow.c (convert_memory_address_addr_space): Rename to ...
>         (convert_memory_address_addr_space_1): This.  Add in_const argument.
>         Inside a CONST RTL, permute the conversion and addition of constant
>         for zero and sign extended pointers.
>         (convert_memory_address_addr_space): New function.
>
>
> ---
>  gcc/explow.c |   40 ++++++++++++++++++++++++++++------------
>  1 files changed, 28 insertions(+), 12 deletions(-)
>
> diff --git a/gcc/explow.c b/gcc/explow.c
> index eb7dc85..64017a0 100644
> --- a/gcc/explow.c
> +++ b/gcc/explow.c
> @@ -310,11 +310,13 @@ break_out_memory_refs (rtx x)
>     an address in the address space's address mode, or vice versa (TO_MODE 
> says
>     which way).  We take advantage of the fact that pointers are not allowed 
> to
>     overflow by commuting arithmetic operations over conversions so that 
> address
> -   arithmetic insns can be used.  */
> +   arithmetic insns can be used. IN_CONST is true if this conversion is 
> inside
> +   a CONST.  */
>
> -rtx
> -convert_memory_address_addr_space (enum machine_mode to_mode 
> ATTRIBUTE_UNUSED,
> -                                  rtx x, addr_space_t as ATTRIBUTE_UNUSED)
> +static rtx
> +convert_memory_address_addr_space_1 (enum machine_mode to_mode 
> ATTRIBUTE_UNUSED,
> +                                    rtx x, addr_space_t as ATTRIBUTE_UNUSED,
> +                                    bool in_const)
>  {
>  #ifndef POINTERS_EXTEND_UNSIGNED
>    gcc_assert (GET_MODE (x) == to_mode || GET_MODE (x) == VOIDmode);
> @@ -370,8 +372,8 @@ convert_memory_address_addr_space (enum machine_mode 
> to_mode ATTRIBUTE_UNUSED,
>
>      case CONST:
>        return gen_rtx_CONST (to_mode,
> -                           convert_memory_address_addr_space
> -                             (to_mode, XEXP (x, 0), as));
> +                           convert_memory_address_addr_space_1
> +                             (to_mode, XEXP (x, 0), as, true));
>        break;
>
>      case PLUS:
> @@ -381,16 +383,18 @@ convert_memory_address_addr_space (enum machine_mode 
> to_mode ATTRIBUTE_UNUSED,
>          does not change it or if one operand is a constant and we are
>          using a ptr_extend instruction  (POINTERS_EXTEND_UNSIGNED < 0).
>          We can always safely permute them if we are making the address
> -        narrower.  */
> +        narrower. Inside a CONST RTL, this is safe for both pointers
> +        zero or sign extended as pointers cannot wrap. */
>        if (GET_MODE_SIZE (to_mode) < GET_MODE_SIZE (from_mode)
>           || (GET_CODE (x) == PLUS
>               && CONST_INT_P (XEXP (x, 1))
> -             && (XEXP (x, 1) == convert_memory_address_addr_space
> -                                  (to_mode, XEXP (x, 1), as)
> -                 || POINTERS_EXTEND_UNSIGNED < 0)))
> +             && ((in_const && POINTERS_EXTEND_UNSIGNED !=0)
> +                 || XEXP (x, 1) == convert_memory_address_addr_space_1
> +                                    (to_mode, XEXP (x, 1), as, in_const)
> +                  || POINTERS_EXTEND_UNSIGNED < 0)))
>         return gen_rtx_fmt_ee (GET_CODE (x), to_mode,
> -                              convert_memory_address_addr_space
> -                                (to_mode, XEXP (x, 0), as),
> +                              convert_memory_address_addr_space_1
> +                                (to_mode, XEXP (x, 0), as, in_const),
>                                XEXP (x, 1));
>        break;
>
> @@ -402,6 +406,18 @@ convert_memory_address_addr_space (enum machine_mode 
> to_mode ATTRIBUTE_UNUSED,
>                         x, POINTERS_EXTEND_UNSIGNED);
>  #endif /* defined(POINTERS_EXTEND_UNSIGNED) */
>  }
> +
> +/* Given X, a memory address in address space AS' pointer mode, convert it to
> +   an address in the address space's address mode, or vice versa (TO_MODE 
> says
> +   which way).  We take advantage of the fact that pointers are not allowed 
> to
> +   overflow by commuting arithmetic operations over conversions so that 
> address
> +   arithmetic insns can be used.  */
> +
> +rtx
> +convert_memory_address_addr_space (enum machine_mode to_mode, rtx x, 
> addr_space_t as)
> +{
> +  return convert_memory_address_addr_space_1 (to_mode, x, as, false);
> +}
>
>  /* Return something equivalent to X but valid as a memory address for 
> something
>     of mode MODE in the named address space AS.  When X is not itself valid,
> --
> 1.7.2.5
>

Reply via email to