https://gcc.gnu.org/g:af981ba6b6dfb1a7e15e4472318535ab7d866893

commit r17-3934-gaf981ba6b6dfb1a7e15e4472318535ab7d866893
Author: Jakub Jelinek <[email protected]>
Date:   Fri Sep 4 19:46:19 2026 +0200

    RISC-V: Improve __builtin_bitreverse{8,16,32,64} code generation [PR126671]
    
    The following patch attempts to improve code generation for
    __builtin_bitreverse{8,16,32,64} when ZBKB extension is enabled, by using
            brev8   a0,a0
    or
            rev8    a0,a0
            brev8   t0,a0
            srli    a0,t0,48        ! 16 for rv32
    or (bitreversesi2 if rv64)
            rev8    a0,a0
            brev8   t0,a0
            srai    a0,t0,32
    or (bitreversesi2 if rv32 or bitreversedi2 if rv64)
            rev8    a0,a0
            brev8   a0,a0
    
    Only tested in a cross on a testcase with the 4 builtins, hope CI will pick
    this up when posted with RISC-V in the subject.
    
    The bswaphi2 change is not strictly necessary, just weird to limit it
    only to TARGET_ZBB when bswap<word_mode>2 is also TARGET_ZBKB.
    
    2026-09-04  Jakub Jelinek  <[email protected]>
    
            PR target/126671
            * config/riscv/bitmanip.md (bswaphi2): Use
            TARGET_ZBB || TARGET_ZBKB condition instead of just
            TARGET_ZBB.
            (bitreverse<mode>2): New expander.
    
            * gcc.target/riscv/bitreverse-1-zbkb.c: New test.
            * gcc.target/riscv/bitreverse-2-zbkb.c: New test.
            * gcc.target/riscv/bitreverse-3-zbkb.c: New test.
    
    Reviewed-by: Jeff Law <[email protected]>

Diff:
---
 gcc/config/riscv/bitmanip.md                       | 37 ++++++++++-
 gcc/testsuite/gcc.target/riscv/bitreverse-1-zbkb.c |  6 ++
 gcc/testsuite/gcc.target/riscv/bitreverse-2-zbkb.c | 73 ++++++++++++++++++++++
 gcc/testsuite/gcc.target/riscv/bitreverse-3-zbkb.c | 59 +++++++++++++++++
 4 files changed, 174 insertions(+), 1 deletion(-)

diff --git a/gcc/config/riscv/bitmanip.md b/gcc/config/riscv/bitmanip.md
index 1f0b3ec3d506..a9fc5af5a0e0 100644
--- a/gcc/config/riscv/bitmanip.md
+++ b/gcc/config/riscv/bitmanip.md
@@ -549,7 +549,7 @@
 (define_expand "bswaphi2"
   [(set (match_operand:HI 0 "register_operand" "=r")
         (bswap:HI (match_operand:HI 1 "register_operand" "r")))]
-  "TARGET_ZBB"
+  "TARGET_ZBB || TARGET_ZBKB"
 {
   rtx tmp = gen_reg_rtx (word_mode);
   rtx newop1 = gen_lowpart (word_mode, operands[1]);
@@ -566,6 +566,41 @@
   DONE;
 })
 
+(define_expand "bitreverse<mode>2"
+  [(match_operand:ANYI 0 "register_operand")
+   (match_operand:ANYI 1 "register_operand")]
+  "TARGET_ZBKB"
+{
+  rtx newop1 = gen_lowpart (word_mode, operands[1]);
+  rtx tmp = newop1, tmp2;
+  if (<MODE>mode != QImode)
+    {
+      tmp = gen_reg_rtx (word_mode);
+      if (TARGET_64BIT)
+       emit_insn (gen_bswapdi2 (tmp, newop1));
+      else
+       emit_insn (gen_bswapsi2 (tmp, newop1));
+    }
+  tmp2 = gen_reg_rtx (word_mode);
+  if (TARGET_64BIT)
+    emit_insn (gen_riscv_brev8_di (tmp2, tmp));
+  else
+    emit_insn (gen_riscv_brev8_si (tmp2, tmp));
+  tmp = tmp2;
+  if (<MODE>mode != word_mode && <MODE>mode != QImode)
+    {
+      tmp = gen_reg_rtx (word_mode);
+      if (TARGET_64BIT)
+       emit_insn (gen_lshrdi3 (tmp, tmp2,
+                               GEN_INT (64 - GET_MODE_BITSIZE (<MODE>mode))));
+      else
+       emit_insn (gen_lshrsi3 (tmp, tmp2,
+                               GEN_INT (32 - GET_MODE_BITSIZE (<MODE>mode))));
+    }
+  emit_move_insn (operands[0], gen_lowpart (<MODE>mode, tmp));
+  DONE;
+})
+
 (define_expand "<bitmanip_optab>di3"
   [(set (match_operand:DI 0 "register_operand" "=r")
         (bitmanip_minmax:DI (match_operand:DI 1 "register_operand" "r")
diff --git a/gcc/testsuite/gcc.target/riscv/bitreverse-1-zbkb.c 
b/gcc/testsuite/gcc.target/riscv/bitreverse-1-zbkb.c
new file mode 100644
index 000000000000..02d445cf6c0b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/bitreverse-1-zbkb.c
@@ -0,0 +1,6 @@
+/* { dg-do run { target riscv_zbkb } } */
+/* { dg-options "-march=rv64gc_zbkb" { target { rv64 } } } */
+/* { dg-options "-march=rv32gc_zbkb" { target { rv32 } } } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-O1" "-Os" "-Oz" "-Og" "-flto"} } */
+
+#include "../../gcc.dg/builtin-bitreverse-1.c"
diff --git a/gcc/testsuite/gcc.target/riscv/bitreverse-2-zbkb.c 
b/gcc/testsuite/gcc.target/riscv/bitreverse-2-zbkb.c
new file mode 100644
index 000000000000..12e4dc8345ee
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/bitreverse-2-zbkb.c
@@ -0,0 +1,73 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gc_zbkb -O2 -mabi=lp64" } */
+/* { dg-skip-if "needs -O2" { *-*-* } { "-O0" "-O1" "-O3" "-Og" "-Os" "-Oz" 
"-flto" } { "" } } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+/*
+** br8:
+**     brev8   a0,a0
+**     andi    a0,a0,0xff
+**     ret
+**  ...
+*/
+unsigned char
+br8 (unsigned char x)
+{
+  return __builtin_bitreverse8 (x);
+}
+
+/*
+** br16:
+**     rev8    a0,a0
+**     brev8   t0,a0
+**     srli    a0,t0,48
+**     ret
+**  ...
+*/
+unsigned short
+br16 (unsigned short x)
+{
+  return __builtin_bitreverse16 (x);
+}
+
+/*
+** br32:
+**     rev8    a0,a0
+**     brev8   t0,a0
+**     srai    a0,t0,32
+**     ret
+**  ...
+*/
+unsigned
+br32 (unsigned x)
+{
+  return __builtin_bitreverse32 (x);
+}
+
+/*
+** br64:
+**     rev8    a0,a0
+**     brev8   a0,a0
+**     ret
+**  ...
+*/
+unsigned long long
+br64 (unsigned long long x)
+{
+  return __builtin_bitreverse64 (x);
+}
+
+/*
+** br128:
+**     rev8    a5,a0
+**     rev8    a0,a1
+**     brev8   a0,a0
+**     brev8   a1,a5
+**     ret
+**  ...
+*/
+unsigned __int128
+br128 (unsigned __int128 x)
+{
+  return __builtin_bitreverse128 (x);
+}
diff --git a/gcc/testsuite/gcc.target/riscv/bitreverse-3-zbkb.c 
b/gcc/testsuite/gcc.target/riscv/bitreverse-3-zbkb.c
new file mode 100644
index 000000000000..9aee7af57d64
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/bitreverse-3-zbkb.c
@@ -0,0 +1,59 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv32gc_zbkb -O2 -mabi=ilp32" } */
+/* { dg-skip-if "needs -O2" { *-*-* } { "-O0" "-O1" "-O3" "-Og" "-Os" "-Oz" 
"-flto" } { "" } } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+/*
+** br8:
+**     brev8   a0,a0
+**     andi    a0,a0,0xff
+**     ret
+**  ...
+*/
+unsigned char
+br8 (unsigned char x)
+{
+  return __builtin_bitreverse8 (x);
+}
+
+/*
+** br16:
+**     rev8    a0,a0
+**     brev8   t0,a0
+**     srli    a0,t0,16
+**     ret
+**  ...
+*/
+unsigned short
+br16 (unsigned short x)
+{
+  return __builtin_bitreverse16 (x);
+}
+
+/*
+** br32:
+**     rev8    a0,a0
+**     brev8   a0,a0
+**     ret
+**  ...
+*/
+unsigned
+br32 (unsigned x)
+{
+  return __builtin_bitreverse32 (x);
+}
+
+/*
+** br64:
+**     rev8    a5,a0
+**     rev8    a0,a1
+**     brev8   a0,a0
+**     brev8   a1,a5
+**     ret
+**  ...
+*/
+unsigned long long
+br64 (unsigned long long x)
+{
+  return __builtin_bitreverse64 (x);
+}

Reply via email to