Andrew Stubbs <[email protected]> writes:
> [...]
> diff --git a/gcc/simplify-rtx.cc b/gcc/simplify-rtx.cc
> index 38c8abfe3e7..67f3307d2b0 100644
> --- a/gcc/simplify-rtx.cc
> +++ b/gcc/simplify-rtx.cc
> @@ -8777,9 +8777,43 @@ simplify_context::simplify_subreg (machine_mode
> outermode, rtx op,
> && (! MEM_VOLATILE_P (op)
> || ! have_insn_for (SET, innermode))
> && !(STRICT_ALIGNMENT && MEM_ALIGN (op) < GET_MODE_ALIGNMENT
> (outermode))
> - && known_le (outersize, innersize))
> + && known_le (outersize, innersize)
> + /* You can't get the Nth element of a vector of addresses (i.e.
> + gather/scatter) by adding an offset to the base. */
> + && !VECTOR_MODE_P (GET_MODE (XEXP (op, 0))))
> return adjust_address_nv (op, outermode, byte);
>
> + /* Simplify (subreg:<m> (mem:<vec_m> (reg:<vec_p> addr)) x)
> + to (mem:<m> (subreg:<p> (reg:<vec_p>)) y) */
> + if (MEM_P (op)
> + && VECTOR_MODE_P (innermode)
> + && VECTOR_MODE_P (GET_MODE (XEXP (op, 0)))
> + && GET_MODE_INNER (innermode) == outermode)
> + {
> + unsigned int index;
> + if (constant_multiple_p (byte, GET_MODE_SIZE (outermode), &index))
> + {
I think this should instead be:
poly_uint64 index;
if (multiple_p (byte, GET_MODE_SIZE (outermode), &index))
...
with:
> + rtx addr = XEXP (op, 0);
> + machine_mode addrmode = GET_MODE (addr);
> + machine_mode addr_elt_mode = GET_MODE_INNER (addrmode);
...this using "auto" or "scalar_mode" instead of "machine_mode". Then:
> + poly_uint64 addr_byte = index * GET_MODE_SIZE (addr_elt_mode);
...this will still be a poly_uint64, but with the non-constant portion
coming from the index rather than the mode.
LGTM with that change, thanks, and sorry for the slow review.
Richard
> +
> + rtx new_addr
> + = (REG_P (addr)
> + ? simplify_gen_subreg (addr_elt_mode, addr, addrmode,
> + addr_byte)
> + : simplify_subreg (addr_elt_mode, addr, addrmode, addr_byte));
> + if (new_addr)
> + {
> + rtx new_mem = gen_rtx_MEM (outermode, new_addr);
> + set_mem_addr_space (new_mem, MEM_ADDR_SPACE (op));
> + MEM_VOLATILE_P (new_mem) = MEM_VOLATILE_P (op);
> + MEM_NOTRAP_P (new_mem) = MEM_NOTRAP_P (op);
> + return new_mem;
> + }
> + }
> + }
> +
> /* Handle complex or vector values represented as CONCAT or VEC_CONCAT
> of two parts. */
> if (GET_CODE (op) == CONCAT
> diff --git a/gcc/target.def b/gcc/target.def
> index 11334f9d443..4c4f91827b2 100644
> --- a/gcc/target.def
> +++ b/gcc/target.def
> @@ -3451,7 +3451,10 @@ HOOK_VECTOR (TARGET_ADDR_SPACE_HOOKS, addr_space)
> DEFHOOK
> (pointer_mode,
> "Define this to return the machine mode to use for pointers to\n\
> -@var{address_space} if the target supports named address spaces.\n\
> +@var{address_space} if the target supports named address spaces.\n\n\
> +Targets that support vectors of pointers should return only the scalar
> base\n\
> +mode here, but permit the vector modes in\n\
> +@code{TARGET_ADDR_SPACE_VALID_POINTER_MODE}.\n\n\
> The default version of this hook returns @code{ptr_mode}.",
> scalar_int_mode, (addr_space_t address_space),
> default_addr_space_pointer_mode)
> @@ -3460,7 +3463,11 @@ The default version of this hook returns
> @code{ptr_mode}.",
> DEFHOOK
> (address_mode,
> "Define this to return the machine mode to use for addresses in\n\
> -@var{address_space} if the target supports named address spaces.\n\
> +@var{address_space} if the target supports named address spaces.\n\n\
> +Targets that support vectors of addresses should return only the scalar
> base\n\
> +mode here, but permit the vector modes in\n\
> +@code{TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P} and\n\
> +@code{TARGET_ADDR_SPACE_LEGITIMIZE_ADDRESS}.\n\n\
> The default version of this hook returns @code{Pmode}.",
> scalar_int_mode, (addr_space_t address_space),
> default_addr_space_address_mode)
> @@ -3470,13 +3477,16 @@ The default version of this hook returns
> @code{Pmode}.",
> DEFHOOK
> (valid_pointer_mode,
> "Define this to return nonzero if the port can handle pointers\n\
> -with machine mode @var{mode} to address space @var{as}. This target\n\
> -hook is the same as the @code{TARGET_VALID_POINTER_MODE} target hook,\n\
> -except that it includes explicit named address space support. The default\n\
> -version of this hook returns true for the modes returned by either the\n\
> -@code{TARGET_ADDR_SPACE_POINTER_MODE} or
> @code{TARGET_ADDR_SPACE_ADDRESS_MODE}\n\
> -target hooks for the given address space.",
> - bool, (scalar_int_mode mode, addr_space_t as),
> +with machine mode @var{mode} to address space @var{as}. This hook can\n\
> +also be used to allow pointers to use vector modes (e.g. to permit\n\
> +@samp{(mem:V4SI (reg:V4DI))}). This target hook is the same as the\n\
> +@code{TARGET_VALID_POINTER_MODE} target hook, except that it includes\n\
> +explicit named address space support, and does not mandate\n\
> +@code{scalar_int_mode}. The default version of this hook returns true for\n\
> +the modes returned by either the @code{TARGET_ADDR_SPACE_POINTER_MODE}\n\
> +or @code{TARGET_ADDR_SPACE_ADDRESS_MODE} target hooks for the given
> address\n\
> +space.",
> + bool, (machine_mode mode, addr_space_t as),
> default_addr_space_valid_pointer_mode)
>
> /* True if an address is a valid memory address to a given named address
> diff --git a/gcc/targhooks.cc b/gcc/targhooks.cc
> index 7123827cfd7..01defd7dbb3 100644
> --- a/gcc/targhooks.cc
> +++ b/gcc/targhooks.cc
> @@ -1728,10 +1728,13 @@ default_addr_space_address_mode (addr_space_t
> addrspace ATTRIBUTE_UNUSED)
> To match the above, the same modes apply to all address spaces. */
>
> bool
> -default_addr_space_valid_pointer_mode (scalar_int_mode mode,
> +default_addr_space_valid_pointer_mode (machine_mode mode,
> addr_space_t as ATTRIBUTE_UNUSED)
> {
> - return targetm.valid_pointer_mode (mode);
> + if (! SCALAR_INT_MODE_P (mode))
> + return false;
> +
> + return targetm.valid_pointer_mode (as_a <scalar_int_mode> (mode));
> }
>
> /* Some places still assume that all pointer or address modes are the
> diff --git a/gcc/targhooks.h b/gcc/targhooks.h
> index ffeaeb2a772..2a429e7f4a4 100644
> --- a/gcc/targhooks.h
> +++ b/gcc/targhooks.h
> @@ -206,8 +206,7 @@ extern bool default_valid_pointer_mode (scalar_int_mode);
> extern bool default_ref_may_alias_errno (class ao_ref *);
> extern scalar_int_mode default_addr_space_pointer_mode (addr_space_t);
> extern scalar_int_mode default_addr_space_address_mode (addr_space_t);
> -extern bool default_addr_space_valid_pointer_mode (scalar_int_mode,
> - addr_space_t);
> +extern bool default_addr_space_valid_pointer_mode (machine_mode,
> addr_space_t);
> extern bool default_addr_space_legitimate_address_p (machine_mode, rtx, bool,
> addr_space_t, code_helper);
> extern rtx default_addr_space_legitimize_address (rtx, rtx, machine_mode,