[AArch64] Fix handling of npatterns>1 constants for partial SVE modes
authorRichard Sandiford <richard.sandiford@arm.com>
Thu, 19 Dec 2019 14:52:46 +0000 (14:52 +0000)
committerRichard Sandiford <rsandifo@gcc.gnu.org>
Thu, 19 Dec 2019 14:52:46 +0000 (14:52 +0000)
For partial SVE vectors of element X, we want to treat duplicates
of single X elements in the same way as for full vectors of X.
But if a constant instead contains a repeating pattern of X elements,
the transition from one value to the next must happen at container
boundaries rather than element boundaries.  E.g. a VNx4HI should
in that case contain the same number of constants as a VNx4SI.

Fixing this means that we need a reinterpret from the container-based
mode to the partial mode; e.g. in the above example we need a
reinterpret from VNx4SI to VNx4HI.  We can't use subregs for that
because they're forbidden by aarch64_can_change_class_mode; we should
handle them in the same way as for big-endian instead.

2019-12-19  Richard Sandiford  <richard.sandiford@arm.com>

gcc/
* config/aarch64/aarch64.c (aarch64_simd_valid_immediate): When
handling partial SVE vectors, use the container mode rather than
the element mode if the constant isn't a single-element duplicate.
* config/aarch64/aarch64-sve.md (@aarch64_sve_reinterpret<mode>):
Check targetm.can_change_mode_class instead of BYTES_BIG_ENDIAN.

gcc/testsuite/
* gcc.target/aarch64/sve/mixed_size_9.c: New test.

From-SVN: r279580

gcc/ChangeLog
gcc/config/aarch64/aarch64-sve.md
gcc/config/aarch64/aarch64.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/aarch64/sve/mixed_size_9.c [new file with mode: 0644]

index 9126ec1a19bf98cc5d365b1f2bf9392a44fa6913..308774df148082ff3f287942ceb11952a894ea15 100644 (file)
@@ -1,3 +1,11 @@
+2019-12-19  Richard Sandiford  <richard.sandiford@arm.com>
+
+       * config/aarch64/aarch64.c (aarch64_simd_valid_immediate): When
+       handling partial SVE vectors, use the container mode rather than
+       the element mode if the constant isn't a single-element duplicate.
+       * config/aarch64/aarch64-sve.md (@aarch64_sve_reinterpret<mode>):
+       Check targetm.can_change_mode_class instead of BYTES_BIG_ENDIAN.
+
 2019-12-19  Andrew Stubbs  <ams@codesourcery.com>
 
        * config/gcn/gcn-valu.md (addv64si3<exec_clobber>): Rename to ...
index 1d9cdad23bdc3f73c2a6e01baa7376c73022886b..feb7559641469cb6f86b6f28b2bf7021be41cbfd 100644 (file)
          UNSPEC_REINTERPRET))]
   "TARGET_SVE"
   {
-    if (!BYTES_BIG_ENDIAN)
+    machine_mode src_mode = GET_MODE (operands[1]);
+    if (targetm.can_change_mode_class (<MODE>mode, src_mode, FP_REGS))
       {
        emit_move_insn (operands[0], gen_lowpart (<MODE>mode, operands[1]));
        DONE;
index 88baf96efc2d60d7dc4ea6e57900e51821902e6f..a85f8b04c202bd34909dea7035b044726fe853be 100644 (file)
@@ -16826,12 +16826,28 @@ aarch64_simd_valid_immediate (rtx op, simd_immediate_info *info,
        }
     }
 
-  unsigned int elt_size = GET_MODE_SIZE (elt_mode);
+  /* If all elements in an SVE vector have the same value, we have a free
+     choice between using the element mode and using the container mode.
+     Using the element mode means that unused parts of the vector are
+     duplicates of the used elements, while using the container mode means
+     that the unused parts are an extension of the used elements.  Using the
+     element mode is better for (say) VNx4HI 0x101, since 0x01010101 is valid
+     for its container mode VNx4SI while 0x00000101 isn't.
+
+     If not all elements in an SVE vector have the same value, we need the
+     transition from one element to the next to occur at container boundaries.
+     E.g. a fixed-length VNx4HI containing { 1, 2, 3, 4 } should be treated
+     in the same way as a VNx4SI containing { 1, 2, 3, 4 }.  */
+  scalar_int_mode elt_int_mode;
+  if ((vec_flags & VEC_SVE_DATA) && n_elts > 1)
+    elt_int_mode = aarch64_sve_container_int_mode (mode);
+  else
+    elt_int_mode = int_mode_for_mode (elt_mode).require ();
+
+  unsigned int elt_size = GET_MODE_SIZE (elt_int_mode);
   if (elt_size > 8)
     return false;
 
-  scalar_int_mode elt_int_mode = int_mode_for_mode (elt_mode).require ();
-
   /* Expand the vector constant out into a byte vector, with the least
      significant byte of the register first.  */
   auto_vec<unsigned char, 16> bytes;
index 7d474882c634382c0ebf4456223269927fb117da..bbca1aa5b1684b8ba5e8d47a07488171e1b6d84c 100644 (file)
@@ -1,3 +1,7 @@
+2019-12-19  Richard Sandiford  <richard.sandiford@arm.com>
+
+       * gcc.target/aarch64/sve/mixed_size_9.c: New test.
+
 2019-12-19  Richard Sandiford  <richard.sandiford@arm.com>
 
        * gcc.target/aarch64/sve/mixed_size_8.c: New test.
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/mixed_size_9.c b/gcc/testsuite/gcc.target/aarch64/sve/mixed_size_9.c
new file mode 100644 (file)
index 0000000..5f78150
--- /dev/null
@@ -0,0 +1,18 @@
+/* { dg-options "-O2 -ftree-vectorize -fno-vect-cost-model -msve-vector-bits=256" } */
+/* Originally from gcc.dg/vect/pr88598-4.c.  */
+
+#define N 4
+
+int a[N];
+
+int __attribute__ ((noipa))
+f2 (void)
+{
+  int b[N] = { 0, 31, 0, 31 }, res = 0;
+  for (int i = 0; i < N; ++i)
+    res += a[i] & b[i];
+  return res;
+}
+
+/* { dg-final { scan-assembler-not {\tmov\tz[0-9]\.d, #} } } */
+/* { dg-final { scan-assembler-not {\tstr\tz[0-9],} } } */