Hi!

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.

--- 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")

        Jakub

Reply via email to