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

Reply via email to