Skip to content

Conversation

@realqhc
Copy link
Contributor

@realqhc realqhc commented Dec 3, 2024

Add intrinsic support for XCVsimd extension.

Documentation: https://docs.openhwgroup.org/projects/cv32e40p-user-manual/en/latest/instruction_set_extensions.html#simd

Co-authored-by: @melonedo

@llvmbot
Copy link
Member

llvmbot commented Dec 3, 2024

@llvm/pr-subscribers-llvm-ir

@llvm/pr-subscribers-backend-risc-v

Author: None (realqhc)

Changes

Add intrinsic support for XCVsimd extension.

Documentation: https://docs.openhwgroup.org/projects/cv32e40p-user-manual/en/latest/instruction_set_extensions.html#simd

Co-authored-by: @melonedo


Patch is 79.67 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/118557.diff

4 Files Affected:

  • (modified) llvm/include/llvm/IR/IntrinsicsRISCVXCV.td (+124)
  • (modified) llvm/lib/Target/RISCV/RISCVExpandPseudoInsts.cpp (+22)
  • (modified) llvm/lib/Target/RISCV/RISCVInstrInfoXCV.td (+227)
  • (added) llvm/test/CodeGen/RISCV/xcvsimd.ll (+2266)
diff --git a/llvm/include/llvm/IR/IntrinsicsRISCVXCV.td b/llvm/include/llvm/IR/IntrinsicsRISCVXCV.td index 6e7e90438c6211..2f8e7acec5b347 100644 --- a/llvm/include/llvm/IR/IntrinsicsRISCVXCV.td +++ b/llvm/include/llvm/IR/IntrinsicsRISCVXCV.td @@ -42,6 +42,70 @@ class ScalarCoreVMacGprGprGprImmIntrinsic : Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [IntrNoMem, IntrWillReturn, IntrSpeculatable, ImmArg<ArgIndex<3>>]>; +class ScalarCoreVSimdGprIntrinsic + : Intrinsic<[llvm_i32_ty], [llvm_i32_ty], + [IntrNoMem, IntrWillReturn, IntrSpeculatable]>; + +class ScalarCoreVSimdGprGprIntrinsic + : Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], + [IntrNoMem, IntrWillReturn, IntrSpeculatable]>; + +class ScalarCoreVSimdGprImmIntrinsic + : Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], + [IntrNoMem, IntrWillReturn, IntrSpeculatable, ImmArg<ArgIndex<1>>]>; + +class ScalarCoreVSimdGprGprGprIntrinsic + : Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [IntrNoMem, IntrWillReturn, IntrSpeculatable]>; + +class ScalarCoreVSimdGprGprImmIntrinsic + : Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [IntrNoMem, IntrWillReturn, IntrSpeculatable, ImmArg<ArgIndex<2>>]>; + +class ScalarCoreVSimdGprGprGprImmIntrinsic + : Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [IntrNoMem, IntrWillReturn, IntrSpeculatable, ImmArg<ArgIndex<3>>]>; + +multiclass ScalarCoreVSimdGprIntrinsicHB { + def int_riscv_cv_simd_ # NAME # _h : ScalarCoreVSimdGprIntrinsic; + def int_riscv_cv_simd_ # NAME # _b : ScalarCoreVSimdGprIntrinsic; +} + +multiclass ScalarCoreVSimdGprGprIntrinsicHB { + def int_riscv_cv_simd_ # NAME # _h : ScalarCoreVSimdGprGprIntrinsic; + def int_riscv_cv_simd_ # NAME # _b : ScalarCoreVSimdGprGprIntrinsic; +} + +multiclass ScalarCoreVSimdGprGprGprIntrinsicHB { + def int_riscv_cv_simd_ # NAME # _h : ScalarCoreVSimdGprGprGprIntrinsic; + def int_riscv_cv_simd_ # NAME # _b : ScalarCoreVSimdGprGprGprIntrinsic; +} + +multiclass ScalarCoreVSimdGprGprIntrinsicDiv { + def int_riscv_cv_simd_ # NAME # _div2 : ScalarCoreVSimdGprGprIntrinsic; + def int_riscv_cv_simd_ # NAME # _div4 : ScalarCoreVSimdGprGprIntrinsic; + def int_riscv_cv_simd_ # NAME # _div8 : ScalarCoreVSimdGprGprIntrinsic; +} + +multiclass ScalarCoreVSimdGprImmIntrinsicHB { + def int_riscv_cv_simd_ # NAME # _h : ScalarCoreVSimdGprImmIntrinsic; + def int_riscv_cv_simd_ # NAME # _b : ScalarCoreVSimdGprImmIntrinsic; +} + +multiclass CoreVSimdBinary <bit exclude_h = false> { + if exclude_h then { + def int_riscv_cv_simd_ # NAME # _b : ScalarCoreVSimdGprGprIntrinsic; + } else { + defm NAME : ScalarCoreVSimdGprGprIntrinsicHB; + } + defm NAME # _sc : ScalarCoreVSimdGprGprIntrinsicHB; +} + +multiclass CoreVSimdTernary { + defm NAME : ScalarCoreVSimdGprGprGprIntrinsicHB; + defm NAME # _sc : ScalarCoreVSimdGprGprGprIntrinsicHB; +} + let TargetPrefix = "riscv" in { def int_riscv_cv_bitmanip_extract : ScalarCoreVBitManipGprGprIntrinsic; def int_riscv_cv_bitmanip_extractu : ScalarCoreVBitManipGprGprIntrinsic; @@ -90,4 +154,64 @@ let TargetPrefix = "riscv" in { def int_riscv_cv_mac_machhuRN : ScalarCoreVMacGprGprGprImmIntrinsic; def int_riscv_cv_mac_macsRN : ScalarCoreVMacGprGprGprImmIntrinsic; def int_riscv_cv_mac_machhsRN : ScalarCoreVMacGprGprGprImmIntrinsic; + + defm add : CoreVSimdBinary<true>; + def int_riscv_cv_simd_add_h : ScalarCoreVSimdGprGprImmIntrinsic; + defm sub : CoreVSimdBinary<true>; + def int_riscv_cv_simd_sub_h : ScalarCoreVSimdGprGprImmIntrinsic; + defm avg : CoreVSimdBinary; + defm avgu : CoreVSimdBinary; + defm min : CoreVSimdBinary; + defm minu : CoreVSimdBinary; + defm max : CoreVSimdBinary; + defm maxu : CoreVSimdBinary; + defm srl : CoreVSimdBinary; + defm sra : CoreVSimdBinary; + defm sll : CoreVSimdBinary; + defm or : CoreVSimdBinary; + defm xor : CoreVSimdBinary; + defm and : CoreVSimdBinary; + + defm abs : ScalarCoreVSimdGprIntrinsicHB; + + defm dotup : CoreVSimdBinary; + defm dotusp : CoreVSimdBinary; + defm dotsp : CoreVSimdBinary; + defm sdotup : CoreVSimdTernary; + defm sdotusp : CoreVSimdTernary; + defm sdotsp : CoreVSimdTernary; + + defm extract : ScalarCoreVSimdGprImmIntrinsicHB; + defm extractu : ScalarCoreVSimdGprImmIntrinsicHB; + def int_riscv_cv_simd_insert_b : ScalarCoreVSimdGprGprImmIntrinsic; + def int_riscv_cv_simd_insert_h : ScalarCoreVSimdGprGprImmIntrinsic; + + + defm shuffle : ScalarCoreVSimdGprGprIntrinsicHB; + def int_riscv_cv_simd_shuffle_sci_h : ScalarCoreVSimdGprImmIntrinsic; + def int_riscv_cv_simd_shuffle_sci_b : ScalarCoreVSimdGprImmIntrinsic; + defm shuffle2 : ScalarCoreVSimdGprGprGprIntrinsicHB; + + def int_riscv_cv_simd_packhi_h : ScalarCoreVSimdGprGprIntrinsic; + def int_riscv_cv_simd_packlo_h : ScalarCoreVSimdGprGprIntrinsic; + def int_riscv_cv_simd_packhi_b : ScalarCoreVSimdGprGprGprIntrinsic; + def int_riscv_cv_simd_packlo_b : ScalarCoreVSimdGprGprGprIntrinsic; + + defm cmpeq : CoreVSimdBinary; + defm cmpne : CoreVSimdBinary; + defm cmpgt : CoreVSimdBinary; + defm cmpge : CoreVSimdBinary; + defm cmplt : CoreVSimdBinary; + defm cmple : CoreVSimdBinary; + defm cmpgtu : CoreVSimdBinary; + defm cmpgeu : CoreVSimdBinary; + defm cmpltu : CoreVSimdBinary; + defm cmpleu : CoreVSimdBinary; + + def int_riscv_cv_simd_cplxmul_r : ScalarCoreVSimdGprGprGprImmIntrinsic; + def int_riscv_cv_simd_cplxmul_i : ScalarCoreVSimdGprGprGprImmIntrinsic; + + def int_riscv_cv_simd_cplxconj : ScalarCoreVSimdGprIntrinsic; + + def int_riscv_cv_simd_subrotmj : ScalarCoreVSimdGprGprImmIntrinsic; } // TargetPrefix = "riscv" diff --git a/llvm/lib/Target/RISCV/RISCVExpandPseudoInsts.cpp b/llvm/lib/Target/RISCV/RISCVExpandPseudoInsts.cpp index eb3e1a1fe9fd5e..08cabc7c47faae 100644 --- a/llvm/lib/Target/RISCV/RISCVExpandPseudoInsts.cpp +++ b/llvm/lib/Target/RISCV/RISCVExpandPseudoInsts.cpp @@ -56,6 +56,8 @@ class RISCVExpandPseudo : public MachineFunctionPass { MachineBasicBlock::iterator MBBI); bool expandRV32ZdinxLoad(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI); + bool expandVendorXcvsimdShuffle(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MBBI); #ifndef NDEBUG unsigned getInstSizeInBytes(const MachineFunction &MF) const { unsigned Size = 0; @@ -164,6 +166,8 @@ bool RISCVExpandPseudo::expandMI(MachineBasicBlock &MBB, case RISCV::PseudoVMSET_M_B64: // vmset.m vd => vmxnor.mm vd, vd, vd return expandVMSET_VMCLR(MBB, MBBI, RISCV::VMXNOR_MM); + case RISCV::CV_SHUFFLE_SCI_B_PSEUDO: + return expandVendorXcvsimdShuffle(MBB, MBBI); } return false; @@ -415,6 +419,24 @@ bool RISCVExpandPseudo::expandRV32ZdinxLoad(MachineBasicBlock &MBB, return true; } +bool RISCVExpandPseudo::expandVendorXcvsimdShuffle(MachineBasicBlock &MBB, + MachineBasicBlock::iterator + MBBI) { + DebugLoc DL = MBBI->getDebugLoc(); + Register DstReg = MBBI->getOperand(0).getReg(); + Register SrcReg = MBBI->getOperand(1).getReg(); + uint8_t Imm = MBBI->getOperand(2).getImm(); + const unsigned Opcodes[] = { + RISCV::CV_SHUFFLEI0_SCI_B, RISCV::CV_SHUFFLEI1_SCI_B, + RISCV::CV_SHUFFLEI2_SCI_B, RISCV::CV_SHUFFLEI3_SCI_B}; + const MCInstrDesc &Desc = TII->get(Opcodes[Imm >> 6]); + BuildMI(MBB, MBBI, DL, Desc, DstReg) + .addReg(SrcReg) + .addImm(APInt(6, Imm, true).getSExtValue()); + MBBI->eraseFromParent(); + return true; +} + class RISCVPreRAExpandPseudo : public MachineFunctionPass { public: const RISCVSubtarget *STI; diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoXCV.td b/llvm/lib/Target/RISCV/RISCVInstrInfoXCV.td index 4478e246111080..76e8a378e2935d 100644 --- a/llvm/lib/Target/RISCV/RISCVInstrInfoXCV.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfoXCV.td @@ -864,3 +864,230 @@ let Predicates = [HasVendorXCVmac] in { def : PatCoreVMacGprGprGprUimm5<"macsRN", "MACSRN">; def : PatCoreVMacGprGprGprUimm5<"machhsRN", "MACHHSRN">; } + +//===----------------------------------------------------------------------===// +// Patterns for SIMD operations +//===----------------------------------------------------------------------===// + +def cv_tsimm6 : Operand<XLenVT>, TImmLeaf<XLenVT, [{return isInt<6>(Imm);}]> { + let ParserMatchClass = SImmAsmOperand<6>; + let EncoderMethod = "getImmOpValue"; + let DecoderMethod = "decodeSImmOperand<6>"; + let OperandType = "OPERAND_SIMM6"; + let MCOperandPredicate = [{ + int64_t Imm; + return MCOp.evaluateAsConstantImm(Imm) && isUInt<6>(Imm); + }]; + let OperandNamespace = "RISCVOp"; +} + + +class CVUImmAsmOperand<int width> : AsmOperandClass { + let Name = "CVUImm" # width; + let RenderMethod = "addImmOperands"; + let DiagnosticType = !strconcat("Invalid", Name); +} + +def cv_uimm6 : Operand<XLenVT>, ImmLeaf<XLenVT, [{return isUInt<6>(Imm);}]> { + let ParserMatchClass = UImmAsmOperand<6>; + let EncoderMethod = "getImmOpValue"; + let DecoderMethod = "decodeUImmOperand<6>"; + let OperandType = "OPERAND_UIMM6"; + let MCOperandPredicate = [{ + int64_t Imm; + return MCOp.evaluateAsConstantImm(Imm) && isUInt<6>(Imm); + }]; + let OperandNamespace = "RISCVOp"; +} + +def cv_imm8: Operand<XLenVT>, TImmLeaf<XLenVT, [{return isUInt<8>(Imm);}]>; + +class PatCorevGprGpr <string intr, string asm> : + PatGprGpr<!cast<Intrinsic>("int_riscv_cv_simd_" # intr), + !cast<RVInst>("CV_" # asm)>; + +// Note that rd is the last argument +class PatCorevGprGprGpr <string intr, string asm> : + Pat<(!cast<Intrinsic>("int_riscv_cv_simd_" # intr) GPR:$rs1, GPR:$rs2, GPR:$rd), + (!cast<RVInst>("CV_" # asm) GPR:$rd, GPR:$rs1, GPR:$rs2)>; + +class PatCorevGprTImm <string intr, string asm> : + PatGprImm<!cast<Intrinsic>("int_riscv_cv_simd_" # intr), + !cast<RVInst>("CV_" # asm), cv_tsimm6>; + +class PatCorevGprImm <string intr, string asm> : + PatGprImm<!cast<Intrinsic>("int_riscv_cv_simd_" # intr), + !cast<RVInst>("CV_" # asm), simm6>; + +class PatCorevGprUImm <string intr, string asm> : + PatGprImm<!cast<Intrinsic>("int_riscv_cv_simd_" # intr), + !cast<RVInst>("CV_" # asm), cv_uimm6>; + +multiclass PatCorevGprGprHB <string intr> { + def : PatCorevGprGpr<intr # "_h", NAME # "_H">; + def : PatCorevGprGpr<intr # "_b", NAME # "_B">; +} + +multiclass PatCorevGprGprGprHB <string intr> { + def : PatCorevGprGprGpr<intr # "_h", NAME # "_H">; + def : PatCorevGprGprGpr<intr # "_b", NAME # "_B">; +} + +multiclass PatCorevGprTImmHB <string intr> { + def : PatCorevGprTImm<intr # "_h", NAME # "_H">; + def : PatCorevGprTImm<intr # "_b", NAME # "_B">; +} + +multiclass PatCorevGprImmHB <string intr> { + def : PatCorevGprImm<intr # "_h", NAME # "_H">; + def : PatCorevGprImm<intr # "_b", NAME # "_B">; +} + +multiclass PatCorevGprUImmHB <string intr> { + def : PatCorevGprUImm<intr # "_h", NAME # "_H">; + def : PatCorevGprUImm<intr # "_b", NAME # "_B">; +} + +class PatCorevGprGprDiv <Intrinsic intr, string asm, int div> : + Pat<(intr GPR:$rs1, GPR:$rs2, (i32 div)), + (!cast<RVInst>("CV_" # asm) GPR:$rs1, GPR:$rs2)>; + +class PatCorevGprGprGprDiv <Intrinsic intr, string asm, int div> : + Pat<(intr GPR:$rd, GPR:$rs1, GPR:$rs2, (i32 div)), + (!cast<RVInst>("CV_" # asm) GPR:$rd, GPR:$rs1, GPR:$rs2)>; + +class PatCorevGprShuffle <Intrinsic intr, RVInst inst, int s> : + Pat<(intr GPR:$rs1, (i32 s)), + (inst GPR:$rs1, 0)>; + +multiclass PatCorevGprGprDivAll <Intrinsic intr> { + def : PatCorevGprGprDiv<intr, NAME # "_DIV2", 1>; + def : PatCorevGprGprDiv<intr, NAME # "_DIV4", 2>; + def : PatCorevGprGprDiv<intr, NAME # "_DIV8", 3>; +} + +multiclass PatCorevGprGprGprDivAll <Intrinsic intr> { + def : PatCorevGprGprGprDiv<intr, NAME # "_DIV2", 1>; + def : PatCorevGprGprGprDiv<intr, NAME # "_DIV4", 2>; + def : PatCorevGprGprGprDiv<intr, NAME # "_DIV8", 3>; +} + +class PatCorevGpr <string intr, string asm> : + PatGpr<!cast<Intrinsic>("int_riscv_cv_simd_" # intr), + !cast<RVInst>("CV_" # asm)>; + +multiclass PatCorevGprHB <string intr> { + def : PatCorevGpr<intr # "_h", NAME # "_H">; + def : PatCorevGpr<intr # "_b", NAME # "_B">; +} + +multiclass PatCorevBinary <string intr, bit exclude_h = false> { + if exclude_h then { + def : PatCorevGprGpr<intr # "_b", NAME # "_B">; + } else { + defm NAME : PatCorevGprGprHB<intr>; + } + defm NAME # "_SC" : PatCorevGprGprHB<intr # "_sc">; + defm NAME # "_SCI" : PatCorevGprImmHB<intr # "_sc">; +} + +multiclass PatCorevBinaryUnsigned <string intr> { + defm NAME : PatCorevGprGprHB<intr>; + defm NAME # "_SC" : PatCorevGprGprHB<intr # "_sc">; + defm NAME # "_SCI" : PatCorevGprUImmHB<intr # "_sc">; +} + +multiclass PatCorevTernary <string intr> { + defm NAME : PatCorevGprGprGprHB<intr>; + defm NAME # "_SC" : PatCorevGprGprGprHB<intr # "_sc">; + def : Pat<(!cast<Intrinsic>("int_riscv_cv_simd_" # intr # "_sc_h") GPR:$rs1, simm6:$rs2, GPR:$rd), + (!cast<RVInst>("CV_" # NAME # "_SCI_H") GPR:$rd, GPR:$rs1, simm6:$rs2)>; + def : Pat<(!cast<Intrinsic>("int_riscv_cv_simd_" # intr # "_sc_b") GPR:$rs1, simm6:$rs2, GPR:$rd), + (!cast<RVInst>("CV_" # NAME # "_SCI_B") GPR:$rd, GPR:$rs1, simm6:$rs2)>; +} + +multiclass PatCorevTernaryUnsigned <string intr> { + defm NAME : PatCorevGprGprGprHB<intr>; + defm NAME # "_SC" : PatCorevGprGprGprHB<intr # "_sc">; + def : Pat<(!cast<Intrinsic>("int_riscv_cv_simd_" # intr # "_sc_h") GPR:$rs1, cv_uimm6:$rs2, GPR:$rd), + (!cast<RVInst>("CV_" # NAME # "_SCI_H") GPR:$rd, GPR:$rs1, cv_uimm6:$rs2)>; + def : Pat<(!cast<Intrinsic>("int_riscv_cv_simd_" # intr # "_sc_b") GPR:$rs1, cv_uimm6:$rs2, GPR:$rd), + (!cast<RVInst>("CV_" # NAME # "_SCI_B") GPR:$rd, GPR:$rs1, cv_uimm6:$rs2)>; +} + +let Predicates = [HasVendorXCVsimd] in { + defm ADD : PatCorevBinary<"add", true>; + def : PatCorevGprGprDiv<int_riscv_cv_simd_add_h, "ADD_H", 0>; + defm SUB : PatCorevBinary<"sub", true>; + def : PatCorevGprGprDiv<int_riscv_cv_simd_sub_h, "SUB_H", 0>; + defm AVG : PatCorevBinary<"avg">; + defm AVGU : PatCorevBinaryUnsigned<"avgu">; + defm MIN : PatCorevBinary<"min">; + defm MINU : PatCorevBinaryUnsigned<"minu">; + defm MAX : PatCorevBinary<"max">; + defm MAXU : PatCorevBinaryUnsigned<"maxu">; + defm SRL : PatCorevBinaryUnsigned<"srl">; + defm SRA : PatCorevBinaryUnsigned<"sra">; + defm SLL : PatCorevBinaryUnsigned<"sll">; + defm OR : PatCorevBinary<"or">; + defm XOR : PatCorevBinary<"xor">; + defm AND : PatCorevBinary<"and">; + + defm ABS : PatCorevGprHB<"abs">; + + defm DOTUP : PatCorevBinaryUnsigned<"dotup">; + defm DOTUSP : PatCorevBinary<"dotusp">; + defm DOTSP : PatCorevBinary<"dotsp">; + defm SDOTUP : PatCorevTernaryUnsigned<"sdotup">; + defm SDOTUSP : PatCorevTernary<"sdotusp">; + defm SDOTSP : PatCorevTernary<"sdotsp">; + + defm EXTRACT : PatCorevGprTImmHB<"extract">; + defm EXTRACTU : PatCorevGprTImmHB<"extractu">; + def : Pat<(int_riscv_cv_simd_insert_b GPR:$rd, GPR:$rs1, cv_tsimm6:$imm), + (CV_INSERT_B GPR:$rd, GPR:$rs1, cv_tsimm6:$imm)>; + def : Pat<(int_riscv_cv_simd_insert_h GPR:$rd, GPR:$rs1, cv_tsimm6:$imm), + (CV_INSERT_H GPR:$rd, GPR:$rs1, cv_tsimm6:$imm)>; + + defm SHUFFLE : PatCorevGprGprHB<"shuffle">; + def : PatCorevGprTImm<"shuffle_sci_h", "SHUFFLE_SCI_H">; + + def CV_SHUFFLE_SCI_B_PSEUDO : Pseudo<(outs GPR:$rd), (ins GPR:$rs, cv_imm8:$imm), []>; + def : PatGprImm<int_riscv_cv_simd_shuffle_sci_b, CV_SHUFFLE_SCI_B_PSEUDO, cv_imm8>; + + def : Pat<(int_riscv_cv_simd_shuffle2_h GPR:$rs1, GPR:$rs2, GPR:$rd), + (CV_SHUFFLE2_H GPR:$rd, GPR:$rs1, GPR:$rs2)>; + def : Pat<(int_riscv_cv_simd_shuffle2_b GPR:$rs1, GPR:$rs2, GPR:$rd), + (CV_SHUFFLE2_B GPR:$rd, GPR:$rs1, GPR:$rs2)>; + + def : PatCorevGprGpr<"packhi_h", "PACK_H">; + def : PatCorevGprGpr<"packlo_h", "PACK">; + def : Pat<(int_riscv_cv_simd_packhi_b GPR:$rd, GPR:$rs1, GPR:$rs2), + (CV_PACKHI_B GPR:$rd, GPR:$rs1, GPR:$rs2)>; + def : Pat<(int_riscv_cv_simd_packlo_b GPR:$rd, GPR:$rs1, GPR:$rs2), + (CV_PACKLO_B GPR:$rd, GPR:$rs1, GPR:$rs2)>; + + defm CMPEQ : PatCorevBinary<"cmpeq">; + defm CMPNE : PatCorevBinary<"cmpne">; + defm CMPGT : PatCorevBinary<"cmpgt">; + defm CMPGE : PatCorevBinary<"cmpge">; + defm CMPLT : PatCorevBinary<"cmplt">; + defm CMPLE : PatCorevBinary<"cmple">; + defm CMPGTU : PatCorevBinaryUnsigned<"cmpgtu">; + defm CMPGEU : PatCorevBinaryUnsigned<"cmpgeu">; + defm CMPLTU : PatCorevBinaryUnsigned<"cmpltu">; + defm CMPLEU : PatCorevBinaryUnsigned<"cmpleu">; + + def : PatCorevGprGprGprDiv<int_riscv_cv_simd_cplxmul_r, "CPLXMUL_R", 0>; + defm CPLXMUL_R : PatCorevGprGprGprDivAll<int_riscv_cv_simd_cplxmul_r>; + def : PatCorevGprGprGprDiv<int_riscv_cv_simd_cplxmul_i, "CPLXMUL_I", 0>; + defm CPLXMUL_I : PatCorevGprGprGprDivAll<int_riscv_cv_simd_cplxmul_i>; + + def : PatCorevGpr<"cplxconj", "CPLXCONJ">; + + def : PatCorevGprGprDiv<int_riscv_cv_simd_subrotmj, "SUBROTMJ", 0>; + defm SUBROTMJ : PatCorevGprGprDivAll<int_riscv_cv_simd_subrotmj>; + + defm ADD : PatCorevGprGprDivAll<int_riscv_cv_simd_add_h>; + defm SUB : PatCorevGprGprDivAll<int_riscv_cv_simd_sub_h>; +} // Predicates = [HasVendorXCVsimd] \ No newline at end of file diff --git a/llvm/test/CodeGen/RISCV/xcvsimd.ll b/llvm/test/CodeGen/RISCV/xcvsimd.ll new file mode 100644 index 00000000000000..ab39e75ab32d91 --- /dev/null +++ b/llvm/test/CodeGen/RISCV/xcvsimd.ll @@ -0,0 +1,2266 @@ +; RUN: llc -O0 -mtriple=riscv32 -mattr=+m -mattr=+xcvsimd -verify-machineinstrs < %s \ +; RUN: | FileCheck %s + +declare i32 @llvm.riscv.cv.simd.add.h(i32, i32, i32) + +define i32 @test.cv.add.h(i32 %a, i32 %b) { +; CHECK-LABEL: test.cv.add.h: +; CHECK: # %bb.0: +; CHECK-NEXT: cv.add.h a0, a0, a1 +; CHECK-NEXT: ret + %1 = call i32 @llvm.riscv.cv.simd.add.h(i32 %a, i32 %b, i32 0) + ret i32 %1 +} + +declare i32 @llvm.riscv.cv.simd.add.b(i32, i32) + +define i32 @test.cv.add.b(i32 %a, i32 %b) { +; CHECK-LABEL: test.cv.add.b: +; CHECK: # %bb.0: +; CHECK-NEXT: cv.add.b a0, a0, a1 +; CHECK-NEXT: ret + %1 = call i32 @llvm.riscv.cv.simd.add.b(i32 %a, i32 %b) + ret i32 %1 +} + +declare i32 @llvm.riscv.cv.simd.add.sc.h(i32, i32) + +define i32 @test.cv.add.sc.h(i32 %a, i32 %b) { +; CHECK-LABEL: test.cv.add.sc.h: +; CHECK: # %bb.0: +; CHECK-NEXT: cv.add.sc.h a0, a0, a1 +; CHECK-NEXT: ret + %1 = call i32 @llvm.riscv.cv.simd.add.sc.h(i32 %a, i32 %b) + ret i32 %1 +} + +define i32 @test.cv.add.sci.h(i32 %a) { +; CHECK-LABEL: test.cv.add.sci.h: +; CHECK: # %bb.0: +; CHECK-NEXT: cv.add.sci.h a0, a0, 5 +; CHECK-NEXT: ret + %1 = call i32 @llvm.riscv.cv.simd.add.sc.h(i32 %a, i32 5) + ret i32 %1 +} + +declare i32 @llvm.riscv.cv.simd.add.sc.b(i32, i32) + +define i32 @test.cv.add.sc.b(i32 %a, i32 %b) { +; CHECK-LABEL: test.cv.add.sc.b: +; CHECK: # %bb.0: +; CHECK-NEXT: cv.add.sc.b a0, a0, a1 +; CHECK-NEXT: ret + %1 = call i32 @llvm.riscv.cv.simd.add.sc.b(i32 %a, i32 %b) + ret i32 %1 +} + +define i32 @test.cv.add.sci.b(i32 %a) { +; CHECK-LABEL: test.cv.add.sci.b: +; CHECK: # %bb.0: +; CHECK-NEXT: cv.add.sci.b a0, a0, 5 +; CHECK-NEXT: ret + %1 = call i32 @llvm.riscv.cv.simd.add.sc.b(i32 %a, i32 5) + ret i32 %1 +} + +declare i32 @llvm.riscv.cv.simd.sub.h(i32, i32, i32) + +define i32 @test.cv.sub.h(i32 %a, i32 %b) { +; CHECK-LABEL: test.cv.sub.h: +; CHECK: # %bb.0: +; CHECK-NEXT: cv.sub.h a0, a0, a1 +; CHECK-NEXT: ret + %1 = call i32 @llvm.riscv.cv.simd.sub.h(i32 %a, i32 %b, i32 0) + ret i32 %1 +} + +declare i32 @llvm.riscv.cv.simd.sub.b(i32, i32) + +define i32 @test.cv.sub.b(i32 %a, i32 %b) { +; CHECK-LABEL: test.cv.sub.b: +; CHECK: # %bb.0: +; CHECK-NEXT: cv.sub.b a0, a0, a1 +; CHECK-NEXT: ret + %1 = call i32 @llvm.riscv.cv.simd.sub.b(i32 %a, i32 %b) + ret i32 %1 +} + +declare i32 @llvm.riscv.cv.simd.sub.sc.h(i32, i32) + +define i32 @test.cv.sub.sc.h(i32 %a, i32 %b) { +; CHECK-LABEL: test.cv.sub.sc.h: +; CHECK: # %bb.0: +; CHECK-NEXT: cv.sub.sc.h a0, a0, a1 +; CHECK-NEXT: ret + %1 = call i32 @llvm.riscv.cv.simd.sub.sc.h(i32 %a, i32 %b) + r... [truncated] 
@github-actions
Copy link

github-actions bot commented Dec 3, 2024

✅ With the latest revision this PR passed the C/C++ code formatter.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment