[RFA] Minor optimization of variable bit testing

Jeff Law jeffreyalaw@gmail.com
Thu Nov 4 15:09:55 GMT 2021



On 11/3/2021 2:15 AM, Richard Biener via Gcc-patches wrote:
> On Tue, Nov 2, 2021 at 4:53 PM Jeff Law <jlaw@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.
Will do.   FWIW, it feels like match.pd is getting a bit unwieldy in 
terms of being able to find things.  I wonder if we should be looking to 
break it up into multiple files.  Not critical of course, but it's grown 
to ~6k lines at this point.


>
> +/* ((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.
Ah, I didn't know the language allowed us to do that.  Will do and 
adjust operand #s.



>   You can merge the
> patterns with
>
> (for cmp (ne eq)
>         icmp (eq ne)
Thanks.  I was pretty sure we we had this kind of mapping capability, 
now that I know what to look for, it's easy to find.


>    (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.
I'll add that test as well and retest.

Thanks,
jeff



More information about the Gcc-patches mailing list