match.pd: Generalize the PR64309 simplifications [PR96669]

The following patch generalizes the PR64309 simplifications, so that instead
of working only with constants 1 and 1 it works with any two power of two
constants, and works also for right shift (in that case it rules out the
first one being negative, as it is arithmetic shift then).

2021-01-15  Jakub Jelinek  <jakub@redhat.com>

	PR tree-optimization/96669
	* match.pd (((1 << A) & 1) != 0 -> A == 0,
	((1 << A) & 1) == 0 -> A != 0): Generalize for 1s replaced by
	possibly different power of two constants and to right shift too.

	* gcc.dg/tree-ssa/pr96669-1.c: New test.
This commit is contained in:
Jakub Jelinek 2021-01-15 21:12:14 +01:00
parent 5c046034e3
commit 0425f4c1b6
2 changed files with 76 additions and 4 deletions

View File

@ -3117,13 +3117,26 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
(op @0 { build_int_cst (TREE_TYPE (@1), low); })))))))
/* ((1 << A) & 1) != 0 -> A == 0
((1 << A) & 1) == 0 -> A != 0 */
/* Simplify ((C << x) & D) != 0 where C and D are power of two constants,
either to false if D is smaller (unsigned comparison) than C, or to
x == log2 (D) - log2 (C). Similarly for right shifts. */
(for cmp (ne eq)
icmp (eq ne)
(simplify
(cmp (bit_and (lshift integer_onep @0) integer_onep) integer_zerop)
(icmp @0 { build_zero_cst (TREE_TYPE (@0)); })))
(cmp (bit_and (lshift integer_pow2p@1 @0) integer_pow2p@2) integer_zerop)
(with { int c1 = wi::clz (wi::to_wide (@1));
int c2 = wi::clz (wi::to_wide (@2)); }
(if (c1 < c2)
{ constant_boolean_node (cmp == NE_EXPR ? false : true, type); }
(icmp @0 { build_int_cst (TREE_TYPE (@0), c1 - c2); }))))
(simplify
(cmp (bit_and (rshift integer_pow2p@1 @0) integer_pow2p@2) integer_zerop)
(if (tree_int_cst_sgn (@1) > 0)
(with { int c1 = wi::clz (wi::to_wide (@1));
int c2 = wi::clz (wi::to_wide (@2)); }
(if (c1 > c2)
{ constant_boolean_node (cmp == NE_EXPR ? false : true, type); }
(icmp @0 { build_int_cst (TREE_TYPE (@0), c2 - c1); }))))))
/* (CST1 << A) == CST2 -> A == ctz (CST2) - ctz (CST1)
(CST1 << A) != CST2 -> A != ctz (CST2) - ctz (CST1)

View File

@ -0,0 +1,59 @@
/* PR tree-optimization/96669 */
/* { dg-do compile } */
/* { dg-options "-O2 -fdump-tree-original" } */
/* { dg-final { scan-tree-dump "return a == 0;" "original" } } */
/* { dg-final { scan-tree-dump "return 1;" "original" } } */
/* { dg-final { scan-tree-dump "return c == 3;" "original" } } */
/* { dg-final { scan-tree-dump "return d != 1;" "original" } } */
/* { dg-final { scan-tree-dump "return e != 0;" "original" } } */
/* { dg-final { scan-tree-dump "return f == 1;" "original" } } */
/* { dg-final { scan-tree-dump "return 0;" "original" } } */
/* { dg-final { scan-tree-dump "return h != 1;" "original" } } */
int
f1 (int a)
{
return ((1 << a) & 1) != 0;
}
int
f2 (int b)
{
return ((2 << b) & 1) == 0;
}
int
f3 (int c)
{
return ((2 << c) & 16) != 0;
}
int
f4 (int d)
{
return ((16 << d) & 32) == 0;
}
int
f5 (int e)
{
return ((1 >> e) & 1) == 0;
}
int
f6 (int f)
{
return ((2 >> f) & 1) != 0;
}
int
f7 (int g)
{
return ((1 >> g) & 2) != 0;
}
int
f8 (int h)
{
return ((32 >> h) & 16) == 0;
}