Using nonzero_bits() in insn conditions?
Jeff Law
jeffreyalaw@gmail.com
Fri Mar 21 00:02:36 GMT 2025
On 3/19/25 4:14 AM, Georg-Johann Lay wrote:
> Am 16.03.25 um 14:51 schrieb Jeff Law via Gcc:
>> On 3/13/25 5:39 AM, Georg-Johann Lay via Gcc wrote:
>>> There are situations where knowledge about which bits
>>> of a value are (not) set can be used for optimization.
>>> For example in an insn combine pattern like:
>>>
>>> (define_insn_and_split ""
>>> [(set (match_operand:QI 0 "register_operand" "=d")
>>> (ior:QI (ashift:QI (match_operand:QI 1 "register_operand" "r")
>>> (match_operand:QI 2
>>> "const_0_to_7_operand" "n"))
>>> (match_operand:QI 3 "register_operand" "0")))]
>>> "optimize
>>> && !reload_completed
>>> && nonzero_bits (operands[1], VOIDmode) == 1"
>>> ...
>>>
>>> This pattern is only correct when operands[1] is 0 or 1.
>>>
>>> While such patterns seem to work, it's all quite wonky,
>>> in particular since nonzero_bits() may forget about known
>>> properties in later passes.
>> While it works most of the time, it's fundamentally wrong to have a
>> pattern where the conditional is dependent on state that changes based
>> on pass specific data, nearby context, etc.
>>
>>>
>>> For the use case I have in mind, it is in order when the
>>> pattern works until split1 which would transform it into
>>> something else (and without nonzero_bits() in the insn
>>> condition, asserting that the existence of the pattern
>>> certifies the bit condition).
>> It's still the wrong thing to do. You'll get away with it for a
>> while, but one day it'll break.
>>
>> We have similar problems in the RISC-V world where we would like to be
>> able to match certain patterns based on known ranges of an operand.
>> The most common case would be bset/bclr/binv on an SImode object on
>> rv64 where the bit twiddled is variable. In particular we need to
>> know the bit position is not bit 31.
>>
>> There's no way to really describe that in an insn's condition because
>> range information like that isn't available in RTL and something like
>> nonzero bits is pass specific.
>>
>> As a result we're limited in our ability to use the bset/bclr/binv
>> instructions.
>>
>> Jeff
>
> One way to support this is a new target hook that would run somewhere
> in recog_for_combine(). The hook would allow the backend to replace
> the pattern as synthesized by combine with an equivalent pattern.
Much simpler: Add a split pass immediately after combine. Use
define_insn_and_split to handle rewriting. No hooks needed.
Jeff
More information about the Gcc
mailing list