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