Using nonzero_bits() in insn conditions?
Jeff Law
jeffreyalaw@gmail.com
Sun Mar 16 13:51:55 GMT 2025
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
More information about the Gcc
mailing list