]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
aarch64: Use VNx16BI for more SVE WHILE* results [PR121118]
authorRichard Sandiford <richard.sandiford@arm.com>
Mon, 4 Aug 2025 10:45:28 +0000 (11:45 +0100)
committerRichard Sandiford <richard.sandiford@arm.com>
Mon, 4 Aug 2025 10:45:28 +0000 (11:45 +0100)
PR121118 is about a case where we try to construct a predicate
constant using a permutation of a PFALSE and a WHILELO.  The WHILELO
is a .H operation and its result has mode VNx8BI.  However, the
permute instruction expects both inputs to be VNx16BI, leading to
an unrecognisable insn ICE.

VNx8BI is effectively a form of VNx16BI in which every odd-indexed
bit is insignificant.  In the PR's testcase that's OK, since those
bits will be dropped by the permutation.  But if the WHILELO had been a
VNx4BI, so that only every fourth bit is significant, the input to the
permutation would have had undefined bits.  The testcase in the patch
has an example of this.

This feeds into a related ACLE problem that I'd been meaning to
fix for a long time: every bit of an svbool_t result is significant,
and so every ACLE intrinsic that returns an svbool_t should return a
VNx16BI.  That doesn't currently happen for ACLE svwhile* intrinsics.

This patch fixes both issues together.

We still need to keep the current WHILE* patterns for autovectorisation,
where the result mode should match the element width.  The patch
therefore adds a new set of patterns that are defined to return
VNx16BI instead.  For want of a better scheme, it uses an "_acle"
suffix to distinguish these new patterns from the "normal" ones.

The formulation used is:

  (and:VNx16BI (subreg:VNx16BI normal-pattern 0) C)

where C has mode VNx16BI and is a canonical ptrue for normal-pattern's
element width (so that the low bit of each element is set and the upper
bits are clear).

This is a bit clunky, and leads to some repetition.  But it has two
advantages:

* After g:965564eafb721f8000013a3112f1bba8d8fae32b, converting the
  above expression back to normal-pattern's mode will reduce to
  normal-pattern, so that the pattern for testing the result using a
  PTEST doesn't change.

* It gives RTL optimisers a bit more information, as the new tests
  demonstrate.

In the expression above, C is matched using a new "special" predicate
aarch64_ptrue_all_operand, where "special" means that the mode on the
predicate is not necessarily the mode of the expression.  In this case,
C always has mode VNx16BI, but the mode on the predicate indicates which
kind of canonical PTRUE is needed.

gcc/
PR testsuite/121118
* config/aarch64/iterators.md (VNx16BI_ONLY): New mode iterator.
* config/aarch64/predicates.md (aarch64_ptrue_all_operand): New
predicate.
* config/aarch64/aarch64-sve.md
(@aarch64_sve_while_<while_optab_cmp><GPI:mode><VNx16BI_ONLY:mode>_acle)
(@aarch64_sve_while_<while_optab_cmp><GPI:mode><PRED_HSD:mode>_acle)
(*aarch64_sve_while_<while_optab_cmp><GPI:mode><PRED_HSD:mode>_acle)
(*while_<while_optab_cmp><GPI:mode><PRED_HSD:mode>_acle_cc): New
patterns.
* config/aarch64/aarch64-sve-builtins-functions.h
(while_comparison::expand): Use the new _acle patterns that
always return a VNx16BI.
* config/aarch64/aarch64-sve-builtins-sve2.cc
(svwhilerw_svwhilewr_impl::expand): Likewise.
* config/aarch64/aarch64.cc
(aarch64_sve_move_pred_via_while): Likewise.

gcc/testsuite/
PR testsuite/121118
* gcc.target/aarch64/sve/acle/general/pr121118_1.c: New test.
* gcc.target/aarch64/sve/acle/general/whilele_13.c: Likewise.
* gcc.target/aarch64/sve/acle/general/whilelt_6.c: Likewise.
* gcc.target/aarch64/sve2/acle/general/whilege_1.c: Likewise.
* gcc.target/aarch64/sve2/acle/general/whilegt_1.c: Likewise.
* gcc.target/aarch64/sve2/acle/general/whilerw_5.c: Likewise.
* gcc.target/aarch64/sve2/acle/general/whilewr_5.c: Likewise.

13 files changed:
gcc/config/aarch64/aarch64-sve-builtins-functions.h
gcc/config/aarch64/aarch64-sve-builtins-sve2.cc
gcc/config/aarch64/aarch64-sve.md
gcc/config/aarch64/aarch64.cc
gcc/config/aarch64/iterators.md
gcc/config/aarch64/predicates.md
gcc/testsuite/gcc.target/aarch64/sve/acle/general/pr121118_1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general/whilele_13.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general/whilelt_6.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve2/acle/general/whilege_1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve2/acle/general/whilegt_1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve2/acle/general/whilerw_5.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve2/acle/general/whilewr_5.c [new file with mode: 0644]

index 6f1c6948df29de53e68440c04b12baa9ce2fad15..b0cfa703dc4845df1c4f6b607d8502004bec9b39 100644 (file)
@@ -838,7 +838,8 @@ public:
 
     machine_mode pred_mode = e.vector_mode (0);
     scalar_mode reg_mode = GET_MODE_INNER (e.vector_mode (1));
-    return e.use_exact_insn (code_for_while (unspec, reg_mode, pred_mode));
+    auto icode = code_for_aarch64_sve_while_acle (unspec, reg_mode, pred_mode);
+    return e.use_exact_insn (icode);
   }
 
   /* The unspec codes associated with signed and unsigned operations
index 73004a8fd5c5d217f3f2a7f45b4996105f86ce3a..95c5ed81d61026eb8e47ec7dad6c7c7f10b97c3b 100644 (file)
@@ -881,7 +881,9 @@ public:
   {
     for (unsigned int i = 0; i < 2; ++i)
       e.args[i] = e.convert_to_pmode (e.args[i]);
-    return e.use_exact_insn (code_for_while (m_unspec, Pmode, e.gp_mode (0)));
+    auto icode = code_for_aarch64_sve_while_acle (m_unspec, Pmode,
+                                                 e.gp_mode (0));
+    return e.use_exact_insn (icode);
   }
 
   int m_unspec;
index 80a32889f8cfb263d66e93e59732087f1c85ba22..e8c9b67a077dd16019f8ad52f54b5a8eae9f677e 100644 (file)
   "while<cmp_op>\t%0.<PRED_ALL:Vetype>, %<w>1, %<w>2"
 )
 
+;; Likewise, but yield a VNx16BI result regardless of the element width.
+;; The .b case is equivalent to the above.
+(define_expand "@aarch64_sve_while_<while_optab_cmp><GPI:mode><VNx16BI_ONLY:mode>_acle"
+  [(parallel
+     [(set (match_operand:VNx16BI_ONLY 0 "register_operand")
+          (unspec:VNx16BI_ONLY
+            [(const_int SVE_WHILE_B)
+             (match_operand:GPI 1 "aarch64_reg_or_zero")
+             (match_operand:GPI 2 "aarch64_reg_or_zero")]
+            SVE_WHILE))
+      (clobber (reg:CC_NZC CC_REGNUM))])]
+  "TARGET_SVE"
+)
+
+;; For wider elements, bitcast the predicate result to a VNx16BI and use
+;; an (and ...) to indicate that only every second, fourth, or eighth bit
+;; is set.
+(define_expand "@aarch64_sve_while_<while_optab_cmp><GPI:mode><PRED_HSD:mode>_acle"
+  [(parallel
+     [(set (match_operand:VNx16BI 0 "register_operand")
+          (and:VNx16BI
+            (subreg:VNx16BI
+              (unspec:PRED_HSD
+                [(const_int SVE_WHILE_B)
+                 (match_operand:GPI 1 "aarch64_reg_or_zero")
+                 (match_operand:GPI 2 "aarch64_reg_or_zero")]
+                SVE_WHILE)
+              0)
+            (match_dup 3)))
+      (clobber (reg:CC_NZC CC_REGNUM))])]
+  "TARGET_SVE"
+  {
+    operands[3] = aarch64_ptrue_all (<data_bytes>);
+  }
+)
+
+(define_insn "*aarch64_sve_while_<while_optab_cmp><GPI:mode><PRED_HSD:mode>_acle"
+  [(set (match_operand:VNx16BI 0 "register_operand" "=Upa")
+       (and:VNx16BI
+         (subreg:VNx16BI
+           (unspec:PRED_HSD
+             [(const_int SVE_WHILE_B)
+              (match_operand:GPI 1 "aarch64_reg_or_zero" "rZ")
+              (match_operand:GPI 2 "aarch64_reg_or_zero" "rZ")]
+             SVE_WHILE)
+           0)
+         (match_operand:PRED_HSD 3 "aarch64_ptrue_all_operand")))
+   (clobber (reg:CC_NZC CC_REGNUM))]
+  "TARGET_SVE"
+  "while<cmp_op>\t%0.<PRED_HSD:Vetype>, %<w>1, %<w>2"
+)
+
 ;; The WHILE instructions set the flags in the same way as a PTEST with
 ;; a PTRUE GP.  Handle the case in which both results are useful.  The GP
 ;; operands to the PTEST aren't needed, so we allow them to be anything.
   }
 )
 
+(define_insn_and_rewrite "*while_<while_optab_cmp><GPI:mode><PRED_HSD:mode>_acle_cc"
+  [(set (reg:CC_NZC CC_REGNUM)
+       (unspec:CC_NZC
+         [(match_operand 3)
+          (match_operand 4)
+          (const_int SVE_KNOWN_PTRUE)
+          (unspec:PRED_HSD
+            [(const_int SVE_WHILE_B)
+             (match_operand:GPI 1 "aarch64_reg_or_zero" "rZ")
+             (match_operand:GPI 2 "aarch64_reg_or_zero" "rZ")]
+            SVE_WHILE)]
+         UNSPEC_PTEST))
+   (set (match_operand:VNx16BI 0 "register_operand" "=Upa")
+       (and:VNx16BI
+         (subreg:VNx16BI
+           (unspec:PRED_HSD [(const_int SVE_WHILE_B)
+                             (match_dup 1)
+                             (match_dup 2)]
+                            SVE_WHILE)
+           0)
+         (match_operand:PRED_HSD 5 "aarch64_ptrue_all_operand")))]
+  "TARGET_SVE"
+  "while<cmp_op>\t%0.<PRED_HSD:Vetype>, %<w>1, %<w>2"
+  ;; Force the compiler to drop the unused predicate operand, so that we
+  ;; don't have an unnecessary PTRUE.
+  "&& (!CONSTANT_P (operands[3]) || !CONSTANT_P (operands[4]))"
+  {
+    operands[3] = CONSTM1_RTX (VNx16BImode);
+    operands[4] = CONSTM1_RTX (<PRED_HSD:MODE>mode);
+  }
+)
+
 ;; Same, but handle the case in which only the flags result is useful.
 (define_insn_and_rewrite "@while_<while_optab_cmp><GPI:mode><PRED_ALL:mode>_ptest"
   [(set (reg:CC_NZC CC_REGNUM)
index f4a2062b042af0cc29eb2367d9eff783b38015e9..39171cf171a30acfb5bb71d4fac07ae07698bae8 100644 (file)
@@ -6069,9 +6069,9 @@ aarch64_sve_move_pred_via_while (rtx target, machine_mode mode,
                                 unsigned int vl)
 {
   rtx limit = force_reg (DImode, gen_int_mode (vl, DImode));
-  target = aarch64_target_reg (target, mode);
-  emit_insn (gen_while (UNSPEC_WHILELO, DImode, mode,
-                       target, const0_rtx, limit));
+  target = aarch64_target_reg (target, VNx16BImode);
+  emit_insn (gen_aarch64_sve_while_acle (UNSPEC_WHILELO, DImode, mode,
+                                        target, const0_rtx, limit));
   return target;
 }
 
index 8533912e5937c78b6171242b74586eb8bdc5b501..175a55336c56dac4ae758a7bac3dd088ee95b9ce 100644 (file)
 (define_mode_iterator VCVTFPM [V4HF V8HF V4SF])
 
 ;; Iterators for single modes, for "@" patterns.
+(define_mode_iterator VNx16BI_ONLY [VNx16BI])
 (define_mode_iterator VNx16QI_ONLY [VNx16QI])
 (define_mode_iterator VNx16SI_ONLY [VNx16SI])
 (define_mode_iterator VNx8HI_ONLY [VNx8HI])
index 32056daf3298785eda856cf36cf7b4de7addb4ab..4d5d57f1e5d62490122bce8d80feeff3ad0a624d 100644 (file)
 (define_predicate "aarch64_maskload_else_operand"
   (and (match_code "const_vector")
        (match_test "op == CONST0_RTX (GET_MODE (op))")))
+
+;; Check for a VNx16BI predicate that is a canonical PTRUE for the given
+;; predicate mode.
+(define_special_predicate "aarch64_ptrue_all_operand"
+  (and (match_code "const_vector")
+       (match_test "aarch64_ptrue_all_mode (op) == mode")))
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/pr121118_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/pr121118_1.c
new file mode 100644 (file)
index 0000000..b59a972
--- /dev/null
@@ -0,0 +1,16 @@
+/* { dg-options "-O2 -msve-vector-bits=512" } */
+
+typedef __SVBool_t fixed_bool __attribute__((arm_sve_vector_bits(512)));
+
+#define TEST_CONST(NAME, CONST)                                                \
+  fixed_bool                                                           \
+  NAME ()                                                              \
+  {                                                                    \
+    union { unsigned long long i; fixed_bool pg; } u = { CONST };      \
+    return u.pg;                                                       \
+  }
+
+TEST_CONST (test1, 0x02aaaaaaaa)
+TEST_CONST (test2, 0x0155555557)
+TEST_CONST (test3, 0x0013333333333333ULL)
+TEST_CONST (test4, 0x0011111111111113ULL)
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/whilele_13.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/whilele_13.c
new file mode 100644 (file)
index 0000000..cf50dc1
--- /dev/null
@@ -0,0 +1,130 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+#include <arm_sve.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+** test1:
+**     whilele p0\.h, w0, w1
+**     ret
+*/
+svbool_t
+test1 (int32_t x, int32_t y)
+{
+  return svand_z (svptrue_b8 (),
+                 svwhilele_b16 (x, y),
+                 svptrue_b16 ());
+}
+
+/*
+** test2:
+**     whilele p0\.h, x0, x1
+**     ret
+*/
+svbool_t
+test2 (int64_t x, int64_t y)
+{
+  return svand_z (svptrue_b16 (),
+                 svwhilele_b16 (x, y),
+                 svptrue_b16 ());
+}
+
+/*
+** test3:
+**     whilels p0\.s, w0, w1
+**     ret
+*/
+svbool_t
+test3 (uint32_t x, uint32_t y)
+{
+  return svand_z (svptrue_b8 (),
+                 svwhilele_b32 (x, y),
+                 svptrue_b16 ());
+}
+
+/*
+** test4:
+**     whilels p0\.s, x0, x1
+**     ret
+*/
+svbool_t
+test4 (uint64_t x, uint64_t y)
+{
+  return svand_z (svptrue_b8 (),
+                 svwhilele_b32 (x, y),
+                 svptrue_b32 ());
+}
+
+/*
+** test5:
+**     whilele p0\.s, w0, w1
+**     ret
+*/
+svbool_t
+test5 (int32_t x, int32_t y)
+{
+  return svand_z (svptrue_b16 (),
+                 svwhilele_b32 (x, y),
+                 svptrue_b32 ());
+}
+
+/*
+** test6:
+**     whilels p0\.s, w0, w1
+**     ret
+*/
+svbool_t
+test6 (uint32_t x, uint32_t y)
+{
+  return svand_z (svptrue_b32 (),
+                 svwhilele_b32 (x, y),
+                 svptrue_b32 ());
+}
+
+/*
+** test7:
+**     whilels p0\.d, w0, w1
+**     ret
+*/
+svbool_t
+test7 (uint32_t x, uint32_t y)
+{
+  return svand_z (svptrue_b8 (),
+                 svwhilele_b64 (x, y),
+                 svptrue_b64 ());
+}
+
+/*
+** test8:
+**     whilele p0\.d, x0, x1
+**     ret
+*/
+svbool_t
+test8 (int64_t x, int64_t y)
+{
+  return svand_z (svptrue_b16 (),
+                 svwhilele_b64 (x, y),
+                 svptrue_b32 ());
+}
+
+/*
+** test9:
+**     whilels p0\.d, x0, x1
+**     ret
+*/
+svbool_t
+test9 (uint64_t x, uint64_t y)
+{
+  return svand_z (svptrue_b64 (),
+                 svwhilele_b64 (x, y),
+                 svptrue_b64 ());
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/whilelt_6.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/whilelt_6.c
new file mode 100644 (file)
index 0000000..27bf0c2
--- /dev/null
@@ -0,0 +1,130 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+#include <arm_sve.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+** test1:
+**     whilelt p0\.h, w0, w1
+**     ret
+*/
+svbool_t
+test1 (int32_t x, int32_t y)
+{
+  return svand_z (svptrue_b8 (),
+                 svwhilelt_b16 (x, y),
+                 svptrue_b16 ());
+}
+
+/*
+** test2:
+**     whilelt p0\.h, x0, x1
+**     ret
+*/
+svbool_t
+test2 (int64_t x, int64_t y)
+{
+  return svand_z (svptrue_b16 (),
+                 svwhilelt_b16 (x, y),
+                 svptrue_b16 ());
+}
+
+/*
+** test3:
+**     whilelo p0\.s, w0, w1
+**     ret
+*/
+svbool_t
+test3 (uint32_t x, uint32_t y)
+{
+  return svand_z (svptrue_b8 (),
+                 svwhilelt_b32 (x, y),
+                 svptrue_b16 ());
+}
+
+/*
+** test4:
+**     whilelo p0\.s, x0, x1
+**     ret
+*/
+svbool_t
+test4 (uint64_t x, uint64_t y)
+{
+  return svand_z (svptrue_b8 (),
+                 svwhilelt_b32 (x, y),
+                 svptrue_b32 ());
+}
+
+/*
+** test5:
+**     whilelt p0\.s, w0, w1
+**     ret
+*/
+svbool_t
+test5 (int32_t x, int32_t y)
+{
+  return svand_z (svptrue_b16 (),
+                 svwhilelt_b32 (x, y),
+                 svptrue_b32 ());
+}
+
+/*
+** test6:
+**     whilelo p0\.s, w0, w1
+**     ret
+*/
+svbool_t
+test6 (uint32_t x, uint32_t y)
+{
+  return svand_z (svptrue_b32 (),
+                 svwhilelt_b32 (x, y),
+                 svptrue_b32 ());
+}
+
+/*
+** test7:
+**     whilelo p0\.d, w0, w1
+**     ret
+*/
+svbool_t
+test7 (uint32_t x, uint32_t y)
+{
+  return svand_z (svptrue_b8 (),
+                 svwhilelt_b64 (x, y),
+                 svptrue_b64 ());
+}
+
+/*
+** test8:
+**     whilelt p0\.d, x0, x1
+**     ret
+*/
+svbool_t
+test8 (int64_t x, int64_t y)
+{
+  return svand_z (svptrue_b16 (),
+                 svwhilelt_b64 (x, y),
+                 svptrue_b32 ());
+}
+
+/*
+** test9:
+**     whilelo p0\.d, x0, x1
+**     ret
+*/
+svbool_t
+test9 (uint64_t x, uint64_t y)
+{
+  return svand_z (svptrue_b64 (),
+                 svwhilelt_b64 (x, y),
+                 svptrue_b64 ());
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/gcc/testsuite/gcc.target/aarch64/sve2/acle/general/whilege_1.c b/gcc/testsuite/gcc.target/aarch64/sve2/acle/general/whilege_1.c
new file mode 100644 (file)
index 0000000..07b56a8
--- /dev/null
@@ -0,0 +1,130 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+#include <arm_sve.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+** test1:
+**     whilege p0\.h, w0, w1
+**     ret
+*/
+svbool_t
+test1 (int32_t x, int32_t y)
+{
+  return svand_z (svptrue_b8 (),
+                 svwhilege_b16 (x, y),
+                 svptrue_b16 ());
+}
+
+/*
+** test2:
+**     whilege p0\.h, x0, x1
+**     ret
+*/
+svbool_t
+test2 (int64_t x, int64_t y)
+{
+  return svand_z (svptrue_b16 (),
+                 svwhilege_b16 (x, y),
+                 svptrue_b16 ());
+}
+
+/*
+** test3:
+**     whilehs p0\.s, w0, w1
+**     ret
+*/
+svbool_t
+test3 (uint32_t x, uint32_t y)
+{
+  return svand_z (svptrue_b8 (),
+                 svwhilege_b32 (x, y),
+                 svptrue_b16 ());
+}
+
+/*
+** test4:
+**     whilehs p0\.s, x0, x1
+**     ret
+*/
+svbool_t
+test4 (uint64_t x, uint64_t y)
+{
+  return svand_z (svptrue_b8 (),
+                 svwhilege_b32 (x, y),
+                 svptrue_b32 ());
+}
+
+/*
+** test5:
+**     whilege p0\.s, w0, w1
+**     ret
+*/
+svbool_t
+test5 (int32_t x, int32_t y)
+{
+  return svand_z (svptrue_b16 (),
+                 svwhilege_b32 (x, y),
+                 svptrue_b32 ());
+}
+
+/*
+** test6:
+**     whilehs p0\.s, w0, w1
+**     ret
+*/
+svbool_t
+test6 (uint32_t x, uint32_t y)
+{
+  return svand_z (svptrue_b32 (),
+                 svwhilege_b32 (x, y),
+                 svptrue_b32 ());
+}
+
+/*
+** test7:
+**     whilehs p0\.d, w0, w1
+**     ret
+*/
+svbool_t
+test7 (uint32_t x, uint32_t y)
+{
+  return svand_z (svptrue_b8 (),
+                 svwhilege_b64 (x, y),
+                 svptrue_b64 ());
+}
+
+/*
+** test8:
+**     whilege p0\.d, x0, x1
+**     ret
+*/
+svbool_t
+test8 (int64_t x, int64_t y)
+{
+  return svand_z (svptrue_b16 (),
+                 svwhilege_b64 (x, y),
+                 svptrue_b32 ());
+}
+
+/*
+** test9:
+**     whilehs p0\.d, x0, x1
+**     ret
+*/
+svbool_t
+test9 (uint64_t x, uint64_t y)
+{
+  return svand_z (svptrue_b64 (),
+                 svwhilege_b64 (x, y),
+                 svptrue_b64 ());
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/gcc/testsuite/gcc.target/aarch64/sve2/acle/general/whilegt_1.c b/gcc/testsuite/gcc.target/aarch64/sve2/acle/general/whilegt_1.c
new file mode 100644 (file)
index 0000000..df707c3
--- /dev/null
@@ -0,0 +1,130 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+#include <arm_sve.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+** test1:
+**     whilegt p0\.h, w0, w1
+**     ret
+*/
+svbool_t
+test1 (int32_t x, int32_t y)
+{
+  return svand_z (svptrue_b8 (),
+                 svwhilegt_b16 (x, y),
+                 svptrue_b16 ());
+}
+
+/*
+** test2:
+**     whilegt p0\.h, x0, x1
+**     ret
+*/
+svbool_t
+test2 (int64_t x, int64_t y)
+{
+  return svand_z (svptrue_b16 (),
+                 svwhilegt_b16 (x, y),
+                 svptrue_b16 ());
+}
+
+/*
+** test3:
+**     whilehi p0\.s, w0, w1
+**     ret
+*/
+svbool_t
+test3 (uint32_t x, uint32_t y)
+{
+  return svand_z (svptrue_b8 (),
+                 svwhilegt_b32 (x, y),
+                 svptrue_b16 ());
+}
+
+/*
+** test4:
+**     whilehi p0\.s, x0, x1
+**     ret
+*/
+svbool_t
+test4 (uint64_t x, uint64_t y)
+{
+  return svand_z (svptrue_b8 (),
+                 svwhilegt_b32 (x, y),
+                 svptrue_b32 ());
+}
+
+/*
+** test5:
+**     whilegt p0\.s, w0, w1
+**     ret
+*/
+svbool_t
+test5 (int32_t x, int32_t y)
+{
+  return svand_z (svptrue_b16 (),
+                 svwhilegt_b32 (x, y),
+                 svptrue_b32 ());
+}
+
+/*
+** test6:
+**     whilehi p0\.s, w0, w1
+**     ret
+*/
+svbool_t
+test6 (uint32_t x, uint32_t y)
+{
+  return svand_z (svptrue_b32 (),
+                 svwhilegt_b32 (x, y),
+                 svptrue_b32 ());
+}
+
+/*
+** test7:
+**     whilehi p0\.d, w0, w1
+**     ret
+*/
+svbool_t
+test7 (uint32_t x, uint32_t y)
+{
+  return svand_z (svptrue_b8 (),
+                 svwhilegt_b64 (x, y),
+                 svptrue_b64 ());
+}
+
+/*
+** test8:
+**     whilegt p0\.d, x0, x1
+**     ret
+*/
+svbool_t
+test8 (int64_t x, int64_t y)
+{
+  return svand_z (svptrue_b16 (),
+                 svwhilegt_b64 (x, y),
+                 svptrue_b32 ());
+}
+
+/*
+** test9:
+**     whilehi p0\.d, x0, x1
+**     ret
+*/
+svbool_t
+test9 (uint64_t x, uint64_t y)
+{
+  return svand_z (svptrue_b64 (),
+                 svwhilegt_b64 (x, y),
+                 svptrue_b64 ());
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/gcc/testsuite/gcc.target/aarch64/sve2/acle/general/whilerw_5.c b/gcc/testsuite/gcc.target/aarch64/sve2/acle/general/whilerw_5.c
new file mode 100644 (file)
index 0000000..0c24199
--- /dev/null
@@ -0,0 +1,130 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+#include <arm_sve.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+** test1:
+**     whilerw p0\.h, x0, x1
+**     ret
+*/
+svbool_t
+test1 (int16_t *x, int16_t *y)
+{
+  return svand_z (svptrue_b8 (),
+                 svwhilerw (x, y),
+                 svptrue_b16 ());
+}
+
+/*
+** test2:
+**     whilerw p0\.h, x0, x1
+**     ret
+*/
+svbool_t
+test2 (uint16_t *x, uint16_t *y)
+{
+  return svand_z (svptrue_b16 (),
+                 svwhilerw (x, y),
+                 svptrue_b16 ());
+}
+
+/*
+** test3:
+**     whilerw p0\.s, x0, x1
+**     ret
+*/
+svbool_t
+test3 (int32_t *x, int32_t *y)
+{
+  return svand_z (svptrue_b8 (),
+                 svwhilerw (x, y),
+                 svptrue_b16 ());
+}
+
+/*
+** test4:
+**     whilerw p0\.s, x0, x1
+**     ret
+*/
+svbool_t
+test4 (uint32_t *x, uint32_t *y)
+{
+  return svand_z (svptrue_b8 (),
+                 svwhilerw (x, y),
+                 svptrue_b32 ());
+}
+
+/*
+** test5:
+**     whilerw p0\.s, x0, x1
+**     ret
+*/
+svbool_t
+test5 (float32_t *x, float32_t *y)
+{
+  return svand_z (svptrue_b16 (),
+                 svwhilerw (x, y),
+                 svptrue_b32 ());
+}
+
+/*
+** test6:
+**     whilerw p0\.s, x0, x1
+**     ret
+*/
+svbool_t
+test6 (int32_t *x, int32_t *y)
+{
+  return svand_z (svptrue_b32 (),
+                 svwhilerw (x, y),
+                 svptrue_b32 ());
+}
+
+/*
+** test7:
+**     whilerw p0\.d, x0, x1
+**     ret
+*/
+svbool_t
+test7 (int64_t *x, int64_t *y)
+{
+  return svand_z (svptrue_b8 (),
+                 svwhilerw (x, y),
+                 svptrue_b64 ());
+}
+
+/*
+** test8:
+**     whilerw p0\.d, x0, x1
+**     ret
+*/
+svbool_t
+test8 (uint64_t *x, uint64_t *y)
+{
+  return svand_z (svptrue_b16 (),
+                 svwhilerw (x, y),
+                 svptrue_b32 ());
+}
+
+/*
+** test9:
+**     whilerw p0\.d, x0, x1
+**     ret
+*/
+svbool_t
+test9 (float64_t *x, float64_t *y)
+{
+  return svand_z (svptrue_b64 (),
+                 svwhilerw (x, y),
+                 svptrue_b64 ());
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/gcc/testsuite/gcc.target/aarch64/sve2/acle/general/whilewr_5.c b/gcc/testsuite/gcc.target/aarch64/sve2/acle/general/whilewr_5.c
new file mode 100644 (file)
index 0000000..38db9af
--- /dev/null
@@ -0,0 +1,130 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+#include <arm_sve.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+** test1:
+**     whilewr p0\.h, x0, x1
+**     ret
+*/
+svbool_t
+test1 (int16_t *x, int16_t *y)
+{
+  return svand_z (svptrue_b8 (),
+                 svwhilewr (x, y),
+                 svptrue_b16 ());
+}
+
+/*
+** test2:
+**     whilewr p0\.h, x0, x1
+**     ret
+*/
+svbool_t
+test2 (uint16_t *x, uint16_t *y)
+{
+  return svand_z (svptrue_b16 (),
+                 svwhilewr (x, y),
+                 svptrue_b16 ());
+}
+
+/*
+** test3:
+**     whilewr p0\.s, x0, x1
+**     ret
+*/
+svbool_t
+test3 (int32_t *x, int32_t *y)
+{
+  return svand_z (svptrue_b8 (),
+                 svwhilewr (x, y),
+                 svptrue_b16 ());
+}
+
+/*
+** test4:
+**     whilewr p0\.s, x0, x1
+**     ret
+*/
+svbool_t
+test4 (uint32_t *x, uint32_t *y)
+{
+  return svand_z (svptrue_b8 (),
+                 svwhilewr (x, y),
+                 svptrue_b32 ());
+}
+
+/*
+** test5:
+**     whilewr p0\.s, x0, x1
+**     ret
+*/
+svbool_t
+test5 (float32_t *x, float32_t *y)
+{
+  return svand_z (svptrue_b16 (),
+                 svwhilewr (x, y),
+                 svptrue_b32 ());
+}
+
+/*
+** test6:
+**     whilewr p0\.s, x0, x1
+**     ret
+*/
+svbool_t
+test6 (int32_t *x, int32_t *y)
+{
+  return svand_z (svptrue_b32 (),
+                 svwhilewr (x, y),
+                 svptrue_b32 ());
+}
+
+/*
+** test7:
+**     whilewr p0\.d, x0, x1
+**     ret
+*/
+svbool_t
+test7 (int64_t *x, int64_t *y)
+{
+  return svand_z (svptrue_b8 (),
+                 svwhilewr (x, y),
+                 svptrue_b64 ());
+}
+
+/*
+** test8:
+**     whilewr p0\.d, x0, x1
+**     ret
+*/
+svbool_t
+test8 (uint64_t *x, uint64_t *y)
+{
+  return svand_z (svptrue_b16 (),
+                 svwhilewr (x, y),
+                 svptrue_b32 ());
+}
+
+/*
+** test9:
+**     whilewr p0\.d, x0, x1
+**     ret
+*/
+svbool_t
+test9 (float64_t *x, float64_t *y)
+{
+  return svand_z (svptrue_b64 (),
+                 svwhilewr (x, y),
+                 svptrue_b64 ());
+}
+
+#ifdef __cplusplus
+}
+#endif