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