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

Reply via email to