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" } } */

Reply via email to