The vectoriser expands the signed-source clip idiom recognised by
unsigned_integer_narrow_clip as MAX_EXPR <0, x> feeding IFN_SAT_TRUNC,
which lands as smax + uqxtn.  sqxtun does both in one instruction.
Combine offers the merged form because the zero vector carries a
REG_EQUAL note, so only a define_insn is needed.

This completes the smax + uqxtn pair that 10/13 of the pending
"Saturating arithmetic matching improvements" series leaves
(patchwork 142865).

Regression tested on aarch64-linux-gnu under qemu (aarch64.exp,
vect.exp); bootstrapped as part of the tree on x86_64.

Assisted-by: Claude Opus 5 (Anthropic)

gcc/ChangeLog:

        * config/aarch64/aarch64-simd.md
        (*aarch64_sqmovun<mode>_smax<vczle><vczbe>): New pattern.

gcc/testsuite/ChangeLog:

        * gcc.target/aarch64/vect-sat-trunc-3.c: New test.

Signed-off-by: Dominic P <[email protected]>
---
 gcc/config/aarch64/aarch64-simd.md              | 11 +++++++++++
 .../gcc.target/aarch64/vect-sat-trunc-3.c       | 17 +++++++++++++++++
 2 files changed, 28 insertions(+)
 create mode 100644 gcc/testsuite/gcc.target/aarch64/vect-sat-trunc-3.c

diff --git a/gcc/config/aarch64/aarch64-simd.md 
b/gcc/config/aarch64/aarch64-simd.md
index 12dcabb7a15..4fa0e85e962 100644
--- a/gcc/config/aarch64/aarch64-simd.md
+++ b/gcc/config/aarch64/aarch64-simd.md
@@ -6265,6 +6265,17 @@
   [(set_attr "type" "neon_sat_shift_imm_narrow_q")]
 )
 
+;; MAX_EXPR <0, x> feeding IFN_SAT_TRUNC, as the vectoriser builds it.
+(define_insn "*aarch64_sqmovun<mode>_smax<vczle><vczbe>"
+  [(set (match_operand:<VNARROWQ> 0 "register_operand" "=w")
+       (us_truncate:<VNARROWQ>
+         (smax:VQN (match_operand:VQN 1 "register_operand" "w")
+                   (match_operand:VQN 2 "aarch64_simd_or_scalar_imm_zero"))))]
+  "TARGET_SIMD"
+  "sqxtun\\t%<vn2>0<Vmntype>, %<v>1<Vmtype>"
+  [(set_attr "type" "neon_sat_shift_imm_narrow_q")]
+)
+
 (define_expand "aarch64_sqmovun<mode>"
   [(set (match_operand:<VNARROWQ> 0 "register_operand" "=w")
        (truncate:<VNARROWQ>
diff --git a/gcc/testsuite/gcc.target/aarch64/vect-sat-trunc-3.c 
b/gcc/testsuite/gcc.target/aarch64/vect-sat-trunc-3.c
new file mode 100644
index 00000000000..56a4ba209fb
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/vect-sat-trunc-3.c
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=armv8-a" } */
+
+typedef __UINT16_TYPE__ u16;
+
+void
+clip_u16 (u16 *__restrict r, const int *__restrict x, int n)
+{
+  for (int i = 0; i < n; i++)
+    {
+      int v = x[i] | 1;
+      r[i] = (unsigned int) v > 65535u ? ((-v) >> 31) : v;
+    }
+}
+
+/* { dg-final { scan-assembler {\tsqxtun\tv[0-9]+\.4h, v[0-9]+\.4s} } } */
+/* { dg-final { scan-assembler-not {\tuqxtn\tv[0-9]+\.4h, v[0-9]+\.4s} } } */
-- 
2.55.0

Reply via email to