On Fri, Sep 04, 2026 at 09:46:12AM -0600, Jeff Law wrote:
> I'd be a lot more comfortable with a test in the testsuite that at least
> verified the code generation via scan-asm or check-function-bodies.   If you
> look at crc-22-zbkb, I think it has the magic necessary to have a run test
> which could be run on a suitable design or in QEMU.

So like this (only the tests were added, the rest of the patch is
identical):

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.

--- a/gcc/config/riscv/bitmanip.md      2026-08-31 17:12:13.964850866 +0200
+++ b/gcc/config/riscv/bitmanip.md      2026-09-04 12:36:05.599948978 +0200
@@ -549,7 +549,7 @@ (define_insn "*bswap<mode>2"
 (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 @@ (define_expand "bswaphi2"
   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")
--- a/gcc/testsuite/gcc.target/riscv/bitreverse-1-zbkb.c        2026-09-04 
18:35:40.437141651 +0200
+++ b/gcc/testsuite/gcc.target/riscv/bitreverse-1-zbkb.c        2026-09-04 
18:42:26.761276552 +0200
@@ -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"
--- a/gcc/testsuite/gcc.target/riscv/bitreverse-2-zbkb.c        2026-09-04 
18:42:14.498421693 +0200
+++ b/gcc/testsuite/gcc.target/riscv/bitreverse-2-zbkb.c        2026-09-04 
18:52:14.970314668 +0200
@@ -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);
+}
--- a/gcc/testsuite/gcc.target/riscv/bitreverse-3-zbkb.c        2026-09-04 
18:52:29.975137075 +0200
+++ b/gcc/testsuite/gcc.target/riscv/bitreverse-3-zbkb.c        2026-09-04 
18:54:45.475533331 +0200
@@ -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);
+}


        Jakub

Reply via email to