On Wed, Oct 14, 2026 at 7:40 PM Jeff Law <[email protected]> wrote:
>
>
>
> On 8/31/26 2:56 AM, Avinal Kumar wrote:
> > The pattern that folds (X >> C1) & C2 and (X << C1) & C2 was limited
> > to types with precision <= HOST_BITS_PER_WIDE_INT because it used
> > unsigned HOST_WIDE_INT for mask and zerobits arithmetic. This prevents
> > the optimization from firing on __int128 and wider types at the GIMPLE
> > level.
> >
> > Convert the pattern to use wide_int and remove the TYPE_PRECISION guard.
> > Replace the mode-mask loop with wi::exact_log2 (newmask + 1) to check
> > whether newmask is (2^n - 1) for a power-of-two n >= BITS_PER_UNIT.
> > Handle the case where newmask is all-ones at full type precision
> > separately, since newmask + 1 overflows to zero in that case.
> >
> > PR120524
> > PR tree-optimization/120524
> >
> > gcc/ChangeLog:
> >
> > * match.pd: Use wide_int for shift-and-mask folding [PR120524]
> >
> > gcc/testsuite/ChangeLog:
> >
> > * gcc.dg/tree-ssa/pr120524.c: New test.
> >
> > Signed-off-by: Avinal Kumar <[email protected]>
> No concerns with the match.pd change. It looks like a straightforward
> conversion to wi:: While there are things that could perhaps be
> considered "better" by using the operators provided by wi:: rather than
> explicit method calls, those are purely style preferences.
Sure, I can look into operators.
> > +
> > +/* Verify the left shift path of the same pattern also works for 128-bit
> > + types. The mask isolates only the shifted bits, so the redundant lower
> > + bits can be folded into the mask. */
> > +__int128 f3(__int128 a) { return (a << 120) & ((__int128)0xff << 120); }
> > +
> > +/* f1, f2: arithmetic right shifts should be converted to logical shifts.
> > */
> > +/* { dg-final { scan-tree-dump "uint128_t" "optimized" } } */
> > +
> > +/* Verify 64-bit case also works, this is folded by C frontend putting it
> > + here as regression guard. */
> > +long long f4(long long a) { return (a >> 63) & 1; }
> > +
> > +/* All BIT_AND masks should be folded away. */
> > +/* { dg-final { scan-tree-dump-not "& 1" "optimized" } } */
> > +/* { dg-final { scan-tree-dump-not "& 255" "optimized" } } */
> The test seems a bit weak. f1 and f2 both generate a AND expression in
> the .optimized dump without your patch. So you can correctly infer your
> optimization fired for those. However f3/f4 do not seem to be covered
> as I don't see any AND expressions in their .optimized dump without your
> patch. Finding a way to verify the f3/f4 cases seems like the only
> blocking issue.
>
Good catch, I included f4 as regression guard but I guess it wasn't
useful. So I looked into it and here are some options:
1. I can check explicitly for optimized forms, something like:
- for f3: "... 120" "optimized" // shift with no AND
- for f4: ">> 63" "optimized" // confirm the shift survived
or
2. find more mask widening cases and replace f3 and f4 with that
or
3. Just drop f3 and f4 as the required case is covered with f1 and f2.
Please advise which one is more desirable. Thank you.