This patch resolves both PR tree-optimization/64992 and PR
tree-optimization/98956 which are missed optimization enhancement
request, for which Andrew Pinski already has a proposed solution
(related to a fix for PR tree-optimization/98954).  Yesterday,
I proposed an alternate improved patch for PR98954, which although
superior in most respects, alas didn't address this case [which
doesn't include a BIT_AND_EXPR], hence this follow-up fix.

For many functions, F(B), of a (zero-one) Boolean value B, the
expression F(B) != 0 can often be simplified to just B.  Hence
"(B * 5) != 0" is B, "-B != 0" is B, "bswap(B) != 0" is B,
"(B >>r 3) != 0" is B.  These are all currently optimized by GCC,
with the strange exception of left shifts by a constant (possibly
due to the undefined/implementation defined behaviour when the
shift constant is larger than the first operand's precision).
This patch adds support for this particular case, when the shift
constant is valid.

This patch has been tested on x86_64-pc-linux-gnu with make bootstrap
and make -k check, both with and without --target_board=unix{-m32},
with no new failures.  Ok for mainline?


2022-08-08  Roger Sayle  <ro...@nextmovesoftware.com>

gcc/ChangeLog
        PR tree-optimization/64992
        PR tree-optimization/98956
        * match.pd (ne (lshift @0 @1) 0): Simplify (X << C) != 0 to X
        when X is zero_one_valued_p and the shift constant C is valid.
        (eq (lshift @0 @1) 0): Likewise, simplify (X << C) == 0 to !X
        when X is zero_one_valued_p and the shift constant C is valid.

gcc/testsuite/ChangeLog
        PR tree-optimization/64992
        * gcc.dg/pr64992.c: New test case.


Thanks in advance,
Roger
--

diff --git a/gcc/match.pd b/gcc/match.pd
index f82f94a..ef6d8e2 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -1900,6 +1900,22 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
       && TYPE_PRECISION (type) <= TYPE_PRECISION (TREE_TYPE (@0)))
   (mult (convert @1) (convert @2))))
 
+/* (X << C) != 0 can be simplified to X, when X is zero_one_valued_p.  */
+(simplify
+  (ne (lshift zero_one_valued_p@0 INTEGER_CST@1) integer_zerop@2)
+  (if (tree_fits_shwi_p (@1)
+       && tree_to_shwi (@1) > 0
+       && tree_to_shwi (@1) < TYPE_PRECISION (TREE_TYPE (@0)))
+    (convert @0)))
+
+/* (X << C) == 0 can be simplified to X == 0, when X is zero_one_valued_p.  */
+(simplify
+  (eq (lshift zero_one_valued_p@0 INTEGER_CST@1) integer_zerop@2)
+  (if (tree_fits_shwi_p (@1)
+       && tree_to_shwi (@1) > 0
+       && tree_to_shwi (@1) < TYPE_PRECISION (TREE_TYPE (@0)))
+    (eq @0 @2)))
+
 /* Convert ~ (-A) to A - 1.  */
 (simplify
  (bit_not (convert? (negate @0)))
diff --git a/gcc/testsuite/gcc.dg/pr64992.c b/gcc/testsuite/gcc.dg/pr64992.c
new file mode 100644
index 0000000..43fbcf7
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr64992.c
@@ -0,0 +1,7 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+
+_Bool foo(_Bool x) { return (x << 2) != 0; }
+_Bool bar(_Bool x) { return (x << 2) == 0; }
+
+/* { dg-final { scan-tree-dump-not " << " "optimized" } } */

Reply via email to