match.pd: Simplify (~A & 1) == (~B & 1) at -O1 [PR112533]

At -O1, GCC lowers (~a & 1) == (~b & 1) into two different GIMPLE
forms depending on whether the boolean values come from a function
return boundary or an inline expression:

  1. Via function return (e.g. inlined is_even), GCC preserves the
     eq/ne form because the function boundary hides the internal
     structure from the gimplifier:
       ((a&1)==0) == ((b&1)==0)   outer node is eq/ne

  2. Via inline expression (directly written), GCC sees the full
     boolean expression tree at once and folds to bit_xor during
     gimplification:
       ((a&1)!=0) ^ ((b&1)==0)   outer node is bit_xor

Add a generalized match.pd rule handling:
  1. ((x & c) == 0) OP ((y & c) == 0)
  2. ((x & c) != 0) OP ((y & c) == 0)

for OP in { ==, !=, ^ } and pow2 masks.

Fold these directly into the canonical xor-mask form:
  ((x ^ y) & c) == 0
  ((x ^ y) & c) != 0

Bootstrapped and tested on aarch64-linux-gnu with
RUNTESTFLAGS="tree-ssa.exp".

Changes since v1:
* v5: Add :s to the inner comparisons and bit_and expressions.
      Simplify the innersame check to compare icmp0 and icmp1
      directly.

* v4: Removed the ((x & c) == 0) OP (y & c) simplify rule and
      mark the corresponding test case as XFAIL.

* v3: Collapse both previous simplify rules into one generalized
      matcher covering all combinations of outer {eq, ne, bit_xor}
      and inner {eq, ne} comparisons.
      Add missing mixed-polarity test cases.

* v2: Generalize mask from integer_onep to integer_pow2p.
      Combine both patterns into single one.
      Split test into bool-eq-evenness.c, bool-eq-bitxor.c,
      bool-eq-pow2.c.

	PR tree-optimization/112533

gcc/ChangeLog:
	* match.pd: Canonicalize boolean comparisons of masked pow2
	bits into xor-mask tests.

gcc/testsuite/ChangeLog:
	* gcc.dg/tree-ssa/bool-eq-bitxor.c: New test.
	* gcc.dg/tree-ssa/bool-eq-evenness.c: New test.
	* gcc.dg/tree-ssa/bool-eq-pow2.c: New test.

Signed-off-by: Shivam Gupta <shivam98.tkg@gmail.com>
4 files changed