On 9/16/26 9:16 AM, [email protected] wrote:
From: Kyrylo Tkachov <[email protected]> Unsigned saturating truncation can form its sign mask from ~X instead of -X. This avoids negating the minimum signed value. For negative X, ~X is nonnegative and its top-bit shift is zero. For positive X above the result range, ~X is negative and its top-bit shift is all ones. Recognize this form. Keep the unsigned range comparison because a signed comparison does not clamp negative inputs. With AArch64 -O2 -march=armv8-a -fopenmp-simd: before: complement_clip4: ldr q31, [x1] movi v30.4s, 0xff, msl 8 not v29.16b, v31.16b cmhi v30.4s, v31.4s, v30.4s cmlt v29.4s, v29.4s, #0 bif v29.16b, v31.16b, v30.16b xtn v29.4h, v29.4s str d29, [x0] ret after: complement_clip4: ldr q31, [x1] movi v30.4s, 0 smax v30.4s, v31.4s, v30.4s uqxtn v30.4h, v30.4s str d30, [x0] ret Tests cover both widths, extrema, bounds, LTO, and a signed-comparison counterexample. The AArch64 test covers both valid forms. Bootstrapped and tested on aarch64-none-linux-gnu. Ok for trunk? Changes since v3: - Rebase after the constant-clamp matcher changes. gcc/ChangeLog: * match-sat-alu.pd (unsigned_integer_narrow_clip): Add the complement form. gcc/testsuite/ChangeLog: * gcc.dg/sat-trunc-signed-cmp-2.c: New test. * gcc.dg/vect/vect-sat-trunc-complement-1.c: Likewise. * gcc.target/aarch64/vect-sat-trunc-complement-1.c: Likewise.
OK jeff
