On Tue, Nov 2, 2021 at 4:53 PM Jeff Law <j...@tachyum.com> wrote:
>
>
> 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.

There are related patterns like

/* (CST1 << A) == CST2 -> A == ctz (CST2) - ctz (CST1)
   (CST1 << A) != CST2 -> A != ctz (CST2) - ctz (CST1)

please move the new patterns next to those.

+/* ((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))); }))

you don't need @3 or @0 so no need to specify them.  You can merge the
patterns with

(for cmp (ne eq)
       icmp (eq ne)
  (simplify
    (cmp
+  (bit_and
      (nop_convert? (lshift integer_onep @1)) integer_pow2p@2) integer_zerop)
    (icmp @1 { wide_int_to_tree (TREE_TYPE (@1),
+                         wi::exact_log2 (wi::to_wide (@2))); }))

I belive the integer constant you build should be of the type of @1 (I
fixed that above,
also using wide_int_to_tree.  The pattern is written in a way that _could_ match
vector operations and a vector by vector shift in which case the
wi::to_wide would
ICE - integer_pow2p currently does not match vector constants.  But maybe be
defensive and add

  (if (INTEGRAL_TYPE_P (TREE_TYPE (@1)))

I think the patch is OK with those changes.

Thanks,
Richard.


>
> Jeff

Reply via email to