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