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