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.
The backend could use nonzero_bits and ranges information which have
to be available. As is seems, nonzero_bits is available. For ranges
information I don't know. The backend would have to make sure that
no other routes can lead to the pattern (provided extra range or
bits info is used. When the hook us used for, say canonicalization,
other ways to the patterns are in order).
The default implementation of the hook just returns the unchanged
pattern.
Johann