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