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  <jakub@redhat.com>
	    Marc Glisse  <marc.glisse@inria.fr>

	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.
This commit is contained in:
Jakub Jelinek 2021-05-12 09:46:03 +02:00
parent e0c4c6bce8
commit f5f1838435
2 changed files with 33 additions and 0 deletions

View File

@ -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)

View File

@ -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" } } */
}