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

Reply via email to