https://gcc.gnu.org/g:282087fbab2d230a103c844316ac9c48db4e3b94
commit r17-5639-g282087fbab2d230a103c844316ac9c48db4e3b94 Author: Jiawei <[email protected]> Date: Tue Oct 27 07:31:07 2026 -0600 [PATCH 2/3] RISC-V: Eliminate redundant masks on Zbs bclr indices BCLR already uses only the low log2(XLEN) bits of its index. Recognize the rotate form with an explicit XLEN - 1 mask and emit bclr directly, avoiding the redundant mask on RV32 and RV64. gcc/ChangeLog: * config/riscv/bitmanip.md (*bclr<mode>_mask): New pattern. gcc/testsuite/ChangeLog: * gcc.target/riscv/zbs-bclr.c: Select RV32 or RV64 options and add masked-index, bitmap and narrower-mask cases. Diff: --- gcc/config/riscv/bitmanip.md | 15 +++++++++++++++ gcc/testsuite/gcc.target/riscv/zbs-bclr.c | 30 +++++++++++++++++++++++++++--- 2 files changed, 42 insertions(+), 3 deletions(-) diff --git a/gcc/config/riscv/bitmanip.md b/gcc/config/riscv/bitmanip.md index fe2b9fbae02a..f3207a72180c 100644 --- a/gcc/config/riscv/bitmanip.md +++ b/gcc/config/riscv/bitmanip.md @@ -958,6 +958,21 @@ "bclr\t%0,%1,%2" [(set_attr "type" "bitmanip")]) +;; BCLR uses only the low log2(XLEN) bits of the index, just like +;; BSET and BINV, so an explicit XLEN - 1 mask is redundant. +(define_insn "*bclr<mode>_mask" + [(set (match_operand:X 0 "register_operand" "=r") + (and:X + (rotate:X + (const_int -2) + (subreg:QI + (and:X (match_operand:X 2 "register_operand" "r") + (match_operand 3 "<X:shiftm1>" "<X:shiftm1p>")) 0)) + (match_operand:X 1 "register_operand" "r")))] + "TARGET_ZBS" + "bclr\t%0,%1,%2" + [(set_attr "type" "bitmanip")]) + (define_insn "*bclri<mode>" [(set (match_operand:X 0 "register_operand" "=r") (and:X (match_operand:X 1 "register_operand" "r") diff --git a/gcc/testsuite/gcc.target/riscv/zbs-bclr.c b/gcc/testsuite/gcc.target/riscv/zbs-bclr.c index e37580dc245f..93ef46e8b4c1 100644 --- a/gcc/testsuite/gcc.target/riscv/zbs-bclr.c +++ b/gcc/testsuite/gcc.target/riscv/zbs-bclr.c @@ -1,5 +1,6 @@ /* { dg-do compile } */ -/* { dg-options "-march=rv64gc_zbs -mabi=lp64" } */ +/* { dg-options "-march=rv64gc_zbs -mabi=lp64" { target { rv64 } } } */ +/* { dg-options "-march=rv32gc_zbs -mabi=ilp32" { target { rv32 } } } */ /* { dg-skip-if "" { *-*-* } { "-O0" "-Og" } } */ /* bclr */ @@ -16,6 +17,29 @@ foo1 (long i) return i & ~(1L << 20); } -/* { dg-final { scan-assembler-times "bclr\t" 1 } } */ +/* bclr with an XLEN - 1 mask. */ +unsigned long +foo2 (unsigned long i, unsigned long j) +{ + return i & ~(1UL << (j & (__riscv_xlen - 1))); +} + +/* bclr with the modulo used by bitmap helpers. */ +void +foo3 (unsigned long *map, unsigned long j) +{ + map[j / __riscv_xlen] &= ~(1UL << (j % __riscv_xlen)); +} + +/* A narrower mask must be retained. */ +unsigned long +foo4 (unsigned long i, unsigned long j) +{ + return i & ~(1UL << (j & 7)); +} + +/* { dg-final { scan-assembler-times "bclr\t" 4 } } */ /* { dg-final { scan-assembler-times "bclri\t" 1 } } */ -/* { dg-final { scan-assembler-not {\mandi} } } */ +/* { dg-final { scan-assembler-times "andi\t" 1 } } */ +/* { dg-final { scan-assembler-not "bset\t" } } */ +/* { dg-final { scan-assembler-not "andn\t" } } */
