https://gcc.gnu.org/bugzilla/show_bug.cgi?id=126981
--- Comment #4 from GCC Commits <cvs-commit at gcc dot gnu.org> --- The master branch has been updated by Kyrylo Tkachov <[email protected]>: https://gcc.gnu.org/g:9e1c435c70a2ad4ca5285307b4a760f92c7a3426 commit r17-3899-g9e1c435c70a2ad4ca5285307b4a760f92c7a3426 Author: Kyrylo Tkachov <[email protected]> Date: Thu Sep 3 15:44:32 2026 +0200 aarch64: Use SVE2 SQXTNB and UQXTNB for saturating truncation vect_recog_sat_trunc_pattern forms .SAT_TRUNC only when the target has an sstrunc or ustrunc optab for the mode pair it selected. SVE2 has SQXTNB and UQXTNB, but only exposes them through unspecs for the ACLE, so a saturating truncation is vectorized as a minimum, or a minimum and a maximum, feeding a truncating store. The bottom forms write each result into the low half of its source element, which is where the element of the unpacked result mode lives. That holds when the source is itself unpacked, since the bits above each source element are then don't-care on both sides. Extend VNARROWQ and Vnarrowq to the SVE modes whose elements halve without changing the number of lanes, and provide the two optabs over SVE_HSDI. The unpacked source modes come out of that for free. For void f (int8_t *__restrict d, const int16_t *__restrict s, int n) { for (int i = 0; i < n; ++i) { int16_t x = s[i]; int8_t t = (int8_t) x; d[i] = -128 <= x && x <= 127 ? t : x < 0 ? -128 : 127; } } the inner loop changes from ld1h z31.h, p7/z, [x1, x3, lsl 1] smin z31.h, z31.h, #127 smax z31.h, z31.h, #-128 st1b z31.h, p7, [x0, x3] to ld1h z31.h, p7/z, [x1, x3, lsl 1] sqxtnb z31.b, z31.h st1b z31.h, p7, [x0, x3] This also makes the NARROW_CLIP form of .SAT_TRUNC reachable on aarch64, so add a runtime test for the PR tree-optimization/126981 fix on top of the target independent one. Bootstrapped and tested on aarch64-none-linux-gnu. gcc/ChangeLog: * config/aarch64/iterators.md (VNARROWQ, Vnarrowq): Add the SVE modes whose elements halve without changing the number of lanes. (Ventype): Add the unpacked SVE modes. * config/aarch64/aarch64-sve2.md (<sat_trunc_op>trunc<mode><Vnarrowq>2): New pattern. gcc/testsuite/ChangeLog: * gcc.target/aarch64/sve2/vect-sat-trunc-1.c: New test. * gcc.target/aarch64/sve2/vect-sat-trunc-1_run.c: Likewise. * gcc.target/aarch64/sve2/vect-sat-trunc-2.c: Likewise. * gcc.target/aarch64/sve2/vect-sat-trunc-2_run.c: Likewise. * gcc.target/aarch64/sve2/vect-sat-trunc-clip-1_run.c: Likewise. Signed-off-by: Kyrylo Tkachov <[email protected]>
