On 8/26/26 2:13 AM, Jin Ma wrote:
The branch-specific Zbs pattern only recognizes bit indices
zero-extended from QImode. Bit tests with an XLEN-wide index instead
mask the index with XLEN - 1, so combine emits a bset/and pair before
the branch.
BEXT applies the same XLEN - 1 mask to its index. Match the masked
form only when the mask is exactly XLEN - 1, then split it into bext
and the branch. With register allocation normalized, the key sequence
changes from:
bset t0,zero,a1
and a4,t0,t1
bne a4,zero,.L
to:
bext a4,t1,a1
bne a4,zero,.L
This removes one instruction from each affected branch. On SPEC CPU
2017 Integer 541.leela_r, the measured dynamic instruction count drops
by about 0.5%.
gcc/ChangeLog:
* config/riscv/bitmanip.md (*branch<X:mode>_bext_mask_pos):
New pattern.
gcc/testsuite/ChangeLog:
* g++.target/riscv/zbs-branch-bext.C: New test.
* gcc.target/riscv/zbs-branch-bext.c: New test.
Signed-off-by: Jin Ma <[email protected]>
Good find. Just a couple of small things and I think this can go forward.
+(define_insn_and_split "*branch<X:mode>_bext_mask_pos"
If I look at the combine dump, these appear to be 3->2 splits. So we're
better off using a define_split rather than define_insn_and_split.
+ "(TARGET_ZBS
+ && INTVAL (operands[4]) + 1 == GET_MODE_BITSIZE (<MODE>mode))"
Probably want UINTVAL rather than INTVAL to guard against tripping an
overflow.
With those changes this is OK. Given they're meaningful changes, please
go through the test cycle again.
FWIW, I did a pass through the assembly dumps of spec2017 hot blocks
looking for missed bexts a while back, but I was focused much more on
extraction from a constant bit position. Thanks so much for tackling
the non-constant cases. We've still got work to do here. See the
testcases in pr32648.
Jeff