1//===-- RISCVInstrInfo.td - Target Description for RISCV ---*- tablegen -*-===//
2//
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
6//
7//===----------------------------------------------------------------------===//
8//
9// This file describes the RISC-V instructions in TableGen format.
10//
11//===----------------------------------------------------------------------===//
12
13//===----------------------------------------------------------------------===//
14// RISC-V specific DAG Nodes.
15//===----------------------------------------------------------------------===//
16
17// Target-independent type requirements, but with target-specific formats.
18def SDT_CallSeqStart : SDCallSeqStart<[SDTCisVT<0, i32>,
19                                       SDTCisVT<1, i32>]>;
20def SDT_CallSeqEnd   : SDCallSeqEnd<[SDTCisVT<0, i32>,
21                                     SDTCisVT<1, i32>]>;
22
23// Target-dependent type requirements.
24def SDT_RISCVCall     : SDTypeProfile<0, -1, [SDTCisVT<0, XLenVT>]>;
25def SDT_RISCVSelectCC : SDTypeProfile<1, 5, [SDTCisSameAs<1, 2>,
26                                             SDTCisSameAs<0, 4>,
27                                             SDTCisSameAs<4, 5>]>;
28def SDT_RISCVReadCycleWide : SDTypeProfile<2, 0, [SDTCisVT<0, i32>,
29                                                  SDTCisVT<1, i32>]>;
30
31// Target-independent nodes, but with target-specific formats.
32def callseq_start : SDNode<"ISD::CALLSEQ_START", SDT_CallSeqStart,
33                           [SDNPHasChain, SDNPOutGlue]>;
34def callseq_end   : SDNode<"ISD::CALLSEQ_END", SDT_CallSeqEnd,
35                           [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue]>;
36
37// Target-dependent nodes.
38def riscv_call      : SDNode<"RISCVISD::CALL", SDT_RISCVCall,
39                             [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue,
40                              SDNPVariadic]>;
41def riscv_ret_flag  : SDNode<"RISCVISD::RET_FLAG", SDTNone,
42                             [SDNPHasChain, SDNPOptInGlue, SDNPVariadic]>;
43def riscv_uret_flag : SDNode<"RISCVISD::URET_FLAG", SDTNone,
44                             [SDNPHasChain, SDNPOptInGlue]>;
45def riscv_sret_flag : SDNode<"RISCVISD::SRET_FLAG", SDTNone,
46                             [SDNPHasChain, SDNPOptInGlue]>;
47def riscv_mret_flag : SDNode<"RISCVISD::MRET_FLAG", SDTNone,
48                             [SDNPHasChain, SDNPOptInGlue]>;
49def riscv_selectcc  : SDNode<"RISCVISD::SELECT_CC", SDT_RISCVSelectCC>;
50def riscv_tail      : SDNode<"RISCVISD::TAIL", SDT_RISCVCall,
51                             [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue,
52                              SDNPVariadic]>;
53def riscv_sllw      : SDNode<"RISCVISD::SLLW", SDTIntShiftOp>;
54def riscv_sraw      : SDNode<"RISCVISD::SRAW", SDTIntShiftOp>;
55def riscv_srlw      : SDNode<"RISCVISD::SRLW", SDTIntShiftOp>;
56
57def riscv_read_cycle_wide : SDNode<"RISCVISD::READ_CYCLE_WIDE",
58                                   SDT_RISCVReadCycleWide,
59                                   [SDNPHasChain, SDNPSideEffect]>;
60
61//===----------------------------------------------------------------------===//
62// Operand and SDNode transformation definitions.
63//===----------------------------------------------------------------------===//
64
65class ImmXLenAsmOperand<string prefix, string suffix = ""> : AsmOperandClass {
66  let Name = prefix # "ImmXLen" # suffix;
67  let RenderMethod = "addImmOperands";
68  let DiagnosticType = !strconcat("Invalid", Name);
69}
70
71class ImmAsmOperand<string prefix, int width, string suffix> : AsmOperandClass {
72  let Name = prefix # "Imm" # width # suffix;
73  let RenderMethod = "addImmOperands";
74  let DiagnosticType = !strconcat("Invalid", Name);
75}
76
77def ImmZeroAsmOperand : AsmOperandClass {
78  let Name = "ImmZero";
79  let RenderMethod = "addImmOperands";
80  let DiagnosticType = !strconcat("Invalid", Name);
81}
82
83class SImmAsmOperand<int width, string suffix = "">
84    : ImmAsmOperand<"S", width, suffix> {
85}
86
87class UImmAsmOperand<int width, string suffix = "">
88    : ImmAsmOperand<"U", width, suffix> {
89}
90
91def FenceArg : AsmOperandClass {
92  let Name = "FenceArg";
93  let RenderMethod = "addFenceArgOperands";
94  let DiagnosticType = "InvalidFenceArg";
95}
96
97def fencearg : Operand<XLenVT> {
98  let ParserMatchClass = FenceArg;
99  let PrintMethod = "printFenceArg";
100  let DecoderMethod = "decodeUImmOperand<4>";
101  let OperandType = "OPERAND_UIMM4";
102  let OperandNamespace = "RISCVOp";
103}
104
105def UImmLog2XLenAsmOperand : AsmOperandClass {
106  let Name = "UImmLog2XLen";
107  let RenderMethod = "addImmOperands";
108  let DiagnosticType = "InvalidUImmLog2XLen";
109}
110
111def uimmlog2xlen : Operand<XLenVT>, ImmLeaf<XLenVT, [{
112  if (Subtarget->is64Bit())
113    return isUInt<6>(Imm);
114  return isUInt<5>(Imm);
115}]> {
116  let ParserMatchClass = UImmLog2XLenAsmOperand;
117  // TODO: should ensure invalid shamt is rejected when decoding.
118  let DecoderMethod = "decodeUImmOperand<6>";
119  let MCOperandPredicate = [{
120    int64_t Imm;
121    if (!MCOp.evaluateAsConstantImm(Imm))
122      return false;
123    if (STI.getTargetTriple().isArch64Bit())
124      return  isUInt<6>(Imm);
125    return isUInt<5>(Imm);
126  }];
127  let OperandType = "OPERAND_UIMMLOG2XLEN";
128  let OperandNamespace = "RISCVOp";
129}
130
131def uimm5 : Operand<XLenVT>, ImmLeaf<XLenVT, [{return isUInt<5>(Imm);}]> {
132  let ParserMatchClass = UImmAsmOperand<5>;
133  let DecoderMethod = "decodeUImmOperand<5>";
134  let OperandType = "OPERAND_UIMM5";
135  let OperandNamespace = "RISCVOp";
136}
137
138def simm12 : Operand<XLenVT>, ImmLeaf<XLenVT, [{return isInt<12>(Imm);}]> {
139  let ParserMatchClass = SImmAsmOperand<12>;
140  let EncoderMethod = "getImmOpValue";
141  let DecoderMethod = "decodeSImmOperand<12>";
142  let MCOperandPredicate = [{
143    int64_t Imm;
144    if (MCOp.evaluateAsConstantImm(Imm))
145      return isInt<12>(Imm);
146    return MCOp.isBareSymbolRef();
147  }];
148  let OperandType = "OPERAND_SIMM12";
149  let OperandNamespace = "RISCVOp";
150}
151
152// A 12-bit signed immediate plus one where the imm range will be -2047~2048.
153def simm12_plus1 : Operand<XLenVT>, ImmLeaf<XLenVT,
154  [{return (isInt<12>(Imm) && Imm != -2048) || Imm == 2048;}]> {
155  let ParserMatchClass = SImmAsmOperand<12>;
156  let EncoderMethod = "getImmOpValue";
157  let DecoderMethod = "decodeSImmOperand<12>";
158  let MCOperandPredicate = [{
159    int64_t Imm;
160    if (MCOp.evaluateAsConstantImm(Imm))
161      return (isInt<12>(Imm) && Imm != -2048) || Imm == 2048;
162    return MCOp.isBareSymbolRef();
163  }];
164}
165
166// A 13-bit signed immediate where the least significant bit is zero.
167def simm13_lsb0 : Operand<OtherVT> {
168  let ParserMatchClass = SImmAsmOperand<13, "Lsb0">;
169  let PrintMethod = "printBranchOperand";
170  let EncoderMethod = "getImmOpValueAsr1";
171  let DecoderMethod = "decodeSImmOperandAndLsl1<13>";
172  let MCOperandPredicate = [{
173    int64_t Imm;
174    if (MCOp.evaluateAsConstantImm(Imm))
175      return isShiftedInt<12, 1>(Imm);
176    return MCOp.isBareSymbolRef();
177  }];
178  let OperandType = "OPERAND_PCREL";
179}
180
181class UImm20Operand : Operand<XLenVT> {
182  let EncoderMethod = "getImmOpValue";
183  let DecoderMethod = "decodeUImmOperand<20>";
184  let MCOperandPredicate = [{
185    int64_t Imm;
186    if (MCOp.evaluateAsConstantImm(Imm))
187      return isUInt<20>(Imm);
188    return MCOp.isBareSymbolRef();
189  }];
190  let OperandType = "OPERAND_UIMM20";
191  let OperandNamespace = "RISCVOp";
192}
193
194def uimm20_lui : UImm20Operand {
195  let ParserMatchClass = UImmAsmOperand<20, "LUI">;
196}
197def uimm20_auipc : UImm20Operand {
198  let ParserMatchClass = UImmAsmOperand<20, "AUIPC">;
199}
200
201def Simm21Lsb0JALAsmOperand : SImmAsmOperand<21, "Lsb0JAL"> {
202  let ParserMethod = "parseJALOffset";
203}
204
205// A 21-bit signed immediate where the least significant bit is zero.
206def simm21_lsb0_jal : Operand<OtherVT> {
207  let ParserMatchClass = Simm21Lsb0JALAsmOperand;
208  let PrintMethod = "printBranchOperand";
209  let EncoderMethod = "getImmOpValueAsr1";
210  let DecoderMethod = "decodeSImmOperandAndLsl1<21>";
211  let MCOperandPredicate = [{
212    int64_t Imm;
213    if (MCOp.evaluateAsConstantImm(Imm))
214      return isShiftedInt<20, 1>(Imm);
215    return MCOp.isBareSymbolRef();
216  }];
217  let OperandType = "OPERAND_PCREL";
218}
219
220def BareSymbol : AsmOperandClass {
221  let Name = "BareSymbol";
222  let RenderMethod = "addImmOperands";
223  let DiagnosticType = "InvalidBareSymbol";
224  let ParserMethod = "parseBareSymbol";
225}
226
227// A bare symbol.
228def bare_symbol : Operand<XLenVT> {
229  let ParserMatchClass = BareSymbol;
230}
231
232def CallSymbol : AsmOperandClass {
233  let Name = "CallSymbol";
234  let RenderMethod = "addImmOperands";
235  let DiagnosticType = "InvalidCallSymbol";
236  let ParserMethod = "parseCallSymbol";
237}
238
239// A bare symbol used in call/tail only.
240def call_symbol : Operand<XLenVT> {
241  let ParserMatchClass = CallSymbol;
242}
243
244def PseudoJumpSymbol : AsmOperandClass {
245  let Name = "PseudoJumpSymbol";
246  let RenderMethod = "addImmOperands";
247  let DiagnosticType = "InvalidPseudoJumpSymbol";
248  let ParserMethod = "parsePseudoJumpSymbol";
249}
250
251// A bare symbol used for pseudo jumps only.
252def pseudo_jump_symbol : Operand<XLenVT> {
253  let ParserMatchClass = PseudoJumpSymbol;
254}
255
256def TPRelAddSymbol : AsmOperandClass {
257  let Name = "TPRelAddSymbol";
258  let RenderMethod = "addImmOperands";
259  let DiagnosticType = "InvalidTPRelAddSymbol";
260  let ParserMethod = "parseOperandWithModifier";
261}
262
263// A bare symbol with the %tprel_add variant.
264def tprel_add_symbol : Operand<XLenVT> {
265  let ParserMatchClass = TPRelAddSymbol;
266}
267
268def CSRSystemRegister : AsmOperandClass {
269  let Name = "CSRSystemRegister";
270  let ParserMethod = "parseCSRSystemRegister";
271  let DiagnosticType = "InvalidCSRSystemRegister";
272}
273
274def csr_sysreg : Operand<XLenVT> {
275  let ParserMatchClass = CSRSystemRegister;
276  let PrintMethod = "printCSRSystemRegister";
277  let DecoderMethod = "decodeUImmOperand<12>";
278  let OperandType = "OPERAND_UIMM12";
279  let OperandNamespace = "RISCVOp";
280}
281
282// A parameterized register class alternative to i32imm/i64imm from Target.td.
283def ixlenimm : Operand<XLenVT>;
284
285def ixlenimm_li : Operand<XLenVT> {
286  let ParserMatchClass = ImmXLenAsmOperand<"", "LI">;
287}
288
289// Standalone (codegen-only) immleaf patterns.
290def simm32     : ImmLeaf<XLenVT, [{return isInt<32>(Imm);}]>;
291def simm32hi20 : ImmLeaf<XLenVT, [{return isShiftedInt<20, 12>(Imm);}]>;
292// A mask value that won't affect significant shift bits.
293def immbottomxlenset : ImmLeaf<XLenVT, [{
294  if (Subtarget->is64Bit())
295    return countTrailingOnes<uint64_t>(Imm) >= 6;
296  return countTrailingOnes<uint64_t>(Imm) >= 5;
297}]>;
298
299// A 6-bit constant greater than 32.
300def uimm6gt32 : ImmLeaf<XLenVT, [{
301  return isUInt<6>(Imm) && Imm > 32;
302}]>;
303
304// Addressing modes.
305// Necessary because a frameindex can't be matched directly in a pattern.
306def AddrFI : ComplexPattern<iPTR, 1, "SelectAddrFI", [frameindex], []>;
307
308// Extract least significant 12 bits from an immediate value and sign extend
309// them.
310def LO12Sext : SDNodeXForm<imm, [{
311  return CurDAG->getTargetConstant(SignExtend64<12>(N->getZExtValue()),
312                                   SDLoc(N), N->getValueType(0));
313}]>;
314
315// Extract the most significant 20 bits from an immediate value. Add 1 if bit
316// 11 is 1, to compensate for the low 12 bits in the matching immediate addi
317// or ld/st being negative.
318def HI20 : SDNodeXForm<imm, [{
319  return CurDAG->getTargetConstant(((N->getZExtValue()+0x800) >> 12) & 0xfffff,
320                                   SDLoc(N), N->getValueType(0));
321}]>;
322
323// Return the negation of an immediate value.
324def NegImm : SDNodeXForm<imm, [{
325  return CurDAG->getTargetConstant(-N->getSExtValue(), SDLoc(N),
326                                   N->getValueType(0));
327}]>;
328
329// Return an immediate value minus 32.
330def ImmSub32 : SDNodeXForm<imm, [{
331  return CurDAG->getTargetConstant(N->getSExtValue() - 32, SDLoc(N),
332                                   N->getValueType(0));
333}]>;
334
335// Return an immediate subtracted from XLen.
336def ImmSubFromXLen : SDNodeXForm<imm, [{
337  uint64_t XLen = Subtarget->getXLen();
338  return CurDAG->getTargetConstant(XLen - N->getZExtValue(), SDLoc(N),
339                                   N->getValueType(0));
340}]>;
341
342// Return an immediate subtracted from 32.
343def ImmSubFrom32 : SDNodeXForm<imm, [{
344  return CurDAG->getTargetConstant(32 - N->getZExtValue(), SDLoc(N),
345                                   N->getValueType(0));
346}]>;
347
348//===----------------------------------------------------------------------===//
349// Instruction Formats
350//===----------------------------------------------------------------------===//
351
352include "RISCVInstrFormats.td"
353
354//===----------------------------------------------------------------------===//
355// Instruction Class Templates
356//===----------------------------------------------------------------------===//
357
358let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
359class BranchCC_rri<bits<3> funct3, string opcodestr>
360    : RVInstB<funct3, OPC_BRANCH, (outs),
361              (ins GPR:$rs1, GPR:$rs2, simm13_lsb0:$imm12),
362              opcodestr, "$rs1, $rs2, $imm12">,
363      Sched<[WriteJmp, ReadJmp, ReadJmp]> {
364  let isBranch = 1;
365  let isTerminator = 1;
366}
367
368let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in
369class Load_ri<bits<3> funct3, string opcodestr>
370    : RVInstI<funct3, OPC_LOAD, (outs GPR:$rd), (ins GPR:$rs1, simm12:$imm12),
371              opcodestr, "$rd, ${imm12}(${rs1})">;
372
373// Operands for stores are in the order srcreg, base, offset rather than
374// reflecting the order these fields are specified in the instruction
375// encoding.
376let hasSideEffects = 0, mayLoad = 0, mayStore = 1 in
377class Store_rri<bits<3> funct3, string opcodestr>
378    : RVInstS<funct3, OPC_STORE, (outs),
379              (ins GPR:$rs2, GPR:$rs1, simm12:$imm12),
380              opcodestr, "$rs2, ${imm12}(${rs1})">;
381
382let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
383class ALU_ri<bits<3> funct3, string opcodestr>
384    : RVInstI<funct3, OPC_OP_IMM, (outs GPR:$rd), (ins GPR:$rs1, simm12:$imm12),
385              opcodestr, "$rd, $rs1, $imm12">,
386      Sched<[WriteIALU, ReadIALU]>;
387
388let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
389class Shift_ri<bit arithshift, bits<3> funct3, string opcodestr>
390    : RVInstIShift<arithshift, funct3, OPC_OP_IMM, (outs GPR:$rd),
391                   (ins GPR:$rs1, uimmlog2xlen:$shamt), opcodestr,
392                   "$rd, $rs1, $shamt">,
393      Sched<[WriteShift, ReadShift]>;
394
395let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
396class ALU_rr<bits<7> funct7, bits<3> funct3, string opcodestr>
397    : RVInstR<funct7, funct3, OPC_OP, (outs GPR:$rd), (ins GPR:$rs1, GPR:$rs2),
398              opcodestr, "$rd, $rs1, $rs2">;
399
400let hasNoSchedulingInfo = 1,
401    hasSideEffects = 1, mayLoad = 0, mayStore = 0 in
402class CSR_ir<bits<3> funct3, string opcodestr>
403    : RVInstI<funct3, OPC_SYSTEM, (outs GPR:$rd), (ins csr_sysreg:$imm12, GPR:$rs1),
404              opcodestr, "$rd, $imm12, $rs1">, Sched<[WriteCSR, ReadCSR]>;
405
406let hasNoSchedulingInfo = 1,
407    hasSideEffects = 1, mayLoad = 0, mayStore = 0 in
408class CSR_ii<bits<3> funct3, string opcodestr>
409    : RVInstI<funct3, OPC_SYSTEM, (outs GPR:$rd),
410              (ins csr_sysreg:$imm12, uimm5:$rs1),
411              opcodestr, "$rd, $imm12, $rs1">, Sched<[WriteCSR]>;
412
413let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
414class ShiftW_ri<bit arithshift, bits<3> funct3, string opcodestr>
415    : RVInstIShiftW<arithshift, funct3, OPC_OP_IMM_32, (outs GPR:$rd),
416                    (ins GPR:$rs1, uimm5:$shamt), opcodestr,
417                    "$rd, $rs1, $shamt">,
418      Sched<[WriteShift32, ReadShift32]>;
419
420let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
421class ALUW_rr<bits<7> funct7, bits<3> funct3, string opcodestr>
422    : RVInstR<funct7, funct3, OPC_OP_32, (outs GPR:$rd),
423              (ins GPR:$rs1, GPR:$rs2), opcodestr, "$rd, $rs1, $rs2">;
424
425let hasSideEffects = 1, mayLoad = 0, mayStore = 0 in
426class Priv<string opcodestr, bits<7> funct7>
427    : RVInstR<funct7, 0b000, OPC_SYSTEM, (outs), (ins GPR:$rs1, GPR:$rs2),
428              opcodestr, "">;
429
430//===----------------------------------------------------------------------===//
431// Instructions
432//===----------------------------------------------------------------------===//
433
434let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in {
435let isReMaterializable = 1, isAsCheapAsAMove = 1 in
436def LUI : RVInstU<OPC_LUI, (outs GPR:$rd), (ins uimm20_lui:$imm20),
437                  "lui", "$rd, $imm20">, Sched<[WriteIALU]>;
438
439def AUIPC : RVInstU<OPC_AUIPC, (outs GPR:$rd), (ins uimm20_auipc:$imm20),
440                    "auipc", "$rd, $imm20">, Sched<[WriteIALU]>;
441
442let isCall = 1 in
443def JAL : RVInstJ<OPC_JAL, (outs GPR:$rd), (ins simm21_lsb0_jal:$imm20),
444                  "jal", "$rd, $imm20">, Sched<[WriteJal]>;
445
446let isCall = 1 in
447def JALR : RVInstI<0b000, OPC_JALR, (outs GPR:$rd),
448                   (ins GPR:$rs1, simm12:$imm12),
449                   "jalr", "$rd, ${imm12}(${rs1})">,
450           Sched<[WriteJalr, ReadJalr]>;
451} // hasSideEffects = 0, mayLoad = 0, mayStore = 0
452
453def BEQ  : BranchCC_rri<0b000, "beq">;
454def BNE  : BranchCC_rri<0b001, "bne">;
455def BLT  : BranchCC_rri<0b100, "blt">;
456def BGE  : BranchCC_rri<0b101, "bge">;
457def BLTU : BranchCC_rri<0b110, "bltu">;
458def BGEU : BranchCC_rri<0b111, "bgeu">;
459
460def LB  : Load_ri<0b000, "lb">, Sched<[WriteLDB, ReadMemBase]>;
461def LH  : Load_ri<0b001, "lh">, Sched<[WriteLDH, ReadMemBase]>;
462def LW  : Load_ri<0b010, "lw">, Sched<[WriteLDW, ReadMemBase]>;
463def LBU : Load_ri<0b100, "lbu">, Sched<[WriteLDB, ReadMemBase]>;
464def LHU : Load_ri<0b101, "lhu">, Sched<[WriteLDH, ReadMemBase]>;
465
466def SB : Store_rri<0b000, "sb">, Sched<[WriteSTB, ReadStoreData, ReadMemBase]>;
467def SH : Store_rri<0b001, "sh">, Sched<[WriteSTH, ReadStoreData, ReadMemBase]>;
468def SW : Store_rri<0b010, "sw">, Sched<[WriteSTW, ReadStoreData, ReadMemBase]>;
469
470// ADDI isn't always rematerializable, but isReMaterializable will be used as
471// a hint which is verified in isReallyTriviallyReMaterializable.
472let isReMaterializable = 1, isAsCheapAsAMove = 1 in
473def ADDI  : ALU_ri<0b000, "addi">;
474
475def SLTI  : ALU_ri<0b010, "slti">;
476def SLTIU : ALU_ri<0b011, "sltiu">;
477
478let isReMaterializable = 1, isAsCheapAsAMove = 1 in {
479def XORI  : ALU_ri<0b100, "xori">;
480def ORI   : ALU_ri<0b110, "ori">;
481}
482
483def ANDI  : ALU_ri<0b111, "andi">;
484
485def SLLI : Shift_ri<0, 0b001, "slli">;
486def SRLI : Shift_ri<0, 0b101, "srli">;
487def SRAI : Shift_ri<1, 0b101, "srai">;
488
489def ADD  : ALU_rr<0b0000000, 0b000, "add">, Sched<[WriteIALU, ReadIALU, ReadIALU]>;
490def SUB  : ALU_rr<0b0100000, 0b000, "sub">, Sched<[WriteIALU, ReadIALU, ReadIALU]>;
491def SLL  : ALU_rr<0b0000000, 0b001, "sll">, Sched<[WriteIALU, ReadIALU, ReadIALU]>;
492def SLT  : ALU_rr<0b0000000, 0b010, "slt">, Sched<[WriteIALU, ReadIALU, ReadIALU]>;
493def SLTU : ALU_rr<0b0000000, 0b011, "sltu">, Sched<[WriteIALU, ReadIALU, ReadIALU]>;
494def XOR  : ALU_rr<0b0000000, 0b100, "xor">, Sched<[WriteIALU, ReadIALU, ReadIALU]>;
495def SRL  : ALU_rr<0b0000000, 0b101, "srl">, Sched<[WriteIALU, ReadIALU, ReadIALU]>;
496def SRA  : ALU_rr<0b0100000, 0b101, "sra">, Sched<[WriteIALU, ReadIALU, ReadIALU]>;
497def OR   : ALU_rr<0b0000000, 0b110, "or">, Sched<[WriteIALU, ReadIALU, ReadIALU]>;
498def AND  : ALU_rr<0b0000000, 0b111, "and">, Sched<[WriteIALU, ReadIALU, ReadIALU]>;
499
500let hasSideEffects = 1, mayLoad = 0, mayStore = 0 in {
501def FENCE : RVInstI<0b000, OPC_MISC_MEM, (outs),
502                    (ins fencearg:$pred, fencearg:$succ),
503                    "fence", "$pred, $succ">, Sched<[]> {
504  bits<4> pred;
505  bits<4> succ;
506
507  let rs1 = 0;
508  let rd = 0;
509  let imm12 = {0b0000,pred,succ};
510}
511
512def FENCE_TSO : RVInstI<0b000, OPC_MISC_MEM, (outs), (ins), "fence.tso", "">, Sched<[]> {
513  let rs1 = 0;
514  let rd = 0;
515  let imm12 = {0b1000,0b0011,0b0011};
516}
517
518def FENCE_I : RVInstI<0b001, OPC_MISC_MEM, (outs), (ins), "fence.i", "">, Sched<[]> {
519  let rs1 = 0;
520  let rd = 0;
521  let imm12 = 0;
522}
523
524def ECALL : RVInstI<0b000, OPC_SYSTEM, (outs), (ins), "ecall", "">, Sched<[WriteJmp]> {
525  let rs1 = 0;
526  let rd = 0;
527  let imm12 = 0;
528}
529
530def EBREAK : RVInstI<0b000, OPC_SYSTEM, (outs), (ins), "ebreak", "">,
531             Sched<[]> {
532  let rs1 = 0;
533  let rd = 0;
534  let imm12 = 1;
535}
536
537// This is a de facto standard (as set by GNU binutils) 32-bit unimplemented
538// instruction (i.e., it should always trap, if your implementation has invalid
539// instruction traps).
540def UNIMP : RVInstI<0b001, OPC_SYSTEM, (outs), (ins), "unimp", "">,
541            Sched<[]> {
542  let rs1 = 0;
543  let rd = 0;
544  let imm12 = 0b110000000000;
545}
546} // hasSideEffects = 1, mayLoad = 0, mayStore = 0
547
548def CSRRW : CSR_ir<0b001, "csrrw">;
549def CSRRS : CSR_ir<0b010, "csrrs">;
550def CSRRC : CSR_ir<0b011, "csrrc">;
551
552def CSRRWI : CSR_ii<0b101, "csrrwi">;
553def CSRRSI : CSR_ii<0b110, "csrrsi">;
554def CSRRCI : CSR_ii<0b111, "csrrci">;
555
556/// RV64I instructions
557
558let Predicates = [IsRV64] in {
559def LWU   : Load_ri<0b110, "lwu">, Sched<[WriteLDWU, ReadMemBase]>;
560def LD    : Load_ri<0b011, "ld">, Sched<[WriteLDD, ReadMemBase]>;
561def SD    : Store_rri<0b011, "sd">, Sched<[WriteSTD, ReadStoreData, ReadMemBase]>;
562
563let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
564def ADDIW : RVInstI<0b000, OPC_OP_IMM_32, (outs GPR:$rd),
565                    (ins GPR:$rs1, simm12:$imm12),
566                    "addiw", "$rd, $rs1, $imm12">,
567            Sched<[WriteIALU32, ReadIALU32]>;
568
569def SLLIW : ShiftW_ri<0, 0b001, "slliw">;
570def SRLIW : ShiftW_ri<0, 0b101, "srliw">;
571def SRAIW : ShiftW_ri<1, 0b101, "sraiw">;
572
573def ADDW  : ALUW_rr<0b0000000, 0b000, "addw">,
574            Sched<[WriteIALU32, ReadIALU32, ReadIALU32]>;
575def SUBW  : ALUW_rr<0b0100000, 0b000, "subw">,
576            Sched<[WriteIALU32, ReadIALU32, ReadIALU32]>;
577def SLLW  : ALUW_rr<0b0000000, 0b001, "sllw">,
578            Sched<[WriteIALU32, ReadIALU32, ReadIALU32]>;
579def SRLW  : ALUW_rr<0b0000000, 0b101, "srlw">,
580            Sched<[WriteIALU32, ReadIALU32, ReadIALU32]>;
581def SRAW  : ALUW_rr<0b0100000, 0b101, "sraw">,
582            Sched<[WriteIALU32, ReadIALU32, ReadIALU32]>;
583} // Predicates = [IsRV64]
584
585//===----------------------------------------------------------------------===//
586// Privileged instructions
587//===----------------------------------------------------------------------===//
588
589let isBarrier = 1, isReturn = 1, isTerminator = 1 in {
590def URET : Priv<"uret", 0b0000000>, Sched<[]> {
591  let rd = 0;
592  let rs1 = 0;
593  let rs2 = 0b00010;
594}
595
596def SRET : Priv<"sret", 0b0001000>, Sched<[]> {
597  let rd = 0;
598  let rs1 = 0;
599  let rs2 = 0b00010;
600}
601
602def MRET : Priv<"mret", 0b0011000>, Sched<[]> {
603  let rd = 0;
604  let rs1 = 0;
605  let rs2 = 0b00010;
606}
607} // isBarrier = 1, isReturn = 1, isTerminator = 1
608
609def WFI : Priv<"wfi", 0b0001000>, Sched<[]> {
610  let rd = 0;
611  let rs1 = 0;
612  let rs2 = 0b00101;
613}
614
615let hasSideEffects = 1, mayLoad = 0, mayStore = 0 in
616def SFENCE_VMA : RVInstR<0b0001001, 0b000, OPC_SYSTEM, (outs),
617                         (ins GPR:$rs1, GPR:$rs2),
618                         "sfence.vma", "$rs1, $rs2">, Sched<[]> {
619  let rd = 0;
620}
621
622//===----------------------------------------------------------------------===//
623// Debug instructions
624//===----------------------------------------------------------------------===//
625
626let isBarrier = 1, isReturn = 1, isTerminator = 1 in {
627def DRET : Priv<"dret", 0b0111101>, Sched<[]> {
628  let rd = 0;
629  let rs1 = 0;
630  let rs2 = 0b10010;
631}
632} // isBarrier = 1, isReturn = 1, isTerminator = 1
633
634//===----------------------------------------------------------------------===//
635// Assembler Pseudo Instructions (User-Level ISA, Version 2.2, Chapter 20)
636//===----------------------------------------------------------------------===//
637
638def : InstAlias<"nop",           (ADDI      X0,      X0,       0)>;
639
640// Note that the size is 32 because up to 8 32-bit instructions are needed to
641// generate an arbitrary 64-bit immediate. However, the size does not really
642// matter since PseudoLI is currently only used in the AsmParser where it gets
643// expanded to real instructions immediately.
644let hasSideEffects = 0, mayLoad = 0, mayStore = 0, Size = 32,
645    isCodeGenOnly = 0, isAsmParserOnly = 1 in
646def PseudoLI : Pseudo<(outs GPR:$rd), (ins ixlenimm_li:$imm), [],
647                      "li", "$rd, $imm">;
648
649def PseudoLB  : PseudoLoad<"lb">;
650def PseudoLBU : PseudoLoad<"lbu">;
651def PseudoLH  : PseudoLoad<"lh">;
652def PseudoLHU : PseudoLoad<"lhu">;
653def PseudoLW  : PseudoLoad<"lw">;
654
655def PseudoSB  : PseudoStore<"sb">;
656def PseudoSH  : PseudoStore<"sh">;
657def PseudoSW  : PseudoStore<"sw">;
658
659let Predicates = [IsRV64] in {
660def PseudoLWU : PseudoLoad<"lwu">;
661def PseudoLD  : PseudoLoad<"ld">;
662def PseudoSD  : PseudoStore<"sd">;
663} // Predicates = [IsRV64]
664
665def : InstAlias<"mv $rd, $rs",   (ADDI GPR:$rd, GPR:$rs,       0)>;
666def : InstAlias<"not $rd, $rs",  (XORI GPR:$rd, GPR:$rs,      -1)>;
667def : InstAlias<"neg $rd, $rs",  (SUB  GPR:$rd,      X0, GPR:$rs)>;
668
669let Predicates = [IsRV64] in {
670def : InstAlias<"negw $rd, $rs",   (SUBW  GPR:$rd,      X0, GPR:$rs)>;
671def : InstAlias<"sext.w $rd, $rs", (ADDIW GPR:$rd, GPR:$rs,       0)>;
672} // Predicates = [IsRV64]
673
674def : InstAlias<"seqz $rd, $rs", (SLTIU GPR:$rd, GPR:$rs,       1)>;
675def : InstAlias<"snez $rd, $rs", (SLTU  GPR:$rd,      X0, GPR:$rs)>;
676def : InstAlias<"sltz $rd, $rs", (SLT   GPR:$rd, GPR:$rs,      X0)>;
677def : InstAlias<"sgtz $rd, $rs", (SLT   GPR:$rd,      X0, GPR:$rs)>;
678
679// sgt/sgtu are recognised by the GNU assembler but the canonical slt/sltu
680// form will always be printed. Therefore, set a zero weight.
681def : InstAlias<"sgt $rd, $rs, $rt", (SLT GPR:$rd, GPR:$rt, GPR:$rs), 0>;
682def : InstAlias<"sgtu $rd, $rs, $rt", (SLTU GPR:$rd, GPR:$rt, GPR:$rs), 0>;
683
684def : InstAlias<"beqz $rs, $offset",
685                (BEQ GPR:$rs,      X0, simm13_lsb0:$offset)>;
686def : InstAlias<"bnez $rs, $offset",
687                (BNE GPR:$rs,      X0, simm13_lsb0:$offset)>;
688def : InstAlias<"blez $rs, $offset",
689                (BGE      X0, GPR:$rs, simm13_lsb0:$offset)>;
690def : InstAlias<"bgez $rs, $offset",
691                (BGE GPR:$rs,      X0, simm13_lsb0:$offset)>;
692def : InstAlias<"bltz $rs, $offset",
693                (BLT GPR:$rs,      X0, simm13_lsb0:$offset)>;
694def : InstAlias<"bgtz $rs, $offset",
695                (BLT      X0, GPR:$rs, simm13_lsb0:$offset)>;
696
697// Always output the canonical mnemonic for the pseudo branch instructions.
698// The GNU tools emit the canonical mnemonic for the branch pseudo instructions
699// as well (e.g. "bgt" will be recognised by the assembler but never printed by
700// objdump). Match this behaviour by setting a zero weight.
701def : InstAlias<"bgt $rs, $rt, $offset",
702                (BLT  GPR:$rt, GPR:$rs, simm13_lsb0:$offset), 0>;
703def : InstAlias<"ble $rs, $rt, $offset",
704                (BGE  GPR:$rt, GPR:$rs, simm13_lsb0:$offset), 0>;
705def : InstAlias<"bgtu $rs, $rt, $offset",
706                (BLTU GPR:$rt, GPR:$rs, simm13_lsb0:$offset), 0>;
707def : InstAlias<"bleu $rs, $rt, $offset",
708                (BGEU GPR:$rt, GPR:$rs, simm13_lsb0:$offset), 0>;
709
710def : InstAlias<"j $offset",   (JAL X0, simm21_lsb0_jal:$offset)>;
711def : InstAlias<"jal $offset", (JAL X1, simm21_lsb0_jal:$offset)>;
712
713// Non-zero offset aliases of "jalr" are the lowest weight, followed by the
714// two-register form, then the one-register forms and finally "ret".
715def : InstAlias<"jr $rs",                (JALR      X0, GPR:$rs, 0), 3>;
716def : InstAlias<"jr ${offset}(${rs})",   (JALR      X0, GPR:$rs, simm12:$offset)>;
717def : InstAlias<"jalr $rs",              (JALR      X1, GPR:$rs, 0), 3>;
718def : InstAlias<"jalr ${offset}(${rs})", (JALR      X1, GPR:$rs, simm12:$offset)>;
719def : InstAlias<"jalr $rd, $rs",         (JALR GPR:$rd, GPR:$rs, 0), 2>;
720def : InstAlias<"ret",                   (JALR      X0,      X1, 0), 4>;
721
722// Non-canonical forms for jump targets also accepted by the assembler.
723def : InstAlias<"jr $rs, $offset",        (JALR      X0, GPR:$rs, simm12:$offset), 0>;
724def : InstAlias<"jalr $rs, $offset",      (JALR      X1, GPR:$rs, simm12:$offset), 0>;
725def : InstAlias<"jalr $rd, $rs, $offset", (JALR GPR:$rd, GPR:$rs, simm12:$offset), 0>;
726
727def : InstAlias<"fence", (FENCE 0xF, 0xF)>; // 0xF == iorw
728
729def : InstAlias<"rdinstret $rd", (CSRRS GPR:$rd, INSTRET.Encoding, X0)>;
730def : InstAlias<"rdcycle $rd",   (CSRRS GPR:$rd, CYCLE.Encoding, X0)>;
731def : InstAlias<"rdtime $rd",    (CSRRS GPR:$rd, TIME.Encoding, X0)>;
732
733let Predicates = [IsRV32] in {
734def : InstAlias<"rdinstreth $rd", (CSRRS GPR:$rd, INSTRETH.Encoding, X0)>;
735def : InstAlias<"rdcycleh $rd",   (CSRRS GPR:$rd, CYCLEH.Encoding, X0)>;
736def : InstAlias<"rdtimeh $rd",    (CSRRS GPR:$rd, TIMEH.Encoding, X0)>;
737} // Predicates = [IsRV32]
738
739def : InstAlias<"csrr $rd, $csr", (CSRRS GPR:$rd, csr_sysreg:$csr,      X0)>;
740def : InstAlias<"csrw $csr, $rs", (CSRRW      X0, csr_sysreg:$csr, GPR:$rs)>;
741def : InstAlias<"csrs $csr, $rs", (CSRRS      X0, csr_sysreg:$csr, GPR:$rs)>;
742def : InstAlias<"csrc $csr, $rs", (CSRRC      X0, csr_sysreg:$csr, GPR:$rs)>;
743
744def : InstAlias<"csrwi $csr, $imm", (CSRRWI X0, csr_sysreg:$csr, uimm5:$imm)>;
745def : InstAlias<"csrsi $csr, $imm", (CSRRSI X0, csr_sysreg:$csr, uimm5:$imm)>;
746def : InstAlias<"csrci $csr, $imm", (CSRRCI X0, csr_sysreg:$csr, uimm5:$imm)>;
747
748let EmitPriority = 0 in {
749def : InstAlias<"csrw $csr, $imm", (CSRRWI X0, csr_sysreg:$csr, uimm5:$imm)>;
750def : InstAlias<"csrs $csr, $imm", (CSRRSI X0, csr_sysreg:$csr, uimm5:$imm)>;
751def : InstAlias<"csrc $csr, $imm", (CSRRCI X0, csr_sysreg:$csr, uimm5:$imm)>;
752
753def : InstAlias<"csrrw $rd, $csr, $imm", (CSRRWI GPR:$rd, csr_sysreg:$csr, uimm5:$imm)>;
754def : InstAlias<"csrrs $rd, $csr, $imm", (CSRRSI GPR:$rd, csr_sysreg:$csr, uimm5:$imm)>;
755def : InstAlias<"csrrc $rd, $csr, $imm", (CSRRCI GPR:$rd, csr_sysreg:$csr, uimm5:$imm)>;
756}
757
758def : InstAlias<"sfence.vma",     (SFENCE_VMA      X0, X0)>;
759def : InstAlias<"sfence.vma $rs", (SFENCE_VMA GPR:$rs, X0)>;
760
761let EmitPriority = 0 in {
762def : InstAlias<"lb $rd, (${rs1})",
763                (LB  GPR:$rd, GPR:$rs1, 0)>;
764def : InstAlias<"lh $rd, (${rs1})",
765                (LH  GPR:$rd, GPR:$rs1, 0)>;
766def : InstAlias<"lw $rd, (${rs1})",
767                (LW  GPR:$rd, GPR:$rs1, 0)>;
768def : InstAlias<"lbu $rd, (${rs1})",
769                (LBU  GPR:$rd, GPR:$rs1, 0)>;
770def : InstAlias<"lhu $rd, (${rs1})",
771                (LHU  GPR:$rd, GPR:$rs1, 0)>;
772
773def : InstAlias<"sb $rs2, (${rs1})",
774                (SB  GPR:$rs2, GPR:$rs1, 0)>;
775def : InstAlias<"sh $rs2, (${rs1})",
776                (SH  GPR:$rs2, GPR:$rs1, 0)>;
777def : InstAlias<"sw $rs2, (${rs1})",
778                (SW  GPR:$rs2, GPR:$rs1, 0)>;
779
780def : InstAlias<"add $rd, $rs1, $imm12",
781                (ADDI  GPR:$rd, GPR:$rs1, simm12:$imm12)>;
782def : InstAlias<"and $rd, $rs1, $imm12",
783                (ANDI  GPR:$rd, GPR:$rs1, simm12:$imm12)>;
784def : InstAlias<"xor $rd, $rs1, $imm12",
785                (XORI  GPR:$rd, GPR:$rs1, simm12:$imm12)>;
786def : InstAlias<"or $rd, $rs1, $imm12",
787                (ORI  GPR:$rd, GPR:$rs1, simm12:$imm12)>;
788def : InstAlias<"sll $rd, $rs1, $shamt",
789                (SLLI  GPR:$rd, GPR:$rs1, uimmlog2xlen:$shamt)>;
790def : InstAlias<"srl $rd, $rs1, $shamt",
791                (SRLI  GPR:$rd, GPR:$rs1, uimmlog2xlen:$shamt)>;
792def : InstAlias<"sra $rd, $rs1, $shamt",
793                (SRAI  GPR:$rd, GPR:$rs1, uimmlog2xlen:$shamt)>;
794let Predicates = [IsRV64] in {
795def : InstAlias<"lwu $rd, (${rs1})",
796                (LWU  GPR:$rd, GPR:$rs1, 0)>;
797def : InstAlias<"ld $rd, (${rs1})",
798                (LD  GPR:$rd, GPR:$rs1, 0)>;
799def : InstAlias<"sd $rs2, (${rs1})",
800                (SD  GPR:$rs2, GPR:$rs1, 0)>;
801
802def : InstAlias<"addw $rd, $rs1, $imm12",
803                (ADDIW  GPR:$rd, GPR:$rs1, simm12:$imm12)>;
804def : InstAlias<"sllw $rd, $rs1, $shamt",
805                (SLLIW  GPR:$rd, GPR:$rs1, uimm5:$shamt)>;
806def : InstAlias<"srlw $rd, $rs1, $shamt",
807                (SRLIW  GPR:$rd, GPR:$rs1, uimm5:$shamt)>;
808def : InstAlias<"sraw $rd, $rs1, $shamt",
809                (SRAIW  GPR:$rd, GPR:$rs1, uimm5:$shamt)>;
810} // Predicates = [IsRV64]
811def : InstAlias<"slt $rd, $rs1, $imm12",
812                (SLTI  GPR:$rd, GPR:$rs1, simm12:$imm12)>;
813def : InstAlias<"sltu $rd, $rs1, $imm12",
814                (SLTIU  GPR:$rd, GPR:$rs1, simm12:$imm12)>;
815}
816
817def : MnemonicAlias<"move", "mv">;
818
819// The SCALL and SBREAK instructions wererenamed to ECALL and EBREAK in
820// version 2.1 of the user-level ISA. Like the GNU toolchain, we still accept
821// the old name for backwards compatibility.
822def : MnemonicAlias<"scall", "ecall">;
823def : MnemonicAlias<"sbreak", "ebreak">;
824
825// This alias was added to the spec in December 2020. Don't print it by default
826// to allow assembly we print to be compatible with versions of GNU assembler
827// that don't support this alias.
828def : InstAlias<"zext.b $rd, $rs", (ANDI GPR:$rd, GPR:$rs, 0xFF), 0>;
829
830//===----------------------------------------------------------------------===//
831// Pseudo-instructions and codegen patterns
832//
833// Naming convention: For 'generic' pattern classes, we use the naming
834// convention PatTy1Ty2. For pattern classes which offer a more complex
835// expansion, prefix the class name, e.g. BccPat.
836//===----------------------------------------------------------------------===//
837
838/// Generic pattern classes
839
840class PatGprGpr<SDPatternOperator OpNode, RVInst Inst>
841    : Pat<(OpNode GPR:$rs1, GPR:$rs2), (Inst GPR:$rs1, GPR:$rs2)>;
842class PatGprSimm12<SDPatternOperator OpNode, RVInstI Inst>
843    : Pat<(OpNode GPR:$rs1, simm12:$imm12), (Inst GPR:$rs1, simm12:$imm12)>;
844class PatGprUimmLog2XLen<SDPatternOperator OpNode, RVInstIShift Inst>
845    : Pat<(OpNode GPR:$rs1, uimmlog2xlen:$shamt),
846          (Inst GPR:$rs1, uimmlog2xlen:$shamt)>;
847
848/// Predicates
849
850def IsOrAdd: PatFrag<(ops node:$A, node:$B), (or node:$A, node:$B), [{
851  return isOrEquivalentToAdd(N);
852}]>;
853def assertsexti32 : PatFrag<(ops node:$src), (assertsext node:$src), [{
854  return cast<VTSDNode>(N->getOperand(1))->getVT().bitsLE(MVT::i32);
855}]>;
856def sexti32 : PatFrags<(ops node:$src),
857                       [(sext_inreg node:$src, i32),
858                        (assertsexti32 node:$src)]>;
859def assertzexti32 : PatFrag<(ops node:$src), (assertzext node:$src), [{
860  return cast<VTSDNode>(N->getOperand(1))->getVT().bitsLE(MVT::i32);
861}]>;
862def zexti32 : PatFrags<(ops node:$src),
863                       [(and node:$src, 0xffffffff),
864                        (assertzexti32 node:$src)]>;
865
866def SRLIWPat : PatFrag<(ops node:$A, node:$B),
867                       (srl (and node:$A, imm), node:$B), [{
868  return MatchSRLIW(N);
869}]>;
870
871// Check that it is a SLLIUW (Shift Logical Left Immediate Unsigned i32
872// on RV64). Also used to optimize the same sequence without SLLIUW.
873def SLLIUWPat : PatFrag<(ops node:$A, node:$B),
874                        (and (shl node:$A, node:$B), imm), [{
875  return MatchSLLIUW(N);
876}]>;
877
878/// Immediates
879
880def : Pat<(simm12:$imm), (ADDI X0, simm12:$imm)>;
881def : Pat<(simm32hi20:$imm), (LUI (HI20 imm:$imm))>;
882def : Pat<(simm32:$imm), (ADDI (LUI (HI20 imm:$imm)), (LO12Sext imm:$imm))>,
883      Requires<[IsRV32]>;
884
885/// Simple arithmetic operations
886
887def : PatGprGpr<add, ADD>;
888def : PatGprSimm12<add, ADDI>;
889def : PatGprGpr<sub, SUB>;
890def : PatGprGpr<or, OR>;
891def : PatGprSimm12<or, ORI>;
892def : PatGprGpr<and, AND>;
893def : PatGprSimm12<and, ANDI>;
894def : PatGprGpr<xor, XOR>;
895def : PatGprSimm12<xor, XORI>;
896def : PatGprUimmLog2XLen<shl, SLLI>;
897def : PatGprUimmLog2XLen<srl, SRLI>;
898def : PatGprUimmLog2XLen<sra, SRAI>;
899
900// Match both a plain shift and one where the shift amount is masked (this is
901// typically introduced when the legalizer promotes the shift amount and
902// zero-extends it). For RISC-V, the mask is unnecessary as shifts in the base
903// ISA only read the least significant 5 bits (RV32I) or 6 bits (RV64I).
904class shiftop<SDPatternOperator operator>
905    : PatFrags<(ops node:$val, node:$count),
906               [(operator node:$val, node:$count),
907                (operator node:$val, (and node:$count, immbottomxlenset))]>;
908class shiftopw<SDPatternOperator operator>
909    : PatFrags<(ops node:$val, node:$count),
910               [(operator node:$val, node:$count),
911                (operator node:$val, (and node:$count, (XLenVT 31)))]>;
912
913def : PatGprGpr<shiftop<shl>, SLL>;
914def : PatGprGpr<shiftop<srl>, SRL>;
915def : PatGprGpr<shiftop<sra>, SRA>;
916
917// This is a special case of the ADD instruction used to facilitate the use of a
918// fourth operand to emit a relocation on a symbol relating to this instruction.
919// The relocation does not affect any bits of the instruction itself but is used
920// as a hint to the linker.
921let hasSideEffects = 0, mayLoad = 0, mayStore = 0, isCodeGenOnly = 0 in
922def PseudoAddTPRel : Pseudo<(outs GPR:$rd),
923                            (ins GPR:$rs1, GPR:$rs2, tprel_add_symbol:$src), [],
924                            "add", "$rd, $rs1, $rs2, $src">;
925
926/// FrameIndex calculations
927
928def : Pat<(add (XLenVT AddrFI:$Rs), simm12:$imm12),
929          (ADDI (XLenVT AddrFI:$Rs), simm12:$imm12)>;
930def : Pat<(IsOrAdd (XLenVT AddrFI:$Rs), simm12:$imm12),
931          (ADDI (XLenVT AddrFI:$Rs), simm12:$imm12)>;
932
933/// Setcc
934
935def : PatGprGpr<setlt, SLT>;
936def : PatGprSimm12<setlt, SLTI>;
937def : PatGprGpr<setult, SLTU>;
938def : PatGprSimm12<setult, SLTIU>;
939
940// Define pattern expansions for setcc operations that aren't directly
941// handled by a RISC-V instruction.
942def : Pat<(seteq GPR:$rs1, 0), (SLTIU GPR:$rs1, 1)>;
943def : Pat<(seteq GPR:$rs1, GPR:$rs2), (SLTIU (XOR GPR:$rs1, GPR:$rs2), 1)>;
944def : Pat<(seteq GPR:$rs1, simm12_plus1:$imm12),
945          (SLTIU (ADDI GPR:$rs1, (NegImm simm12_plus1:$imm12)), 1)>;
946def : Pat<(setne GPR:$rs1, 0), (SLTU X0, GPR:$rs1)>;
947def : Pat<(setne GPR:$rs1, GPR:$rs2), (SLTU X0, (XOR GPR:$rs1, GPR:$rs2))>;
948def : Pat<(setne GPR:$rs1, simm12_plus1:$imm12),
949          (SLTU X0, (ADDI GPR:$rs1, (NegImm simm12_plus1:$imm12)))>;
950def : Pat<(setugt GPR:$rs1, GPR:$rs2), (SLTU GPR:$rs2, GPR:$rs1)>;
951def : Pat<(setuge GPR:$rs1, GPR:$rs2), (XORI (SLTU GPR:$rs1, GPR:$rs2), 1)>;
952def : Pat<(setule GPR:$rs1, GPR:$rs2), (XORI (SLTU GPR:$rs2, GPR:$rs1), 1)>;
953def : Pat<(setgt GPR:$rs1, GPR:$rs2), (SLT GPR:$rs2, GPR:$rs1)>;
954def : Pat<(setge GPR:$rs1, GPR:$rs2), (XORI (SLT GPR:$rs1, GPR:$rs2), 1)>;
955def : Pat<(setle GPR:$rs1, GPR:$rs2), (XORI (SLT GPR:$rs2, GPR:$rs1), 1)>;
956
957let usesCustomInserter = 1 in
958class SelectCC_rrirr<RegisterClass valty, RegisterClass cmpty>
959    : Pseudo<(outs valty:$dst),
960             (ins cmpty:$lhs, cmpty:$rhs, ixlenimm:$imm,
961              valty:$truev, valty:$falsev),
962             [(set valty:$dst, (riscv_selectcc cmpty:$lhs, cmpty:$rhs,
963              (XLenVT imm:$imm), valty:$truev, valty:$falsev))]>;
964
965def Select_GPR_Using_CC_GPR : SelectCC_rrirr<GPR, GPR>;
966
967/// Branches and jumps
968
969// Match `(brcond (CondOp ..), ..)` and lower to the appropriate RISC-V branch
970// instruction.
971class BccPat<PatFrag CondOp, RVInstB Inst>
972    : Pat<(brcond (XLenVT (CondOp GPR:$rs1, GPR:$rs2)), bb:$imm12),
973          (Inst GPR:$rs1, GPR:$rs2, simm13_lsb0:$imm12)>;
974
975def : BccPat<seteq, BEQ>;
976def : BccPat<setne, BNE>;
977def : BccPat<setlt, BLT>;
978def : BccPat<setge, BGE>;
979def : BccPat<setult, BLTU>;
980def : BccPat<setuge, BGEU>;
981
982class BccSwapPat<PatFrag CondOp, RVInst InstBcc>
983    : Pat<(brcond (XLenVT (CondOp GPR:$rs1, GPR:$rs2)), bb:$imm12),
984          (InstBcc GPR:$rs2, GPR:$rs1, bb:$imm12)>;
985
986// Condition codes that don't have matching RISC-V branch instructions, but
987// are trivially supported by swapping the two input operands
988def : BccSwapPat<setgt, BLT>;
989def : BccSwapPat<setle, BGE>;
990def : BccSwapPat<setugt, BLTU>;
991def : BccSwapPat<setule, BGEU>;
992
993// Extra patterns are needed for a brcond without a setcc (i.e. where the
994// condition was calculated elsewhere).
995def : Pat<(brcond GPR:$cond, bb:$imm12), (BNE GPR:$cond, X0, bb:$imm12)>;
996// In this pattern, the `(xor $cond, 1)` functions like (boolean) `not`, as the
997// `brcond` only uses the lowest bit.
998def : Pat<(brcond (XLenVT (xor GPR:$cond, 1)), bb:$imm12),
999          (BEQ GPR:$cond, X0, bb:$imm12)>;
1000
1001let isBarrier = 1, isBranch = 1, isTerminator = 1 in
1002def PseudoBR : Pseudo<(outs), (ins simm21_lsb0_jal:$imm20), [(br bb:$imm20)]>,
1003               PseudoInstExpansion<(JAL X0, simm21_lsb0_jal:$imm20)>;
1004
1005let isBarrier = 1, isBranch = 1, isIndirectBranch = 1, isTerminator = 1 in
1006def PseudoBRIND : Pseudo<(outs), (ins GPR:$rs1, simm12:$imm12), []>,
1007                  PseudoInstExpansion<(JALR X0, GPR:$rs1, simm12:$imm12)>;
1008
1009def : Pat<(brind GPR:$rs1), (PseudoBRIND GPR:$rs1, 0)>;
1010def : Pat<(brind (add GPR:$rs1, simm12:$imm12)),
1011          (PseudoBRIND GPR:$rs1, simm12:$imm12)>;
1012
1013// PseudoCALLReg is a generic pseudo instruction for calls which will eventually
1014// expand to auipc and jalr while encoding, with any given register used as the
1015// destination.
1016// Define AsmString to print "call" when compile with -S flag.
1017// Define isCodeGenOnly = 0 to support parsing assembly "call" instruction.
1018let isCall = 1, isBarrier = 1, isCodeGenOnly = 0, hasSideEffects = 0,
1019    mayStore = 0, mayLoad = 0 in
1020def PseudoCALLReg : Pseudo<(outs GPR:$rd), (ins call_symbol:$func), []> {
1021  let AsmString = "call\t$rd, $func";
1022}
1023
1024// PseudoCALL is a pseudo instruction which will eventually expand to auipc
1025// and jalr while encoding. This is desirable, as an auipc+jalr pair with
1026// R_RISCV_CALL and R_RISCV_RELAX relocations can be be relaxed by the linker
1027// if the offset fits in a signed 21-bit immediate.
1028// Define AsmString to print "call" when compile with -S flag.
1029// Define isCodeGenOnly = 0 to support parsing assembly "call" instruction.
1030let isCall = 1, Defs = [X1], isCodeGenOnly = 0 in
1031def PseudoCALL : Pseudo<(outs), (ins call_symbol:$func), []> {
1032  let AsmString = "call\t$func";
1033}
1034
1035def : Pat<(riscv_call tglobaladdr:$func), (PseudoCALL tglobaladdr:$func)>;
1036def : Pat<(riscv_call texternalsym:$func), (PseudoCALL texternalsym:$func)>;
1037
1038def : Pat<(riscv_uret_flag), (URET X0, X0)>;
1039def : Pat<(riscv_sret_flag), (SRET X0, X0)>;
1040def : Pat<(riscv_mret_flag), (MRET X0, X0)>;
1041
1042let isCall = 1, Defs = [X1] in
1043def PseudoCALLIndirect : Pseudo<(outs), (ins GPR:$rs1),
1044                                [(riscv_call GPR:$rs1)]>,
1045                         PseudoInstExpansion<(JALR X1, GPR:$rs1, 0)>;
1046
1047let isBarrier = 1, isReturn = 1, isTerminator = 1 in
1048def PseudoRET : Pseudo<(outs), (ins), [(riscv_ret_flag)]>,
1049                PseudoInstExpansion<(JALR X0, X1, 0)>;
1050
1051// PseudoTAIL is a pseudo instruction similar to PseudoCALL and will eventually
1052// expand to auipc and jalr while encoding.
1053// Define AsmString to print "tail" when compile with -S flag.
1054let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1, Uses = [X2],
1055    isCodeGenOnly = 0 in
1056def PseudoTAIL : Pseudo<(outs), (ins call_symbol:$dst), []> {
1057  let AsmString = "tail\t$dst";
1058}
1059
1060let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1, Uses = [X2] in
1061def PseudoTAILIndirect : Pseudo<(outs), (ins GPRTC:$rs1),
1062                                [(riscv_tail GPRTC:$rs1)]>,
1063                         PseudoInstExpansion<(JALR X0, GPR:$rs1, 0)>;
1064
1065def : Pat<(riscv_tail (iPTR tglobaladdr:$dst)),
1066          (PseudoTAIL texternalsym:$dst)>;
1067def : Pat<(riscv_tail (iPTR texternalsym:$dst)),
1068          (PseudoTAIL texternalsym:$dst)>;
1069
1070let isCall = 0, isBarrier = 1, isBranch = 1, isTerminator = 1,
1071    isCodeGenOnly = 0, hasSideEffects = 0, mayStore = 0, mayLoad = 0 in
1072def PseudoJump : Pseudo<(outs GPR:$rd), (ins pseudo_jump_symbol:$target), []> {
1073  let AsmString = "jump\t$target, $rd";
1074}
1075
1076let hasSideEffects = 0, mayLoad = 0, mayStore = 0, isCodeGenOnly = 0,
1077    isAsmParserOnly = 1 in
1078def PseudoLLA : Pseudo<(outs GPR:$dst), (ins bare_symbol:$src), [],
1079                       "lla", "$dst, $src">;
1080
1081let hasSideEffects = 0, mayLoad = 1, mayStore = 0, isCodeGenOnly = 0,
1082    isAsmParserOnly = 1 in
1083def PseudoLA : Pseudo<(outs GPR:$dst), (ins bare_symbol:$src), [],
1084                      "la", "$dst, $src">;
1085
1086let hasSideEffects = 0, mayLoad = 1, mayStore = 0, isCodeGenOnly = 0,
1087    isAsmParserOnly = 1 in
1088def PseudoLA_TLS_IE : Pseudo<(outs GPR:$dst), (ins bare_symbol:$src), [],
1089                             "la.tls.ie", "$dst, $src">;
1090
1091let hasSideEffects = 0, mayLoad = 1, mayStore = 0, isCodeGenOnly = 0,
1092    isAsmParserOnly = 1 in
1093def PseudoLA_TLS_GD : Pseudo<(outs GPR:$dst), (ins bare_symbol:$src), [],
1094                             "la.tls.gd", "$dst, $src">;
1095
1096
1097/// Sign/Zero Extends
1098
1099// There are single-instruction versions of these in Zbb, so disable these
1100// Pseudos if that extension is present.
1101let hasSideEffects = 0, mayLoad = 0,
1102    mayStore = 0, isCodeGenOnly = 0, isAsmParserOnly = 1 in {
1103def PseudoSEXT_B : Pseudo<(outs GPR:$rd), (ins GPR:$rs), [], "sext.b", "$rd, $rs">;
1104def PseudoSEXT_H : Pseudo<(outs GPR:$rd), (ins GPR:$rs), [], "sext.h", "$rd, $rs">;
1105// rv64's sext.w is defined above, using InstAlias<"sext.w ...
1106// zext.b is defined above, using InstAlias<"zext.b ...
1107def PseudoZEXT_H : Pseudo<(outs GPR:$rd), (ins GPR:$rs), [], "zext.h", "$rd, $rs">;
1108} // hasSideEffects = 0, ...
1109
1110let Predicates = [IsRV64], hasSideEffects = 0, mayLoad = 0, mayStore = 0,
1111  isCodeGenOnly = 0, isAsmParserOnly = 1 in {
1112def PseudoZEXT_W : Pseudo<(outs GPR:$rd), (ins GPR:$rs), [], "zext.w", "$rd, $rs">;
1113} // Predicates = [IsRV64], ...
1114
1115/// Loads
1116
1117multiclass LdPat<PatFrag LoadOp, RVInst Inst> {
1118  def : Pat<(LoadOp GPR:$rs1), (Inst GPR:$rs1, 0)>;
1119  def : Pat<(LoadOp AddrFI:$rs1), (Inst AddrFI:$rs1, 0)>;
1120  def : Pat<(LoadOp (add GPR:$rs1, simm12:$imm12)),
1121            (Inst GPR:$rs1, simm12:$imm12)>;
1122  def : Pat<(LoadOp (add AddrFI:$rs1, simm12:$imm12)),
1123            (Inst AddrFI:$rs1, simm12:$imm12)>;
1124  def : Pat<(LoadOp (IsOrAdd AddrFI:$rs1, simm12:$imm12)),
1125            (Inst AddrFI:$rs1, simm12:$imm12)>;
1126}
1127
1128defm : LdPat<sextloadi8, LB>;
1129defm : LdPat<extloadi8, LB>;
1130defm : LdPat<sextloadi16, LH>;
1131defm : LdPat<extloadi16, LH>;
1132defm : LdPat<load, LW>, Requires<[IsRV32]>;
1133defm : LdPat<zextloadi8, LBU>;
1134defm : LdPat<zextloadi16, LHU>;
1135
1136/// Stores
1137
1138multiclass StPat<PatFrag StoreOp, RVInst Inst, RegisterClass StTy> {
1139  def : Pat<(StoreOp StTy:$rs2, GPR:$rs1), (Inst StTy:$rs2, GPR:$rs1, 0)>;
1140  def : Pat<(StoreOp StTy:$rs2, AddrFI:$rs1), (Inst StTy:$rs2, AddrFI:$rs1, 0)>;
1141  def : Pat<(StoreOp StTy:$rs2, (add GPR:$rs1, simm12:$imm12)),
1142            (Inst StTy:$rs2, GPR:$rs1, simm12:$imm12)>;
1143  def : Pat<(StoreOp StTy:$rs2, (add AddrFI:$rs1, simm12:$imm12)),
1144            (Inst StTy:$rs2, AddrFI:$rs1, simm12:$imm12)>;
1145  def : Pat<(StoreOp StTy:$rs2, (IsOrAdd AddrFI:$rs1, simm12:$imm12)),
1146            (Inst StTy:$rs2, AddrFI:$rs1, simm12:$imm12)>;
1147}
1148
1149defm : StPat<truncstorei8, SB, GPR>;
1150defm : StPat<truncstorei16, SH, GPR>;
1151defm : StPat<store, SW, GPR>, Requires<[IsRV32]>;
1152
1153/// Fences
1154
1155// Refer to Table A.6 in the version 2.3 draft of the RISC-V Instruction Set
1156// Manual: Volume I.
1157
1158// fence acquire -> fence r, rw
1159def : Pat<(atomic_fence (XLenVT 4), (timm)), (FENCE 0b10, 0b11)>;
1160// fence release -> fence rw, w
1161def : Pat<(atomic_fence (XLenVT 5), (timm)), (FENCE 0b11, 0b1)>;
1162// fence acq_rel -> fence.tso
1163def : Pat<(atomic_fence (XLenVT 6), (timm)), (FENCE_TSO)>;
1164// fence seq_cst -> fence rw, rw
1165def : Pat<(atomic_fence (XLenVT 7), (timm)), (FENCE 0b11, 0b11)>;
1166
1167// Lowering for atomic load and store is defined in RISCVInstrInfoA.td.
1168// Although these are lowered to fence+load/store instructions defined in the
1169// base RV32I/RV64I ISA, this lowering is only used when the A extension is
1170// present. This is necessary as it isn't valid to mix __atomic_* libcalls
1171// with inline atomic operations for the same object.
1172
1173/// Other pseudo-instructions
1174
1175// Pessimistically assume the stack pointer will be clobbered
1176let Defs = [X2], Uses = [X2] in {
1177def ADJCALLSTACKDOWN : Pseudo<(outs), (ins i32imm:$amt1, i32imm:$amt2),
1178                              [(callseq_start timm:$amt1, timm:$amt2)]>;
1179def ADJCALLSTACKUP   : Pseudo<(outs), (ins i32imm:$amt1, i32imm:$amt2),
1180                              [(callseq_end timm:$amt1, timm:$amt2)]>;
1181} // Defs = [X2], Uses = [X2]
1182
1183/// RV64 patterns
1184
1185let Predicates = [IsRV64, NotHasStdExtZba] in {
1186def : Pat<(and GPR:$rs1, 0xffffffff), (SRLI (SLLI GPR:$rs1, 32), 32)>;
1187
1188// If we're shifting a 32-bit zero extended value left by 0-31 bits, use 2
1189// shifts instead of 3. This can occur when unsigned is used to index an array.
1190def : Pat<(shl (and GPR:$rs1, 0xffffffff), uimm5:$shamt),
1191          (SRLI (SLLI GPR:$rs1, 32), (ImmSubFrom32 uimm5:$shamt))>;
1192// shl/and can appear in the other order too.
1193def : Pat<(SLLIUWPat GPR:$rs1, uimm5:$shamt),
1194          (SRLI (SLLI GPR:$rs1, 32), (ImmSubFrom32 uimm5:$shamt))>;
1195}
1196
1197let Predicates = [IsRV64] in {
1198
1199/// sext and zext
1200
1201def : Pat<(sext_inreg GPR:$rs1, i32), (ADDIW GPR:$rs1, 0)>;
1202
1203/// ALU operations
1204
1205def : Pat<(sext_inreg (add GPR:$rs1, GPR:$rs2), i32),
1206          (ADDW GPR:$rs1, GPR:$rs2)>;
1207def : Pat<(sext_inreg (add GPR:$rs1, simm12:$imm12), i32),
1208          (ADDIW GPR:$rs1, simm12:$imm12)>;
1209def : Pat<(sext_inreg (sub GPR:$rs1, GPR:$rs2), i32),
1210          (SUBW GPR:$rs1, GPR:$rs2)>;
1211def : Pat<(sext_inreg (shl GPR:$rs1, uimm5:$shamt), i32),
1212          (SLLIW GPR:$rs1, uimm5:$shamt)>;
1213def : Pat<(SRLIWPat GPR:$rs1, uimm5:$shamt),
1214          (SRLIW GPR:$rs1, uimm5:$shamt)>;
1215def : Pat<(srl (shl GPR:$rs1, (i64 32)), uimm6gt32:$shamt),
1216          (SRLIW GPR:$rs1, (ImmSub32 uimm6gt32:$shamt))>;
1217def : Pat<(sra (sext_inreg GPR:$rs1, i32), uimm5:$shamt),
1218          (SRAIW GPR:$rs1, uimm5:$shamt)>;
1219def : Pat<(sra (shl GPR:$rs1, (i64 32)), uimm6gt32:$shamt),
1220          (SRAIW GPR:$rs1, (ImmSub32 uimm6gt32:$shamt))>;
1221
1222def : PatGprGpr<shiftopw<riscv_sllw>, SLLW>;
1223def : PatGprGpr<shiftopw<riscv_srlw>, SRLW>;
1224def : PatGprGpr<shiftopw<riscv_sraw>, SRAW>;
1225
1226/// Loads
1227
1228defm : LdPat<sextloadi32, LW>;
1229defm : LdPat<extloadi32, LW>;
1230defm : LdPat<zextloadi32, LWU>;
1231defm : LdPat<load, LD>;
1232
1233/// Stores
1234
1235defm : StPat<truncstorei32, SW, GPR>;
1236defm : StPat<store, SD, GPR>;
1237} // Predicates = [IsRV64]
1238
1239/// readcyclecounter
1240// On RV64, we can directly read the 64-bit "cycle" CSR.
1241let Predicates = [IsRV64] in
1242def : Pat<(readcyclecounter), (CSRRS CYCLE.Encoding, X0)>;
1243// On RV32, ReadCycleWide will be expanded to the suggested loop reading both
1244// halves of the 64-bit "cycle" CSR.
1245let Predicates = [IsRV32], usesCustomInserter = 1, hasNoSchedulingInfo = 1 in
1246def ReadCycleWide : Pseudo<(outs GPR:$lo, GPR:$hi), (ins),
1247                           [(set GPR:$lo, GPR:$hi, (riscv_read_cycle_wide))],
1248                           "", "">;
1249
1250/// traps
1251
1252// We lower `trap` to `unimp`, as this causes a hard exception on nearly all
1253// systems.
1254def : Pat<(trap), (UNIMP)>;
1255
1256// We lower `debugtrap` to `ebreak`, as this will get the attention of the
1257// debugger if possible.
1258def : Pat<(debugtrap), (EBREAK)>;
1259
1260//===----------------------------------------------------------------------===//
1261// Standard extensions
1262//===----------------------------------------------------------------------===//
1263
1264include "RISCVInstrInfoM.td"
1265include "RISCVInstrInfoA.td"
1266include "RISCVInstrInfoF.td"
1267include "RISCVInstrInfoD.td"
1268include "RISCVInstrInfoC.td"
1269include "RISCVInstrInfoB.td"
1270include "RISCVInstrInfoV.td"
1271include "RISCVInstrInfoZfh.td"
1272