On 9/23/26 4:14 AM, Dominic P wrote:
(x ^ CST) - CST and "bit N-1 of x set ? x - 2^N : x", CST being bit N-1,
are sign_extend<N> (x) when x has no bit above N - 1 set.  PR125405's
rule needs an explicit (x & M) in the IL, so neither spelling reaches it
when the range comes from x's type instead.

The xor constant must be positive in the xor's own type, or the convert
sign-extends and the fold loses a - 2^N.  A width with no integer mode
narrows to a signed _BitInt, so large _BitInt operands fold before
lowering.  The cond rule fires in phiopt through
match_simplify_replacement and costs one convert.  Vectors decline on
INTEGRAL_TYPE_P (type); a ternary with an outer conversion on the arms
and the unsigned-compare spelling are not handled.  All 25 relative-
branch sites in PiTubeDirect's 6502 interpreter fold: -28 branches and
-328 B in M6502_run, LTO image.

Bootstrapped and regression tested on x86_64-pc-linux-gnu.

Assisted-by: Claude Opus 5 (Anthropic)
Signed-off-by: Dominic P <[email protected]>

gcc/ChangeLog:

        * match.pd (`(x ^ CST) - CST`): New pattern.
        (`(signed:N) x < 0 ? (T) x - CST : (T) x`): New pattern.

gcc/testsuite/ChangeLog:

        * gcc.dg/tree-ssa/sext-xor-1.c: New test.
        * gcc.dg/tree-ssa/sext-xor-2.c: New test.
        * gcc.dg/tree-ssa/sext-cond-1.c: New test.
        * gcc.dg/tree-ssa/sext-cond-2.c: New test.
        * gcc.dg/tree-ssa/sext-bitint-1.c: New test.
        * gcc.dg/tree-ssa/sext-vector-1.c: New test.
        * gcc.dg/torture/sext-idiom-1.c: New test.
        * gcc.target/arm/sext-idiom-1.c: New test.
---
Changes in v2, all from Andrea Pinski's review of v1:
  - comments name the constant: "(x ^ CST) - CST -> sign_extend<N> (x)
    where CST is (1 << (N - 1))", and the same form on the cond rule.
  - match integer_pow2p@1 rather than INTEGER_CST@1, so the power-of-two
    requirement is visible; the now-redundant "width > 0" is gone.
  - a width the target does no arithmetic in is narrowed to a signed
    _BitInt instead of being refused, so _BitInt(256) at N = 128 and at
    N = 191 now fold on a 32- as well as a 64-bit host.  Using the _BitInt
    type is what fixes it: the v1 ICE was gimple-lower-bitint's handle_cast
    on a cast to a plain 128-bit integer type, which arm gives TImode.
  - type_has_mode_precision_p is kept only on the plain-integer arm, where
    it rejects a width with no mode (48 in a 64-bit type); on the _BitInt
    arm it never fired, so it is gone.
  - wi::shifted_mask (0, k, true, prec) replaces -wi::set_bit_in_zero (k,
    prec) in both rules.
  - the cond rule checks !TYPE_UNSIGNED on the compared type.
OK.  I'll note you include an ARM test, but no indication the patch was tested on ARM.  I'll assume it's going to do the right thing.

jeff

Reply via email to