diff --git a/llvm/docs/RISCVUsage.rst b/llvm/docs/RISCVUsage.rst --- a/llvm/docs/RISCVUsage.rst +++ b/llvm/docs/RISCVUsage.rst @@ -185,6 +185,9 @@ ``XTHeadBs`` LLVM implements `the THeadBs (single-bit operations) vendor-defined instructions specified in `_ by T-HEAD of Alibaba. Instructions are prefixed with `th.` as described in the specification. +``XTheadMac`` + LLVM implements `the XTheadMac (multiply-accumulate instructions) vendor-defined instructions specified in `_ by T-HEAD of Alibaba. Instructions are prefixed with `th.` as described in the specification. + ``XTHeadVdot`` LLVM implements `version 1.0.0 of the THeadV-family custom instructions specification `_ by T-HEAD of Alibaba. All instructions are prefixed with `th.` as described in the specification, and the riscv-toolchain-convention document linked above. diff --git a/llvm/docs/ReleaseNotes.rst b/llvm/docs/ReleaseNotes.rst --- a/llvm/docs/ReleaseNotes.rst +++ b/llvm/docs/ReleaseNotes.rst @@ -111,6 +111,7 @@ * Adds support for the vendor-defined XTHeadBa (address-generation) extension. * Adds support for the vendor-defined XTHeadBb (basic bit-manipulation) extension. * Adds support for the vendor-defined XTHeadBs (single-bit) extension. +* Adds support for the vendor-defined XTHeadMac (multiply-accumulate instructions) extension. Changes to the WebAssembly Backend ---------------------------------- 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 @@ -112,6 +112,7 @@ {"xtheadba", RISCVExtensionVersion{1, 0}}, {"xtheadbb", RISCVExtensionVersion{1, 0}}, {"xtheadbs", RISCVExtensionVersion{1, 0}}, + {"xtheadmac", RISCVExtensionVersion{1, 0}}, {"xtheadvdot", RISCVExtensionVersion{1, 0}}, {"xventanacondops", RISCVExtensionVersion{1, 0}}, }; diff --git a/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp b/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp --- a/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp +++ b/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp @@ -492,6 +492,13 @@ if (Result != MCDisassembler::Fail) return Result; } + if (STI.getFeatureBits()[RISCV::FeatureVendorXTHeadMac]) { + LLVM_DEBUG(dbgs() << "Trying XTHeadMac custom opcode table:\n"); + Result = decodeInstruction(DecoderTableTHeadMac32, MI, Insn, Address, + this, STI); + if (Result != MCDisassembler::Fail) + return Result; + } if (STI.getFeatureBits()[RISCV::FeatureVendorXTHeadVdot]) { LLVM_DEBUG(dbgs() << "Trying XTHeadVdot custom opcode table:\n"); Result = diff --git a/llvm/lib/Target/RISCV/RISCVFeatures.td b/llvm/lib/Target/RISCV/RISCVFeatures.td --- a/llvm/lib/Target/RISCV/RISCVFeatures.td +++ b/llvm/lib/Target/RISCV/RISCVFeatures.td @@ -484,6 +484,13 @@ AssemblerPredicate<(all_of FeatureVendorXTHeadBs), "'xtheadbs' (T-Head single-bit instructions)">; +def FeatureVendorXTHeadMac + : SubtargetFeature<"xtheadmac", "HasVendorXTHeadMac", "true", + "'xtheadmac' (T-Head Multiply-Accumulate Instructions)">; +def HasVendorXTHeadMac : Predicate<"Subtarget->hasVendorXTHeadMac()">, + AssemblerPredicate<(all_of FeatureVendorXTHeadMac), + "'xtheadmac' (T-Head Multiply-Accumulate Instructions)">; + def FeatureVendorXTHeadVdot : SubtargetFeature<"xtheadvdot", "HasVendorXTHeadVdot", "true", "'xtheadvdot' (T-Head Vector Extensions for Dot)", diff --git a/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp b/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp --- a/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp +++ b/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp @@ -2681,6 +2681,10 @@ case RISCV::MULW: case RISCV::SLLIW: case RISCV::PACKW: + case RISCV::TH_MULAW: + case RISCV::TH_MULAH: + case RISCV::TH_MULSW: + case RISCV::TH_MULSH: // Result is already sign extended just remove the sext.w. // NOTE: We only handle the nodes that are selected with hasAllWUsers. ReplaceUses(N, N0.getNode()); diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoXTHead.td b/llvm/lib/Target/RISCV/RISCVInstrInfoXTHead.td --- a/llvm/lib/Target/RISCV/RISCVInstrInfoXTHead.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfoXTHead.td @@ -86,6 +86,17 @@ (ins GPR:$rs1, uimm5:$shamt), opcodestr, "$rd, $rs1, $shamt">; + +let Predicates = [HasVendorXTHeadMac], DecoderNamespace = "THeadMac", + hasSideEffects = 0, mayLoad = 0, mayStore = 0, isCommutable = 1 in +class THMulAccumulate_rr funct7, string opcodestr> + : RVInstR { + let Constraints = "$rd_wb = $rd"; +} + + //===----------------------------------------------------------------------===// // Combination of instruction classes. // Use these multiclasses to define instructions more easily. @@ -128,6 +139,18 @@ Sched<[WriteSingleBitImm, ReadSingleBitImm]>; } // Predicates = [HasVendorXTHeadBs] +let Predicates = [HasVendorXTHeadMac] in { +def TH_MULA : THMulAccumulate_rr<0b0010000, "th.mula">; +def TH_MULAH : THMulAccumulate_rr<0b0010100, "th.mulah">; +def TH_MULS : THMulAccumulate_rr<0b0010001, "th.muls">; +def TH_MULSH : THMulAccumulate_rr<0b0010101, "th.mulsh">; +} // Predicates = [HasVendorXTHeadMac] + +let Predicates = [HasVendorXTHeadMac, IsRV64], IsSignExtendingOpW = 1 in { +def TH_MULAW : THMulAccumulate_rr<0b0010010, "th.mulaw">; +def TH_MULSW : THMulAccumulate_rr<0b0010011, "th.mulsw">; +} // Predicates = [HasVendorXTHeadMac, IsRV64] + let Predicates = [HasVendorXTHeadVdot], Constraints = "@earlyclobber $vd", RVVConstraint = WidenV in { @@ -327,6 +350,52 @@ (TH_TST (XORI GPR:$rs1, -1), SingleBitSetMask:$mask)>; } // Predicates = [HasVendorXTHeadBs] +let Predicates = [HasVendorXTHeadMac] in { +def : Pat<(add GPR:$rd, (mul GPR:$rs1, GPR:$rs2)), (TH_MULA GPR:$rd, GPR:$rs1, GPR:$rs2)>; +def : Pat<(sub GPR:$rd, (mul GPR:$rs1, GPR:$rs2)), (TH_MULS GPR:$rd, GPR:$rs1, GPR:$rs2)>; +} // Predicates = [HasVendorXTHeadMac] + +let Predicates = [HasVendorXTHeadMac, IsRV64] in { +// mulaw, mulsw are available only in RV64. +def : Pat<(binop_allwusers GPR:$rd, (mul GPR:$rs1, GPR:$rs2)), + (TH_MULAW GPR:$rd, GPR:$rs1, GPR:$rs2)>; +def : Pat<(binop_allwusers GPR:$rd, (mul GPR:$rs1, GPR:$rs2)), + (TH_MULSW GPR:$rd, GPR:$rs1, GPR:$rs2)>; +// mulah, mulsh need an outer (sext_inreg ..., i32) in RV64. +def : Pat<(binop_allwusers GPR:$rd, (mul + (sext_inreg GPR:$rs1, i16), + (sext_inreg GPR:$rs2, i16))), + (TH_MULAH GPR:$rd, GPR:$rs1, GPR:$rs2)>; +def : Pat<(binop_allwusers GPR:$rd, (mul + (sext_inreg GPR:$rs1, i16), + (sext_inreg GPR:$rs2, i16))), + (TH_MULSH GPR:$rd, GPR:$rs1, GPR:$rs2)>; +// Also try match for mulah, mulsh in the absense of Zbb or THeadBb. +def : Pat<(binop_allwusers GPR:$rd, (mul + (sra (shl GPR:$rs1, (i64 48)), (i64 48)), + (sra (shl GPR:$rs2, (i64 48)), (i64 48)))), + (TH_MULAH GPR:$rd, GPR:$rs1, GPR:$rs2)>; +def : Pat<(binop_allwusers GPR:$rd, (mul + (sra (shl GPR:$rs1, (i64 48)), (i64 48)), + (sra (shl GPR:$rs2, (i64 48)), (i64 48)))), + (TH_MULSH GPR:$rd, GPR:$rs1, GPR:$rs2)>; +} // Predicates = [HasVendorXTHeadMac, IsRV64] + +let Predicates = [HasVendorXTHeadMac, IsRV32] in { +def : Pat<(add GPR:$rd, (mul (sext_inreg GPR:$rs1, i16), (sext_inreg GPR:$rs2, i16))), + (TH_MULAH GPR:$rd, GPR:$rs1, GPR:$rs2)>; +def : Pat<(sub GPR:$rd, (mul (sext_inreg GPR:$rs1, i16), (sext_inreg GPR:$rs2, i16))), + (TH_MULSH GPR:$rd, GPR:$rs1, GPR:$rs2)>; +// Also try match for mulah, mulsh in the absense of Zbb or THeadBb. +def : Pat<(add GPR:$rd, (mul + (sra (shl GPR:$rs1, (i32 16)), (i32 16)), + (sra (shl GPR:$rs2, (i32 16)), (i32 16)))), + (TH_MULAH GPR:$rd, GPR:$rs1, GPR:$rs2)>; +def : Pat<(sub GPR:$rd, (mul + (sra (shl GPR:$rs1, (i32 16)), (i32 16)), + (sra (shl GPR:$rs2, (i32 16)), (i32 16)))), + (TH_MULSH GPR:$rd, GPR:$rs1, GPR:$rs2)>; +} // Predicates = [HasVendorXTHeadMac, IsRV32] defm PseudoTHVdotVMAQA : VPseudoVMAQA_VV_VX; defm PseudoTHVdotVMAQAU : VPseudoVMAQA_VV_VX; diff --git a/llvm/test/CodeGen/RISCV/attributes.ll b/llvm/test/CodeGen/RISCV/attributes.ll --- a/llvm/test/CodeGen/RISCV/attributes.ll +++ b/llvm/test/CodeGen/RISCV/attributes.ll @@ -41,6 +41,7 @@ ; RUN: llc -mtriple=riscv32 -mattr=+svnapot %s -o - | FileCheck --check-prefixes=CHECK,RV32SVNAPOT %s ; RUN: llc -mtriple=riscv32 -mattr=+svpbmt %s -o - | FileCheck --check-prefixes=CHECK,RV32SVPBMT %s ; RUN: llc -mtriple=riscv32 -mattr=+svinval %s -o - | FileCheck --check-prefixes=CHECK,RV32SVINVAL %s +; RUN: llc -mtriple=riscv32 -mattr=+xtheadmac %s -o - | FileCheck --check-prefixes=CHECK,RV32XTHEADMAC %s ; RUN: llc -mtriple=riscv32 -mattr=+experimental-zca %s -o - | FileCheck --check-prefixes=CHECK,RV32ZCA %s ; RUN: llc -mtriple=riscv32 -mattr=+experimental-zcb %s -o - | FileCheck --check-prefixes=CHECK,RV32ZCB %s ; RUN: llc -mtriple=riscv32 -mattr=+experimental-zcd %s -o - | FileCheck --check-prefixes=CHECK,RV32ZCD %s @@ -91,6 +92,7 @@ ; RUN: llc -mtriple=riscv64 -mattr=+xtheadba %s -o - | FileCheck --check-prefixes=CHECK,RV64XTHEADBA %s ; RUN: llc -mtriple=riscv64 -mattr=+xtheadbb %s -o - | FileCheck --check-prefixes=CHECK,RV64XTHEADBB %s ; RUN: llc -mtriple=riscv64 -mattr=+xtheadbs %s -o - | FileCheck --check-prefixes=CHECK,RV64XTHEADBS %s +; RUN: llc -mtriple=riscv64 -mattr=+xtheadmac %s -o - | FileCheck --check-prefixes=CHECK,RV64XTHEADMAC %s ; RUN: llc -mtriple=riscv64 -mattr=+xtheadvdot %s -o - | FileCheck --check-prefixes=CHECK,RV64XTHEADVDOT %s ; RUN: llc -mtriple=riscv64 -mattr=+experimental-zawrs %s -o - | FileCheck --check-prefixes=CHECK,RV64ZAWRS %s ; RUN: llc -mtriple=riscv64 -mattr=+experimental-ztso %s -o - | FileCheck --check-prefixes=CHECK,RV64ZTSO %s @@ -140,6 +142,7 @@ ; RV32SVNAPOT: .attribute 5, "rv32i2p0_svnapot1p0" ; RV32SVPBMT: .attribute 5, "rv32i2p0_svpbmt1p0" ; RV32SVINVAL: .attribute 5, "rv32i2p0_svinval1p0" +; RV32XTHEADMAC: .attribute 5, "rv32i2p0_xtheadmac1p0" ; RV32ZCA: .attribute 5, "rv32i2p0_zca1p0" ; RV32ZCB: .attribute 5, "rv32i2p0_zca1p0_zcb1p0" ; RV32ZCD: .attribute 5, "rv32i2p0_zcd1p0" @@ -190,6 +193,7 @@ ; RV64XTHEADBA: .attribute 5, "rv64i2p0_xtheadba1p0" ; RV64XTHEADBB: .attribute 5, "rv64i2p0_xtheadbb1p0" ; RV64XTHEADBS: .attribute 5, "rv64i2p0_xtheadbs1p0" +; RV64XTHEADMAC: .attribute 5, "rv64i2p0_xtheadmac1p0" ; RV64XTHEADVDOT: .attribute 5, "rv64i2p0_f2p0_d2p0_v1p0_zve32f1p0_zve32x1p0_zve64d1p0_zve64f1p0_zve64x1p0_zvl128b1p0_zvl32b1p0_zvl64b1p0_xtheadvdot1p0" ; RV64ZTSO: .attribute 5, "rv64i2p0_ztso0p1" ; RV64ZCA: .attribute 5, "rv64i2p0_zca1p0" diff --git a/llvm/test/CodeGen/RISCV/xtheadmac.ll b/llvm/test/CodeGen/RISCV/xtheadmac.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/RISCV/xtheadmac.ll @@ -0,0 +1,152 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -mtriple=riscv32 -mattr=+xtheadmac -mattr=+m -verify-machineinstrs < %s \ +; RUN: | FileCheck %s -check-prefix=RV32XTHEADMAC +; RUN: llc -mtriple=riscv64 -mattr=+xtheadmac -mattr=+m -verify-machineinstrs < %s \ +; RUN: | FileCheck %s -check-prefix=RV64XTHEADMAC + +define i32 @mula_i32(i32 %a, i32 %b, i32 %c) { +; RV32XTHEADMAC-LABEL: mula_i32: +; RV32XTHEADMAC: # %bb.0: +; RV32XTHEADMAC-NEXT: th.mula a0, a1, a2 +; RV32XTHEADMAC-NEXT: ret +; +; RV64XTHEADMAC-LABEL: mula_i32: +; RV64XTHEADMAC: # %bb.0: +; RV64XTHEADMAC-NEXT: th.mulaw a0, a1, a2 +; RV64XTHEADMAC-NEXT: ret + %d = mul i32 %b, %c + %e = add i32 %a, %d + ret i32 %e +} + +define i32 @muls_i32(i32 %a, i32 %b, i32 %c) { +; RV32XTHEADMAC-LABEL: muls_i32: +; RV32XTHEADMAC: # %bb.0: +; RV32XTHEADMAC-NEXT: th.muls a0, a1, a2 +; RV32XTHEADMAC-NEXT: ret +; +; RV64XTHEADMAC-LABEL: muls_i32: +; RV64XTHEADMAC: # %bb.0: +; RV64XTHEADMAC-NEXT: th.mulsw a0, a1, a2 +; RV64XTHEADMAC-NEXT: ret + %d = mul i32 %b, %c + %e = sub i32 %a, %d + ret i32 %e +} + +define i64 @mula_i64(i64 %a, i64 %b, i64 %c) { +; RV32XTHEADMAC-LABEL: mula_i64: +; RV32XTHEADMAC: # %bb.0: +; RV32XTHEADMAC-NEXT: mulhu a6, a2, a4 +; RV32XTHEADMAC-NEXT: th.mula a6, a2, a5 +; RV32XTHEADMAC-NEXT: th.mula a6, a3, a4 +; RV32XTHEADMAC-NEXT: th.mula a2, a0, a4 +; RV32XTHEADMAC-NEXT: sltu a0, a2, a0 +; RV32XTHEADMAC-NEXT: add a0, a1, a0 +; RV32XTHEADMAC-NEXT: add a1, a0, a6 +; RV32XTHEADMAC-NEXT: mv a0, a2 +; RV32XTHEADMAC-NEXT: ret +; +; RV64XTHEADMAC-LABEL: mula_i64: +; RV64XTHEADMAC: # %bb.0: +; RV64XTHEADMAC-NEXT: th.mula a0, a1, a2 +; RV64XTHEADMAC-NEXT: ret + %d = mul i64 %b, %c + %f = add i64 %a, %d + ret i64 %f +} + +define i64 @mulaw_i64(i32 %a, i32 %b, i32 %c) { +; RV32XTHEADMAC-LABEL: mulaw_i64: +; RV32XTHEADMAC: # %bb.0: +; RV32XTHEADMAC-NEXT: th.mula a0, a1, a2 +; RV32XTHEADMAC-NEXT: srai a1, a0, 31 +; RV32XTHEADMAC-NEXT: ret +; +; RV64XTHEADMAC-LABEL: mulaw_i64: +; RV64XTHEADMAC: # %bb.0: +; RV64XTHEADMAC-NEXT: th.mulaw a0, a1, a2 +; RV64XTHEADMAC-NEXT: ret + %d = mul i32 %b, %c + %e = add i32 %a, %d + %f = sext i32 %e to i64 + ret i64 %f +} + +define i64 @mulah_i64(i32 %a, i16 %b, i16 %c) { +; RV32XTHEADMAC-LABEL: mulah_i64: +; RV32XTHEADMAC: # %bb.0: +; RV32XTHEADMAC-NEXT: th.mulah a0, a1, a2 +; RV32XTHEADMAC-NEXT: srai a1, a0, 31 +; RV32XTHEADMAC-NEXT: ret +; +; RV64XTHEADMAC-LABEL: mulah_i64: +; RV64XTHEADMAC: # %bb.0: +; RV64XTHEADMAC-NEXT: th.mulah a0, a1, a2 +; RV64XTHEADMAC-NEXT: ret + %d = sext i16 %b to i32 + %e = sext i16 %c to i32 + %f = mul i32 %d, %e + %g = add i32 %a, %f + %h = sext i32 %g to i64 + ret i64 %h +} + +define i64 @muls_i64(i64 %a, i64 %b, i64 %c) { +; RV32XTHEADMAC-LABEL: muls_i64: +; RV32XTHEADMAC: # %bb.0: +; RV32XTHEADMAC-NEXT: mulhu a6, a2, a4 +; RV32XTHEADMAC-NEXT: th.mula a6, a2, a5 +; RV32XTHEADMAC-NEXT: th.mula a6, a3, a4 +; RV32XTHEADMAC-NEXT: mul a3, a2, a4 +; RV32XTHEADMAC-NEXT: th.muls a2, a0, a4 +; RV32XTHEADMAC-NEXT: sltu a0, a0, a3 +; RV32XTHEADMAC-NEXT: sub a1, a1, a0 +; RV32XTHEADMAC-NEXT: sub a1, a1, a6 +; RV32XTHEADMAC-NEXT: mv a0, a2 +; RV32XTHEADMAC-NEXT: ret +; +; RV64XTHEADMAC-LABEL: muls_i64: +; RV64XTHEADMAC: # %bb.0: +; RV64XTHEADMAC-NEXT: th.muls a0, a1, a2 +; RV64XTHEADMAC-NEXT: ret + %d = mul i64 %b, %c + %f = sub i64 %a, %d + ret i64 %f +} + +define i64 @mulsw_i64(i32 %a, i32 %b, i32 %c) { +; RV32XTHEADMAC-LABEL: mulsw_i64: +; RV32XTHEADMAC: # %bb.0: +; RV32XTHEADMAC-NEXT: th.muls a0, a1, a2 +; RV32XTHEADMAC-NEXT: srai a1, a0, 31 +; RV32XTHEADMAC-NEXT: ret +; +; RV64XTHEADMAC-LABEL: mulsw_i64: +; RV64XTHEADMAC: # %bb.0: +; RV64XTHEADMAC-NEXT: th.mulsw a0, a1, a2 +; RV64XTHEADMAC-NEXT: ret + %d = mul i32 %b, %c + %e = sub i32 %a, %d + %f = sext i32 %e to i64 + ret i64 %f +} + +define i64 @mulsh_i64(i32 %a, i16 %b, i16 %c) { +; RV32XTHEADMAC-LABEL: mulsh_i64: +; RV32XTHEADMAC: # %bb.0: +; RV32XTHEADMAC-NEXT: th.mulsh a0, a1, a2 +; RV32XTHEADMAC-NEXT: srai a1, a0, 31 +; RV32XTHEADMAC-NEXT: ret +; +; RV64XTHEADMAC-LABEL: mulsh_i64: +; RV64XTHEADMAC: # %bb.0: +; RV64XTHEADMAC-NEXT: th.mulsh a0, a1, a2 +; RV64XTHEADMAC-NEXT: ret + %d = sext i16 %b to i32 + %e = sext i16 %c to i32 + %f = mul i32 %d, %e + %g = sub i32 %a, %f + %h = sext i32 %g to i64 + ret i64 %h +} diff --git a/llvm/test/MC/RISCV/rv32xtheadmac-invalid.s b/llvm/test/MC/RISCV/rv32xtheadmac-invalid.s new file mode 100644 --- /dev/null +++ b/llvm/test/MC/RISCV/rv32xtheadmac-invalid.s @@ -0,0 +1,4 @@ +# RUN: not llvm-mc -triple riscv32 -mattr=+xtheadmac < %s 2>&1 | FileCheck %s + +th.mulaw t0, t1, t2 # CHECK: :[[@LINE]]:1: error: instruction requires the following: RV64I Base Instruction Set{{$}} +th.mulsw t0, t1, t2 # CHECK: :[[@LINE]]:1: error: instruction requires the following: RV64I Base Instruction Set{{$}} diff --git a/llvm/test/MC/RISCV/rv32xtheadmac-valid.s b/llvm/test/MC/RISCV/rv32xtheadmac-valid.s new file mode 100644 --- /dev/null +++ b/llvm/test/MC/RISCV/rv32xtheadmac-valid.s @@ -0,0 +1,21 @@ +# RUN: llvm-mc %s -triple=riscv32 -mattr=+xtheadmac -show-encoding \ +# RUN: | FileCheck -check-prefixes=CHECK-ASM,CHECK-ASM-AND-OBJ %s +# RUN: llvm-mc -filetype=obj -triple=riscv32 -mattr=+xtheadmac < %s \ +# RUN: | llvm-objdump --mattr=+xtheadmac -d -r - \ +# RUN: | FileCheck --check-prefix=CHECK-ASM-AND-OBJ %s + +# CHECK-ASM-AND-OBJ: th.mula a0, a1, a2 +# CHECK-ASM: encoding: [0x0b,0x95,0xc5,0x20] +th.mula a0, a1, a2 + +# CHECK-ASM-AND-OBJ: th.mulah a0, a1, a2 +# CHECK-ASM: encoding: [0x0b,0x95,0xc5,0x28] +th.mulah a0, a1, a2 + +# CHECK-ASM-AND-OBJ: th.muls a0, a1, a2 +# CHECK-ASM: encoding: [0x0b,0x95,0xc5,0x22] +th.muls a0, a1, a2 + +# CHECK-ASM-AND-OBJ: th.mulsh a0, a1, a2 +# CHECK-ASM: encoding: [0x0b,0x95,0xc5,0x2a] +th.mulsh a0, a1, a2 diff --git a/llvm/test/MC/RISCV/rv64xtheadmac-valid.s b/llvm/test/MC/RISCV/rv64xtheadmac-valid.s new file mode 100644 --- /dev/null +++ b/llvm/test/MC/RISCV/rv64xtheadmac-valid.s @@ -0,0 +1,29 @@ +# RUN: llvm-mc %s -triple=riscv64 -mattr=+xtheadmac -show-encoding \ +# RUN: | FileCheck -check-prefixes=CHECK-ASM,CHECK-ASM-AND-OBJ %s +# RUN: llvm-mc -filetype=obj -triple=riscv64 -mattr=+xtheadmac < %s \ +# RUN: | llvm-objdump --mattr=+xtheadmac -d -r - \ +# RUN: | FileCheck --check-prefix=CHECK-ASM-AND-OBJ %s + +# CHECK-ASM-AND-OBJ: th.mula a0, a1, a2 +# CHECK-ASM: encoding: [0x0b,0x95,0xc5,0x20] +th.mula a0, a1, a2 + +# CHECK-ASM-AND-OBJ: th.mulah a0, a1, a2 +# CHECK-ASM: encoding: [0x0b,0x95,0xc5,0x28] +th.mulah a0, a1, a2 + +# CHECK-ASM-AND-OBJ: th.mulaw a0, a1, a2 +# CHECK-ASM: encoding: [0x0b,0x95,0xc5,0x24] +th.mulaw a0, a1, a2 + +# CHECK-ASM-AND-OBJ: th.muls a0, a1, a2 +# CHECK-ASM: encoding: [0x0b,0x95,0xc5,0x22] +th.muls a0, a1, a2 + +# CHECK-ASM-AND-OBJ: th.mulsh a0, a1, a2 +# CHECK-ASM: encoding: [0x0b,0x95,0xc5,0x2a] +th.mulsh a0, a1, a2 + +# CHECK-ASM-AND-OBJ: th.mulsw a0, a1, a2 +# CHECK-ASM: encoding: [0x0b,0x95,0xc5,0x26] +th.mulsw a0, a1, a2 diff --git a/llvm/test/MC/RISCV/xtheadmac-invalid.s b/llvm/test/MC/RISCV/xtheadmac-invalid.s new file mode 100644 --- /dev/null +++ b/llvm/test/MC/RISCV/xtheadmac-invalid.s @@ -0,0 +1,7 @@ +# RUN: not llvm-mc -triple riscv32 -mattr=+xtheadmac < %s 2>&1 | FileCheck %s +# RUN: not llvm-mc -triple riscv64 -mattr=+xtheadmac < %s 2>&1 | FileCheck %s + +th.mula t0, t1, 0(t2) # CHECK: :[[@LINE]]:18: error: invalid operand for instruction +th.muls t0, 12, t2 # CHECK: :[[@LINE]]:14: error: invalid operand for instruction +th.mulsh t0, t1, 34 # CHECK: :[[@LINE]]:18: error: invalid operand for instruction +th.mulsw t0, -56, t2 # CHECK: :[[@LINE]]:14: error: invalid operand for instruction