https://gcc.gnu.org/bugzilla/show_bug.cgi?id=126490

--- Comment #5 from GCC Commits <cvs-commit at gcc dot gnu.org> ---
The releases/gcc-15 branch has been updated by Jakub Jelinek
<[email protected]>:

https://gcc.gnu.org/g:64c1725f5632f9f58938382e931f0dedbede35e8

commit r15-11444-g64c1725f5632f9f58938382e931f0dedbede35e8
Author: Jakub Jelinek <[email protected]>
Date:   Fri Jul 31 09:03:05 2026 +0200

    match.pd: Fix (a & b) == (a ^ b) -> !(a | b) simplification [PR126490]

    The following testcase is miscompiled.
    We have 2 different simplifications
    (a & b) ^ (a == b) -> !(a | b)
    (a & b) == (a ^ b) -> !(a | b)
    where both a and b are truth_valued_p.  That doesn't mean they have
    boolean type, it means that either they have integral type with one bit
    precision (boolean, unsigned or signed) or they are result of comparisons
    etc.
    Now, because both a and b appear as operands of the same &, they
necessarily
    have the same or uselessly compatible type.  For the first case, the a == b
    comparison necessarily has to have the same type too and so type is the
same
    type as well.
    For the second case that is not the case, e.g. in the problematic
    testcase both a and b are unsigned _BitInt(1) while == has int type, but
    it could very well be also that a and b are results of comparisons etc.
    and have int type.
    Now, the comment properly uses ! for the replacement, but the replacement
    of the simplification actually uses bit_not, so ~.  ~ is fine for 1-bit
    precision, but not for wider ones.
    The following patch differentiates between the case when a and b have
    1-bit precision type, then it ensures ~ is done in that type and only
    then it is converted to type, while for other cases it does ^ 1 instead.

    2026-07-31  Jakub Jelinek  <[email protected]>

            PR tree-optimization/126490
            * match.pd ((a & b) == (a ^ b) -> !(a | b)): If @0 has
            integral one bit precision type, use (convert:type ...) around the
            bit_not just in case the comparison has a different result type
            from the type of its operands.  Otherwise do that too but with
            bit_not replaced with bit_xor with one of the appropriate type.

            * gcc.dg/torture/bitint-104.c: New test.

    Reviewed-by: Richard Biener <[email protected]>
    (cherry picked from commit a7a444ddd1eb51d755d613e5cc413548f6574b53)

Reply via email to