On Fri, Aug 8, 2014 at 8:51 PM, Andrew Pinski <[email protected]> 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
>