diff --git a/clang/include/clang/Basic/BuiltinsRISCV.def b/clang/include/clang/Basic/BuiltinsRISCV.def --- a/clang/include/clang/Basic/BuiltinsRISCV.def +++ b/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") diff --git a/clang/test/CodeGen/RISCV/rvp-intrinsics/riscv32-zbpbo.c b/clang/test/CodeGen/RISCV/rvp-intrinsics/riscv32-zbpbo.c new file mode 100644 --- /dev/null +++ b/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); +} diff --git a/clang/test/CodeGen/RISCV/rvp-intrinsics/riscv64-zbpbo.c b/clang/test/CodeGen/RISCV/rvp-intrinsics/riscv64-zbpbo.c new file mode 100644 --- /dev/null +++ b/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); +} diff --git a/llvm/lib/Support/RISCVISAInfo.cpp b/llvm/lib/Support/RISCVISAInfo.cpp --- a/llvm/lib/Support/RISCVISAInfo.cpp +++ b/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}}, }; diff --git a/llvm/lib/Target/RISCV/RISCV.td b/llvm/lib/Target/RISCV/RISCV.td --- a/llvm/lib/Target/RISCV/RISCV.td +++ b/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)">; diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp --- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp +++ b/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, diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoZb.td b/llvm/lib/Target/RISCV/RISCVInstrInfoZb.td --- a/llvm/lib/Target/RISCV/RISCVInstrInfoZb.td +++ b/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; + +let Predicates = [HasStdExtZbb] in { def : PatGpr; def : PatGpr; } // 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; def : PatGprGpr; +} // Predicates = [HasStdExtZbbOrZbpbo] + +let Predicates = [HasStdExtZbb] in { def : PatGprGpr; def : PatGprGpr; } // 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)>; diff --git a/llvm/lib/Target/RISCV/RISCVSubtarget.h b/llvm/lib/Target/RISCV/RISCVSubtarget.h --- a/llvm/lib/Target/RISCV/RISCVSubtarget.h +++ b/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; } diff --git a/llvm/test/CodeGen/RISCV/rv32zbpbo.ll b/llvm/test/CodeGen/RISCV/rv32zbpbo.ll new file mode 100644 --- /dev/null +++ b/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 +} diff --git a/llvm/test/CodeGen/RISCV/rv64zbpbo.ll b/llvm/test/CodeGen/RISCV/rv64zbpbo.ll new file mode 100644 --- /dev/null +++ b/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 +} diff --git a/llvm/test/MC/RISCV/rv32zbpbo-valid.s b/llvm/test/MC/RISCV/rv32zbpbo-valid.s new file mode 100644 --- /dev/null +++ b/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 diff --git a/llvm/test/MC/RISCV/rv64zbpbo-valid.s b/llvm/test/MC/RISCV/rv64zbpbo-valid.s new file mode 100644 --- /dev/null +++ b/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