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]>

Reply via email to