]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
aarch64: Expand CTZ to RBIT + CLZ for SVE [PR109498]
authorSoumya AR <soumyaa@nvidia.com>
Tue, 8 Oct 2024 13:37:24 +0000 (14:37 +0100)
committerRichard Sandiford <richard.sandiford@arm.com>
Tue, 8 Oct 2024 13:37:24 +0000 (14:37 +0100)
Currently, we vectorize CTZ for SVE by using the following operation:
.CTZ (X) = (PREC - 1) - .CLZ (X & -X)

Instead, this patch expands CTZ to RBIT + CLZ for SVE, as suggested in PR109498.

The patch was bootstrapped and regtested on aarch64-linux-gnu, no regression.
OK for mainline?

Signed-off-by: Soumya AR <soumyaa@nvidia.com>
gcc/ChangeLog:
PR target/109498
* config/aarch64/aarch64-sve.md (ctz<mode>2): Added pattern to expand
CTZ to RBIT + CLZ for SVE.

gcc/testsuite/ChangeLog:
PR target/109498
* gcc.target/aarch64/sve/ctz.c: New test.

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

index 90db51e51b9d2d8b730498983458e7bf215aa93f..06bd3e4bb2c0b31392f3483db240f92a549c441a 100644 (file)
 ;; - NOT
 ;; -------------------------------------------------------------------------
 
+(define_expand "ctz<mode>2"
+  [(set (match_operand:SVE_I 0 "register_operand")
+       (unspec:SVE_I
+         [(match_dup 2)
+          (ctz:SVE_I
+            (match_operand:SVE_I 1 "register_operand"))]
+         UNSPEC_PRED_X))]
+  "TARGET_SVE"
+  {
+     rtx pred = aarch64_ptrue_reg (<VPRED>mode);
+     rtx temp = gen_reg_rtx (<MODE>mode);
+     emit_insn (gen_aarch64_pred_rbit<mode> (temp, pred, operands[1]));
+     emit_insn (gen_aarch64_pred_clz<mode> (operands[0], pred, temp));
+     DONE;
+  }
+)
+
 ;; Unpredicated integer unary arithmetic.
 (define_expand "<optab><mode>2"
   [(set (match_operand:SVE_I 0 "register_operand")
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/ctz.c b/gcc/testsuite/gcc.target/aarch64/sve/ctz.c
new file mode 100644 (file)
index 0000000..433a917
--- /dev/null
@@ -0,0 +1,49 @@
+/* { dg-final { check-function-bodies "**" "" } } */
+/* { dg-options "-O3 --param aarch64-autovec-preference=sve-only" } */
+
+#include <stdint.h>
+
+#define FUNC(FUNCTION, NAME, DTYPE)                 \
+void                                                     \
+NAME (DTYPE *__restrict x, DTYPE *__restrict y, int n) { \
+  for (int i = 0; i < n; i++)                            \
+    x[i] = FUNCTION (y[i]);                         \
+}                                                        \
+
+
+/*
+** ctz_uint8:
+**     ...
+**     rbit    z[0-9]+\.b, p[0-7]/m, z[0-9]+\.b
+**     clz     z[0-9]+\.b, p[0-7]/m, z[0-9]+\.b
+**     ...
+*/
+FUNC (__builtin_ctzg, ctz_uint8, uint8_t)
+
+/*
+** ctz_uint16:
+**     ...
+**     rbit    z[0-9]+\.h, p[0-7]/m, z[0-9]+\.h
+**     clz     z[0-9]+\.h, p[0-7]/m, z[0-9]+\.h
+**     ...
+*/
+FUNC (__builtin_ctzg, ctz_uint16, uint16_t)
+
+/*
+** ctz_uint32:
+**     ...
+**     rbit    z[0-9]+\.s, p[0-7]/m, z[0-9]+\.s
+**     clz     z[0-9]+\.s, p[0-7]/m, z[0-9]+\.s
+**     ...
+*/
+FUNC (__builtin_ctz, ctz_uint32, uint32_t)
+
+/*
+** ctz_uint64:
+**     ...
+**     rbit    z[0-9]+\.d, p[0-7]/m, z[0-9]+\.d
+**     clz     z[0-9]+\.d, p[0-7]/m, z[0-9]+\.d
+**     ...
+*/
+FUNC (__builtin_ctzll, ctz_uint64, uint64_t)
+