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

A signed value clamped to the range of a narrower unsigned type is unsigned
saturating truncation.  Recognize nested MIN and MAX operations in either
order.

Keep the clamp match independent of use count.  At this use, require an exact
zero lower bound, the maximum upper bound, and one use of the outer clamp.
The inner clamp can have other uses.

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

before:

clamp_u16_4:
        ldr     q0, [x1]
        movi    v30.4s, 0xff, msl 8
        movi    v31.4s, 0
        smin    v30.4s, v0.4s, v30.4s
        smax    v30.4s, v30.4s, v31.4s
        xtn     v30.4h, v30.4s
        str     d30, [x0]
        ret

after:

clamp_u16_4:
        ldr     q31, [x1]
        movi    v30.4s, 0
        smax    v30.4s, v31.4s, v30.4s
        uqxtn   v30.4h, v30.4s
        str     d30, [x0]
        ret

Runtime tests cover both clamp orders, two widths, and LTO.  Target tests
cover valid bounds, invalid bounds, and extra uses of each clamp.

Bootstrapped and tested on aarch64-none-linux-gnu.

Ok for trunk?

Changes since v3:
- Make the clamp match independent of use count.
- Check the outer clamp use at the consumer.
- Match the zero bound with integer_zerop.

gcc/ChangeLog:

        * match-sat-alu.pd (integer_constant_clamp): New match.
        (unsigned_integer_narrow_clip): Add the constant-clamp form.

gcc/testsuite/ChangeLog:

        * gcc.dg/vect/vect-sat-trunc-clamp-1.c: New test.
        * gcc.target/aarch64/vect-sat-trunc-clamp-inner-use-1.c: Likewise.
        * gcc.target/aarch64/vect-sat-trunc-clamp-multi-use-1.c: Likewise.
        * gcc.target/aarch64/vect-sat-trunc-clamp-u-1.c: Likewise.
        * gcc.target/aarch64/vect-sat-trunc-clamp-u-negative-1.c: Likewise.

Signed-off-by: Kyrylo Tkachov <[email protected]>
OK
jeff

Reply via email to