On TARGET_DOTPROD targets the SAD can be lowered to two instructions:
UABD/SABD to compute the lane-wise absolute differences into a V8QI temporary
followed by a single UDOT against a vector of all-ones to widen and accumulate
the eight byte lanes into a V2SI result. The signed variant uses SABD but
still feeds UDOT since absolute differences are unsigned.
A new test sadv8qi-dotprod.c verifies that both unsigned and signed
SAD loops emit UABD/SABD + UDOT on arm_v8_2a_dotprod targets.
gcc/ChangeLog
* config/aarch64/aarch64-simd.md: Add define_expand <su>sadv8qi
guarded by TARGET_DOTPROD.
gcc/testsuite/ChangeLog
* gcc.target/aarch64/sadv8qi-dotprod.c: New test.
Signed-off-by: Naveen <[email protected]>
---
gcc/config/aarch64/aarch64-simd.md | 15 ++++++++
.../gcc.target/aarch64/sadv8qi-dotprod.c | 35 +++++++++++++++++++
2 files changed, 50 insertions(+)
create mode 100644 gcc/testsuite/gcc.target/aarch64/sadv8qi-dotprod.c
diff --git a/gcc/config/aarch64/aarch64-simd.md
b/gcc/config/aarch64/aarch64-simd.md
index e91692ce486..34937877a64 100644
--- a/gcc/config/aarch64/aarch64-simd.md
+++ b/gcc/config/aarch64/aarch64-simd.md
@@ -1235,6 +1235,21 @@
[(set_attr "type" "neon_reduc_add<q>")]
)
+(define_expand "<su>sadv8qi"
+ [(use (match_operand:V2SI 0 "register_operand"))
+ (USMAX:V8QI (match_operand:V8QI 1 "register_operand")
+ (match_operand:V8QI 2 "register_operand"))
+ (use (match_operand:V2SI 3 "register_operand"))]
+ "TARGET_DOTPROD"
+ {
+ rtx ones = force_reg (V8QImode, CONST1_RTX (V8QImode));
+ rtx abd = gen_reg_rtx (V8QImode);
+ emit_insn (gen_aarch64_<su>abdv8qi (abd, operands[1], operands[2]));
+ emit_insn (gen_udot_prodv2siv8qi (operands[0], abd, ones, operands[3]));
+ DONE;
+ }
+)
+
;; Emit a sequence to produce a sum-of-absolute-differences of the V16QI
;; inputs in operands 1 and 2. The sequence also has to perform a widening
;; reduction of the difference into a V4SI vector and accumulate that into
diff --git a/gcc/testsuite/gcc.target/aarch64/sadv8qi-dotprod.c
b/gcc/testsuite/gcc.target/aarch64/sadv8qi-dotprod.c
new file mode 100644
index 00000000000..7a19d64d6b5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sadv8qi-dotprod.c
@@ -0,0 +1,35 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target arm_v8_2a_dotprod_neon_ok } */
+/* { dg-add-options arm_v8_2a_dotprod_neon } */
+/* { dg-additional-options "-O3 -fno-vect-cost-model -fno-unroll-loops" } */
+
+#pragma GCC target "+nosve"
+
+#define N 8
+
+unsigned char upix1[N], upix2[N];
+signed char spix1[N], spix2[N];
+
+int
+ufoo (void)
+{
+ int sum = 0;
+ int i;
+ for (i = 0; i < N; ++i)
+ sum += __builtin_abs (upix1[i] - upix2[i]);
+ return sum;
+}
+
+int
+sfoo (void)
+{
+ int sum = 0;
+ int i;
+ for (i = 0; i < N; ++i)
+ sum += __builtin_abs (spix1[i] - spix2[i]);
+ return sum;
+}
+
+/* { dg-final { scan-assembler {\tuabd\tv[0-9]+\.8b, v[0-9]+\.8b, v[0-9]+\.8b}
} } */
+/* { dg-final { scan-assembler {\tsabd\tv[0-9]+\.8b, v[0-9]+\.8b, v[0-9]+\.8b}
} } */
+/* { dg-final { scan-assembler-times {\tudot\tv[0-9]+\.2s, v[0-9]+\.8b,
v[0-9]+\.8b} 2 } } */
--
2.34.1