sunshaoce created this revision.
sunshaoce added reviewers: asb, craig.topper, jrtc27, Jim, luismarques, 
kito-cheng, frasercrmck.
Herald added subscribers: VincentWu, luke957, StephenFan, vkmr, evandro, 
apazos, sameer.abuasal, s.egerton, benna, psnobl, jocewei, PkmX, the_o, 
brucehoult, MartinMosbeck, rogfer01, edward-jones, zzheng, shiva0217, niosHD, 
sabuasal, simoncook, johnrusso, rbar, hiraditya, arichardson.
Herald added a project: All.
sunshaoce requested review of this revision.
Herald added subscribers: llvm-commits, cfe-commits, pcwang-thead, eopXD, 
MaskRay.
Herald added projects: clang, LLVM.

Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D128604

Files:
  clang/include/clang/Basic/BuiltinsRISCV.def
  clang/test/CodeGen/RISCV/rvp-intrinsics/riscv32-zbpbo.c
  clang/test/CodeGen/RISCV/rvp-intrinsics/riscv64-zbpbo.c
  llvm/lib/Support/RISCVISAInfo.cpp
  llvm/lib/Target/RISCV/RISCV.td
  llvm/lib/Target/RISCV/RISCVISelLowering.cpp
  llvm/lib/Target/RISCV/RISCVInstrInfoZb.td
  llvm/lib/Target/RISCV/RISCVSubtarget.h
  llvm/test/CodeGen/RISCV/rv32zbpbo.ll
  llvm/test/CodeGen/RISCV/rv64zbpbo.ll
  llvm/test/MC/RISCV/rv32zbpbo-valid.s
  llvm/test/MC/RISCV/rv64zbpbo-valid.s

Index: llvm/test/MC/RISCV/rv64zbpbo-valid.s
===================================================================
--- /dev/null
+++ llvm/test/MC/RISCV/rv64zbpbo-valid.s
@@ -0,0 +1,35 @@
+# RUN: llvm-mc %s -triple=riscv64 -mattr=+experimental-zbpbo -riscv-no-aliases -show-encoding \
+# RUN:     | FileCheck -check-prefixes=CHECK-ASM,CHECK-ASM-AND-OBJ %s
+# RUN: llvm-mc -filetype=obj -triple=riscv64 -mattr=+experimental-zbpbo < %s \
+# RUN:     | llvm-objdump --mattr=+experimental-zbpbo -M no-aliases -d -r - \
+# RUN:     | FileCheck --check-prefix=CHECK-ASM-AND-OBJ %s
+
+# CHECK-ASM-AND-OBJ: pack t0, t1, t2
+# CHECK-ASM: encoding: [0xb3,0x42,0x73,0x08]
+pack t0, t1, t2
+
+# CHECK-ASM-AND-OBJ: packu t0, t1, t2
+# CHECK-ASM: encoding: [0xb3,0x42,0x73,0x48]
+packu t0, t1, t2
+
+# CHECK-ASM-AND-OBJ: fsrw t0, t1, t2, t3
+# CHECK-ASM: encoding: [0xbb,0x52,0xc3,0x3d]
+fsrw t0, t1, t2, t3
+
+# CHECK-ASM-AND-OBJ: max t0, t1, t2
+# CHECK-ASM: encoding: [0xb3,0x62,0x73,0x0a]
+max t0, t1, t2
+
+# CHECK-ASM-AND-OBJ: min t0, t1, t2
+# CHECK-ASM: encoding: [0xb3,0x42,0x73,0x0a]
+min t0, t1, t2
+
+# CHECK-S-OBJ: rev8.h t0, t1
+rev8.h x5, x6
+
+# CHECK-ASM-AND-OBJ: cmix t0, t1, t2, t3
+# CHECK-ASM: encoding: [0xb3,0x92,0x63,0xe6]
+cmix t0, t1, t2, t3
+
+# CHECK-ASM: encoding: [0x93,0x52,0xf3,0x6b]
+rev t0, t1
Index: llvm/test/MC/RISCV/rv32zbpbo-valid.s
===================================================================
--- /dev/null
+++ llvm/test/MC/RISCV/rv32zbpbo-valid.s
@@ -0,0 +1,43 @@
+# RUN: llvm-mc %s -triple=riscv32 -mattr=+experimental-zbpbo -riscv-no-aliases -show-encoding \
+# RUN:     | FileCheck -check-prefixes=CHECK-ASM,CHECK-ASM-AND-OBJ %s
+# RUN: llvm-mc -filetype=obj -triple=riscv32 -mattr=+experimental-zbpbo < %s \
+# RUN:     | llvm-objdump --mattr=+experimental-zbpbo -M no-aliases -d -r - \
+# RUN:     | FileCheck --check-prefix=CHECK-ASM-AND-OBJ %s
+
+# CHECK-ASM-AND-OBJ: clz t0, t1
+# CHECK-ASM: encoding: [0x93,0x12,0x03,0x60]
+clz t0, t1
+
+# CHECK-ASM-AND-OBJ: pack t0, t1, t2
+# CHECK-ASM: encoding: [0xb3,0x42,0x73,0x08]
+pack t0, t1, t2
+
+# CHECK-ASM-AND-OBJ: packu t0, t1, t2
+# CHECK-ASM: encoding: [0xb3,0x42,0x73,0x48]
+packu t0, t1, t2
+
+# CHECK-ASM-AND-OBJ: fsr t0, t1, t2, t3
+# CHECK-ASM: encoding: [0xb3,0x52,0xc3,0x3d]
+fsr t0, t1, t2, t3
+
+# CHECK-ASM-AND-OBJ: fsri t0, t1, t2, 0
+# CHECK-ASM: encoding: [0x93,0x52,0x03,0x3c]
+fsri t0, t1, t2, 0
+
+# CHECK-ASM-AND-OBJ: max t0, t1, t2
+# CHECK-ASM: encoding: [0xb3,0x62,0x73,0x0a]
+max t0, t1, t2
+
+# CHECK-ASM-AND-OBJ: min t0, t1, t2
+# CHECK-ASM: encoding: [0xb3,0x42,0x73,0x0a]
+min t0, t1, t2
+
+# CHECK-S-OBJ: rev8.h t0, t1
+rev8.h x5, x6
+
+# CHECK-ASM-AND-OBJ: cmix t0, t1, t2, t3
+# CHECK-ASM: encoding: [0xb3,0x92,0x63,0xe6]
+cmix t0, t1, t2, t3
+
+# CHECK-ASM: encoding: [0x93,0x52,0xf3,0x69]
+rev t0, t1
Index: llvm/test/CodeGen/RISCV/rv64zbpbo.ll
===================================================================
--- /dev/null
+++ llvm/test/CodeGen/RISCV/rv64zbpbo.ll
@@ -0,0 +1,103 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc -mtriple=riscv64 -verify-machineinstrs < %s \
+; RUN:   | FileCheck %s -check-prefix=RV64I
+; RUN: llc -mtriple=riscv64 -mattr=+experimental-zbpbo -verify-machineinstrs < %s \
+; RUN:   | FileCheck %s -check-prefix=RV64ZBPBO
+
+define i64 @pack_i64(i64 %a, i64 %b) nounwind {
+; RV64I-LABEL: pack_i64:
+; RV64I:       # %bb.0:
+; RV64I-NEXT:    slli a0, a0, 32
+; RV64I-NEXT:    srli a0, a0, 32
+; RV64I-NEXT:    slli a1, a1, 32
+; RV64I-NEXT:    or a0, a1, a0
+; RV64I-NEXT:    ret
+;
+; RV64ZBPBO-LABEL: pack_i64:
+; RV64ZBPBO:       # %bb.0:
+; RV64ZBPBO-NEXT:    pack a0, a0, a1
+; RV64ZBPBO-NEXT:    ret
+  %shl = and i64 %a, 4294967295
+  %shl1 = shl i64 %b, 32
+  %or = or i64 %shl1, %shl
+  ret i64 %or
+}
+
+define i64 @packu_i64(i64 %a, i64 %b) nounwind {
+; RV64I-LABEL: packu_i64:
+; RV64I:       # %bb.0:
+; RV64I-NEXT:    srli a0, a0, 32
+; RV64I-NEXT:    srli a1, a1, 32
+; RV64I-NEXT:    slli a1, a1, 32
+; RV64I-NEXT:    or a0, a1, a0
+; RV64I-NEXT:    ret
+;
+; RV64ZBPBO-LABEL: packu_i64:
+; RV64ZBPBO:       # %bb.0:
+; RV64ZBPBO-NEXT:    packu a0, a0, a1
+; RV64ZBPBO-NEXT:    ret
+  %shr = lshr i64 %a, 32
+  %shr1 = and i64 %b, -4294967296
+  %or = or i64 %shr1, %shr
+  ret i64 %or
+}
+
+; TODO: fsrw
+
+define i64 @max_i64(i64 %a, i64 %b) nounwind {
+; RV64I-LABEL: max_i64:
+; RV64I:       # %bb.0:
+; RV64I-NEXT:    blt a1, a0, .LBB2_2
+; RV64I-NEXT:  # %bb.1:
+; RV64I-NEXT:    mv a0, a1
+; RV64I-NEXT:  .LBB2_2:
+; RV64I-NEXT:    ret
+;
+; RV64ZBPBO-LABEL: max_i64:
+; RV64ZBPBO:       # %bb.0:
+; RV64ZBPBO-NEXT:    max a0, a0, a1
+; RV64ZBPBO-NEXT:    ret
+  %cmp = icmp sgt i64 %a, %b
+  %cond = select i1 %cmp, i64 %a, i64 %b
+  ret i64 %cond
+}
+
+define i64 @min_i64(i64 %a, i64 %b) nounwind {
+; RV64I-LABEL: min_i64:
+; RV64I:       # %bb.0:
+; RV64I-NEXT:    blt a0, a1, .LBB3_2
+; RV64I-NEXT:  # %bb.1:
+; RV64I-NEXT:    mv a0, a1
+; RV64I-NEXT:  .LBB3_2:
+; RV64I-NEXT:    ret
+;
+; RV64ZBPBO-LABEL: min_i64:
+; RV64ZBPBO:       # %bb.0:
+; RV64ZBPBO-NEXT:    min a0, a0, a1
+; RV64ZBPBO-NEXT:    ret
+  %cmp = icmp slt i64 %a, %b
+  %cond = select i1 %cmp, i64 %a, i64 %b
+  ret i64 %cond
+}
+
+; TODO: rev8.h, rev
+
+define i64 @cmix_i64(i64 %a, i64 %b, i64 %c) nounwind {
+; RV64I-LABEL: cmix_i64:
+; RV64I:       # %bb.0:
+; RV64I-NEXT:    and a0, a1, a0
+; RV64I-NEXT:    not a1, a1
+; RV64I-NEXT:    and a1, a1, a2
+; RV64I-NEXT:    or a0, a1, a0
+; RV64I-NEXT:    ret
+;
+; RV64ZBPBO-LABEL: cmix_i64:
+; RV64ZBPBO:       # %bb.0:
+; RV64ZBPBO-NEXT:    cmix a0, a1, a0, a2
+; RV64ZBPBO-NEXT:    ret
+  %and = and i64 %b, %a
+  %neg = xor i64 %b, -1
+  %and1 = and i64 %neg, %c
+  %or = or i64 %and1, %and
+  ret i64 %or
+}
Index: llvm/test/CodeGen/RISCV/rv32zbpbo.ll
===================================================================
--- /dev/null
+++ llvm/test/CodeGen/RISCV/rv32zbpbo.ll
@@ -0,0 +1,208 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc -mtriple=riscv32 -verify-machineinstrs < %s \
+; RUN:   | FileCheck %s -check-prefix=RV32I
+; RUN: llc -mtriple=riscv32 -mattr=+experimental-zbpbo -verify-machineinstrs < %s \
+; RUN:   | FileCheck %s -check-prefix=RV32ZBPBO
+
+declare i32 @llvm.ctlz.i32(i32, i1)
+
+define i32 @ctlz_i32(i32 %a) nounwind {
+; CHECK-LABEL: ctlz_i32:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    addi sp, sp, -16
+; CHECK-NEXT:    sw ra, 12(sp) # 4-byte Folded Spill
+; CHECK-NEXT:    beqz a0, .LBB0_2
+; CHECK-NEXT:  # %bb.1: # %cond.false
+; CHECK-NEXT:    srli a1, a0, 1
+; CHECK-NEXT:    or a0, a0, a1
+; CHECK-NEXT:    srli a1, a0, 2
+; CHECK-NEXT:    or a0, a0, a1
+; CHECK-NEXT:    srli a1, a0, 4
+; CHECK-NEXT:    or a0, a0, a1
+; CHECK-NEXT:    srli a1, a0, 8
+; CHECK-NEXT:    or a0, a0, a1
+; CHECK-NEXT:    srli a1, a0, 16
+; CHECK-NEXT:    or a0, a0, a1
+; CHECK-NEXT:    not a0, a0
+; CHECK-NEXT:    srli a1, a0, 1
+; CHECK-NEXT:    lui a2, 349525
+; CHECK-NEXT:    addi a2, a2, 1365
+; CHECK-NEXT:    and a1, a1, a2
+; CHECK-NEXT:    sub a0, a0, a1
+; CHECK-NEXT:    lui a1, 209715
+; CHECK-NEXT:    addi a1, a1, 819
+; CHECK-NEXT:    and a2, a0, a1
+; CHECK-NEXT:    srli a0, a0, 2
+; CHECK-NEXT:    and a0, a0, a1
+; CHECK-NEXT:    add a0, a2, a0
+; CHECK-NEXT:    srli a1, a0, 4
+; CHECK-NEXT:    add a0, a0, a1
+; CHECK-NEXT:    lui a1, 61681
+; CHECK-NEXT:    addi a1, a1, -241
+; CHECK-NEXT:    and a0, a0, a1
+; CHECK-NEXT:    lui a1, 4112
+; CHECK-NEXT:    addi a1, a1, 257
+; CHECK-NEXT:    call __mulsi3@plt
+; CHECK-NEXT:    srli a0, a0, 24
+; CHECK-NEXT:    j .LBB0_3
+; CHECK-NEXT:  .LBB0_2:
+; CHECK-NEXT:    li a0, 32
+; CHECK-NEXT:  .LBB0_3: # %cond.end
+; CHECK-NEXT:    lw ra, 12(sp) # 4-byte Folded Reload
+; CHECK-NEXT:    addi sp, sp, 16
+; CHECK-NEXT:    ret
+; RV32I-LABEL: ctlz_i32:
+; RV32I:       # %bb.0:
+; RV32I-NEXT:    addi sp, sp, -16
+; RV32I-NEXT:    sw ra, 12(sp) # 4-byte Folded Spill
+; RV32I-NEXT:    beqz a0, .LBB0_2
+; RV32I-NEXT:  # %bb.1: # %cond.false
+; RV32I-NEXT:    srli a1, a0, 1
+; RV32I-NEXT:    or a0, a0, a1
+; RV32I-NEXT:    srli a1, a0, 2
+; RV32I-NEXT:    or a0, a0, a1
+; RV32I-NEXT:    srli a1, a0, 4
+; RV32I-NEXT:    or a0, a0, a1
+; RV32I-NEXT:    srli a1, a0, 8
+; RV32I-NEXT:    or a0, a0, a1
+; RV32I-NEXT:    srli a1, a0, 16
+; RV32I-NEXT:    or a0, a0, a1
+; RV32I-NEXT:    not a0, a0
+; RV32I-NEXT:    srli a1, a0, 1
+; RV32I-NEXT:    lui a2, 349525
+; RV32I-NEXT:    addi a2, a2, 1365
+; RV32I-NEXT:    and a1, a1, a2
+; RV32I-NEXT:    sub a0, a0, a1
+; RV32I-NEXT:    lui a1, 209715
+; RV32I-NEXT:    addi a1, a1, 819
+; RV32I-NEXT:    and a2, a0, a1
+; RV32I-NEXT:    srli a0, a0, 2
+; RV32I-NEXT:    and a0, a0, a1
+; RV32I-NEXT:    add a0, a2, a0
+; RV32I-NEXT:    srli a1, a0, 4
+; RV32I-NEXT:    add a0, a0, a1
+; RV32I-NEXT:    lui a1, 61681
+; RV32I-NEXT:    addi a1, a1, -241
+; RV32I-NEXT:    and a0, a0, a1
+; RV32I-NEXT:    lui a1, 4112
+; RV32I-NEXT:    addi a1, a1, 257
+; RV32I-NEXT:    call __mulsi3@plt
+; RV32I-NEXT:    srli a0, a0, 24
+; RV32I-NEXT:    j .LBB0_3
+; RV32I-NEXT:  .LBB0_2:
+; RV32I-NEXT:    li a0, 32
+; RV32I-NEXT:  .LBB0_3: # %cond.end
+; RV32I-NEXT:    lw ra, 12(sp) # 4-byte Folded Reload
+; RV32I-NEXT:    addi sp, sp, 16
+; RV32I-NEXT:    ret
+;
+; RV32ZBPBO-LABEL: ctlz_i32:
+; RV32ZBPBO:       # %bb.0:
+; RV32ZBPBO-NEXT:    beqz a0, .LBB0_2
+; RV32ZBPBO-NEXT:  # %bb.1: # %cond.false
+; RV32ZBPBO-NEXT:    clz a0, a0
+; RV32ZBPBO-NEXT:    ret
+; RV32ZBPBO-NEXT:  .LBB0_2:
+; RV32ZBPBO-NEXT:    li a0, 32
+; RV32ZBPBO-NEXT:    ret
+  %1 = call i32 @llvm.ctlz.i32(i32 %a, i1 false)
+  ret i32 %1
+}
+
+define i32 @pack_i32(i32 %a, i32 %b) nounwind {
+; RV32I-LABEL: pack_i32:
+; RV32I:       # %bb.0:
+; RV32I-NEXT:    slli a0, a0, 16
+; RV32I-NEXT:    srli a0, a0, 16
+; RV32I-NEXT:    slli a1, a1, 16
+; RV32I-NEXT:    or a0, a1, a0
+; RV32I-NEXT:    ret
+;
+; RV32ZBPBO-LABEL: pack_i32:
+; RV32ZBPBO:       # %bb.0:
+; RV32ZBPBO-NEXT:    pack a0, a0, a1
+; RV32ZBPBO-NEXT:    ret
+  %shl = and i32 %a, 65535
+  %shl1 = shl i32 %b, 16
+  %or = or i32 %shl1, %shl
+  ret i32 %or
+}
+
+define i32 @packu_i32(i32 %a, i32 %b) nounwind {
+; RV32I-LABEL: packu_i32:
+; RV32I:       # %bb.0:
+; RV32I-NEXT:    srli a0, a0, 16
+; RV32I-NEXT:    lui a2, 1048560
+; RV32I-NEXT:    and a1, a1, a2
+; RV32I-NEXT:    or a0, a1, a0
+; RV32I-NEXT:    ret
+;
+; RV32ZBPBO-LABEL: packu_i32:
+; RV32ZBPBO:       # %bb.0:
+; RV32ZBPBO-NEXT:    packu a0, a0, a1
+; RV32ZBPBO-NEXT:    ret
+  %shr = lshr i32 %a, 16
+  %shr1 = and i32 %b, -65536
+  %or = or i32 %shr1, %shr
+  ret i32 %or
+}
+
+; TODO: fsr,fsri
+
+define i32 @max_i32(i32 %a, i32 %b) nounwind {
+; RV32I-LABEL: max_i32:
+; RV32I:       # %bb.0:
+; RV32I-NEXT:    blt a1, a0, .LBB3_2
+; RV32I-NEXT:  # %bb.1:
+; RV32I-NEXT:    mv a0, a1
+; RV32I-NEXT:  .LBB3_2:
+; RV32I-NEXT:    ret
+;
+; RV32ZBPBO-LABEL: max_i32:
+; RV32ZBPBO:       # %bb.0:
+; RV32ZBPBO-NEXT:    max a0, a0, a1
+; RV32ZBPBO-NEXT:    ret
+  %cmp = icmp sgt i32 %a, %b
+  %cond = select i1 %cmp, i32 %a, i32 %b
+  ret i32 %cond
+}
+
+define i32 @min_i32(i32 %a, i32 %b) nounwind {
+; RV32I-LABEL: min_i32:
+; RV32I:       # %bb.0:
+; RV32I-NEXT:    blt a0, a1, .LBB4_2
+; RV32I-NEXT:  # %bb.1:
+; RV32I-NEXT:    mv a0, a1
+; RV32I-NEXT:  .LBB4_2:
+; RV32I-NEXT:    ret
+;
+; RV32ZBPBO-LABEL: min_i32:
+; RV32ZBPBO:       # %bb.0:
+; RV32ZBPBO-NEXT:    min a0, a0, a1
+; RV32ZBPBO-NEXT:    ret
+  %cmp = icmp slt i32 %a, %b
+  %cond = select i1 %cmp, i32 %a, i32 %b
+  ret i32 %cond
+}
+
+; TODO: rev8.h, rev
+
+define i32 @cmix_i32(i32 %a, i32 %b, i32 %c) nounwind {
+; RV32I-LABEL: cmix_i32:
+; RV32I:       # %bb.0:
+; RV32I-NEXT:    and a0, a1, a0
+; RV32I-NEXT:    not a1, a1
+; RV32I-NEXT:    and a1, a1, a2
+; RV32I-NEXT:    or a0, a1, a0
+; RV32I-NEXT:    ret
+;
+; RV32ZBPBO-LABEL: cmix_i32:
+; RV32ZBPBO:       # %bb.0:
+; RV32ZBPBO-NEXT:    cmix a0, a1, a0, a2
+; RV32ZBPBO-NEXT:    ret
+  %and = and i32 %b, %a
+  %neg = xor i32 %b, -1
+  %and1 = and i32 %neg, %c
+  %or = or i32 %and1, %and
+  ret i32 %or
+}
Index: llvm/lib/Target/RISCV/RISCVSubtarget.h
===================================================================
--- llvm/lib/Target/RISCV/RISCVSubtarget.h
+++ llvm/lib/Target/RISCV/RISCVSubtarget.h
@@ -60,6 +60,7 @@
   bool HasStdExtZbr = false;
   bool HasStdExtZbs = false;
   bool HasStdExtZbt = false;
+  bool HasStdExtZbpbo = false;
   bool HasStdExtV = false;
   bool HasStdExtZve32x = false;
   bool HasStdExtZve32f = false;
@@ -158,6 +159,7 @@
   bool hasStdExtZbf() const { return HasStdExtZbf; }
   bool hasStdExtZbm() const { return HasStdExtZbm; }
   bool hasStdExtZbp() const { return HasStdExtZbp; }
+  bool hasStdExtZbpbo() const { return HasStdExtZbpbo; }
   bool hasStdExtZbr() const { return HasStdExtZbr; }
   bool hasStdExtZbs() const { return HasStdExtZbs; }
   bool hasStdExtZbt() const { return HasStdExtZbt; }
Index: llvm/lib/Target/RISCV/RISCVInstrInfoZb.td
===================================================================
--- llvm/lib/Target/RISCV/RISCVInstrInfoZb.td
+++ llvm/lib/Target/RISCV/RISCVInstrInfoZb.td
@@ -451,34 +451,41 @@
 } // Predicates = [HasStdExtZbpOrZbkx]
 
 let Predicates = [HasStdExtZbt] in {
-def CMIX : RVBTernaryR<0b11, 0b001, OPC_OP, "cmix", "$rd, $rs2, $rs1, $rs3">,
-           Sched<[WriteCMix, ReadCMix, ReadCMix, ReadCMix]>;
 def CMOV : RVBTernaryR<0b11, 0b101, OPC_OP, "cmov", "$rd, $rs2, $rs1, $rs3">,
            Sched<[WriteCMov, ReadCMov, ReadCMov, ReadCMov]>;
 def FSL  : RVBTernaryR<0b10, 0b001, OPC_OP, "fsl", "$rd, $rs1, $rs3, $rs2">,
            Sched<[WriteFSReg, ReadFSReg, ReadFSReg, ReadFSReg]>;
+} // Predicates = [HasStdExtZbt]
+
+let Predicates = [HasStdExtZbtOrZbpbo] in {
+def CMIX : RVBTernaryR<0b11, 0b001, OPC_OP, "cmix", "$rd, $rs2, $rs1, $rs3">,
+           Sched<[WriteCMix, ReadCMix, ReadCMix, ReadCMix]>;
 def FSR  : RVBTernaryR<0b10, 0b101, OPC_OP, "fsr", "$rd, $rs1, $rs3, $rs2">,
            Sched<[WriteFSReg, ReadFSReg, ReadFSReg, ReadFSReg]>;
 def FSRI : RVBTernaryImm6<0b101, OPC_OP_IMM, "fsri",
                           "$rd, $rs1, $rs3, $shamt">,
            Sched<[WriteFSRImm, ReadFSRImm, ReadFSRImm]>;
-} // Predicates = [HasStdExtZbt]
+} // Predicates = [HasStdExtZbtOrZbpbo]
 
 let Predicates = [HasStdExtZbt, IsRV64] in {
 def FSLW  : RVBTernaryR<0b10, 0b001, OPC_OP_32,
                         "fslw", "$rd, $rs1, $rs3, $rs2">,
             Sched<[WriteFSReg32, ReadFSReg32, ReadFSReg32, ReadFSReg32]>;
-def FSRW  : RVBTernaryR<0b10, 0b101, OPC_OP_32, "fsrw",
-                        "$rd, $rs1, $rs3, $rs2">,
-            Sched<[WriteFSReg32, ReadFSReg32, ReadFSReg32, ReadFSReg32]>;
 def FSRIW : RVBTernaryImm5<0b10, 0b101, OPC_OP_IMM_32,
                            "fsriw", "$rd, $rs1, $rs3, $shamt">,
             Sched<[WriteFSRImm32, ReadFSRImm32, ReadFSRImm32]>;
 } // Predicates = [HasStdExtZbt, IsRV64]
 
-let Predicates = [HasStdExtZbb] in {
+let Predicates = [HasStdExtZbtOrZbpbo, IsRV64] in
+def FSRW  : RVBTernaryR<0b10, 0b101, OPC_OP_32, "fsrw",
+                        "$rd, $rs1, $rs3, $rs2">,
+            Sched<[WriteFSReg32, ReadFSReg32, ReadFSReg32, ReadFSReg32]>;
+
+let Predicates = [HasStdExtZbbOrZbpbo] in
 def CLZ  : RVBUnary<0b0110000, 0b00000, 0b001, OPC_OP_IMM, "clz">,
            Sched<[WriteCLZ, ReadCLZ]>;
+
+let Predicates = [HasStdExtZbb] in {
 def CTZ  : RVBUnary<0b0110000, 0b00001, 0b001, OPC_OP_IMM, "ctz">,
            Sched<[WriteCTZ, ReadCTZ]>;
 def CPOP : RVBUnary<0b0110000, 0b00010, 0b001, OPC_OP_IMM, "cpop">,
@@ -537,13 +544,16 @@
              Sched<[WriteCLMUL, ReadCLMUL, ReadCLMUL]>;
 } // Predicates = [HasStdExtZbcOrZbkc]
 
-let Predicates = [HasStdExtZbb] in {
+let Predicates = [HasStdExtZbbOrZbpbo] in {
 def MIN  : ALU_rr<0b0000101, 0b100, "min", /*Commutable*/1>,
            Sched<[WriteIALU, ReadIALU, ReadIALU]>;
-def MINU : ALU_rr<0b0000101, 0b101, "minu", /*Commutable*/1>,
-           Sched<[WriteIALU, ReadIALU, ReadIALU]>;
 def MAX  : ALU_rr<0b0000101, 0b110, "max", /*Commutable*/1>,
            Sched<[WriteIALU, ReadIALU, ReadIALU]>;
+} // Predicates = [HasStdExtZbbOrZbpbo]
+
+let Predicates = [HasStdExtZbb] in {
+def MINU : ALU_rr<0b0000101, 0b101, "minu", /*Commutable*/1>,
+           Sched<[WriteIALU, ReadIALU, ReadIALU]>;
 def MAXU : ALU_rr<0b0000101, 0b111, "maxu", /*Commutable*/1>,
            Sched<[WriteIALU, ReadIALU, ReadIALU]>;
 } // Predicates = [HasStdExtZbb]
@@ -566,18 +576,19 @@
                    Sched<[WriteCompress32, ReadCompress32, ReadCompress32]>;
 } // Predicates = [HasStdExtZbe, IsRV64]
 
-let Predicates = [HasStdExtZbpOrZbkb] in {
+let Predicates = [HasStdExtZbpOrZbkbOrZbpbo] in
 def PACK  : ALU_rr<0b0000100, 0b100, "pack">,
             Sched<[WritePACK, ReadPACK, ReadPACK]>;
+
+let Predicates = [HasStdExtZbpOrZbkb] in
 def PACKH : ALU_rr<0b0000100, 0b111, "packh">,
             Sched<[WritePACK, ReadPACK, ReadPACK]>;
-} // Predicates = [HasStdExtZbpOrZbkb]
 
 let Predicates = [HasStdExtZbpOrZbkb, IsRV64] in 
 def PACKW  : ALUW_rr<0b0000100, 0b100, "packw">,
              Sched<[WritePACK32, ReadPACK32, ReadPACK32]>;
 
-let Predicates = [HasStdExtZbp] in 
+let Predicates = [HasStdExtZbpOrZbpbo] in 
 def PACKU : ALU_rr<0b0100100, 0b100, "packu">,
             Sched<[WritePACKU, ReadPACKU, ReadPACKU]>;
 
@@ -692,6 +703,9 @@
 def : InstAlias<"orc.h $rd, $rs",  (GORCI GPR:$rd, GPR:$rs, 0b01111)>;
 } // Predicates = [HasStdExtZbp]
 
+let Predicates = [HasStdExtZbpOrZbpbo] in
+def : InstAlias<"rev8.h $rd, $rs", (GREVI GPR:$rd, GPR:$rs, 0b01000)>;
+
 let Predicates = [HasStdExtZbp, IsRV32] in {
 def : InstAlias<"rev16 $rd, $rs", (GREVI GPR:$rd, GPR:$rs, 0b10000)>;
 // rev8 is considered an instruction rather than an alias.
@@ -714,6 +728,11 @@
 def : InstAlias<"orc $rd, $rs",   (GORCI GPR:$rd, GPR:$rs, 0b11111)>;
 } // Predicates = [HasStdExtZbp, IsRV32]
 
+let Predicates = [HasStdExtZbpOrZbpbo, IsRV32] in
+def : InstAlias<"rev $rd, $rs",   (GREVI GPR:$rd, GPR:$rs, 0b11111)>;
+let Predicates = [HasStdExtZbpOrZbpbo, IsRV64] in
+def : InstAlias<"rev $rd, $rs",   (GREVI GPR:$rd, GPR:$rs, 0b111111)>;
+
 let Predicates = [HasStdExtZbp, IsRV64] in {
 def : InstAlias<"rev16.w $rd, $rs", (GREVI GPR:$rd, GPR:$rs, 0b010000)>;
 def : InstAlias<"rev8.w $rd, $rs",  (GREVI GPR:$rd, GPR:$rs, 0b011000)>;
@@ -948,12 +967,14 @@
 def : Pat<(i64 (riscv_grev GPR:$rs1, 56)), (REV8_RV64 GPR:$rs1)>;
 } // Predicates = [HasStdExtZbp, IsRV64]
 
-let Predicates = [HasStdExtZbt] in {
+let Predicates = [HasStdExtZbtOrZbpbo] in {
 def : Pat<(or (and (not GPR:$rs2), GPR:$rs3), (and GPR:$rs2, GPR:$rs1)),
           (CMIX GPR:$rs1, GPR:$rs2, GPR:$rs3)>;
 def : Pat<(xor (and (xor GPR:$rs1, GPR:$rs3), GPR:$rs2), GPR:$rs3),
           (CMIX GPR:$rs1, GPR:$rs2, GPR:$rs3)>;
+} // Predicates = [HasStdExtZbtOrZbpbo]
 
+let Predicates = [HasStdExtZbt] in {
 def : Pat<(select (XLenVT (setne GPR:$rs2, 0)), GPR:$rs1, GPR:$rs3),
           (CMOV GPR:$rs1, GPR:$rs2, GPR:$rs3)>;
 def : Pat<(select (XLenVT (seteq GPR:$rs2, 0)), GPR:$rs3, GPR:$rs1),
@@ -985,9 +1006,11 @@
           (CMOV GPR:$rs1, GPR:$rs2, GPR:$rs3)>;
 } // Predicates = [HasStdExtZbt]
 
-let Predicates = [HasStdExtZbt] in {
+let Predicates = [HasStdExtZbt] in
 def : Pat<(riscv_fsl GPR:$rs1, GPR:$rs3, GPR:$rs2),
           (FSL GPR:$rs1, GPR:$rs2, GPR:$rs3)>;
+
+let Predicates = [HasStdExtZbtOrZbpbo] in {
 def : Pat<(riscv_fsr GPR:$rs1, GPR:$rs3, GPR:$rs2),
           (FSR GPR:$rs1, GPR:$rs2, GPR:$rs3)>;
 def : Pat<(riscv_fsr GPR:$rs1, GPR:$rs3, uimmlog2xlen:$shamt),
@@ -996,13 +1019,15 @@
 // XLen and swap the operands.
 def : Pat<(riscv_fsl GPR:$rs3, GPR:$rs1, uimmlog2xlen:$shamt),
           (FSRI GPR:$rs1, GPR:$rs3, (ImmSubFromXLen uimmlog2xlen:$shamt))>;
-} // Predicates = [HasStdExtZbt]
+} // Predicates = [HasStdExtZbtOrZbpbo]
+
+let Predicates = [HasStdExtZbtOrZbpbo, IsRV64] in
+def : Pat<(riscv_fsrw GPR:$rs1, GPR:$rs3, GPR:$rs2),
+          (FSRW GPR:$rs1, GPR:$rs2, GPR:$rs3)>;
 
 let Predicates = [HasStdExtZbt, IsRV64] in {
 def : Pat<(riscv_fslw GPR:$rs1, GPR:$rs3, GPR:$rs2),
           (FSLW GPR:$rs1, GPR:$rs2, GPR:$rs3)>;
-def : Pat<(riscv_fsrw GPR:$rs1, GPR:$rs3, GPR:$rs2),
-          (FSRW GPR:$rs1, GPR:$rs2, GPR:$rs3)>;
 def : Pat<(riscv_fsrw GPR:$rs1, GPR:$rs3, uimm5:$shamt),
           (FSRIW GPR:$rs1, GPR:$rs3, uimm5:$shamt)>;
 // We can use FSRIW for FSLW by immediate if we subtract the immediate from
@@ -1011,8 +1036,10 @@
           (FSRIW GPR:$rs1, GPR:$rs3, (ImmSubFrom32 uimm5:$shamt))>;
 } // Predicates = [HasStdExtZbt, IsRV64]
 
-let Predicates = [HasStdExtZbb] in {
+let Predicates = [HasStdExtZbbOrZbpbo] in
 def : PatGpr<ctlz, CLZ>;
+
+let Predicates = [HasStdExtZbb] in {
 def : PatGpr<cttz, CTZ>;
 def : PatGpr<ctpop, CPOP>;
 } // Predicates = [HasStdExtZbb]
@@ -1028,9 +1055,12 @@
 def : Pat<(sext_inreg GPR:$rs1, i16), (SEXT_H GPR:$rs1)>;
 } // Predicates = [HasStdExtZbb]
 
-let Predicates = [HasStdExtZbb] in {
+let Predicates = [HasStdExtZbbOrZbpbo] in {
 def : PatGprGpr<smin, MIN>;
 def : PatGprGpr<smax, MAX>;
+} // Predicates = [HasStdExtZbbOrZbpbo]
+
+let Predicates = [HasStdExtZbb] in {
 def : PatGprGpr<umin, MINU>;
 def : PatGprGpr<umax, MAXU>;
 } // Predicates = [HasStdExtZbb]
@@ -1052,14 +1082,15 @@
           (PACKH GPR:$rs1, GPR:$rs2)>;
 } // Predicates = [HasStdExtZbpOrZbkb]
 
-let Predicates = [HasStdExtZbpOrZbkb, IsRV32] in
+let Predicates = [HasStdExtZbpOrZbkbOrZbpbo, IsRV32] in
 def : Pat<(i32 (or (and GPR:$rs1, 0x0000FFFF), (shl GPR:$rs2, (i32 16)))),
           (PACK GPR:$rs1, GPR:$rs2)>;
 
-let Predicates = [HasStdExtZbpOrZbkb, IsRV64] in {
+let Predicates = [HasStdExtZbpOrZbkbOrZbpbo, IsRV64] in
 def : Pat<(i64 (or (and GPR:$rs1, 0x00000000FFFFFFFF), (shl GPR:$rs2, (i64 32)))),
           (PACK GPR:$rs1, GPR:$rs2)>;
 
+let Predicates = [HasStdExtZbpOrZbkb, IsRV64] in {
 def : Pat<(i64 (sext_inreg (or (shl GPR:$rs2, (i64 16)),
                                (and GPR:$rs1, 0x000000000000FFFF)),
                            i32)),
@@ -1069,18 +1100,18 @@
           (PACKW GPR:$rs1, GPR:$rs2)>;
 } // Predicates = [HasStdExtZbpOrZbkb, IsRV64]
 
-let Predicates = [HasStdExtZbp, IsRV32] in
+let Predicates = [HasStdExtZbpOrZbpbo, IsRV32] in
 def : Pat<(i32 (or (and GPR:$rs2, 0xFFFF0000), (srl GPR:$rs1, (i32 16)))),
           (PACKU GPR:$rs1, GPR:$rs2)>;
 
-let Predicates = [HasStdExtZbp, IsRV64] in {
+let Predicates = [HasStdExtZbpOrZbpbo, IsRV64] in
 def : Pat<(i64 (or (and GPR:$rs2, 0xFFFFFFFF00000000), (srl GPR:$rs1, (i64 32)))),
           (PACKU GPR:$rs1, GPR:$rs2)>;
 
+let Predicates = [HasStdExtZbp, IsRV64] in
 def : Pat<(i64 (or (and (assertsexti32 GPR:$rs2), 0xFFFFFFFFFFFF0000),
                    (srl (and GPR:$rs1, 0xFFFFFFFF), (i64 16)))),
           (PACKUW GPR:$rs1, GPR:$rs2)>;
-} // Predicates = [HasStdExtZbp, IsRV64]
 
 let Predicates = [HasStdExtZbbOrZbp, IsRV32] in
 def : Pat<(i32 (and GPR:$rs, 0xFFFF)), (ZEXT_H_RV32 GPR:$rs)>;
Index: llvm/lib/Target/RISCV/RISCVISelLowering.cpp
===================================================================
--- llvm/lib/Target/RISCV/RISCVISelLowering.cpp
+++ llvm/lib/Target/RISCV/RISCVISelLowering.cpp
@@ -283,6 +283,10 @@
     if (Subtarget.is64Bit())
       setOperationAction(ISD::ABS, MVT::i32, Custom);
   }
+  if (Subtarget.hasStdExtZbpbo()) {
+    setOperationAction({ISD::SMIN, ISD::SMAX}, XLenVT, Legal);
+    setOperationAction(ISD::CTLZ, MVT::i32, Legal);
+  }
 
   if (Subtarget.hasStdExtZbt()) {
     setOperationAction({ISD::FSHL, ISD::FSHR}, XLenVT, Custom);
@@ -294,6 +298,9 @@
     setOperationAction(ISD::SELECT, XLenVT, Custom);
   }
 
+  if (Subtarget.hasStdExtZbt())
+    setOperationAction({ISD::FSHL, ISD::FSHR}, XLenVT, Custom);
+
   static constexpr ISD::NodeType FPLegalNodeTypes[] = {
       ISD::FMINNUM,        ISD::FMAXNUM,       ISD::LRINT,
       ISD::LLRINT,         ISD::LROUND,        ISD::LLROUND,
Index: llvm/lib/Target/RISCV/RISCV.td
===================================================================
--- llvm/lib/Target/RISCV/RISCV.td
+++ llvm/lib/Target/RISCV/RISCV.td
@@ -247,6 +247,41 @@
                                    "'Zbc' (Carry-Less Multiplication) or "
                                    "'Zbkc' (Carry-less multiply instructions for Cryptography)">;
 
+def FeatureStdExtZbpbo
+    : SubtargetFeature<"experimental-zbpbo", "HasStdExtZbpbo", "true",
+                       "'Zbpbo' ('B' & 'P' Overlay Instructions)">;
+def HasStdExtZbpbo
+    : Predicate<"Subtarget->hasStdExtZbpbo()">,
+                             AssemblerPredicate<(all_of FeatureStdExtZbpbo),
+                             "'Zbpbo' ('B' & 'P' Overlay Instructions)">;
+
+def HasStdExtZbbOrZbpbo
+    : Predicate<"Subtarget->hasStdExtZbb() || Subtarget->hasStdExtZbpbo()">,
+                AssemblerPredicate<(any_of FeatureStdExtZbb, FeatureStdExtZbpbo),
+                                   "'Zbb' (Basic Bit-Manipulation) or "
+                                   "'Zbpbo' ('B' & 'P' Overlay Instructions)">;
+
+def HasStdExtZbpOrZbpbo
+    : Predicate<"Subtarget->hasStdExtZbp() || Subtarget->hasStdExtZbpbo()">,
+                AssemblerPredicate<(any_of FeatureStdExtZbp, FeatureStdExtZbpbo),
+                                   "'Zbp' (Permutation 'Zb' Instructions) or "
+                                   "'Zbpbo' ('B' & 'P' Overlay Instructions)">;
+
+def HasStdExtZbpOrZbkbOrZbpbo
+    : Predicate<"Subtarget->hasStdExtZbp() || Subtarget->hasStdExtZbkb()"
+                 "|| Subtarget->hasStdExtZbpbo()">,
+                AssemblerPredicate<(any_of FeatureStdExtZbp, FeatureStdExtZbkb,
+                                           FeatureStdExtZbpbo),
+                                   "'Zbp' (Permutation 'Zb' Instructions) or "
+                                   "'Zbkb' (Bitmanip instructions for Cryptography) or "
+                                   "'Zbpbo' ('B' & 'P' Overlay Instructions)">;
+
+def HasStdExtZbtOrZbpbo
+    : Predicate<"Subtarget->hasStdExtZbt() || Subtarget->hasStdExtZbpbo()">,
+                AssemblerPredicate<(any_of FeatureStdExtZbt, FeatureStdExtZbpbo),
+                                   "'Zbt' (Ternary 'Zb' Instructions) or "
+                                   "'Zbpbo' ('B' & 'P' Overlay Instructions)">;
+
 def FeatureStdExtZknd
     : SubtargetFeature<"zknd", "HasStdExtZknd", "true",
                        "'Zknd' (NIST Suite: AES Decryption)">;
Index: llvm/lib/Support/RISCVISAInfo.cpp
===================================================================
--- llvm/lib/Support/RISCVISAInfo.cpp
+++ llvm/lib/Support/RISCVISAInfo.cpp
@@ -104,6 +104,7 @@
     {"zbp", RISCVExtensionVersion{0, 93}},
     {"zbr", RISCVExtensionVersion{0, 93}},
     {"zbt", RISCVExtensionVersion{0, 93}},
+    {"zbpbo", RISCVExtensionVersion{0, 911}},
     {"zvfh", RISCVExtensionVersion{0, 1}},
 };
 
Index: clang/test/CodeGen/RISCV/rvp-intrinsics/riscv64-zbpbo.c
===================================================================
--- /dev/null
+++ clang/test/CodeGen/RISCV/rvp-intrinsics/riscv64-zbpbo.c
@@ -0,0 +1,33 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py
+// RUN: %clang_cc1 -no-opaque-pointers -triple riscv64 -target-feature +experimental-zbpbo -emit-llvm %s -o - \
+// RUN:     | FileCheck %s  -check-prefix=RV64ZBPBO
+
+// RV64ZBPBO-LABEL: @fsrw(
+// RV64ZBPBO-NEXT:  entry:
+// RV64ZBPBO-NEXT:    [[RS1_ADDR:%.*]] = alloca i64, align 8
+// RV64ZBPBO-NEXT:    [[RS2_ADDR:%.*]] = alloca i64, align 8
+// RV64ZBPBO-NEXT:    [[RS3_ADDR:%.*]] = alloca i64, align 8
+// RV64ZBPBO-NEXT:    store i64 [[RS1:%.*]], i64* [[RS1_ADDR]], align 8
+// RV64ZBPBO-NEXT:    store i64 [[RS2:%.*]], i64* [[RS2_ADDR]], align 8
+// RV64ZBPBO-NEXT:    store i64 [[RS3:%.*]], i64* [[RS3_ADDR]], align 8
+// RV64ZBPBO-NEXT:    [[TMP0:%.*]] = load i64, i64* [[RS1_ADDR]], align 8
+// RV64ZBPBO-NEXT:    [[TMP1:%.*]] = load i64, i64* [[RS2_ADDR]], align 8
+// RV64ZBPBO-NEXT:    [[TMP2:%.*]] = load i64, i64* [[RS3_ADDR]], align 8
+// RV64ZBPBO-NEXT:    [[TMP3:%.*]] = call i64 @llvm.riscv.fsr.i64(i64 [[TMP0]], i64 [[TMP1]], i64 [[TMP2]])
+// RV64ZBPBO-NEXT:    ret i64 [[TMP3]]
+//
+long fsrw(long rs1, long rs2, long rs3) {
+  return __builtin_riscv_fsr_64(rs1, rs2, rs3);
+}
+
+// RV64ZBPBO-LABEL: @grevi(
+// RV64ZBPBO-NEXT:  entry:
+// RV64ZBPBO-NEXT:    [[RS1_ADDR:%.*]] = alloca i64, align 8
+// RV64ZBPBO-NEXT:    store i64 [[RS1:%.*]], i64* [[RS1_ADDR]], align 8
+// RV64ZBPBO-NEXT:    [[TMP0:%.*]] = load i64, i64* [[RS1_ADDR]], align 8
+// RV64ZBPBO-NEXT:    [[TMP1:%.*]] = call i64 @llvm.riscv.grev.i64(i64 [[TMP0]], i64 13)
+// RV64ZBPBO-NEXT:    ret i64 [[TMP1]]
+//
+long grevi(long rs1) {
+  return __builtin_riscv_grev_64(rs1, 13);
+}
Index: clang/test/CodeGen/RISCV/rvp-intrinsics/riscv32-zbpbo.c
===================================================================
--- /dev/null
+++ clang/test/CodeGen/RISCV/rvp-intrinsics/riscv32-zbpbo.c
@@ -0,0 +1,60 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py
+// RUN: %clang_cc1 -no-opaque-pointers -triple riscv32 -target-feature +experimental-zbpbo -emit-llvm %s -o - \
+// RUN:     | FileCheck %s  -check-prefix=RV32ZBPBO
+
+// RV32ZBPBO-LABEL: @clz_32(
+// RV32ZBPBO-NEXT:  entry:
+// RV32ZBPBO-NEXT:    [[A_ADDR:%.*]] = alloca i32, align 4
+// RV32ZBPBO-NEXT:    store i32 [[A:%.*]], i32* [[A_ADDR]], align 4
+// RV32ZBPBO-NEXT:    [[TMP0:%.*]] = load i32, i32* [[A_ADDR]], align 4
+// RV32ZBPBO-NEXT:    [[TMP1:%.*]] = call i32 @llvm.ctlz.i32(i32 [[TMP0]], i1 false)
+// RV32ZBPBO-NEXT:    ret i32 [[TMP1]]
+//
+int clz_32(int a) {
+  return __builtin_riscv_clz_32(a);
+}
+
+// RV32ZBPBO-LABEL: @fsr(
+// RV32ZBPBO-NEXT:  entry:
+// RV32ZBPBO-NEXT:    [[RS1_ADDR:%.*]] = alloca i32, align 4
+// RV32ZBPBO-NEXT:    [[RS2_ADDR:%.*]] = alloca i32, align 4
+// RV32ZBPBO-NEXT:    [[RS3_ADDR:%.*]] = alloca i32, align 4
+// RV32ZBPBO-NEXT:    store i32 [[RS1:%.*]], i32* [[RS1_ADDR]], align 4
+// RV32ZBPBO-NEXT:    store i32 [[RS2:%.*]], i32* [[RS2_ADDR]], align 4
+// RV32ZBPBO-NEXT:    store i32 [[RS3:%.*]], i32* [[RS3_ADDR]], align 4
+// RV32ZBPBO-NEXT:    [[TMP0:%.*]] = load i32, i32* [[RS1_ADDR]], align 4
+// RV32ZBPBO-NEXT:    [[TMP1:%.*]] = load i32, i32* [[RS2_ADDR]], align 4
+// RV32ZBPBO-NEXT:    [[TMP2:%.*]] = load i32, i32* [[RS3_ADDR]], align 4
+// RV32ZBPBO-NEXT:    [[TMP3:%.*]] = call i32 @llvm.riscv.fsr.i32(i32 [[TMP0]], i32 [[TMP1]], i32 [[TMP2]])
+// RV32ZBPBO-NEXT:    ret i32 [[TMP3]]
+//
+int fsr(int rs1, int rs2, int rs3) {
+  return __builtin_riscv_fsr_32(rs1, rs2, rs3);
+}
+
+// RV32ZBPBO-LABEL: @fsri(
+// RV32ZBPBO-NEXT:  entry:
+// RV32ZBPBO-NEXT:    [[RS1_ADDR:%.*]] = alloca i32, align 4
+// RV32ZBPBO-NEXT:    [[RS2_ADDR:%.*]] = alloca i32, align 4
+// RV32ZBPBO-NEXT:    store i32 [[RS1:%.*]], i32* [[RS1_ADDR]], align 4
+// RV32ZBPBO-NEXT:    store i32 [[RS2:%.*]], i32* [[RS2_ADDR]], align 4
+// RV32ZBPBO-NEXT:    [[TMP0:%.*]] = load i32, i32* [[RS1_ADDR]], align 4
+// RV32ZBPBO-NEXT:    [[TMP1:%.*]] = load i32, i32* [[RS2_ADDR]], align 4
+// RV32ZBPBO-NEXT:    [[TMP2:%.*]] = call i32 @llvm.riscv.fsr.i32(i32 [[TMP0]], i32 [[TMP1]], i32 15)
+// RV32ZBPBO-NEXT:    ret i32 [[TMP2]]
+//
+int fsri(int rs1, int rs2) {
+  return __builtin_riscv_fsr_32(rs1, rs2, 15);
+}
+
+// RV32ZBPBO-LABEL: @grevi(
+// RV32ZBPBO-NEXT:  entry:
+// RV32ZBPBO-NEXT:    [[RS1_ADDR:%.*]] = alloca i32, align 4
+// RV32ZBPBO-NEXT:    store i32 [[RS1:%.*]], i32* [[RS1_ADDR]], align 4
+// RV32ZBPBO-NEXT:    [[TMP0:%.*]] = load i32, i32* [[RS1_ADDR]], align 4
+// RV32ZBPBO-NEXT:    [[TMP1:%.*]] = call i32 @llvm.riscv.grev.i32(i32 [[TMP0]], i32 13)
+// RV32ZBPBO-NEXT:    ret i32 [[TMP1]]
+//
+long grevi(long rs1) {
+  return __builtin_riscv_grev_32(rs1, 13);
+}
Index: clang/include/clang/Basic/BuiltinsRISCV.def
===================================================================
--- clang/include/clang/Basic/BuiltinsRISCV.def
+++ clang/include/clang/Basic/BuiltinsRISCV.def
@@ -18,7 +18,7 @@
 // Zbb extension
 TARGET_BUILTIN(__builtin_riscv_orc_b_32, "ZiZi", "nc", "zbb")
 TARGET_BUILTIN(__builtin_riscv_orc_b_64, "WiWi", "nc", "zbb,64bit")
-TARGET_BUILTIN(__builtin_riscv_clz_32, "ZiZi", "nc", "zbb")
+TARGET_BUILTIN(__builtin_riscv_clz_32, "ZiZi", "nc", "zbb|experimental-zbpbo")
 TARGET_BUILTIN(__builtin_riscv_clz_64, "WiWi", "nc", "zbb,64bit")
 TARGET_BUILTIN(__builtin_riscv_ctz_32, "ZiZi", "nc", "zbb")
 TARGET_BUILTIN(__builtin_riscv_ctz_64, "WiWi", "nc", "zbb,64bit")
@@ -46,8 +46,10 @@
 TARGET_BUILTIN(__builtin_riscv_bfp_64, "WiWiWi", "nc", "experimental-zbf,64bit")
 
 // Zbp extension
-TARGET_BUILTIN(__builtin_riscv_grev_32, "ZiZiZi", "nc", "experimental-zbp")
-TARGET_BUILTIN(__builtin_riscv_grev_64, "WiWiWi", "nc", "experimental-zbp,64bit")
+TARGET_BUILTIN(__builtin_riscv_grev_32, "ZiZiZi", "nc",
+               "experimental-zbp|experimental-zbpbo")
+TARGET_BUILTIN(__builtin_riscv_grev_64, "WiWiWi", "nc",
+               "experimental-zbp|experimental-zbpbo,64bit")
 TARGET_BUILTIN(__builtin_riscv_gorc_32, "ZiZiZi", "nc", "experimental-zbp")
 TARGET_BUILTIN(__builtin_riscv_gorc_64, "WiWiWi", "nc", "experimental-zbp,64bit")
 TARGET_BUILTIN(__builtin_riscv_shfl_32, "ZiZiZi", "nc", "experimental-zbp")
@@ -71,9 +73,11 @@
 
 // Zbt extension
 TARGET_BUILTIN(__builtin_riscv_fsl_32, "LiLiLiLi", "nc", "experimental-zbt")
-TARGET_BUILTIN(__builtin_riscv_fsr_32, "LiLiLiLi", "nc", "experimental-zbt")
+TARGET_BUILTIN(__builtin_riscv_fsr_32, "LiLiLiLi", "nc",
+               "experimental-zbt|experimental-zbpbo")
 TARGET_BUILTIN(__builtin_riscv_fsl_64, "WiWiWiWi", "nc", "experimental-zbt,64bit")
-TARGET_BUILTIN(__builtin_riscv_fsr_64, "WiWiWiWi", "nc", "experimental-zbt,64bit")
+TARGET_BUILTIN(__builtin_riscv_fsr_64, "WiWiWiWi", "nc",
+               "experimental-zbt|experimental-zbpbo,64bit")
 
 // Zbkb extension
 TARGET_BUILTIN(__builtin_riscv_brev8, "LiLi", "nc", "zbkb")
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to