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
