On 6/29/2026 12:14 AM, liuhongt wrote:
When op1's range is [N, N + 1] and one of N or N + 1 is a power of
two, split a TRUNC_DIV_EXPR into two divisions by constants selected
by a compare:

   op0 / op1  ->  op1 == N ? op0 / N : op0 / (N + 1)

Each arm divides by a constant, so expansion strength-reduces it (a
shift on the power-of-two arm) and the divide instruction is avoided.

This grows code, so gate it on optimize_bb_for_speed_p.

Bootstrapped and regtested on x86_64-pc-linux-gnu{-m32,}.
Ok for trunk?

        PR middle-end/125708

gcc/ChangeLog:

        * vr-values.cc
        (simplify_using_ranges::simplify_div_or_mod_using_ranges):
        Compute op1's upper bound for all codes and add the
        near-power-of-two TRUNC_DIV_EXPR split, guarded on
        optimize_bb_for_speed_p.

gcc/testsuite/ChangeLog:

        * gcc.dg/tree-ssa/pr125708-1.c: New test.
        * gcc.target/i386/pr125708-2.c: New test.
Note that you're introducing a conditional branch into the mix as well.  If it's a poorly predicted branch, then you could end up burning more cycles on the branch mispredict than the division would have taken.

I'd kind of want to get a better sense of whether or not we're actually making an improvement here.

If we're selecting across 1/2 for the divisor and the dividend is a suitable type, then this really becomes a conditional right shift by 1, right?  That seems likely to have a generally profitable synthesis.  But an arbitary n, n+1 where one of them is a power of two isn't as obvious to me.

jeff

Reply via email to