[RISCV] Support scalar bitreverse using P extension rev instruction. (#183245)

This commit is contained in:
Craig Topper 2026-02-25 12:42:59 -08:00 committed by GitHub
parent 84594d7539
commit b68307569b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 175 additions and 2 deletions

View File

@ -411,8 +411,7 @@ RISCVTargetLowering::RISCVTargetLowering(const TargetMachine &TM,
setOperationAction(ISD::BSWAP, XLenVT,
Subtarget.hasREV8Like() ? Legal : Expand);
if ((Subtarget.hasVendorXCVbitmanip() || Subtarget.hasVendorXqcibm()) &&
!Subtarget.is64Bit()) {
if (Subtarget.hasREVLike()) {
setOperationAction(ISD::BITREVERSE, XLenVT, Legal);
} else {
// Zbkb can use rev8+brev8 to implement bitreverse.

View File

@ -1725,6 +1725,8 @@ let Predicates = [HasStdExtP] in {
} // Predicates = [HasStdExtP]
let Predicates = [HasStdExtP, IsRV32] in {
def : PatGpr<bitreverse, REV_RV32>;
def : PatGprGpr<saddsat, SADD>;
def : PatGprGpr<ssubsat, SSUB>;
def : PatGprGpr<uaddsat, SADDU>;
@ -1764,6 +1766,8 @@ let Predicates = [HasStdExtP, IsRV64] in {
def : PatGpr<riscv_absw, ABSW>;
def : PatGpr<riscv_clsw, CLSW>;
def : PatGpr<bitreverse, REV_RV64>;
// 32-bit PLI SD node pattern
def: Pat<(v2i32 (splat_vector simm10:$imm10)), (PLI_W simm10:$imm10)>;

View File

@ -200,6 +200,9 @@ public:
bool hasREV8Like() const {
return HasStdExtZbb || HasStdExtZbkb || HasVendorXTHeadBb;
}
bool hasREVLike() const {
return HasStdExtP || ((HasVendorXCVbitmanip || HasVendorXqcibm) && !IsRV64);
}
bool hasBEXTILike() const { return HasStdExtZbs || HasVendorXTHeadBs; }

View File

@ -11,6 +11,10 @@
; RUN: | FileCheck %s -check-prefixes=RV32ZB,RV32ZBKB
; RUN: llc -mtriple=riscv64 -mattr=+zbkb -verify-machineinstrs < %s \
; RUN: | FileCheck %s -check-prefixes=RV64ZB,RV64ZBKB
; RUN: llc -mtriple=riscv32 -mattr=+zbb,+experimental-p -verify-machineinstrs < %s \
; RUN: | FileCheck %s -check-prefixes=RV32ZB,RV32P
; RUN: llc -mtriple=riscv64 -mattr=+zbb,+experimental-p -verify-machineinstrs < %s \
; RUN: | FileCheck %s -check-prefixes=RV64ZB,RV64P
define i16 @test_bswap_i16(i16 %a) nounwind {
; RV32I-LABEL: test_bswap_i16:
@ -326,6 +330,18 @@ define i7 @test_bitreverse_i7(i7 %a) nounwind {
; RV64ZBKB-NEXT: brev8 a0, a0
; RV64ZBKB-NEXT: srli a0, a0, 57
; RV64ZBKB-NEXT: ret
;
; RV32P-LABEL: test_bitreverse_i7:
; RV32P: # %bb.0:
; RV32P-NEXT: rev a0, a0
; RV32P-NEXT: srli a0, a0, 25
; RV32P-NEXT: ret
;
; RV64P-LABEL: test_bitreverse_i7:
; RV64P: # %bb.0:
; RV64P-NEXT: rev a0, a0
; RV64P-NEXT: srli a0, a0, 57
; RV64P-NEXT: ret
%tmp = call i7 @llvm.bitreverse.i7(i7 %a)
ret i7 %tmp
}
@ -416,6 +432,18 @@ define i8 @test_bitreverse_i8(i8 %a) nounwind {
; RV64ZBKB: # %bb.0:
; RV64ZBKB-NEXT: brev8 a0, a0
; RV64ZBKB-NEXT: ret
;
; RV32P-LABEL: test_bitreverse_i8:
; RV32P: # %bb.0:
; RV32P-NEXT: rev a0, a0
; RV32P-NEXT: srli a0, a0, 24
; RV32P-NEXT: ret
;
; RV64P-LABEL: test_bitreverse_i8:
; RV64P: # %bb.0:
; RV64P-NEXT: rev a0, a0
; RV64P-NEXT: srli a0, a0, 56
; RV64P-NEXT: ret
%tmp = call i8 @llvm.bitreverse.i8(i8 %a)
ret i8 %tmp
}
@ -544,6 +572,18 @@ define i16 @test_bitreverse_i16(i16 %a) nounwind {
; RV64ZBKB-NEXT: brev8 a0, a0
; RV64ZBKB-NEXT: srli a0, a0, 48
; RV64ZBKB-NEXT: ret
;
; RV32P-LABEL: test_bitreverse_i16:
; RV32P: # %bb.0:
; RV32P-NEXT: rev a0, a0
; RV32P-NEXT: srli a0, a0, 16
; RV32P-NEXT: ret
;
; RV64P-LABEL: test_bitreverse_i16:
; RV64P: # %bb.0:
; RV64P-NEXT: rev a0, a0
; RV64P-NEXT: srli a0, a0, 48
; RV64P-NEXT: ret
%tmp = call i16 @llvm.bitreverse.i16(i16 %a)
ret i16 %tmp
}
@ -688,6 +728,17 @@ define i32 @test_bitreverse_i32(i32 %a) nounwind {
; RV64ZBKB-NEXT: brev8 a0, a0
; RV64ZBKB-NEXT: srli a0, a0, 32
; RV64ZBKB-NEXT: ret
;
; RV32P-LABEL: test_bitreverse_i32:
; RV32P: # %bb.0:
; RV32P-NEXT: rev a0, a0
; RV32P-NEXT: ret
;
; RV64P-LABEL: test_bitreverse_i32:
; RV64P: # %bb.0:
; RV64P-NEXT: rev a0, a0
; RV64P-NEXT: srli a0, a0, 32
; RV64P-NEXT: ret
%tmp = call i32 @llvm.bitreverse.i32(i32 %a)
ret i32 %tmp
}
@ -896,6 +947,18 @@ define i64 @test_bitreverse_i64(i64 %a) nounwind {
; RV64ZBKB-NEXT: rev8 a0, a0
; RV64ZBKB-NEXT: brev8 a0, a0
; RV64ZBKB-NEXT: ret
;
; RV32P-LABEL: test_bitreverse_i64:
; RV32P: # %bb.0:
; RV32P-NEXT: rev a2, a1
; RV32P-NEXT: rev a1, a0
; RV32P-NEXT: mv a0, a2
; RV32P-NEXT: ret
;
; RV64P-LABEL: test_bitreverse_i64:
; RV64P: # %bb.0:
; RV64P-NEXT: rev a0, a0
; RV64P-NEXT: ret
%tmp = call i64 @llvm.bitreverse.i64(i64 %a)
ret i64 %tmp
}
@ -1010,6 +1073,22 @@ define i16 @test_bswap_bitreverse_i16(i16 %a) nounwind {
; RV64ZBKB: # %bb.0:
; RV64ZBKB-NEXT: brev8 a0, a0
; RV64ZBKB-NEXT: ret
;
; RV32P-LABEL: test_bswap_bitreverse_i16:
; RV32P: # %bb.0:
; RV32P-NEXT: rev8 a0, a0
; RV32P-NEXT: srli a0, a0, 16
; RV32P-NEXT: rev a0, a0
; RV32P-NEXT: srli a0, a0, 16
; RV32P-NEXT: ret
;
; RV64P-LABEL: test_bswap_bitreverse_i16:
; RV64P: # %bb.0:
; RV64P-NEXT: rev8 a0, a0
; RV64P-NEXT: srli a0, a0, 48
; RV64P-NEXT: rev a0, a0
; RV64P-NEXT: srli a0, a0, 48
; RV64P-NEXT: ret
%tmp = call i16 @llvm.bswap.i16(i16 %a)
%tmp2 = call i16 @llvm.bitreverse.i16(i16 %tmp)
ret i16 %tmp2
@ -1125,6 +1204,20 @@ define i32 @test_bswap_bitreverse_i32(i32 %a) nounwind {
; RV64ZBKB: # %bb.0:
; RV64ZBKB-NEXT: brev8 a0, a0
; RV64ZBKB-NEXT: ret
;
; RV32P-LABEL: test_bswap_bitreverse_i32:
; RV32P: # %bb.0:
; RV32P-NEXT: rev8 a0, a0
; RV32P-NEXT: rev a0, a0
; RV32P-NEXT: ret
;
; RV64P-LABEL: test_bswap_bitreverse_i32:
; RV64P: # %bb.0:
; RV64P-NEXT: rev8 a0, a0
; RV64P-NEXT: srli a0, a0, 32
; RV64P-NEXT: rev a0, a0
; RV64P-NEXT: srli a0, a0, 32
; RV64P-NEXT: ret
%tmp = call i32 @llvm.bswap.i32(i32 %a)
%tmp2 = call i32 @llvm.bitreverse.i32(i32 %tmp)
ret i32 %tmp2
@ -1283,6 +1376,20 @@ define i64 @test_bswap_bitreverse_i64(i64 %a) nounwind {
; RV64ZBKB: # %bb.0:
; RV64ZBKB-NEXT: brev8 a0, a0
; RV64ZBKB-NEXT: ret
;
; RV32P-LABEL: test_bswap_bitreverse_i64:
; RV32P: # %bb.0:
; RV32P-NEXT: rev8 a1, a1
; RV32P-NEXT: rev8 a0, a0
; RV32P-NEXT: rev a0, a0
; RV32P-NEXT: rev a1, a1
; RV32P-NEXT: ret
;
; RV64P-LABEL: test_bswap_bitreverse_i64:
; RV64P: # %bb.0:
; RV64P-NEXT: rev8 a0, a0
; RV64P-NEXT: rev a0, a0
; RV64P-NEXT: ret
%tmp = call i64 @llvm.bswap.i64(i64 %a)
%tmp2 = call i64 @llvm.bitreverse.i64(i64 %tmp)
ret i64 %tmp2
@ -1398,6 +1505,22 @@ define i16 @test_bitreverse_bswap_i16(i16 %a) nounwind {
; RV64ZBKB: # %bb.0:
; RV64ZBKB-NEXT: brev8 a0, a0
; RV64ZBKB-NEXT: ret
;
; RV32P-LABEL: test_bitreverse_bswap_i16:
; RV32P: # %bb.0:
; RV32P-NEXT: rev8 a0, a0
; RV32P-NEXT: srli a0, a0, 16
; RV32P-NEXT: rev a0, a0
; RV32P-NEXT: srli a0, a0, 16
; RV32P-NEXT: ret
;
; RV64P-LABEL: test_bitreverse_bswap_i16:
; RV64P: # %bb.0:
; RV64P-NEXT: rev8 a0, a0
; RV64P-NEXT: srli a0, a0, 48
; RV64P-NEXT: rev a0, a0
; RV64P-NEXT: srli a0, a0, 48
; RV64P-NEXT: ret
%tmp = call i16 @llvm.bitreverse.i16(i16 %a)
%tmp2 = call i16 @llvm.bswap.i16(i16 %tmp)
ret i16 %tmp2
@ -1513,6 +1636,20 @@ define i32 @test_bitreverse_bswap_i32(i32 %a) nounwind {
; RV64ZBKB: # %bb.0:
; RV64ZBKB-NEXT: brev8 a0, a0
; RV64ZBKB-NEXT: ret
;
; RV32P-LABEL: test_bitreverse_bswap_i32:
; RV32P: # %bb.0:
; RV32P-NEXT: rev8 a0, a0
; RV32P-NEXT: rev a0, a0
; RV32P-NEXT: ret
;
; RV64P-LABEL: test_bitreverse_bswap_i32:
; RV64P: # %bb.0:
; RV64P-NEXT: rev8 a0, a0
; RV64P-NEXT: srli a0, a0, 32
; RV64P-NEXT: rev a0, a0
; RV64P-NEXT: srli a0, a0, 32
; RV64P-NEXT: ret
%tmp = call i32 @llvm.bitreverse.i32(i32 %a)
%tmp2 = call i32 @llvm.bswap.i32(i32 %tmp)
ret i32 %tmp2
@ -1671,6 +1808,20 @@ define i64 @test_bitreverse_bswap_i64(i64 %a) nounwind {
; RV64ZBKB: # %bb.0:
; RV64ZBKB-NEXT: brev8 a0, a0
; RV64ZBKB-NEXT: ret
;
; RV32P-LABEL: test_bitreverse_bswap_i64:
; RV32P: # %bb.0:
; RV32P-NEXT: rev8 a0, a0
; RV32P-NEXT: rev8 a1, a1
; RV32P-NEXT: rev a0, a0
; RV32P-NEXT: rev a1, a1
; RV32P-NEXT: ret
;
; RV64P-LABEL: test_bitreverse_bswap_i64:
; RV64P: # %bb.0:
; RV64P-NEXT: rev8 a0, a0
; RV64P-NEXT: rev a0, a0
; RV64P-NEXT: ret
%tmp = call i64 @llvm.bitreverse.i64(i64 %a)
%tmp2 = call i64 @llvm.bswap.i64(i64 %tmp)
ret i64 %tmp2
@ -1724,6 +1875,22 @@ define i32 @pr55484(i32 %0) {
; RV64ZBKB-NEXT: or a0, a0, a1
; RV64ZBKB-NEXT: srai a0, a0, 48
; RV64ZBKB-NEXT: ret
;
; RV32P-LABEL: pr55484:
; RV32P: # %bb.0:
; RV32P-NEXT: srli a1, a0, 8
; RV32P-NEXT: slli a0, a0, 8
; RV32P-NEXT: or a0, a1, a0
; RV32P-NEXT: sext.h a0, a0
; RV32P-NEXT: ret
;
; RV64P-LABEL: pr55484:
; RV64P: # %bb.0:
; RV64P-NEXT: srli a1, a0, 8
; RV64P-NEXT: slli a0, a0, 8
; RV64P-NEXT: or a0, a1, a0
; RV64P-NEXT: sext.h a0, a0
; RV64P-NEXT: ret
%2 = lshr i32 %0, 8
%3 = shl i32 %0, 8
%4 = or i32 %2, %3