1//== LoongArchInstrInfo.td - Target Description for LoongArch -*- 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 LoongArch instructions in TableGen format.
10//
11//===----------------------------------------------------------------------===//
12
13//===----------------------------------------------------------------------===//
14// LoongArch 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_LoongArchCall : SDTypeProfile<0, -1, [SDTCisVT<0, GRLenVT>]>;
25def SDT_LoongArchIntBinOpW : SDTypeProfile<1, 2, [
26  SDTCisSameAs<0, 1>, SDTCisSameAs<0, 2>, SDTCisVT<0, i64>
27]>;
28
29def SDT_LoongArchBStrIns: SDTypeProfile<1, 4, [
30  SDTCisInt<0>, SDTCisSameAs<0, 1>, SDTCisSameAs<0, 2>, SDTCisInt<3>,
31  SDTCisSameAs<3, 4>
32]>;
33
34def SDT_LoongArchBStrPick: SDTypeProfile<1, 3, [
35  SDTCisInt<0>, SDTCisSameAs<0, 1>, SDTCisInt<2>, SDTCisSameAs<2, 3>
36]>;
37
38// "VI" means no output and an integer input.
39def SDT_LoongArchVI : SDTypeProfile<0, 1, [SDTCisVT<0, GRLenVT>]>;
40
41def SDT_LoongArchCsrrd : SDTypeProfile<1, 1, [SDTCisInt<0>,
42                                              SDTCisVT<1, GRLenVT>]>;
43def SDT_LoongArchCsrwr : SDTypeProfile<1, 2, [SDTCisInt<0>, SDTCisSameAs<0, 1>,
44                                              SDTCisVT<2, GRLenVT>]>;
45def SDT_LoongArchCsrxchg : SDTypeProfile<1, 3, [SDTCisInt<0>,
46                                                SDTCisSameAs<0, 1>,
47                                                SDTCisSameAs<0, 2>,
48                                                SDTCisVT<3, GRLenVT>]>;
49def SDT_LoongArchIocsrwr : SDTypeProfile<0, 2, [SDTCisInt<0>,
50                                                SDTCisSameAs<0, 1>]>;
51def SDT_LoongArchMovgr2fcsr : SDTypeProfile<0, 2, [SDTCisVT<0, GRLenVT>,
52                                                   SDTCisSameAs<0, 1>]>;
53def SDT_LoongArchMovfcsr2gr : SDTypeProfile<1, 1, [SDTCisVT<0, GRLenVT>,
54                                                   SDTCisSameAs<0, 1>]>;
55
56// TODO: Add LoongArch specific DAG Nodes
57// Target-independent nodes, but with target-specific formats.
58def callseq_start : SDNode<"ISD::CALLSEQ_START", SDT_CallSeqStart,
59                           [SDNPHasChain, SDNPOutGlue]>;
60def callseq_end : SDNode<"ISD::CALLSEQ_END", SDT_CallSeqEnd,
61                         [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue]>;
62
63// Target-dependent nodes.
64def loongarch_call : SDNode<"LoongArchISD::CALL", SDT_LoongArchCall,
65                            [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue,
66                             SDNPVariadic]>;
67def loongarch_ret : SDNode<"LoongArchISD::RET", SDTNone,
68                           [SDNPHasChain, SDNPOptInGlue, SDNPVariadic]>;
69def loongarch_tail : SDNode<"LoongArchISD::TAIL", SDT_LoongArchCall,
70                            [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue,
71                             SDNPVariadic]>;
72def loongarch_sll_w : SDNode<"LoongArchISD::SLL_W", SDT_LoongArchIntBinOpW>;
73def loongarch_sra_w : SDNode<"LoongArchISD::SRA_W", SDT_LoongArchIntBinOpW>;
74def loongarch_srl_w : SDNode<"LoongArchISD::SRL_W", SDT_LoongArchIntBinOpW>;
75def loongarch_rotr_w : SDNode<"LoongArchISD::ROTR_W", SDT_LoongArchIntBinOpW>;
76def loongarch_rotl_w : SDNode<"LoongArchISD::ROTL_W", SDT_LoongArchIntBinOpW>;
77def loongarch_crc_w_b_w
78    : SDNode<"LoongArchISD::CRC_W_B_W", SDT_LoongArchIntBinOpW, [SDNPHasChain]>;
79def loongarch_crc_w_h_w
80    : SDNode<"LoongArchISD::CRC_W_H_W", SDT_LoongArchIntBinOpW, [SDNPHasChain]>;
81def loongarch_crc_w_w_w
82    : SDNode<"LoongArchISD::CRC_W_W_W", SDT_LoongArchIntBinOpW, [SDNPHasChain]>;
83def loongarch_crc_w_d_w
84    : SDNode<"LoongArchISD::CRC_W_D_W", SDT_LoongArchIntBinOpW, [SDNPHasChain]>;
85def loongarch_crcc_w_b_w : SDNode<"LoongArchISD::CRCC_W_B_W",
86                                  SDT_LoongArchIntBinOpW, [SDNPHasChain]>;
87def loongarch_crcc_w_h_w : SDNode<"LoongArchISD::CRCC_W_H_W",
88                                  SDT_LoongArchIntBinOpW, [SDNPHasChain]>;
89def loongarch_crcc_w_w_w : SDNode<"LoongArchISD::CRCC_W_W_W",
90                                  SDT_LoongArchIntBinOpW, [SDNPHasChain]>;
91def loongarch_crcc_w_d_w : SDNode<"LoongArchISD::CRCC_W_D_W",
92                                  SDT_LoongArchIntBinOpW, [SDNPHasChain]>;
93def loongarch_bstrins
94    : SDNode<"LoongArchISD::BSTRINS", SDT_LoongArchBStrIns>;
95def loongarch_bstrpick
96    : SDNode<"LoongArchISD::BSTRPICK", SDT_LoongArchBStrPick>;
97def loongarch_revb_2h : SDNode<"LoongArchISD::REVB_2H", SDTUnaryOp>;
98def loongarch_revb_2w : SDNode<"LoongArchISD::REVB_2W", SDTUnaryOp>;
99def loongarch_bitrev_4b : SDNode<"LoongArchISD::BITREV_4B", SDTUnaryOp>;
100def loongarch_bitrev_w : SDNode<"LoongArchISD::BITREV_W", SDTUnaryOp>;
101def loongarch_clzw : SDNode<"LoongArchISD::CLZ_W", SDTIntBitCountUnaryOp>;
102def loongarch_ctzw : SDNode<"LoongArchISD::CTZ_W", SDTIntBitCountUnaryOp>;
103def loongarch_dbar : SDNode<"LoongArchISD::DBAR", SDT_LoongArchVI,
104                             [SDNPHasChain, SDNPSideEffect]>;
105def loongarch_ibar : SDNode<"LoongArchISD::IBAR", SDT_LoongArchVI,
106                             [SDNPHasChain, SDNPSideEffect]>;
107def loongarch_break : SDNode<"LoongArchISD::BREAK", SDT_LoongArchVI,
108                              [SDNPHasChain, SDNPSideEffect]>;
109def loongarch_movfcsr2gr : SDNode<"LoongArchISD::MOVFCSR2GR",
110                                  SDT_LoongArchMovfcsr2gr, [SDNPHasChain]>;
111def loongarch_movgr2fcsr : SDNode<"LoongArchISD::MOVGR2FCSR",
112                                  SDT_LoongArchMovgr2fcsr,
113                                  [SDNPHasChain, SDNPSideEffect]>;
114def loongarch_syscall : SDNode<"LoongArchISD::SYSCALL", SDT_LoongArchVI,
115                                [SDNPHasChain, SDNPSideEffect]>;
116def loongarch_csrrd : SDNode<"LoongArchISD::CSRRD", SDT_LoongArchCsrrd,
117                              [SDNPHasChain, SDNPSideEffect]>;
118def loongarch_csrwr : SDNode<"LoongArchISD::CSRWR", SDT_LoongArchCsrwr,
119                              [SDNPHasChain, SDNPSideEffect]>;
120def loongarch_csrxchg : SDNode<"LoongArchISD::CSRXCHG",
121                                SDT_LoongArchCsrxchg,
122                                [SDNPHasChain, SDNPSideEffect]>;
123def loongarch_iocsrrd_b : SDNode<"LoongArchISD::IOCSRRD_B", SDTUnaryOp,
124                                  [SDNPHasChain, SDNPSideEffect]>;
125def loongarch_iocsrrd_h : SDNode<"LoongArchISD::IOCSRRD_H", SDTUnaryOp,
126                                  [SDNPHasChain, SDNPSideEffect]>;
127def loongarch_iocsrrd_w : SDNode<"LoongArchISD::IOCSRRD_W", SDTUnaryOp,
128                                  [SDNPHasChain, SDNPSideEffect]>;
129def loongarch_iocsrrd_d : SDNode<"LoongArchISD::IOCSRRD_D", SDTUnaryOp,
130                                  [SDNPHasChain, SDNPSideEffect]>;
131def loongarch_iocsrwr_b : SDNode<"LoongArchISD::IOCSRWR_B",
132                                  SDT_LoongArchIocsrwr,
133                                  [SDNPHasChain, SDNPSideEffect]>;
134def loongarch_iocsrwr_h : SDNode<"LoongArchISD::IOCSRWR_H",
135                                  SDT_LoongArchIocsrwr,
136                                  [SDNPHasChain, SDNPSideEffect]>;
137def loongarch_iocsrwr_w : SDNode<"LoongArchISD::IOCSRWR_W",
138                                  SDT_LoongArchIocsrwr,
139                                  [SDNPHasChain, SDNPSideEffect]>;
140def loongarch_iocsrwr_d : SDNode<"LoongArchISD::IOCSRWR_D",
141                                  SDT_LoongArchIocsrwr,
142                                  [SDNPHasChain, SDNPSideEffect]>;
143def loongarch_cpucfg : SDNode<"LoongArchISD::CPUCFG", SDTUnaryOp,
144                               [SDNPHasChain]>;
145
146def to_fclass_mask: SDNodeXForm<timm, [{
147  uint64_t Check = N->getZExtValue();
148  unsigned Mask = 0;
149  if (Check & fcSNan)
150    Mask |= LoongArch::FClassMaskSignalingNaN;
151  if (Check & fcQNan)
152    Mask |= LoongArch::FClassMaskQuietNaN;
153  if (Check & fcPosInf)
154    Mask |= LoongArch::FClassMaskPositiveInfinity;
155  if (Check & fcNegInf)
156    Mask |= LoongArch::FClassMaskNegativeInfinity;
157  if (Check & fcPosNormal)
158    Mask |= LoongArch::FClassMaskPositiveNormal;
159  if (Check & fcNegNormal)
160    Mask |= LoongArch::FClassMaskNegativeNormal;
161  if (Check & fcPosSubnormal)
162    Mask |= LoongArch::FClassMaskPositiveSubnormal;
163  if (Check & fcNegSubnormal)
164    Mask |= LoongArch::FClassMaskNegativeSubnormal;
165  if (Check & fcPosZero)
166    Mask |= LoongArch::FClassMaskPositiveZero;
167  if (Check & fcNegZero)
168    Mask |= LoongArch::FClassMaskNegativeZero;
169  return CurDAG->getTargetConstant(Mask, SDLoc(N), Subtarget->getGRLenVT());
170}]>;
171
172//===----------------------------------------------------------------------===//
173// Operand and SDNode transformation definitions.
174//===----------------------------------------------------------------------===//
175
176class ImmAsmOperand<string prefix, int width, string suffix>
177    : AsmOperandClass {
178  let Name = prefix # "Imm" # width # suffix;
179  let DiagnosticType = !strconcat("Invalid", Name);
180  let RenderMethod = "addImmOperands";
181}
182
183class SImmAsmOperand<int width, string suffix = "">
184    : ImmAsmOperand<"S", width, suffix> {
185}
186
187class UImmAsmOperand<int width, string suffix = "">
188    : ImmAsmOperand<"U", width, suffix> {
189}
190
191// A parse method for "$r*" or "$r*, 0", where the 0 is be silently ignored.
192// Only used for "AM*" instructions, in order to be compatible with GAS.
193def AtomicMemAsmOperand : AsmOperandClass {
194  let Name = "AtomicMemAsmOperand";
195  let RenderMethod = "addRegOperands";
196  let PredicateMethod = "isGPR";
197  let ParserMethod = "parseAtomicMemOp";
198}
199
200def GPRMemAtomic : RegisterOperand<GPR> {
201  let ParserMatchClass = AtomicMemAsmOperand;
202  let PrintMethod = "printAtomicMemOp";
203}
204
205// A parameterized register class alternative to i32imm/i64imm from Target.td.
206def grlenimm : Operand<GRLenVT>;
207def imm32 : Operand<GRLenVT> {
208  let ParserMatchClass = ImmAsmOperand<"", 32, "">;
209}
210
211def uimm1 : Operand<GRLenVT>, ImmLeaf<GRLenVT, [{return isUInt<1>(Imm);}]>{
212  let ParserMatchClass = UImmAsmOperand<1>;
213}
214
215def uimm2 : Operand<GRLenVT>, ImmLeaf<GRLenVT, [{return isUInt<2>(Imm);}]> {
216  let ParserMatchClass = UImmAsmOperand<2>;
217}
218
219def uimm2_plus1 : Operand<GRLenVT>,
220    ImmLeaf<GRLenVT, [{return isUInt<2>(Imm - 1);}]> {
221  let ParserMatchClass = UImmAsmOperand<2, "plus1">;
222  let EncoderMethod = "getImmOpValueSub1";
223  let DecoderMethod = "decodeUImmOperand<2, 1>";
224}
225
226def uimm3 : Operand<GRLenVT>, ImmLeaf<GRLenVT, [{return isUInt<3>(Imm);}]> {
227  let ParserMatchClass = UImmAsmOperand<3>;
228}
229
230def uimm4 : Operand<GRLenVT>, ImmLeaf<GRLenVT, [{return isUInt<4>(Imm);}]> {
231  let ParserMatchClass = UImmAsmOperand<4>;
232}
233
234def uimm5 : Operand<GRLenVT>, ImmLeaf<GRLenVT, [{return isUInt<5>(Imm);}]> {
235  let ParserMatchClass = UImmAsmOperand<5>;
236}
237
238def uimm6 : Operand<GRLenVT>, ImmLeaf<GRLenVT, [{return isUInt<6>(Imm);}]> {
239  let ParserMatchClass = UImmAsmOperand<6>;
240}
241
242def uimm7 : Operand<GRLenVT> {
243  let ParserMatchClass = UImmAsmOperand<7>;
244}
245
246def uimm8 : Operand<GRLenVT>, ImmLeaf<GRLenVT, [{return isUInt<8>(Imm);}]> {
247  let ParserMatchClass = UImmAsmOperand<8>;
248}
249
250class UImm12Operand : Operand<GRLenVT>,
251                      ImmLeaf <GRLenVT, [{return isUInt<12>(Imm);}]> {
252  let DecoderMethod = "decodeUImmOperand<12>";
253}
254
255def uimm12 : UImm12Operand {
256  let ParserMatchClass = UImmAsmOperand<12>;
257}
258
259def uimm12_ori : UImm12Operand {
260  let ParserMatchClass = UImmAsmOperand<12, "ori">;
261}
262
263def uimm14 : Operand<GRLenVT>,
264             ImmLeaf <GRLenVT, [{return isUInt<14>(Imm);}]> {
265  let ParserMatchClass = UImmAsmOperand<14>;
266}
267
268def uimm15 : Operand<GRLenVT>,
269             ImmLeaf <GRLenVT, [{return isUInt<15>(Imm);}]> {
270  let ParserMatchClass = UImmAsmOperand<15>;
271}
272
273def simm5 : Operand<GRLenVT> {
274  let ParserMatchClass = SImmAsmOperand<5>;
275  let DecoderMethod = "decodeSImmOperand<5>";
276}
277
278def simm8 : Operand<GRLenVT> {
279  let ParserMatchClass = SImmAsmOperand<8>;
280  let DecoderMethod = "decodeSImmOperand<8>";
281}
282
283foreach I = [1, 2, 3] in {
284def simm8_lsl # I : Operand<GRLenVT> {
285  let ParserMatchClass = SImmAsmOperand<8, "lsl" # I>;
286  let EncoderMethod = "getImmOpValueAsr<" # I # ">";
287  let DecoderMethod = "decodeSImmOperand<8," # I # ">";
288}
289}
290
291def simm9_lsl3 : Operand<GRLenVT> {
292  let ParserMatchClass = SImmAsmOperand<9, "lsl3">;
293  let EncoderMethod = "getImmOpValueAsr<3>";
294  let DecoderMethod = "decodeSImmOperand<9, 3>";
295}
296
297def simm10 : Operand<GRLenVT> {
298  let ParserMatchClass = SImmAsmOperand<10>;
299}
300
301def simm10_lsl2 : Operand<GRLenVT> {
302  let ParserMatchClass = SImmAsmOperand<10, "lsl2">;
303  let EncoderMethod = "getImmOpValueAsr<2>";
304  let DecoderMethod = "decodeSImmOperand<10, 2>";
305}
306
307def simm11_lsl1 : Operand<GRLenVT> {
308  let ParserMatchClass = SImmAsmOperand<11, "lsl1">;
309  let EncoderMethod = "getImmOpValueAsr<1>";
310  let DecoderMethod = "decodeSImmOperand<11, 1>";
311}
312
313class SImm12Operand : Operand<GRLenVT>,
314                      ImmLeaf <GRLenVT, [{return isInt<12>(Imm);}]> {
315  let DecoderMethod = "decodeSImmOperand<12>";
316}
317
318def simm12 : SImm12Operand {
319  let ParserMatchClass = SImmAsmOperand<12>;
320}
321
322def simm12_addlike : SImm12Operand {
323  let ParserMatchClass = SImmAsmOperand<12, "addlike">;
324}
325
326def simm12_lu52id : SImm12Operand {
327  let ParserMatchClass = SImmAsmOperand<12, "lu52id">;
328}
329
330def simm13 : Operand<GRLenVT> {
331  let ParserMatchClass = SImmAsmOperand<13>;
332  let DecoderMethod = "decodeSImmOperand<13>";
333}
334
335def simm14_lsl2 : Operand<GRLenVT>,
336    ImmLeaf<GRLenVT, [{return isShiftedInt<14,2>(Imm);}]> {
337  let ParserMatchClass = SImmAsmOperand<14, "lsl2">;
338  let EncoderMethod = "getImmOpValueAsr<2>";
339  let DecoderMethod = "decodeSImmOperand<14, 2>";
340}
341
342def simm16 : Operand<GRLenVT> {
343  let ParserMatchClass = SImmAsmOperand<16>;
344  let DecoderMethod = "decodeSImmOperand<16>";
345}
346
347def simm16_lsl2 : Operand<GRLenVT>,
348    ImmLeaf<GRLenVT, [{return isInt<16>(Imm>>2);}]> {
349  let ParserMatchClass = SImmAsmOperand<16, "lsl2">;
350  let EncoderMethod = "getImmOpValueAsr<2>";
351  let DecoderMethod = "decodeSImmOperand<16, 2>";
352}
353
354def simm16_lsl2_br : Operand<OtherVT> {
355  let ParserMatchClass = SImmAsmOperand<16, "lsl2">;
356  let EncoderMethod = "getImmOpValueAsr<2>";
357  let DecoderMethod = "decodeSImmOperand<16, 2>";
358}
359
360class SImm20Operand : Operand<GRLenVT> {
361  let DecoderMethod = "decodeSImmOperand<20>";
362}
363
364def simm20 : SImm20Operand {
365  let ParserMatchClass = SImmAsmOperand<20>;
366}
367
368def simm20_pcalau12i : SImm20Operand {
369  let ParserMatchClass = SImmAsmOperand<20, "pcalau12i">;
370}
371
372def simm20_lu12iw : SImm20Operand {
373  let ParserMatchClass = SImmAsmOperand<20, "lu12iw">;
374}
375
376def simm20_lu32id : SImm20Operand {
377  let ParserMatchClass = SImmAsmOperand<20, "lu32id">;
378}
379
380def simm21_lsl2 : Operand<OtherVT> {
381  let ParserMatchClass = SImmAsmOperand<21, "lsl2">;
382  let EncoderMethod = "getImmOpValueAsr<2>";
383  let DecoderMethod = "decodeSImmOperand<21, 2>";
384}
385
386def SImm26OperandB: AsmOperandClass {
387  let Name = "SImm26OperandB";
388  let PredicateMethod = "isSImm26Operand";
389  let RenderMethod = "addImmOperands";
390  let DiagnosticType = "InvalidSImm26Operand";
391  let ParserMethod = "parseImmediate";
392}
393
394// A symbol or an imm used in B/PseudoBR.
395def simm26_b : Operand<OtherVT> {
396  let ParserMatchClass = SImm26OperandB;
397  let EncoderMethod = "getImmOpValueAsr<2>";
398  let DecoderMethod = "decodeSImmOperand<26, 2>";
399}
400
401def SImm26OperandBL: AsmOperandClass {
402  let Name = "SImm26OperandBL";
403  let PredicateMethod = "isSImm26Operand";
404  let RenderMethod = "addImmOperands";
405  let DiagnosticType = "InvalidSImm26Operand";
406  let ParserMethod = "parseSImm26Operand";
407}
408
409// A symbol or an imm used in BL/PseudoCALL/PseudoTAIL.
410def simm26_symbol : Operand<GRLenVT> {
411  let ParserMatchClass = SImm26OperandBL;
412  let EncoderMethod = "getImmOpValueAsr<2>";
413  let DecoderMethod = "decodeSImmOperand<26, 2>";
414}
415
416// A 32-bit signed immediate with the lowest 16 bits zeroed, suitable for
417// direct use with `addu16i.d`.
418def simm16_lsl16 : Operand<GRLenVT>,
419    ImmLeaf<GRLenVT, [{return isShiftedInt<16, 16>(Imm);}]>;
420
421// A 32-bit signed immediate expressible with a pair of `addu16i.d + addi` for
422// use in additions.
423def simm32_hi16_lo12: Operand<GRLenVT>, ImmLeaf<GRLenVT, [{
424  return isShiftedInt<16, 16>(Imm - SignExtend64<12>(Imm));
425}]>;
426
427def BareSymbol : AsmOperandClass {
428  let Name = "BareSymbol";
429  let RenderMethod = "addImmOperands";
430  let DiagnosticType = "InvalidBareSymbol";
431  let ParserMethod = "parseImmediate";
432}
433
434// A bare symbol used in "PseudoLA_*" instructions.
435def bare_symbol : Operand<GRLenVT> {
436  let ParserMatchClass = BareSymbol;
437}
438
439// Standalone (codegen-only) immleaf patterns.
440
441// A 12-bit signed immediate plus one where the imm range will be [-2047, 2048].
442def simm12_plus1 : ImmLeaf<GRLenVT,
443  [{return (isInt<12>(Imm) && Imm != -2048) || Imm == 2048;}]>;
444
445// Return the negation of an immediate value.
446def NegImm : SDNodeXForm<imm, [{
447  return CurDAG->getTargetConstant(-N->getSExtValue(), SDLoc(N),
448                                   N->getValueType(0));
449}]>;
450
451// FP immediate patterns.
452def fpimm0    : PatLeaf<(fpimm), [{return N->isExactlyValue(+0.0);}]>;
453def fpimm0neg : PatLeaf<(fpimm), [{return N->isExactlyValue(-0.0);}]>;
454def fpimm1    : PatLeaf<(fpimm), [{return N->isExactlyValue(+1.0);}]>;
455
456// Return an immediate subtracted from 32.
457def ImmSubFrom32 : SDNodeXForm<imm, [{
458  return CurDAG->getTargetConstant(32 - N->getZExtValue(), SDLoc(N),
459                                   N->getValueType(0));
460}]>;
461
462// Return the lowest 12 bits of the signed immediate.
463def LO12: SDNodeXForm<imm, [{
464  return CurDAG->getTargetConstant(SignExtend64<12>(N->getSExtValue()),
465                                   SDLoc(N), N->getValueType(0));
466}]>;
467
468// Return the higher 16 bits of the signed immediate.
469def HI16 : SDNodeXForm<imm, [{
470  return CurDAG->getTargetConstant(N->getSExtValue() >> 16, SDLoc(N),
471                                   N->getValueType(0));
472}]>;
473
474// Return the higher 16 bits of the signed immediate, adjusted for use within an
475// `addu16i.d + addi` pair.
476def HI16ForAddu16idAddiPair: SDNodeXForm<imm, [{
477  auto Imm = N->getSExtValue();
478  return CurDAG->getTargetConstant((Imm - SignExtend64<12>(Imm)) >> 16,
479                                   SDLoc(N), N->getValueType(0));
480}]>;
481
482def BaseAddr : ComplexPattern<iPTR, 1, "SelectBaseAddr">;
483def AddrConstant : ComplexPattern<iPTR, 2, "SelectAddrConstant">;
484def NonFIBaseAddr : ComplexPattern<iPTR, 1, "selectNonFIBaseAddr">;
485
486def fma_nsz : PatFrag<(ops node:$fj, node:$fk, node:$fa),
487                      (fma node:$fj, node:$fk, node:$fa), [{
488  return N->getFlags().hasNoSignedZeros();
489}]>;
490
491// Check if (add r, imm) can be optimized to (ADDI (ADDI r, imm0), imm1),
492// in which imm = imm0 + imm1, and both imm0 & imm1 are simm12.
493def AddiPair : PatLeaf<(imm), [{
494  if (!N->hasOneUse())
495    return false;
496  // The immediate operand must be in range [-4096,-2049] or [2048,4094].
497  int64_t Imm = N->getSExtValue();
498  return (-4096 <= Imm && Imm <= -2049) || (2048 <= Imm && Imm <= 4094);
499}]>;
500
501// Return -2048 if immediate is negative or 2047 if positive.
502def AddiPairImmLarge : SDNodeXForm<imm, [{
503  int64_t Imm = N->getSExtValue() < 0 ? -2048 : 2047;
504  return CurDAG->getTargetConstant(Imm, SDLoc(N),
505                                   N->getValueType(0));
506}]>;
507
508// Return imm - (imm < 0 ? -2048 : 2047).
509def AddiPairImmSmall : SDNodeXForm<imm, [{
510  int64_t Imm = N->getSExtValue();
511  int64_t Adj = Imm < 0 ? -2048 : 2047;
512  return CurDAG->getTargetConstant(Imm - Adj, SDLoc(N),
513                                   N->getValueType(0));
514}]>;
515
516// Check if (mul r, imm) can be optimized to (SLLI (ALSL r, r, i0), i1),
517// in which imm = (1 + (1 << i0)) << i1.
518def AlslSlliImm : PatLeaf<(imm), [{
519  if (!N->hasOneUse())
520    return false;
521  uint64_t Imm = N->getZExtValue();
522  unsigned I1 = llvm::countr_zero(Imm);
523  uint64_t Rem = Imm >> I1;
524  return Rem == 3 || Rem == 5 || Rem == 9 || Rem == 17;
525}]>;
526
527def AlslSlliImmI1 : SDNodeXForm<imm, [{
528  uint64_t Imm = N->getZExtValue();
529  unsigned I1 = llvm::countr_zero(Imm);
530  return CurDAG->getTargetConstant(I1, SDLoc(N),
531                                   N->getValueType(0));
532}]>;
533
534def AlslSlliImmI0 : SDNodeXForm<imm, [{
535  uint64_t Imm = N->getZExtValue();
536  unsigned I1 = llvm::countr_zero(Imm);
537  uint64_t I0;
538  switch (Imm >> I1) {
539  case 3:  I0 = 1; break;
540  case 5:  I0 = 2; break;
541  case 9:  I0 = 3; break;
542  default: I0 = 4; break;
543  }
544  return CurDAG->getTargetConstant(I0, SDLoc(N),
545                                   N->getValueType(0));
546}]>;
547
548// Check if (and r, imm) can be optimized to (BSTRINS r, R0, msb, lsb),
549// in which imm = ~((2^^(msb-lsb+1) - 1) << lsb).
550def BstrinsImm : PatLeaf<(imm), [{
551  if (!N->hasOneUse())
552    return false;
553  uint64_t Imm = N->getZExtValue();
554  // andi can be used instead if Imm <= 0xfff.
555  if (Imm <= 0xfff)
556    return false;
557  unsigned MaskIdx, MaskLen;
558  return N->getValueType(0).getSizeInBits() == 32
559             ? llvm::isShiftedMask_32(~Imm, MaskIdx, MaskLen)
560             : llvm::isShiftedMask_64(~Imm, MaskIdx, MaskLen);
561}]>;
562
563def BstrinsMsb: SDNodeXForm<imm, [{
564  uint64_t Imm = N->getZExtValue();
565  unsigned MaskIdx, MaskLen;
566  N->getValueType(0).getSizeInBits() == 32
567      ? llvm::isShiftedMask_32(~Imm, MaskIdx, MaskLen)
568      : llvm::isShiftedMask_64(~Imm, MaskIdx, MaskLen);
569  return CurDAG->getTargetConstant(MaskIdx + MaskLen - 1, SDLoc(N),
570                                   N->getValueType(0));
571}]>;
572
573def BstrinsLsb: SDNodeXForm<imm, [{
574  uint64_t Imm = N->getZExtValue();
575  unsigned MaskIdx, MaskLen;
576  N->getValueType(0).getSizeInBits() == 32
577      ? llvm::isShiftedMask_32(~Imm, MaskIdx, MaskLen)
578      : llvm::isShiftedMask_64(~Imm, MaskIdx, MaskLen);
579  return CurDAG->getTargetConstant(MaskIdx, SDLoc(N), N->getValueType(0));
580}]>;
581
582//===----------------------------------------------------------------------===//
583// Instruction Formats
584//===----------------------------------------------------------------------===//
585
586include "LoongArchInstrFormats.td"
587include "LoongArchFloatInstrFormats.td"
588include "LoongArchLSXInstrFormats.td"
589include "LoongArchLASXInstrFormats.td"
590include "LoongArchLBTInstrFormats.td"
591
592//===----------------------------------------------------------------------===//
593// Instruction Class Templates
594//===----------------------------------------------------------------------===//
595
596let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in {
597class ALU_3R<bits<32> op>
598    : Fmt3R<op, (outs GPR:$rd), (ins GPR:$rj, GPR:$rk), "$rd, $rj, $rk">;
599class ALU_2R<bits<32> op>
600    : Fmt2R<op, (outs GPR:$rd), (ins GPR:$rj), "$rd, $rj">;
601
602class ALU_3RI2<bits<32> op, Operand ImmOpnd>
603    : Fmt3RI2<op, (outs GPR:$rd), (ins GPR:$rj, GPR:$rk, ImmOpnd:$imm2),
604              "$rd, $rj, $rk, $imm2">;
605class ALU_3RI3<bits<32> op, Operand ImmOpnd>
606    : Fmt3RI3<op, (outs GPR:$rd), (ins GPR:$rj, GPR:$rk, ImmOpnd:$imm3),
607              "$rd, $rj, $rk, $imm3">;
608class ALU_2RI5<bits<32> op, Operand ImmOpnd>
609    : Fmt2RI5<op, (outs GPR:$rd), (ins GPR:$rj, ImmOpnd:$imm5),
610              "$rd, $rj, $imm5">;
611class ALU_2RI6<bits<32> op, Operand ImmOpnd>
612    : Fmt2RI6<op, (outs GPR:$rd), (ins GPR:$rj, ImmOpnd:$imm6),
613              "$rd, $rj, $imm6">;
614class ALU_2RI12<bits<32> op, Operand ImmOpnd>
615    : Fmt2RI12<op, (outs GPR:$rd), (ins GPR:$rj, ImmOpnd:$imm12),
616               "$rd, $rj, $imm12">;
617class ALU_2RI16<bits<32> op, Operand ImmOpnd>
618    : Fmt2RI16<op, (outs GPR:$rd), (ins GPR:$rj, ImmOpnd:$imm16),
619               "$rd, $rj, $imm16">;
620class ALU_1RI20<bits<32> op, Operand ImmOpnd>
621    : Fmt1RI20<op, (outs GPR:$rd), (ins ImmOpnd:$imm20), "$rd, $imm20">;
622} // hasSideEffects = 0, mayLoad = 0, mayStore = 0
623
624let hasSideEffects = 1, mayLoad = 0, mayStore = 0 in
625class MISC_I15<bits<32> op>
626    : FmtI15<op, (outs), (ins uimm15:$imm15), "$imm15">;
627
628let hasSideEffects = 1, mayLoad = 0, mayStore = 0 in
629class RDTIME_2R<bits<32> op>
630    : Fmt2R<op, (outs GPR:$rd, GPR:$rj), (ins), "$rd, $rj">;
631
632let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in {
633class BrCC_2RI16<bits<32> op>
634    : Fmt2RI16<op, (outs), (ins GPR:$rj, GPR:$rd, simm16_lsl2_br:$imm16),
635               "$rj, $rd, $imm16"> {
636  let isBranch = 1;
637  let isTerminator = 1;
638}
639class BrCCZ_1RI21<bits<32> op>
640    : Fmt1RI21<op, (outs), (ins GPR:$rj, simm21_lsl2:$imm21),
641               "$rj, $imm21"> {
642  let isBranch = 1;
643  let isTerminator = 1;
644}
645class Br_I26<bits<32> op>
646    : FmtI26<op, (outs), (ins simm26_b:$imm26), "$imm26"> {
647  let isBranch = 1;
648  let isTerminator = 1;
649  let isBarrier = 1;
650}
651} // hasSideEffects = 0, mayLoad = 0, mayStore = 0
652
653let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in {
654class LOAD_3R<bits<32> op>
655    : Fmt3R<op, (outs GPR:$rd), (ins GPR:$rj, GPR:$rk), "$rd, $rj, $rk">;
656class LOAD_2RI12<bits<32> op>
657    : Fmt2RI12<op, (outs GPR:$rd), (ins GPR:$rj, simm12_addlike:$imm12),
658               "$rd, $rj, $imm12">;
659class LOAD_2RI14<bits<32> op>
660    : Fmt2RI14<op, (outs GPR:$rd), (ins GPR:$rj, simm14_lsl2:$imm14),
661               "$rd, $rj, $imm14">;
662} // hasSideEffects = 0, mayLoad = 1, mayStore = 0
663
664let hasSideEffects = 0, mayLoad = 0, mayStore = 1 in {
665class STORE_3R<bits<32> op>
666    : Fmt3R<op, (outs), (ins GPR:$rd, GPR:$rj, GPR:$rk),
667            "$rd, $rj, $rk">;
668class STORE_2RI12<bits<32> op>
669    : Fmt2RI12<op, (outs), (ins GPR:$rd, GPR:$rj, simm12_addlike:$imm12),
670               "$rd, $rj, $imm12">;
671class STORE_2RI14<bits<32> op>
672    : Fmt2RI14<op, (outs), (ins GPR:$rd, GPR:$rj, simm14_lsl2:$imm14),
673               "$rd, $rj, $imm14">;
674} // hasSideEffects = 0, mayLoad = 0, mayStore = 1
675
676let hasSideEffects = 0, mayLoad = 1, mayStore = 1, Constraints = "@earlyclobber $rd" in
677class AM_3R<bits<32> op>
678    : Fmt3R<op, (outs GPR:$rd), (ins GPR:$rk, GPRMemAtomic:$rj),
679            "$rd, $rk, $rj">;
680
681let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in
682class LLBase<bits<32> op>
683    : Fmt2RI14<op, (outs GPR:$rd), (ins GPR:$rj, simm14_lsl2:$imm14),
684               "$rd, $rj, $imm14">;
685
686let hasSideEffects = 0, mayLoad = 0, mayStore = 1, Constraints = "$rd = $dst" in
687class SCBase<bits<32> op>
688    : Fmt2RI14<op, (outs GPR:$dst), (ins GPR:$rd, GPR:$rj, simm14_lsl2:$imm14),
689               "$rd, $rj, $imm14">;
690
691let hasSideEffects = 1 in
692class IOCSRRD<bits<32> op>
693    : Fmt2R<op, (outs GPR:$rd), (ins GPR:$rj), "$rd, $rj">;
694
695let hasSideEffects = 1 in
696class IOCSRWR<bits<32> op>
697    : Fmt2R<op, (outs), (ins GPR:$rd, GPR:$rj), "$rd, $rj">;
698
699//===----------------------------------------------------------------------===//
700// Basic Integer Instructions
701//===----------------------------------------------------------------------===//
702
703// Arithmetic Operation Instructions
704def ADD_W : ALU_3R<0x00100000>;
705def SUB_W : ALU_3R<0x00110000>;
706def ADDI_W : ALU_2RI12<0x02800000, simm12_addlike>;
707def ALSL_W : ALU_3RI2<0x00040000, uimm2_plus1>;
708def LU12I_W : ALU_1RI20<0x14000000, simm20_lu12iw>;
709def SLT  : ALU_3R<0x00120000>;
710def SLTU : ALU_3R<0x00128000>;
711def SLTI  : ALU_2RI12<0x02000000, simm12>;
712def SLTUI : ALU_2RI12<0x02400000, simm12>;
713def PCADDI    : ALU_1RI20<0x18000000, simm20>;
714def PCADDU12I : ALU_1RI20<0x1c000000, simm20>;
715def PCALAU12I : ALU_1RI20<0x1a000000, simm20_pcalau12i>;
716def AND  : ALU_3R<0x00148000>;
717def OR   : ALU_3R<0x00150000>;
718def NOR  : ALU_3R<0x00140000>;
719def XOR  : ALU_3R<0x00158000>;
720def ANDN : ALU_3R<0x00168000>;
721def ORN  : ALU_3R<0x00160000>;
722def ANDI : ALU_2RI12<0x03400000, uimm12>;
723def ORI  : ALU_2RI12<0x03800000, uimm12_ori>;
724def XORI : ALU_2RI12<0x03c00000, uimm12>;
725def MUL_W   : ALU_3R<0x001c0000>;
726def MULH_W  : ALU_3R<0x001c8000>;
727def MULH_WU : ALU_3R<0x001d0000>;
728let usesCustomInserter = true in {
729def DIV_W   : ALU_3R<0x00200000>;
730def MOD_W   : ALU_3R<0x00208000>;
731def DIV_WU  : ALU_3R<0x00210000>;
732def MOD_WU  : ALU_3R<0x00218000>;
733} // usesCustomInserter = true
734
735// Bit-shift Instructions
736def SLL_W  : ALU_3R<0x00170000>;
737def SRL_W  : ALU_3R<0x00178000>;
738def SRA_W  : ALU_3R<0x00180000>;
739def ROTR_W : ALU_3R<0x001b0000>;
740
741def SLLI_W  : ALU_2RI5<0x00408000, uimm5>;
742def SRLI_W  : ALU_2RI5<0x00448000, uimm5>;
743def SRAI_W  : ALU_2RI5<0x00488000, uimm5>;
744def ROTRI_W : ALU_2RI5<0x004c8000, uimm5>;
745
746// Bit-manipulation Instructions
747def EXT_W_B : ALU_2R<0x00005c00>;
748def EXT_W_H : ALU_2R<0x00005800>;
749def CLO_W   : ALU_2R<0x00001000>;
750def CLZ_W   : ALU_2R<0x00001400>;
751def CTO_W   : ALU_2R<0x00001800>;
752def CTZ_W   : ALU_2R<0x00001c00>;
753def BYTEPICK_W : ALU_3RI2<0x00080000, uimm2>;
754def REVB_2H   : ALU_2R<0x00003000>;
755def BITREV_4B : ALU_2R<0x00004800>;
756def BITREV_W  : ALU_2R<0x00005000>;
757let Constraints = "$rd = $dst" in {
758def BSTRINS_W  : FmtBSTR_W<0x00600000, (outs GPR:$dst),
759                           (ins GPR:$rd, GPR:$rj, uimm5:$msbw, uimm5:$lsbw),
760                           "$rd, $rj, $msbw, $lsbw">;
761}
762def BSTRPICK_W : FmtBSTR_W<0x00608000, (outs GPR:$rd),
763                           (ins GPR:$rj, uimm5:$msbw, uimm5:$lsbw),
764                           "$rd, $rj, $msbw, $lsbw">;
765def MASKEQZ : ALU_3R<0x00130000>;
766def MASKNEZ : ALU_3R<0x00138000>;
767
768// Branch Instructions
769def BEQ  : BrCC_2RI16<0x58000000>;
770def BNE  : BrCC_2RI16<0x5c000000>;
771def BLT  : BrCC_2RI16<0x60000000>;
772def BGE  : BrCC_2RI16<0x64000000>;
773def BLTU : BrCC_2RI16<0x68000000>;
774def BGEU : BrCC_2RI16<0x6c000000>;
775def BEQZ : BrCCZ_1RI21<0x40000000>;
776def BNEZ : BrCCZ_1RI21<0x44000000>;
777def B : Br_I26<0x50000000>;
778
779let hasSideEffects = 0, mayLoad = 0, mayStore = 0, isCall = 1, Defs=[R1] in
780def BL : FmtI26<0x54000000, (outs), (ins simm26_symbol:$imm26), "$imm26">;
781let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
782def JIRL : Fmt2RI16<0x4c000000, (outs GPR:$rd),
783                    (ins GPR:$rj, simm16_lsl2:$imm16), "$rd, $rj, $imm16">;
784
785// Common Memory Access Instructions
786def LD_B  : LOAD_2RI12<0x28000000>;
787def LD_H  : LOAD_2RI12<0x28400000>;
788def LD_W  : LOAD_2RI12<0x28800000>;
789def LD_BU : LOAD_2RI12<0x2a000000>;
790def LD_HU : LOAD_2RI12<0x2a400000>;
791def ST_B : STORE_2RI12<0x29000000>;
792def ST_H : STORE_2RI12<0x29400000>;
793def ST_W : STORE_2RI12<0x29800000>;
794let hasSideEffects = 0, mayLoad = 1, mayStore = 1 in
795def PRELD : FmtPRELD<(outs), (ins uimm5:$imm5, GPR:$rj, simm12:$imm12),
796                     "$imm5, $rj, $imm12">;
797
798// Atomic Memory Access Instructions
799def LL_W : LLBase<0x20000000>;
800def SC_W : SCBase<0x21000000>;
801
802// Barrier Instructions
803def DBAR : MISC_I15<0x38720000>;
804def IBAR : MISC_I15<0x38728000>;
805
806// Other Miscellaneous Instructions
807def SYSCALL : MISC_I15<0x002b0000>;
808def BREAK   : MISC_I15<0x002a0000>;
809def RDTIMEL_W : RDTIME_2R<0x00006000>;
810def RDTIMEH_W : RDTIME_2R<0x00006400>;
811def CPUCFG : ALU_2R<0x00006c00>;
812
813// Cache Maintenance Instructions
814def CACOP : FmtCACOP<(outs), (ins uimm5:$op, GPR:$rj, simm12:$imm12),
815                     "$op, $rj, $imm12">;
816
817/// LA64 instructions
818
819let Predicates = [IsLA64] in {
820
821// Arithmetic Operation Instructions for 64-bits
822def ADD_D : ALU_3R<0x00108000>;
823def SUB_D : ALU_3R<0x00118000>;
824def ADDI_D : ALU_2RI12<0x02c00000, simm12_addlike>;
825def ADDU16I_D : ALU_2RI16<0x10000000, simm16>;
826def ALSL_WU : ALU_3RI2<0x00060000, uimm2_plus1>;
827def ALSL_D  : ALU_3RI2<0x002c0000, uimm2_plus1>;
828let Constraints = "$rd = $dst" in {
829let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
830def LU32I_D : Fmt1RI20<0x16000000, (outs GPR:$dst),
831                       (ins GPR:$rd, simm20_lu32id:$imm20),
832                       "$rd, $imm20">;
833}
834def LU52I_D : ALU_2RI12<0x03000000, simm12_lu52id>;
835def PCADDU18I : ALU_1RI20<0x1e000000, simm20>;
836def MUL_D     : ALU_3R<0x001d8000>;
837def MULH_D    : ALU_3R<0x001e0000>;
838def MULH_DU   : ALU_3R<0x001e8000>;
839def MULW_D_W  : ALU_3R<0x001f0000>;
840def MULW_D_WU : ALU_3R<0x001f8000>;
841let usesCustomInserter = true in {
842def DIV_D     : ALU_3R<0x00220000>;
843def MOD_D     : ALU_3R<0x00228000>;
844def DIV_DU    : ALU_3R<0x00230000>;
845def MOD_DU    : ALU_3R<0x00238000>;
846} // usesCustomInserter = true
847
848// Bit-shift Instructions for 64-bits
849def SLL_D  : ALU_3R<0x00188000>;
850def SRL_D  : ALU_3R<0x00190000>;
851def SRA_D  : ALU_3R<0x00198000>;
852def ROTR_D : ALU_3R<0x001b8000>;
853def SLLI_D  : ALU_2RI6<0x00410000, uimm6>;
854def SRLI_D  : ALU_2RI6<0x00450000, uimm6>;
855def SRAI_D  : ALU_2RI6<0x00490000, uimm6>;
856def ROTRI_D : ALU_2RI6<0x004d0000, uimm6>;
857
858// Bit-manipulation Instructions for 64-bits
859def CLO_D : ALU_2R<0x00002000>;
860def CLZ_D : ALU_2R<0x00002400>;
861def CTO_D : ALU_2R<0x00002800>;
862def CTZ_D : ALU_2R<0x00002c00>;
863def BYTEPICK_D : ALU_3RI3<0x000c0000, uimm3>;
864def REVB_4H   : ALU_2R<0x00003400>;
865def REVB_2W   : ALU_2R<0x00003800>;
866def REVB_D    : ALU_2R<0x00003c00>;
867def REVH_2W   : ALU_2R<0x00004000>;
868def REVH_D    : ALU_2R<0x00004400>;
869def BITREV_8B : ALU_2R<0x00004c00>;
870def BITREV_D  : ALU_2R<0x00005400>;
871let Constraints = "$rd = $dst" in {
872def BSTRINS_D  : FmtBSTR_D<0x00800000, (outs GPR:$dst),
873                           (ins GPR:$rd, GPR:$rj, uimm6:$msbd, uimm6:$lsbd),
874                           "$rd, $rj, $msbd, $lsbd">;
875}
876def BSTRPICK_D : FmtBSTR_D<0x00c00000, (outs GPR:$rd),
877                           (ins GPR:$rj, uimm6:$msbd, uimm6:$lsbd),
878                           "$rd, $rj, $msbd, $lsbd">;
879
880// Common Memory Access Instructions for 64-bits
881def LD_WU : LOAD_2RI12<0x2a800000>;
882def LD_D  : LOAD_2RI12<0x28c00000>;
883def ST_D : STORE_2RI12<0x29c00000>;
884def LDX_B  : LOAD_3R<0x38000000>;
885def LDX_H  : LOAD_3R<0x38040000>;
886def LDX_W  : LOAD_3R<0x38080000>;
887def LDX_D  : LOAD_3R<0x380c0000>;
888def LDX_BU : LOAD_3R<0x38200000>;
889def LDX_HU : LOAD_3R<0x38240000>;
890def LDX_WU : LOAD_3R<0x38280000>;
891def STX_B : STORE_3R<0x38100000>;
892def STX_H : STORE_3R<0x38140000>;
893def STX_W : STORE_3R<0x38180000>;
894def STX_D : STORE_3R<0x381c0000>;
895def LDPTR_W : LOAD_2RI14<0x24000000>;
896def LDPTR_D : LOAD_2RI14<0x26000000>;
897def STPTR_W : STORE_2RI14<0x25000000>;
898def STPTR_D : STORE_2RI14<0x27000000>;
899let hasSideEffects = 0, mayLoad = 1, mayStore = 1 in
900def PRELDX : FmtPRELDX<(outs), (ins uimm5:$imm5, GPR:$rj, GPR:$rk),
901                       "$imm5, $rj, $rk">;
902
903// Bound Check Memory Access Instructions
904def LDGT_B : LOAD_3R<0x38780000>;
905def LDGT_H : LOAD_3R<0x38788000>;
906def LDGT_W : LOAD_3R<0x38790000>;
907def LDGT_D : LOAD_3R<0x38798000>;
908def LDLE_B : LOAD_3R<0x387a0000>;
909def LDLE_H : LOAD_3R<0x387a8000>;
910def LDLE_W : LOAD_3R<0x387b0000>;
911def LDLE_D : LOAD_3R<0x387b8000>;
912def STGT_B : STORE_3R<0x387c0000>;
913def STGT_H : STORE_3R<0x387c8000>;
914def STGT_W : STORE_3R<0x387d0000>;
915def STGT_D : STORE_3R<0x387d8000>;
916def STLE_B : STORE_3R<0x387e0000>;
917def STLE_H : STORE_3R<0x387e8000>;
918def STLE_W : STORE_3R<0x387f0000>;
919def STLE_D : STORE_3R<0x387f8000>;
920
921// Atomic Memory Access Instructions for 64-bits
922def AMSWAP_W     : AM_3R<0x38600000>;
923def AMSWAP_D     : AM_3R<0x38608000>;
924def AMADD_W      : AM_3R<0x38610000>;
925def AMADD_D      : AM_3R<0x38618000>;
926def AMAND_W      : AM_3R<0x38620000>;
927def AMAND_D      : AM_3R<0x38628000>;
928def AMOR_W       : AM_3R<0x38630000>;
929def AMOR_D       : AM_3R<0x38638000>;
930def AMXOR_W      : AM_3R<0x38640000>;
931def AMXOR_D      : AM_3R<0x38648000>;
932def AMMAX_W      : AM_3R<0x38650000>;
933def AMMAX_D      : AM_3R<0x38658000>;
934def AMMIN_W      : AM_3R<0x38660000>;
935def AMMIN_D      : AM_3R<0x38668000>;
936def AMMAX_WU     : AM_3R<0x38670000>;
937def AMMAX_DU     : AM_3R<0x38678000>;
938def AMMIN_WU     : AM_3R<0x38680000>;
939def AMMIN_DU     : AM_3R<0x38688000>;
940def AMSWAP__DB_W : AM_3R<0x38690000>;
941def AMSWAP__DB_D : AM_3R<0x38698000>;
942def AMADD__DB_W  : AM_3R<0x386a0000>;
943def AMADD__DB_D  : AM_3R<0x386a8000>;
944def AMAND__DB_W  : AM_3R<0x386b0000>;
945def AMAND__DB_D  : AM_3R<0x386b8000>;
946def AMOR__DB_W   : AM_3R<0x386c0000>;
947def AMOR__DB_D   : AM_3R<0x386c8000>;
948def AMXOR__DB_W  : AM_3R<0x386d0000>;
949def AMXOR__DB_D  : AM_3R<0x386d8000>;
950def AMMAX__DB_W  : AM_3R<0x386e0000>;
951def AMMAX__DB_D  : AM_3R<0x386e8000>;
952def AMMIN__DB_W  : AM_3R<0x386f0000>;
953def AMMIN__DB_D  : AM_3R<0x386f8000>;
954def AMMAX__DB_WU : AM_3R<0x38700000>;
955def AMMAX__DB_DU : AM_3R<0x38708000>;
956def AMMIN__DB_WU : AM_3R<0x38710000>;
957def AMMIN__DB_DU : AM_3R<0x38718000>;
958def LL_D : LLBase<0x22000000>;
959def SC_D : SCBase<0x23000000>;
960
961// CRC Check Instructions
962def CRC_W_B_W  : ALU_3R<0x00240000>;
963def CRC_W_H_W  : ALU_3R<0x00248000>;
964def CRC_W_W_W  : ALU_3R<0x00250000>;
965def CRC_W_D_W  : ALU_3R<0x00258000>;
966def CRCC_W_B_W : ALU_3R<0x00260000>;
967def CRCC_W_H_W : ALU_3R<0x00268000>;
968def CRCC_W_W_W : ALU_3R<0x00270000>;
969def CRCC_W_D_W : ALU_3R<0x00278000>;
970
971// Other Miscellaneous Instructions for 64-bits
972def ASRTLE_D : FmtASRT<0x00010000, (outs), (ins GPR:$rj, GPR:$rk),
973                       "$rj, $rk">;
974def ASRTGT_D : FmtASRT<0x00018000, (outs), (ins GPR:$rj, GPR:$rk),
975                       "$rj, $rk">;
976def RDTIME_D : RDTIME_2R<0x00006800>;
977} // Predicates = [IsLA64]
978
979//===----------------------------------------------------------------------===//
980// Pseudo-instructions and codegen patterns
981//
982// Naming convention: For 'generic' pattern classes, we use the naming
983// convention PatTy1Ty2.
984//===----------------------------------------------------------------------===//
985
986/// Generic pattern classes
987
988class PatGprGpr<SDPatternOperator OpNode, LAInst Inst>
989    : Pat<(OpNode GPR:$rj, GPR:$rk), (Inst GPR:$rj, GPR:$rk)>;
990class PatGprGpr_32<SDPatternOperator OpNode, LAInst Inst>
991    : Pat<(sext_inreg (OpNode GPR:$rj, GPR:$rk), i32), (Inst GPR:$rj, GPR:$rk)>;
992class PatGpr<SDPatternOperator OpNode, LAInst Inst>
993    : Pat<(OpNode GPR:$rj), (Inst GPR:$rj)>;
994
995class PatGprImm<SDPatternOperator OpNode, LAInst Inst, Operand ImmOpnd>
996    : Pat<(OpNode GPR:$rj, ImmOpnd:$imm),
997          (Inst GPR:$rj, ImmOpnd:$imm)>;
998class PatGprImm_32<SDPatternOperator OpNode, LAInst Inst, Operand ImmOpnd>
999    : Pat<(sext_inreg (OpNode GPR:$rj, ImmOpnd:$imm), i32),
1000          (Inst GPR:$rj, ImmOpnd:$imm)>;
1001
1002/// Predicates
1003def AddLike: PatFrags<(ops node:$A, node:$B),
1004                      [(add node:$A, node:$B), (or node:$A, node:$B)], [{
1005    return N->getOpcode() == ISD::ADD || isOrEquivalentToAdd(N);
1006}]>;
1007
1008/// Simple arithmetic operations
1009
1010// Match both a plain shift and one where the shift amount is masked (this is
1011// typically introduced when the legalizer promotes the shift amount and
1012// zero-extends it). For LoongArch, the mask is unnecessary as shifts in the
1013// base ISA only read the least significant 5 bits (LA32) or 6 bits (LA64).
1014def shiftMaskGRLen
1015    : ComplexPattern<GRLenVT, 1, "selectShiftMaskGRLen", [], [], 0>;
1016def shiftMask32 : ComplexPattern<i64, 1, "selectShiftMask32", [], [], 0>;
1017
1018def sexti32 : ComplexPattern<i64, 1, "selectSExti32">;
1019def zexti32 : ComplexPattern<i64, 1, "selectZExti32">;
1020
1021class shiftop<SDPatternOperator operator>
1022    : PatFrag<(ops node:$val, node:$count),
1023              (operator node:$val, (GRLenVT (shiftMaskGRLen node:$count)))>;
1024class shiftopw<SDPatternOperator operator>
1025    : PatFrag<(ops node:$val, node:$count),
1026              (operator node:$val, (i64 (shiftMask32 node:$count)))>;
1027
1028def mul_const_oneuse : PatFrag<(ops node:$A, node:$B),
1029                               (mul node:$A, node:$B), [{
1030  if (auto *N1C = dyn_cast<ConstantSDNode>(N->getOperand(1)))
1031    return N1C->hasOneUse();
1032  return false;
1033}]>;
1034
1035let Predicates = [IsLA32] in {
1036def : PatGprGpr<add, ADD_W>;
1037def : PatGprImm<add, ADDI_W, simm12>;
1038def : PatGprGpr<sub, SUB_W>;
1039def : PatGprGpr<sdiv, DIV_W>;
1040def : PatGprGpr<udiv, DIV_WU>;
1041def : PatGprGpr<srem, MOD_W>;
1042def : PatGprGpr<urem, MOD_WU>;
1043def : PatGprGpr<mul, MUL_W>;
1044def : PatGprGpr<mulhs, MULH_W>;
1045def : PatGprGpr<mulhu, MULH_WU>;
1046def : PatGprGpr<rotr, ROTR_W>;
1047def : PatGprImm<rotr, ROTRI_W, uimm5>;
1048
1049foreach Idx = 1...3 in {
1050  defvar ShamtA = !mul(8, Idx);
1051  defvar ShamtB = !mul(8, !sub(4, Idx));
1052  def : Pat<(or (shl GPR:$rk, (i32 ShamtA)), (srl GPR:$rj, (i32 ShamtB))),
1053            (BYTEPICK_W GPR:$rj, GPR:$rk, Idx)>;
1054}
1055} // Predicates = [IsLA32]
1056
1057let Predicates = [IsLA64] in {
1058def : PatGprGpr<add, ADD_D>;
1059def : PatGprGpr_32<add, ADD_W>;
1060def : PatGprImm<add, ADDI_D, simm12>;
1061def : PatGprImm_32<add, ADDI_W, simm12>;
1062def : PatGprGpr<sub, SUB_D>;
1063def : PatGprGpr_32<sub, SUB_W>;
1064def : PatGprGpr<sdiv, DIV_D>;
1065def : PatGprGpr<udiv, DIV_DU>;
1066def : PatGprGpr<srem, MOD_D>;
1067def : PatGprGpr<urem, MOD_DU>;
1068def : PatGprGpr<rotr, ROTR_D>;
1069def : PatGprGpr<loongarch_rotr_w, ROTR_W>;
1070def : PatGprImm<rotr, ROTRI_D, uimm6>;
1071def : PatGprImm_32<rotr, ROTRI_W, uimm5>;
1072def : Pat<(loongarch_rotl_w GPR:$rj, uimm5:$imm),
1073          (ROTRI_W GPR:$rj, (ImmSubFrom32 uimm5:$imm))>;
1074def : Pat<(sext_inreg (loongarch_rotl_w GPR:$rj, uimm5:$imm), i32),
1075          (ROTRI_W GPR:$rj, (ImmSubFrom32 uimm5:$imm))>;
1076// TODO: Select "_W[U]" instructions for i32xi32 if only lower 32 bits of the
1077// product are used.
1078def : PatGprGpr<mul, MUL_D>;
1079def : PatGprGpr<mulhs, MULH_D>;
1080def : PatGprGpr<mulhu, MULH_DU>;
1081// Select MULW_D_W for calculating the full 64 bits product of i32xi32 signed
1082// multiplication.
1083def : Pat<(i64 (mul (sext_inreg GPR:$rj, i32), (sext_inreg GPR:$rk, i32))),
1084          (MULW_D_W GPR:$rj, GPR:$rk)>;
1085// Select MULW_D_WU for calculating the full 64 bits product of i32xi32
1086// unsigned multiplication.
1087def : Pat<(i64 (mul (loongarch_bstrpick GPR:$rj, (i64 31), (i64 0)),
1088                    (loongarch_bstrpick GPR:$rk, (i64 31), (i64 0)))),
1089          (MULW_D_WU GPR:$rj, GPR:$rk)>;
1090
1091def : Pat<(add GPR:$rj, simm16_lsl16:$imm),
1092          (ADDU16I_D GPR:$rj, (HI16 $imm))>;
1093def : Pat<(add GPR:$rj, simm32_hi16_lo12:$imm),
1094          (ADDI_D (ADDU16I_D GPR:$rj, (HI16ForAddu16idAddiPair $imm)),
1095                  (LO12 $imm))>;
1096def : Pat<(sext_inreg (add GPR:$rj, simm32_hi16_lo12:$imm), i32),
1097          (ADDI_W (ADDU16I_D GPR:$rj, (HI16ForAddu16idAddiPair $imm)),
1098                  (LO12 $imm))>;
1099
1100let Predicates = [IsLA32] in {
1101def : Pat<(add GPR:$rj, (AddiPair:$im)),
1102          (ADDI_W (ADDI_W GPR:$rj, (AddiPairImmLarge AddiPair:$im)),
1103                  (AddiPairImmSmall AddiPair:$im))>;
1104} // Predicates = [IsLA32]
1105
1106let Predicates = [IsLA64] in {
1107def : Pat<(add GPR:$rj, (AddiPair:$im)),
1108          (ADDI_D (ADDI_D GPR:$rj, (AddiPairImmLarge AddiPair:$im)),
1109                  (AddiPairImmSmall AddiPair:$im))>;
1110def : Pat<(sext_inreg (add GPR:$rj, (AddiPair:$im)), i32),
1111          (ADDI_W (ADDI_W GPR:$rj, (AddiPairImmLarge AddiPair:$im)),
1112                  (AddiPairImmSmall AddiPair:$im))>;
1113} // Predicates = [IsLA64]
1114
1115let Predicates = [IsLA32] in {
1116foreach Idx0 = 1...4 in {
1117  foreach Idx1 = 1...4 in {
1118    defvar CImm = !add(1, !shl(!add(1, !shl(1, Idx0)), Idx1));
1119    def : Pat<(mul_const_oneuse GPR:$r, (i32 CImm)),
1120              (ALSL_W (ALSL_W GPR:$r, GPR:$r, (i32 Idx0)),
1121                      GPR:$r, (i32 Idx1))>;
1122  }
1123}
1124foreach Idx0 = 1...4 in {
1125  foreach Idx1 = 1...4 in {
1126    defvar Cb = !add(1, !shl(1, Idx0));
1127    defvar CImm = !add(Cb, !shl(Cb, Idx1));
1128    def : Pat<(mul_const_oneuse GPR:$r, (i32 CImm)),
1129              (ALSL_W (ALSL_W GPR:$r, GPR:$r, (i32 Idx0)),
1130                      (ALSL_W GPR:$r, GPR:$r, (i32 Idx0)), (i32 Idx1))>;
1131  }
1132}
1133} // Predicates = [IsLA32]
1134
1135let Predicates = [IsLA64] in {
1136foreach Idx0 = 1...4 in {
1137  foreach Idx1 = 1...4 in {
1138    defvar CImm = !add(1, !shl(!add(1, !shl(1, Idx0)), Idx1));
1139    def : Pat<(sext_inreg (mul_const_oneuse GPR:$r, (i64 CImm)), i32),
1140              (ALSL_W (ALSL_W GPR:$r, GPR:$r, (i64 Idx0)),
1141                      GPR:$r, (i64 Idx1))>;
1142    def : Pat<(mul_const_oneuse GPR:$r, (i64 CImm)),
1143              (ALSL_D (ALSL_D GPR:$r, GPR:$r, (i64 Idx0)),
1144                      GPR:$r, (i64 Idx1))>;
1145  }
1146}
1147foreach Idx0 = 1...4 in {
1148  foreach Idx1 = 1...4 in {
1149    defvar Cb = !add(1, !shl(1, Idx0));
1150    defvar CImm = !add(Cb, !shl(Cb, Idx1));
1151    def : Pat<(sext_inreg (mul_const_oneuse GPR:$r, (i64 CImm)), i32),
1152              (ALSL_W (ALSL_W GPR:$r, GPR:$r, (i64 Idx0)),
1153                      (ALSL_W GPR:$r, GPR:$r, (i64 Idx0)), (i64 Idx1))>;
1154    def : Pat<(mul_const_oneuse GPR:$r, (i64 CImm)),
1155              (ALSL_D (ALSL_D GPR:$r, GPR:$r, (i64 Idx0)),
1156                      (ALSL_D GPR:$r, GPR:$r, (i64 Idx0)), (i64 Idx1))>;
1157  }
1158}
1159} // Predicates = [IsLA64]
1160
1161let Predicates = [IsLA32] in {
1162def : Pat<(mul GPR:$rj, (AlslSlliImm:$im)),
1163          (SLLI_W (ALSL_W GPR:$rj, GPR:$rj, (AlslSlliImmI0 AlslSlliImm:$im)),
1164                  (AlslSlliImmI1 AlslSlliImm:$im))>;
1165} // Predicates = [IsLA32]
1166
1167let Predicates = [IsLA64] in {
1168def : Pat<(sext_inreg (mul GPR:$rj, (AlslSlliImm:$im)), i32),
1169          (SLLI_W (ALSL_W GPR:$rj, GPR:$rj, (AlslSlliImmI0 AlslSlliImm:$im)),
1170                  (AlslSlliImmI1 AlslSlliImm:$im))>;
1171def : Pat<(mul GPR:$rj, (AlslSlliImm:$im)),
1172          (SLLI_D (ALSL_D GPR:$rj, GPR:$rj, (AlslSlliImmI0 AlslSlliImm:$im)),
1173                  (AlslSlliImmI1 AlslSlliImm:$im))>;
1174} // Predicates = [IsLA64]
1175
1176foreach Idx = 1...7 in {
1177  defvar ShamtA = !mul(8, Idx);
1178  defvar ShamtB = !mul(8, !sub(8, Idx));
1179  def : Pat<(or (shl GPR:$rk, (i64 ShamtA)), (srl GPR:$rj, (i64 ShamtB))),
1180            (BYTEPICK_D GPR:$rj, GPR:$rk, Idx)>;
1181}
1182
1183foreach Idx = 1...3 in {
1184  defvar ShamtA = !mul(8, Idx);
1185  defvar ShamtB = !mul(8, !sub(4, Idx));
1186  // NOTE: the srl node would already be transformed into a loongarch_bstrpick
1187  // by the time this pattern gets to execute, hence the weird construction.
1188  def : Pat<(sext_inreg (or (shl GPR:$rk, (i64 ShamtA)),
1189                            (loongarch_bstrpick GPR:$rj, (i64 31),
1190                                                         (i64 ShamtB))), i32),
1191            (BYTEPICK_W GPR:$rj, GPR:$rk, Idx)>;
1192}
1193} // Predicates = [IsLA64]
1194
1195def : PatGprGpr<and, AND>;
1196def : PatGprImm<and, ANDI, uimm12>;
1197def : PatGprGpr<or, OR>;
1198def : PatGprImm<or, ORI, uimm12>;
1199def : PatGprGpr<xor, XOR>;
1200def : PatGprImm<xor, XORI, uimm12>;
1201def : Pat<(not GPR:$rj), (NOR GPR:$rj, R0)>;
1202def : Pat<(not (or GPR:$rj, GPR:$rk)), (NOR GPR:$rj, GPR:$rk)>;
1203def : Pat<(or GPR:$rj, (not GPR:$rk)), (ORN GPR:$rj, GPR:$rk)>;
1204def : Pat<(and GPR:$rj, (not GPR:$rk)), (ANDN GPR:$rj, GPR:$rk)>;
1205
1206let Predicates = [IsLA32] in {
1207def : Pat<(and GPR:$rj, BstrinsImm:$imm),
1208          (BSTRINS_W GPR:$rj, R0, (BstrinsMsb BstrinsImm:$imm),
1209                     (BstrinsLsb BstrinsImm:$imm))>;
1210} // Predicates = [IsLA32]
1211
1212let Predicates = [IsLA64] in {
1213def : Pat<(and GPR:$rj, BstrinsImm:$imm),
1214          (BSTRINS_D GPR:$rj, R0, (BstrinsMsb BstrinsImm:$imm),
1215                     (BstrinsLsb BstrinsImm:$imm))>;
1216} // Predicates = [IsLA64]
1217
1218/// Traps
1219
1220// We lower `trap` to `amswap.w rd:$r0, rk:$r1, rj:$r0`, as this is guaranteed
1221// to trap with an INE (non-existent on LA32, explicitly documented to INE on
1222// LA64). And the resulting signal is different from `debugtrap` like on some
1223// other existing ports so programs/porters might have an easier time.
1224def PseudoUNIMP : Pseudo<(outs), (ins), [(trap)]>,
1225                  PseudoInstExpansion<(AMSWAP_W R0, R1, R0)>;
1226
1227// We lower `debugtrap` to `break 0`, as this is guaranteed to exist and work,
1228// even for LA32 Primary. Also, because so far the ISA does not provide a
1229// specific trap instruction/kind exclusively for alerting the debugger,
1230// every other project uses the generic immediate of 0 for this.
1231def : Pat<(debugtrap), (BREAK 0)>;
1232
1233/// Bit counting operations
1234
1235let Predicates = [IsLA64] in {
1236def : PatGpr<ctlz, CLZ_D>;
1237def : PatGpr<cttz, CTZ_D>;
1238def : Pat<(ctlz (not GPR:$rj)), (CLO_D GPR:$rj)>;
1239def : Pat<(cttz (not GPR:$rj)), (CTO_D GPR:$rj)>;
1240def : PatGpr<loongarch_clzw, CLZ_W>;
1241def : PatGpr<loongarch_ctzw, CTZ_W>;
1242def : Pat<(loongarch_clzw (not GPR:$rj)), (CLO_W GPR:$rj)>;
1243def : Pat<(loongarch_ctzw (not GPR:$rj)), (CTO_W GPR:$rj)>;
1244} // Predicates = [IsLA64]
1245
1246let Predicates = [IsLA32] in {
1247def : PatGpr<ctlz, CLZ_W>;
1248def : PatGpr<cttz, CTZ_W>;
1249def : Pat<(ctlz (not GPR:$rj)), (CLO_W GPR:$rj)>;
1250def : Pat<(cttz (not GPR:$rj)), (CTO_W GPR:$rj)>;
1251} // Predicates = [IsLA32]
1252
1253/// FrameIndex calculations
1254let Predicates = [IsLA32] in {
1255def : Pat<(AddLike (i32 BaseAddr:$rj), simm12:$imm12),
1256          (ADDI_W (i32 BaseAddr:$rj), simm12:$imm12)>;
1257} // Predicates = [IsLA32]
1258let Predicates = [IsLA64] in {
1259def : Pat<(AddLike (i64 BaseAddr:$rj), simm12:$imm12),
1260          (ADDI_D (i64 BaseAddr:$rj), simm12:$imm12)>;
1261} // Predicates = [IsLA64]
1262
1263/// Shifted addition
1264let Predicates = [IsLA32] in {
1265def : Pat<(add GPR:$rk, (shl GPR:$rj, uimm2_plus1:$imm2)),
1266          (ALSL_W GPR:$rj, GPR:$rk, uimm2_plus1:$imm2)>;
1267} // Predicates = [IsLA32]
1268let Predicates = [IsLA64] in {
1269def : Pat<(add GPR:$rk, (shl GPR:$rj, uimm2_plus1:$imm2)),
1270          (ALSL_D GPR:$rj, GPR:$rk, uimm2_plus1:$imm2)>;
1271def : Pat<(sext_inreg (add GPR:$rk, (shl GPR:$rj, uimm2_plus1:$imm2)), i32),
1272          (ALSL_W GPR:$rj, GPR:$rk, uimm2_plus1:$imm2)>;
1273def : Pat<(loongarch_bstrpick (add GPR:$rk, (shl GPR:$rj, uimm2_plus1:$imm2)),
1274                              (i64 31), (i64 0)),
1275          (ALSL_WU GPR:$rj, GPR:$rk, uimm2_plus1:$imm2)>;
1276} // Predicates = [IsLA64]
1277
1278/// Shift
1279
1280let Predicates = [IsLA32] in {
1281def : PatGprGpr<shiftop<shl>, SLL_W>;
1282def : PatGprGpr<shiftop<sra>, SRA_W>;
1283def : PatGprGpr<shiftop<srl>, SRL_W>;
1284def : PatGprImm<shl, SLLI_W, uimm5>;
1285def : PatGprImm<sra, SRAI_W, uimm5>;
1286def : PatGprImm<srl, SRLI_W, uimm5>;
1287} // Predicates = [IsLA32]
1288
1289let Predicates = [IsLA64] in {
1290def : PatGprGpr<shiftopw<loongarch_sll_w>, SLL_W>;
1291def : PatGprGpr<shiftopw<loongarch_sra_w>, SRA_W>;
1292def : PatGprGpr<shiftopw<loongarch_srl_w>, SRL_W>;
1293def : PatGprGpr<shiftop<shl>, SLL_D>;
1294def : PatGprGpr<shiftop<sra>, SRA_D>;
1295def : PatGprGpr<shiftop<srl>, SRL_D>;
1296def : PatGprImm<shl, SLLI_D, uimm6>;
1297def : PatGprImm<sra, SRAI_D, uimm6>;
1298def : PatGprImm<srl, SRLI_D, uimm6>;
1299} // Predicates = [IsLA64]
1300
1301/// sext and zext
1302
1303def : Pat<(sext_inreg GPR:$rj, i8), (EXT_W_B GPR:$rj)>;
1304def : Pat<(sext_inreg GPR:$rj, i16), (EXT_W_H GPR:$rj)>;
1305
1306let Predicates = [IsLA64] in {
1307def : Pat<(sext_inreg GPR:$rj, i32), (ADDI_W GPR:$rj, 0)>;
1308} // Predicates = [IsLA64]
1309
1310/// Setcc
1311
1312def : PatGprGpr<setlt, SLT>;
1313def : PatGprImm<setlt, SLTI, simm12>;
1314def : PatGprGpr<setult, SLTU>;
1315def : PatGprImm<setult, SLTUI, simm12>;
1316
1317// Define pattern expansions for setcc operations that aren't directly
1318// handled by a LoongArch instruction.
1319def : Pat<(seteq GPR:$rj, 0), (SLTUI GPR:$rj, 1)>;
1320def : Pat<(seteq GPR:$rj, GPR:$rk), (SLTUI (XOR GPR:$rj, GPR:$rk), 1)>;
1321let Predicates = [IsLA32] in {
1322def : Pat<(seteq GPR:$rj, simm12_plus1:$imm12),
1323          (SLTUI (ADDI_W GPR:$rj, (NegImm simm12_plus1:$imm12)), 1)>;
1324} // Predicates = [IsLA32]
1325let Predicates = [IsLA64] in {
1326def : Pat<(seteq GPR:$rj, simm12_plus1:$imm12),
1327          (SLTUI (ADDI_D GPR:$rj, (NegImm simm12_plus1:$imm12)), 1)>;
1328} // Predicates = [IsLA64]
1329def : Pat<(setne GPR:$rj, 0), (SLTU R0, GPR:$rj)>;
1330def : Pat<(setne GPR:$rj, GPR:$rk), (SLTU R0, (XOR GPR:$rj, GPR:$rk))>;
1331let Predicates = [IsLA32] in {
1332def : Pat<(setne GPR:$rj, simm12_plus1:$imm12),
1333          (SLTU R0, (ADDI_W GPR:$rj, (NegImm simm12_plus1:$imm12)))>;
1334} // Predicates = [IsLA32]
1335let Predicates = [IsLA64] in {
1336def : Pat<(setne GPR:$rj, simm12_plus1:$imm12),
1337          (SLTU R0, (ADDI_D GPR:$rj, (NegImm simm12_plus1:$imm12)))>;
1338} // Predicates = [IsLA64]
1339def : Pat<(setugt GPR:$rj, GPR:$rk), (SLTU GPR:$rk, GPR:$rj)>;
1340def : Pat<(setuge GPR:$rj, GPR:$rk), (XORI (SLTU GPR:$rj, GPR:$rk), 1)>;
1341def : Pat<(setule GPR:$rj, GPR:$rk), (XORI (SLTU GPR:$rk, GPR:$rj), 1)>;
1342def : Pat<(setgt GPR:$rj, GPR:$rk), (SLT GPR:$rk, GPR:$rj)>;
1343def : Pat<(setge GPR:$rj, GPR:$rk), (XORI (SLT GPR:$rj, GPR:$rk), 1)>;
1344def : Pat<(setle GPR:$rj, GPR:$rk), (XORI (SLT GPR:$rk, GPR:$rj), 1)>;
1345
1346/// Select
1347
1348def : Pat<(select GPR:$cond, GPR:$t, 0), (MASKEQZ GPR:$t, GPR:$cond)>;
1349def : Pat<(select GPR:$cond, 0, GPR:$f), (MASKNEZ GPR:$f, GPR:$cond)>;
1350def : Pat<(select GPR:$cond, GPR:$t, GPR:$f),
1351          (OR (MASKEQZ GPR:$t, GPR:$cond), (MASKNEZ GPR:$f, GPR:$cond))>;
1352
1353/// Branches and jumps
1354
1355class BccPat<PatFrag CondOp, LAInst Inst>
1356    : Pat<(brcond (GRLenVT (CondOp GPR:$rj, GPR:$rd)), bb:$imm16),
1357          (Inst GPR:$rj, GPR:$rd, bb:$imm16)>;
1358
1359def : BccPat<seteq, BEQ>;
1360def : BccPat<setne, BNE>;
1361def : BccPat<setlt, BLT>;
1362def : BccPat<setge, BGE>;
1363def : BccPat<setult, BLTU>;
1364def : BccPat<setuge, BGEU>;
1365
1366class BccSwapPat<PatFrag CondOp, LAInst InstBcc>
1367    : Pat<(brcond (GRLenVT (CondOp GPR:$rd, GPR:$rj)), bb:$imm16),
1368          (InstBcc GPR:$rj, GPR:$rd, bb:$imm16)>;
1369
1370// Condition codes that don't have matching LoongArch branch instructions, but
1371// are trivially supported by swapping the two input operands.
1372def : BccSwapPat<setgt, BLT>;
1373def : BccSwapPat<setle, BGE>;
1374def : BccSwapPat<setugt, BLTU>;
1375def : BccSwapPat<setule, BGEU>;
1376
1377// An extra pattern is needed for a brcond without a setcc (i.e. where the
1378// condition was calculated elsewhere).
1379def : Pat<(brcond GPR:$rj, bb:$imm21), (BNEZ GPR:$rj, bb:$imm21)>;
1380
1381def : Pat<(brcond (GRLenVT (seteq GPR:$rj, 0)), bb:$imm21),
1382          (BEQZ GPR:$rj, bb:$imm21)>;
1383def : Pat<(brcond (GRLenVT (setne GPR:$rj, 0)), bb:$imm21),
1384          (BNEZ GPR:$rj, bb:$imm21)>;
1385
1386let isBarrier = 1, isBranch = 1, isTerminator = 1 in
1387def PseudoBR : Pseudo<(outs), (ins simm26_b:$imm26), [(br bb:$imm26)]>,
1388               PseudoInstExpansion<(B simm26_b:$imm26)>;
1389
1390let isBarrier = 1, isBranch = 1, isIndirectBranch = 1, isTerminator = 1 in
1391def PseudoBRIND : Pseudo<(outs), (ins GPR:$rj, simm16_lsl2:$imm16)>,
1392                  PseudoInstExpansion<(JIRL R0, GPR:$rj, simm16_lsl2:$imm16)>;
1393
1394def : Pat<(brind GPR:$rj), (PseudoBRIND GPR:$rj, 0)>;
1395def : Pat<(brind (add GPR:$rj, simm16_lsl2:$imm16)),
1396          (PseudoBRIND GPR:$rj, simm16_lsl2:$imm16)>;
1397
1398let isCall = 1, Defs = [R1] in
1399def PseudoCALL : Pseudo<(outs), (ins simm26_symbol:$func)>;
1400
1401def : Pat<(loongarch_call tglobaladdr:$func), (PseudoCALL tglobaladdr:$func)>;
1402def : Pat<(loongarch_call texternalsym:$func), (PseudoCALL texternalsym:$func)>;
1403
1404let isCall = 1, Defs = [R1] in
1405def PseudoCALLIndirect : Pseudo<(outs), (ins GPR:$rj),
1406                                [(loongarch_call GPR:$rj)]>,
1407                         PseudoInstExpansion<(JIRL R1, GPR:$rj, 0)>;
1408
1409let isCall = 1, hasSideEffects = 0, mayStore = 0, mayLoad = 0, Defs = [R1] in
1410def PseudoJIRL_CALL : Pseudo<(outs), (ins GPR:$rj, simm16_lsl2:$imm16)>,
1411                      PseudoInstExpansion<(JIRL R1, GPR:$rj,
1412                                           simm16_lsl2:$imm16)>;
1413
1414let isBarrier = 1, isReturn = 1, isTerminator = 1 in
1415def PseudoRET : Pseudo<(outs), (ins), [(loongarch_ret)]>,
1416                PseudoInstExpansion<(JIRL R0, R1, 0)>;
1417
1418let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1, Uses = [R3] in
1419def PseudoTAIL : Pseudo<(outs), (ins simm26_symbol:$dst)>;
1420
1421def : Pat<(loongarch_tail (iPTR tglobaladdr:$dst)),
1422          (PseudoTAIL tglobaladdr:$dst)>;
1423def : Pat<(loongarch_tail (iPTR texternalsym:$dst)),
1424          (PseudoTAIL texternalsym:$dst)>;
1425
1426let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1, Uses = [R3] in
1427def PseudoTAILIndirect : Pseudo<(outs), (ins GPRT:$rj),
1428                                [(loongarch_tail GPRT:$rj)]>,
1429                         PseudoInstExpansion<(JIRL R0, GPR:$rj, 0)>;
1430
1431let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1,
1432    hasSideEffects = 0, mayStore = 0, mayLoad = 0, Uses = [R3] in
1433def PseudoB_TAIL : Pseudo<(outs), (ins simm26_b:$imm26)>,
1434                   PseudoInstExpansion<(B simm26_b:$imm26)>;
1435
1436let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1,
1437    hasSideEffects = 0, mayStore = 0, mayLoad = 0, Uses = [R3] in
1438def PseudoJIRL_TAIL : Pseudo<(outs), (ins GPR:$rj, simm16_lsl2:$imm16)>,
1439                      PseudoInstExpansion<(JIRL R0, GPR:$rj,
1440                                           simm16_lsl2:$imm16)>;
1441
1442/// Load address (la*) macro instructions.
1443
1444// Define isCodeGenOnly = 0 to expose them to tablegened assembly parser.
1445let hasSideEffects = 0, mayLoad = 0, mayStore = 0, isCodeGenOnly = 0,
1446    isAsmParserOnly = 1 in {
1447def PseudoLA_ABS : Pseudo<(outs GPR:$dst), (ins bare_symbol:$src), [],
1448                          "la.abs", "$dst, $src">;
1449def PseudoLA_ABS_LARGE : Pseudo<(outs GPR:$dst),
1450                                (ins GPR:$tmp, bare_symbol:$src), [],
1451                                "la.abs", "$dst, $src">;
1452def PseudoLA_PCREL : Pseudo<(outs GPR:$dst), (ins bare_symbol:$src), [],
1453                            "la.pcrel", "$dst, $src">;
1454def PseudoLA_PCREL_LARGE : Pseudo<(outs GPR:$dst),
1455                                  (ins GPR:$tmp, bare_symbol:$src), [],
1456                                  "la.pcrel", "$dst, $tmp, $src">,
1457                           Requires<[IsLA64]>;
1458def PseudoLA_TLS_LE : Pseudo<(outs GPR:$dst), (ins bare_symbol:$src), [],
1459                             "la.tls.le", "$dst, $src">;
1460}
1461let hasSideEffects = 0, mayLoad = 1, mayStore = 0, isCodeGenOnly = 0,
1462    isAsmParserOnly = 1 in {
1463def PseudoLA_GOT : Pseudo<(outs GPR:$dst), (ins bare_symbol:$src), [],
1464                          "la.got", "$dst, $src">;
1465def PseudoLA_GOT_LARGE : Pseudo<(outs GPR:$dst),
1466                                (ins GPR:$tmp, bare_symbol:$src), [],
1467                                "la.got", "$dst, $tmp, $src">,
1468                         Requires<[IsLA64]>;
1469def PseudoLA_TLS_IE : Pseudo<(outs GPR:$dst), (ins bare_symbol:$src), [],
1470                             "la.tls.ie", "$dst, $src">;
1471def PseudoLA_TLS_IE_LARGE : Pseudo<(outs GPR:$dst),
1472                                   (ins GPR:$tmp, bare_symbol:$src), [],
1473                                   "la.tls.ie", "$dst, $tmp, $src">,
1474                            Requires<[IsLA64]>;
1475def PseudoLA_TLS_LD : Pseudo<(outs GPR:$dst), (ins bare_symbol:$src), [],
1476                             "la.tls.ld", "$dst, $src">;
1477def PseudoLA_TLS_LD_LARGE : Pseudo<(outs GPR:$dst),
1478                                   (ins GPR:$tmp, bare_symbol:$src), [],
1479                                   "la.tls.ld", "$dst, $tmp, $src">,
1480                            Requires<[IsLA64]>;
1481def PseudoLA_TLS_GD : Pseudo<(outs GPR:$dst), (ins bare_symbol:$src), [],
1482                             "la.tls.gd", "$dst, $src">;
1483def PseudoLA_TLS_GD_LARGE : Pseudo<(outs GPR:$dst),
1484                                   (ins GPR:$tmp, bare_symbol:$src), [],
1485                                   "la.tls.gd", "$dst, $tmp, $src">,
1486                            Requires<[IsLA64]>;
1487}
1488
1489// Load address inst alias: "la", "la.global" and "la.local".
1490// Default:
1491//     la = la.global = la.got
1492//     la.local = la.pcrel
1493// With feature "+la-global-with-pcrel":
1494//     la = la.global = la.pcrel
1495// With feature "+la-global-with-abs":
1496//     la = la.global = la.abs
1497// With feature "+la-local-with-abs":
1498//     la.local = la.abs
1499// With features "+la-global-with-pcrel,+la-global-with-abs"(disorder):
1500//     la = la.global = la.pcrel
1501// Note: To keep consistent with gnu-as behavior, the "la" can only have one
1502//       register operand.
1503def : InstAlias<"la $dst, $src", (PseudoLA_GOT GPR:$dst, bare_symbol:$src)>;
1504def : InstAlias<"la.global $dst, $src",
1505                (PseudoLA_GOT GPR:$dst, bare_symbol:$src)>;
1506def : InstAlias<"la.global $dst, $tmp, $src",
1507                (PseudoLA_GOT_LARGE GPR:$dst, GPR:$tmp, bare_symbol:$src)>;
1508def : InstAlias<"la.local $dst, $src",
1509                (PseudoLA_PCREL GPR:$dst, bare_symbol:$src)>;
1510def : InstAlias<"la.local $dst, $tmp, $src",
1511                (PseudoLA_PCREL_LARGE GPR:$dst, GPR:$tmp, bare_symbol:$src)>;
1512
1513// Note: Keep HasLaGlobalWithPcrel before HasLaGlobalWithAbs to ensure
1514// "la-global-with-pcrel" takes effect when bose "la-global-with-pcrel" and
1515// "la-global-with-abs" are enabled.
1516let Predicates = [HasLaGlobalWithPcrel] in {
1517def : InstAlias<"la $dst, $src", (PseudoLA_PCREL GPR:$dst, bare_symbol:$src)>;
1518def : InstAlias<"la.global $dst, $src",
1519                (PseudoLA_PCREL GPR:$dst, bare_symbol:$src)>;
1520def : InstAlias<"la.global $dst, $tmp, $src",
1521                (PseudoLA_PCREL_LARGE GPR:$dst, GPR:$tmp, bare_symbol:$src)>;
1522} // Predicates = [HasLaGlobalWithPcrel]
1523
1524let Predicates = [HasLaGlobalWithAbs] in {
1525def : InstAlias<"la $dst, $src", (PseudoLA_ABS GPR:$dst, bare_symbol:$src)>;
1526def : InstAlias<"la.global $dst, $src",
1527                (PseudoLA_ABS GPR:$dst, bare_symbol:$src)>;
1528def : InstAlias<"la.global $dst, $tmp, $src",
1529                (PseudoLA_ABS_LARGE GPR:$dst, GPR:$tmp, bare_symbol:$src)>;
1530} // Predicates = [HasLaGlobalWithAbs]
1531
1532let Predicates = [HasLaLocalWithAbs] in {
1533def : InstAlias<"la.local $dst, $src",
1534                (PseudoLA_ABS GPR:$dst, bare_symbol:$src)>;
1535def : InstAlias<"la.local $dst, $tmp, $src",
1536                (PseudoLA_ABS_LARGE GPR:$dst, GPR:$tmp, bare_symbol:$src)>;
1537} // Predicates = [HasLaLocalWithAbs]
1538
1539/// BSTRINS and BSTRPICK
1540
1541let Predicates = [IsLA32] in {
1542def : Pat<(loongarch_bstrins GPR:$rd, GPR:$rj, uimm5:$msbd, uimm5:$lsbd),
1543          (BSTRINS_W GPR:$rd, GPR:$rj, uimm5:$msbd, uimm5:$lsbd)>;
1544def : Pat<(loongarch_bstrpick GPR:$rj, uimm5:$msbd, uimm5:$lsbd),
1545          (BSTRPICK_W GPR:$rj, uimm5:$msbd, uimm5:$lsbd)>;
1546} // Predicates = [IsLA32]
1547
1548let Predicates = [IsLA64] in {
1549def : Pat<(loongarch_bstrins GPR:$rd, GPR:$rj, uimm6:$msbd, uimm6:$lsbd),
1550          (BSTRINS_D GPR:$rd, GPR:$rj, uimm6:$msbd, uimm6:$lsbd)>;
1551def : Pat<(loongarch_bstrpick GPR:$rj, uimm6:$msbd, uimm6:$lsbd),
1552          (BSTRPICK_D GPR:$rj, uimm6:$msbd, uimm6:$lsbd)>;
1553} // Predicates = [IsLA64]
1554
1555/// Byte-swapping and bit-reversal
1556
1557def : Pat<(loongarch_revb_2h GPR:$rj), (REVB_2H GPR:$rj)>;
1558def : Pat<(loongarch_bitrev_4b GPR:$rj), (BITREV_4B GPR:$rj)>;
1559
1560let Predicates = [IsLA32] in {
1561def : Pat<(bswap GPR:$rj), (ROTRI_W (REVB_2H GPR:$rj), 16)>;
1562def : Pat<(bitreverse GPR:$rj), (BITREV_W GPR:$rj)>;
1563def : Pat<(bswap (bitreverse GPR:$rj)), (BITREV_4B GPR:$rj)>;
1564def : Pat<(bitreverse (bswap GPR:$rj)), (BITREV_4B GPR:$rj)>;
1565} // Predicates = [IsLA32]
1566
1567let Predicates = [IsLA64] in {
1568def : Pat<(loongarch_revb_2w GPR:$rj), (REVB_2W GPR:$rj)>;
1569def : Pat<(bswap GPR:$rj), (REVB_D GPR:$rj)>;
1570def : Pat<(loongarch_bitrev_w GPR:$rj), (BITREV_W GPR:$rj)>;
1571def : Pat<(bitreverse GPR:$rj), (BITREV_D GPR:$rj)>;
1572def : Pat<(bswap (bitreverse GPR:$rj)), (BITREV_8B GPR:$rj)>;
1573def : Pat<(bitreverse (bswap GPR:$rj)), (BITREV_8B GPR:$rj)>;
1574} // Predicates = [IsLA64]
1575
1576/// Loads
1577
1578multiclass LdPat<PatFrag LoadOp, LAInst Inst, ValueType vt = GRLenVT> {
1579  def : Pat<(vt (LoadOp BaseAddr:$rj)), (Inst BaseAddr:$rj, 0)>;
1580  def : Pat<(vt (LoadOp (AddrConstant GPR:$rj, simm12:$imm12))),
1581            (Inst GPR:$rj, simm12:$imm12)>;
1582  def : Pat<(vt (LoadOp (AddLike BaseAddr:$rj, simm12:$imm12))),
1583            (Inst BaseAddr:$rj, simm12:$imm12)>;
1584}
1585
1586defm : LdPat<sextloadi8, LD_B>;
1587defm : LdPat<extloadi8, LD_B>;
1588defm : LdPat<sextloadi16, LD_H>;
1589defm : LdPat<extloadi16, LD_H>;
1590defm : LdPat<load, LD_W>, Requires<[IsLA32]>;
1591defm : LdPat<zextloadi8, LD_BU>;
1592defm : LdPat<zextloadi16, LD_HU>;
1593let Predicates = [IsLA64] in {
1594defm : LdPat<sextloadi32, LD_W, i64>;
1595defm : LdPat<extloadi32, LD_W, i64>;
1596defm : LdPat<zextloadi32, LD_WU, i64>;
1597defm : LdPat<load, LD_D, i64>;
1598} // Predicates = [IsLA64]
1599
1600// LA64 register-register-addressed loads
1601let Predicates = [IsLA64] in {
1602class RegRegLdPat<PatFrag LoadOp, LAInst Inst, ValueType vt>
1603  : Pat<(vt (LoadOp (add NonFIBaseAddr:$rj, GPR:$rk))),
1604        (Inst NonFIBaseAddr:$rj, GPR:$rk)>;
1605
1606def : RegRegLdPat<extloadi8, LDX_B, i64>;
1607def : RegRegLdPat<sextloadi8, LDX_B, i64>;
1608def : RegRegLdPat<zextloadi8, LDX_BU, i64>;
1609def : RegRegLdPat<extloadi16, LDX_H, i64>;
1610def : RegRegLdPat<sextloadi16, LDX_H, i64>;
1611def : RegRegLdPat<zextloadi16, LDX_HU, i64>;
1612def : RegRegLdPat<extloadi32, LDX_W, i64>;
1613def : RegRegLdPat<sextloadi32, LDX_W, i64>;
1614def : RegRegLdPat<zextloadi32, LDX_WU, i64>;
1615def : RegRegLdPat<load, LDX_D, i64>;
1616} // Predicates = [IsLA64]
1617
1618/// Stores
1619
1620multiclass StPat<PatFrag StoreOp, LAInst Inst, RegisterClass StTy,
1621                 ValueType vt> {
1622  def : Pat<(StoreOp (vt StTy:$rd), BaseAddr:$rj),
1623            (Inst StTy:$rd, BaseAddr:$rj, 0)>;
1624  def : Pat<(StoreOp (vt StTy:$rs2), (AddrConstant GPR:$rj, simm12:$imm12)),
1625            (Inst StTy:$rs2, GPR:$rj, simm12:$imm12)>;
1626  def : Pat<(StoreOp (vt StTy:$rd), (AddLike BaseAddr:$rj, simm12:$imm12)),
1627            (Inst StTy:$rd, BaseAddr:$rj, simm12:$imm12)>;
1628}
1629
1630defm : StPat<truncstorei8, ST_B, GPR, GRLenVT>;
1631defm : StPat<truncstorei16, ST_H, GPR, GRLenVT>;
1632defm : StPat<store, ST_W, GPR, i32>, Requires<[IsLA32]>;
1633let Predicates = [IsLA64] in {
1634defm : StPat<truncstorei32, ST_W, GPR, i64>;
1635defm : StPat<store, ST_D, GPR, i64>;
1636} // Predicates = [IsLA64]
1637
1638let Predicates = [IsLA64] in {
1639def : Pat<(i64 (sextloadi32 (AddLike BaseAddr:$rj, simm14_lsl2:$imm14))),
1640          (LDPTR_W BaseAddr:$rj, simm14_lsl2:$imm14)>;
1641def : Pat<(i64 (load (AddLike BaseAddr:$rj, simm14_lsl2:$imm14))),
1642          (LDPTR_D BaseAddr:$rj, simm14_lsl2:$imm14)>;
1643def : Pat<(truncstorei32 (i64 GPR:$rd),
1644                         (AddLike BaseAddr:$rj, simm14_lsl2:$imm14)),
1645          (STPTR_W GPR:$rd, BaseAddr:$rj, simm14_lsl2:$imm14)>;
1646def : Pat<(store (i64 GPR:$rd), (AddLike BaseAddr:$rj, simm14_lsl2:$imm14)),
1647          (STPTR_D GPR:$rd, BaseAddr:$rj, simm14_lsl2:$imm14)>;
1648} // Predicates = [IsLA64]
1649
1650// LA64 register-register-addressed stores
1651let Predicates = [IsLA64] in {
1652class RegRegStPat<PatFrag StoreOp, LAInst Inst, RegisterClass StTy,
1653                  ValueType vt>
1654  : Pat<(StoreOp (vt StTy:$rd), (add NonFIBaseAddr:$rj, GPR:$rk)),
1655        (Inst StTy:$rd, NonFIBaseAddr:$rj, GPR:$rk)>;
1656
1657def : RegRegStPat<truncstorei8, STX_B, GPR, i64>;
1658def : RegRegStPat<truncstorei16, STX_H, GPR, i64>;
1659def : RegRegStPat<truncstorei32, STX_W, GPR, i64>;
1660def : RegRegStPat<store, STX_D, GPR, i64>;
1661} // Predicates = [IsLA64]
1662
1663/// Atomic loads and stores
1664
1665// DBAR hint encoding for LA664 and later micro-architectures, paraphrased from
1666// the Linux patch revealing it [1]:
1667//
1668// - Bit 4: kind of constraint (0: completion, 1: ordering)
1669// - Bit 3: barrier for previous read (0: true, 1: false)
1670// - Bit 2: barrier for previous write (0: true, 1: false)
1671// - Bit 1: barrier for succeeding read (0: true, 1: false)
1672// - Bit 0: barrier for succeeding write (0: true, 1: false)
1673//
1674// Hint 0x700: barrier for "read after read" from the same address, which is
1675// e.g. needed by LL-SC loops on older models. (DBAR 0x700 behaves the same as
1676// nop if such reordering is disabled on supporting newer models.)
1677//
1678// [1]: https://lore.kernel.org/loongarch/20230516124536.535343-1-chenhuacai@loongson.cn/
1679//
1680// Implementations without support for the finer-granularity hints simply treat
1681// all as the full barrier (DBAR 0), so we can unconditionally start emiting the
1682// more precise hints right away.
1683
1684def : Pat<(atomic_fence 4, timm), (DBAR 0b10100)>; // acquire
1685def : Pat<(atomic_fence 5, timm), (DBAR 0b10010)>; // release
1686def : Pat<(atomic_fence 6, timm), (DBAR 0b10000)>; // acqrel
1687def : Pat<(atomic_fence 7, timm), (DBAR 0b10000)>; // seqcst
1688
1689defm : LdPat<atomic_load_8, LD_B>;
1690defm : LdPat<atomic_load_16, LD_H>;
1691defm : LdPat<atomic_load_32, LD_W>;
1692
1693class release_seqcst_store<PatFrag base>
1694    : PatFrag<(ops node:$val, node:$ptr), (base node:$val, node:$ptr), [{
1695  AtomicOrdering Ordering = cast<AtomicSDNode>(N)->getSuccessOrdering();
1696  return isReleaseOrStronger(Ordering);
1697}]>;
1698
1699class unordered_monotonic_store<PatFrag base>
1700    : PatFrag<(ops node:$val, node:$ptr), (base node:$val, node:$ptr), [{
1701  AtomicOrdering Ordering = cast<AtomicSDNode>(N)->getSuccessOrdering();
1702  return !isReleaseOrStronger(Ordering);
1703}]>;
1704
1705def atomic_store_release_seqcst_32 : release_seqcst_store<atomic_store_32>;
1706def atomic_store_release_seqcst_64 : release_seqcst_store<atomic_store_64>;
1707def atomic_store_unordered_monotonic_32
1708    : unordered_monotonic_store<atomic_store_32>;
1709def atomic_store_unordered_monotonic_64
1710    : unordered_monotonic_store<atomic_store_64>;
1711
1712defm : StPat<atomic_store_8, ST_B, GPR, GRLenVT>;
1713defm : StPat<atomic_store_16, ST_H, GPR, GRLenVT>;
1714defm : StPat<atomic_store_unordered_monotonic_32, ST_W, GPR, i32>,
1715                   Requires<[IsLA32]>;
1716
1717def PseudoAtomicStoreW
1718  : Pseudo<(outs GPR:$dst), (ins GPR:$rk, GPR:$rj)>,
1719           PseudoInstExpansion<(AMSWAP__DB_W R0, GPR:$rk, GPRMemAtomic:$rj)>;
1720
1721def : Pat<(atomic_store_release_seqcst_32 GPR:$rj, GPR:$rk),
1722          (PseudoAtomicStoreW GPR:$rj, GPR:$rk)>;
1723
1724let Predicates = [IsLA64] in {
1725def PseudoAtomicStoreD
1726  : Pseudo<(outs GPR:$dst), (ins GPR:$rk, GPR:$rj)>,
1727           PseudoInstExpansion<(AMSWAP__DB_D R0, GPR:$rk, GPRMemAtomic:$rj)>;
1728
1729def : Pat<(atomic_store_release_seqcst_64 GPR:$rj, GPR:$rk),
1730          (PseudoAtomicStoreD GPR:$rj, GPR:$rk)>;
1731
1732defm : LdPat<atomic_load_64, LD_D>;
1733defm : StPat<atomic_store_unordered_monotonic_32, ST_W, GPR, i64>;
1734defm : StPat<atomic_store_unordered_monotonic_64, ST_D, GPR, i64>;
1735} // Predicates = [IsLA64]
1736
1737/// Atomic Ops
1738
1739class PseudoMaskedAM
1740    : Pseudo<(outs GPR:$res, GPR:$scratch),
1741             (ins GPR:$addr, GPR:$incr, GPR:$mask, grlenimm:$ordering)> {
1742  let Constraints = "@earlyclobber $res,@earlyclobber $scratch";
1743  let mayLoad = 1;
1744  let mayStore = 1;
1745  let hasSideEffects = 0;
1746  let Size = 36;
1747}
1748
1749def PseudoMaskedAtomicSwap32 : PseudoMaskedAM;
1750def PseudoMaskedAtomicLoadAdd32 : PseudoMaskedAM;
1751def PseudoMaskedAtomicLoadSub32 : PseudoMaskedAM;
1752def PseudoMaskedAtomicLoadNand32 : PseudoMaskedAM;
1753
1754class PseudoAM : Pseudo<(outs GPR:$res, GPR:$scratch),
1755                        (ins GPR:$addr, GPR:$incr, grlenimm:$ordering)> {
1756  let Constraints = "@earlyclobber $res,@earlyclobber $scratch";
1757  let mayLoad = 1;
1758  let mayStore = 1;
1759  let hasSideEffects = 0;
1760  let Size = 24;
1761}
1762
1763def PseudoAtomicSwap32 : PseudoAM;
1764def PseudoAtomicLoadNand32 : PseudoAM;
1765def PseudoAtomicLoadNand64 : PseudoAM;
1766def PseudoAtomicLoadAdd32 : PseudoAM;
1767def PseudoAtomicLoadSub32 : PseudoAM;
1768def PseudoAtomicLoadAnd32 : PseudoAM;
1769def PseudoAtomicLoadOr32 : PseudoAM;
1770def PseudoAtomicLoadXor32 : PseudoAM;
1771
1772multiclass PseudoBinPat<string Op, Pseudo BinInst> {
1773  def : Pat<(!cast<PatFrag>(Op#"_monotonic") GPR:$addr, GPR:$incr),
1774            (BinInst GPR:$addr, GPR:$incr, 2)>;
1775  def : Pat<(!cast<PatFrag>(Op#"_acquire") GPR:$addr, GPR:$incr),
1776            (BinInst GPR:$addr, GPR:$incr, 4)>;
1777  def : Pat<(!cast<PatFrag>(Op#"_release") GPR:$addr, GPR:$incr),
1778            (BinInst GPR:$addr, GPR:$incr, 5)>;
1779  def : Pat<(!cast<PatFrag>(Op#"_acq_rel") GPR:$addr, GPR:$incr),
1780            (BinInst GPR:$addr, GPR:$incr, 6)>;
1781  def : Pat<(!cast<PatFrag>(Op#"_seq_cst") GPR:$addr, GPR:$incr),
1782            (BinInst GPR:$addr, GPR:$incr, 7)>;
1783}
1784
1785class PseudoMaskedAMUMinUMax
1786    : Pseudo<(outs GPR:$res, GPR:$scratch1, GPR:$scratch2),
1787             (ins GPR:$addr, GPR:$incr, GPR:$mask, grlenimm:$ordering)> {
1788  let Constraints = "@earlyclobber $res,@earlyclobber $scratch1,"
1789                    "@earlyclobber $scratch2";
1790  let mayLoad = 1;
1791  let mayStore = 1;
1792  let hasSideEffects = 0;
1793  let Size = 48;
1794}
1795
1796def PseudoMaskedAtomicLoadUMax32 : PseudoMaskedAMUMinUMax;
1797def PseudoMaskedAtomicLoadUMin32 : PseudoMaskedAMUMinUMax;
1798
1799class PseudoMaskedAMMinMax
1800    : Pseudo<(outs GPR:$res, GPR:$scratch1, GPR:$scratch2),
1801             (ins GPR:$addr, GPR:$incr, GPR:$mask, grlenimm:$sextshamt,
1802              grlenimm:$ordering)> {
1803  let Constraints = "@earlyclobber $res,@earlyclobber $scratch1,"
1804                    "@earlyclobber $scratch2";
1805  let mayLoad = 1;
1806  let mayStore = 1;
1807  let hasSideEffects = 0;
1808  let Size = 56;
1809}
1810
1811def PseudoMaskedAtomicLoadMax32 : PseudoMaskedAMMinMax;
1812def PseudoMaskedAtomicLoadMin32 : PseudoMaskedAMMinMax;
1813
1814/// Compare and exchange
1815
1816class PseudoCmpXchg
1817    : Pseudo<(outs GPR:$res, GPR:$scratch),
1818             (ins GPR:$addr, GPR:$cmpval, GPR:$newval, grlenimm:$fail_order)> {
1819  let Constraints = "@earlyclobber $res,@earlyclobber $scratch";
1820  let mayLoad = 1;
1821  let mayStore = 1;
1822  let hasSideEffects = 0;
1823  let Size = 36;
1824}
1825
1826def PseudoCmpXchg32 : PseudoCmpXchg;
1827def PseudoCmpXchg64 : PseudoCmpXchg;
1828
1829def PseudoMaskedCmpXchg32
1830    : Pseudo<(outs GPR:$res, GPR:$scratch),
1831             (ins GPR:$addr, GPR:$cmpval, GPR:$newval, GPR:$mask,
1832              grlenimm:$fail_order)> {
1833  let Constraints = "@earlyclobber $res,@earlyclobber $scratch";
1834  let mayLoad = 1;
1835  let mayStore = 1;
1836  let hasSideEffects = 0;
1837  let Size = 44;
1838}
1839
1840class PseudoMaskedAMMinMaxPat<Intrinsic intrin, Pseudo AMInst>
1841    : Pat<(intrin GPR:$addr, GPR:$incr, GPR:$mask, GPR:$shiftamt,
1842           timm:$ordering),
1843          (AMInst GPR:$addr, GPR:$incr, GPR:$mask, GPR:$shiftamt,
1844           timm:$ordering)>;
1845
1846class AtomicPat<Intrinsic intrin, Pseudo AMInst>
1847    : Pat<(intrin GPR:$addr, GPR:$incr, GPR:$mask, timm:$ordering),
1848          (AMInst GPR:$addr, GPR:$incr, GPR:$mask, timm:$ordering)>;
1849
1850// These atomic cmpxchg PatFrags only care about the failure ordering.
1851// The PatFrags defined by multiclass `ternary_atomic_op_ord` in
1852// TargetSelectionDAG.td care about the merged memory ordering that is the
1853// stronger one between success and failure. But for LoongArch LL-SC we only
1854// need to care about the failure ordering as explained in PR #67391. So we
1855// define these PatFrags that will be used to define cmpxchg pats below.
1856multiclass ternary_atomic_op_failure_ord {
1857  def NAME#_failure_monotonic : PatFrag<(ops node:$ptr, node:$cmp, node:$val),
1858      (!cast<SDPatternOperator>(NAME) node:$ptr, node:$cmp, node:$val), [{
1859    AtomicOrdering Ordering = cast<AtomicSDNode>(N)->getFailureOrdering();
1860    return Ordering == AtomicOrdering::Monotonic;
1861  }]>;
1862  def NAME#_failure_acquire : PatFrag<(ops node:$ptr, node:$cmp, node:$val),
1863      (!cast<SDPatternOperator>(NAME) node:$ptr, node:$cmp, node:$val), [{
1864    AtomicOrdering Ordering = cast<AtomicSDNode>(N)->getFailureOrdering();
1865    return Ordering == AtomicOrdering::Acquire;
1866  }]>;
1867  def NAME#_failure_release : PatFrag<(ops node:$ptr, node:$cmp, node:$val),
1868      (!cast<SDPatternOperator>(NAME) node:$ptr, node:$cmp, node:$val), [{
1869    AtomicOrdering Ordering = cast<AtomicSDNode>(N)->getFailureOrdering();
1870    return Ordering == AtomicOrdering::Release;
1871  }]>;
1872  def NAME#_failure_acq_rel : PatFrag<(ops node:$ptr, node:$cmp, node:$val),
1873      (!cast<SDPatternOperator>(NAME) node:$ptr, node:$cmp, node:$val), [{
1874    AtomicOrdering Ordering = cast<AtomicSDNode>(N)->getFailureOrdering();
1875    return Ordering == AtomicOrdering::AcquireRelease;
1876  }]>;
1877  def NAME#_failure_seq_cst : PatFrag<(ops node:$ptr, node:$cmp, node:$val),
1878      (!cast<SDPatternOperator>(NAME) node:$ptr, node:$cmp, node:$val), [{
1879    AtomicOrdering Ordering = cast<AtomicSDNode>(N)->getFailureOrdering();
1880    return Ordering == AtomicOrdering::SequentiallyConsistent;
1881  }]>;
1882}
1883
1884defm atomic_cmp_swap_32 : ternary_atomic_op_failure_ord;
1885defm atomic_cmp_swap_64 : ternary_atomic_op_failure_ord;
1886
1887let Predicates = [IsLA64] in {
1888def : AtomicPat<int_loongarch_masked_atomicrmw_xchg_i64,
1889                PseudoMaskedAtomicSwap32>;
1890def : Pat<(atomic_swap_32 GPR:$addr, GPR:$incr),
1891          (AMSWAP__DB_W GPR:$incr, GPR:$addr)>;
1892def : Pat<(atomic_swap_64 GPR:$addr, GPR:$incr),
1893          (AMSWAP__DB_D GPR:$incr, GPR:$addr)>;
1894def : Pat<(atomic_load_add_64 GPR:$rj, GPR:$rk),
1895          (AMADD__DB_D GPR:$rk, GPR:$rj)>;
1896def : AtomicPat<int_loongarch_masked_atomicrmw_add_i64,
1897                PseudoMaskedAtomicLoadAdd32>;
1898def : Pat<(atomic_load_sub_32 GPR:$rj, GPR:$rk),
1899          (AMADD__DB_W (SUB_W R0, GPR:$rk), GPR:$rj)>;
1900def : Pat<(atomic_load_sub_64 GPR:$rj, GPR:$rk),
1901          (AMADD__DB_D (SUB_D R0, GPR:$rk), GPR:$rj)>;
1902def : AtomicPat<int_loongarch_masked_atomicrmw_sub_i64,
1903                PseudoMaskedAtomicLoadSub32>;
1904defm : PseudoBinPat<"atomic_load_nand_64", PseudoAtomicLoadNand64>;
1905def : AtomicPat<int_loongarch_masked_atomicrmw_nand_i64,
1906                PseudoMaskedAtomicLoadNand32>;
1907def : Pat<(atomic_load_add_32 GPR:$rj, GPR:$rk),
1908          (AMADD__DB_W GPR:$rk, GPR:$rj)>;
1909def : Pat<(atomic_load_and_32 GPR:$rj, GPR:$rk),
1910          (AMAND__DB_W GPR:$rk, GPR:$rj)>;
1911def : Pat<(atomic_load_and_64 GPR:$rj, GPR:$rk),
1912          (AMAND__DB_D GPR:$rk, GPR:$rj)>;
1913def : Pat<(atomic_load_or_32 GPR:$rj, GPR:$rk),
1914          (AMOR__DB_W GPR:$rk, GPR:$rj)>;
1915def : Pat<(atomic_load_or_64 GPR:$rj, GPR:$rk),
1916          (AMOR__DB_D GPR:$rk, GPR:$rj)>;
1917def : Pat<(atomic_load_xor_32 GPR:$rj, GPR:$rk),
1918          (AMXOR__DB_W GPR:$rk, GPR:$rj)>;
1919def : Pat<(atomic_load_xor_64 GPR:$rj, GPR:$rk),
1920          (AMXOR__DB_D GPR:$rk, GPR:$rj)>;
1921
1922def : Pat<(atomic_load_umin_32 GPR:$rj, GPR:$rk),
1923          (AMMIN__DB_WU GPR:$rk, GPR:$rj)>;
1924def : Pat<(atomic_load_umin_64 GPR:$rj, GPR:$rk),
1925          (AMMIN__DB_DU GPR:$rk, GPR:$rj)>;
1926def : Pat<(atomic_load_umax_32 GPR:$rj, GPR:$rk),
1927          (AMMAX__DB_WU GPR:$rk, GPR:$rj)>;
1928def : Pat<(atomic_load_umax_64 GPR:$rj, GPR:$rk),
1929          (AMMAX__DB_DU GPR:$rk, GPR:$rj)>;
1930
1931def : Pat<(atomic_load_min_32 GPR:$rj, GPR:$rk),
1932          (AMMIN__DB_W GPR:$rk, GPR:$rj)>;
1933def : Pat<(atomic_load_min_64 GPR:$rj, GPR:$rk),
1934          (AMMIN__DB_D GPR:$rk, GPR:$rj)>;
1935def : Pat<(atomic_load_max_32 GPR:$rj, GPR:$rk),
1936          (AMMAX__DB_W GPR:$rk, GPR:$rj)>;
1937def : Pat<(atomic_load_max_64 GPR:$rj, GPR:$rk),
1938          (AMMAX__DB_D GPR:$rk, GPR:$rj)>;
1939
1940def : AtomicPat<int_loongarch_masked_atomicrmw_umax_i64,
1941                PseudoMaskedAtomicLoadUMax32>;
1942def : AtomicPat<int_loongarch_masked_atomicrmw_umin_i64,
1943                PseudoMaskedAtomicLoadUMin32>;
1944
1945// Ordering constants must be kept in sync with the AtomicOrdering enum in
1946// AtomicOrdering.h.
1947multiclass PseudoCmpXchgPat<string Op, Pseudo CmpXchgInst,
1948                            ValueType vt = GRLenVT> {
1949  def : Pat<(vt (!cast<PatFrag>(Op#"_failure_monotonic") GPR:$addr, GPR:$cmp, GPR:$new)),
1950            (CmpXchgInst GPR:$addr, GPR:$cmp, GPR:$new, 2)>;
1951  def : Pat<(vt (!cast<PatFrag>(Op#"_failure_acquire") GPR:$addr, GPR:$cmp, GPR:$new)),
1952            (CmpXchgInst GPR:$addr, GPR:$cmp, GPR:$new, 4)>;
1953  def : Pat<(vt (!cast<PatFrag>(Op#"_failure_release") GPR:$addr, GPR:$cmp, GPR:$new)),
1954            (CmpXchgInst GPR:$addr, GPR:$cmp, GPR:$new, 5)>;
1955  def : Pat<(vt (!cast<PatFrag>(Op#"_failure_acq_rel") GPR:$addr, GPR:$cmp, GPR:$new)),
1956            (CmpXchgInst GPR:$addr, GPR:$cmp, GPR:$new, 6)>;
1957  def : Pat<(vt (!cast<PatFrag>(Op#"_failure_seq_cst") GPR:$addr, GPR:$cmp, GPR:$new)),
1958            (CmpXchgInst GPR:$addr, GPR:$cmp, GPR:$new, 7)>;
1959}
1960
1961defm : PseudoCmpXchgPat<"atomic_cmp_swap_32", PseudoCmpXchg32>;
1962defm : PseudoCmpXchgPat<"atomic_cmp_swap_64", PseudoCmpXchg64, i64>;
1963def : Pat<(int_loongarch_masked_cmpxchg_i64
1964            GPR:$addr, GPR:$cmpval, GPR:$newval, GPR:$mask, timm:$fail_order),
1965          (PseudoMaskedCmpXchg32
1966            GPR:$addr, GPR:$cmpval, GPR:$newval, GPR:$mask, timm:$fail_order)>;
1967
1968def : PseudoMaskedAMMinMaxPat<int_loongarch_masked_atomicrmw_max_i64,
1969                              PseudoMaskedAtomicLoadMax32>;
1970def : PseudoMaskedAMMinMaxPat<int_loongarch_masked_atomicrmw_min_i64,
1971                              PseudoMaskedAtomicLoadMin32>;
1972} // Predicates = [IsLA64]
1973
1974defm : PseudoBinPat<"atomic_load_nand_32", PseudoAtomicLoadNand32>;
1975
1976let Predicates = [IsLA32] in {
1977def : AtomicPat<int_loongarch_masked_atomicrmw_xchg_i32,
1978                PseudoMaskedAtomicSwap32>;
1979defm : PseudoBinPat<"atomic_swap_32", PseudoAtomicSwap32>;
1980def : AtomicPat<int_loongarch_masked_atomicrmw_add_i32,
1981                PseudoMaskedAtomicLoadAdd32>;
1982def : AtomicPat<int_loongarch_masked_atomicrmw_sub_i32,
1983                PseudoMaskedAtomicLoadSub32>;
1984def : AtomicPat<int_loongarch_masked_atomicrmw_nand_i32,
1985                PseudoMaskedAtomicLoadNand32>;
1986defm : PseudoBinPat<"atomic_load_add_32", PseudoAtomicLoadAdd32>;
1987defm : PseudoBinPat<"atomic_load_sub_32", PseudoAtomicLoadSub32>;
1988defm : PseudoBinPat<"atomic_load_and_32", PseudoAtomicLoadAnd32>;
1989defm : PseudoBinPat<"atomic_load_or_32", PseudoAtomicLoadOr32>;
1990defm : PseudoBinPat<"atomic_load_xor_32", PseudoAtomicLoadXor32>;
1991} // Predicates = [IsLA32]
1992
1993/// Intrinsics
1994
1995def : Pat<(int_loongarch_cacop_d timm:$op, i64:$rj, timm:$imm12),
1996          (CACOP timm:$op, GPR:$rj, timm:$imm12)>;
1997def : Pat<(int_loongarch_cacop_w i32:$op, i32:$rj, i32:$imm12),
1998          (CACOP timm:$op, GPR:$rj, timm:$imm12)>;
1999def : Pat<(loongarch_dbar uimm15:$imm15), (DBAR uimm15:$imm15)>;
2000def : Pat<(loongarch_ibar uimm15:$imm15), (IBAR uimm15:$imm15)>;
2001def : Pat<(loongarch_break uimm15:$imm15), (BREAK uimm15:$imm15)>;
2002def : Pat<(loongarch_syscall uimm15:$imm15), (SYSCALL uimm15:$imm15)>;
2003
2004let Predicates = [IsLA64] in {
2005// CRC Check Instructions
2006def : PatGprGpr<loongarch_crc_w_b_w, CRC_W_B_W>;
2007def : PatGprGpr<loongarch_crc_w_h_w, CRC_W_H_W>;
2008def : PatGprGpr<loongarch_crc_w_w_w, CRC_W_W_W>;
2009def : PatGprGpr<loongarch_crc_w_d_w, CRC_W_D_W>;
2010def : PatGprGpr<loongarch_crcc_w_b_w, CRCC_W_B_W>;
2011def : PatGprGpr<loongarch_crcc_w_h_w, CRCC_W_H_W>;
2012def : PatGprGpr<loongarch_crcc_w_w_w, CRCC_W_W_W>;
2013def : PatGprGpr<loongarch_crcc_w_d_w, CRCC_W_D_W>;
2014} // Predicates = [IsLA64]
2015
2016/// Other pseudo-instructions
2017
2018// Pessimistically assume the stack pointer will be clobbered
2019let Defs = [R3], Uses = [R3] in {
2020def ADJCALLSTACKDOWN : Pseudo<(outs), (ins i32imm:$amt1, i32imm:$amt2),
2021                              [(callseq_start timm:$amt1, timm:$amt2)]>;
2022def ADJCALLSTACKUP   : Pseudo<(outs), (ins i32imm:$amt1, i32imm:$amt2),
2023                              [(callseq_end timm:$amt1, timm:$amt2)]>;
2024} // Defs = [R3], Uses = [R3]
2025
2026//===----------------------------------------------------------------------===//
2027// Assembler Pseudo Instructions
2028//===----------------------------------------------------------------------===//
2029
2030def : InstAlias<"nop", (ANDI R0, R0, 0)>;
2031def : InstAlias<"move $dst, $src", (OR GPR:$dst, GPR:$src, R0)>;
2032// `ret` is supported since binutils commit 20f2e2686c79a5ac (version 2.40 and
2033// later).
2034def : InstAlias<"ret", (JIRL R0, R1, 0)>;
2035def : InstAlias<"jr $rj", (JIRL R0, GPR:$rj, 0)>;
2036
2037// Branches implemented with alias.
2038// Always output the canonical mnemonic for the pseudo branch instructions.
2039// The GNU tools emit the canonical mnemonic for the branch pseudo instructions
2040// as well (e.g. "bgt" will be recognised by the assembler but never printed by
2041// objdump). Match this behaviour by setting a zero weight.
2042def : InstAlias<"bgt $rj, $rd, $imm16",
2043                (BLT GPR:$rd, GPR:$rj, simm16_lsl2_br:$imm16), 0>;
2044def : InstAlias<"bgtu $rj, $rd, $imm16",
2045                (BLTU GPR:$rd, GPR:$rj, simm16_lsl2_br:$imm16), 0>;
2046def : InstAlias<"ble $rj, $rd, $imm16",
2047                (BGE GPR:$rd, GPR:$rj, simm16_lsl2_br:$imm16), 0>;
2048def : InstAlias<"bleu $rj, $rd, $imm16",
2049                (BGEU GPR:$rd, GPR:$rj, simm16_lsl2_br:$imm16), 0>;
2050def : InstAlias<"bltz $rd, $imm16",
2051                (BLT GPR:$rd, R0, simm16_lsl2_br:$imm16), 0>;
2052def : InstAlias<"bgtz $rj, $imm16",
2053                (BLT R0, GPR:$rj, simm16_lsl2_br:$imm16), 0>;
2054def : InstAlias<"blez $rj, $imm16",
2055                (BGE R0, GPR:$rj, simm16_lsl2_br:$imm16), 0>;
2056def : InstAlias<"bgez $rd, $imm16",
2057                (BGE GPR:$rd, R0, simm16_lsl2_br:$imm16), 0>;
2058
2059// Load immediate.
2060let hasSideEffects = 0, mayLoad = 0, mayStore = 0, isCodeGenOnly = 0,
2061    isAsmParserOnly = 1 in {
2062def PseudoLI_W : Pseudo<(outs GPR:$rd), (ins imm32:$imm), [],
2063                        "li.w", "$rd, $imm">;
2064def PseudoLI_D : Pseudo<(outs GPR:$rd), (ins grlenimm:$imm), [],
2065                        "li.d", "$rd, $imm">, Requires<[IsLA64]>;
2066}
2067
2068//===----------------------------------------------------------------------===//
2069// Basic Floating-Point Instructions
2070//===----------------------------------------------------------------------===//
2071
2072include "LoongArchFloat32InstrInfo.td"
2073include "LoongArchFloat64InstrInfo.td"
2074
2075let Predicates = [HasBasicF], usesCustomInserter = 1 in {
2076  def WRFCSR : Pseudo<(outs), (ins uimm2:$fcsr, GPR:$src),
2077               [(loongarch_movgr2fcsr uimm2:$fcsr, GRLenVT:$src)]>;
2078  def RDFCSR : Pseudo<(outs GPR:$rd), (ins uimm2:$fcsr),
2079               [(set GPR:$rd, (loongarch_movfcsr2gr uimm2:$fcsr))]>;
2080}
2081
2082//===----------------------------------------------------------------------===//
2083// Privilege Instructions
2084//===----------------------------------------------------------------------===//
2085
2086// CSR Access Instructions
2087let hasSideEffects = 1 in
2088def CSRRD : FmtCSR<0x04000000, (outs GPR:$rd), (ins uimm14:$csr_num),
2089                   "$rd, $csr_num">;
2090let hasSideEffects = 1, Constraints = "$rd = $dst" in {
2091def CSRWR : FmtCSR<0x04000020, (outs GPR:$dst),
2092                   (ins GPR:$rd, uimm14:$csr_num), "$rd, $csr_num">;
2093def CSRXCHG : FmtCSRXCHG<0x04000000, (outs GPR:$dst),
2094                         (ins GPR:$rd, GPR:$rj, uimm14:$csr_num),
2095                         "$rd, $rj, $csr_num">;
2096} // hasSideEffects = 1, Constraints = "$rd = $dst"
2097
2098// IOCSR Access Instructions
2099def IOCSRRD_B : IOCSRRD<0x06480000>;
2100def IOCSRRD_H : IOCSRRD<0x06480400>;
2101def IOCSRRD_W : IOCSRRD<0x06480800>;
2102def IOCSRWR_B : IOCSRWR<0x06481000>;
2103def IOCSRWR_H : IOCSRWR<0x06481400>;
2104def IOCSRWR_W : IOCSRWR<0x06481800>;
2105let Predicates = [IsLA64] in {
2106def IOCSRRD_D : IOCSRRD<0x06480c00>;
2107def IOCSRWR_D : IOCSRWR<0x06481c00>;
2108} // Predicates = [IsLA64]
2109
2110// TLB Maintenance Instructions
2111let hasSideEffects = 1, mayLoad = 0, mayStore = 0 in {
2112def TLBSRCH  : FmtI32<0x06482800>;
2113def TLBRD    : FmtI32<0x06482c00>;
2114def TLBWR    : FmtI32<0x06483000>;
2115def TLBFILL  : FmtI32<0x06483400>;
2116def TLBCLR   : FmtI32<0x06482000>;
2117def TLBFLUSH : FmtI32<0x06482400>;
2118def INVTLB : FmtINVTLB<(outs), (ins GPR:$rk, GPR:$rj, uimm5:$op),
2119                       "$op, $rj, $rk">;
2120} // hasSideEffects = 1, mayLoad = 0, mayStore = 0
2121
2122// Software Page Walking Instructions
2123def LDDIR : Fmt2RI8<0x06400000, (outs GPR:$rd),
2124                    (ins GPR:$rj, uimm8:$imm8), "$rd, $rj, $imm8">;
2125def LDPTE : FmtLDPTE<(outs), (ins GPR:$rj, uimm8:$seq), "$rj, $seq">;
2126
2127
2128// Other Miscellaneous Instructions
2129let hasSideEffects = 1, mayLoad = 0, mayStore = 0 in
2130def ERTN : FmtI32<0x06483800>;
2131def DBCL : MISC_I15<0x002a8000>;
2132def IDLE : MISC_I15<0x06488000>;
2133
2134//===----------------------------------------------------------------------===//
2135// Privilege Intrinsics
2136//===----------------------------------------------------------------------===//
2137
2138def : Pat<(loongarch_csrrd uimm14:$imm14), (CSRRD uimm14:$imm14)>;
2139def : Pat<(loongarch_csrwr GPR:$rd, uimm14:$imm14),
2140          (CSRWR GPR:$rd, uimm14:$imm14)>;
2141def : Pat<(loongarch_csrxchg GPR:$rd, GPR:$rj, uimm14:$imm14),
2142          (CSRXCHG GPR:$rd, GPR:$rj, uimm14:$imm14)>;
2143
2144def : Pat<(loongarch_iocsrrd_b GPR:$rj), (IOCSRRD_B GPR:$rj)>;
2145def : Pat<(loongarch_iocsrrd_h GPR:$rj), (IOCSRRD_H GPR:$rj)>;
2146def : Pat<(loongarch_iocsrrd_w GPR:$rj), (IOCSRRD_W GPR:$rj)>;
2147
2148def : Pat<(loongarch_iocsrwr_b GPR:$rd, GPR:$rj), (IOCSRWR_B GPR:$rd, GPR:$rj)>;
2149def : Pat<(loongarch_iocsrwr_h GPR:$rd, GPR:$rj), (IOCSRWR_H GPR:$rd, GPR:$rj)>;
2150def : Pat<(loongarch_iocsrwr_w GPR:$rd, GPR:$rj), (IOCSRWR_W GPR:$rd, GPR:$rj)>;
2151
2152def : Pat<(loongarch_cpucfg GPR:$rj), (CPUCFG GPR:$rj)>;
2153
2154let Predicates = [IsLA64] in {
2155def : Pat<(loongarch_iocsrrd_d GPR:$rj), (IOCSRRD_D GPR:$rj)>;
2156def : Pat<(loongarch_iocsrwr_d GPR:$rd, GPR:$rj), (IOCSRWR_D GPR:$rd, GPR:$rj)>;
2157def : Pat<(int_loongarch_asrtle_d GPR:$rj, GPR:$rk),
2158          (ASRTLE_D GPR:$rj, GPR:$rk)>;
2159def : Pat<(int_loongarch_asrtgt_d GPR:$rj, GPR:$rk),
2160          (ASRTGT_D GPR:$rj, GPR:$rk)>;
2161def : Pat<(int_loongarch_lddir_d GPR:$rj, timm:$imm8),
2162          (LDDIR GPR:$rj, timm:$imm8)>;
2163def : Pat<(int_loongarch_ldpte_d GPR:$rj, timm:$imm8),
2164          (LDPTE GPR:$rj, timm:$imm8)>;
2165} // Predicates = [IsLA64]
2166
2167//===----------------------------------------------------------------------===//
2168// LSX Instructions
2169//===----------------------------------------------------------------------===//
2170include "LoongArchLSXInstrInfo.td"
2171
2172//===----------------------------------------------------------------------===//
2173// LASX Instructions
2174//===----------------------------------------------------------------------===//
2175include "LoongArchLASXInstrInfo.td"
2176
2177//===----------------------------------------------------------------------===//
2178// LVZ Instructions
2179//===----------------------------------------------------------------------===//
2180include "LoongArchLVZInstrInfo.td"
2181
2182//===----------------------------------------------------------------------===//
2183// LBT Instructions
2184//===----------------------------------------------------------------------===//
2185include "LoongArchLBTInstrInfo.td"
2186