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