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