On 9/16/26 9:16 AM, [email protected] wrote:
From: Kyrylo Tkachov <[email protected]>

An arithmetic right shift preserves its input sign.  The range test and
conversion can therefore use the shifted value while the saturation value
uses the original input:

   shifted = x >> 8;
   range = (unsigned int) shifted + 32768;
   out = range > 65535
         ? (short int) (x >> 31) ^ 32767 : (short int) shifted;

This is equivalent to .SAT_TRUNC (shifted).  Recognize a
precision-minus-one sign shift and allow the saturation value to use the
original input sign.  The sign shift produces zero or minus one, so its
optional signed conversion can narrow or extend the value exactly.

Require the data shift to be a constant smaller than the input precision.
Require the range type to be at least as wide as the shifted value and the
output type, so the conversion and clamp constants do not lose bits.

With AArch64 -O2 -march=armv8-a -fopenmp-simd:

before:

         ldp     d0, d30, [x1]
         movi    v27.2s, 0x80, lsl 8
         movi    v25.2s, 0xff, msl 8
         mvni    v31.4h, 0x80, lsl 8
         sshr    v29.2s, v0.2s, 8
         sshr    v28.2s, v30.2s, 8
         cmlt    v0.2s, v0.2s, #0
         cmlt    v30.2s, v30.2s, #0
         add     v26.2s, v29.2s, v27.2s
         add     v27.2s, v28.2s, v27.2s
         uzp1    v30.4h, v0.4h, v30.4h
         uzp1    v28.4h, v29.4h, v28.4h
         cmhi    v26.2s, v26.2s, v25.2s
         cmhi    v27.2s, v27.2s, v25.2s
         eor     v31.8b, v30.8b, v31.8b
         uzp1    v27.4h, v26.4h, v27.4h
         bit     v28.8b, v31.8b, v27.8b
         str     d28, [x0]
         ret

after:

         ldr     q31, [x1]
         sqshrn  v31.4h, v31.4s, 8
         str     d31, [x0]
         ret

The vector sequence becomes one SQSHRN.  Runtime tests cover valid and
wrapping forms.  Target tests cover valid forms, rejected forms, and the
related signed saturating addition and subtraction forms.

Bootstrapped and tested on aarch64-none-linux-gnu.
Tested on x86_64-pc-linux-gnu.

Ok for trunk?

Changes since v3:
- Rebase on current trunk.

gcc/ChangeLog:

        * match-sat-alu.pd (signed_integer_sat_val): Recognize an arithmetic
        sign shift.
        (signed_integer_sat_trunc): Use signed_integer_sat_val in the existing
        form.  Recognize a shifted value with an equivalent pre-shift sign
        source.

gcc/testsuite/ChangeLog:

        * gcc.dg/vect/vect-sat-trunc-shift-sign-source-1.c: New test.
        * gcc.target/aarch64/sat_s_val_ashr-1.c: Likewise.
        * gcc.target/aarch64/vect-sat-trunc-shift-sign-source-1.c: Likewise.
        * gcc.target/aarch64/vect-sat-trunc-shift-sign-source-negative-1.c:
        Likewise.

Signed-off-by: Kyrylo Tkachov <[email protected]>
OK.  This is starting to get fairly hard to read.  But I think this and patch #2 of the series are the worst (which is why they're getting reviewed last).  Don't be afraid of comments in the conditionals themselves -- they speak to intent and ease the burden on any future reader.

Jeff




Reply via email to