1 //===-- RISCVInstrInfo.td - Target Description for RISC-V --*- tablegen -*-===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 // This file describes the RISC-V instructions in TableGen format.
11 //===----------------------------------------------------------------------===//
13 //===----------------------------------------------------------------------===//
14 // RISC-V specific DAG Nodes.
15 //===----------------------------------------------------------------------===//
17 // Target-independent type requirements, but with target-specific formats.
18 def SDT_CallSeqStart : SDCallSeqStart<[SDTCisVT<0, i32>,
20 def SDT_CallSeqEnd : SDCallSeqEnd<[SDTCisVT<0, i32>,
23 // Target-dependent type requirements.
24 def SDT_RISCVCall : SDTypeProfile<0, -1, [SDTCisVT<0, XLenVT>]>;
25 def SDT_RISCVSelectCC : SDTypeProfile<1, 5, [SDTCisSameAs<1, 2>,
29 def SDT_RISCVBrCC : SDTypeProfile<0, 4, [SDTCisSameAs<0, 1>,
31 SDTCisVT<3, OtherVT>]>;
32 def SDT_RISCVReadCSR : SDTypeProfile<1, 1, [SDTCisInt<0>, SDTCisInt<1>]>;
33 def SDT_RISCVWriteCSR : SDTypeProfile<0, 2, [SDTCisInt<0>, SDTCisInt<1>]>;
34 def SDT_RISCVSwapCSR : SDTypeProfile<1, 2, [SDTCisInt<0>, SDTCisInt<1>,
36 def SDT_RISCVReadCycleWide : SDTypeProfile<2, 0, [SDTCisVT<0, i32>,
38 def SDT_RISCVIntUnaryOpW : SDTypeProfile<1, 1, [
39 SDTCisSameAs<0, 1>, SDTCisVT<0, i64>
41 def SDT_RISCVIntBinOpW : SDTypeProfile<1, 2, [
42 SDTCisSameAs<0, 1>, SDTCisSameAs<0, 2>, SDTCisVT<0, i64>
44 def SDT_RISCVIntShiftDOpW : SDTypeProfile<1, 3, [
45 SDTCisSameAs<0, 1>, SDTCisSameAs<0, 2>, SDTCisVT<0, i64>, SDTCisVT<3, i64>
48 // Target-independent nodes, but with target-specific formats.
49 def callseq_start : SDNode<"ISD::CALLSEQ_START", SDT_CallSeqStart,
50 [SDNPHasChain, SDNPOutGlue]>;
51 def callseq_end : SDNode<"ISD::CALLSEQ_END", SDT_CallSeqEnd,
52 [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue]>;
54 // Target-dependent nodes.
55 def riscv_call : SDNode<"RISCVISD::CALL", SDT_RISCVCall,
56 [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue,
58 def riscv_ret_glue : SDNode<"RISCVISD::RET_GLUE", SDTNone,
59 [SDNPHasChain, SDNPOptInGlue, SDNPVariadic]>;
60 def riscv_sret_glue : SDNode<"RISCVISD::SRET_GLUE", SDTNone,
61 [SDNPHasChain, SDNPOptInGlue]>;
62 def riscv_mret_glue : SDNode<"RISCVISD::MRET_GLUE", SDTNone,
63 [SDNPHasChain, SDNPOptInGlue]>;
64 def riscv_selectcc : SDNode<"RISCVISD::SELECT_CC", SDT_RISCVSelectCC>;
65 def riscv_brcc : SDNode<"RISCVISD::BR_CC", SDT_RISCVBrCC,
67 def riscv_tail : SDNode<"RISCVISD::TAIL", SDT_RISCVCall,
68 [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue,
70 def riscv_sllw : SDNode<"RISCVISD::SLLW", SDT_RISCVIntBinOpW>;
71 def riscv_sraw : SDNode<"RISCVISD::SRAW", SDT_RISCVIntBinOpW>;
72 def riscv_srlw : SDNode<"RISCVISD::SRLW", SDT_RISCVIntBinOpW>;
73 def riscv_read_csr : SDNode<"RISCVISD::READ_CSR", SDT_RISCVReadCSR,
75 def riscv_write_csr : SDNode<"RISCVISD::WRITE_CSR", SDT_RISCVWriteCSR,
77 def riscv_swap_csr : SDNode<"RISCVISD::SWAP_CSR", SDT_RISCVSwapCSR,
80 def riscv_read_cycle_wide : SDNode<"RISCVISD::READ_CYCLE_WIDE",
81 SDT_RISCVReadCycleWide,
82 [SDNPHasChain, SDNPSideEffect]>;
84 def riscv_add_lo : SDNode<"RISCVISD::ADD_LO", SDTIntBinOp>;
85 def riscv_hi : SDNode<"RISCVISD::HI", SDTIntUnaryOp>;
86 def riscv_lla : SDNode<"RISCVISD::LLA", SDTIntUnaryOp>;
87 def riscv_add_tprel : SDNode<"RISCVISD::ADD_TPREL",
88 SDTypeProfile<1, 3, [SDTCisSameAs<0, 1>,
93 //===----------------------------------------------------------------------===//
94 // Operand and SDNode transformation definitions.
95 //===----------------------------------------------------------------------===//
97 class ImmXLenAsmOperand<string prefix, string suffix = ""> : AsmOperandClass {
98 let Name = prefix # "ImmXLen" # suffix;
99 let RenderMethod = "addImmOperands";
100 let DiagnosticType = !strconcat("Invalid", Name);
103 class ImmAsmOperand<string prefix, int width, string suffix> : AsmOperandClass {
104 let Name = prefix # "Imm" # width # suffix;
105 let RenderMethod = "addImmOperands";
106 let DiagnosticType = !strconcat("Invalid", Name);
109 def ImmZeroAsmOperand : AsmOperandClass {
110 let Name = "ImmZero";
111 let RenderMethod = "addImmOperands";
112 let DiagnosticType = !strconcat("Invalid", Name);
115 // A parse method for (${gpr}) or 0(${gpr}), where the 0 is be silently ignored.
116 def ZeroOffsetMemOpOperand : AsmOperandClass {
117 let Name = "ZeroOffsetMemOpOperand";
118 let RenderMethod = "addRegOperands";
119 let PredicateMethod = "isGPR";
120 let ParserMethod = "parseZeroOffsetMemOp";
123 class MemOperand<RegisterClass regClass> : RegisterOperand<regClass>{
124 let OperandType = "OPERAND_MEMORY";
127 def GPRMemZeroOffset : MemOperand<GPR> {
128 let ParserMatchClass = ZeroOffsetMemOpOperand;
129 let PrintMethod = "printZeroOffsetMemOp";
132 def GPRMem : MemOperand<GPR>;
134 def SPMem : MemOperand<SP>;
136 def GPRCMem : MemOperand<GPRC>;
138 class SImmAsmOperand<int width, string suffix = "">
139 : ImmAsmOperand<"S", width, suffix> {
142 class UImmAsmOperand<int width, string suffix = "">
143 : ImmAsmOperand<"U", width, suffix> {
146 class RISCVOp<ValueType vt = XLenVT> : Operand<vt> {
147 let OperandNamespace = "RISCVOp";
150 class RISCVUImmOp<int bitsNum> : RISCVOp {
151 let ParserMatchClass = UImmAsmOperand<bitsNum>;
152 let DecoderMethod = "decodeUImmOperand<" # bitsNum # ">";
153 let OperandType = "OPERAND_UIMM" # bitsNum;
156 class RISCVUImmLeafOp<int bitsNum> :
157 RISCVUImmOp<bitsNum>, ImmLeaf<XLenVT, "return isUInt<" # bitsNum # ">(Imm);">;
159 class RISCVSImmOp<int bitsNum> : RISCVOp {
160 let ParserMatchClass = SImmAsmOperand<bitsNum>;
161 let EncoderMethod = "getImmOpValue";
162 let DecoderMethod = "decodeSImmOperand<" # bitsNum # ">";
163 let OperandType = "OPERAND_SIMM" # bitsNum;
166 class RISCVSImmLeafOp<int bitsNum> :
167 RISCVSImmOp<bitsNum>, ImmLeaf<XLenVT, "return isInt<" # bitsNum # ">(Imm);">;
169 def FenceArg : AsmOperandClass {
170 let Name = "FenceArg";
171 let RenderMethod = "addFenceArgOperands";
172 let ParserMethod = "parseFenceArg";
175 def fencearg : RISCVOp {
176 let ParserMatchClass = FenceArg;
177 let PrintMethod = "printFenceArg";
178 let DecoderMethod = "decodeUImmOperand<4>";
179 let OperandType = "OPERAND_UIMM4";
182 def UImmLog2XLenAsmOperand : AsmOperandClass {
183 let Name = "UImmLog2XLen";
184 let RenderMethod = "addImmOperands";
185 let DiagnosticType = "InvalidUImmLog2XLen";
188 def uimmlog2xlen : RISCVOp, ImmLeaf<XLenVT, [{
189 if (Subtarget->is64Bit())
190 return isUInt<6>(Imm);
191 return isUInt<5>(Imm);
193 let ParserMatchClass = UImmLog2XLenAsmOperand;
194 // TODO: should ensure invalid shamt is rejected when decoding.
195 let DecoderMethod = "decodeUImmOperand<6>";
196 let MCOperandPredicate = [{
198 if (!MCOp.evaluateAsConstantImm(Imm))
200 if (STI.getTargetTriple().isArch64Bit())
201 return isUInt<6>(Imm);
202 return isUInt<5>(Imm);
204 let OperandType = "OPERAND_UIMMLOG2XLEN";
207 def InsnDirectiveOpcode : AsmOperandClass {
208 let Name = "InsnDirectiveOpcode";
209 let ParserMethod = "parseInsnDirectiveOpcode";
210 let RenderMethod = "addImmOperands";
211 let PredicateMethod = "isImm";
214 def uimm1 : RISCVUImmLeafOp<1>;
215 def uimm2 : RISCVUImmLeafOp<2> {
216 let MCOperandPredicate = [{
218 if (!MCOp.evaluateAsConstantImm(Imm))
220 return isUInt<2>(Imm);
223 def uimm3 : RISCVUImmOp<3>;
224 def uimm4 : RISCVUImmOp<4>;
225 def uimm5 : RISCVUImmLeafOp<5>;
226 def uimm6 : RISCVUImmLeafOp<6>;
227 def uimm7_opcode : RISCVUImmOp<7> {
228 let ParserMatchClass = InsnDirectiveOpcode;
230 def uimm7 : RISCVUImmOp<7>;
231 def uimm8 : RISCVUImmOp<8>;
232 def simm12 : RISCVSImmLeafOp<12> {
233 let MCOperandPredicate = [{
235 if (MCOp.evaluateAsConstantImm(Imm))
236 return isInt<12>(Imm);
237 return MCOp.isBareSymbolRef();
241 // A 12-bit signed immediate which cannot fit in 6-bit signed immediate,
242 // but even negative value fit in 12-bit.
243 def simm12_no6 : ImmLeaf<XLenVT, [{
244 return isInt<12>(Imm) && !isInt<6>(Imm) && isInt<12>(-Imm);}]>;
246 // A 13-bit signed immediate where the least significant bit is zero.
247 def simm13_lsb0 : Operand<OtherVT> {
248 let ParserMatchClass = SImmAsmOperand<13, "Lsb0">;
249 let PrintMethod = "printBranchOperand";
250 let EncoderMethod = "getImmOpValueAsr1";
251 let DecoderMethod = "decodeSImmOperandAndLsl1<13>";
252 let MCOperandPredicate = [{
254 if (MCOp.evaluateAsConstantImm(Imm))
255 return isShiftedInt<12, 1>(Imm);
256 return MCOp.isBareSymbolRef();
258 let OperandType = "OPERAND_PCREL";
261 class UImm20Operand : RISCVOp {
262 let EncoderMethod = "getImmOpValue";
263 let DecoderMethod = "decodeUImmOperand<20>";
264 let OperandType = "OPERAND_UIMM20";
267 class UImm20OperandMaybeSym : UImm20Operand {
268 let MCOperandPredicate = [{
270 if (MCOp.evaluateAsConstantImm(Imm))
271 return isUInt<20>(Imm);
272 return MCOp.isBareSymbolRef();
276 def uimm20_lui : UImm20OperandMaybeSym {
277 let ParserMatchClass = UImmAsmOperand<20, "LUI">;
279 def uimm20_auipc : UImm20OperandMaybeSym {
280 let ParserMatchClass = UImmAsmOperand<20, "AUIPC">;
283 def uimm20 : UImm20Operand {
284 let ParserMatchClass = UImmAsmOperand<20>;
285 let MCOperandPredicate = [{
287 if (!MCOp.evaluateAsConstantImm(Imm))
289 return isUInt<20>(Imm);
293 def Simm21Lsb0JALAsmOperand : SImmAsmOperand<21, "Lsb0JAL"> {
294 let ParserMethod = "parseJALOffset";
297 // A 21-bit signed immediate where the least significant bit is zero.
298 def simm21_lsb0_jal : Operand<OtherVT> {
299 let ParserMatchClass = Simm21Lsb0JALAsmOperand;
300 let PrintMethod = "printBranchOperand";
301 let EncoderMethod = "getImmOpValueAsr1";
302 let DecoderMethod = "decodeSImmOperandAndLsl1<21>";
303 let MCOperandPredicate = [{
305 if (MCOp.evaluateAsConstantImm(Imm))
306 return isShiftedInt<20, 1>(Imm);
307 return MCOp.isBareSymbolRef();
309 let OperandType = "OPERAND_PCREL";
312 def BareSymbol : AsmOperandClass {
313 let Name = "BareSymbol";
314 let RenderMethod = "addImmOperands";
315 let DiagnosticType = "InvalidBareSymbol";
316 let ParserMethod = "parseBareSymbol";
320 def bare_symbol : Operand<XLenVT> {
321 let ParserMatchClass = BareSymbol;
324 def CallSymbol : AsmOperandClass {
325 let Name = "CallSymbol";
326 let RenderMethod = "addImmOperands";
327 let DiagnosticType = "InvalidCallSymbol";
328 let ParserMethod = "parseCallSymbol";
331 // A bare symbol used in call/tail only.
332 def call_symbol : Operand<XLenVT> {
333 let ParserMatchClass = CallSymbol;
336 def PseudoJumpSymbol : AsmOperandClass {
337 let Name = "PseudoJumpSymbol";
338 let RenderMethod = "addImmOperands";
339 let DiagnosticType = "InvalidPseudoJumpSymbol";
340 let ParserMethod = "parsePseudoJumpSymbol";
343 // A bare symbol used for pseudo jumps only.
344 def pseudo_jump_symbol : Operand<XLenVT> {
345 let ParserMatchClass = PseudoJumpSymbol;
348 def TPRelAddSymbol : AsmOperandClass {
349 let Name = "TPRelAddSymbol";
350 let RenderMethod = "addImmOperands";
351 let DiagnosticType = "InvalidTPRelAddSymbol";
352 let ParserMethod = "parseOperandWithModifier";
355 // A bare symbol with the %tprel_add variant.
356 def tprel_add_symbol : Operand<XLenVT> {
357 let ParserMatchClass = TPRelAddSymbol;
360 def CSRSystemRegister : AsmOperandClass {
361 let Name = "CSRSystemRegister";
362 let ParserMethod = "parseCSRSystemRegister";
363 let DiagnosticType = "InvalidCSRSystemRegister";
366 def csr_sysreg : RISCVOp {
367 let ParserMatchClass = CSRSystemRegister;
368 let PrintMethod = "printCSRSystemRegister";
369 let DecoderMethod = "decodeUImmOperand<12>";
370 let OperandType = "OPERAND_UIMM12";
373 // A parameterized register class alternative to i32imm/i64imm from Target.td.
374 def ixlenimm : Operand<XLenVT>;
376 def ixlenimm_li : Operand<XLenVT> {
377 let ParserMatchClass = ImmXLenAsmOperand<"", "LI">;
380 // Accepts subset of LI operands, used by LAImm and LLAImm
381 def ixlenimm_li_restricted : Operand<XLenVT> {
382 let ParserMatchClass = ImmXLenAsmOperand<"", "LI_Restricted">;
385 // Standalone (codegen-only) immleaf patterns.
387 // A 6-bit constant greater than 32.
388 def uimm6gt32 : ImmLeaf<XLenVT, [{
389 return isUInt<6>(Imm) && Imm > 32;
393 // Necessary because a frameindex can't be matched directly in a pattern.
394 def FrameAddrRegImm : ComplexPattern<iPTR, 2, "SelectFrameAddrRegImm",
395 [frameindex, or, add]>;
396 def AddrRegImm : ComplexPattern<iPTR, 2, "SelectAddrRegImm">;
398 // Return the negation of an immediate value.
399 def NegImm : SDNodeXForm<imm, [{
400 return CurDAG->getTargetConstant(-N->getSExtValue(), SDLoc(N),
404 // Return an immediate value minus 32.
405 def ImmSub32 : SDNodeXForm<imm, [{
406 return CurDAG->getTargetConstant(N->getSExtValue() - 32, SDLoc(N),
410 // Return an immediate subtracted from XLen.
411 def ImmSubFromXLen : SDNodeXForm<imm, [{
412 uint64_t XLen = Subtarget->getXLen();
413 return CurDAG->getTargetConstant(XLen - N->getZExtValue(), SDLoc(N),
417 // Return an immediate subtracted from 32.
418 def ImmSubFrom32 : SDNodeXForm<imm, [{
419 return CurDAG->getTargetConstant(32 - N->getZExtValue(), SDLoc(N),
423 // Check if (add r, imm) can be optimized to (ADDI (ADDI r, imm0), imm1),
424 // in which imm = imm0 + imm1 and both imm0 and imm1 are simm12. We make imm0
425 // as large as possible and imm1 as small as possible so that we might be able
426 // to use c.addi for the small immediate.
427 def AddiPair : PatLeaf<(imm), [{
430 // The immediate operand must be in range [-4096,-2049] or [2048,4094].
431 int64_t Imm = N->getSExtValue();
432 return (-4096 <= Imm && Imm <= -2049) || (2048 <= Imm && Imm <= 4094);
435 // Return imm - (imm < 0 ? -2048 : 2047).
436 def AddiPairImmSmall : SDNodeXForm<imm, [{
437 int64_t Imm = N->getSExtValue();
438 int64_t Adj = N->getSExtValue() < 0 ? -2048 : 2047;
439 return CurDAG->getTargetConstant(Imm - Adj, SDLoc(N),
443 // Return -2048 if immediate is negative or 2047 if positive. These are the
444 // largest simm12 values.
445 def AddiPairImmLarge : SDNodeXForm<imm, [{
446 int64_t Imm = N->getSExtValue() < 0 ? -2048 : 2047;
447 return CurDAG->getTargetConstant(Imm, SDLoc(N),
451 def TrailingZeros : SDNodeXForm<imm, [{
452 return CurDAG->getTargetConstant(llvm::countr_zero(N->getZExtValue()),
453 SDLoc(N), N->getValueType(0));
456 def XLenSubTrailingOnes : SDNodeXForm<imm, [{
457 uint64_t XLen = Subtarget->getXLen();
458 uint64_t TrailingOnes = llvm::countr_one(N->getZExtValue());
459 return CurDAG->getTargetConstant(XLen - TrailingOnes, SDLoc(N),
463 // Checks if this mask is a non-empty sequence of ones starting at the
464 // most/least significant bit with the remainder zero and exceeds simm32/simm12.
465 def LeadingOnesMask : PatLeaf<(imm), [{
468 return !isInt<32>(N->getSExtValue()) && isMask_64(~N->getSExtValue());
471 def TrailingOnesMask : PatLeaf<(imm), [{
474 return !isInt<12>(N->getSExtValue()) && isMask_64(N->getZExtValue());
475 }], XLenSubTrailingOnes>;
477 // Similar to LeadingOnesMask, but only consider leading ones in the lower 32
479 def LeadingOnesWMask : PatLeaf<(imm), [{
482 // If the value is a uint32 but not an int32, it must have bit 31 set and
483 // bits 63:32 cleared. After that we're looking for a shifted mask but not
485 int64_t Imm = N->getSExtValue();
486 return !isInt<32>(Imm) && isUInt<32>(Imm) && isShiftedMask_64(Imm) &&
487 Imm != UINT64_C(0xffffffff);
490 //===----------------------------------------------------------------------===//
491 // Instruction Formats
492 //===----------------------------------------------------------------------===//
494 include "RISCVInstrFormats.td"
496 //===----------------------------------------------------------------------===//
497 // Instruction Class Templates
498 //===----------------------------------------------------------------------===//
500 let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
501 class BranchCC_rri<bits<3> funct3, string opcodestr>
502 : RVInstB<funct3, OPC_BRANCH, (outs),
503 (ins GPR:$rs1, GPR:$rs2, simm13_lsb0:$imm12),
504 opcodestr, "$rs1, $rs2, $imm12">,
505 Sched<[WriteJmp, ReadJmp, ReadJmp]> {
507 let isTerminator = 1;
510 let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in {
511 class Load_ri<bits<3> funct3, string opcodestr>
512 : RVInstI<funct3, OPC_LOAD, (outs GPR:$rd), (ins GPRMem:$rs1, simm12:$imm12),
513 opcodestr, "$rd, ${imm12}(${rs1})">;
515 class HLoad_r<bits<7> funct7, bits<5> funct5, string opcodestr>
516 : RVInstR<funct7, 0b100, OPC_SYSTEM, (outs GPR:$rd),
517 (ins GPRMemZeroOffset:$rs1), opcodestr, "$rd, $rs1"> {
522 // Operands for stores are in the order srcreg, base, offset rather than
523 // reflecting the order these fields are specified in the instruction
525 let hasSideEffects = 0, mayLoad = 0, mayStore = 1 in {
526 class Store_rri<bits<3> funct3, string opcodestr>
527 : RVInstS<funct3, OPC_STORE, (outs),
528 (ins GPR:$rs2, GPRMem:$rs1, simm12:$imm12),
529 opcodestr, "$rs2, ${imm12}(${rs1})">;
531 class HStore_rr<bits<7> funct7, string opcodestr>
532 : RVInstR<funct7, 0b100, OPC_SYSTEM, (outs),
533 (ins GPR:$rs2, GPRMemZeroOffset:$rs1),
534 opcodestr, "$rs2, $rs1"> {
539 let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
540 class ALU_ri<bits<3> funct3, string opcodestr>
541 : RVInstI<funct3, OPC_OP_IMM, (outs GPR:$rd), (ins GPR:$rs1, simm12:$imm12),
542 opcodestr, "$rd, $rs1, $imm12">,
543 Sched<[WriteIALU, ReadIALU]>;
545 let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
546 class Shift_ri<bits<5> imm11_7, bits<3> funct3, string opcodestr>
547 : RVInstIShift<imm11_7, funct3, OPC_OP_IMM, (outs GPR:$rd),
548 (ins GPR:$rs1, uimmlog2xlen:$shamt), opcodestr,
549 "$rd, $rs1, $shamt">,
550 Sched<[WriteShiftImm, ReadShiftImm]>;
552 let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
553 class ALU_rr<bits<7> funct7, bits<3> funct3, string opcodestr,
555 : RVInstR<funct7, funct3, OPC_OP, (outs GPR:$rd), (ins GPR:$rs1, GPR:$rs2),
556 opcodestr, "$rd, $rs1, $rs2"> {
557 let isCommutable = Commutable;
560 let hasNoSchedulingInfo = 1,
561 hasSideEffects = 1, mayLoad = 0, mayStore = 0 in
562 class CSR_ir<bits<3> funct3, string opcodestr>
563 : RVInstI<funct3, OPC_SYSTEM, (outs GPR:$rd), (ins csr_sysreg:$imm12, GPR:$rs1),
564 opcodestr, "$rd, $imm12, $rs1">, Sched<[WriteCSR, ReadCSR]>;
566 let hasNoSchedulingInfo = 1,
567 hasSideEffects = 1, mayLoad = 0, mayStore = 0 in
568 class CSR_ii<bits<3> funct3, string opcodestr>
569 : RVInstI<funct3, OPC_SYSTEM, (outs GPR:$rd),
570 (ins csr_sysreg:$imm12, uimm5:$rs1),
571 opcodestr, "$rd, $imm12, $rs1">, Sched<[WriteCSR]>;
573 let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
574 class ShiftW_ri<bits<7> imm11_5, bits<3> funct3, string opcodestr>
575 : RVInstIShiftW<imm11_5, funct3, OPC_OP_IMM_32, (outs GPR:$rd),
576 (ins GPR:$rs1, uimm5:$shamt), opcodestr,
577 "$rd, $rs1, $shamt">,
578 Sched<[WriteShiftImm32, ReadShiftImm32]>;
580 let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
581 class ALUW_rr<bits<7> funct7, bits<3> funct3, string opcodestr,
583 : RVInstR<funct7, funct3, OPC_OP_32, (outs GPR:$rd),
584 (ins GPR:$rs1, GPR:$rs2), opcodestr, "$rd, $rs1, $rs2"> {
585 let isCommutable = Commutable;
588 let hasSideEffects = 1, mayLoad = 0, mayStore = 0 in
589 class Priv<string opcodestr, bits<7> funct7>
590 : RVInstR<funct7, 0b000, OPC_SYSTEM, (outs), (ins GPR:$rs1, GPR:$rs2),
593 let hasSideEffects = 1, mayLoad = 0, mayStore = 0 in
594 class Priv_rr<string opcodestr, bits<7> funct7>
595 : RVInstR<funct7, 0b000, OPC_SYSTEM, (outs), (ins GPR:$rs1, GPR:$rs2),
596 opcodestr, "$rs1, $rs2"> {
600 //===----------------------------------------------------------------------===//
602 //===----------------------------------------------------------------------===//
604 let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in {
605 let isReMaterializable = 1, isAsCheapAsAMove = 1,
606 IsSignExtendingOpW = 1 in
607 def LUI : RVInstU<OPC_LUI, (outs GPR:$rd), (ins uimm20_lui:$imm20),
608 "lui", "$rd, $imm20">, Sched<[WriteIALU]>;
610 def AUIPC : RVInstU<OPC_AUIPC, (outs GPR:$rd), (ins uimm20_auipc:$imm20),
611 "auipc", "$rd, $imm20">, Sched<[WriteIALU]>;
613 def JAL : RVInstJ<OPC_JAL, (outs GPR:$rd), (ins simm21_lsb0_jal:$imm20),
614 "jal", "$rd, $imm20">, Sched<[WriteJal]>;
616 def JALR : RVInstI<0b000, OPC_JALR, (outs GPR:$rd),
617 (ins GPR:$rs1, simm12:$imm12),
618 "jalr", "$rd, ${imm12}(${rs1})">,
619 Sched<[WriteJalr, ReadJalr]>;
620 } // hasSideEffects = 0, mayLoad = 0, mayStore = 0
622 def BEQ : BranchCC_rri<0b000, "beq">;
623 def BNE : BranchCC_rri<0b001, "bne">;
624 def BLT : BranchCC_rri<0b100, "blt">;
625 def BGE : BranchCC_rri<0b101, "bge">;
626 def BLTU : BranchCC_rri<0b110, "bltu">;
627 def BGEU : BranchCC_rri<0b111, "bgeu">;
629 let IsSignExtendingOpW = 1 in {
630 def LB : Load_ri<0b000, "lb">, Sched<[WriteLDB, ReadMemBase]>;
631 def LH : Load_ri<0b001, "lh">, Sched<[WriteLDH, ReadMemBase]>;
632 def LW : Load_ri<0b010, "lw">, Sched<[WriteLDW, ReadMemBase]>;
633 def LBU : Load_ri<0b100, "lbu">, Sched<[WriteLDB, ReadMemBase]>;
634 def LHU : Load_ri<0b101, "lhu">, Sched<[WriteLDH, ReadMemBase]>;
637 def SB : Store_rri<0b000, "sb">, Sched<[WriteSTB, ReadStoreData, ReadMemBase]>;
638 def SH : Store_rri<0b001, "sh">, Sched<[WriteSTH, ReadStoreData, ReadMemBase]>;
639 def SW : Store_rri<0b010, "sw">, Sched<[WriteSTW, ReadStoreData, ReadMemBase]>;
641 // ADDI isn't always rematerializable, but isReMaterializable will be used as
642 // a hint which is verified in isReallyTriviallyReMaterializable.
643 let isReMaterializable = 1, isAsCheapAsAMove = 1 in
644 def ADDI : ALU_ri<0b000, "addi">;
646 let IsSignExtendingOpW = 1 in {
647 def SLTI : ALU_ri<0b010, "slti">;
648 def SLTIU : ALU_ri<0b011, "sltiu">;
651 let isReMaterializable = 1, isAsCheapAsAMove = 1 in {
652 def XORI : ALU_ri<0b100, "xori">;
653 def ORI : ALU_ri<0b110, "ori">;
656 def ANDI : ALU_ri<0b111, "andi">;
658 def SLLI : Shift_ri<0b00000, 0b001, "slli">;
659 def SRLI : Shift_ri<0b00000, 0b101, "srli">;
660 def SRAI : Shift_ri<0b01000, 0b101, "srai">;
662 def ADD : ALU_rr<0b0000000, 0b000, "add", Commutable=1>,
663 Sched<[WriteIALU, ReadIALU, ReadIALU]>;
664 def SUB : ALU_rr<0b0100000, 0b000, "sub">,
665 Sched<[WriteIALU, ReadIALU, ReadIALU]>;
666 def SLL : ALU_rr<0b0000000, 0b001, "sll">,
667 Sched<[WriteShiftReg, ReadShiftReg, ReadShiftReg]>;
668 let IsSignExtendingOpW = 1 in {
669 def SLT : ALU_rr<0b0000000, 0b010, "slt">,
670 Sched<[WriteIALU, ReadIALU, ReadIALU]>;
671 def SLTU : ALU_rr<0b0000000, 0b011, "sltu">,
672 Sched<[WriteIALU, ReadIALU, ReadIALU]>;
674 def XOR : ALU_rr<0b0000000, 0b100, "xor", Commutable=1>,
675 Sched<[WriteIALU, ReadIALU, ReadIALU]>;
676 def SRL : ALU_rr<0b0000000, 0b101, "srl">,
677 Sched<[WriteShiftReg, ReadShiftReg, ReadShiftReg]>;
678 def SRA : ALU_rr<0b0100000, 0b101, "sra">,
679 Sched<[WriteShiftReg, ReadShiftReg, ReadShiftReg]>;
680 def OR : ALU_rr<0b0000000, 0b110, "or", Commutable=1>,
681 Sched<[WriteIALU, ReadIALU, ReadIALU]>;
682 def AND : ALU_rr<0b0000000, 0b111, "and", Commutable=1>,
683 Sched<[WriteIALU, ReadIALU, ReadIALU]>;
685 let hasSideEffects = 1, mayLoad = 0, mayStore = 0 in {
686 def FENCE : RVInstI<0b000, OPC_MISC_MEM, (outs),
687 (ins fencearg:$pred, fencearg:$succ),
688 "fence", "$pred, $succ">, Sched<[]> {
694 let imm12 = {0b0000,pred,succ};
697 def FENCE_TSO : RVInstI<0b000, OPC_MISC_MEM, (outs), (ins), "fence.tso", "">, Sched<[]> {
700 let imm12 = {0b1000,0b0011,0b0011};
703 def FENCE_I : RVInstI<0b001, OPC_MISC_MEM, (outs), (ins), "fence.i", "">, Sched<[]> {
709 def ECALL : RVInstI<0b000, OPC_SYSTEM, (outs), (ins), "ecall", "">, Sched<[WriteJmp]> {
715 def EBREAK : RVInstI<0b000, OPC_SYSTEM, (outs), (ins), "ebreak", "">,
722 // This is a de facto standard (as set by GNU binutils) 32-bit unimplemented
723 // instruction (i.e., it should always trap, if your implementation has invalid
724 // instruction traps).
725 def UNIMP : RVInstI<0b001, OPC_SYSTEM, (outs), (ins), "unimp", "">,
729 let imm12 = 0b110000000000;
732 let Predicates = [HasStdExtZawrs] in {
733 def WRS_NTO : RVInstI<0b000, OPC_SYSTEM, (outs), (ins), "wrs.nto", "">,
737 let imm12 = 0b000000001101;
740 def WRS_STO : RVInstI<0b000, OPC_SYSTEM, (outs), (ins), "wrs.sto", "">,
744 let imm12 = 0b000000011101;
746 } // Predicates = [HasStdExtZawrs]
748 } // hasSideEffects = 1, mayLoad = 0, mayStore = 0
750 def CSRRW : CSR_ir<0b001, "csrrw">;
751 def CSRRS : CSR_ir<0b010, "csrrs">;
752 def CSRRC : CSR_ir<0b011, "csrrc">;
754 def CSRRWI : CSR_ii<0b101, "csrrwi">;
755 def CSRRSI : CSR_ii<0b110, "csrrsi">;
756 def CSRRCI : CSR_ii<0b111, "csrrci">;
758 /// RV64I instructions
760 let Predicates = [IsRV64] in {
761 def LWU : Load_ri<0b110, "lwu">, Sched<[WriteLDW, ReadMemBase]>;
762 def LD : Load_ri<0b011, "ld">, Sched<[WriteLDD, ReadMemBase]>;
763 def SD : Store_rri<0b011, "sd">, Sched<[WriteSTD, ReadStoreData, ReadMemBase]>;
765 let IsSignExtendingOpW = 1 in {
766 let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
767 def ADDIW : RVInstI<0b000, OPC_OP_IMM_32, (outs GPR:$rd),
768 (ins GPR:$rs1, simm12:$imm12),
769 "addiw", "$rd, $rs1, $imm12">,
770 Sched<[WriteIALU32, ReadIALU32]>;
772 def SLLIW : ShiftW_ri<0b0000000, 0b001, "slliw">;
773 def SRLIW : ShiftW_ri<0b0000000, 0b101, "srliw">;
774 def SRAIW : ShiftW_ri<0b0100000, 0b101, "sraiw">;
776 def ADDW : ALUW_rr<0b0000000, 0b000, "addw", Commutable=1>,
777 Sched<[WriteIALU32, ReadIALU32, ReadIALU32]>;
778 def SUBW : ALUW_rr<0b0100000, 0b000, "subw">,
779 Sched<[WriteIALU32, ReadIALU32, ReadIALU32]>;
780 def SLLW : ALUW_rr<0b0000000, 0b001, "sllw">,
781 Sched<[WriteShiftReg32, ReadShiftReg32, ReadShiftReg32]>;
782 def SRLW : ALUW_rr<0b0000000, 0b101, "srlw">,
783 Sched<[WriteShiftReg32, ReadShiftReg32, ReadShiftReg32]>;
784 def SRAW : ALUW_rr<0b0100000, 0b101, "sraw">,
785 Sched<[WriteShiftReg32, ReadShiftReg32, ReadShiftReg32]>;
786 } // IsSignExtendingOpW = 1
787 } // Predicates = [IsRV64]
789 //===----------------------------------------------------------------------===//
790 // Privileged instructions
791 //===----------------------------------------------------------------------===//
793 let isBarrier = 1, isReturn = 1, isTerminator = 1 in {
794 def SRET : Priv<"sret", 0b0001000>, Sched<[]> {
800 def MRET : Priv<"mret", 0b0011000>, Sched<[]> {
805 } // isBarrier = 1, isReturn = 1, isTerminator = 1
807 def WFI : Priv<"wfi", 0b0001000>, Sched<[]> {
813 let Predicates = [HasStdExtSvinval] in {
814 def SFENCE_W_INVAL : Priv<"sfence.w.inval", 0b0001100>, Sched<[]> {
820 def SFENCE_INVAL_IR : Priv<"sfence.inval.ir", 0b0001100>, Sched<[]> {
825 def SINVAL_VMA : Priv_rr<"sinval.vma", 0b0001011>, Sched<[]>;
826 def HINVAL_VVMA : Priv_rr<"hinval.vvma", 0b0010011>, Sched<[]>;
827 def HINVAL_GVMA : Priv_rr<"hinval.gvma", 0b0110011>, Sched<[]>;
828 } // Predicates = [HasStdExtSvinval]
830 def SFENCE_VMA : Priv_rr<"sfence.vma", 0b0001001>, Sched<[]>;
832 let Predicates = [HasStdExtH] in {
833 def HFENCE_VVMA : Priv_rr<"hfence.vvma", 0b0010001>, Sched<[]>;
834 def HFENCE_GVMA : Priv_rr<"hfence.gvma", 0b0110001>, Sched<[]>;
836 def HLV_B : HLoad_r<0b0110000, 0b00000, "hlv.b">, Sched<[]>;
837 def HLV_BU : HLoad_r<0b0110000, 0b00001, "hlv.bu">, Sched<[]>;
838 def HLV_H : HLoad_r<0b0110010, 0b00000, "hlv.h">, Sched<[]>;
839 def HLV_HU : HLoad_r<0b0110010, 0b00001, "hlv.hu">, Sched<[]>;
840 def HLVX_HU : HLoad_r<0b0110010, 0b00011, "hlvx.hu">, Sched<[]>;
841 def HLV_W : HLoad_r<0b0110100, 0b00000, "hlv.w">, Sched<[]>;
842 def HLVX_WU : HLoad_r<0b0110100, 0b00011, "hlvx.wu">, Sched<[]>;
843 def HSV_B : HStore_rr<0b0110001, "hsv.b">, Sched<[]>;
844 def HSV_H : HStore_rr<0b0110011, "hsv.h">, Sched<[]>;
845 def HSV_W : HStore_rr<0b0110101, "hsv.w">, Sched<[]>;
847 let Predicates = [IsRV64, HasStdExtH] in {
848 def HLV_WU : HLoad_r<0b0110100, 0b00001, "hlv.wu">, Sched<[]>;
849 def HLV_D : HLoad_r<0b0110110, 0b00000, "hlv.d">, Sched<[]>;
850 def HSV_D : HStore_rr<0b0110111, "hsv.d">, Sched<[]>;
853 //===----------------------------------------------------------------------===//
854 // Debug instructions
855 //===----------------------------------------------------------------------===//
857 let isBarrier = 1, isReturn = 1, isTerminator = 1 in {
858 def DRET : Priv<"dret", 0b0111101>, Sched<[]> {
863 } // isBarrier = 1, isReturn = 1, isTerminator = 1
865 //===----------------------------------------------------------------------===//
866 // Assembler Pseudo Instructions (User-Level ISA, Version 2.2, Chapter 20)
867 //===----------------------------------------------------------------------===//
869 def : InstAlias<"nop", (ADDI X0, X0, 0)>;
871 // Note that the size is 32 because up to 8 32-bit instructions are needed to
872 // generate an arbitrary 64-bit immediate. However, the size does not really
873 // matter since PseudoLI is currently only used in the AsmParser where it gets
874 // expanded to real instructions immediately.
875 let hasSideEffects = 0, mayLoad = 0, mayStore = 0, Size = 32,
876 isCodeGenOnly = 0, isAsmParserOnly = 1 in
877 def PseudoLI : Pseudo<(outs GPR:$rd), (ins ixlenimm_li:$imm), [],
880 def PseudoLB : PseudoLoad<"lb">;
881 def PseudoLBU : PseudoLoad<"lbu">;
882 def PseudoLH : PseudoLoad<"lh">;
883 def PseudoLHU : PseudoLoad<"lhu">;
884 def PseudoLW : PseudoLoad<"lw">;
886 def PseudoSB : PseudoStore<"sb">;
887 def PseudoSH : PseudoStore<"sh">;
888 def PseudoSW : PseudoStore<"sw">;
890 let Predicates = [IsRV64] in {
891 def PseudoLWU : PseudoLoad<"lwu">;
892 def PseudoLD : PseudoLoad<"ld">;
893 def PseudoSD : PseudoStore<"sd">;
894 } // Predicates = [IsRV64]
896 def : InstAlias<"li $rd, $imm", (ADDI GPR:$rd, X0, simm12:$imm)>;
897 def : InstAlias<"mv $rd, $rs", (ADDI GPR:$rd, GPR:$rs, 0)>;
898 def : InstAlias<"not $rd, $rs", (XORI GPR:$rd, GPR:$rs, -1)>;
899 def : InstAlias<"neg $rd, $rs", (SUB GPR:$rd, X0, GPR:$rs)>;
901 let Predicates = [IsRV64] in {
902 def : InstAlias<"negw $rd, $rs", (SUBW GPR:$rd, X0, GPR:$rs)>;
903 def : InstAlias<"sext.w $rd, $rs", (ADDIW GPR:$rd, GPR:$rs, 0)>;
904 } // Predicates = [IsRV64]
906 def : InstAlias<"seqz $rd, $rs", (SLTIU GPR:$rd, GPR:$rs, 1)>;
907 def : InstAlias<"snez $rd, $rs", (SLTU GPR:$rd, X0, GPR:$rs)>;
908 def : InstAlias<"sltz $rd, $rs", (SLT GPR:$rd, GPR:$rs, X0)>;
909 def : InstAlias<"sgtz $rd, $rs", (SLT GPR:$rd, X0, GPR:$rs)>;
911 // sgt/sgtu are recognised by the GNU assembler but the canonical slt/sltu
912 // form will always be printed. Therefore, set a zero weight.
913 def : InstAlias<"sgt $rd, $rs, $rt", (SLT GPR:$rd, GPR:$rt, GPR:$rs), 0>;
914 def : InstAlias<"sgtu $rd, $rs, $rt", (SLTU GPR:$rd, GPR:$rt, GPR:$rs), 0>;
916 def : InstAlias<"beqz $rs, $offset",
917 (BEQ GPR:$rs, X0, simm13_lsb0:$offset)>;
918 def : InstAlias<"bnez $rs, $offset",
919 (BNE GPR:$rs, X0, simm13_lsb0:$offset)>;
920 def : InstAlias<"blez $rs, $offset",
921 (BGE X0, GPR:$rs, simm13_lsb0:$offset)>;
922 def : InstAlias<"bgez $rs, $offset",
923 (BGE GPR:$rs, X0, simm13_lsb0:$offset)>;
924 def : InstAlias<"bltz $rs, $offset",
925 (BLT GPR:$rs, X0, simm13_lsb0:$offset)>;
926 def : InstAlias<"bgtz $rs, $offset",
927 (BLT X0, GPR:$rs, simm13_lsb0:$offset)>;
929 // Always output the canonical mnemonic for the pseudo branch instructions.
930 // The GNU tools emit the canonical mnemonic for the branch pseudo instructions
931 // as well (e.g. "bgt" will be recognised by the assembler but never printed by
932 // objdump). Match this behaviour by setting a zero weight.
933 def : InstAlias<"bgt $rs, $rt, $offset",
934 (BLT GPR:$rt, GPR:$rs, simm13_lsb0:$offset), 0>;
935 def : InstAlias<"ble $rs, $rt, $offset",
936 (BGE GPR:$rt, GPR:$rs, simm13_lsb0:$offset), 0>;
937 def : InstAlias<"bgtu $rs, $rt, $offset",
938 (BLTU GPR:$rt, GPR:$rs, simm13_lsb0:$offset), 0>;
939 def : InstAlias<"bleu $rs, $rt, $offset",
940 (BGEU GPR:$rt, GPR:$rs, simm13_lsb0:$offset), 0>;
942 def : InstAlias<"j $offset", (JAL X0, simm21_lsb0_jal:$offset)>;
943 def : InstAlias<"jal $offset", (JAL X1, simm21_lsb0_jal:$offset)>;
945 // Non-zero offset aliases of "jalr" are the lowest weight, followed by the
946 // two-register form, then the one-register forms and finally "ret".
947 def : InstAlias<"jr $rs", (JALR X0, GPR:$rs, 0), 3>;
948 def : InstAlias<"jr ${offset}(${rs})", (JALR X0, GPR:$rs, simm12:$offset)>;
949 def : InstAlias<"jalr $rs", (JALR X1, GPR:$rs, 0), 3>;
950 def : InstAlias<"jalr ${offset}(${rs})", (JALR X1, GPR:$rs, simm12:$offset)>;
951 def : InstAlias<"jalr $rd, $rs", (JALR GPR:$rd, GPR:$rs, 0), 2>;
952 def : InstAlias<"ret", (JALR X0, X1, 0), 4>;
954 // Non-canonical forms for jump targets also accepted by the assembler.
955 def : InstAlias<"jr $rs, $offset", (JALR X0, GPR:$rs, simm12:$offset), 0>;
956 def : InstAlias<"jalr $rs, $offset", (JALR X1, GPR:$rs, simm12:$offset), 0>;
957 def : InstAlias<"jalr $rd, $rs, $offset", (JALR GPR:$rd, GPR:$rs, simm12:$offset), 0>;
959 def : InstAlias<"fence", (FENCE 0xF, 0xF)>; // 0xF == iorw
961 let Predicates = [HasStdExtZihintpause] in
962 def : InstAlias<"pause", (FENCE 0x1, 0x0)>; // 0x1 == w
964 def : InstAlias<"rdinstret $rd", (CSRRS GPR:$rd, INSTRET.Encoding, X0)>;
965 def : InstAlias<"rdcycle $rd", (CSRRS GPR:$rd, CYCLE.Encoding, X0)>;
966 def : InstAlias<"rdtime $rd", (CSRRS GPR:$rd, TIME.Encoding, X0)>;
968 let Predicates = [IsRV32] in {
969 def : InstAlias<"rdinstreth $rd", (CSRRS GPR:$rd, INSTRETH.Encoding, X0)>;
970 def : InstAlias<"rdcycleh $rd", (CSRRS GPR:$rd, CYCLEH.Encoding, X0)>;
971 def : InstAlias<"rdtimeh $rd", (CSRRS GPR:$rd, TIMEH.Encoding, X0)>;
972 } // Predicates = [IsRV32]
974 def : InstAlias<"csrr $rd, $csr", (CSRRS GPR:$rd, csr_sysreg:$csr, X0)>;
975 def : InstAlias<"csrw $csr, $rs", (CSRRW X0, csr_sysreg:$csr, GPR:$rs)>;
976 def : InstAlias<"csrs $csr, $rs", (CSRRS X0, csr_sysreg:$csr, GPR:$rs)>;
977 def : InstAlias<"csrc $csr, $rs", (CSRRC X0, csr_sysreg:$csr, GPR:$rs)>;
979 def : InstAlias<"csrwi $csr, $imm", (CSRRWI X0, csr_sysreg:$csr, uimm5:$imm)>;
980 def : InstAlias<"csrsi $csr, $imm", (CSRRSI X0, csr_sysreg:$csr, uimm5:$imm)>;
981 def : InstAlias<"csrci $csr, $imm", (CSRRCI X0, csr_sysreg:$csr, uimm5:$imm)>;
983 let EmitPriority = 0 in {
984 def : InstAlias<"csrw $csr, $imm", (CSRRWI X0, csr_sysreg:$csr, uimm5:$imm)>;
985 def : InstAlias<"csrs $csr, $imm", (CSRRSI X0, csr_sysreg:$csr, uimm5:$imm)>;
986 def : InstAlias<"csrc $csr, $imm", (CSRRCI X0, csr_sysreg:$csr, uimm5:$imm)>;
988 def : InstAlias<"csrrw $rd, $csr, $imm", (CSRRWI GPR:$rd, csr_sysreg:$csr, uimm5:$imm)>;
989 def : InstAlias<"csrrs $rd, $csr, $imm", (CSRRSI GPR:$rd, csr_sysreg:$csr, uimm5:$imm)>;
990 def : InstAlias<"csrrc $rd, $csr, $imm", (CSRRCI GPR:$rd, csr_sysreg:$csr, uimm5:$imm)>;
993 def : InstAlias<"sfence.vma", (SFENCE_VMA X0, X0)>;
994 def : InstAlias<"sfence.vma $rs", (SFENCE_VMA GPR:$rs, X0)>;
996 def : InstAlias<"hfence.gvma", (HFENCE_GVMA X0, X0)>;
997 def : InstAlias<"hfence.gvma $rs", (HFENCE_GVMA GPR:$rs, X0)>;
999 def : InstAlias<"hfence.vvma", (HFENCE_VVMA X0, X0)>;
1000 def : InstAlias<"hfence.vvma $rs", (HFENCE_VVMA GPR:$rs, X0)>;
1002 let Predicates = [HasStdExtZihintntl] in {
1003 def : InstAlias<"ntl.p1", (ADD X0, X0, X2)>;
1004 def : InstAlias<"ntl.pall", (ADD X0, X0, X3)>;
1005 def : InstAlias<"ntl.s1", (ADD X0, X0, X4)>;
1006 def : InstAlias<"ntl.all", (ADD X0, X0, X5)>;
1007 } // Predicates = [HasStdExtZihintntl]
1009 let EmitPriority = 0 in {
1010 def : InstAlias<"lb $rd, (${rs1})",
1011 (LB GPR:$rd, GPR:$rs1, 0)>;
1012 def : InstAlias<"lh $rd, (${rs1})",
1013 (LH GPR:$rd, GPR:$rs1, 0)>;
1014 def : InstAlias<"lw $rd, (${rs1})",
1015 (LW GPR:$rd, GPR:$rs1, 0)>;
1016 def : InstAlias<"lbu $rd, (${rs1})",
1017 (LBU GPR:$rd, GPR:$rs1, 0)>;
1018 def : InstAlias<"lhu $rd, (${rs1})",
1019 (LHU GPR:$rd, GPR:$rs1, 0)>;
1021 def : InstAlias<"sb $rs2, (${rs1})",
1022 (SB GPR:$rs2, GPR:$rs1, 0)>;
1023 def : InstAlias<"sh $rs2, (${rs1})",
1024 (SH GPR:$rs2, GPR:$rs1, 0)>;
1025 def : InstAlias<"sw $rs2, (${rs1})",
1026 (SW GPR:$rs2, GPR:$rs1, 0)>;
1028 def : InstAlias<"add $rd, $rs1, $imm12",
1029 (ADDI GPR:$rd, GPR:$rs1, simm12:$imm12)>;
1030 def : InstAlias<"and $rd, $rs1, $imm12",
1031 (ANDI GPR:$rd, GPR:$rs1, simm12:$imm12)>;
1032 def : InstAlias<"xor $rd, $rs1, $imm12",
1033 (XORI GPR:$rd, GPR:$rs1, simm12:$imm12)>;
1034 def : InstAlias<"or $rd, $rs1, $imm12",
1035 (ORI GPR:$rd, GPR:$rs1, simm12:$imm12)>;
1036 def : InstAlias<"sll $rd, $rs1, $shamt",
1037 (SLLI GPR:$rd, GPR:$rs1, uimmlog2xlen:$shamt)>;
1038 def : InstAlias<"srl $rd, $rs1, $shamt",
1039 (SRLI GPR:$rd, GPR:$rs1, uimmlog2xlen:$shamt)>;
1040 def : InstAlias<"sra $rd, $rs1, $shamt",
1041 (SRAI GPR:$rd, GPR:$rs1, uimmlog2xlen:$shamt)>;
1042 let Predicates = [IsRV64] in {
1043 def : InstAlias<"lwu $rd, (${rs1})",
1044 (LWU GPR:$rd, GPR:$rs1, 0)>;
1045 def : InstAlias<"ld $rd, (${rs1})",
1046 (LD GPR:$rd, GPR:$rs1, 0)>;
1047 def : InstAlias<"sd $rs2, (${rs1})",
1048 (SD GPR:$rs2, GPR:$rs1, 0)>;
1050 def : InstAlias<"addw $rd, $rs1, $imm12",
1051 (ADDIW GPR:$rd, GPR:$rs1, simm12:$imm12)>;
1052 def : InstAlias<"sllw $rd, $rs1, $shamt",
1053 (SLLIW GPR:$rd, GPR:$rs1, uimm5:$shamt)>;
1054 def : InstAlias<"srlw $rd, $rs1, $shamt",
1055 (SRLIW GPR:$rd, GPR:$rs1, uimm5:$shamt)>;
1056 def : InstAlias<"sraw $rd, $rs1, $shamt",
1057 (SRAIW GPR:$rd, GPR:$rs1, uimm5:$shamt)>;
1058 } // Predicates = [IsRV64]
1059 def : InstAlias<"slt $rd, $rs1, $imm12",
1060 (SLTI GPR:$rd, GPR:$rs1, simm12:$imm12)>;
1061 def : InstAlias<"sltu $rd, $rs1, $imm12",
1062 (SLTIU GPR:$rd, GPR:$rs1, simm12:$imm12)>;
1065 def : MnemonicAlias<"move", "mv">;
1067 // The SCALL and SBREAK instructions wererenamed to ECALL and EBREAK in
1068 // version 2.1 of the user-level ISA. Like the GNU toolchain, we still accept
1069 // the old name for backwards compatibility.
1070 def : MnemonicAlias<"scall", "ecall">;
1071 def : MnemonicAlias<"sbreak", "ebreak">;
1073 // This alias was added to the spec in December 2020. Don't print it by default
1074 // to allow assembly we print to be compatible with versions of GNU assembler
1075 // that don't support this alias.
1076 def : InstAlias<"zext.b $rd, $rs", (ANDI GPR:$rd, GPR:$rs, 0xFF), 0>;
1078 let Predicates = [HasStdExtZicfilp] in {
1079 def : InstAlias<"lpad $imm20", (AUIPC X0, uimm20:$imm20)>;
1082 //===----------------------------------------------------------------------===//
1083 // .insn directive instructions
1084 //===----------------------------------------------------------------------===//
1086 def AnyRegOperand : AsmOperandClass {
1087 let Name = "AnyRegOperand";
1088 let RenderMethod = "addRegOperands";
1089 let PredicateMethod = "isAnyReg";
1092 def AnyReg : Operand<XLenVT> {
1093 let OperandType = "OPERAND_REGISTER";
1094 let ParserMatchClass = AnyRegOperand;
1097 // isCodeGenOnly = 1 to hide them from the tablegened assembly parser.
1098 let isCodeGenOnly = 1, hasSideEffects = 1, mayLoad = 1, mayStore = 1,
1099 hasNoSchedulingInfo = 1 in {
1100 def InsnR : DirectiveInsnR<(outs AnyReg:$rd), (ins uimm7_opcode:$opcode, uimm3:$funct3,
1101 uimm7:$funct7, AnyReg:$rs1,
1103 "$opcode, $funct3, $funct7, $rd, $rs1, $rs2">;
1104 def InsnR4 : DirectiveInsnR4<(outs AnyReg:$rd), (ins uimm7_opcode:$opcode,
1107 AnyReg:$rs1, AnyReg:$rs2,
1109 "$opcode, $funct3, $funct2, $rd, $rs1, $rs2, $rs3">;
1110 def InsnI : DirectiveInsnI<(outs AnyReg:$rd), (ins uimm7_opcode:$opcode, uimm3:$funct3,
1111 AnyReg:$rs1, simm12:$imm12),
1112 "$opcode, $funct3, $rd, $rs1, $imm12">;
1113 def InsnI_Mem : DirectiveInsnI<(outs AnyReg:$rd), (ins uimm7_opcode:$opcode,
1117 "$opcode, $funct3, $rd, ${imm12}(${rs1})">;
1118 def InsnB : DirectiveInsnB<(outs), (ins uimm7_opcode:$opcode, uimm3:$funct3,
1119 AnyReg:$rs1, AnyReg:$rs2,
1120 simm13_lsb0:$imm12),
1121 "$opcode, $funct3, $rs1, $rs2, $imm12">;
1122 def InsnU : DirectiveInsnU<(outs AnyReg:$rd), (ins uimm7_opcode:$opcode,
1124 "$opcode, $rd, $imm20">;
1125 def InsnJ : DirectiveInsnJ<(outs AnyReg:$rd), (ins uimm7_opcode:$opcode,
1126 simm21_lsb0_jal:$imm20),
1127 "$opcode, $rd, $imm20">;
1128 def InsnS : DirectiveInsnS<(outs), (ins uimm7_opcode:$opcode, uimm3:$funct3,
1129 AnyReg:$rs2, AnyReg:$rs1,
1131 "$opcode, $funct3, $rs2, ${imm12}(${rs1})">;
1134 // Use InstAliases to match these so that we can combine the insn and format
1135 // into a mnemonic to use as the key for the tablegened asm matcher table. The
1136 // parser will take care of creating these fake mnemonics and will only do it
1137 // for known formats.
1138 let EmitPriority = 0 in {
1139 def : InstAlias<".insn_r $opcode, $funct3, $funct7, $rd, $rs1, $rs2",
1140 (InsnR AnyReg:$rd, uimm7_opcode:$opcode, uimm3:$funct3, uimm7:$funct7,
1141 AnyReg:$rs1, AnyReg:$rs2)>;
1142 // Accept 4 register form of ".insn r" as alias for ".insn r4".
1143 def : InstAlias<".insn_r $opcode, $funct3, $funct2, $rd, $rs1, $rs2, $rs3",
1144 (InsnR4 AnyReg:$rd, uimm7_opcode:$opcode, uimm3:$funct3, uimm2:$funct2,
1145 AnyReg:$rs1, AnyReg:$rs2, AnyReg:$rs3)>;
1146 def : InstAlias<".insn_r4 $opcode, $funct3, $funct2, $rd, $rs1, $rs2, $rs3",
1147 (InsnR4 AnyReg:$rd, uimm7_opcode:$opcode, uimm3:$funct3, uimm2:$funct2,
1148 AnyReg:$rs1, AnyReg:$rs2, AnyReg:$rs3)>;
1149 def : InstAlias<".insn_i $opcode, $funct3, $rd, $rs1, $imm12",
1150 (InsnI AnyReg:$rd, uimm7_opcode:$opcode, uimm3:$funct3, AnyReg:$rs1,
1152 def : InstAlias<".insn_i $opcode, $funct3, $rd, ${imm12}(${rs1})",
1153 (InsnI_Mem AnyReg:$rd, uimm7_opcode:$opcode, uimm3:$funct3,
1154 AnyReg:$rs1, simm12:$imm12)>;
1155 def : InstAlias<".insn_b $opcode, $funct3, $rs1, $rs2, $imm12",
1156 (InsnB uimm7_opcode:$opcode, uimm3:$funct3, AnyReg:$rs1,
1157 AnyReg:$rs2, simm13_lsb0:$imm12)>;
1158 // Accept sb as an alias for b.
1159 def : InstAlias<".insn_sb $opcode, $funct3, $rs1, $rs2, $imm12",
1160 (InsnB uimm7_opcode:$opcode, uimm3:$funct3, AnyReg:$rs1,
1161 AnyReg:$rs2, simm13_lsb0:$imm12)>;
1162 def : InstAlias<".insn_u $opcode, $rd, $imm20",
1163 (InsnU AnyReg:$rd, uimm7_opcode:$opcode, uimm20_lui:$imm20)>;
1164 def : InstAlias<".insn_j $opcode, $rd, $imm20",
1165 (InsnJ AnyReg:$rd, uimm7_opcode:$opcode, simm21_lsb0_jal:$imm20)>;
1166 // Accept uj as an alias for j.
1167 def : InstAlias<".insn_uj $opcode, $rd, $imm20",
1168 (InsnJ AnyReg:$rd, uimm7_opcode:$opcode, simm21_lsb0_jal:$imm20)>;
1169 def : InstAlias<".insn_s $opcode, $funct3, $rs2, ${imm12}(${rs1})",
1170 (InsnS uimm7_opcode:$opcode, uimm3:$funct3, AnyReg:$rs2,
1171 AnyReg:$rs1, simm12:$imm12)>;
1174 //===----------------------------------------------------------------------===//
1175 // Pseudo-instructions and codegen patterns
1177 // Naming convention: For 'generic' pattern classes, we use the naming
1178 // convention PatTy1Ty2. For pattern classes which offer a more complex
1179 // expansion, prefix the class name, e.g. BccPat.
1180 //===----------------------------------------------------------------------===//
1182 /// Generic pattern classes
1184 class PatGpr<SDPatternOperator OpNode, RVInst Inst, ValueType vt = XLenVT>
1185 : Pat<(vt (OpNode (vt GPR:$rs1))), (Inst GPR:$rs1)>;
1186 class PatGprGpr<SDPatternOperator OpNode, RVInst Inst, ValueType vt1 = XLenVT,
1187 ValueType vt2 = XLenVT>
1188 : Pat<(vt1 (OpNode (vt1 GPR:$rs1), (vt2 GPR:$rs2))), (Inst GPR:$rs1, GPR:$rs2)>;
1190 class PatGprImm<SDPatternOperator OpNode, RVInst Inst, ImmLeaf ImmType,
1191 ValueType vt = XLenVT>
1192 : Pat<(vt (OpNode (vt GPR:$rs1), ImmType:$imm)),
1193 (Inst GPR:$rs1, ImmType:$imm)>;
1194 class PatGprSimm12<SDPatternOperator OpNode, RVInstI Inst>
1195 : PatGprImm<OpNode, Inst, simm12>;
1196 class PatGprUimmLog2XLen<SDPatternOperator OpNode, RVInstIShift Inst>
1197 : PatGprImm<OpNode, Inst, uimmlog2xlen>;
1201 def assertsexti32 : PatFrag<(ops node:$src), (assertsext node:$src), [{
1202 return cast<VTSDNode>(N->getOperand(1))->getVT().bitsLE(MVT::i32);
1204 def sexti16 : ComplexPattern<XLenVT, 1, "selectSExtBits<16>">;
1205 def sexti32 : ComplexPattern<i64, 1, "selectSExtBits<32>">;
1206 def assertzexti32 : PatFrag<(ops node:$src), (assertzext node:$src), [{
1207 return cast<VTSDNode>(N->getOperand(1))->getVT().bitsLE(MVT::i32);
1209 def zexti32 : ComplexPattern<i64, 1, "selectZExtBits<32>">;
1210 def zexti16 : ComplexPattern<XLenVT, 1, "selectZExtBits<16>">;
1211 def zexti16i32 : ComplexPattern<i32, 1, "selectZExtBits<16>">;
1212 def zexti8 : ComplexPattern<XLenVT, 1, "selectZExtBits<8>">;
1213 def zexti8i32 : ComplexPattern<i32, 1, "selectZExtBits<8>">;
1215 def ext : PatFrags<(ops node:$A), [(sext node:$A), (zext node:$A)]>;
1217 class binop_oneuse<SDPatternOperator operator>
1218 : PatFrag<(ops node:$A, node:$B),
1219 (operator node:$A, node:$B), [{
1220 return N->hasOneUse();
1223 def and_oneuse : binop_oneuse<and>;
1224 def mul_oneuse : binop_oneuse<mul>;
1226 def mul_const_oneuse : PatFrag<(ops node:$A, node:$B),
1227 (mul node:$A, node:$B), [{
1228 if (auto *N1C = dyn_cast<ConstantSDNode>(N->getOperand(1)))
1229 return N1C->hasOneUse();
1233 class unop_oneuse<SDPatternOperator operator>
1234 : PatFrag<(ops node:$A),
1235 (operator node:$A), [{
1236 return N->hasOneUse();
1239 def sext_oneuse : unop_oneuse<sext>;
1240 def zext_oneuse : unop_oneuse<zext>;
1241 def anyext_oneuse : unop_oneuse<anyext>;
1242 def ext_oneuse : unop_oneuse<ext>;
1243 def fpext_oneuse : unop_oneuse<any_fpextend>;
1245 def 33signbits_node : PatLeaf<(i64 GPR:$src), [{
1246 return CurDAG->ComputeNumSignBits(SDValue(N, 0)) > 32;
1249 /// Simple arithmetic operations
1251 def : PatGprGpr<add, ADD>;
1252 def : PatGprSimm12<add, ADDI>;
1253 def : PatGprGpr<sub, SUB>;
1254 def : PatGprGpr<or, OR>;
1255 def : PatGprSimm12<or, ORI>;
1256 def : PatGprGpr<and, AND>;
1257 def : PatGprSimm12<and, ANDI>;
1258 def : PatGprGpr<xor, XOR>;
1259 def : PatGprSimm12<xor, XORI>;
1260 def : PatGprUimmLog2XLen<shl, SLLI>;
1261 def : PatGprUimmLog2XLen<srl, SRLI>;
1262 def : PatGprUimmLog2XLen<sra, SRAI>;
1264 // Select 'or' as ADDI if the immediate bits are known to be 0 in $rs1. This
1265 // can improve compressibility.
1266 def or_is_add : PatFrag<(ops node:$lhs, node:$rhs), (or node:$lhs, node:$rhs),[{
1267 KnownBits Known0 = CurDAG->computeKnownBits(N->getOperand(0), 0);
1268 KnownBits Known1 = CurDAG->computeKnownBits(N->getOperand(1), 0);
1269 return KnownBits::haveNoCommonBitsSet(Known0, Known1);
1271 def : PatGprSimm12<or_is_add, ADDI>;
1273 // negate of low bit can be done via two (compressible) shifts. The negate
1274 // is never compressible since rs1 and rd can't be the same register.
1275 def : Pat<(XLenVT (sub 0, (and_oneuse GPR:$rs, 1))),
1276 (SRAI (SLLI $rs, (ImmSubFromXLen (XLenVT 1))),
1277 (ImmSubFromXLen (XLenVT 1)))>;
1279 // AND with leading/trailing ones mask exceeding simm32/simm12.
1280 def : Pat<(i64 (and GPR:$rs, LeadingOnesMask:$mask)),
1281 (SLLI (SRLI $rs, LeadingOnesMask:$mask), LeadingOnesMask:$mask)>;
1282 def : Pat<(XLenVT (and GPR:$rs, TrailingOnesMask:$mask)),
1283 (SRLI (SLLI $rs, TrailingOnesMask:$mask), TrailingOnesMask:$mask)>;
1285 // Match both a plain shift and one where the shift amount is masked (this is
1286 // typically introduced when the legalizer promotes the shift amount and
1287 // zero-extends it). For RISC-V, the mask is unnecessary as shifts in the base
1288 // ISA only read the least significant 5 bits (RV32I) or 6 bits (RV64I).
1289 def shiftMaskXLen : ComplexPattern<XLenVT, 1, "selectShiftMaskXLen", [], [], 0>;
1290 def shiftMask32 : ComplexPattern<i64, 1, "selectShiftMask32", [], [], 0>;
1292 class shiftop<SDPatternOperator operator>
1293 : PatFrag<(ops node:$val, node:$count),
1294 (operator node:$val, (XLenVT (shiftMaskXLen node:$count)))>;
1295 class shiftopw<SDPatternOperator operator>
1296 : PatFrag<(ops node:$val, node:$count),
1297 (operator node:$val, (i64 (shiftMask32 node:$count)))>;
1299 def : PatGprGpr<shiftop<shl>, SLL>;
1300 def : PatGprGpr<shiftop<srl>, SRL>;
1301 def : PatGprGpr<shiftop<sra>, SRA>;
1303 // This is a special case of the ADD instruction used to facilitate the use of a
1304 // fourth operand to emit a relocation on a symbol relating to this instruction.
1305 // The relocation does not affect any bits of the instruction itself but is used
1306 // as a hint to the linker.
1307 let hasSideEffects = 0, mayLoad = 0, mayStore = 0, isCodeGenOnly = 0 in
1308 def PseudoAddTPRel : Pseudo<(outs GPR:$rd),
1309 (ins GPR:$rs1, GPR:$rs2, tprel_add_symbol:$src), [],
1310 "add", "$rd, $rs1, $rs2, $src">;
1312 /// FrameIndex calculations
1314 def : Pat<(FrameAddrRegImm (iPTR GPR:$rs1), simm12:$imm12),
1315 (ADDI GPR:$rs1, simm12:$imm12)>;
1317 /// HI and ADD_LO address nodes.
1319 def : Pat<(riscv_hi tglobaladdr:$in), (LUI tglobaladdr:$in)>;
1320 def : Pat<(riscv_hi tblockaddress:$in), (LUI tblockaddress:$in)>;
1321 def : Pat<(riscv_hi tjumptable:$in), (LUI tjumptable:$in)>;
1322 def : Pat<(riscv_hi tconstpool:$in), (LUI tconstpool:$in)>;
1324 def : Pat<(riscv_add_lo GPR:$hi, tglobaladdr:$lo),
1325 (ADDI GPR:$hi, tglobaladdr:$lo)>;
1326 def : Pat<(riscv_add_lo GPR:$hi, tblockaddress:$lo),
1327 (ADDI GPR:$hi, tblockaddress:$lo)>;
1328 def : Pat<(riscv_add_lo GPR:$hi, tjumptable:$lo),
1329 (ADDI GPR:$hi, tjumptable:$lo)>;
1330 def : Pat<(riscv_add_lo GPR:$hi, tconstpool:$lo),
1331 (ADDI GPR:$hi, tconstpool:$lo)>;
1333 /// TLS address nodes.
1335 def : Pat<(riscv_hi tglobaltlsaddr:$in), (LUI tglobaltlsaddr:$in)>;
1336 def : Pat<(riscv_add_tprel GPR:$rs1, GPR:$rs2, tglobaltlsaddr:$src),
1337 (PseudoAddTPRel GPR:$rs1, GPR:$rs2, tglobaltlsaddr:$src)>;
1338 def : Pat<(riscv_add_lo GPR:$src, tglobaltlsaddr:$lo),
1339 (ADDI GPR:$src, tglobaltlsaddr:$lo)>;
1343 def : PatGprGpr<setlt, SLT>;
1344 def : PatGprSimm12<setlt, SLTI>;
1345 def : PatGprGpr<setult, SLTU>;
1346 def : PatGprSimm12<setult, SLTIU>;
1348 // RISC-V doesn't have general instructions for integer setne/seteq, but we can
1349 // check for equality with 0. These ComplexPatterns rewrite the setne/seteq into
1350 // something that can be compared with 0.
1351 // These ComplexPatterns must be used in pairs.
1352 def riscv_setne : ComplexPattern<XLenVT, 1, "selectSETNE", [setcc]>;
1353 def riscv_seteq : ComplexPattern<XLenVT, 1, "selectSETEQ", [setcc]>;
1355 // Define pattern expansions for setcc operations that aren't directly
1356 // handled by a RISC-V instruction.
1357 def : Pat<(riscv_seteq (XLenVT GPR:$rs1)), (SLTIU GPR:$rs1, 1)>;
1358 def : Pat<(riscv_setne (XLenVT GPR:$rs1)), (SLTU (XLenVT X0), GPR:$rs1)>;
1359 def : Pat<(XLenVT (setne (XLenVT GPR:$rs1), -1)), (SLTIU GPR:$rs1, -1)>;
1361 def IntCCtoRISCVCC : SDNodeXForm<riscv_selectcc, [{
1362 ISD::CondCode CC = cast<CondCodeSDNode>(N->getOperand(2))->get();
1363 RISCVCC::CondCode BrCC = getRISCVCCForIntCC(CC);
1364 return CurDAG->getTargetConstant(BrCC, SDLoc(N), Subtarget->getXLenVT());
1367 def riscv_selectcc_frag : PatFrag<(ops node:$lhs, node:$rhs, node:$cc,
1368 node:$truev, node:$falsev),
1369 (riscv_selectcc node:$lhs, node:$rhs,
1370 node:$cc, node:$truev,
1371 node:$falsev), [{}],
1374 let Predicates = [HasShortForwardBranchOpt], isSelect = 1,
1375 Constraints = "$dst = $falsev", isCommutable = 1, Size = 8 in {
1376 // This instruction moves $truev to $dst when the condition is true. It will
1377 // be expanded to control flow in RISCVExpandPseudoInsts.
1378 def PseudoCCMOVGPR : Pseudo<(outs GPR:$dst),
1379 (ins GPR:$lhs, GPR:$rhs, ixlenimm:$cc,
1380 GPR:$falsev, GPR:$truev),
1382 (riscv_selectcc_frag:$cc (XLenVT GPR:$lhs),
1384 (XLenVT GPR:$truev),
1386 Sched<[WriteSFB, ReadSFBJmp, ReadSFBJmp,
1387 ReadSFBALU, ReadSFBALU]>;
1390 // Conditional binops, that updates update $dst to (op rs1, rs2) when condition
1391 // is true. Returns $falsev otherwise. Selected by optimizeSelect.
1392 // TODO: Can we use DefaultOperands on the regular binop to accomplish this more
1393 // like how ARM does predication?
1394 let hasSideEffects = 0, mayLoad = 0, mayStore = 0, Size = 8,
1395 Constraints = "$dst = $falsev" in {
1396 def PseudoCCADD : Pseudo<(outs GPR:$dst),
1397 (ins GPR:$lhs, GPR:$rhs, ixlenimm:$cc,
1398 GPR:$falsev, GPR:$rs1, GPR:$rs2), []>,
1399 Sched<[WriteSFB, ReadSFBJmp, ReadSFBJmp,
1400 ReadSFBALU, ReadSFBALU, ReadSFBALU]>;
1401 def PseudoCCSUB : Pseudo<(outs GPR:$dst),
1402 (ins GPR:$lhs, GPR:$rhs, ixlenimm:$cc,
1403 GPR:$falsev, GPR:$rs1, GPR:$rs2), []>,
1404 Sched<[WriteSFB, ReadSFBJmp, ReadSFBJmp,
1405 ReadSFBALU, ReadSFBALU, ReadSFBALU]>;
1406 def PseudoCCSLL : Pseudo<(outs GPR:$dst),
1407 (ins GPR:$lhs, GPR:$rhs, ixlenimm:$cc,
1408 GPR:$falsev, GPR:$rs1, GPR:$rs2), []>,
1409 Sched<[WriteSFB, ReadSFBJmp, ReadSFBJmp, ReadSFBALU,
1410 ReadSFBALU, ReadSFBALU]>;
1411 def PseudoCCSRL : Pseudo<(outs GPR:$dst),
1412 (ins GPR:$lhs, GPR:$rhs, ixlenimm:$cc,
1413 GPR:$falsev, GPR:$rs1, GPR:$rs2), []>,
1414 Sched<[WriteSFB, ReadSFBJmp, ReadSFBJmp, ReadSFBALU,
1415 ReadSFBALU, ReadSFBALU]>;
1416 def PseudoCCSRA : Pseudo<(outs GPR:$dst),
1417 (ins GPR:$lhs, GPR:$rhs, ixlenimm:$cc,
1418 GPR:$falsev, GPR:$rs1, GPR:$rs2), []>,
1419 Sched<[WriteSFB, ReadSFBJmp, ReadSFBJmp, ReadSFBALU,
1420 ReadSFBALU, ReadSFBALU]>;
1421 def PseudoCCAND : Pseudo<(outs GPR:$dst),
1422 (ins GPR:$lhs, GPR:$rhs, ixlenimm:$cc,
1423 GPR:$falsev, GPR:$rs1, GPR:$rs2), []>,
1424 Sched<[WriteSFB, ReadSFBJmp, ReadSFBJmp,
1425 ReadSFBALU, ReadSFBALU, ReadSFBALU]>;
1426 def PseudoCCOR : Pseudo<(outs GPR:$dst),
1427 (ins GPR:$lhs, GPR:$rhs, ixlenimm:$cc,
1428 GPR:$falsev, GPR:$rs1, GPR:$rs2), []>,
1429 Sched<[WriteSFB, ReadSFBJmp, ReadSFBJmp,
1430 ReadSFBALU, ReadSFBALU, ReadSFBALU]>;
1431 def PseudoCCXOR : Pseudo<(outs GPR:$dst),
1432 (ins GPR:$lhs, GPR:$rhs, ixlenimm:$cc,
1433 GPR:$falsev, GPR:$rs1, GPR:$rs2), []>,
1434 Sched<[WriteSFB, ReadSFBJmp, ReadSFBJmp,
1435 ReadSFBALU, ReadSFBALU, ReadSFBALU]>;
1437 def PseudoCCADDI : Pseudo<(outs GPR:$dst),
1438 (ins GPR:$lhs, GPR:$rhs, ixlenimm:$cc,
1439 GPR:$falsev, GPR:$rs1, simm12:$rs2), []>,
1440 Sched<[WriteSFB, ReadSFBJmp, ReadSFBJmp, ReadSFBALU,
1442 def PseudoCCSLLI : Pseudo<(outs GPR:$dst),
1443 (ins GPR:$lhs, GPR:$rhs, ixlenimm:$cc,
1444 GPR:$falsev, GPR:$rs1, simm12:$rs2), []>,
1445 Sched<[WriteSFB, ReadSFBJmp, ReadSFBJmp, ReadSFBALU,
1447 def PseudoCCSRLI : Pseudo<(outs GPR:$dst),
1448 (ins GPR:$lhs, GPR:$rhs, ixlenimm:$cc,
1449 GPR:$falsev, GPR:$rs1, simm12:$rs2), []>,
1450 Sched<[WriteSFB, ReadSFBJmp, ReadSFBJmp, ReadSFBALU,
1452 def PseudoCCSRAI : Pseudo<(outs GPR:$dst),
1453 (ins GPR:$lhs, GPR:$rhs, ixlenimm:$cc,
1454 GPR:$falsev, GPR:$rs1, simm12:$rs2), []>,
1455 Sched<[WriteSFB, ReadSFBJmp, ReadSFBJmp, ReadSFBALU,
1457 def PseudoCCANDI : Pseudo<(outs GPR:$dst),
1458 (ins GPR:$lhs, GPR:$rhs, ixlenimm:$cc,
1459 GPR:$falsev, GPR:$rs1, simm12:$rs2), []>,
1460 Sched<[WriteSFB, ReadSFBJmp, ReadSFBJmp, ReadSFBALU,
1462 def PseudoCCORI : Pseudo<(outs GPR:$dst),
1463 (ins GPR:$lhs, GPR:$rhs, ixlenimm:$cc,
1464 GPR:$falsev, GPR:$rs1, simm12:$rs2), []>,
1465 Sched<[WriteSFB, ReadSFBJmp, ReadSFBJmp, ReadSFBALU,
1467 def PseudoCCXORI : Pseudo<(outs GPR:$dst),
1468 (ins GPR:$lhs, GPR:$rhs, ixlenimm:$cc,
1469 GPR:$falsev, GPR:$rs1, simm12:$rs2), []>,
1470 Sched<[WriteSFB, ReadSFBJmp, ReadSFBJmp, ReadSFBALU,
1473 // RV64I instructions
1474 def PseudoCCADDW : Pseudo<(outs GPR:$dst),
1475 (ins GPR:$lhs, GPR:$rhs, ixlenimm:$cc,
1476 GPR:$falsev, GPR:$rs1, GPR:$rs2), []>,
1477 Sched<[WriteSFB, ReadSFBJmp, ReadSFBJmp,
1478 ReadSFBALU, ReadSFBALU, ReadSFBALU]>;
1479 def PseudoCCSUBW : Pseudo<(outs GPR:$dst),
1480 (ins GPR:$lhs, GPR:$rhs, ixlenimm:$cc,
1481 GPR:$falsev, GPR:$rs1, GPR:$rs2), []>,
1482 Sched<[WriteSFB, ReadSFBJmp, ReadSFBJmp,
1483 ReadSFBALU, ReadSFBALU, ReadSFBALU]>;
1484 def PseudoCCSLLW : Pseudo<(outs GPR:$dst),
1485 (ins GPR:$lhs, GPR:$rhs, ixlenimm:$cc,
1486 GPR:$falsev, GPR:$rs1, GPR:$rs2), []>,
1487 Sched<[WriteSFB, ReadSFBJmp, ReadSFBJmp, ReadSFBALU,
1488 ReadSFBALU, ReadSFBALU]>;
1489 def PseudoCCSRLW : Pseudo<(outs GPR:$dst),
1490 (ins GPR:$lhs, GPR:$rhs, ixlenimm:$cc,
1491 GPR:$falsev, GPR:$rs1, GPR:$rs2), []>,
1492 Sched<[WriteSFB, ReadSFBJmp, ReadSFBJmp, ReadSFBALU,
1493 ReadSFBALU, ReadSFBALU]>;
1494 def PseudoCCSRAW : Pseudo<(outs GPR:$dst),
1495 (ins GPR:$lhs, GPR:$rhs, ixlenimm:$cc,
1496 GPR:$falsev, GPR:$rs1, GPR:$rs2), []>,
1497 Sched<[WriteSFB, ReadSFBJmp, ReadSFBJmp, ReadSFBALU,
1498 ReadSFBALU, ReadSFBALU]>;
1500 def PseudoCCADDIW : Pseudo<(outs GPR:$dst),
1501 (ins GPR:$lhs, GPR:$rhs, ixlenimm:$cc,
1502 GPR:$falsev, GPR:$rs1, simm12:$rs2), []>,
1503 Sched<[WriteSFB, ReadSFBJmp, ReadSFBJmp, ReadSFBALU,
1505 def PseudoCCSLLIW : Pseudo<(outs GPR:$dst),
1506 (ins GPR:$lhs, GPR:$rhs, ixlenimm:$cc,
1507 GPR:$falsev, GPR:$rs1, simm12:$rs2), []>,
1508 Sched<[WriteSFB, ReadSFBJmp, ReadSFBJmp, ReadSFBALU,
1510 def PseudoCCSRLIW : Pseudo<(outs GPR:$dst),
1511 (ins GPR:$lhs, GPR:$rhs, ixlenimm:$cc,
1512 GPR:$falsev, GPR:$rs1, simm12:$rs2), []>,
1513 Sched<[WriteSFB, ReadSFBJmp, ReadSFBJmp, ReadSFBALU,
1515 def PseudoCCSRAIW : Pseudo<(outs GPR:$dst),
1516 (ins GPR:$lhs, GPR:$rhs, ixlenimm:$cc,
1517 GPR:$falsev, GPR:$rs1, simm12:$rs2), []>,
1518 Sched<[WriteSFB, ReadSFBJmp, ReadSFBJmp, ReadSFBALU,
1522 multiclass SelectCC_GPR_rrirr<DAGOperand valty, ValueType vt> {
1523 let usesCustomInserter = 1 in
1524 def _Using_CC_GPR : Pseudo<(outs valty:$dst),
1525 (ins GPR:$lhs, GPR:$rhs, ixlenimm:$cc,
1526 valty:$truev, valty:$falsev),
1528 (riscv_selectcc_frag:$cc (XLenVT GPR:$lhs), GPR:$rhs, cond,
1529 (vt valty:$truev), valty:$falsev))]>;
1530 // Explicitly select 0 in the condition to X0. The register coalescer doesn't
1532 def : Pat<(riscv_selectcc_frag:$cc (XLenVT GPR:$lhs), 0, cond, (vt valty:$truev),
1534 (!cast<Instruction>(NAME#"_Using_CC_GPR") GPR:$lhs, (XLenVT X0),
1535 (IntCCtoRISCVCC $cc), valty:$truev, valty:$falsev)>;
1538 let Predicates = [NoShortForwardBranchOpt] in
1539 defm Select_GPR : SelectCC_GPR_rrirr<GPR, XLenVT>;
1541 class SelectCompressOpt<CondCode Cond>
1542 : Pat<(riscv_selectcc_frag:$select (XLenVT GPR:$lhs), simm12_no6:$Constant, Cond,
1543 (XLenVT GPR:$truev), GPR:$falsev),
1544 (Select_GPR_Using_CC_GPR (ADDI GPR:$lhs, (NegImm simm12:$Constant)), (XLenVT X0),
1545 (IntCCtoRISCVCC $select), GPR:$truev, GPR:$falsev)>;
1547 def OptForMinSize : Predicate<"MF ? MF->getFunction().hasMinSize() : false">;
1549 let Predicates = [HasStdExtC, OptForMinSize] in {
1550 def : SelectCompressOpt<SETEQ>;
1551 def : SelectCompressOpt<SETNE>;
1554 /// Branches and jumps
1556 // Match `riscv_brcc` and lower to the appropriate RISC-V branch instruction.
1557 multiclass BccPat<CondCode Cond, RVInstB Inst> {
1558 def : Pat<(riscv_brcc (XLenVT GPR:$rs1), GPR:$rs2, Cond, bb:$imm12),
1559 (Inst GPR:$rs1, GPR:$rs2, simm13_lsb0:$imm12)>;
1560 // Explicitly select 0 to X0. The register coalescer doesn't always do it.
1561 def : Pat<(riscv_brcc (XLenVT GPR:$rs1), 0, Cond, bb:$imm12),
1562 (Inst GPR:$rs1, (XLenVT X0), simm13_lsb0:$imm12)>;
1565 class BrccCompressOpt<CondCode Cond, RVInstB Inst>
1566 : Pat<(riscv_brcc GPR:$lhs, simm12_no6:$Constant, Cond, bb:$place),
1567 (Inst (ADDI GPR:$lhs, (NegImm simm12:$Constant)), (XLenVT X0), bb:$place)>;
1569 defm : BccPat<SETEQ, BEQ>;
1570 defm : BccPat<SETNE, BNE>;
1571 defm : BccPat<SETLT, BLT>;
1572 defm : BccPat<SETGE, BGE>;
1573 defm : BccPat<SETULT, BLTU>;
1574 defm : BccPat<SETUGE, BGEU>;
1576 let Predicates = [HasStdExtC, OptForMinSize] in {
1577 def : BrccCompressOpt<SETEQ, BEQ>;
1578 def : BrccCompressOpt<SETNE, BNE>;
1581 class LongBccPseudo : Pseudo<(outs),
1582 (ins GPR:$rs1, GPR:$rs2, simm21_lsb0_jal:$imm20),
1587 let hasSideEffects = 0;
1590 let isAsmParserOnly = 1;
1591 let hasNoSchedulingInfo = 1;
1594 def PseudoLongBEQ : LongBccPseudo;
1595 def PseudoLongBNE : LongBccPseudo;
1596 def PseudoLongBLT : LongBccPseudo;
1597 def PseudoLongBGE : LongBccPseudo;
1598 def PseudoLongBLTU : LongBccPseudo;
1599 def PseudoLongBGEU : LongBccPseudo;
1601 let isBarrier = 1, isBranch = 1, isTerminator = 1 in
1602 def PseudoBR : Pseudo<(outs), (ins simm21_lsb0_jal:$imm20), [(br bb:$imm20)]>,
1603 PseudoInstExpansion<(JAL X0, simm21_lsb0_jal:$imm20)>;
1605 let isBarrier = 1, isBranch = 1, isIndirectBranch = 1, isTerminator = 1 in
1606 def PseudoBRIND : Pseudo<(outs), (ins GPRJALR:$rs1, simm12:$imm12), []>,
1607 PseudoInstExpansion<(JALR X0, GPR:$rs1, simm12:$imm12)>;
1609 def : Pat<(brind GPRJALR:$rs1), (PseudoBRIND GPRJALR:$rs1, 0)>;
1610 def : Pat<(brind (add GPRJALR:$rs1, simm12:$imm12)),
1611 (PseudoBRIND GPRJALR:$rs1, simm12:$imm12)>;
1613 // PseudoCALLReg is a generic pseudo instruction for calls which will eventually
1614 // expand to auipc and jalr while encoding, with any given register used as the
1616 // Define AsmString to print "call" when compile with -S flag.
1617 // Define isCodeGenOnly = 0 to support parsing assembly "call" instruction.
1618 let isCall = 1, isBarrier = 1, isCodeGenOnly = 0, Size = 8, hasSideEffects = 0,
1619 mayStore = 0, mayLoad = 0 in
1620 def PseudoCALLReg : Pseudo<(outs GPR:$rd), (ins call_symbol:$func), [],
1621 "call", "$rd, $func">,
1622 Sched<[WriteIALU, WriteJalr, ReadJalr]>;
1624 // PseudoCALL is a pseudo instruction which will eventually expand to auipc
1625 // and jalr while encoding. This is desirable, as an auipc+jalr pair with
1626 // R_RISCV_CALL and R_RISCV_RELAX relocations can be be relaxed by the linker
1627 // if the offset fits in a signed 21-bit immediate.
1628 // Define AsmString to print "call" when compile with -S flag.
1629 // Define isCodeGenOnly = 0 to support parsing assembly "call" instruction.
1630 let isCall = 1, Defs = [X1], isCodeGenOnly = 0, Size = 8 in
1631 def PseudoCALL : Pseudo<(outs), (ins call_symbol:$func), [],
1633 Sched<[WriteIALU, WriteJalr, ReadJalr]>;
1635 def : Pat<(riscv_call tglobaladdr:$func), (PseudoCALL tglobaladdr:$func)>;
1636 def : Pat<(riscv_call texternalsym:$func), (PseudoCALL texternalsym:$func)>;
1638 def : Pat<(riscv_sret_glue), (SRET (XLenVT X0), (XLenVT X0))>;
1639 def : Pat<(riscv_mret_glue), (MRET (XLenVT X0), (XLenVT X0))>;
1641 let isCall = 1, Defs = [X1] in
1642 def PseudoCALLIndirect : Pseudo<(outs), (ins GPRJALR:$rs1),
1643 [(riscv_call GPRJALR:$rs1)]>,
1644 PseudoInstExpansion<(JALR X1, GPR:$rs1, 0)>;
1646 let isBarrier = 1, isReturn = 1, isTerminator = 1 in
1647 def PseudoRET : Pseudo<(outs), (ins), [(riscv_ret_glue)]>,
1648 PseudoInstExpansion<(JALR X0, X1, 0)>;
1650 // PseudoTAIL is a pseudo instruction similar to PseudoCALL and will eventually
1651 // expand to auipc and jalr while encoding.
1652 // Define AsmString to print "tail" when compile with -S flag.
1653 let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1, Uses = [X2],
1654 Size = 8, isCodeGenOnly = 0 in
1655 def PseudoTAIL : Pseudo<(outs), (ins call_symbol:$dst), [],
1657 Sched<[WriteIALU, WriteJalr, ReadJalr]>;
1659 let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1, Uses = [X2] in
1660 def PseudoTAILIndirect : Pseudo<(outs), (ins GPRTC:$rs1),
1661 [(riscv_tail GPRTC:$rs1)]>,
1662 PseudoInstExpansion<(JALR X0, GPR:$rs1, 0)>;
1664 def : Pat<(riscv_tail (iPTR tglobaladdr:$dst)),
1665 (PseudoTAIL tglobaladdr:$dst)>;
1666 def : Pat<(riscv_tail (iPTR texternalsym:$dst)),
1667 (PseudoTAIL texternalsym:$dst)>;
1669 let isCall = 0, isBarrier = 1, isBranch = 1, isTerminator = 1, Size = 8,
1670 isCodeGenOnly = 0, hasSideEffects = 0, mayStore = 0, mayLoad = 0 in
1671 def PseudoJump : Pseudo<(outs GPR:$rd), (ins pseudo_jump_symbol:$target), [],
1672 "jump", "$target, $rd">,
1673 Sched<[WriteIALU, WriteJalr, ReadJalr]>;
1675 // Pseudo for a rematerializable constant materialization sequence.
1676 // This is an experimental feature enabled by
1677 // -riscv-use-rematerializable-movimm in RISCVISelDAGToDAG.cpp
1678 // It will be expanded after register allocation.
1679 // FIXME: The scheduling information does not reflect the multiple instructions.
1680 let hasSideEffects = 0, mayLoad = 0, mayStore = 0, Size = 8, isCodeGenOnly = 1,
1681 isPseudo = 1, isReMaterializable = 1, IsSignExtendingOpW = 1 in
1682 def PseudoMovImm : Pseudo<(outs GPR:$dst), (ins i32imm:$imm), []>,
1685 let hasSideEffects = 0, mayLoad = 0, mayStore = 0, Size = 8, isCodeGenOnly = 0,
1686 isAsmParserOnly = 1 in
1687 def PseudoLLA : Pseudo<(outs GPR:$dst), (ins bare_symbol:$src), [],
1688 "lla", "$dst, $src">;
1690 // Refer to comment on PseudoLI for explanation of Size=32
1691 let hasSideEffects = 0, mayLoad = 0, mayStore = 0, Size = 8, isCodeGenOnly = 0,
1692 isAsmParserOnly = 1 in
1693 def PseudoLLAImm : Pseudo<(outs GPR:$dst), (ins ixlenimm_li_restricted:$imm), [],
1694 "lla", "$dst, $imm">;
1695 def : Pat<(riscv_lla tglobaladdr:$in), (PseudoLLA tglobaladdr:$in)>;
1696 def : Pat<(riscv_lla tblockaddress:$in), (PseudoLLA tblockaddress:$in)>;
1697 def : Pat<(riscv_lla tjumptable:$in), (PseudoLLA tjumptable:$in)>;
1698 def : Pat<(riscv_lla tconstpool:$in), (PseudoLLA tconstpool:$in)>;
1700 let hasSideEffects = 0, mayLoad = 1, mayStore = 0, Size = 8, isCodeGenOnly = 0,
1701 isAsmParserOnly = 1 in
1702 def PseudoLGA : Pseudo<(outs GPR:$dst), (ins bare_symbol:$src), [],
1703 "lga", "$dst, $src">;
1705 let hasSideEffects = 0, mayLoad = 1, mayStore = 0, Size = 8, isCodeGenOnly = 0,
1706 isAsmParserOnly = 1 in
1707 def PseudoLA : Pseudo<(outs GPR:$dst), (ins bare_symbol:$src), [],
1708 "la", "$dst, $src">;
1710 // Refer to comment on PseudoLI for explanation of Size=32
1711 let hasSideEffects = 0, mayLoad = 0, mayStore = 0, Size = 32,
1712 isCodeGenOnly = 0, isAsmParserOnly = 1 in
1713 def PseudoLAImm : Pseudo<(outs GPR:$rd), (ins ixlenimm_li_restricted:$imm), [],
1716 let hasSideEffects = 0, mayLoad = 1, mayStore = 0, Size = 8, isCodeGenOnly = 0,
1717 isAsmParserOnly = 1 in
1718 def PseudoLA_TLS_IE : Pseudo<(outs GPR:$dst), (ins bare_symbol:$src), [],
1719 "la.tls.ie", "$dst, $src">;
1721 let hasSideEffects = 0, mayLoad = 0, mayStore = 0, Size = 8, isCodeGenOnly = 0,
1722 isAsmParserOnly = 1 in
1723 def PseudoLA_TLS_GD : Pseudo<(outs GPR:$dst), (ins bare_symbol:$src), [],
1724 "la.tls.gd", "$dst, $src">;
1727 /// Sign/Zero Extends
1729 // There are single-instruction versions of these in Zbb, so disable these
1730 // Pseudos if that extension is present.
1731 let hasSideEffects = 0, mayLoad = 0,
1732 mayStore = 0, isCodeGenOnly = 0, isAsmParserOnly = 1 in {
1733 def PseudoSEXT_B : Pseudo<(outs GPR:$rd), (ins GPR:$rs), [], "sext.b", "$rd, $rs">;
1734 def PseudoSEXT_H : Pseudo<(outs GPR:$rd), (ins GPR:$rs), [], "sext.h", "$rd, $rs">;
1735 // rv64's sext.w is defined above, using InstAlias<"sext.w ...
1736 // zext.b is defined above, using InstAlias<"zext.b ...
1737 def PseudoZEXT_H : Pseudo<(outs GPR:$rd), (ins GPR:$rs), [], "zext.h", "$rd, $rs">;
1738 } // hasSideEffects = 0, ...
1740 let Predicates = [IsRV64], hasSideEffects = 0, mayLoad = 0, mayStore = 0,
1741 isCodeGenOnly = 0, isAsmParserOnly = 1 in {
1742 def PseudoZEXT_W : Pseudo<(outs GPR:$rd), (ins GPR:$rs), [], "zext.w", "$rd, $rs">;
1743 } // Predicates = [IsRV64], ...
1747 class LdPat<PatFrag LoadOp, RVInst Inst, ValueType vt = XLenVT>
1748 : Pat<(vt (LoadOp (AddrRegImm (XLenVT GPR:$rs1), simm12:$imm12))),
1749 (Inst GPR:$rs1, simm12:$imm12)>;
1751 def : LdPat<sextloadi8, LB>;
1752 def : LdPat<extloadi8, LBU>; // Prefer unsigned due to no c.lb in Zcb.
1753 def : LdPat<sextloadi16, LH>;
1754 def : LdPat<extloadi16, LH>;
1755 def : LdPat<load, LW, i32>;
1756 def : LdPat<zextloadi8, LBU>;
1757 def : LdPat<zextloadi16, LHU>;
1761 class StPat<PatFrag StoreOp, RVInst Inst, RegisterClass StTy,
1763 : Pat<(StoreOp (vt StTy:$rs2), (AddrRegImm (XLenVT GPR:$rs1),
1765 (Inst StTy:$rs2, GPR:$rs1, simm12:$imm12)>;
1767 def : StPat<truncstorei8, SB, GPR, XLenVT>;
1768 def : StPat<truncstorei16, SH, GPR, XLenVT>;
1769 def : StPat<store, SW, GPR, i32>;
1773 // Refer to Table A.6 in the version 2.3 draft of the RISC-V Instruction Set
1774 // Manual: Volume I.
1776 // fence acquire -> fence r, rw
1777 def : Pat<(atomic_fence (XLenVT 4), (timm)), (FENCE 0b10, 0b11)>;
1778 // fence release -> fence rw, w
1779 def : Pat<(atomic_fence (XLenVT 5), (timm)), (FENCE 0b11, 0b1)>;
1780 // fence acq_rel -> fence.tso
1781 def : Pat<(atomic_fence (XLenVT 6), (timm)), (FENCE_TSO)>;
1782 // fence seq_cst -> fence rw, rw
1783 def : Pat<(atomic_fence (XLenVT 7), (timm)), (FENCE 0b11, 0b11)>;
1785 // Lowering for atomic load and store is defined in RISCVInstrInfoA.td.
1786 // Although these are lowered to fence+load/store instructions defined in the
1787 // base RV32I/RV64I ISA, this lowering is only used when the A extension is
1788 // present. This is necessary as it isn't valid to mix __atomic_* libcalls
1789 // with inline atomic operations for the same object.
1791 /// Access to system registers
1793 // Helpers for defining specific operations. They are defined for each system
1794 // register separately. Side effect is not used because dependencies are
1795 // expressed via use-def properties.
1797 class ReadSysReg<SysReg SR, list<Register> Regs>
1798 : Pseudo<(outs GPR:$rd), (ins),
1799 [(set GPR:$rd, (XLenVT (riscv_read_csr (XLenVT SR.Encoding))))]>,
1800 PseudoInstExpansion<(CSRRS GPR:$rd, SR.Encoding, X0)> {
1801 let hasSideEffects = 0;
1805 class WriteSysReg<SysReg SR, list<Register> Regs>
1806 : Pseudo<(outs), (ins GPR:$val),
1807 [(riscv_write_csr (XLenVT SR.Encoding), (XLenVT GPR:$val))]>,
1808 PseudoInstExpansion<(CSRRW X0, SR.Encoding, GPR:$val)> {
1809 let hasSideEffects = 0;
1813 class WriteSysRegImm<SysReg SR, list<Register> Regs>
1814 : Pseudo<(outs), (ins uimm5:$val),
1815 [(riscv_write_csr (XLenVT SR.Encoding), uimm5:$val)]>,
1816 PseudoInstExpansion<(CSRRWI X0, SR.Encoding, uimm5:$val)> {
1817 let hasSideEffects = 0;
1821 class SwapSysReg<SysReg SR, list<Register> Regs>
1822 : Pseudo<(outs GPR:$rd), (ins GPR:$val),
1823 [(set GPR:$rd, (riscv_swap_csr (XLenVT SR.Encoding), (XLenVT GPR:$val)))]>,
1824 PseudoInstExpansion<(CSRRW GPR:$rd, SR.Encoding, GPR:$val)> {
1825 let hasSideEffects = 0;
1830 class SwapSysRegImm<SysReg SR, list<Register> Regs>
1831 : Pseudo<(outs GPR:$rd), (ins uimm5:$val),
1832 [(set GPR:$rd, (XLenVT (riscv_swap_csr (XLenVT SR.Encoding), uimm5:$val)))]>,
1833 PseudoInstExpansion<(CSRRWI GPR:$rd, SR.Encoding, uimm5:$val)> {
1834 let hasSideEffects = 0;
1839 def ReadFRM : ReadSysReg<SysRegFRM, [FRM]>;
1840 def WriteFRM : WriteSysReg<SysRegFRM, [FRM]>;
1841 def WriteFRMImm : WriteSysRegImm<SysRegFRM, [FRM]>;
1842 def SwapFRMImm : SwapSysRegImm<SysRegFRM, [FRM]>;
1844 def WriteVXRMImm : WriteSysRegImm<SysRegVXRM, [VXRM]>;
1846 let hasSideEffects = true in {
1847 def ReadFFLAGS : ReadSysReg<SysRegFFLAGS, [FFLAGS]>;
1848 def WriteFFLAGS : WriteSysReg<SysRegFFLAGS, [FFLAGS]>;
1850 /// Other pseudo-instructions
1852 // Pessimistically assume the stack pointer will be clobbered
1853 let Defs = [X2], Uses = [X2] in {
1854 def ADJCALLSTACKDOWN : Pseudo<(outs), (ins i32imm:$amt1, i32imm:$amt2),
1855 [(callseq_start timm:$amt1, timm:$amt2)]>;
1856 def ADJCALLSTACKUP : Pseudo<(outs), (ins i32imm:$amt1, i32imm:$amt2),
1857 [(callseq_end timm:$amt1, timm:$amt2)]>;
1858 } // Defs = [X2], Uses = [X2]
1862 let Predicates = [IsRV64, NotHasStdExtZba] in {
1863 def : Pat<(i64 (and GPR:$rs1, 0xffffffff)), (SRLI (SLLI GPR:$rs1, 32), 32)>;
1865 // If we're shifting a 32-bit zero extended value left by 0-31 bits, use 2
1866 // shifts instead of 3. This can occur when unsigned is used to index an array.
1867 def : Pat<(i64 (shl (and GPR:$rs1, 0xffffffff), uimm5:$shamt)),
1868 (SRLI (SLLI GPR:$rs1, 32), (ImmSubFrom32 uimm5:$shamt))>;
1871 class binop_allhusers<SDPatternOperator operator>
1872 : PatFrag<(ops node:$lhs, node:$rhs),
1873 (XLenVT (operator node:$lhs, node:$rhs)), [{
1874 return hasAllHUsers(Node);
1877 // PatFrag to allow ADDW/SUBW/MULW/SLLW to be selected from i64 add/sub/mul/shl
1878 // if only the lower 32 bits of their result is used.
1879 class binop_allwusers<SDPatternOperator operator>
1880 : PatFrag<(ops node:$lhs, node:$rhs),
1881 (i64 (operator node:$lhs, node:$rhs)), [{
1882 return hasAllWUsers(Node);
1885 def sexti32_allwusers : PatFrag<(ops node:$src),
1886 (sext_inreg node:$src, i32), [{
1887 return hasAllWUsers(Node);
1890 def ImmSExt32 : SDNodeXForm<imm, [{
1891 return CurDAG->getTargetConstant(SignExtend64<32>(N->getSExtValue()),
1892 SDLoc(N), N->getValueType(0));
1894 // Look for constants where the upper 32 bits are 0, but sign extending bit 31
1895 // would be an simm12.
1896 def u32simm12 : ImmLeaf<XLenVT, [{
1897 return isUInt<32>(Imm) && isInt<12>(SignExtend64<32>(Imm));
1900 let Predicates = [IsRV64] in {
1902 def : Pat<(i64 (and GPR:$rs, LeadingOnesWMask:$mask)),
1903 (SLLI (SRLIW $rs, LeadingOnesWMask:$mask), LeadingOnesWMask:$mask)>;
1907 // Sign extend is not needed if all users are W instructions.
1908 def : Pat<(sexti32_allwusers GPR:$rs1), (XLenVT GPR:$rs1)>;
1910 def : Pat<(sext_inreg GPR:$rs1, i32), (ADDIW GPR:$rs1, 0)>;
1914 def : Pat<(i64 (srl (and GPR:$rs1, 0xffffffff), uimm5:$shamt)),
1915 (SRLIW GPR:$rs1, uimm5:$shamt)>;
1916 def : Pat<(i64 (srl (shl GPR:$rs1, (i64 32)), uimm6gt32:$shamt)),
1917 (SRLIW GPR:$rs1, (ImmSub32 uimm6gt32:$shamt))>;
1918 def : Pat<(sra (sext_inreg GPR:$rs1, i32), uimm5:$shamt),
1919 (SRAIW GPR:$rs1, uimm5:$shamt)>;
1920 def : Pat<(i64 (sra (shl GPR:$rs1, (i64 32)), uimm6gt32:$shamt)),
1921 (SRAIW GPR:$rs1, (ImmSub32 uimm6gt32:$shamt))>;
1923 def : PatGprGpr<shiftopw<riscv_sllw>, SLLW>;
1924 def : PatGprGpr<shiftopw<riscv_srlw>, SRLW>;
1925 def : PatGprGpr<shiftopw<riscv_sraw>, SRAW>;
1927 // Select W instructions if only the lower 32 bits of the result are used.
1928 def : PatGprGpr<binop_allwusers<add>, ADDW>;
1929 def : PatGprSimm12<binop_allwusers<add>, ADDIW>;
1930 def : PatGprGpr<binop_allwusers<sub>, SUBW>;
1931 def : PatGprImm<binop_allwusers<shl>, SLLIW, uimm5>;
1933 // If this is a shr of a value sign extended from i32, and all the users only
1934 // use the lower 32 bits, we can use an sraiw to remove the sext_inreg. This
1935 // occurs because SimplifyDemandedBits prefers srl over sra.
1936 def : Pat<(binop_allwusers<srl> (sext_inreg GPR:$rs1, i32), uimm5:$shamt),
1937 (SRAIW GPR:$rs1, uimm5:$shamt)>;
1939 // Use binop_allwusers to recover immediates that may have been broken by
1940 // SimplifyDemandedBits.
1941 def : Pat<(binop_allwusers<and> GPR:$rs1, u32simm12:$imm),
1942 (ANDI GPR:$rs1, u32simm12:$imm)>;
1944 def : Pat<(binop_allwusers<or> GPR:$rs1, u32simm12:$imm),
1945 (ORI GPR:$rs1, u32simm12:$imm)>;
1947 def : Pat<(binop_allwusers<xor> GPR:$rs1, u32simm12:$imm),
1948 (XORI GPR:$rs1, u32simm12:$imm)>;
1951 def : LdPat<sextloadi32, LW, i64>;
1952 def : LdPat<extloadi32, LW, i64>;
1953 def : LdPat<zextloadi32, LWU, i64>;
1954 def : LdPat<load, LD, i64>;
1958 def : StPat<truncstorei32, SW, GPR, i64>;
1959 def : StPat<store, SD, GPR, i64>;
1960 } // Predicates = [IsRV64]
1962 /// readcyclecounter
1963 // On RV64, we can directly read the 64-bit "cycle" CSR.
1964 let Predicates = [IsRV64] in
1965 def : Pat<(i64 (readcyclecounter)), (CSRRS CYCLE.Encoding, (XLenVT X0))>;
1966 // On RV32, ReadCycleWide will be expanded to the suggested loop reading both
1967 // halves of the 64-bit "cycle" CSR.
1968 let Predicates = [IsRV32], usesCustomInserter = 1, hasNoSchedulingInfo = 1 in
1969 def ReadCycleWide : Pseudo<(outs GPR:$lo, GPR:$hi), (ins),
1970 [(set GPR:$lo, GPR:$hi, (riscv_read_cycle_wide))],
1975 // We lower `trap` to `unimp`, as this causes a hard exception on nearly all
1977 def : Pat<(trap), (UNIMP)>;
1979 // We lower `debugtrap` to `ebreak`, as this will get the attention of the
1980 // debugger if possible.
1981 def : Pat<(debugtrap), (EBREAK)>;
1983 let Predicates = [IsRV64], Uses = [X5],
1984 Defs = [X1, X6, X7, X28, X29, X30, X31] in
1985 def HWASAN_CHECK_MEMACCESS_SHORTGRANULES
1986 : Pseudo<(outs), (ins GPRJALR:$ptr, i32imm:$accessinfo),
1987 [(int_hwasan_check_memaccess_shortgranules (i64 X5), GPRJALR:$ptr,
1988 (i32 timm:$accessinfo))]>;
1990 // This gets lowered into a 20-byte instruction sequence (at most)
1991 let hasSideEffects = 0, mayLoad = 1, mayStore = 0,
1992 Defs = [ X6, X7, X28, X29, X30, X31 ], Size = 20 in {
1994 : Pseudo<(outs), (ins GPRJALR:$ptr, i32imm:$type), []>, Sched<[]>;
1997 /// Simple optimization
1998 def : Pat<(XLenVT (add GPR:$rs1, (AddiPair:$rs2))),
1999 (ADDI (ADDI GPR:$rs1, (AddiPairImmLarge AddiPair:$rs2)),
2000 (AddiPairImmSmall GPR:$rs2))>;
2002 let Predicates = [IsRV64] in {
2003 // Select W instructions if only the lower 32-bits of the result are used.
2004 def : Pat<(binop_allwusers<add> GPR:$rs1, (AddiPair:$rs2)),
2005 (ADDIW (ADDIW GPR:$rs1, (AddiPairImmLarge AddiPair:$rs2)),
2006 (AddiPairImmSmall AddiPair:$rs2))>;
2009 let Predicates = [HasShortForwardBranchOpt] in
2010 def : Pat<(XLenVT (abs GPR:$rs1)),
2011 (PseudoCCSUB (XLenVT GPR:$rs1), (XLenVT X0), /* COND_LT */ 2,
2012 (XLenVT GPR:$rs1), (XLenVT X0), (XLenVT GPR:$rs1))>;
2013 let Predicates = [HasShortForwardBranchOpt, IsRV64] in
2014 def : Pat<(sext_inreg (abs 33signbits_node:$rs1), i32),
2015 (PseudoCCSUBW (i64 GPR:$rs1), (i64 X0), /* COND_LT */ 2,
2016 (i64 GPR:$rs1), (i64 X0), (i64 GPR:$rs1))>;
2018 //===----------------------------------------------------------------------===//
2019 // Experimental RV64 i32 legalization patterns.
2020 //===----------------------------------------------------------------------===//
2022 def simm12i32 : ImmLeaf<i32, [{return isInt<12>(Imm);}]>;
2024 // Convert from i32 immediate to i64 target immediate to make SelectionDAG type
2025 // checking happy so we can use ADDIW which expects an XLen immediate.
2026 def as_i64imm : SDNodeXForm<imm, [{
2027 return CurDAG->getTargetConstant(N->getSExtValue(), SDLoc(N), MVT::i64);
2030 def zext_is_sext : PatFrag<(ops node:$src), (zext node:$src), [{
2031 KnownBits Known = CurDAG->computeKnownBits(N->getOperand(0), 0);
2032 return Known.isNonNegative();
2035 let Predicates = [IsRV64] in {
2036 def : LdPat<sextloadi8, LB, i32>;
2037 def : LdPat<extloadi8, LBU, i32>; // Prefer unsigned due to no c.lb in Zcb.
2038 def : LdPat<sextloadi16, LH, i32>;
2039 def : LdPat<extloadi16, LH, i32>;
2040 def : LdPat<zextloadi8, LBU, i32>;
2041 def : LdPat<zextloadi16, LHU, i32>;
2043 def : StPat<truncstorei8, SB, GPR, i32>;
2044 def : StPat<truncstorei16, SH, GPR, i32>;
2046 def : Pat<(anyext GPR:$src), (COPY GPR:$src)>;
2047 def : Pat<(sext GPR:$src), (ADDIW GPR:$src, 0)>;
2048 def : Pat<(trunc GPR:$src), (COPY GPR:$src)>;
2050 def : PatGprGpr<add, ADDW, i32, i32>;
2051 def : PatGprGpr<sub, SUBW, i32, i32>;
2052 def : PatGprGpr<and, AND, i32, i32>;
2053 def : PatGprGpr<or, OR, i32, i32>;
2054 def : PatGprGpr<xor, XOR, i32, i32>;
2055 def : PatGprGpr<shiftopw<shl>, SLLW, i32, i64>;
2056 def : PatGprGpr<shiftopw<srl>, SRLW, i32, i64>;
2057 def : PatGprGpr<shiftopw<sra>, SRAW, i32, i64>;
2059 def : Pat<(i32 (add GPR:$rs1, simm12i32:$imm)),
2060 (ADDIW GPR:$rs1, (i64 (as_i64imm $imm)))>;
2061 def : Pat<(i32 (and GPR:$rs1, simm12i32:$imm)),
2062 (ANDI GPR:$rs1, (i64 (as_i64imm $imm)))>;
2063 def : Pat<(i32 (or GPR:$rs1, simm12i32:$imm)),
2064 (ORI GPR:$rs1, (i64 (as_i64imm $imm)))>;
2065 def : Pat<(i32 (xor GPR:$rs1, simm12i32:$imm)),
2066 (XORI GPR:$rs1, (i64 (as_i64imm $imm)))>;
2068 def : PatGprImm<shl, SLLIW, uimm5, i32>;
2069 def : PatGprImm<srl, SRLIW, uimm5, i32>;
2070 def : PatGprImm<sra, SRAIW, uimm5, i32>;
2072 def : Pat<(i32 (and GPR:$rs, TrailingOnesMask:$mask)),
2073 (SRLI (SLLI $rs, (i64 (XLenSubTrailingOnes $mask))),
2074 (i64 (XLenSubTrailingOnes $mask)))>;
2076 // Use sext if the sign bit of the input is 0.
2077 def : Pat<(zext_is_sext GPR:$src), (ADDIW GPR:$src, 0)>;
2080 let Predicates = [IsRV64, NotHasStdExtZba] in {
2081 def : Pat<(zext GPR:$src), (SRLI (SLLI GPR:$src, 32), 32)>;
2083 // If we're shifting a 32-bit zero extended value left by 0-31 bits, use 2
2084 // shifts instead of 3. This can occur when unsigned is used to index an array.
2085 def : Pat<(shl (zext GPR:$rs), uimm5:$shamt),
2086 (SRLI (SLLI GPR:$rs, 32), (ImmSubFrom32 uimm5:$shamt))>;
2089 //===----------------------------------------------------------------------===//
2090 // Standard extensions
2091 //===----------------------------------------------------------------------===//
2093 // Multiply and Division
2094 include "RISCVInstrInfoM.td"
2097 include "RISCVInstrInfoA.td"
2100 include "RISCVInstrInfoF.td"
2101 include "RISCVInstrInfoD.td"
2102 include "RISCVInstrInfoZfh.td"
2103 include "RISCVInstrInfoZfbfmin.td"
2104 include "RISCVInstrInfoZfa.td"
2106 // Scalar bitmanip and cryptography
2107 include "RISCVInstrInfoZb.td"
2108 include "RISCVInstrInfoZk.td"
2111 include "RISCVInstrInfoV.td"
2112 include "RISCVInstrInfoZvk.td"
2115 include "RISCVInstrInfoZicbo.td"
2116 include "RISCVInstrInfoZicond.td"
2119 include "RISCVInstrInfoC.td"
2120 include "RISCVInstrInfoZc.td"
2122 //===----------------------------------------------------------------------===//
2123 // Vendor extensions
2124 //===----------------------------------------------------------------------===//
2126 include "RISCVInstrInfoXVentana.td"
2127 include "RISCVInstrInfoXTHead.td"
2128 include "RISCVInstrInfoXSf.td"
2129 include "RISCVInstrInfoXCV.td"