diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 34fbb355818..6edd51af290 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,11 @@ +2014-10-14 Andrew Pinski + + * 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. + 2014-10-14 Andrew Pinski Revert: diff --git a/gcc/explow.c b/gcc/explow.c index 3ba766d2f1c..4f6465bef7a 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,