https://gcc.gnu.org/g:4b9034d6b240aa2bac3152703c3961b76e30a187

commit r17-4671-g4b9034d6b240aa2bac3152703c3961b76e30a187
Author: Dominic P <[email protected]>
Date:   Thu Sep 10 15:33:43 2026 +0100

    aarch64: express sqxtun and friends as us_truncate of smax
    
    The sqxtun patterns are written with more complex RTL than the
    instruction needs: us_truncate of an smax against zero is what they
    should match.  Rewrite them that way, so that the shape the vectoriser
    produces for MAX_EXPR <0, x> fed into IFN_SAT_TRUNC is matched by the
    sqxtun pattern itself.
    
    The rewrite covers more than the two sqxtun patterns.
    sqxtun2, sqshrun, sqshrun2, sqrshrun and sqrshrun2 wrap their results in
    the same truncate/smin/smax clamp against half_mask, so converting only
    the sqxtun pair would have left two spellings of "saturate into the
    unsigned narrow mode" in one file; they are converted too.  The named
    expanders build the us_truncate form directly, which is what keeps the
    vqmovun_*, vqshrun_n_* and vqrshrun_n_* intrinsics working: they reach
    the patterns through gen_* rather than through recog on a combination.
    
    aarch64_simd_umax_half_mode and aarch64_simd_umax_quarter_mode lose their
    last users and are removed.  The scalar sqshrun/sqrshrun define_insns are
    unchanged: they compute in the wide mode and the expander takes a
    lowpart, so there is no truncate for the clamp to fold into.
    
    The vqmovun/vqshrun_n/vqrshrun_n tests in
    gcc.target/aarch64/advsimd-intrinsics compare against expected values and
    run under qemu, so the family already has execution coverage; the new
    test only checks that the vectoriser's form reaches sqxtun.
    
    Bootstrapped and regression tested on x86_64-pc-linux-gnu, and
    cross-tested on aarch64-linux-gnu under qemu (aarch64.exp, simd.exp,
    advsimd-intrinsics.exp, vect.exp).
    
    Assisted-by: Claude Opus 5 (Anthropic)
    
    gcc/ChangeLog:
    
            * config/aarch64/predicates.md (aarch64_simd_umax_half_mode)
            (aarch64_simd_umax_quarter_mode): Remove.
            * config/aarch64/aarch64-simd.md (aarch64_sqmovun<mode>)
            (*aarch64_sqmovun<mode>_insn<vczle><vczbe>)
            (aarch64_sqxtun2<mode>_le, aarch64_sqxtun2<mode>_be)
            (aarch64_sqxtun2<mode>)
            (*aarch64_sqshrun_n<mode>_insn<vczle><vczbe>)
            (aarch64_sqshrun_n<mode>)
            (*aarch64_sqrshrun_n<mode>_insn<vczle><vczbe>)
            (aarch64_sqrshrun_n<mode>, aarch64_sqshrun2_n<mode>_insn_le)
            (aarch64_sqshrun2_n<mode>_insn_be, aarch64_sqshrun2_n<mode>)
            (aarch64_sqrshrun2_n<mode>_insn_le)
            (aarch64_sqrshrun2_n<mode>_insn_be, aarch64_sqrshrun2_n<mode>):
            Match an us_truncate of an smax instead of a truncate of an smin
            of an smax.
    
    gcc/testsuite/ChangeLog:
    
            * gcc.target/aarch64/vect-sat-trunc-3.c: New test.
    
    Signed-off-by: Dominic P <[email protected]>

Diff:
---
 gcc/config/aarch64/aarch64-simd.md                 | 211 ++++++++-------------
 gcc/config/aarch64/predicates.md                   |  15 --
 .../gcc.target/aarch64/vect-sat-trunc-3.c          |  41 ++++
 3 files changed, 125 insertions(+), 142 deletions(-)

diff --git a/gcc/config/aarch64/aarch64-simd.md 
b/gcc/config/aarch64/aarch64-simd.md
index fe6cb4250f6a..9d1a929576c7 100644
--- a/gcc/config/aarch64/aarch64-simd.md
+++ b/gcc/config/aarch64/aarch64-simd.md
@@ -6282,12 +6282,10 @@
 
 (define_insn "aarch64_sqmovun<mode>"
   [(set (match_operand:<VNARROWQ> 0 "register_operand" "=w")
-       (truncate:<VNARROWQ>
-         (smin:SD_HSDI
-           (smax:SD_HSDI
-             (match_operand:SD_HSDI 1 "register_operand" "w")
-             (const_int 0))
-           (const_int <half_mask>))))]
+       (us_truncate:<VNARROWQ>
+         (smax:SD_HSDI
+           (match_operand:SD_HSDI 1 "register_operand" "w")
+           (const_int 0))))]
    "TARGET_SIMD"
    "sqxtun\\t%<vn2>0<Vmntype>, %<v>1<Vmtype>"
    [(set_attr "type" "neon_sat_shift_imm_narrow_q")]
@@ -6295,11 +6293,9 @@
 
 (define_insn "*aarch64_sqmovun<mode>_insn<vczle><vczbe>"
   [(set (match_operand:<VNARROWQ> 0 "register_operand" "=w")
-       (truncate:<VNARROWQ>
-         (smin:VQN
-           (smax:VQN (match_operand:VQN 1 "register_operand" "w")
-                     (match_operand:VQN 2 "aarch64_simd_or_scalar_imm_zero"))
-           (match_operand:VQN 3 "aarch64_simd_umax_half_mode"))))]
+       (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")]
@@ -6307,17 +6303,12 @@
 
 (define_expand "aarch64_sqmovun<mode>"
   [(set (match_operand:<VNARROWQ> 0 "register_operand" "=w")
-       (truncate:<VNARROWQ>
-         (smin:VQN
-           (smax:VQN (match_operand:VQN 1 "register_operand" "w")
-                     (match_dup 2))
-           (match_dup 3))))]
+       (us_truncate:<VNARROWQ>
+         (smax:VQN (match_operand:VQN 1 "register_operand" "w")
+                   (match_dup 2))))]
   "TARGET_SIMD"
   {
     operands[2] = CONST0_RTX (<MODE>mode);
-    operands[3]
-      = aarch64_simd_gen_const_vector_dup (<MODE>mode,
-                       GET_MODE_MASK (GET_MODE_INNER (<VNARROWQ>mode)));
   }
 )
 
@@ -6325,12 +6316,10 @@
   [(set (match_operand:<VNARROWQ2> 0 "register_operand" "=w")
        (vec_concat:<VNARROWQ2>
          (match_operand:<VNARROWQ> 1 "register_operand" "0")
-         (truncate:<VNARROWQ>
-           (smin:VQN
-             (smax:VQN
-               (match_operand:VQN 2 "register_operand" "w")
-               (match_operand:VQN 3 "aarch64_simd_or_scalar_imm_zero"))
-             (match_operand:VQN 4 "aarch64_simd_umax_half_mode")))))]
+         (us_truncate:<VNARROWQ>
+           (smax:VQN
+             (match_operand:VQN 2 "register_operand" "w")
+             (match_operand:VQN 3 "aarch64_simd_or_scalar_imm_zero")))))]
   "TARGET_SIMD && !BYTES_BIG_ENDIAN"
   "sqxtun2\\t%0.<V2ntype>, %2.<Vtype>"
    [(set_attr "type" "neon_sat_shift_imm_narrow_q")]
@@ -6339,12 +6328,10 @@
 (define_insn "aarch64_sqxtun2<mode>_be"
   [(set (match_operand:<VNARROWQ2> 0 "register_operand" "=w")
        (vec_concat:<VNARROWQ2>
-         (truncate:<VNARROWQ>
-           (smin:VQN
-             (smax:VQN
-               (match_operand:VQN 2 "register_operand" "w")
-               (match_operand:VQN 3 "aarch64_simd_or_scalar_imm_zero"))
-             (match_operand:VQN 4 "aarch64_simd_umax_half_mode")))
+         (us_truncate:<VNARROWQ>
+           (smax:VQN
+             (match_operand:VQN 2 "register_operand" "w")
+             (match_operand:VQN 3 "aarch64_simd_or_scalar_imm_zero")))
          (match_operand:<VNARROWQ> 1 "register_operand" "0")))]
   "TARGET_SIMD && BYTES_BIG_ENDIAN"
   "sqxtun2\\t%0.<V2ntype>, %2.<Vtype>"
@@ -6358,14 +6345,12 @@
   "TARGET_SIMD"
   {
     rtx zeros = CONST0_RTX (<MODE>mode);
-    rtx half_umax = aarch64_simd_gen_const_vector_dup (<MODE>mode,
-                       GET_MODE_MASK (GET_MODE_INNER (<VNARROWQ>mode)));
     if (BYTES_BIG_ENDIAN)
       emit_insn (gen_aarch64_sqxtun2<mode>_be (operands[0], operands[1],
-                                              operands[2], zeros, half_umax));
+                                              operands[2], zeros));
     else
       emit_insn (gen_aarch64_sqxtun2<mode>_le (operands[0], operands[1],
-                                              operands[2], zeros, half_umax));
+                                              operands[2], zeros));
     DONE;
   }
 )
@@ -7626,14 +7611,12 @@
 
 (define_insn "*aarch64_sqshrun_n<mode>_insn<vczle><vczbe>"
   [(set (match_operand:<VNARROWQ> 0 "register_operand" "=w")
-       (truncate:<VNARROWQ>
-         (smin:VQN
-           (smax:VQN
-             (ashiftrt:VQN
-               (match_operand:VQN 1 "register_operand" "w")
-               (match_operand:VQN 2 "aarch64_simd_shift_imm_vec_<vn_mode>"))
-             (match_operand:VQN 3 "aarch64_simd_imm_zero"))
-           (match_operand:VQN 4 "aarch64_simd_umax_half_mode"))))]
+       (us_truncate:<VNARROWQ>
+         (smax:VQN
+           (ashiftrt:VQN
+             (match_operand:VQN 1 "register_operand" "w")
+             (match_operand:VQN 2 "aarch64_simd_shift_imm_vec_<vn_mode>"))
+           (match_operand:VQN 3 "aarch64_simd_imm_zero"))))]
   "TARGET_SIMD"
   "sqshrun\t%<vn2>0<Vmntype>, %<v>1<Vmtype>, %2"
   [(set_attr "type" "neon_shift_imm_narrow_q")]
@@ -7669,38 +7652,31 @@
 
 (define_expand "aarch64_sqshrun_n<mode>"
   [(set (match_operand:<VNARROWQ> 0 "register_operand")
-       (truncate:<VNARROWQ>
-         (smin:VQN
-           (smax:VQN
-             (ashiftrt:VQN
-               (match_operand:VQN 1 "register_operand")
-               (match_operand:SI 2 "aarch64_simd_shift_imm_offset_<vn_mode>"))
-             (match_dup 3))
-           (match_dup 4))))]
+       (us_truncate:<VNARROWQ>
+         (smax:VQN
+           (ashiftrt:VQN
+             (match_operand:VQN 1 "register_operand")
+             (match_operand:SI 2 "aarch64_simd_shift_imm_offset_<vn_mode>"))
+           (match_dup 3))))]
   "TARGET_SIMD"
   {
     operands[2] = aarch64_simd_gen_const_vector_dup (<MODE>mode,
                                                 INTVAL (operands[2]));
     operands[3] = CONST0_RTX (<MODE>mode);
-    operands[4]
-      = aarch64_simd_gen_const_vector_dup (<MODE>mode,
-                       GET_MODE_MASK (GET_MODE_INNER (<VNARROWQ>mode)));
   }
 )
 
 (define_insn "*aarch64_sqrshrun_n<mode>_insn<vczle><vczbe>"
   [(set (match_operand:<VNARROWQ> 0 "register_operand" "=w")
-       (truncate:<VNARROWQ>
-         (smin:<V2XWIDE>
-           (smax:<V2XWIDE>
-             (ashiftrt:<V2XWIDE>
-               (plus:<V2XWIDE>
-                 (sign_extend:<V2XWIDE>
-                   (match_operand:VQN 1 "register_operand" "w"))
-                 (match_operand:<V2XWIDE> 3 "aarch64_int_rnd_operand"))
-               (match_operand:VQN 2 "aarch64_simd_shift_imm_vec_<vn_mode>"))
-             (match_operand:<V2XWIDE> 4 "aarch64_simd_imm_zero"))
-           (match_operand:<V2XWIDE> 5 "aarch64_simd_umax_quarter_mode"))))]
+       (us_truncate:<VNARROWQ>
+         (smax:<V2XWIDE>
+           (ashiftrt:<V2XWIDE>
+             (plus:<V2XWIDE>
+               (sign_extend:<V2XWIDE>
+                 (match_operand:VQN 1 "register_operand" "w"))
+               (match_operand:<V2XWIDE> 3 "aarch64_int_rnd_operand"))
+             (match_operand:VQN 2 "aarch64_simd_shift_imm_vec_<vn_mode>"))
+           (match_operand:<V2XWIDE> 4 "aarch64_simd_imm_zero"))))]
   "TARGET_SIMD
    && aarch64_const_vec_rnd_cst_p (operands[3], operands[2])"
   "sqrshrun\t%<vn2>0<Vmntype>, %<v>1<Vmtype>, %2"
@@ -7743,17 +7719,15 @@
 
 (define_expand "aarch64_sqrshrun_n<mode>"
   [(set (match_operand:<VNARROWQ> 0 "register_operand")
-       (truncate:<VNARROWQ>
-         (smin:<V2XWIDE>
-           (smax:<V2XWIDE>
-             (ashiftrt:<V2XWIDE>
-               (plus:<V2XWIDE>
-                 (sign_extend:<V2XWIDE>
-                   (match_operand:VQN 1 "register_operand"))
-                 (match_dup 3))
-               (match_operand:SI 2 "aarch64_simd_shift_imm_offset_<vn_mode>"))
-             (match_dup 4))
-           (match_dup 5))))]
+       (us_truncate:<VNARROWQ>
+         (smax:<V2XWIDE>
+           (ashiftrt:<V2XWIDE>
+             (plus:<V2XWIDE>
+               (sign_extend:<V2XWIDE>
+                 (match_operand:VQN 1 "register_operand"))
+               (match_dup 3))
+             (match_operand:SI 2 "aarch64_simd_shift_imm_offset_<vn_mode>"))
+           (match_dup 4))))]
   "TARGET_SIMD"
   {
     int prec = GET_MODE_UNIT_PRECISION (<V2XWIDE>mode);
@@ -7762,9 +7736,6 @@
     operands[3] = gen_const_vec_duplicate (<V2XWIDE>mode, operands[3]);
     operands[2] = gen_const_vec_duplicate (<MODE>mode, operands[2]);
     operands[4] = CONST0_RTX (<V2XWIDE>mode);
-    operands[5]
-      = gen_int_mode (GET_MODE_MASK (GET_MODE_INNER (<VNARROWQ>mode)), DImode);
-    operands[5] = gen_const_vec_duplicate (<V2XWIDE>mode, operands[5]);
   }
 )
 
@@ -7894,14 +7865,12 @@
   [(set (match_operand:<VNARROWQ2> 0 "register_operand" "=w")
        (vec_concat:<VNARROWQ2>
          (match_operand:<VNARROWQ> 1 "register_operand" "0")
-         (truncate:<VNARROWQ>
-           (smin:VQN
-             (smax:VQN
-               (ashiftrt:VQN
-                 (match_operand:VQN 2 "register_operand" "w")
-                 (match_operand:VQN 3 "aarch64_simd_shift_imm_vec_<vn_mode>"))
-               (match_operand:VQN 4 "aarch64_simd_imm_zero"))
-             (match_operand:VQN 5 "aarch64_simd_umax_half_mode")))))]
+         (us_truncate:<VNARROWQ>
+           (smax:VQN
+             (ashiftrt:VQN
+               (match_operand:VQN 2 "register_operand" "w")
+               (match_operand:VQN 3 "aarch64_simd_shift_imm_vec_<vn_mode>"))
+             (match_operand:VQN 4 "aarch64_simd_imm_zero")))))]
   "TARGET_SIMD && !BYTES_BIG_ENDIAN"
   "sqshrun2\t%<vn2>0.<V2ntype>, %<v>2.<Vtype>, %3"
   [(set_attr "type" "neon_shift_imm_narrow_q")]
@@ -7910,14 +7879,12 @@
 (define_insn "aarch64_sqshrun2_n<mode>_insn_be"
   [(set (match_operand:<VNARROWQ2> 0 "register_operand" "=w")
        (vec_concat:<VNARROWQ2>
-         (truncate:<VNARROWQ>
-           (smin:VQN
-             (smax:VQN
-               (ashiftrt:VQN
-                 (match_operand:VQN 2 "register_operand" "w")
-                 (match_operand:VQN 3 "aarch64_simd_shift_imm_vec_<vn_mode>"))
-               (match_operand:VQN 4 "aarch64_simd_imm_zero"))
-             (match_operand:VQN 5 "aarch64_simd_umax_half_mode")))
+         (us_truncate:<VNARROWQ>
+           (smax:VQN
+             (ashiftrt:VQN
+               (match_operand:VQN 2 "register_operand" "w")
+               (match_operand:VQN 3 "aarch64_simd_shift_imm_vec_<vn_mode>"))
+             (match_operand:VQN 4 "aarch64_simd_imm_zero")))
          (match_operand:<VNARROWQ> 1 "register_operand" "0")))]
   "TARGET_SIMD && BYTES_BIG_ENDIAN"
   "sqshrun2\t%<vn2>0.<V2ntype>, %<v>2.<Vtype>, %3"
@@ -7934,17 +7901,14 @@
     operands[3] = aarch64_simd_gen_const_vector_dup (<MODE>mode,
                                                 INTVAL (operands[3]));
     rtx zeros = CONST0_RTX (<MODE>mode);
-    rtx half_umax
-      = aarch64_simd_gen_const_vector_dup (<MODE>mode,
-                       GET_MODE_MASK (GET_MODE_INNER (<VNARROWQ>mode)));
     if (BYTES_BIG_ENDIAN)
       emit_insn (gen_aarch64_sqshrun2_n<mode>_insn_be (operands[0],
                                operands[1], operands[2], operands[3],
-                               zeros, half_umax));
+                               zeros));
     else
       emit_insn (gen_aarch64_sqshrun2_n<mode>_insn_le (operands[0],
                                operands[1], operands[2], operands[3],
-                               zeros, half_umax));
+                               zeros));
     DONE;
   }
 )
@@ -7953,17 +7917,15 @@
   [(set (match_operand:<VNARROWQ2> 0 "register_operand" "=w")
        (vec_concat:<VNARROWQ2>
          (match_operand:<VNARROWQ> 1 "register_operand" "0")
-         (truncate:<VNARROWQ>
-           (smin:<V2XWIDE>
-             (smax:<V2XWIDE>
-               (ashiftrt:<V2XWIDE>
-                 (plus:<V2XWIDE>
-                   (sign_extend:<V2XWIDE>
-                     (match_operand:VQN 2 "register_operand" "w"))
-                   (match_operand:<V2XWIDE> 4 "aarch64_int_rnd_operand"))
-                 (match_operand:VQN 3 "aarch64_simd_shift_imm_vec_<vn_mode>"))
-               (match_operand:<V2XWIDE> 5 "aarch64_simd_imm_zero"))
-             (match_operand:<V2XWIDE> 6 "aarch64_simd_umax_quarter_mode")))))]
+         (us_truncate:<VNARROWQ>
+           (smax:<V2XWIDE>
+             (ashiftrt:<V2XWIDE>
+               (plus:<V2XWIDE>
+                 (sign_extend:<V2XWIDE>
+                   (match_operand:VQN 2 "register_operand" "w"))
+                 (match_operand:<V2XWIDE> 4 "aarch64_int_rnd_operand"))
+               (match_operand:VQN 3 "aarch64_simd_shift_imm_vec_<vn_mode>"))
+             (match_operand:<V2XWIDE> 5 "aarch64_simd_imm_zero")))))]
   "TARGET_SIMD && !BYTES_BIG_ENDIAN
    && aarch64_const_vec_rnd_cst_p (operands[4], operands[3])"
   "sqrshrun2\t%<vn2>0.<V2ntype>, %<v>2.<Vtype>, %3"
@@ -7973,17 +7935,15 @@
 (define_insn "aarch64_sqrshrun2_n<mode>_insn_be"
   [(set (match_operand:<VNARROWQ2> 0 "register_operand" "=w")
        (vec_concat:<VNARROWQ2>
-         (truncate:<VNARROWQ>
-           (smin:<V2XWIDE>
-             (smax:<V2XWIDE>
-               (ashiftrt:<V2XWIDE>
-                 (plus:<V2XWIDE>
-                   (sign_extend:<V2XWIDE>
-                     (match_operand:VQN 2 "register_operand" "w"))
-                   (match_operand:<V2XWIDE> 4 "aarch64_int_rnd_operand"))
-                 (match_operand:VQN 3 "aarch64_simd_shift_imm_vec_<vn_mode>"))
-               (match_operand:<V2XWIDE> 5 "aarch64_simd_imm_zero"))
-             (match_operand:<V2XWIDE> 6 "aarch64_simd_umax_quarter_mode")))
+         (us_truncate:<VNARROWQ>
+           (smax:<V2XWIDE>
+             (ashiftrt:<V2XWIDE>
+               (plus:<V2XWIDE>
+                 (sign_extend:<V2XWIDE>
+                   (match_operand:VQN 2 "register_operand" "w"))
+                 (match_operand:<V2XWIDE> 4 "aarch64_int_rnd_operand"))
+               (match_operand:VQN 3 "aarch64_simd_shift_imm_vec_<vn_mode>"))
+             (match_operand:<V2XWIDE> 5 "aarch64_simd_imm_zero")))
          (match_operand:<VNARROWQ> 1 "register_operand" "0")))]
   "TARGET_SIMD && BYTES_BIG_ENDIAN
    && aarch64_const_vec_rnd_cst_p (operands[4], operands[3])"
@@ -8003,18 +7963,15 @@
     rtx rnd = immed_wide_int_const (rnd_wi, GET_MODE_INNER (<V2XWIDE>mode));
     rnd = gen_const_vec_duplicate (<V2XWIDE>mode, rnd);
     rtx zero = CONST0_RTX (<V2XWIDE>mode);
-    rtx half_umax
-      = aarch64_simd_gen_const_vector_dup (<V2XWIDE>mode,
-                       GET_MODE_MASK (GET_MODE_INNER (<VNARROWQ>mode)));
     operands[3] = gen_const_vec_duplicate (<MODE>mode, operands[3]);
     if (BYTES_BIG_ENDIAN)
       emit_insn (gen_aarch64_sqrshrun2_n<mode>_insn_be (operands[0],
                                operands[1], operands[2], operands[3], rnd,
-                               zero, half_umax));
+                               zero));
     else
       emit_insn (gen_aarch64_sqrshrun2_n<mode>_insn_le (operands[0],
                                operands[1], operands[2], operands[3], rnd,
-                               zero, half_umax));
+                               zero));
     DONE;
   }
 )
diff --git a/gcc/config/aarch64/predicates.md b/gcc/config/aarch64/predicates.md
index 6f4d1dac6bf9..523974240f03 100644
--- a/gcc/config/aarch64/predicates.md
+++ b/gcc/config/aarch64/predicates.md
@@ -744,21 +744,6 @@
                        GET_MODE_UNIT_BITSIZE (GET_MODE (op)) / 2,
                        GET_MODE_UNIT_BITSIZE (GET_MODE (op)) / 2)")))
 
-(define_predicate "aarch64_simd_umax_half_mode"
-  (and (match_code "const_vector")
-       (match_test "aarch64_const_vec_all_same_in_range_p (op,
-                               (HOST_WIDE_INT_1U
-                               << (GET_MODE_UNIT_BITSIZE (mode) / 2)) - 1,
-                               (HOST_WIDE_INT_1U
-                               << (GET_MODE_UNIT_BITSIZE (mode) / 2)) - 1)")))
-
-(define_predicate "aarch64_simd_umax_quarter_mode"
-  (and (match_code "const_vector")
-       (match_test "aarch64_const_vec_all_same_in_range_p (op,
-                               (HOST_WIDE_INT_1U
-                               << (GET_MODE_UNIT_BITSIZE (mode) / 4)) - 1,
-                               (HOST_WIDE_INT_1U
-                               << (GET_MODE_UNIT_BITSIZE (mode) / 4)) - 1)")))
 (define_predicate "aarch64_simd_shift_imm_vec_qi"
   (and (match_code "const_vector")
        (match_test "aarch64_const_vec_all_same_in_range_p (op, 1, 8)")))
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 000000000000..5efe52e80bbb
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/vect-sat-trunc-3.c
@@ -0,0 +1,41 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=armv8-a" } */
+/* { dg-additional-options "-fno-schedule-insns -fno-schedule-insns2" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+typedef __UINT16_TYPE__ u16;
+
+static inline u16
+clip_u16 (int x)
+{
+  return (unsigned int) x > 65535u ? ((-x) >> 31) : x;
+}
+
+/*
+** clu:
+**     ...
+**     ldp     q[0-9]+, q[0-9]+, \[x[0-9]+\]
+**     orr     v[0-9]+\.4s, #1
+**     sqxtun  v[0-9]+\.4h, v[0-9]+\.4s
+**     orr     v[0-9]+\.4s, #1
+**     sqxtun  v[0-9]+\.4h, v[0-9]+\.4s
+**     stp     d[0-9]+, d[0-9]+, \[x[0-9]+\]
+**     ret
+*/
+void
+clu (u16 *__restrict r, const int *__restrict x)
+{
+  for (int i = 0; i < 8; i++)
+    r[i] = clip_u16 (x[i] | 1);
+}
+
+/* The same in a variable-length loop.  */
+void
+clu_n (u16 *__restrict r, const int *__restrict x, int n)
+{
+  for (int i = 0; i < n; i++)
+    r[i] = clip_u16 (x[i] | 1);
+}
+
+/* { dg-final { scan-assembler-times {\tsqxtun\tv[0-9]+\.4h, v[0-9]+\.4s} 3 } 
} */
+/* { dg-final { scan-assembler-not {\tuqxtn\tv[0-9]+\.4h, v[0-9]+\.4s} } } */

Reply via email to