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