From f5f1838435400b837c8677c53a611e2dc6d56442 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Wed, 12 May 2021 09:46:03 +0200 Subject: [PATCH] match.pd: Optimize (x & y) == x into (x & ~y) == 0 [PR94589] > Somewhere in RTL (_M_value&1)==_M_value is turned into (_M_value&-2)==0, > that could be worth doing already in GIMPLE. Apparently it is /* Simplify eq/ne (and/ior x y) x/y) for targets with a BICS instruction or constant folding if x/y is a constant. */ if ((code == EQ || code == NE) && (op0code == AND || op0code == IOR) && !side_effects_p (op1) && op1 != CONST0_RTX (cmp_mode)) { /* Both (eq/ne (and x y) x) and (eq/ne (ior x y) y) simplify to (eq/ne (and (not y) x) 0). */ ... /* Both (eq/ne (and x y) y) and (eq/ne (ior x y) x) simplify to (eq/ne (and (not x) y) 0). */ Yes, doing that on GIMPLE for the case where the not argument is constant would simplify the phiopt follow-up (it would be single imm use then). On Thu, May 06, 2021 at 09:42:41PM +0200, Marc Glisse wrote: > We can probably do it in 2 steps, first something like > > (for cmp (eq ne) > (simplify > (cmp (bit_and:c @0 @1) @0) > (cmp (@0 (bit_not! @1)) { build_zero_cst (TREE_TYPE (@0)); }))) > > to get rid of the double use, and then simplify X&C==0 to X<=~C if C is a > mask 111...000 (I thought we already had a function to detect such masks, or > the 000...111, but I can't find them anymore). Ok, here is the first step then. 2021-05-12 Jakub Jelinek Marc Glisse PR tree-optimization/94589 * match.pd ((X & Y) == X -> (X & ~Y) == 0, (X | Y) == Y -> (X & ~Y) == 0): New GIMPLE simplifications. * gcc.dg/tree-ssa/pr94589-1.c: New test. --- gcc/match.pd | 12 ++++++++++++ gcc/testsuite/gcc.dg/tree-ssa/pr94589-1.c | 21 +++++++++++++++++++++ 2 files changed, 33 insertions(+) create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/pr94589-1.c diff --git a/gcc/match.pd b/gcc/match.pd index 19f4a78..cdb8763 100644 --- a/gcc/match.pd +++ b/gcc/match.pd @@ -4764,6 +4764,18 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) (cmp:c (bit_xor:c @0 @1) @0) (cmp @1 { build_zero_cst (TREE_TYPE (@1)); })) +#if GIMPLE + /* (X & Y) == X becomes (X & ~Y) == 0. */ + (simplify + (cmp:c (bit_and:c @0 @1) @0) + (cmp (bit_and @0 (bit_not! @1)) { build_zero_cst (TREE_TYPE (@0)); })) + + /* (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)); })) +#endif + /* (X ^ C1) op C2 can be rewritten as X op (C1 ^ C2). */ (simplify (cmp (convert?@3 (bit_xor @0 INTEGER_CST@1)) INTEGER_CST@2) diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr94589-1.c b/gcc/testsuite/gcc.dg/tree-ssa/pr94589-1.c new file mode 100644 index 0000000..7e1aaaa --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr94589-1.c @@ -0,0 +1,21 @@ +/* PR tree-optimization/94589 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ + +int +foo (int x) +{ + return (x & 23) == x; +/* { dg-final { scan-tree-dump " & -24;" "optimized" } } */ +/* { dg-final { scan-tree-dump-not " & 23;" "optimized" } } */ +/* { dg-final { scan-tree-dump " == 0" "optimized" } } */ +} + +int +bar (int x) +{ + return (x | 137) != 137; +/* { dg-final { scan-tree-dump " & -138;" "optimized" } } */ +/* { dg-final { scan-tree-dump-not " \\| 137;" "optimized" } } */ +/* { dg-final { scan-tree-dump " != 0" "optimized" } } */ +} -- 2.7.4