summaryrefslogtreecommitdiff
path: root/gcc/config/aarch64/aarch64.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/config/aarch64/aarch64.c')
-rw-r--r--gcc/config/aarch64/aarch64.c33
1 files changed, 32 insertions, 1 deletions
diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
index 1d48108516d..d3d7d1e60d6 100644
--- a/gcc/config/aarch64/aarch64.c
+++ b/gcc/config/aarch64/aarch64.c
@@ -8316,7 +8316,8 @@ aarch64_cannot_change_mode_class (enum machine_mode from,
/* Limited combinations of subregs are safe on FPREGs. Particularly,
1. Vector Mode to Scalar mode where 1 unit of the vector is accessed.
2. Scalar to Scalar for integer modes or same size float modes.
- 3. Vector to Vector modes. */
+ 3. Vector to Vector modes.
+ 4. On little-endian only, Vector-Structure to Vector modes. */
if (GET_MODE_SIZE (from) > GET_MODE_SIZE (to))
{
if (aarch64_vector_mode_supported_p (from)
@@ -8332,11 +8333,41 @@ aarch64_cannot_change_mode_class (enum machine_mode from,
if (aarch64_vector_mode_supported_p (from)
&& aarch64_vector_mode_supported_p (to))
return false;
+
+ /* Within an vector structure straddling multiple vector registers
+ we are in a mixed-endian representation. As such, we can't
+ easily change modes for BYTES_BIG_ENDIAN. Otherwise, we can
+ switch between vectors and vector structures cheaply. */
+ if (!BYTES_BIG_ENDIAN)
+ if ((aarch64_vector_mode_supported_p (from)
+ && aarch64_vect_struct_mode_p (to))
+ || (aarch64_vector_mode_supported_p (to)
+ && aarch64_vect_struct_mode_p (from)))
+ return false;
}
return true;
}
+/* Implement MODES_TIEABLE_P. */
+
+bool
+aarch64_modes_tieable_p (enum machine_mode mode1, enum machine_mode mode2)
+{
+ if (GET_MODE_CLASS (mode1) == GET_MODE_CLASS (mode2))
+ return true;
+
+ /* We specifically want to allow elements of "structure" modes to
+ be tieable to the structure. This more general condition allows
+ other rarer situations too. */
+ if (TARGET_SIMD
+ && aarch64_vector_mode_p (mode1)
+ && aarch64_vector_mode_p (mode2))
+ return true;
+
+ return false;
+}
+
#undef TARGET_ADDRESS_COST
#define TARGET_ADDRESS_COST aarch64_address_cost