[RFA] Minor optimization of variable bit testing

Jeff Law jlaw@tachyum.com
Tue Nov 2 15:52:24 GMT 2021


I was wandering spec chasing down instances where we should be 
generating bit-test, bit-set and bit-clear types of instructions for our 
target when I ran across a generic missed optimization in this space.


(((1 << N) & C) != 0)  -> (N == C')
(((1 << N) & C) == 0)  -> (N != C')

Where C is a constant power of 2 and C' is log2 (C).



That obviously avoids the shift by a variable amount and the bit masking 
which is the primary effect.  I did see cases where we were able to 
constant propagate into uses of N, but those were only in PHI nodes and 
never triggered any real secondary effects in the cases I looked at.


Anyway, it's a fairly minor optimization, but with the analysis done and 
patch in hand, it's silly not to take the easy win.


Bootstrapped and regression tested on x86_64 and verified that the 
affected spec benchmark (gcc itself) still passes on our target.

OK for the trunk?  Note I added the patterns at the end of match.pd.  
Certainly open to moving them elsewhere.


Jeff
-------------- next part --------------
diff --git a/gcc/match.pd b/gcc/match.pd
index 4fbba3922e5..b275631555d 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -6835,3 +6835,20 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
    to the number of trailing zeroes.  */
 (match (ctz_table_index @1 @2 @3)
   (rshift (mult (bit_and:c (negate @1) @1) INTEGER_CST@2) INTEGER_CST@3))
+
+/* ((1 << n) & M) != 0  -> n == log2 (M) */
+(simplify
+ (ne
+  (bit_and
+   (nop_convert? (lshift integer_onep@0 @1)) integer_pow2p@2) integer_zerop@3)
+ (eq @1 { build_int_cst (integer_type_node,
+                         wi::exact_log2 (wi::to_wide (@2))); }))
+
+/* ((1 << n) & M) == 0  -> n != log2 (M) */
+(simplify
+ (eq
+  (bit_and
+   (nop_convert? (lshift integer_onep@0 @1)) integer_pow2p@2) integer_zerop@3)
+ (ne @1 { build_int_cst (integer_type_node,
+                         wi::exact_log2 (wi::to_wide (@2))); }))
+
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/bittest.c b/gcc/testsuite/gcc.dg/tree-ssa/bittest.c
new file mode 100644
index 00000000000..7d712cad1ee
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/bittest.c
@@ -0,0 +1,27 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+
+
+void bar (void);
+
+void
+foo(unsigned int abc123)
+{
+  unsigned int xyzpdq = (1 << abc123);
+  if ((xyzpdq & 0x800) != 0)
+    bar();
+}
+
+void
+baz(unsigned int abc123)
+{
+  unsigned int xyzpdq = (1 << abc123);
+  if ((xyzpdq & 0x800) == 0)
+    bar();
+}
+
+/* What we want to verify is that the bit test against xyzpdq is
+   replaced with a test against abc123 which avoids the shifting
+   and bit ops.  */
+/* { dg-final { scan-tree-dump-not "xyzpdq" "optimized"} } */
+/* { dg-final { scan-tree-dump-times "if .abc123" 2 "optimized"} } */


More information about the Gcc-patches mailing list