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