@@ -2369,6 +2369,14 @@ a unit of memory is accessed. @var{alias} specifies an alias set for the
reference. In general two items are in different alias sets if they cannot
reference the same memory address.
+The @var{addr} expression can represent either a scalar base address, or a
+vector of addresses (using an appropriate vector mode). In the vector case,
+the number of lanes in the address mode must match the number of lanes in the
+data mode @var{m}. Each vector lane can be viewed as an independent, parallel
+memory access of the corresponding scalar mode. If multiple lanes represent
+the same, or overlapping, memory location then the effect is undefined. All
+lanes are assumed to have the same attributes (address space, volatile, etc.).
+
The construct @code{(mem:BLK (scratch))} is considered to alias all
other memories. Thus it may be used as a memory barrier in epilogue
stack deallocation patterns.
@@ -11497,16 +11497,27 @@ c_register_addr_space ("__ea", ADDR_SPACE_EA);
@deftypefn {Target Hook} scalar_int_mode TARGET_ADDR_SPACE_POINTER_MODE (addr_space_t @var{address_space})
Define this to return the machine mode to use for pointers to
@var{address_space} if the target supports named address spaces.
+
+Targets that support vectors of pointers should return only the scalar base
+mode here, but permit the vector modes in
+@code{TARGET_ADDR_SPACE_VALID_POINTER_MODE}.
+
The default version of this hook returns @code{ptr_mode}.
@end deftypefn
@deftypefn {Target Hook} scalar_int_mode TARGET_ADDR_SPACE_ADDRESS_MODE (addr_space_t @var{address_space})
Define this to return the machine mode to use for addresses in
@var{address_space} if the target supports named address spaces.
+
+Targets that support vectors of addresses should return only the scalar base
+mode here, but permit the vector modes in
+@code{TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P} and
+@code{TARGET_ADDR_SPACE_LEGITIMIZE_ADDRESS}.
+
The default version of this hook returns @code{Pmode}.
@end deftypefn
-@deftypefn {Target Hook} bool TARGET_ADDR_SPACE_VALID_POINTER_MODE (scalar_int_mode @var{mode}, addr_space_t @var{as})
+@deftypefn {Target Hook} bool TARGET_ADDR_SPACE_VALID_POINTER_MODE (machine_mode @var{mode}, addr_space_t @var{as})
Define this to return nonzero if the port can handle pointers
with machine mode @var{mode} to address space @var{as}. This target
hook is the same as the @code{TARGET_VALID_POINTER_MODE} target hook,
@@ -540,14 +540,29 @@ gen_rtx_CONST_INT (machine_mode mode ATTRIBUTE_UNUSED, HOST_WIDE_INT arg)
return *slot;
}
+/* Return a CONST_INT, CONST_POLY_INT, or CONST_VECTOR containing the given
+ value. In the case of a vector, the value will be duplicated. */
+
rtx
gen_int_mode (poly_int64 c, machine_mode mode)
{
- c = trunc_int_for_mode (c, mode);
+ machine_mode s_mode = (VECTOR_MODE_P (mode) ? GET_MODE_INNER (mode) : mode);
+ rtx val;
+
+ c = trunc_int_for_mode (c, s_mode);
if (c.is_constant ())
- return GEN_INT (c.coeffs[0]);
- unsigned int prec = GET_MODE_PRECISION (as_a <scalar_mode> (mode));
- return immed_wide_int_const (poly_wide_int::from (c, prec, SIGNED), mode);
+ val = GEN_INT (c.coeffs[0]);
+ else
+ {
+ unsigned int prec = GET_MODE_PRECISION (as_a <scalar_mode> (s_mode));
+ val = immed_wide_int_const (poly_wide_int::from (c, prec, SIGNED),
+ s_mode);
+ }
+
+ if (VECTOR_MODE_P (mode))
+ val = gen_const_vec_duplicate (mode, val);
+
+ return val;
}
/* CONST_DOUBLEs might be created from pairs of integers, or from
@@ -2381,7 +2396,7 @@ adjust_address_1 (rtx memref, machine_mode mode, poly_int64 offset,
{
rtx addr = XEXP (memref, 0);
rtx new_rtx;
- scalar_int_mode address_mode;
+ machine_mode address_mode;
class mem_attrs attrs (*get_mem_attrs (memref)), *defattrs;
unsigned HOST_WIDE_INT max_align;
#ifdef POINTERS_EXTEND_UNSIGNED
@@ -2415,7 +2430,10 @@ adjust_address_1 (rtx memref, machine_mode mode, poly_int64 offset,
/* Convert a possibly large offset to a signed value within the
range of the target address space. */
address_mode = get_address_mode (memref);
- offset = trunc_int_for_mode (offset, address_mode);
+ if (!VECTOR_MODE_P (address_mode))
+ offset = trunc_int_for_mode (offset, address_mode);
+ else
+ offset = trunc_int_for_mode (offset, GET_MODE_INNER (address_mode));
if (adjust_address)
{
@@ -298,8 +298,13 @@ convert_memory_address_addr_space_1 (scalar_int_mode to_mode ATTRIBUTE_UNUSED,
bool in_const ATTRIBUTE_UNUSED,
bool no_emit ATTRIBUTE_UNUSED)
{
+ machine_mode xmode = GET_MODE (x);
+ bool vecaddr_p = VECTOR_MODE_P (GET_MODE (x));
+ if (vecaddr_p)
+ xmode = GET_MODE_INNER (xmode);
+
#ifndef POINTERS_EXTEND_UNSIGNED
- gcc_assert (GET_MODE (x) == to_mode || GET_MODE (x) == VOIDmode);
+ gcc_assert (xmode == to_mode || xmode == VOIDmode);
return x;
#else /* defined(POINTERS_EXTEND_UNSIGNED) */
scalar_int_mode pointer_mode, address_mode, from_mode;
@@ -307,9 +312,12 @@ convert_memory_address_addr_space_1 (scalar_int_mode to_mode ATTRIBUTE_UNUSED,
enum rtx_code code;
/* If X already has the right mode, just return it. */
- if (GET_MODE (x) == to_mode)
+ if (xmode == to_mode)
return x;
+ /* TODO: support vector conversions. */
+ gcc_assert (!vecaddr_p);
+
pointer_mode = targetm.addr_space.pointer_mode (as);
address_mode = targetm.addr_space.address_mode (as);
from_mode = to_mode == pointer_mode ? address_mode : pointer_mode;
@@ -1632,7 +1632,9 @@ address_operand (rtx op, machine_mode mode)
{
/* Wrong mode for an address expr. */
if (GET_MODE (op) != VOIDmode
- && ! SCALAR_INT_MODE_P (GET_MODE (op)))
+ && !(SCALAR_INT_MODE_P (GET_MODE (op))
+ || (VECTOR_MODE_P (GET_MODE (op))
+ && SCALAR_INT_MODE_P (GET_MODE_INNER (GET_MODE (op))))))
return false;
return memory_address_p (mode, op);
@@ -3691,7 +3691,7 @@ inline rtx single_set (const rtx_insn *insn)
return single_set_2 (insn, PATTERN (insn));
}
-extern scalar_int_mode get_address_mode (rtx mem);
+extern machine_mode get_address_mode (rtx mem);
extern bool rtx_addr_can_trap_p (const_rtx);
extern bool nonzero_address_p (const_rtx);
extern bool rtx_unstable_p (const_rtx);
@@ -6295,7 +6295,7 @@ low_bitmask_len (machine_mode mode, unsigned HOST_WIDE_INT m)
/* Return the mode of MEM's address. */
-scalar_int_mode
+machine_mode
get_address_mode (rtx mem)
{
machine_mode mode;
@@ -6303,7 +6303,7 @@ get_address_mode (rtx mem)
gcc_assert (MEM_P (mem));
mode = GET_MODE (XEXP (mem, 0));
if (mode != VOIDmode)
- return as_a <scalar_int_mode> (mode);
+ return mode;
return targetm.addr_space.address_mode (MEM_ADDR_SPACE (mem));
}
@@ -8679,7 +8679,10 @@ 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 by adding
+ offsets. */
+ && !VECTOR_MODE_P (GET_MODE (XEXP (op, 0))))
return adjust_address_nv (op, outermode, byte);
/* Handle complex or vector values represented as CONCAT or VEC_CONCAT
@@ -3448,7 +3448,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)
@@ -3457,7 +3460,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)
@@ -3473,7 +3480,7 @@ 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),
+ 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
@@ -1728,10 +1728,10 @@ 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);
+ return targetm.valid_pointer_mode (as_a <scalar_int_mode> (mode));
}
/* Some places still assume that all pointer or address modes are the
@@ -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,