sunshaoce updated this revision to Diff 443555.
sunshaoce added a comment.

Rebase


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D128604/new/

https://reviews.llvm.org/D128604

Files:
  clang/include/clang/Basic/BuiltinsRISCV.def
  clang/lib/Sema/SemaChecking.cpp
  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/attributes.ll
  llvm/test/CodeGen/RISCV/rv32zbpbo-intrinsics.ll
  llvm/test/CodeGen/RISCV/rv32zbpbo.ll
  llvm/test/CodeGen/RISCV/rv64zbpbo-intrinsics.ll
  llvm/test/CodeGen/RISCV/rv64zbpbo.ll
  llvm/test/MC/RISCV/rv32zbpbo-aliases-valid.s
  llvm/test/MC/RISCV/rv32zbpbo-valid.s
  llvm/test/MC/RISCV/rv64zbpbo-aliases-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,29 @@
+# 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-ASM-AND-OBJ: cmix t0, t1, t2, t3
+# CHECK-ASM: encoding: [0xb3,0x92,0x63,0xe6]
+cmix t0, t1, t2, t3
Index: llvm/test/MC/RISCV/rv64zbpbo-aliases-valid.s
===================================================================
--- /dev/null
+++ llvm/test/MC/RISCV/rv64zbpbo-aliases-valid.s
@@ -0,0 +1,18 @@
+# RUN: llvm-mc %s -triple=riscv64 -mattr=+experimental-zbpbo -riscv-no-aliases \
+# RUN:     | FileCheck -check-prefixes=CHECK-S-OBJ-NOALIAS %s
+# RUN: llvm-mc %s  -triple=riscv64 -mattr=+experimental-zbpbo \
+# RUN:     | FileCheck -check-prefixes=CHECK-S-OBJ %s
+# RUN: llvm-mc -filetype=obj -triple riscv64 -mattr=+experimental-zbpbo < %s \
+# RUN:     | llvm-objdump -d -r -M no-aliases --mattr=+experimental-zbpbo - \
+# RUN:     | FileCheck -check-prefixes=CHECK-S-OBJ-NOALIAS %s
+# RUN: llvm-mc -filetype=obj -triple riscv64 -mattr=+experimental-zbpbo < %s \
+# RUN:     | llvm-objdump -d -r --mattr=+experimental-zbpbo - \
+# RUN:     | FileCheck -check-prefixes=CHECK-S-OBJ %s
+
+# CHECK-S-OBJ-NOALIAS: grevi t0, t1, 8
+# CHECK-S-OBJ: rev8.h t0, t1
+rev8.h x5, x6
+
+# CHECK-S-OBJ-NOALIAS: grevi t0, t1, 63
+# CHECK-S-OBJ: rev t0, t1
+rev x5, x6
Index: llvm/test/MC/RISCV/rv32zbpbo-valid.s
===================================================================
--- /dev/null
+++ llvm/test/MC/RISCV/rv32zbpbo-valid.s
@@ -0,0 +1,37 @@
+# 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-ASM-AND-OBJ: cmix t0, t1, t2, t3
+# CHECK-ASM: encoding: [0xb3,0x92,0x63,0xe6]
+cmix t0, t1, t2, t3
Index: llvm/test/MC/RISCV/rv32zbpbo-aliases-valid.s
===================================================================
--- /dev/null
+++ llvm/test/MC/RISCV/rv32zbpbo-aliases-valid.s
@@ -0,0 +1,26 @@
+# RUN: llvm-mc %s -triple=riscv32 -mattr=+experimental-zbpbo -riscv-no-aliases \
+# RUN:     | FileCheck -check-prefixes=CHECK-S-OBJ-NOALIAS %s
+# RUN: llvm-mc %s -triple=riscv32 -mattr=+experimental-zbpbo \
+# RUN:     | FileCheck -check-prefixes=CHECK-S-OBJ %s
+# RUN: llvm-mc -filetype=obj -triple riscv32 -mattr=+experimental-zbpbo < %s \
+# RUN:     | llvm-objdump -d -r -M no-aliases --mattr=+experimental-zbpbo - \
+# RUN:     | FileCheck -check-prefixes=CHECK-S-OBJ-NOALIAS %s
+# RUN: llvm-mc -filetype=obj -triple riscv32 -mattr=+experimental-zbpbo < %s \
+# RUN:     | llvm-objdump -d -r --mattr=+experimental-zbpbo - \
+# RUN:     | FileCheck -check-prefixes=CHECK-S-OBJ %s
+
+# CHECK-S-OBJ-NOALIAS: grevi t0, t1, 8
+# CHECK-S-OBJ: rev8.h t0, t1
+rev8.h x5, x6
+
+# CHECK-S-OBJ-NOALIAS: grevi t0, t1, 31
+# CHECK-S-OBJ: rev t0, t1
+rev x5, x6
+
+# CHECK-S-OBJ-NOALIAS: pack t0, t1, t2
+# CHECK-S-OBJ: pkbb16 t0, t1, t2
+pkbb16 x5, x6, x7
+
+# CHECK-S-OBJ-NOALIAS: packu t0, t1, t2
+# CHECK-S-OBJ: pktt16 t0, t1, t2
+pktt16 x5, x6, x7
Index: llvm/test/CodeGen/RISCV/rv64zbpbo.ll
===================================================================
--- /dev/null
+++ llvm/test/CodeGen/RISCV/rv64zbpbo.ll
@@ -0,0 +1,119 @@
+; 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:    pkbb32 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:    pktt32 a0, a0, a1
+; RV64ZBPBO-NEXT:    ret
+  %shr = lshr i64 %a, 32
+  %shr1 = and i64 %b, -4294967296
+  %or = or i64 %shr1, %shr
+  ret i64 %or
+}
+
+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
+}
+
+declare i16 @llvm.bswap.i16(i16)
+
+define zeroext i16 @bswap_i16(i16 zeroext %a) nounwind {
+; RV64I-LABEL: bswap_i16:
+; RV64I:       # %bb.0:
+; RV64I-NEXT:    srli a1, a0, 8
+; RV64I-NEXT:    slli a0, a0, 8
+; RV64I-NEXT:    or a0, a0, a1
+; RV64I-NEXT:    slli a0, a0, 48
+; RV64I-NEXT:    srli a0, a0, 48
+; RV64I-NEXT:    ret
+;
+; RV64ZBPBO-LABEL: bswap_i16:
+; RV64ZBPBO:       # %bb.0:
+; RV64ZBPBO-NEXT:    rev8.h a0, a0
+; RV64ZBPBO-NEXT:    ret
+  %1 = tail call i16 @llvm.bswap.i16(i16 %a)
+  ret i16 %1
+}
+
+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/rv64zbpbo-intrinsics.ll
===================================================================
--- /dev/null
+++ llvm/test/CodeGen/RISCV/rv64zbpbo-intrinsics.ll
@@ -0,0 +1,25 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc -mtriple=riscv64 -mattr=+experimental-zbpbo -verify-machineinstrs < %s \
+; RUN:   | FileCheck %s -check-prefix=RV64ZBPBO
+
+declare i32 @llvm.riscv.fsr.i32(i32, i32, i32)
+
+define i32 @fsr_i32(i32 %a, i32 %b, i32 %c) nounwind {
+; RV64ZBPBO-LABEL: fsr_i32:
+; RV64ZBPBO:       # %bb.0:
+; RV64ZBPBO-NEXT:    fsrw a0, a0, a1, a2
+; RV64ZBPBO-NEXT:    ret
+  %1 = call i32 @llvm.riscv.fsr.i32(i32 %a, i32 %b, i32 %c)
+  ret i32 %1
+}
+
+declare i64 @llvm.riscv.grev.i64(i64 %a, i64 %b)
+
+define i64 @revi64(i64 %a) nounwind {
+; RV64ZBPBO-LABEL: revi64:
+; RV64ZBPBO:       # %bb.0:
+; RV64ZBPBO-NEXT:    rev a0, a0
+; RV64ZBPBO-NEXT:    ret
+  %tmp = call i64 @llvm.riscv.grev.i64(i64 %a, i64 63)
+  ret i64 %tmp
+}
Index: llvm/test/CodeGen/RISCV/rv32zbpbo.ll
===================================================================
--- /dev/null
+++ llvm/test/CodeGen/RISCV/rv32zbpbo.ll
@@ -0,0 +1,223 @@
+; 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:    beqz a0, .LBB0_2
+; RV32I-NEXT:  # %bb.1: # %cond.false
+; RV32I-NEXT:    addi sp, sp, -16
+; RV32I-NEXT:    sw ra, 12(sp) # 4-byte Folded Spill
+; 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:    lw ra, 12(sp) # 4-byte Folded Reload
+; RV32I-NEXT:    addi sp, sp, 16
+; RV32I-NEXT:    ret
+; RV32I-NEXT:  .LBB0_2:
+; RV32I-NEXT:    li a0, 32
+; 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:    pkbb16 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:    pktt16 a0, a0, a1
+; RV32ZBPBO-NEXT:    ret
+  %shr = lshr i32 %a, 16
+  %shr1 = and i32 %b, -65536
+  %or = or i32 %shr1, %shr
+  ret i32 %or
+}
+
+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
+}
+
+declare i16 @llvm.bswap.i16(i16)
+
+define zeroext i16 @bswap_i16(i16 zeroext %a) nounwind {
+; RV32I-LABEL: bswap_i16:
+; RV32I:       # %bb.0:
+; RV32I-NEXT:    srli a1, a0, 8
+; RV32I-NEXT:    slli a0, a0, 8
+; RV32I-NEXT:    or a0, a0, a1
+; RV32I-NEXT:    slli a0, a0, 16
+; RV32I-NEXT:    srli a0, a0, 16
+; RV32I-NEXT:    ret
+;
+; RV32ZBPBO-LABEL: bswap_i16:
+; RV32ZBPBO:       # %bb.0:
+; RV32ZBPBO-NEXT:    rev8.h a0, a0
+; RV32ZBPBO-NEXT:    ret
+  %1 = tail call i16 @llvm.bswap.i16(i16 %a)
+  ret i16 %1
+}
+
+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/test/CodeGen/RISCV/rv32zbpbo-intrinsics.ll
===================================================================
--- /dev/null
+++ llvm/test/CodeGen/RISCV/rv32zbpbo-intrinsics.ll
@@ -0,0 +1,34 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc -mtriple=riscv32 -mattr=+experimental-zbpbo -verify-machineinstrs < %s \
+; RUN:   | FileCheck %s -check-prefix=RV32ZBPBO
+
+declare i32 @llvm.riscv.fsr.i32(i32, i32, i32)
+
+define i32 @fsr_i32(i32 %a, i32 %b, i32 %c) nounwind {
+; RV32ZBPBO-LABEL: fsr_i32:
+; RV32ZBPBO:       # %bb.0:
+; RV32ZBPBO-NEXT:    fsr a0, a0, a1, a2
+; RV32ZBPBO-NEXT:    ret
+  %1 = call i32 @llvm.riscv.fsr.i32(i32 %a, i32 %b, i32 %c)
+  ret i32 %1
+}
+
+define i32 @fsri_i32(i32 %a, i32 %b) nounwind {
+; RV32ZBPBO-LABEL: fsri_i32:
+; RV32ZBPBO:       # %bb.0:
+; RV32ZBPBO-NEXT:    fsri a0, a0, a1, 15
+; RV32ZBPBO-NEXT:    ret
+  %1 = call i32 @llvm.riscv.fsr.i32(i32 %a, i32 %b, i32 15)
+  ret i32 %1
+}
+
+declare i32 @llvm.riscv.grev.i32(i32 %a, i32 %b)
+
+define i32 @revi32(i32 %a) nounwind {
+; RV32ZBPBO-LABEL: revi32:
+; RV32ZBPBO:       # %bb.0:
+; RV32ZBPBO-NEXT:    rev a0, a0
+; RV32ZBPBO-NEXT:    ret
+  %tmp = call i32 @llvm.riscv.grev.i32(i32 %a, i32 31)
+  ret i32 %tmp
+}
Index: llvm/test/CodeGen/RISCV/attributes.ll
===================================================================
--- llvm/test/CodeGen/RISCV/attributes.ll
+++ llvm/test/CodeGen/RISCV/attributes.ll
@@ -40,6 +40,7 @@
 ; RUN: llc -mtriple=riscv32 -mattr=+zicboz %s -o - | FileCheck --check-prefix=RV32ZICBOZ %s
 ; RUN: llc -mtriple=riscv32 -mattr=+zicbop %s -o - | FileCheck --check-prefix=RV32ZICBOP %s
 ; RUN: llc -mtriple=riscv32 -mattr=+experimental-p %s -o - | FileCheck --check-prefix=RV32P %s
+; RUN: llc -mtriple=riscv32 -mattr=+experimental-zbpbo %s -o - | FileCheck --check-prefix=RV32ZBPBO %s
 ; RUN: llc -mtriple=riscv32 -mattr=+experimental-zpn %s -o - | FileCheck --check-prefix=RV32ZPN %s
 ; RUN: llc -mtriple=riscv32 -mattr=+experimental-zpsfoperand %s -o - | FileCheck --check-prefix=RV32ZPSFOPERAND %s
 ; RUN: llc -mtriple=riscv64 -mattr=+m %s -o - | FileCheck --check-prefix=RV64M %s
@@ -82,6 +83,7 @@
 ; RUN: llc -mtriple=riscv64 -mattr=+zicboz %s -o - | FileCheck --check-prefix=RV64ZICBOZ %s
 ; RUN: llc -mtriple=riscv64 -mattr=+zicbop %s -o - | FileCheck --check-prefix=RV64ZICBOP %s
 ; RUN: llc -mtriple=riscv64 -mattr=+experimental-p %s -o - | FileCheck --check-prefix=RV64P %s
+; RUN: llc -mtriple=riscv64 -mattr=+experimental-zbpbo %s -o - | FileCheck --check-prefix=RV64ZBPBO %s
 ; RUN: llc -mtriple=riscv64 -mattr=+experimental-zpn %s -o - | FileCheck --check-prefix=RV64ZPN %s
 ; RUN: llc -mtriple=riscv64 -mattr=+experimental-zpsfoperand %s -o - | FileCheck --check-prefix=RV64ZPSFOPERAND %s
 
@@ -125,6 +127,7 @@
 ; RV32ZICBOZ: .attribute 5, "rv32i2p0_zicboz1p0"
 ; RV32ZICBOP: .attribute 5, "rv32i2p0_zicbop1p0"
 ; RV32P: .attribute 5, "rv32i2p0_p0p911_zbpbo0p911_zpn0p911_zpsfoperand0p911"
+; RV32ZBPBO: .attribute 5, "rv32i2p0_zbpbo0p911"
 ; RV32ZPN: .attribute 5, "rv32i2p0_zpn0p911"
 ; RV32ZPSFOPERAND: .attribute 5, "rv32i2p0_zpsfoperand0p911"
 
@@ -168,6 +171,7 @@
 ; RV64ZICBOZ: .attribute 5, "rv64i2p0_zicboz1p0"
 ; RV64ZICBOP: .attribute 5, "rv64i2p0_zicbop1p0"
 ; RV64P: .attribute 5, "rv64i2p0_p0p911_zbpbo0p911_zpn0p911_zpsfoperand0p911"
+; RV64ZBPBO: .attribute 5, "rv64i2p0_zbpbo0p911"
 ; RV64ZPN: .attribute 5, "rv64i2p0_zpn0p911"
 ; RV64ZPSFOPERAND: .attribute 5, "rv64i2p0_zpsfoperand0p911"
 
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;
@@ -164,6 +165,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
@@ -406,9 +406,13 @@
            Sched<[WriteORC, ReadORC, ReadORC]>;
 def GREV : ALU_rr<0b0110100, 0b101, "grev">,
            Sched<[WriteREV, ReadREV, ReadREV]>;
+} // Predicates = [HasStdExtZbp]
 
+let Predicates = [HasStdExtZbpOrZbpbo] in
 def GREVI : RVBShift_ri<0b01101, 0b101, OPC_OP_IMM, "grevi">,
             Sched<[WriteREVImm, ReadREVImm]>;
+
+let Predicates = [HasStdExtZbp] in {
 def GORCI : RVBShift_ri<0b00101, 0b101, OPC_OP_IMM, "gorci">,
             Sched<[WriteORCImm, ReadORCImm]>;
 
@@ -455,34 +459,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">,
@@ -541,13 +552,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]
@@ -570,18 +584,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]>;
 
@@ -665,7 +680,6 @@
 def : InstAlias<"rev.n $rd, $rs",  (GREVI GPR:$rd, GPR:$rs, 0b00011)>;
 def : InstAlias<"rev4.b $rd, $rs", (GREVI GPR:$rd, GPR:$rs, 0b00100)>;
 def : InstAlias<"rev2.b $rd, $rs", (GREVI GPR:$rd, GPR:$rs, 0b00110)>;
-def : InstAlias<"rev8.h $rd, $rs", (GREVI GPR:$rd, GPR:$rs, 0b01000)>;
 def : InstAlias<"rev4.h $rd, $rs", (GREVI GPR:$rd, GPR:$rs, 0b01100)>;
 def : InstAlias<"rev2.h $rd, $rs", (GREVI GPR:$rd, GPR:$rs, 0b01110)>;
 def : InstAlias<"rev.h $rd, $rs",  (GREVI GPR:$rd, GPR:$rs, 0b01111)>;
@@ -696,12 +710,14 @@
 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.
 def : InstAlias<"rev4 $rd, $rs",  (GREVI GPR:$rd, GPR:$rs, 0b11100)>;
 def : InstAlias<"rev2 $rd, $rs",  (GREVI GPR:$rd, GPR:$rs, 0b11110)>;
-def : InstAlias<"rev $rd, $rs",   (GREVI GPR:$rd, GPR:$rs, 0b11111)>;
 
 def : InstAlias<"zip8 $rd, $rs",   (SHFLI   GPR:$rd, GPR:$rs, 0b1000)>;
 def : InstAlias<"unzip8 $rd, $rs", (UNSHFLI GPR:$rd, GPR:$rs, 0b1000)>;
@@ -718,6 +734,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)>;
@@ -811,6 +832,20 @@
                 (BEXTI GPR:$rd, GPR:$rs1, uimmlog2xlen:$shamt), 0>;
 } // Predicates = [HasStdExtZbs]
 
+let Predicates = [HasStdExtZbpbo, IsRV32] in {
+def : InstAlias<"pkbb16 $rd, $rs1, $rs2",
+                (PACK GPR:$rd, GPR:$rs1, GPR:$rs2)>;
+def : InstAlias<"pktt16 $rd, $rs1, $rs2",
+                (PACKU GPR:$rd, GPR:$rs1, GPR:$rs2)>;
+} // Predicates = [HasStdExtZbpbo]
+
+let Predicates = [HasStdExtZbpbo, IsRV64] in {
+def : InstAlias<"pkbb32 $rd, $rs1, $rs2",
+                (PACK GPR:$rd, GPR:$rs1, GPR:$rs2)>;
+def : InstAlias<"pktt32 $rd, $rs1, $rs2",
+                (PACKU GPR:$rd, GPR:$rs1, GPR:$rs2)>;
+} // Predicates = [HasStdExtZbpbo]
+
 //===----------------------------------------------------------------------===//
 // Codegen patterns
 //===----------------------------------------------------------------------===//
@@ -905,13 +940,16 @@
 def : Pat<(i32 (riscv_unshfl GPR:$rs1, 15)), (UNZIP_RV32 GPR:$rs1)>;
 } // Predicates = [HasStdExtZbpOrZbkb, IsRV32]
 
-let Predicates = [HasStdExtZbp] in {
+let Predicates = [HasStdExtZbpOrZbpbo] in {
 def : PatGprGpr<riscv_grev, GREV>;
-def : PatGprGpr<riscv_gorc, GORC>;
 def : PatGprImm<riscv_grev, GREVI, uimmlog2xlen>;
+def : PatGprGpr<riscv_shfl, SHFL>;
+} // Predicates = [HasStdExtZbpOrZbpbo]
+
+let Predicates = [HasStdExtZbp] in {
+def : PatGprGpr<riscv_gorc, GORC>;
 def : PatGprImm<riscv_gorc, GORCI, uimmlog2xlen>;
 
-def : PatGprGpr<riscv_shfl, SHFL>;
 def : PatGprGpr<riscv_unshfl, UNSHFL>;
 def : PatGprImm<riscv_shfl, SHFLI, shfl_uimm>;
 def : PatGprImm<riscv_unshfl, UNSHFLI, shfl_uimm>;
@@ -952,12 +990,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<(XLenVT (or (and (not GPR:$rs2), GPR:$rs3), (and GPR:$rs2, GPR:$rs1))),
           (CMIX GPR:$rs1, GPR:$rs2, GPR:$rs3)>;
 def : Pat<(XLenVT (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<(XLenVT (select (XLenVT (setne (XLenVT GPR:$rs2), 0)), GPR:$rs1, GPR:$rs3)),
           (CMOV GPR:$rs1, GPR:$rs2, GPR:$rs3)>;
 def : Pat<(XLenVT (select (XLenVT (seteq (XLenVT GPR:$rs2), 0)), GPR:$rs3, GPR:$rs1)),
@@ -989,9 +1029,11 @@
           (CMOV GPR:$rs1, GPR:$rs2, GPR:$rs3)>;
 } // Predicates = [HasStdExtZbt]
 
-let Predicates = [HasStdExtZbt] in {
+let Predicates = [HasStdExtZbt] in
 def : Pat<(XLenVT (riscv_fsl GPR:$rs1, GPR:$rs3, (XLenVT GPR:$rs2))),
           (FSL GPR:$rs1, GPR:$rs2, GPR:$rs3)>;
+
+let Predicates = [HasStdExtZbtOrZbpbo] in {
 def : Pat<(XLenVT (riscv_fsr GPR:$rs1, GPR:$rs3, (XLenVT GPR:$rs2))),
           (FSR GPR:$rs1, GPR:$rs2, GPR:$rs3)>;
 def : Pat<(XLenVT (riscv_fsr GPR:$rs1, GPR:$rs3, uimmlog2xlen:$shamt)),
@@ -1000,13 +1042,15 @@
 // XLen and swap the operands.
 def : Pat<(XLenVT (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
@@ -1015,8 +1059,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]
@@ -1032,9 +1078,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]
@@ -1056,14 +1105,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)),
@@ -1073,18 +1123,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
@@ -294,6 +294,11 @@
     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);
+    setOperationAction({ISD::BITREVERSE, ISD::BSWAP}, MVT::i16, Custom);
+  }
 
   if (Subtarget.hasStdExtZbt()) {
     setOperationAction({ISD::FSHL, ISD::FSHR}, XLenVT, Custom);
@@ -7166,7 +7171,8 @@
     MVT XLenVT = Subtarget.getXLenVT();
     assert((VT == MVT::i8 || VT == MVT::i16 ||
             (VT == MVT::i32 && Subtarget.is64Bit())) &&
-           Subtarget.hasStdExtZbp() && "Unexpected custom legalisation");
+           (Subtarget.hasStdExtZbp() || Subtarget.hasStdExtZbpbo()) &&
+           "Unexpected custom legalisation");
     SDValue NewOp0 = DAG.getNode(ISD::ANY_EXTEND, DL, XLenVT, N->getOperand(0));
     unsigned Imm = VT.getSizeInBits() - 1;
     // If this is BSWAP rather than BITREVERSE, clear the lower 3 bits.
@@ -7871,7 +7877,8 @@
   EVT VT = N->getValueType(0);
   SDLoc DL(N);
 
-  if (!Subtarget.hasStdExtZbp() || Src.getOpcode() != RISCVISD::GREV)
+  if (!(Subtarget.hasStdExtZbp() || Subtarget.hasStdExtZbpbo()) ||
+      Src.getOpcode() != RISCVISD::GREV)
     return SDValue();
 
   if (!isa<ConstantSDNode>(N->getOperand(1)) ||
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
@@ -108,6 +108,7 @@
     {"zbp", RISCVExtensionVersion{0, 93}},
     {"zbr", RISCVExtensionVersion{0, 93}},
     {"zbt", RISCVExtensionVersion{0, 93}},
+    {"zbpbo", RISCVExtensionVersion{0, 911}},
     {"zvfh", RISCVExtensionVersion{0, 1}},
 
     {"p", RISCVExtensionVersion{0, 911}},
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/lib/Sema/SemaChecking.cpp
===================================================================
--- clang/lib/Sema/SemaChecking.cpp
+++ clang/lib/Sema/SemaChecking.cpp
@@ -4321,7 +4321,7 @@
          << Arg->getSourceRange();
 }
 
-static bool isRISCV32Builtin(unsigned BuiltinID) {
+static bool isRISCV32Builtin(unsigned BuiltinID, const TargetInfo &TI) {
   // These builtins only work on riscv32 targets.
   switch (BuiltinID) {
   case RISCV::BI__builtin_riscv_zip_32:
@@ -4337,6 +4337,9 @@
   case RISCV::BI__builtin_riscv_sha512sum0r_32:
   case RISCV::BI__builtin_riscv_sha512sum1r_32:
     return true;
+  case RISCV::BI__builtin_riscv_clz_32:
+    if (!TI.hasFeature("zbb"))
+      return true;
   }
 
   return false;
@@ -4354,7 +4357,7 @@
 
   // Check for 32-bit only builtins on a 64-bit target.
   const llvm::Triple &TT = TI.getTriple();
-  if (TT.getArch() != llvm::Triple::riscv32 && isRISCV32Builtin(BuiltinID))
+  if (TT.getArch() != llvm::Triple::riscv32 && isRISCV32Builtin(BuiltinID, TI))
     return Diag(TheCall->getCallee()->getBeginLoc(),
                 diag::err_32_bit_builtin_64_bit_tgt);
 
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
  • [PATCH] D128604: [RISCV] Suppo... Shao-Ce SUN via Phabricator via cfe-commits

Reply via email to