Richard Sandiford <[email protected]> writes:
> 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.
Sorry, a couple of other things:
>> +
>> + 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));
I think we should use simplify_gen_subreg unconditionally unless there's
a specific reason not to. This is a simplification regardless of what
the address is.
>> + 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;
I think this should use change_address instead. AIUI, that is suitable
for any change that preserves the alias set.
Still LGTM with those changes.
Thanks,
Richard
>> + }
>> + }
>> + }
>> +
>> /* 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,