https://gcc.gnu.org/g:50be38676af8ed32744b856ad6864302f7b400bc
commit r17-4241-g50be38676af8ed32744b856ad6864302f7b400bc Author: Naveen <[email protected]> Date: Mon Sep 14 20:19:42 2026 -0700 aarch64: Use UDOT for V8QI sad when dot product is available 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]> Diff: --- gcc/config/aarch64/aarch64-simd.md | 15 ++++++++++ gcc/testsuite/gcc.target/aarch64/sadv8qi-dotprod.c | 35 ++++++++++++++++++++++ 2 files changed, 50 insertions(+) diff --git a/gcc/config/aarch64/aarch64-simd.md b/gcc/config/aarch64/aarch64-simd.md index 5e87df2bb5fd..fe6cb4250f6a 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 000000000000..351bb66e1fbb --- /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-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 } } */
