[RISCV][Clang] Add support for Zmmul extension
This patch implements recently ratified extension Zmmul, a subextension of M (Integer Multiplication and Division) consisting only multiplication part of it. Differential Revision: https://reviews.llvm.org/D103313 Reviewed By: craig.topper, jrtc27, asb
This commit is contained in:
parent
d1b58cada6
commit
3198364e6e
|
@ -158,8 +158,10 @@ void RISCVTargetInfo::getTargetDefines(const LangOptions &Opts,
|
|||
Builder.defineMacro(Twine("__riscv_", ExtName), Twine(Version));
|
||||
}
|
||||
|
||||
if (ISAInfo->hasExtension("m")) {
|
||||
if (ISAInfo->hasExtension("m") || ISAInfo->hasExtension("zmmul"))
|
||||
Builder.defineMacro("__riscv_mul");
|
||||
|
||||
if (ISAInfo->hasExtension("m")) {
|
||||
Builder.defineMacro("__riscv_div");
|
||||
Builder.defineMacro("__riscv_muldiv");
|
||||
}
|
||||
|
|
|
@ -579,3 +579,12 @@
|
|||
// RUN: -fsyntax-only 2>&1 | FileCheck -check-prefix=RV32-ZHINX-BADVERS %s
|
||||
// RV32-ZHINX-BADVERS: error: invalid arch name 'rv32izhinx0p1'
|
||||
// RV32-ZHINX-BADVERS: unsupported version number 0.1 for extension 'zhinx'
|
||||
|
||||
// RUN: %clang -target riscv32-unknown-elf -march=rv32i_zmmul2p0 -### %s \
|
||||
// RUN: -fsyntax-only 2>&1 | FileCheck -check-prefix=RV32-ZMMUL-BADVERS %s
|
||||
// RV32-ZMMUL-BADVERS: error: invalid arch name 'rv32i_zmmul2p0'
|
||||
// RV32-ZMMUL-BADVERS: unsupported version number 2.0 for extension
|
||||
|
||||
// RUN: %clang -target riscv32-unknown-elf -march=rv32i_zmmul1p0 -### %s \
|
||||
// RUN: -fsyntax-only 2>&1 | FileCheck -check-prefix=RV32-ZMMUL-GOODVERS %s
|
||||
// RV32-ZMMUL-GOODVERS: "-target-feature" "+zmmul"
|
||||
|
|
|
@ -77,6 +77,8 @@ static const RISCVSupportedExtension SupportedExtensions[] = {
|
|||
{"zkt", RISCVExtensionVersion{1, 0}},
|
||||
{"zk", RISCVExtensionVersion{1, 0}},
|
||||
|
||||
{"zmmul", RISCVExtensionVersion{1, 0}},
|
||||
|
||||
{"v", RISCVExtensionVersion{1, 0}},
|
||||
{"zvl32b", RISCVExtensionVersion{1, 0}},
|
||||
{"zvl64b", RISCVExtensionVersion{1, 0}},
|
||||
|
|
|
@ -19,6 +19,19 @@ def HasStdExtM : Predicate<"Subtarget->hasStdExtM()">,
|
|||
AssemblerPredicate<(all_of FeatureStdExtM),
|
||||
"'M' (Integer Multiplication and Division)">;
|
||||
|
||||
def FeatureStdExtZmmul
|
||||
: SubtargetFeature<"zmmul", "HasStdExtZmmul", "true",
|
||||
"'Zmmul' (Integer Multiplication)">;
|
||||
def HasStdExtZmmul : Predicate<"Subtarget->hasStdExtZmmul()">,
|
||||
AssemblerPredicate<(all_of FeatureStdExtZmmul),
|
||||
"'Zmmul' (Integer Multiplication)">;
|
||||
|
||||
def HasStdExtMOrZmmul
|
||||
: Predicate<"Subtarget->hasStdExtM() || Subtarget->hasStdExtZmmul()">,
|
||||
AssemblerPredicate<(any_of FeatureStdExtM, FeatureStdExtZmmul),
|
||||
"'M' (Integer Multiplication and Division) or "
|
||||
"'Zmmul' (Integer Multiplication)">;
|
||||
|
||||
def FeatureStdExtA
|
||||
: SubtargetFeature<"a", "HasStdExtA", "true",
|
||||
"'A' (Atomic Instructions)">;
|
||||
|
|
|
@ -215,21 +215,26 @@ RISCVTargetLowering::RISCVTargetLowering(const TargetMachine &TM,
|
|||
setLibcallName(RTLIB::MULO_I64, nullptr);
|
||||
}
|
||||
|
||||
if (!Subtarget.hasStdExtM()) {
|
||||
setOperationAction({ISD::MUL, ISD::MULHS, ISD::MULHU, ISD::SDIV, ISD::UDIV,
|
||||
ISD::SREM, ISD::UREM},
|
||||
XLenVT, Expand);
|
||||
if (!Subtarget.hasStdExtM() && !Subtarget.hasStdExtZmmul()) {
|
||||
setOperationAction({ISD::MUL, ISD::MULHS, ISD::MULHU}, XLenVT, Expand);
|
||||
} else {
|
||||
if (Subtarget.is64Bit()) {
|
||||
setOperationAction(ISD::MUL, {MVT::i32, MVT::i128}, Custom);
|
||||
|
||||
setOperationAction({ISD::SDIV, ISD::UDIV, ISD::UREM},
|
||||
{MVT::i8, MVT::i16, MVT::i32}, Custom);
|
||||
} else {
|
||||
setOperationAction(ISD::MUL, MVT::i64, Custom);
|
||||
}
|
||||
}
|
||||
|
||||
if (!Subtarget.hasStdExtM()) {
|
||||
setOperationAction({ISD::SDIV, ISD::UDIV, ISD::SREM, ISD::UREM},
|
||||
XLenVT, Expand);
|
||||
} else {
|
||||
if (Subtarget.is64Bit()) {
|
||||
setOperationAction({ISD::SDIV, ISD::UDIV, ISD::UREM},
|
||||
{MVT::i8, MVT::i16, MVT::i32}, Custom);
|
||||
}
|
||||
}
|
||||
|
||||
setOperationAction(
|
||||
{ISD::SDIVREM, ISD::UDIVREM, ISD::SMUL_LOHI, ISD::UMUL_LOHI}, XLenVT,
|
||||
Expand);
|
||||
|
@ -12258,10 +12263,12 @@ bool RISCVTargetLowering::shouldSignExtendTypeInLibCall(EVT Type, bool IsSigned)
|
|||
bool RISCVTargetLowering::decomposeMulByConstant(LLVMContext &Context, EVT VT,
|
||||
SDValue C) const {
|
||||
// Check integral scalar types.
|
||||
const bool HasExtMOrZmmul =
|
||||
Subtarget.hasStdExtM() || Subtarget.hasStdExtZmmul();
|
||||
if (VT.isScalarInteger()) {
|
||||
// Omit the optimization if the sub target has the M extension and the data
|
||||
// size exceeds XLen.
|
||||
if (Subtarget.hasStdExtM() && VT.getSizeInBits() > Subtarget.getXLen())
|
||||
if (HasExtMOrZmmul && VT.getSizeInBits() > Subtarget.getXLen())
|
||||
return false;
|
||||
if (auto *ConstNode = dyn_cast<ConstantSDNode>(C.getNode())) {
|
||||
// Break the MUL to a SLLI and an ADD/SUB.
|
||||
|
@ -12276,7 +12283,7 @@ bool RISCVTargetLowering::decomposeMulByConstant(LLVMContext &Context, EVT VT,
|
|||
return true;
|
||||
// Omit the following optimization if the sub target has the M extension
|
||||
// and the data size >= XLen.
|
||||
if (Subtarget.hasStdExtM() && VT.getSizeInBits() >= Subtarget.getXLen())
|
||||
if (HasExtMOrZmmul && VT.getSizeInBits() >= Subtarget.getXLen())
|
||||
return false;
|
||||
// Break the MUL to two SLLI instructions and an ADD/SUB, if Imm needs
|
||||
// a pair of LUI/ADDI.
|
||||
|
|
|
@ -1883,10 +1883,11 @@ Register RISCVInstrInfo::getVLENFactoredAmount(MachineFunction &MF,
|
|||
} else {
|
||||
Register N = MRI.createVirtualRegister(&RISCV::GPRRegClass);
|
||||
movImm(MBB, II, DL, N, NumOfVReg, Flag);
|
||||
if (!STI.hasStdExtM())
|
||||
if (!STI.hasStdExtM() && !STI.hasStdExtZmmul())
|
||||
MF.getFunction().getContext().diagnose(DiagnosticInfoUnsupported{
|
||||
MF.getFunction(),
|
||||
"M-extension must be enabled to calculate the vscaled size/offset."});
|
||||
"M- or Zmmul-extension must be enabled to calculate the vscaled size/"
|
||||
"offset."});
|
||||
BuildMI(MBB, II, DL, get(RISCV::MUL), VL)
|
||||
.addReg(VL, RegState::Kill)
|
||||
.addReg(N, RegState::Kill)
|
||||
|
|
|
@ -24,7 +24,7 @@ def riscv_remuw : SDNode<"RISCVISD::REMUW", SDT_RISCVIntBinOpW>;
|
|||
// Instructions
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
let Predicates = [HasStdExtM] in {
|
||||
let Predicates = [HasStdExtMOrZmmul] in {
|
||||
def MUL : ALU_rr<0b0000001, 0b000, "mul", /*Commutable*/1>,
|
||||
Sched<[WriteIMul, ReadIMul, ReadIMul]>;
|
||||
def MULH : ALU_rr<0b0000001, 0b001, "mulh", /*Commutable*/1>,
|
||||
|
@ -33,6 +33,9 @@ def MULHSU : ALU_rr<0b0000001, 0b010, "mulhsu">,
|
|||
Sched<[WriteIMul, ReadIMul, ReadIMul]>;
|
||||
def MULHU : ALU_rr<0b0000001, 0b011, "mulhu", /*Commutable*/1>,
|
||||
Sched<[WriteIMul, ReadIMul, ReadIMul]>;
|
||||
} // Predicates = [HasStdExtMOrZmmul]
|
||||
|
||||
let Predicates = [HasStdExtM] in {
|
||||
def DIV : ALU_rr<0b0000001, 0b100, "div">,
|
||||
Sched<[WriteIDiv, ReadIDiv, ReadIDiv]>;
|
||||
def DIVU : ALU_rr<0b0000001, 0b101, "divu">,
|
||||
|
@ -43,9 +46,12 @@ def REMU : ALU_rr<0b0000001, 0b111, "remu">,
|
|||
Sched<[WriteIDiv, ReadIDiv, ReadIDiv]>;
|
||||
} // Predicates = [HasStdExtM]
|
||||
|
||||
let Predicates = [HasStdExtM, IsRV64] in {
|
||||
let Predicates = [HasStdExtMOrZmmul, IsRV64] in {
|
||||
def MULW : ALUW_rr<0b0000001, 0b000, "mulw", /*Commutable*/1>,
|
||||
Sched<[WriteIMul32, ReadIMul32, ReadIMul32]>;
|
||||
} // Predicates = [HasStdExtMOrZmmul, IsRV64]
|
||||
|
||||
let Predicates = [HasStdExtM, IsRV64] in {
|
||||
def DIVW : ALUW_rr<0b0000001, 0b100, "divw">,
|
||||
Sched<[WriteIDiv32, ReadIDiv32, ReadIDiv32]>;
|
||||
def DIVUW : ALUW_rr<0b0000001, 0b101, "divuw">,
|
||||
|
@ -60,21 +66,25 @@ def REMUW : ALUW_rr<0b0000001, 0b111, "remuw">,
|
|||
// Pseudo-instructions and codegen patterns
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
let Predicates = [HasStdExtM] in {
|
||||
let Predicates = [HasStdExtMOrZmmul] in {
|
||||
def : PatGprGpr<mul, MUL>;
|
||||
def : PatGprGpr<mulhs, MULH>;
|
||||
def : PatGprGpr<mulhu, MULHU>;
|
||||
def : PatGprGpr<riscv_mulhsu, MULHSU>;
|
||||
} // Predicates = [HasStdExtMOrZmmul]
|
||||
|
||||
let Predicates = [HasStdExtM] in {
|
||||
def : PatGprGpr<sdiv, DIV>;
|
||||
def : PatGprGpr<udiv, DIVU>;
|
||||
def : PatGprGpr<srem, REM>;
|
||||
def : PatGprGpr<urem, REMU>;
|
||||
} // Predicates = [HasStdExtM]
|
||||
|
||||
let Predicates = [HasStdExtM, IsRV64] in {
|
||||
// Select W instructions if only the lower 32-bits of the result are used.
|
||||
let Predicates = [HasStdExtMOrZmmul, IsRV64] in
|
||||
def : PatGprGpr<binop_allwusers<mul>, MULW>;
|
||||
|
||||
let Predicates = [HasStdExtM, IsRV64] in {
|
||||
def : PatGprGpr<riscv_divw, DIVW>;
|
||||
def : PatGprGpr<riscv_divuw, DIVUW>;
|
||||
def : PatGprGpr<riscv_remuw, REMUW>;
|
||||
|
@ -96,11 +106,11 @@ def : Pat<(srem (sexti32 (i64 GPR:$rs1)), (sexti32 (i64 GPR:$rs2))),
|
|||
(REMW GPR:$rs1, GPR:$rs2)>;
|
||||
} // Predicates = [HasStdExtM, IsRV64]
|
||||
|
||||
let Predicates = [HasStdExtM, IsRV64, NotHasStdExtZba] in {
|
||||
let Predicates = [HasStdExtMOrZmmul, IsRV64, NotHasStdExtZba] in {
|
||||
// Special case for calculating the full 64-bit product of a 32x32 unsigned
|
||||
// multiply where the inputs aren't known to be zero extended. We can shift the
|
||||
// inputs left by 32 and use a MULHU. This saves two SRLIs needed to finish
|
||||
// zeroing the upper 32 bits.
|
||||
def : Pat<(i64 (mul (and GPR:$rs1, 0xffffffff), (and GPR:$rs2, 0xffffffff))),
|
||||
(MULHU (SLLI GPR:$rs1, 32), (SLLI GPR:$rs2, 32))>;
|
||||
} // Predicates = [HasStdExtM, IsRV64, NotHasStdExtZba]
|
||||
} // Predicates = [HasStdExtMOrZmmul, IsRV64, NotHasStdExtZba]
|
||||
|
|
|
@ -89,6 +89,7 @@ private:
|
|||
bool HasStdExtZicbom = false;
|
||||
bool HasStdExtZicboz = false;
|
||||
bool HasStdExtZicbop = false;
|
||||
bool HasStdExtZmmul = false;
|
||||
bool HasRV64 = false;
|
||||
bool IsRV32E = false;
|
||||
bool EnableLinkerRelax = false;
|
||||
|
@ -184,6 +185,7 @@ public:
|
|||
bool hasStdExtZicbom() const { return HasStdExtZicbom; }
|
||||
bool hasStdExtZicboz() const { return HasStdExtZicboz; }
|
||||
bool hasStdExtZicbop() const { return HasStdExtZicbop; }
|
||||
bool hasStdExtZmmul() const { return HasStdExtZmmul; }
|
||||
bool is64Bit() const { return HasRV64; }
|
||||
bool isRV32E() const { return IsRV32E; }
|
||||
bool enableLinkerRelax() const { return EnableLinkerRelax; }
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
;; Generate ELF attributes from llc.
|
||||
|
||||
; RUN: llc -mtriple=riscv32 -mattr=+m %s -o - | FileCheck --check-prefix=RV32M %s
|
||||
; RUN: llc -mtriple=riscv32 -mattr=+zmmul %s -o - | FileCheck --check-prefix=RV32ZMMUL %s
|
||||
; RUN: llc -mtriple=riscv32 -mattr=+m,+zmmul %s -o - | FileCheck --check-prefix=RV32MZMMUL %s
|
||||
; RUN: llc -mtriple=riscv32 -mattr=+a %s -o - | FileCheck --check-prefix=RV32A %s
|
||||
; RUN: llc -mtriple=riscv32 -mattr=+f %s -o - | FileCheck --check-prefix=RV32F %s
|
||||
; RUN: llc -mtriple=riscv32 -mattr=+d %s -o - | FileCheck --check-prefix=RV32D %s
|
||||
|
@ -40,6 +42,8 @@
|
|||
; 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=riscv64 -mattr=+m %s -o - | FileCheck --check-prefix=RV64M %s
|
||||
; RUN: llc -mtriple=riscv64 -mattr=+zmmul %s -o - | FileCheck --check-prefix=RV64ZMMUL %s
|
||||
; RUN: llc -mtriple=riscv64 -mattr=+m,+zmmul %s -o - | FileCheck --check-prefix=RV64MZMMUL %s
|
||||
; RUN: llc -mtriple=riscv64 -mattr=+a %s -o - | FileCheck --check-prefix=RV64A %s
|
||||
; RUN: llc -mtriple=riscv64 -mattr=+f %s -o - | FileCheck --check-prefix=RV64F %s
|
||||
; RUN: llc -mtriple=riscv64 -mattr=+d %s -o - | FileCheck --check-prefix=RV64D %s
|
||||
|
@ -80,6 +84,8 @@
|
|||
; RUN: llc -mtriple=riscv64 -mattr=+zicbop %s -o - | FileCheck --check-prefix=RV64ZICBOP %s
|
||||
|
||||
; RV32M: .attribute 5, "rv32i2p0_m2p0"
|
||||
; RV32ZMMUL: .attribute 5, "rv32i2p0_zmmul1p0"
|
||||
; RV32MZMMUL: .attribute 5, "rv32i2p0_m2p0_zmmul1p0"
|
||||
; RV32A: .attribute 5, "rv32i2p0_a2p0"
|
||||
; RV32F: .attribute 5, "rv32i2p0_f2p0"
|
||||
; RV32D: .attribute 5, "rv32i2p0_f2p0_d2p0"
|
||||
|
@ -120,6 +126,8 @@
|
|||
; RV32ZICBOP: .attribute 5, "rv32i2p0_zicbop1p0"
|
||||
|
||||
; RV64M: .attribute 5, "rv64i2p0_m2p0"
|
||||
; RV64ZMMUL: .attribute 5, "rv64i2p0_zmmul1p0"
|
||||
; RV64MZMMUL: .attribute 5, "rv64i2p0_m2p0_zmmul1p0"
|
||||
; RV64A: .attribute 5, "rv64i2p0_a2p0"
|
||||
; RV64F: .attribute 5, "rv64i2p0_f2p0"
|
||||
; RV64D: .attribute 5, "rv64i2p0_f2p0_d2p0"
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
; RUN: llc -mtriple=riscv32 -mattr=+zmmul -verify-machineinstrs < %s \
|
||||
; RUN: | not FileCheck -check-prefix=CHECK-DIV %s
|
||||
; RUN: llc -mtriple=riscv64 -mattr=+zmmul -verify-machineinstrs < %s \
|
||||
; RUN: | not FileCheck -check-prefix=CHECK-DIV %s
|
||||
; RUN: llc -mtriple=riscv32 -mattr=+zmmul -verify-machineinstrs < %s \
|
||||
; RUN: | not FileCheck -check-prefix=CHECK-REM %s
|
||||
; RUN: llc -mtriple=riscv64 -mattr=+zmmul -verify-machineinstrs < %s \
|
||||
; RUN: | not FileCheck -check-prefix=CHECK-REM %s
|
||||
|
||||
; RUN: llc -mtriple=riscv32 -mattr=+zmmul -verify-machineinstrs < %s \
|
||||
; RUN: | not FileCheck -check-prefix=CHECK-UDIV %s
|
||||
; RUN: llc -mtriple=riscv64 -mattr=+zmmul -verify-machineinstrs < %s \
|
||||
; RUN: | not FileCheck -check-prefix=CHECK-UDIV %s
|
||||
; RUN: llc -mtriple=riscv32 -mattr=+zmmul -verify-machineinstrs < %s \
|
||||
; RUN: | not FileCheck -check-prefix=CHECK-UREM %s
|
||||
; RUN: llc -mtriple=riscv64 -mattr=+zmmul -verify-machineinstrs < %s \
|
||||
; RUN: | not FileCheck -check-prefix=CHECK-UREM %s
|
||||
|
||||
; RUN: llc -mtriple=riscv32 -mattr=+zmmul -verify-machineinstrs < %s \
|
||||
; RUN: | FileCheck -check-prefix=CHECK-MUL %s
|
||||
; RUN: llc -mtriple=riscv64 -mattr=+zmmul -verify-machineinstrs < %s \
|
||||
; RUN: | FileCheck -check-prefix=CHECK-MUL %s
|
||||
|
||||
; RUN: llc -mtriple=riscv32 -mattr=+m -verify-machineinstrs < %s \
|
||||
; RUN: | FileCheck -check-prefixes=CHECK-MUL,CHECK-UDIV,CHECK-DIV,CHECK-UREM,CHECK-REM %s
|
||||
; RUN: llc -mtriple=riscv64 -mattr=+m -verify-machineinstrs < %s \
|
||||
; RUN: | FileCheck -check-prefixes=CHECK-MUL,CHECK-UDIV,CHECK-DIV,CHECK-UREM,CHECK-REM %s
|
||||
|
||||
define i32 @foo(i32 %a, i32 %b) {
|
||||
; CHECK-UDIV: divu{{w?}} {{[as]}}{{[0-9]}}, {{[as]}}{{[0-9]}}, {{[as]}}{{[0-9]}}
|
||||
%1 = udiv i32 %a, %b
|
||||
; CHECK-DIV: div{{w?}} {{[as]}}{{[0-9]}}, {{[as]}}{{[0-9]}}, {{[as]}}{{[0-9]}}
|
||||
%2 = sdiv i32 %a, %1
|
||||
; CHECK-MUL: mul{{w?}} {{[as]}}{{[0-9]}}, {{[as]}}{{[0-9]}}, {{[as]}}{{[0-9]}}
|
||||
%3 = mul i32 %b, %2
|
||||
; CHECK-UREM: remu{{w?}} {{[as]}}{{[0-9]}}, {{[as]}}{{[0-9]}}, {{[as]}}{{[0-9]}}
|
||||
%4 = urem i32 %3, %b
|
||||
; CHECK-REM: rem{{w?}} {{[as]}}{{[0-9]}}, {{[as]}}{{[0-9]}}, {{[as]}}{{[0-9]}}
|
||||
%5 = srem i32 %4, %a
|
||||
ret i32 %5
|
||||
}
|
|
@ -169,7 +169,7 @@ ori a0, a1 # CHECK: :[[@LINE]]:1: error: too few operands for instruction
|
|||
xor s2, s2 # CHECK: :[[@LINE]]:1: error: too few operands for instruction
|
||||
|
||||
# Instruction not in the base ISA
|
||||
mul a4, ra, s0 # CHECK: :[[@LINE]]:1: error: instruction requires the following: 'M' (Integer Multiplication and Division)
|
||||
div a4, ra, s0 # CHECK: :[[@LINE]]:1: error: instruction requires the following: 'M' (Integer Multiplication and Division)
|
||||
amomaxu.w s5, s4, (s3) # CHECK: :[[@LINE]]:1: error: instruction requires the following: 'A' (Atomic Instructions)
|
||||
fadd.s ft0, ft1, ft2 # CHECK: :[[@LINE]]:1: error: instruction requires the following: 'F' (Single-Precision Floating-Point){{$}}
|
||||
fadd.h ft0, ft1, ft2 # CHECK: :[[@LINE]]:1: error: instruction requires the following: 'Zfh' (Half-Precision Floating-Point)
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
# RUN: not llvm-mc %s -triple=riscv32 -mattr=+zmmul -riscv-no-aliases 2>&1 \
|
||||
# RUN: | FileCheck -check-prefixes=CHECK-ERROR %s
|
||||
|
||||
# CHECK-ERROR: 5:1: error: instruction requires the following: 'M' (Integer Multiplication and Division)
|
||||
div s0, s0, s0
|
||||
|
||||
# CHECK-ERROR: 8:1: error: instruction requires the following: 'M' (Integer Multiplication and Division)
|
||||
divu gp, a0, a1
|
||||
|
||||
# CHECK-ERROR: 11:1: error: instruction requires the following: 'M' (Integer Multiplication and Division)
|
||||
rem s2, s2, s8
|
||||
|
||||
# CHECK-ERROR: 14:1: error: instruction requires the following: 'M' (Integer Multiplication and Division)
|
||||
remu x18, x18, x24
|
|
@ -0,0 +1,14 @@
|
|||
# RUN: llvm-mc %s -triple=riscv32 -mattr=+zmmul -riscv-no-aliases 2>&1 \
|
||||
# RUN: | FileCheck -check-prefixes=CHECK-INST %s
|
||||
|
||||
# CHECK-INST: mul a4, ra, s0
|
||||
mul a4, ra, s0
|
||||
|
||||
# CHECK-INST: mulh ra, zero, zero
|
||||
mulh x1, x0, x0
|
||||
|
||||
# CHECK-INST: mulhsu t0, t2, t1
|
||||
mulhsu t0, t2, t1
|
||||
|
||||
# CHECK-INST: mulhu a5, a4, a3
|
||||
mulhu a5, a4, a3
|
|
@ -0,0 +1,14 @@
|
|||
# RUN: not llvm-mc %s -triple=riscv64 -mattr=+zmmul -riscv-no-aliases 2>&1 \
|
||||
# RUN: | FileCheck -check-prefixes=CHECK-ERROR %s
|
||||
|
||||
# CHECK-ERROR: 5:1: error: instruction requires the following: 'M' (Integer Multiplication and Division)
|
||||
divw tp, t0, t1
|
||||
|
||||
# CHECK-ERROR: 8:1: error: instruction requires the following: 'M' (Integer Multiplication and Division)
|
||||
divuw t2, s0, s2
|
||||
|
||||
# CHECK-ERROR: 11:1: error: instruction requires the following: 'M' (Integer Multiplication and Division)
|
||||
remw a0, a1, a2
|
||||
|
||||
# CHECK-ERROR: 14:1: error: instruction requires the following: 'M' (Integer Multiplication and Division)
|
||||
remuw a3, a4, a5
|
|
@ -0,0 +1,5 @@
|
|||
# RUN: llvm-mc %s -triple=riscv64 -mattr=+zmmul -riscv-no-aliases 2>&1 \
|
||||
# RUN: | FileCheck -check-prefixes=CHECK-INST %s
|
||||
|
||||
# CHECK-INST: mulw ra, sp, gp
|
||||
mulw ra, sp, gp
|
Loading…
Reference in New Issue