[gcc r17-2916] [PATCH] match: Simplify `(A | C) == A` to `(A & C) != 0` when C is power of 2 [PR101650]
Jeff Law via Gcc-cvs <[email protected]> Tue, 4 Aug 2026 03:48:43 +0000 (GMT)
| Newsgroups | gmane.comp.gcc.cvs |
|---|---|
| Message-ID | <[email protected]> |
https://gcc.gnu.org/g:372d44c5611ecce9144c985a849ca06f108289fe commit r17-2916-g372d44c5611ecce9144c985a849ca06f108289fe Author: Avinal Kumar <[email protected]> Date: Mon Aug 3 21:48:01 2026 -0600 [PATCH] match: Simplify `(A | C) == A` to `(A & C) != 0` when C is power of 2 [PR101650] The expression (A | C) == A tests if all the bits in C are already set in A. When C is a power of 2, this is equivalent to (A & C) != 0 which avoids OR and compares against 0 instead of original value thus optimizing the comparison. Similarly (A | C) != A can be optimized to (A & C) == 0. --- Bootstrapped and ran full test suite on x86_64 Fedora Linux. Output for this particular patch test: cat gcc/testsuite/gcc/gcc.sum | grep bitcmp-7 PASS: gcc.dg/tree-ssa/bitcmp-7.c (test for excess errors) PASS: gcc.dg/tree-ssa/bitcmp-7.c scan-tree-dump-not optimized "\\| 4" PASS: gcc.dg/tree-ssa/bitcmp-7.c scan-tree-dump-times optimized " & 4" 2 I also included some whitespace changes in some comments. Please let me know if they should be a separate change. PR tree-optimization/101650 gcc/ChangeLog: * match.pd: Simplify (A | C) == A to (A & C) != 0 when C is power of 2. gcc/testsuite/ChangeLog: * gcc.dg/tree-ssa/bitcmp-7.c: New test. Signed-off-by: Avinal Kumar <[email protected]> Diff: --- gcc/match.pd | 20 ++++++++++++++------ gcc/testsuite/gcc.dg/tree-ssa/bitcmp-7.c | 20 ++++++++++++++++++++ 2 files changed, 34 insertions(+), 6 deletions(-) diff --git a/gcc/match.pd b/gcc/match.pd index 8700541fc3f3..293650760e27 100644 --- a/gcc/match.pd +++ b/gcc/match.pd @@ -583,7 +583,7 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) (div @0 integer_minus_onep@1) (if (!TYPE_UNSIGNED (type)) (negate @0))) - /* X / bool_range_Y is X. */ + /* X / bool_range_Y is X. */ (simplify (div @0 SSA_NAME@1) (if (INTEGRAL_TYPE_P (type) @@ -2630,7 +2630,7 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) && canonicalize_math_after_vectorization_p ()) (cond @0 @3 @5)))) - /* Vector Fold (((a < b) & c) | ((a >= b) & d)) into a < b ? c : d. + /* Vector Fold (((a < b) & c) | ((a >= b) & d)) into a < b ? c : d. and ((~(a < b) & c) | (~(a >= b) & d)) into a < b ? c : d. */ (simplify (bit_ior @@ -4787,7 +4787,7 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) (cmp @0 @2))))) /* X <= MAX(X, Y) -> true - X > MAX(X, Y) -> false + X > MAX(X, Y) -> false X >= MIN(X, Y) -> true X < MIN(X, Y) -> false */ (for minmax (min min max max ) @@ -6042,7 +6042,7 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) (convert (convert:unsigned_char_type_node @0)) (convert (convert:signed_char_type_node @0))) (if (bits < prec && bits + 8 > prec) - (with + (with { tree nst = build_int_cst (integer_type_node, bits & 7); tree bt = TYPE_UNSIGNED (st) ? unsigned_char_type_node @@ -8256,6 +8256,14 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) (cmp (bit_and@2 @0 integer_pow2p@1) @1) (icmp @2 { build_zero_cst (TREE_TYPE (@0)); }))) +/* If we have (A | C) == A where C is a power of 2, convert this into + (A & C) != 0. Similarly for NE_EXPR. */ +(for cmp (eq ne) + icmp (ne eq) + (simplify + (cmp:c (bit_ior @0 integer_pow2p@1) @0) + (icmp (bit_and @0 @1) { build_zero_cst (TREE_TYPE (@0)); }))) + (for cmp (ge lt) /* x < 0 ? ~y : y into (x >> (prec-1)) ^ y. */ /* x >= 0 ? ~y : y into ~((x >> (prec-1)) ^ y). */ @@ -10698,7 +10706,7 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) (simplify (popcount (convert?@0 (rot:s@1 @2 @3))) (if (INTEGRAL_TYPE_P (TREE_TYPE (@0)) - && INTEGRAL_TYPE_P (TREE_TYPE (@1)) + && INTEGRAL_TYPE_P (TREE_TYPE (@1)) && (GIMPLE || !TREE_SIDE_EFFECTS (@3))) (with { tree type0 = TREE_TYPE (@0); tree type1 = TREE_TYPE (@1); @@ -12319,7 +12327,7 @@ and, (cond (le @0 @1) @0 (bit_and @0 @1)))))) /* -x & 1 -> x & 1. */ -(simplify +(simplify (bit_and (negate @0) integer_onep@1) (if (!TYPE_OVERFLOW_SANITIZED (type)) (bit_and @0 @1))) diff --git a/gcc/testsuite/gcc.dg/tree-ssa/bitcmp-7.c b/gcc/testsuite/gcc.dg/tree-ssa/bitcmp-7.c new file mode 100644 index 000000000000..ab15be6b1a18 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/bitcmp-7.c @@ -0,0 +1,20 @@ +/* PR tree-optimization/101650 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ + +/* (A | C) == A should become (A & C) != 0 when C is a power of 2. */ +_Bool f_ior_eq(unsigned len) { + const unsigned N = 4; + unsigned newlen = len | N; + return newlen == len; +} + +/* (A | C) != A should become (A & C) == 0 when C is a power of 2. */ +_Bool f_ior_ne(unsigned len) { + const unsigned N = 4; + unsigned newlen = len | N; + return newlen != len; +} + +/* { dg-final { scan-tree-dump-not "\\| 4" "optimized" } } */ +/* { dg-final { scan-tree-dump-times " & 4" 2 "optimized" } } */