On January 15, 2021 7:38:35 PM GMT+01:00, Jakub Jelinek <ja...@redhat.com> wrote: >Hi! > >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). > >Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?
Ok. Richard. >2021-01-15 Jakub Jelinek <ja...@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. > >--- gcc/match.pd.jj 2021-01-15 14:00:21.567135280 +0100 >+++ gcc/match.pd 2021-01-15 17:03:49.207071209 +0100 >@@ -3117,13 +3117,26 @@ (define_operator_list COND_TERNARY > (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) >--- gcc/testsuite/gcc.dg/tree-ssa/pr96669-1.c.jj 2021-01-15 >17:12:11.067414204 +0100 >+++ gcc/testsuite/gcc.dg/tree-ssa/pr96669-1.c 2021-01-15 >17:11:55.486589792 +0100 >@@ -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; >+} > > Jakub