1 //===-- RISCVInstrInfo.td - Target Description for RISCV ---*- 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 // Target-independent nodes, but with target-specific formats.
30 def callseq_start : SDNode<"ISD::CALLSEQ_START", SDT_CallSeqStart,
31 [SDNPHasChain, SDNPOutGlue]>;
32 def callseq_end : SDNode<"ISD::CALLSEQ_END", SDT_CallSeqEnd,
33 [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue]>;
35 // Target-dependent nodes.
36 def riscv_call : SDNode<"RISCVISD::CALL", SDT_RISCVCall,
37 [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue,
39 def riscv_ret_flag : SDNode<"RISCVISD::RET_FLAG", SDTNone,
40 [SDNPHasChain, SDNPOptInGlue, SDNPVariadic]>;
41 def riscv_uret_flag : SDNode<"RISCVISD::URET_FLAG", SDTNone,
42 [SDNPHasChain, SDNPOptInGlue]>;
43 def riscv_sret_flag : SDNode<"RISCVISD::SRET_FLAG", SDTNone,
44 [SDNPHasChain, SDNPOptInGlue]>;
45 def riscv_mret_flag : SDNode<"RISCVISD::MRET_FLAG", SDTNone,
46 [SDNPHasChain, SDNPOptInGlue]>;
47 def riscv_selectcc : SDNode<"RISCVISD::SELECT_CC", SDT_RISCVSelectCC,
49 def riscv_tail : SDNode<"RISCVISD::TAIL", SDT_RISCVCall,
50 [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue,
52 def riscv_sllw : SDNode<"RISCVISD::SLLW", SDTIntShiftOp>;
53 def riscv_sraw : SDNode<"RISCVISD::SRAW", SDTIntShiftOp>;
54 def riscv_srlw : SDNode<"RISCVISD::SRLW", SDTIntShiftOp>;
56 //===----------------------------------------------------------------------===//
57 // Operand and SDNode transformation definitions.
58 //===----------------------------------------------------------------------===//
60 class ImmXLenAsmOperand<string prefix, string suffix = ""> : AsmOperandClass {
61 let Name = prefix # "ImmXLen" # suffix;
62 let RenderMethod = "addImmOperands";
63 let DiagnosticType = !strconcat("Invalid", Name);
66 class ImmAsmOperand<string prefix, int width, string suffix> : AsmOperandClass {
67 let Name = prefix # "Imm" # width # suffix;
68 let RenderMethod = "addImmOperands";
69 let DiagnosticType = !strconcat("Invalid", Name);
72 def ImmZeroAsmOperand : AsmOperandClass {
74 let RenderMethod = "addImmOperands";
75 let DiagnosticType = !strconcat("Invalid", Name);
78 class SImmAsmOperand<int width, string suffix = "">
79 : ImmAsmOperand<"S", width, suffix> {
82 class UImmAsmOperand<int width, string suffix = "">
83 : ImmAsmOperand<"U", width, suffix> {
86 def FenceArg : AsmOperandClass {
87 let Name = "FenceArg";
88 let RenderMethod = "addFenceArgOperands";
89 let DiagnosticType = "InvalidFenceArg";
92 def fencearg : Operand<XLenVT> {
93 let ParserMatchClass = FenceArg;
94 let PrintMethod = "printFenceArg";
95 let DecoderMethod = "decodeUImmOperand<4>";
96 let OperandType = "OPERAND_UIMM4";
97 let OperandNamespace = "RISCVOp";
100 def UImmLog2XLenAsmOperand : AsmOperandClass {
101 let Name = "UImmLog2XLen";
102 let RenderMethod = "addImmOperands";
103 let DiagnosticType = "InvalidUImmLog2XLen";
106 def uimmlog2xlen : Operand<XLenVT>, ImmLeaf<XLenVT, [{
107 if (Subtarget->is64Bit())
108 return isUInt<6>(Imm);
109 return isUInt<5>(Imm);
111 let ParserMatchClass = UImmLog2XLenAsmOperand;
112 // TODO: should ensure invalid shamt is rejected when decoding.
113 let DecoderMethod = "decodeUImmOperand<6>";
114 let MCOperandPredicate = [{
116 if (!MCOp.evaluateAsConstantImm(Imm))
118 if (STI.getTargetTriple().isArch64Bit())
119 return isUInt<6>(Imm);
120 return isUInt<5>(Imm);
122 let OperandType = "OPERAND_UIMMLOG2XLEN";
123 let OperandNamespace = "RISCVOp";
126 def uimm5 : Operand<XLenVT>, ImmLeaf<XLenVT, [{return isUInt<5>(Imm);}]> {
127 let ParserMatchClass = UImmAsmOperand<5>;
128 let DecoderMethod = "decodeUImmOperand<5>";
129 let OperandType = "OPERAND_UIMM5";
130 let OperandNamespace = "RISCVOp";
133 def simm12 : Operand<XLenVT>, ImmLeaf<XLenVT, [{return isInt<12>(Imm);}]> {
134 let ParserMatchClass = SImmAsmOperand<12>;
135 let EncoderMethod = "getImmOpValue";
136 let DecoderMethod = "decodeSImmOperand<12>";
137 let MCOperandPredicate = [{
139 if (MCOp.evaluateAsConstantImm(Imm))
140 return isInt<12>(Imm);
141 return MCOp.isBareSymbolRef();
143 let OperandType = "OPERAND_SIMM12";
144 let OperandNamespace = "RISCVOp";
147 // A 13-bit signed immediate where the least significant bit is zero.
148 def simm13_lsb0 : Operand<OtherVT> {
149 let ParserMatchClass = SImmAsmOperand<13, "Lsb0">;
150 let EncoderMethod = "getImmOpValueAsr1";
151 let DecoderMethod = "decodeSImmOperandAndLsl1<13>";
152 let MCOperandPredicate = [{
154 if (MCOp.evaluateAsConstantImm(Imm))
155 return isShiftedInt<12, 1>(Imm);
156 return MCOp.isBareSymbolRef();
158 let OperandType = "OPERAND_SIMM13_LSB0";
159 let OperandNamespace = "RISCVOp";
162 class UImm20Operand : Operand<XLenVT> {
163 let EncoderMethod = "getImmOpValue";
164 let DecoderMethod = "decodeUImmOperand<20>";
165 let MCOperandPredicate = [{
167 if (MCOp.evaluateAsConstantImm(Imm))
168 return isUInt<20>(Imm);
169 return MCOp.isBareSymbolRef();
171 let OperandType = "OPERAND_UIMM20";
172 let OperandNamespace = "RISCVOp";
175 def uimm20_lui : UImm20Operand {
176 let ParserMatchClass = UImmAsmOperand<20, "LUI">;
178 def uimm20_auipc : UImm20Operand {
179 let ParserMatchClass = UImmAsmOperand<20, "AUIPC">;
182 def Simm21Lsb0JALAsmOperand : SImmAsmOperand<21, "Lsb0JAL"> {
183 let ParserMethod = "parseJALOffset";
186 // A 21-bit signed immediate where the least significant bit is zero.
187 def simm21_lsb0_jal : Operand<OtherVT> {
188 let ParserMatchClass = Simm21Lsb0JALAsmOperand;
189 let EncoderMethod = "getImmOpValueAsr1";
190 let DecoderMethod = "decodeSImmOperandAndLsl1<21>";
191 let MCOperandPredicate = [{
193 if (MCOp.evaluateAsConstantImm(Imm))
194 return isShiftedInt<20, 1>(Imm);
195 return MCOp.isBareSymbolRef();
197 let OperandType = "OPERAND_SIMM21_LSB0";
198 let OperandNamespace = "RISCVOp";
201 def BareSymbol : AsmOperandClass {
202 let Name = "BareSymbol";
203 let RenderMethod = "addImmOperands";
204 let DiagnosticType = "InvalidBareSymbol";
205 let ParserMethod = "parseBareSymbol";
209 def bare_symbol : Operand<XLenVT> {
210 let ParserMatchClass = BareSymbol;
213 def CallSymbol : AsmOperandClass {
214 let Name = "CallSymbol";
215 let RenderMethod = "addImmOperands";
216 let DiagnosticType = "InvalidCallSymbol";
217 let ParserMethod = "parseCallSymbol";
220 // A bare symbol used in call/tail only.
221 def call_symbol : Operand<XLenVT> {
222 let ParserMatchClass = CallSymbol;
225 def TPRelAddSymbol : AsmOperandClass {
226 let Name = "TPRelAddSymbol";
227 let RenderMethod = "addImmOperands";
228 let DiagnosticType = "InvalidTPRelAddSymbol";
229 let ParserMethod = "parseOperandWithModifier";
232 // A bare symbol with the %tprel_add variant.
233 def tprel_add_symbol : Operand<XLenVT> {
234 let ParserMatchClass = TPRelAddSymbol;
237 def CSRSystemRegister : AsmOperandClass {
238 let Name = "CSRSystemRegister";
239 let ParserMethod = "parseCSRSystemRegister";
240 let DiagnosticType = "InvalidCSRSystemRegister";
243 def csr_sysreg : Operand<XLenVT> {
244 let ParserMatchClass = CSRSystemRegister;
245 let PrintMethod = "printCSRSystemRegister";
246 let DecoderMethod = "decodeUImmOperand<12>";
247 let OperandType = "OPERAND_UIMM12";
248 let OperandNamespace = "RISCVOp";
251 // A parameterized register class alternative to i32imm/i64imm from Target.td.
252 def ixlenimm : Operand<XLenVT>;
254 def ixlenimm_li : Operand<XLenVT> {
255 let ParserMatchClass = ImmXLenAsmOperand<"", "LI">;
258 // Standalone (codegen-only) immleaf patterns.
259 def simm32 : ImmLeaf<XLenVT, [{return isInt<32>(Imm);}]>;
260 def simm32hi20 : ImmLeaf<XLenVT, [{return isShiftedInt<20, 12>(Imm);}]>;
261 // A mask value that won't affect significant shift bits.
262 def immbottomxlenset : ImmLeaf<XLenVT, [{
263 if (Subtarget->is64Bit())
264 return countTrailingOnes<uint64_t>(Imm) >= 6;
265 return countTrailingOnes<uint64_t>(Imm) >= 5;
269 // Necessary because a frameindex can't be matched directly in a pattern.
270 def AddrFI : ComplexPattern<iPTR, 1, "SelectAddrFI", [frameindex], []>;
272 // Extract least significant 12 bits from an immediate value and sign extend
274 def LO12Sext : SDNodeXForm<imm, [{
275 return CurDAG->getTargetConstant(SignExtend64<12>(N->getZExtValue()),
276 SDLoc(N), N->getValueType(0));
279 // Extract the most significant 20 bits from an immediate value. Add 1 if bit
280 // 11 is 1, to compensate for the low 12 bits in the matching immediate addi
281 // or ld/st being negative.
282 def HI20 : SDNodeXForm<imm, [{
283 return CurDAG->getTargetConstant(((N->getZExtValue()+0x800) >> 12) & 0xfffff,
284 SDLoc(N), N->getValueType(0));
287 //===----------------------------------------------------------------------===//
288 // Instruction Formats
289 //===----------------------------------------------------------------------===//
291 include "RISCVInstrFormats.td"
293 //===----------------------------------------------------------------------===//
294 // Instruction Class Templates
295 //===----------------------------------------------------------------------===//
297 let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
298 class BranchCC_rri<bits<3> funct3, string opcodestr>
299 : RVInstB<funct3, OPC_BRANCH, (outs),
300 (ins GPR:$rs1, GPR:$rs2, simm13_lsb0:$imm12),
301 opcodestr, "$rs1, $rs2, $imm12"> {
303 let isTerminator = 1;
306 let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in
307 class Load_ri<bits<3> funct3, string opcodestr>
308 : RVInstI<funct3, OPC_LOAD, (outs GPR:$rd), (ins GPR:$rs1, simm12:$imm12),
309 opcodestr, "$rd, ${imm12}(${rs1})">;
311 // Operands for stores are in the order srcreg, base, offset rather than
312 // reflecting the order these fields are specified in the instruction
314 let hasSideEffects = 0, mayLoad = 0, mayStore = 1 in
315 class Store_rri<bits<3> funct3, string opcodestr>
316 : RVInstS<funct3, OPC_STORE, (outs),
317 (ins GPR:$rs2, GPR:$rs1, simm12:$imm12),
318 opcodestr, "$rs2, ${imm12}(${rs1})">;
320 let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
321 class ALU_ri<bits<3> funct3, string opcodestr>
322 : RVInstI<funct3, OPC_OP_IMM, (outs GPR:$rd), (ins GPR:$rs1, simm12:$imm12),
323 opcodestr, "$rd, $rs1, $imm12">;
325 let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
326 class Shift_ri<bit arithshift, bits<3> funct3, string opcodestr>
327 : RVInstIShift<arithshift, funct3, OPC_OP_IMM, (outs GPR:$rd),
328 (ins GPR:$rs1, uimmlog2xlen:$shamt), opcodestr,
329 "$rd, $rs1, $shamt">;
331 let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
332 class ALU_rr<bits<7> funct7, bits<3> funct3, string opcodestr>
333 : RVInstR<funct7, funct3, OPC_OP, (outs GPR:$rd), (ins GPR:$rs1, GPR:$rs2),
334 opcodestr, "$rd, $rs1, $rs2">;
336 let hasSideEffects = 1, mayLoad = 0, mayStore = 0 in
337 class CSR_ir<bits<3> funct3, string opcodestr>
338 : RVInstI<funct3, OPC_SYSTEM, (outs GPR:$rd), (ins csr_sysreg:$imm12, GPR:$rs1),
339 opcodestr, "$rd, $imm12, $rs1">;
341 let hasSideEffects = 1, mayLoad = 0, mayStore = 0 in
342 class CSR_ii<bits<3> funct3, string opcodestr>
343 : RVInstI<funct3, OPC_SYSTEM, (outs GPR:$rd),
344 (ins csr_sysreg:$imm12, uimm5:$rs1),
345 opcodestr, "$rd, $imm12, $rs1">;
347 let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
348 class ShiftW_ri<bit arithshift, bits<3> funct3, string opcodestr>
349 : RVInstIShiftW<arithshift, funct3, OPC_OP_IMM_32, (outs GPR:$rd),
350 (ins GPR:$rs1, uimm5:$shamt), opcodestr,
351 "$rd, $rs1, $shamt">;
353 let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
354 class ALUW_rr<bits<7> funct7, bits<3> funct3, string opcodestr>
355 : RVInstR<funct7, funct3, OPC_OP_32, (outs GPR:$rd),
356 (ins GPR:$rs1, GPR:$rs2), opcodestr, "$rd, $rs1, $rs2">;
358 let hasSideEffects = 1, mayLoad = 0, mayStore = 0 in
359 class Priv<string opcodestr, bits<7> funct7>
360 : RVInstR<funct7, 0b000, OPC_SYSTEM, (outs), (ins GPR:$rs1, GPR:$rs2),
363 //===----------------------------------------------------------------------===//
365 //===----------------------------------------------------------------------===//
367 let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in {
368 let isReMaterializable = 1, isAsCheapAsAMove = 1 in
369 def LUI : RVInstU<OPC_LUI, (outs GPR:$rd), (ins uimm20_lui:$imm20),
370 "lui", "$rd, $imm20">;
372 def AUIPC : RVInstU<OPC_AUIPC, (outs GPR:$rd), (ins uimm20_auipc:$imm20),
373 "auipc", "$rd, $imm20">;
376 def JAL : RVInstJ<OPC_JAL, (outs GPR:$rd), (ins simm21_lsb0_jal:$imm20),
377 "jal", "$rd, $imm20">;
380 def JALR : RVInstI<0b000, OPC_JALR, (outs GPR:$rd),
381 (ins GPR:$rs1, simm12:$imm12),
382 "jalr", "$rd, ${imm12}(${rs1})">;
383 } // hasSideEffects = 0, mayLoad = 0, mayStore = 0
385 def BEQ : BranchCC_rri<0b000, "beq">;
386 def BNE : BranchCC_rri<0b001, "bne">;
387 def BLT : BranchCC_rri<0b100, "blt">;
388 def BGE : BranchCC_rri<0b101, "bge">;
389 def BLTU : BranchCC_rri<0b110, "bltu">;
390 def BGEU : BranchCC_rri<0b111, "bgeu">;
392 def LB : Load_ri<0b000, "lb">;
393 def LH : Load_ri<0b001, "lh">;
394 def LW : Load_ri<0b010, "lw">;
395 def LBU : Load_ri<0b100, "lbu">;
396 def LHU : Load_ri<0b101, "lhu">;
398 def SB : Store_rri<0b000, "sb">;
399 def SH : Store_rri<0b001, "sh">;
400 def SW : Store_rri<0b010, "sw">;
402 // ADDI isn't always rematerializable, but isReMaterializable will be used as
403 // a hint which is verified in isReallyTriviallyReMaterializable.
404 let isReMaterializable = 1, isAsCheapAsAMove = 1 in
405 def ADDI : ALU_ri<0b000, "addi">;
407 def SLTI : ALU_ri<0b010, "slti">;
408 def SLTIU : ALU_ri<0b011, "sltiu">;
410 let isReMaterializable = 1, isAsCheapAsAMove = 1 in {
411 def XORI : ALU_ri<0b100, "xori">;
412 def ORI : ALU_ri<0b110, "ori">;
415 def ANDI : ALU_ri<0b111, "andi">;
417 def SLLI : Shift_ri<0, 0b001, "slli">;
418 def SRLI : Shift_ri<0, 0b101, "srli">;
419 def SRAI : Shift_ri<1, 0b101, "srai">;
421 def ADD : ALU_rr<0b0000000, 0b000, "add">;
422 def SUB : ALU_rr<0b0100000, 0b000, "sub">;
423 def SLL : ALU_rr<0b0000000, 0b001, "sll">;
424 def SLT : ALU_rr<0b0000000, 0b010, "slt">;
425 def SLTU : ALU_rr<0b0000000, 0b011, "sltu">;
426 def XOR : ALU_rr<0b0000000, 0b100, "xor">;
427 def SRL : ALU_rr<0b0000000, 0b101, "srl">;
428 def SRA : ALU_rr<0b0100000, 0b101, "sra">;
429 def OR : ALU_rr<0b0000000, 0b110, "or">;
430 def AND : ALU_rr<0b0000000, 0b111, "and">;
432 let hasSideEffects = 1, mayLoad = 0, mayStore = 0 in {
433 def FENCE : RVInstI<0b000, OPC_MISC_MEM, (outs),
434 (ins fencearg:$pred, fencearg:$succ),
435 "fence", "$pred, $succ"> {
441 let imm12 = {0b0000,pred,succ};
444 def FENCE_TSO : RVInstI<0b000, OPC_MISC_MEM, (outs), (ins), "fence.tso", ""> {
447 let imm12 = {0b1000,0b0011,0b0011};
450 def FENCE_I : RVInstI<0b001, OPC_MISC_MEM, (outs), (ins), "fence.i", ""> {
456 def ECALL : RVInstI<0b000, OPC_SYSTEM, (outs), (ins), "ecall", ""> {
462 def EBREAK : RVInstI<0b000, OPC_SYSTEM, (outs), (ins), "ebreak", ""> {
468 // This is a de facto standard (as set by GNU binutils) 32-bit unimplemented
469 // instruction (i.e., it should always trap, if your implementation has invalid
470 // instruction traps).
471 def UNIMP : RVInstI<0b001, OPC_SYSTEM, (outs), (ins), "unimp", ""> {
474 let imm12 = 0b110000000000;
476 } // hasSideEffects = 1, mayLoad = 0, mayStore = 0
478 def CSRRW : CSR_ir<0b001, "csrrw">;
479 def CSRRS : CSR_ir<0b010, "csrrs">;
480 def CSRRC : CSR_ir<0b011, "csrrc">;
482 def CSRRWI : CSR_ii<0b101, "csrrwi">;
483 def CSRRSI : CSR_ii<0b110, "csrrsi">;
484 def CSRRCI : CSR_ii<0b111, "csrrci">;
486 /// RV64I instructions
488 let Predicates = [IsRV64] in {
489 def LWU : Load_ri<0b110, "lwu">;
490 def LD : Load_ri<0b011, "ld">;
491 def SD : Store_rri<0b011, "sd">;
493 let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
494 def ADDIW : RVInstI<0b000, OPC_OP_IMM_32, (outs GPR:$rd),
495 (ins GPR:$rs1, simm12:$imm12),
496 "addiw", "$rd, $rs1, $imm12">;
498 def SLLIW : ShiftW_ri<0, 0b001, "slliw">;
499 def SRLIW : ShiftW_ri<0, 0b101, "srliw">;
500 def SRAIW : ShiftW_ri<1, 0b101, "sraiw">;
502 def ADDW : ALUW_rr<0b0000000, 0b000, "addw">;
503 def SUBW : ALUW_rr<0b0100000, 0b000, "subw">;
504 def SLLW : ALUW_rr<0b0000000, 0b001, "sllw">;
505 def SRLW : ALUW_rr<0b0000000, 0b101, "srlw">;
506 def SRAW : ALUW_rr<0b0100000, 0b101, "sraw">;
507 } // Predicates = [IsRV64]
509 //===----------------------------------------------------------------------===//
510 // Privileged instructions
511 //===----------------------------------------------------------------------===//
513 let isBarrier = 1, isReturn = 1, isTerminator = 1 in {
514 def URET : Priv<"uret", 0b0000000> {
520 def SRET : Priv<"sret", 0b0001000> {
526 def MRET : Priv<"mret", 0b0011000> {
531 } // isBarrier = 1, isReturn = 1, isTerminator = 1
533 def WFI : Priv<"wfi", 0b0001000> {
539 let hasSideEffects = 1, mayLoad = 0, mayStore = 0 in
540 def SFENCE_VMA : RVInstR<0b0001001, 0b000, OPC_SYSTEM, (outs),
541 (ins GPR:$rs1, GPR:$rs2),
542 "sfence.vma", "$rs1, $rs2"> {
546 //===----------------------------------------------------------------------===//
547 // Assembler Pseudo Instructions (User-Level ISA, Version 2.2, Chapter 20)
548 //===----------------------------------------------------------------------===//
550 def : InstAlias<"nop", (ADDI X0, X0, 0)>;
552 // Note that the size is 32 because up to 8 32-bit instructions are needed to
553 // generate an arbitrary 64-bit immediate. However, the size does not really
554 // matter since PseudoLI is currently only used in the AsmParser where it gets
555 // expanded to real instructions immediately.
556 let hasSideEffects = 0, mayLoad = 0, mayStore = 0, Size = 32,
557 isCodeGenOnly = 0, isAsmParserOnly = 1 in
558 def PseudoLI : Pseudo<(outs GPR:$rd), (ins ixlenimm_li:$imm), [],
561 def PseudoLB : PseudoLoad<"lb">;
562 def PseudoLBU : PseudoLoad<"lbu">;
563 def PseudoLH : PseudoLoad<"lh">;
564 def PseudoLHU : PseudoLoad<"lhu">;
565 def PseudoLW : PseudoLoad<"lw">;
567 def PseudoSB : PseudoStore<"sb">;
568 def PseudoSH : PseudoStore<"sh">;
569 def PseudoSW : PseudoStore<"sw">;
571 let Predicates = [IsRV64] in {
572 def PseudoLWU : PseudoLoad<"lwu">;
573 def PseudoLD : PseudoLoad<"ld">;
574 def PseudoSD : PseudoStore<"sd">;
575 } // Predicates = [IsRV64]
577 def : InstAlias<"mv $rd, $rs", (ADDI GPR:$rd, GPR:$rs, 0)>;
578 def : InstAlias<"not $rd, $rs", (XORI GPR:$rd, GPR:$rs, -1)>;
579 def : InstAlias<"neg $rd, $rs", (SUB GPR:$rd, X0, GPR:$rs)>;
581 let Predicates = [IsRV64] in {
582 def : InstAlias<"negw $rd, $rs", (SUBW GPR:$rd, X0, GPR:$rs)>;
583 def : InstAlias<"sext.w $rd, $rs", (ADDIW GPR:$rd, GPR:$rs, 0)>;
584 } // Predicates = [IsRV64]
586 def : InstAlias<"seqz $rd, $rs", (SLTIU GPR:$rd, GPR:$rs, 1)>;
587 def : InstAlias<"snez $rd, $rs", (SLTU GPR:$rd, X0, GPR:$rs)>;
588 def : InstAlias<"sltz $rd, $rs", (SLT GPR:$rd, GPR:$rs, X0)>;
589 def : InstAlias<"sgtz $rd, $rs", (SLT GPR:$rd, X0, GPR:$rs)>;
591 // sgt/sgtu are recognised by the GNU assembler but the canonical slt/sltu
592 // form will always be printed. Therefore, set a zero weight.
593 def : InstAlias<"sgt $rd, $rs, $rt", (SLT GPR:$rd, GPR:$rt, GPR:$rs), 0>;
594 def : InstAlias<"sgtu $rd, $rs, $rt", (SLTU GPR:$rd, GPR:$rt, GPR:$rs), 0>;
596 def : InstAlias<"beqz $rs, $offset",
597 (BEQ GPR:$rs, X0, simm13_lsb0:$offset)>;
598 def : InstAlias<"bnez $rs, $offset",
599 (BNE GPR:$rs, X0, simm13_lsb0:$offset)>;
600 def : InstAlias<"blez $rs, $offset",
601 (BGE X0, GPR:$rs, simm13_lsb0:$offset)>;
602 def : InstAlias<"bgez $rs, $offset",
603 (BGE GPR:$rs, X0, simm13_lsb0:$offset)>;
604 def : InstAlias<"bltz $rs, $offset",
605 (BLT GPR:$rs, X0, simm13_lsb0:$offset)>;
606 def : InstAlias<"bgtz $rs, $offset",
607 (BLT X0, GPR:$rs, simm13_lsb0:$offset)>;
609 // Always output the canonical mnemonic for the pseudo branch instructions.
610 // The GNU tools emit the canonical mnemonic for the branch pseudo instructions
611 // as well (e.g. "bgt" will be recognised by the assembler but never printed by
612 // objdump). Match this behaviour by setting a zero weight.
613 def : InstAlias<"bgt $rs, $rt, $offset",
614 (BLT GPR:$rt, GPR:$rs, simm13_lsb0:$offset), 0>;
615 def : InstAlias<"ble $rs, $rt, $offset",
616 (BGE GPR:$rt, GPR:$rs, simm13_lsb0:$offset), 0>;
617 def : InstAlias<"bgtu $rs, $rt, $offset",
618 (BLTU GPR:$rt, GPR:$rs, simm13_lsb0:$offset), 0>;
619 def : InstAlias<"bleu $rs, $rt, $offset",
620 (BGEU GPR:$rt, GPR:$rs, simm13_lsb0:$offset), 0>;
622 def : InstAlias<"j $offset", (JAL X0, simm21_lsb0_jal:$offset)>;
623 def : InstAlias<"jal $offset", (JAL X1, simm21_lsb0_jal:$offset)>;
625 // Non-zero offset aliases of "jalr" are the lowest weight, followed by the
626 // two-register form, then the one-register forms and finally "ret".
627 def : InstAlias<"jr $rs", (JALR X0, GPR:$rs, 0), 3>;
628 def : InstAlias<"jr ${offset}(${rs})", (JALR X0, GPR:$rs, simm12:$offset)>;
629 def : InstAlias<"jalr $rs", (JALR X1, GPR:$rs, 0), 3>;
630 def : InstAlias<"jalr ${offset}(${rs})", (JALR X1, GPR:$rs, simm12:$offset)>;
631 def : InstAlias<"jalr $rd, $rs", (JALR GPR:$rd, GPR:$rs, 0), 2>;
632 def : InstAlias<"ret", (JALR X0, X1, 0), 4>;
634 // Non-canonical forms for jump targets also accepted by the assembler.
635 def : InstAlias<"jr $rs, $offset", (JALR X0, GPR:$rs, simm12:$offset), 0>;
636 def : InstAlias<"jalr $rs, $offset", (JALR X1, GPR:$rs, simm12:$offset), 0>;
637 def : InstAlias<"jalr $rd, $rs, $offset", (JALR GPR:$rd, GPR:$rs, simm12:$offset), 0>;
639 def : InstAlias<"fence", (FENCE 0xF, 0xF)>; // 0xF == iorw
641 def : InstAlias<"rdinstret $rd", (CSRRS GPR:$rd, INSTRET.Encoding, X0)>;
642 def : InstAlias<"rdcycle $rd", (CSRRS GPR:$rd, CYCLE.Encoding, X0)>;
643 def : InstAlias<"rdtime $rd", (CSRRS GPR:$rd, TIME.Encoding, X0)>;
645 let Predicates = [IsRV32] in {
646 def : InstAlias<"rdinstreth $rd", (CSRRS GPR:$rd, INSTRETH.Encoding, X0)>;
647 def : InstAlias<"rdcycleh $rd", (CSRRS GPR:$rd, CYCLEH.Encoding, X0)>;
648 def : InstAlias<"rdtimeh $rd", (CSRRS GPR:$rd, TIMEH.Encoding, X0)>;
649 } // Predicates = [IsRV32]
651 def : InstAlias<"csrr $rd, $csr", (CSRRS GPR:$rd, csr_sysreg:$csr, X0)>;
652 def : InstAlias<"csrw $csr, $rs", (CSRRW X0, csr_sysreg:$csr, GPR:$rs)>;
653 def : InstAlias<"csrs $csr, $rs", (CSRRS X0, csr_sysreg:$csr, GPR:$rs)>;
654 def : InstAlias<"csrc $csr, $rs", (CSRRC X0, csr_sysreg:$csr, GPR:$rs)>;
656 def : InstAlias<"csrwi $csr, $imm", (CSRRWI X0, csr_sysreg:$csr, uimm5:$imm)>;
657 def : InstAlias<"csrsi $csr, $imm", (CSRRSI X0, csr_sysreg:$csr, uimm5:$imm)>;
658 def : InstAlias<"csrci $csr, $imm", (CSRRCI X0, csr_sysreg:$csr, uimm5:$imm)>;
660 let EmitPriority = 0 in {
661 def : InstAlias<"csrw $csr, $imm", (CSRRWI X0, csr_sysreg:$csr, uimm5:$imm)>;
662 def : InstAlias<"csrs $csr, $imm", (CSRRSI X0, csr_sysreg:$csr, uimm5:$imm)>;
663 def : InstAlias<"csrc $csr, $imm", (CSRRCI X0, csr_sysreg:$csr, uimm5:$imm)>;
665 def : InstAlias<"csrrw $rd, $csr, $imm", (CSRRWI GPR:$rd, csr_sysreg:$csr, uimm5:$imm)>;
666 def : InstAlias<"csrrs $rd, $csr, $imm", (CSRRSI GPR:$rd, csr_sysreg:$csr, uimm5:$imm)>;
667 def : InstAlias<"csrrc $rd, $csr, $imm", (CSRRCI GPR:$rd, csr_sysreg:$csr, uimm5:$imm)>;
670 def : InstAlias<"sfence.vma", (SFENCE_VMA X0, X0)>;
671 def : InstAlias<"sfence.vma $rs", (SFENCE_VMA GPR:$rs, X0)>;
673 let EmitPriority = 0 in {
674 def : InstAlias<"lb $rd, (${rs1})",
675 (LB GPR:$rd, GPR:$rs1, 0)>;
676 def : InstAlias<"lh $rd, (${rs1})",
677 (LH GPR:$rd, GPR:$rs1, 0)>;
678 def : InstAlias<"lw $rd, (${rs1})",
679 (LW GPR:$rd, GPR:$rs1, 0)>;
680 def : InstAlias<"lbu $rd, (${rs1})",
681 (LBU GPR:$rd, GPR:$rs1, 0)>;
682 def : InstAlias<"lhu $rd, (${rs1})",
683 (LHU GPR:$rd, GPR:$rs1, 0)>;
685 def : InstAlias<"sb $rs2, (${rs1})",
686 (SB GPR:$rs2, GPR:$rs1, 0)>;
687 def : InstAlias<"sh $rs2, (${rs1})",
688 (SH GPR:$rs2, GPR:$rs1, 0)>;
689 def : InstAlias<"sw $rs2, (${rs1})",
690 (SW GPR:$rs2, GPR:$rs1, 0)>;
692 def : InstAlias<"add $rd, $rs1, $imm12",
693 (ADDI GPR:$rd, GPR:$rs1, simm12:$imm12)>;
694 def : InstAlias<"and $rd, $rs1, $imm12",
695 (ANDI GPR:$rd, GPR:$rs1, simm12:$imm12)>;
696 def : InstAlias<"xor $rd, $rs1, $imm12",
697 (XORI GPR:$rd, GPR:$rs1, simm12:$imm12)>;
698 def : InstAlias<"or $rd, $rs1, $imm12",
699 (ORI GPR:$rd, GPR:$rs1, simm12:$imm12)>;
700 def : InstAlias<"sll $rd, $rs1, $shamt",
701 (SLLI GPR:$rd, GPR:$rs1, uimmlog2xlen:$shamt)>;
702 def : InstAlias<"srl $rd, $rs1, $shamt",
703 (SRLI GPR:$rd, GPR:$rs1, uimmlog2xlen:$shamt)>;
704 def : InstAlias<"sra $rd, $rs1, $shamt",
705 (SRAI GPR:$rd, GPR:$rs1, uimmlog2xlen:$shamt)>;
706 let Predicates = [IsRV64] in {
707 def : InstAlias<"lwu $rd, (${rs1})",
708 (LWU GPR:$rd, GPR:$rs1, 0)>;
709 def : InstAlias<"ld $rd, (${rs1})",
710 (LD GPR:$rd, GPR:$rs1, 0)>;
711 def : InstAlias<"sd $rs2, (${rs1})",
712 (SD GPR:$rs2, GPR:$rs1, 0)>;
714 def : InstAlias<"addw $rd, $rs1, $imm12",
715 (ADDIW GPR:$rd, GPR:$rs1, simm12:$imm12)>;
716 def : InstAlias<"sllw $rd, $rs1, $shamt",
717 (SLLIW GPR:$rd, GPR:$rs1, uimm5:$shamt)>;
718 def : InstAlias<"srlw $rd, $rs1, $shamt",
719 (SRLIW GPR:$rd, GPR:$rs1, uimm5:$shamt)>;
720 def : InstAlias<"sraw $rd, $rs1, $shamt",
721 (SRAIW GPR:$rd, GPR:$rs1, uimm5:$shamt)>;
722 } // Predicates = [IsRV64]
723 def : InstAlias<"slt $rd, $rs1, $imm12",
724 (SLTI GPR:$rd, GPR:$rs1, simm12:$imm12)>;
725 def : InstAlias<"sltu $rd, $rs1, $imm12",
726 (SLTIU GPR:$rd, GPR:$rs1, simm12:$imm12)>;
729 def : MnemonicAlias<"move", "mv">;
731 // The SCALL and SBREAK instructions wererenamed to ECALL and EBREAK in
732 // version 2.1 of the user-level ISA. Like the GNU toolchain, we still accept
733 // the old name for backwards compatibility.
734 def : MnemonicAlias<"scall", "ecall">;
735 def : MnemonicAlias<"sbreak", "ebreak">;
737 //===----------------------------------------------------------------------===//
738 // Pseudo-instructions and codegen patterns
740 // Naming convention: For 'generic' pattern classes, we use the naming
741 // convention PatTy1Ty2. For pattern classes which offer a more complex
742 // expension, prefix the class name, e.g. BccPat.
743 //===----------------------------------------------------------------------===//
745 /// Generic pattern classes
747 class PatGprGpr<SDPatternOperator OpNode, RVInst Inst>
748 : Pat<(OpNode GPR:$rs1, GPR:$rs2), (Inst GPR:$rs1, GPR:$rs2)>;
749 class PatGprSimm12<SDPatternOperator OpNode, RVInstI Inst>
750 : Pat<(OpNode GPR:$rs1, simm12:$imm12), (Inst GPR:$rs1, simm12:$imm12)>;
751 class PatGprUimmLog2XLen<SDPatternOperator OpNode, RVInstIShift Inst>
752 : Pat<(OpNode GPR:$rs1, uimmlog2xlen:$shamt),
753 (Inst GPR:$rs1, uimmlog2xlen:$shamt)>;
757 def IsOrAdd: PatFrag<(ops node:$A, node:$B), (or node:$A, node:$B), [{
758 return isOrEquivalentToAdd(N);
760 def assertsexti32 : PatFrag<(ops node:$src), (assertsext node:$src), [{
761 return cast<VTSDNode>(N->getOperand(1))->getVT() == MVT::i32;
763 def sexti32 : PatFrags<(ops node:$src),
764 [(sext_inreg node:$src, i32),
765 (assertsexti32 node:$src)]>;
766 def assertzexti32 : PatFrag<(ops node:$src), (assertzext node:$src), [{
767 return cast<VTSDNode>(N->getOperand(1))->getVT() == MVT::i32;
769 def zexti32 : PatFrags<(ops node:$src),
770 [(and node:$src, 0xffffffff),
771 (assertzexti32 node:$src)]>;
775 def : Pat<(simm12:$imm), (ADDI X0, simm12:$imm)>;
776 def : Pat<(simm32hi20:$imm), (LUI (HI20 imm:$imm))>;
777 def : Pat<(simm32:$imm), (ADDI (LUI (HI20 imm:$imm)), (LO12Sext imm:$imm))>,
780 /// Simple arithmetic operations
782 def : PatGprGpr<add, ADD>;
783 def : PatGprSimm12<add, ADDI>;
784 def : PatGprGpr<sub, SUB>;
785 def : PatGprGpr<or, OR>;
786 def : PatGprSimm12<or, ORI>;
787 def : PatGprGpr<and, AND>;
788 def : PatGprSimm12<and, ANDI>;
789 def : PatGprGpr<xor, XOR>;
790 def : PatGprSimm12<xor, XORI>;
791 def : PatGprUimmLog2XLen<shl, SLLI>;
792 def : PatGprUimmLog2XLen<srl, SRLI>;
793 def : PatGprUimmLog2XLen<sra, SRAI>;
795 // Match both a plain shift and one where the shift amount is masked (this is
796 // typically introduced when the legalizer promotes the shift amount and
797 // zero-extends it). For RISC-V, the mask is unnecessary as shifts in the base
798 // ISA only read the least significant 5 bits (RV32I) or 6 bits (RV64I).
799 class shiftop<SDPatternOperator operator>
800 : PatFrags<(ops node:$val, node:$count),
801 [(operator node:$val, node:$count),
802 (operator node:$val, (and node:$count, immbottomxlenset))]>;
804 def : PatGprGpr<shiftop<shl>, SLL>;
805 def : PatGprGpr<shiftop<srl>, SRL>;
806 def : PatGprGpr<shiftop<sra>, SRA>;
808 // This is a special case of the ADD instruction used to facilitate the use of a
809 // fourth operand to emit a relocation on a symbol relating to this instruction.
810 // The relocation does not affect any bits of the instruction itself but is used
811 // as a hint to the linker.
812 let hasSideEffects = 0, mayLoad = 0, mayStore = 0, isCodeGenOnly = 0 in
813 def PseudoAddTPRel : Pseudo<(outs GPR:$rd),
814 (ins GPR:$rs1, GPR:$rs2, tprel_add_symbol:$src), [],
815 "add", "$rd, $rs1, $rs2, $src">;
817 /// FrameIndex calculations
819 def : Pat<(add (i32 AddrFI:$Rs), simm12:$imm12),
820 (ADDI (i32 AddrFI:$Rs), simm12:$imm12)>;
821 def : Pat<(IsOrAdd (i32 AddrFI:$Rs), simm12:$imm12),
822 (ADDI (i32 AddrFI:$Rs), simm12:$imm12)>;
826 def : PatGprGpr<setlt, SLT>;
827 def : PatGprSimm12<setlt, SLTI>;
828 def : PatGprGpr<setult, SLTU>;
829 def : PatGprSimm12<setult, SLTIU>;
831 // Define pattern expansions for setcc operations that aren't directly
832 // handled by a RISC-V instruction.
833 def : Pat<(seteq GPR:$rs1, 0), (SLTIU GPR:$rs1, 1)>;
834 def : Pat<(seteq GPR:$rs1, GPR:$rs2), (SLTIU (XOR GPR:$rs1, GPR:$rs2), 1)>;
835 def : Pat<(seteq GPR:$rs1, simm12:$imm12),
836 (SLTIU (XORI GPR:$rs1, simm12:$imm12), 1)>;
837 def : Pat<(setne GPR:$rs1, 0), (SLTU X0, GPR:$rs1)>;
838 def : Pat<(setne GPR:$rs1, GPR:$rs2), (SLTU X0, (XOR GPR:$rs1, GPR:$rs2))>;
839 def : Pat<(setne GPR:$rs1, simm12:$imm12),
840 (SLTU X0, (XORI GPR:$rs1, simm12:$imm12))>;
841 def : Pat<(setugt GPR:$rs1, GPR:$rs2), (SLTU GPR:$rs2, GPR:$rs1)>;
842 def : Pat<(setuge GPR:$rs1, GPR:$rs2), (XORI (SLTU GPR:$rs1, GPR:$rs2), 1)>;
843 def : Pat<(setule GPR:$rs1, GPR:$rs2), (XORI (SLTU GPR:$rs2, GPR:$rs1), 1)>;
844 def : Pat<(setgt GPR:$rs1, GPR:$rs2), (SLT GPR:$rs2, GPR:$rs1)>;
845 def : Pat<(setge GPR:$rs1, GPR:$rs2), (XORI (SLT GPR:$rs1, GPR:$rs2), 1)>;
846 def : Pat<(setle GPR:$rs1, GPR:$rs2), (XORI (SLT GPR:$rs2, GPR:$rs1), 1)>;
848 let usesCustomInserter = 1 in
849 class SelectCC_rrirr<RegisterClass valty, RegisterClass cmpty>
850 : Pseudo<(outs valty:$dst),
851 (ins cmpty:$lhs, cmpty:$rhs, ixlenimm:$imm,
852 valty:$truev, valty:$falsev),
853 [(set valty:$dst, (riscv_selectcc cmpty:$lhs, cmpty:$rhs,
854 (XLenVT imm:$imm), valty:$truev, valty:$falsev))]>;
856 def Select_GPR_Using_CC_GPR : SelectCC_rrirr<GPR, GPR>;
858 /// Branches and jumps
860 // Match `(brcond (CondOp ..), ..)` and lower to the appropriate RISC-V branch
862 class BccPat<PatFrag CondOp, RVInstB Inst>
863 : Pat<(brcond (XLenVT (CondOp GPR:$rs1, GPR:$rs2)), bb:$imm12),
864 (Inst GPR:$rs1, GPR:$rs2, simm13_lsb0:$imm12)>;
866 def : BccPat<seteq, BEQ>;
867 def : BccPat<setne, BNE>;
868 def : BccPat<setlt, BLT>;
869 def : BccPat<setge, BGE>;
870 def : BccPat<setult, BLTU>;
871 def : BccPat<setuge, BGEU>;
873 class BccSwapPat<PatFrag CondOp, RVInst InstBcc>
874 : Pat<(brcond (XLenVT (CondOp GPR:$rs1, GPR:$rs2)), bb:$imm12),
875 (InstBcc GPR:$rs2, GPR:$rs1, bb:$imm12)>;
877 // Condition codes that don't have matching RISC-V branch instructions, but
878 // are trivially supported by swapping the two input operands
879 def : BccSwapPat<setgt, BLT>;
880 def : BccSwapPat<setle, BGE>;
881 def : BccSwapPat<setugt, BLTU>;
882 def : BccSwapPat<setule, BGEU>;
884 // An extra pattern is needed for a brcond without a setcc (i.e. where the
885 // condition was calculated elsewhere).
886 def : Pat<(brcond GPR:$cond, bb:$imm12), (BNE GPR:$cond, X0, bb:$imm12)>;
888 let isBarrier = 1, isBranch = 1, isTerminator = 1 in
889 def PseudoBR : Pseudo<(outs), (ins simm21_lsb0_jal:$imm20), [(br bb:$imm20)]>,
890 PseudoInstExpansion<(JAL X0, simm21_lsb0_jal:$imm20)>;
892 let isCall = 1, Defs=[X1] in
893 let isBarrier = 1, isBranch = 1, isIndirectBranch = 1, isTerminator = 1 in
894 def PseudoBRIND : Pseudo<(outs), (ins GPR:$rs1, simm12:$imm12), []>,
895 PseudoInstExpansion<(JALR X0, GPR:$rs1, simm12:$imm12)>;
897 def : Pat<(brind GPR:$rs1), (PseudoBRIND GPR:$rs1, 0)>;
898 def : Pat<(brind (add GPR:$rs1, simm12:$imm12)),
899 (PseudoBRIND GPR:$rs1, simm12:$imm12)>;
901 // PseudoCALLReg is a generic pseudo instruction for calls which will eventually
902 // expand to auipc and jalr while encoding, with any given register used as the
904 // Define AsmString to print "call" when compile with -S flag.
905 // Define isCodeGenOnly = 0 to support parsing assembly "call" instruction.
906 let isCall = 1, isBarrier = 1, isCodeGenOnly = 0, hasSideEffects = 0,
907 mayStore = 0, mayLoad = 0 in
908 def PseudoCALLReg : Pseudo<(outs GPR:$rd), (ins call_symbol:$func), []> {
909 let AsmString = "call\t$rd, $func";
912 // PseudoCALL is a pseudo instruction which will eventually expand to auipc
913 // and jalr while encoding. This is desirable, as an auipc+jalr pair with
914 // R_RISCV_CALL and R_RISCV_RELAX relocations can be be relaxed by the linker
915 // if the offset fits in a signed 21-bit immediate.
916 // Define AsmString to print "call" when compile with -S flag.
917 // Define isCodeGenOnly = 0 to support parsing assembly "call" instruction.
918 let isCall = 1, Defs = [X1], isCodeGenOnly = 0 in
919 def PseudoCALL : Pseudo<(outs), (ins call_symbol:$func), []> {
920 let AsmString = "call\t$func";
923 def : Pat<(riscv_call tglobaladdr:$func), (PseudoCALL tglobaladdr:$func)>;
924 def : Pat<(riscv_call texternalsym:$func), (PseudoCALL texternalsym:$func)>;
926 def : Pat<(riscv_uret_flag), (URET X0, X0)>;
927 def : Pat<(riscv_sret_flag), (SRET X0, X0)>;
928 def : Pat<(riscv_mret_flag), (MRET X0, X0)>;
930 let isCall = 1, Defs = [X1] in
931 def PseudoCALLIndirect : Pseudo<(outs), (ins GPR:$rs1),
932 [(riscv_call GPR:$rs1)]>,
933 PseudoInstExpansion<(JALR X1, GPR:$rs1, 0)>;
935 let isBarrier = 1, isReturn = 1, isTerminator = 1 in
936 def PseudoRET : Pseudo<(outs), (ins), [(riscv_ret_flag)]>,
937 PseudoInstExpansion<(JALR X0, X1, 0)>;
939 // PseudoTAIL is a pseudo instruction similar to PseudoCALL and will eventually
940 // expand to auipc and jalr while encoding.
941 // Define AsmString to print "tail" when compile with -S flag.
942 let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1, Uses = [X2],
944 def PseudoTAIL : Pseudo<(outs), (ins call_symbol:$dst), []> {
945 let AsmString = "tail\t$dst";
948 let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1, Uses = [X2] in
949 def PseudoTAILIndirect : Pseudo<(outs), (ins GPRTC:$rs1),
950 [(riscv_tail GPRTC:$rs1)]>,
951 PseudoInstExpansion<(JALR X0, GPR:$rs1, 0)>;
953 def : Pat<(riscv_tail (iPTR tglobaladdr:$dst)),
954 (PseudoTAIL texternalsym:$dst)>;
955 def : Pat<(riscv_tail (iPTR texternalsym:$dst)),
956 (PseudoTAIL texternalsym:$dst)>;
958 let hasSideEffects = 0, mayLoad = 0, mayStore = 0, isCodeGenOnly = 0,
959 isAsmParserOnly = 1 in
960 def PseudoLLA : Pseudo<(outs GPR:$dst), (ins bare_symbol:$src), [],
961 "lla", "$dst, $src">;
963 let hasSideEffects = 0, mayLoad = 1, mayStore = 0, isCodeGenOnly = 0,
964 isAsmParserOnly = 1 in
965 def PseudoLA : Pseudo<(outs GPR:$dst), (ins bare_symbol:$src), [],
968 let hasSideEffects = 0, mayLoad = 1, mayStore = 0, isCodeGenOnly = 0,
969 isAsmParserOnly = 1 in
970 def PseudoLA_TLS_IE : Pseudo<(outs GPR:$dst), (ins bare_symbol:$src), [],
971 "la.tls.ie", "$dst, $src">;
973 let hasSideEffects = 0, mayLoad = 1, mayStore = 0, isCodeGenOnly = 0,
974 isAsmParserOnly = 1 in
975 def PseudoLA_TLS_GD : Pseudo<(outs GPR:$dst), (ins bare_symbol:$src), [],
976 "la.tls.gd", "$dst, $src">;
980 multiclass LdPat<PatFrag LoadOp, RVInst Inst> {
981 def : Pat<(LoadOp GPR:$rs1), (Inst GPR:$rs1, 0)>;
982 def : Pat<(LoadOp AddrFI:$rs1), (Inst AddrFI:$rs1, 0)>;
983 def : Pat<(LoadOp (add GPR:$rs1, simm12:$imm12)),
984 (Inst GPR:$rs1, simm12:$imm12)>;
985 def : Pat<(LoadOp (add AddrFI:$rs1, simm12:$imm12)),
986 (Inst AddrFI:$rs1, simm12:$imm12)>;
987 def : Pat<(LoadOp (IsOrAdd AddrFI:$rs1, simm12:$imm12)),
988 (Inst AddrFI:$rs1, simm12:$imm12)>;
991 defm : LdPat<sextloadi8, LB>;
992 defm : LdPat<extloadi8, LB>;
993 defm : LdPat<sextloadi16, LH>;
994 defm : LdPat<extloadi16, LH>;
995 defm : LdPat<load, LW>, Requires<[IsRV32]>;
996 defm : LdPat<zextloadi8, LBU>;
997 defm : LdPat<zextloadi16, LHU>;
1001 multiclass StPat<PatFrag StoreOp, RVInst Inst, RegisterClass StTy> {
1002 def : Pat<(StoreOp StTy:$rs2, GPR:$rs1), (Inst StTy:$rs2, GPR:$rs1, 0)>;
1003 def : Pat<(StoreOp StTy:$rs2, AddrFI:$rs1), (Inst StTy:$rs2, AddrFI:$rs1, 0)>;
1004 def : Pat<(StoreOp StTy:$rs2, (add GPR:$rs1, simm12:$imm12)),
1005 (Inst StTy:$rs2, GPR:$rs1, simm12:$imm12)>;
1006 def : Pat<(StoreOp StTy:$rs2, (add AddrFI:$rs1, simm12:$imm12)),
1007 (Inst StTy:$rs2, AddrFI:$rs1, simm12:$imm12)>;
1008 def : Pat<(StoreOp StTy:$rs2, (IsOrAdd AddrFI:$rs1, simm12:$imm12)),
1009 (Inst StTy:$rs2, AddrFI:$rs1, simm12:$imm12)>;
1012 defm : StPat<truncstorei8, SB, GPR>;
1013 defm : StPat<truncstorei16, SH, GPR>;
1014 defm : StPat<store, SW, GPR>, Requires<[IsRV32]>;
1018 // Refer to Table A.6 in the version 2.3 draft of the RISC-V Instruction Set
1019 // Manual: Volume I.
1021 // fence acquire -> fence r, rw
1022 def : Pat<(atomic_fence (XLenVT 4), (timm)), (FENCE 0b10, 0b11)>;
1023 // fence release -> fence rw, w
1024 def : Pat<(atomic_fence (XLenVT 5), (timm)), (FENCE 0b11, 0b1)>;
1025 // fence acq_rel -> fence.tso
1026 def : Pat<(atomic_fence (XLenVT 6), (timm)), (FENCE_TSO)>;
1027 // fence seq_cst -> fence rw, rw
1028 def : Pat<(atomic_fence (XLenVT 7), (timm)), (FENCE 0b11, 0b11)>;
1030 // Lowering for atomic load and store is defined in RISCVInstrInfoA.td.
1031 // Although these are lowered to fence+load/store instructions defined in the
1032 // base RV32I/RV64I ISA, this lowering is only used when the A extension is
1033 // present. This is necessary as it isn't valid to mix __atomic_* libcalls
1034 // with inline atomic operations for the same object.
1036 /// Other pseudo-instructions
1038 // Pessimistically assume the stack pointer will be clobbered
1039 let Defs = [X2], Uses = [X2] in {
1040 def ADJCALLSTACKDOWN : Pseudo<(outs), (ins i32imm:$amt1, i32imm:$amt2),
1041 [(callseq_start timm:$amt1, timm:$amt2)]>;
1042 def ADJCALLSTACKUP : Pseudo<(outs), (ins i32imm:$amt1, i32imm:$amt2),
1043 [(callseq_end timm:$amt1, timm:$amt2)]>;
1044 } // Defs = [X2], Uses = [X2]
1048 let Predicates = [IsRV64] in {
1052 def : Pat<(sext_inreg GPR:$rs1, i32), (ADDIW GPR:$rs1, 0)>;
1053 def : Pat<(and GPR:$rs1, 0xffffffff), (SRLI (SLLI GPR:$rs1, 32), 32)>;
1057 def : Pat<(sext_inreg (add GPR:$rs1, GPR:$rs2), i32),
1058 (ADDW GPR:$rs1, GPR:$rs2)>;
1059 def : Pat<(sext_inreg (add GPR:$rs1, simm12:$imm12), i32),
1060 (ADDIW GPR:$rs1, simm12:$imm12)>;
1061 def : Pat<(sext_inreg (sub GPR:$rs1, GPR:$rs2), i32),
1062 (SUBW GPR:$rs1, GPR:$rs2)>;
1063 def : Pat<(sext_inreg (shl GPR:$rs1, uimm5:$shamt), i32),
1064 (SLLIW GPR:$rs1, uimm5:$shamt)>;
1065 // (srl (zexti32 ...), uimm5:$shamt) is matched with custom code due to the
1066 // need to undo manipulation of the mask value performed by DAGCombine.
1067 def : Pat<(sra (sext_inreg GPR:$rs1, i32), uimm5:$shamt),
1068 (SRAIW GPR:$rs1, uimm5:$shamt)>;
1070 def : PatGprGpr<riscv_sllw, SLLW>;
1071 def : PatGprGpr<riscv_srlw, SRLW>;
1072 def : PatGprGpr<riscv_sraw, SRAW>;
1076 defm : LdPat<sextloadi32, LW>;
1077 defm : LdPat<extloadi32, LW>;
1078 defm : LdPat<zextloadi32, LWU>;
1079 defm : LdPat<load, LD>;
1083 defm : StPat<truncstorei32, SW, GPR>;
1084 defm : StPat<store, SD, GPR>;
1085 } // Predicates = [IsRV64]
1087 /// readcyclecounter
1088 // On RV64, we can directly read the 64-bit "cycle" CSR.
1089 let Predicates = [IsRV64] in
1090 def : Pat<(readcyclecounter), (CSRRS CYCLE.Encoding, X0)>;
1091 // On RV32, ReadCycleWide will be expanded to the suggested loop reading both
1092 // halves of the 64-bit "cycle" CSR.
1093 let Predicates = [IsRV32], usesCustomInserter = 1, hasSideEffects = 0,
1094 mayLoad = 0, mayStore = 0, hasNoSchedulingInfo = 1 in
1095 def ReadCycleWide : Pseudo<(outs GPR:$lo, GPR:$hi), (ins), [], "", "">;
1099 // We lower `trap` to `unimp`, as this causes a hard exception on nearly all
1101 def : Pat<(trap), (UNIMP)>;
1103 // We lower `debugtrap` to `ebreak`, as this will get the attention of the
1104 // debugger if possible.
1105 def : Pat<(debugtrap), (EBREAK)>;
1107 //===----------------------------------------------------------------------===//
1108 // Standard extensions
1109 //===----------------------------------------------------------------------===//
1111 include "RISCVInstrInfoM.td"
1112 include "RISCVInstrInfoA.td"
1113 include "RISCVInstrInfoF.td"
1114 include "RISCVInstrInfoD.td"
1115 include "RISCVInstrInfoC.td"