]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
aarch64: Fix PR99437 - tighten shift predicates for narrowing shift patterns
authorKyrylo Tkachov <kyrylo.tkachov@arm.com>
Mon, 8 Mar 2021 15:05:21 +0000 (15:05 +0000)
committerKyrylo Tkachov <kyrylo.tkachov@arm.com>
Mon, 8 Mar 2021 15:05:21 +0000 (15:05 +0000)
In this bug combine forms the (R)SHRN(2) instructions with an invalid shift amount.
The intrinsic expanders for these patterns validate the right shift amount but if the
final patterns end up being matched by combine (or other RTL passes I suppose) they
still let the wrong const_vector through.

This patch tightens up the predicates for the instructions involved by using predicates
for the right shift amount const_vectors.

gcc/ChangeLog:

PR target/99437
* config/aarch64/predicates.md (aarch64_simd_shift_imm_vec_qi): Define.
(aarch64_simd_shift_imm_vec_hi): Likewise.
(aarch64_simd_shift_imm_vec_si): Likewise.
(aarch64_simd_shift_imm_vec_di): Likewise.
* config/aarch64/aarch64-simd.md (aarch64_shrn<mode>_insn_le): Use
predicate from above.
(aarch64_shrn<mode>_insn_be): Likewise.
(aarch64_rshrn<mode>_insn_le): Likewise.
(aarch64_rshrn<mode>_insn_be): Likewise.
(aarch64_shrn2<mode>_insn_le): Likewise.
(aarch64_shrn2<mode>_insn_be): Likewise.
(aarch64_rshrn2<mode>_insn_le): Likewise.
(aarch64_rshrn2<mode>_insn_be): Likewise.

gcc/testsuite/ChangeLog:

PR target/99437
* gcc.target/aarch64/simd/pr99437.c: New test.

gcc/config/aarch64/aarch64-simd.md
gcc/config/aarch64/predicates.md
gcc/testsuite/gcc.target/aarch64/simd/pr99437.c [new file with mode: 0644]

index 71aa77dd0102579139191b79476c7269cd8e28b3..348a43d835d4e8d7b49fbf166bb584e868e4a8b7 100644 (file)
        (vec_concat:<VNARROWQ2>
          (truncate:<VNARROWQ>
            (lshiftrt:VQN (match_operand:VQN 1 "register_operand" "w")
-                 (match_operand:VQN 2 "aarch64_simd_rshift_imm")))
+             (match_operand:VQN 2 "aarch64_simd_shift_imm_vec_<vn_mode>")))
          (match_operand:<VNARROWQ> 3 "aarch64_simd_or_scalar_imm_zero")))]
   "TARGET_SIMD && !BYTES_BIG_ENDIAN"
   "shrn\\t%0.<Vntype>, %1.<Vtype>, %2"
          (match_operand:<VNARROWQ> 3 "aarch64_simd_or_scalar_imm_zero")
          (truncate:<VNARROWQ>
            (lshiftrt:VQN (match_operand:VQN 1 "register_operand" "w")
-                 (match_operand:VQN 2 "aarch64_simd_rshift_imm")))))]
+             (match_operand:VQN 2 "aarch64_simd_shift_imm_vec_<vn_mode>")))))]
   "TARGET_SIMD && BYTES_BIG_ENDIAN"
   "shrn\\t%0.<Vntype>, %1.<Vtype>, %2"
   [(set_attr "type" "neon_shift_imm_narrow_q")]
   [(set (match_operand:<VNARROWQ2> 0 "register_operand" "=w")
        (vec_concat:<VNARROWQ2>
          (unspec:<VNARROWQ> [(match_operand:VQN 1 "register_operand" "w")
-                              (match_operand:VQN 2 "aarch64_simd_rshift_imm")
-                             ] UNSPEC_RSHRN)
+               (match_operand:VQN 2
+                 "aarch64_simd_shift_imm_vec_<vn_mode>")] UNSPEC_RSHRN)
          (match_operand:<VNARROWQ> 3 "aarch64_simd_or_scalar_imm_zero")))]
   "TARGET_SIMD && !BYTES_BIG_ENDIAN"
   "rshrn\\t%0.<Vntype>, %1.<Vtype>, %2"
        (vec_concat:<VNARROWQ2>
          (match_operand:<VNARROWQ> 3 "aarch64_simd_or_scalar_imm_zero")
          (unspec:<VNARROWQ> [(match_operand:VQN 1 "register_operand" "w")
-                              (match_operand:VQN 2 "aarch64_simd_rshift_imm")
-                             ] UNSPEC_RSHRN)))]
+               (match_operand:VQN 2 "aarch64_simd_shift_imm_vec_<vn_mode>")]
+                 UNSPEC_RSHRN)))]
   "TARGET_SIMD && BYTES_BIG_ENDIAN"
   "rshrn\\t%0.<Vntype>, %1.<Vtype>, %2"
   [(set_attr "type" "neon_shift_imm_narrow_q")]
          (match_operand:<VNARROWQ> 1 "register_operand" "0")
          (truncate:<VNARROWQ>
            (lshiftrt:VQN (match_operand:VQN 2 "register_operand" "w")
-               (match_operand:VQN 3 "aarch64_simd_rshift_imm")))))]
+             (match_operand:VQN 3 "aarch64_simd_shift_imm_vec_<vn_mode>")))))]
   "TARGET_SIMD && !BYTES_BIG_ENDIAN"
   "shrn2\\t%0.<V2ntype>, %2.<Vtype>, %3"
   [(set_attr "type" "neon_shift_imm_narrow_q")]
        (vec_concat:<VNARROWQ2>
          (truncate:<VNARROWQ>
            (lshiftrt:VQN (match_operand:VQN 2 "register_operand" "w")
-               (match_operand:VQN 3 "aarch64_simd_rshift_imm")))
+             (match_operand:VQN 3
+               "aarch64_simd_shift_imm_vec_<vn_mode>")))
          (match_operand:<VNARROWQ> 1 "register_operand" "0")))]
   "TARGET_SIMD && BYTES_BIG_ENDIAN"
   "shrn2\\t%0.<V2ntype>, %2.<Vtype>, %3"
        (vec_concat:<VNARROWQ2>
          (match_operand:<VNARROWQ> 1 "register_operand" "0")
          (unspec:<VNARROWQ> [(match_operand:VQN 2 "register_operand" "w")
-                      (match_operand:VQN 3 "aarch64_simd_rshift_imm")] UNSPEC_RSHRN)))]
+           (match_operand:VQN 3 "aarch64_simd_shift_imm_vec_<vn_mode>")]
+               UNSPEC_RSHRN)))]
   "TARGET_SIMD && !BYTES_BIG_ENDIAN"
   "rshrn2\\t%0.<V2ntype>, %2.<Vtype>, %3"
   [(set_attr "type" "neon_shift_imm_narrow_q")]
   [(set (match_operand:<VNARROWQ2> 0 "register_operand" "=w")
        (vec_concat:<VNARROWQ2>
          (unspec:<VNARROWQ> [(match_operand:VQN 2 "register_operand" "w")
-                      (match_operand:VQN 3 "aarch64_simd_rshift_imm")] UNSPEC_RSHRN)
+               (match_operand:VQN 3 "aarch64_simd_shift_imm_vec_<vn_mode>")]
+                 UNSPEC_RSHRN)
          (match_operand:<VNARROWQ> 1 "register_operand" "0")))]
   "TARGET_SIMD && BYTES_BIG_ENDIAN"
   "rshrn2\\t%0.<V2ntype>, %2.<Vtype>, %3"
index 75612fd9f66cae92ef453b9873c080c3dcc58172..c55842b9c747b817ad8379d6f4e6dbd633ba8fe1 100644 (file)
   (and (match_code "const_int")
        (match_test "IN_RANGE (INTVAL (op), 1, 64)")))
 
+(define_predicate "aarch64_simd_shift_imm_vec_qi"
+  (and (match_code "const_vector")
+       (match_test "aarch64_const_vec_all_same_in_range_p (op, 1, 8)")))
+
+(define_predicate "aarch64_simd_shift_imm_vec_hi"
+  (and (match_code "const_vector")
+       (match_test "aarch64_const_vec_all_same_in_range_p (op, 1, 16)")))
+
+(define_predicate "aarch64_simd_shift_imm_vec_si"
+  (and (match_code "const_vector")
+       (match_test "aarch64_const_vec_all_same_in_range_p (op, 1, 32)")))
+
+(define_predicate "aarch64_simd_shift_imm_vec_di"
+  (and (match_code "const_vector")
+       (match_test "aarch64_const_vec_all_same_in_range_p (op, 1, 64)")))
+
 (define_predicate "aarch64_simd_shift_imm_bitsize_qi"
   (and (match_code "const_int")
        (match_test "IN_RANGE (INTVAL (op), 0, 8)")))
diff --git a/gcc/testsuite/gcc.target/aarch64/simd/pr99437.c b/gcc/testsuite/gcc.target/aarch64/simd/pr99437.c
new file mode 100644 (file)
index 0000000..976fac4
--- /dev/null
@@ -0,0 +1,17 @@
+/* { dg-do assemble } */
+/* { dg-options "-O" } */
+
+#include <arm_neon.h>
+
+uint8x16_t
+foo (uint16x8_t a, uint8x8_t b)
+{
+  return vcombine_u8 (vmovn_u16 (vshrq_n_u16 (a, 9)), b);
+}
+
+uint8x16_t
+foo2 (uint16x8_t a, uint8x8_t b)
+{
+  return vcombine_u8 (b, vmovn_u16 (vshrq_n_u16 (a, 15)));
+}
+