Re: [PATCH] match: Simplify `(A | C) == A` to `(A & C) != 0` when C is power of 2 [PR101650]
Jeffrey Law <[email protected]> Mon, 3 Aug 2026 21:50:38 -0600
| Newsgroups | gmane.comp.gcc.patches |
|---|---|
| Message-ID | <[email protected]> |
On 7/29/2026 9:21 AM, Avinal Kumar wrote: > On Wed, Jul 29, 2026 at 6:38 PM Jeffrey Law > <[email protected]> wrote: >>> I also included some whitespace changes in some comments. Please let me know >>> if they should be a separate change. >> In general formatting fixes should be distinct changes unless they're >> directly in the space you're working. These cases touch independent >> patterns so an independent patch would be better. This policy is mostly >> to make it easier to review by avoiding unnecessary diffs. It's also >> the case that many formatting changes can go in without review under our >> trivial/obvious guidelines. But I don't think it's worth splitting >> these out this time. This is mostly a note for future contributions. > Understood, I will keep that in mind. Thanks > >> It would initially seem this is redundant with this pattern earlier in >> match.pd: >> >> |/* (X | Y) == Y becomes (X & ~Y) == 0. */ (simplify (cmp:c (bit_ior:c >> @0 @1) @1) (cmp (bit_and @0 (bit_not! @1)) { build_zero_cst (TREE_TYPE >> (@0)); }))| >> >> >> So the main question/concern I have is why didn't the existing earlier >> rule in match.pd fire? Presumably the "!" modifier on the bit_not is >> rejecting the rewritten pattern? >> >> Overall it looks good, I just want to make sure we're not utilizing the >> more general pattern for a good reason. >> >> jeff > The existing rule does not fire for this case. Consider these examples: > > _Bool f1(unsigned len) { > unsigned newlen = len | 4; > return newlen == len; > } > > _Bool f2(unsigned len) { > return (len | 5) == 5; > } > > _Bool f3(unsigned x, unsigned y){ > return (x | y) == y; > } > > _Bool f4(unsigned x, unsigned y){ > return (x | ~y) == ~y; > } > > The capture bind @1 to whatever appears on the both side of the > comparision. The replacemnet in the existing rule needs bit_not! @1, > so a match is rejected unless ~@1 simplifies. For constant (5 as in > f2) or already negated value (~y as in f4) the rule fires. But fails > when @1 is a plain variable. > > Removing ! would produce (4 & ~len) == 0 in f1, this is 3 ops. The new > pattern produces (len & 4) == 0, which avoids NOT entirely. > > I would also note that the comment in the existing rule may be > slightly misleading, since readers will expect every form of (X | Y) > == Y to become (X & ~Y) == 0, which is not the case. I can put the > clarification as a follow-up. Thanks. I think we're OK. I somehow kept zeroing in on the constant simplifying. But in the case where the term on both sides of the test is an SSA_NAME and the constant is 2^n, then we can rewrite into the form you're doing without needing any simplification to occur. I've pushed this to the trunk. jeff