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

Reply via email to