xref: /freebsd/contrib/llvm-project/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td (revision 5f4c09dd85bff675e0ca63c55ea3c517e0fddfcc)
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>;
79def loongarch_crc_w_h_w
80    : SDNode<"LoongArchISD::CRC_W_H_W", SDT_LoongArchIntBinOpW>;
81def loongarch_crc_w_w_w
82    : SDNode<"LoongArchISD::CRC_W_W_W", SDT_LoongArchIntBinOpW>;
83def loongarch_crc_w_d_w
84    : SDNode<"LoongArchISD::CRC_W_D_W", SDT_LoongArchIntBinOpW>;
85def loongarch_crcc_w_b_w
86    : SDNode<"LoongArchISD::CRCC_W_B_W", SDT_LoongArchIntBinOpW>;
87def loongarch_crcc_w_h_w
88    : SDNode<"LoongArchISD::CRCC_W_H_W", SDT_LoongArchIntBinOpW>;
89def loongarch_crcc_w_w_w
90    : SDNode<"LoongArchISD::CRCC_W_W_W", SDT_LoongArchIntBinOpW>;
91def loongarch_crcc_w_d_w
92    : SDNode<"LoongArchISD::CRCC_W_D_W", SDT_LoongArchIntBinOpW>;
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", SDT_LoongArchMovfcsr2gr>;
110def loongarch_movgr2fcsr : SDNode<"LoongArchISD::MOVGR2FCSR", SDT_LoongArchMovgr2fcsr,
111                                   [SDNPHasChain, SDNPSideEffect]>;
112def loongarch_syscall : SDNode<"LoongArchISD::SYSCALL", SDT_LoongArchVI,
113                                [SDNPHasChain, SDNPSideEffect]>;
114def loongarch_csrrd : SDNode<"LoongArchISD::CSRRD", SDT_LoongArchCsrrd,
115                              [SDNPHasChain, SDNPSideEffect]>;
116def loongarch_csrwr : SDNode<"LoongArchISD::CSRWR", SDT_LoongArchCsrwr,
117                              [SDNPHasChain, SDNPSideEffect]>;
118def loongarch_csrxchg : SDNode<"LoongArchISD::CSRXCHG",
119                                SDT_LoongArchCsrxchg,
120                                [SDNPHasChain, SDNPSideEffect]>;
121def loongarch_iocsrrd_b : SDNode<"LoongArchISD::IOCSRRD_B", SDTUnaryOp,
122                                  [SDNPHasChain, SDNPSideEffect]>;
123def loongarch_iocsrrd_h : SDNode<"LoongArchISD::IOCSRRD_H", SDTUnaryOp,
124                                  [SDNPHasChain, SDNPSideEffect]>;
125def loongarch_iocsrrd_w : SDNode<"LoongArchISD::IOCSRRD_W", SDTUnaryOp,
126                                  [SDNPHasChain, SDNPSideEffect]>;
127def loongarch_iocsrrd_d : SDNode<"LoongArchISD::IOCSRRD_D", SDTUnaryOp,
128                                  [SDNPHasChain, SDNPSideEffect]>;
129def loongarch_iocsrwr_b : SDNode<"LoongArchISD::IOCSRWR_B",
130                                  SDT_LoongArchIocsrwr,
131                                  [SDNPHasChain, SDNPSideEffect]>;
132def loongarch_iocsrwr_h : SDNode<"LoongArchISD::IOCSRWR_H",
133                                  SDT_LoongArchIocsrwr,
134                                  [SDNPHasChain, SDNPSideEffect]>;
135def loongarch_iocsrwr_w : SDNode<"LoongArchISD::IOCSRWR_W",
136                                  SDT_LoongArchIocsrwr,
137                                  [SDNPHasChain, SDNPSideEffect]>;
138def loongarch_iocsrwr_d : SDNode<"LoongArchISD::IOCSRWR_D",
139                                  SDT_LoongArchIocsrwr,
140                                  [SDNPHasChain, SDNPSideEffect]>;
141def loongarch_cpucfg : SDNode<"LoongArchISD::CPUCFG", SDTUnaryOp,
142                               [SDNPHasChain, SDNPSideEffect]>;
143
144//===----------------------------------------------------------------------===//
145// Operand and SDNode transformation definitions.
146//===----------------------------------------------------------------------===//
147
148class ImmAsmOperand<string prefix, int width, string suffix>
149    : AsmOperandClass {
150  let Name = prefix # "Imm" # width # suffix;
151  let DiagnosticType = !strconcat("Invalid", Name);
152  let RenderMethod = "addImmOperands";
153}
154
155class SImmAsmOperand<int width, string suffix = "">
156    : ImmAsmOperand<"S", width, suffix> {
157}
158
159class UImmAsmOperand<int width, string suffix = "">
160    : ImmAsmOperand<"U", width, suffix> {
161}
162
163// A parse method for "$r*" or "$r*, 0", where the 0 is be silently ignored.
164// Only used for "AM*" instructions, in order to be compatible with GAS.
165def AtomicMemAsmOperand : AsmOperandClass {
166  let Name = "AtomicMemAsmOperand";
167  let RenderMethod = "addRegOperands";
168  let PredicateMethod = "isGPR";
169  let ParserMethod = "parseAtomicMemOp";
170}
171
172def GPRMemAtomic : RegisterOperand<GPR> {
173  let ParserMatchClass = AtomicMemAsmOperand;
174  let PrintMethod = "printAtomicMemOp";
175}
176
177// A parameterized register class alternative to i32imm/i64imm from Target.td.
178def grlenimm : Operand<GRLenVT>;
179def imm32 : Operand<GRLenVT> {
180  let ParserMatchClass = ImmAsmOperand<"", 32, "">;
181}
182
183def uimm2 : Operand<GRLenVT>, ImmLeaf<GRLenVT, [{return isUInt<2>(Imm);}]> {
184  let ParserMatchClass = UImmAsmOperand<2>;
185}
186
187def uimm2_plus1 : Operand<GRLenVT>,
188    ImmLeaf<GRLenVT, [{return isUInt<2>(Imm - 1);}]> {
189  let ParserMatchClass = UImmAsmOperand<2, "plus1">;
190  let EncoderMethod = "getImmOpValueSub1";
191  let DecoderMethod = "decodeUImmOperand<2, 1>";
192}
193
194def uimm3 : Operand<GRLenVT> {
195  let ParserMatchClass = UImmAsmOperand<3>;
196}
197
198def uimm5 : Operand<GRLenVT>, ImmLeaf<GRLenVT, [{return isUInt<5>(Imm);}]> {
199  let ParserMatchClass = UImmAsmOperand<5>;
200}
201
202def uimm6 : Operand<GRLenVT>, ImmLeaf<GRLenVT, [{return isUInt<6>(Imm);}]> {
203  let ParserMatchClass = UImmAsmOperand<6>;
204}
205
206def uimm8 : Operand<GRLenVT>, ImmLeaf<GRLenVT, [{return isUInt<8>(Imm);}]> {
207  let ParserMatchClass = UImmAsmOperand<8>;
208}
209
210class UImm12Operand : Operand<GRLenVT>,
211                      ImmLeaf <GRLenVT, [{return isUInt<12>(Imm);}]> {
212  let DecoderMethod = "decodeUImmOperand<12>";
213}
214
215def uimm12 : UImm12Operand {
216  let ParserMatchClass = UImmAsmOperand<12>;
217}
218
219def uimm12_ori : UImm12Operand {
220  let ParserMatchClass = UImmAsmOperand<12, "ori">;
221}
222
223def uimm14 : Operand<GRLenVT>,
224             ImmLeaf <GRLenVT, [{return isUInt<14>(Imm);}]> {
225  let ParserMatchClass = UImmAsmOperand<14>;
226}
227
228def uimm15 : Operand<GRLenVT>,
229             ImmLeaf <GRLenVT, [{return isUInt<15>(Imm);}]> {
230  let ParserMatchClass = UImmAsmOperand<15>;
231}
232
233class SImm12Operand : Operand<GRLenVT>,
234                      ImmLeaf <GRLenVT, [{return isInt<12>(Imm);}]> {
235  let DecoderMethod = "decodeSImmOperand<12>";
236}
237
238def simm12 : SImm12Operand {
239  let ParserMatchClass = SImmAsmOperand<12>;
240}
241
242def simm12_addlike : SImm12Operand {
243  let ParserMatchClass = SImmAsmOperand<12, "addlike">;
244}
245
246def simm12_lu52id : SImm12Operand {
247  let ParserMatchClass = SImmAsmOperand<12, "lu52id">;
248}
249
250def simm14_lsl2 : Operand<GRLenVT>,
251    ImmLeaf<GRLenVT, [{return isShiftedInt<14,2>(Imm);}]> {
252  let ParserMatchClass = SImmAsmOperand<14, "lsl2">;
253  let EncoderMethod = "getImmOpValueAsr2";
254  let DecoderMethod = "decodeSImmOperand<14, 2>";
255}
256
257def simm16 : Operand<GRLenVT> {
258  let ParserMatchClass = SImmAsmOperand<16>;
259  let DecoderMethod = "decodeSImmOperand<16>";
260}
261
262def simm16_lsl2 : Operand<GRLenVT>,
263    ImmLeaf<GRLenVT, [{return isInt<16>(Imm>>2);}]> {
264  let ParserMatchClass = SImmAsmOperand<16, "lsl2">;
265  let EncoderMethod = "getImmOpValueAsr2";
266  let DecoderMethod = "decodeSImmOperand<16, 2>";
267}
268
269def simm16_lsl2_br : Operand<OtherVT> {
270  let ParserMatchClass = SImmAsmOperand<16, "lsl2">;
271  let EncoderMethod = "getImmOpValueAsr2";
272  let DecoderMethod = "decodeSImmOperand<16, 2>";
273}
274
275class SImm20Operand : Operand<GRLenVT> {
276  let DecoderMethod = "decodeSImmOperand<20>";
277}
278
279def simm20 : SImm20Operand {
280  let ParserMatchClass = SImmAsmOperand<20>;
281}
282
283def simm20_pcalau12i : SImm20Operand {
284  let ParserMatchClass = SImmAsmOperand<20, "pcalau12i">;
285}
286
287def simm20_lu12iw : SImm20Operand {
288  let ParserMatchClass = SImmAsmOperand<20, "lu12iw">;
289}
290
291def simm20_lu32id : SImm20Operand {
292  let ParserMatchClass = SImmAsmOperand<20, "lu32id">;
293}
294
295def simm21_lsl2 : Operand<OtherVT> {
296  let ParserMatchClass = SImmAsmOperand<21, "lsl2">;
297  let EncoderMethod = "getImmOpValueAsr2";
298  let DecoderMethod = "decodeSImmOperand<21, 2>";
299}
300
301def SImm26OperandB: AsmOperandClass {
302  let Name = "SImm26OperandB";
303  let PredicateMethod = "isSImm26Operand";
304  let RenderMethod = "addImmOperands";
305  let DiagnosticType = "InvalidSImm26Operand";
306  let ParserMethod = "parseImmediate";
307}
308
309// A symbol or an imm used in B/PseudoBR.
310def simm26_b : Operand<OtherVT> {
311  let ParserMatchClass = SImm26OperandB;
312  let EncoderMethod = "getImmOpValueAsr2";
313  let DecoderMethod = "decodeSImmOperand<26, 2>";
314}
315
316def SImm26OperandBL: AsmOperandClass {
317  let Name = "SImm26OperandBL";
318  let PredicateMethod = "isSImm26Operand";
319  let RenderMethod = "addImmOperands";
320  let DiagnosticType = "InvalidSImm26Operand";
321  let ParserMethod = "parseSImm26Operand";
322}
323
324// A symbol or an imm used in BL/PseudoCALL/PseudoTAIL.
325def simm26_symbol : Operand<GRLenVT> {
326  let ParserMatchClass = SImm26OperandBL;
327  let EncoderMethod = "getImmOpValueAsr2";
328  let DecoderMethod = "decodeSImmOperand<26, 2>";
329}
330
331def BareSymbol : AsmOperandClass {
332  let Name = "BareSymbol";
333  let RenderMethod = "addImmOperands";
334  let DiagnosticType = "InvalidBareSymbol";
335  let ParserMethod = "parseImmediate";
336}
337
338// A bare symbol used in "PseudoLA_*" instructions.
339def bare_symbol : Operand<GRLenVT> {
340  let ParserMatchClass = BareSymbol;
341}
342
343// Standalone (codegen-only) immleaf patterns.
344
345// A 12-bit signed immediate plus one where the imm range will be [-2047, 2048].
346def simm12_plus1 : ImmLeaf<GRLenVT,
347  [{return (isInt<12>(Imm) && Imm != -2048) || Imm == 2048;}]>;
348
349// Return the negation of an immediate value.
350def NegImm : SDNodeXForm<imm, [{
351  return CurDAG->getTargetConstant(-N->getSExtValue(), SDLoc(N),
352                                   N->getValueType(0));
353}]>;
354
355// FP immediate patterns.
356def fpimm0    : PatLeaf<(fpimm), [{return N->isExactlyValue(+0.0);}]>;
357def fpimm0neg : PatLeaf<(fpimm), [{return N->isExactlyValue(-0.0);}]>;
358def fpimm1    : PatLeaf<(fpimm), [{return N->isExactlyValue(+1.0);}]>;
359
360// Return an immediate subtracted from 32.
361def ImmSubFrom32 : SDNodeXForm<imm, [{
362  return CurDAG->getTargetConstant(32 - N->getZExtValue(), SDLoc(N),
363                                   N->getValueType(0));
364}]>;
365
366def BaseAddr : ComplexPattern<iPTR, 1, "SelectBaseAddr">;
367def NonFIBaseAddr : ComplexPattern<iPTR, 1, "selectNonFIBaseAddr">;
368
369def fma_nsz : PatFrag<(ops node:$fj, node:$fk, node:$fa),
370                      (fma node:$fj, node:$fk, node:$fa), [{
371  return N->getFlags().hasNoSignedZeros();
372}]>;
373
374//===----------------------------------------------------------------------===//
375// Instruction Formats
376//===----------------------------------------------------------------------===//
377
378include "LoongArchInstrFormats.td"
379include "LoongArchFloatInstrFormats.td"
380
381//===----------------------------------------------------------------------===//
382// Instruction Class Templates
383//===----------------------------------------------------------------------===//
384
385class ALU_3R<bits<17> op, string opstr>
386    : Fmt3R<op, (outs GPR:$rd), (ins GPR:$rj, GPR:$rk), opstr, "$rd, $rj, $rk">;
387class ALU_2R<bits<22> op, string opstr>
388    : Fmt2R<op, (outs GPR:$rd), (ins GPR:$rj), opstr, "$rd, $rj">;
389
390class ALU_3RI2<bits<15> op, string opstr, Operand ImmOpnd>
391    : Fmt3RI2<op, (outs GPR:$rd), (ins GPR:$rj, GPR:$rk, ImmOpnd:$imm2), opstr,
392              "$rd, $rj, $rk, $imm2">;
393class ALU_3RI3<bits<14> op, string opstr, Operand ImmOpnd>
394    : Fmt3RI3<op, (outs GPR:$rd), (ins GPR:$rj, GPR:$rk, ImmOpnd:$imm3), opstr,
395              "$rd, $rj, $rk, $imm3">;
396class ALU_2RI5<bits<17> op, string opstr, Operand ImmOpnd>
397    : Fmt2RI5<op, (outs GPR:$rd), (ins GPR:$rj, ImmOpnd:$imm5), opstr,
398              "$rd, $rj, $imm5">;
399class ALU_2RI6<bits<16> op, string opstr, Operand ImmOpnd>
400    : Fmt2RI6<op, (outs GPR:$rd), (ins GPR:$rj, ImmOpnd:$imm6), opstr,
401              "$rd, $rj, $imm6">;
402class ALU_2RI12<bits<10> op, string opstr, Operand ImmOpnd>
403    : Fmt2RI12<op, (outs GPR:$rd), (ins GPR:$rj, ImmOpnd:$imm12), opstr,
404               "$rd, $rj, $imm12">;
405class ALU_2RI16<bits<6> op, string opstr, Operand ImmOpnd>
406    : Fmt2RI16<op, (outs GPR:$rd), (ins GPR:$rj, ImmOpnd:$imm16), opstr,
407               "$rd, $rj, $imm16">;
408class ALU_1RI20<bits<7> op, string opstr, Operand ImmOpnd>
409    : Fmt1RI20<op, (outs GPR:$rd), (ins ImmOpnd:$imm20), opstr, "$rd, $imm20">;
410
411class MISC_I15<bits<17> op, string opstr>
412    : FmtI15<op, (outs), (ins uimm15:$imm15), opstr, "$imm15">;
413
414class RDTIME_2R<bits<22> op, string opstr>
415    : Fmt2R<op, (outs GPR:$rd, GPR:$rj), (ins), opstr, "$rd, $rj">;
416
417class BrCC_2RI16<bits<6> op, string opstr>
418    : Fmt2RI16<op, (outs), (ins GPR:$rj, GPR:$rd, simm16_lsl2_br:$imm16), opstr,
419               "$rj, $rd, $imm16"> {
420  let isBranch = 1;
421  let isTerminator = 1;
422}
423class BrCCZ_1RI21<bits<6> op, string opstr>
424    : Fmt1RI21<op, (outs), (ins GPR:$rj, simm21_lsl2:$imm21), opstr,
425               "$rj, $imm21"> {
426  let isBranch = 1;
427  let isTerminator = 1;
428}
429class Br_I26<bits<6> op, string opstr>
430    : FmtI26<op, (outs), (ins simm26_b:$imm26), opstr, "$imm26"> {
431  let isBranch = 1;
432  let isTerminator = 1;
433}
434
435let mayLoad = 1 in {
436class LOAD_3R<bits<17> op, string opstr>
437    : Fmt3R<op, (outs GPR:$rd), (ins GPR:$rj, GPR:$rk), opstr, "$rd, $rj, $rk">;
438class LOAD_2RI12<bits<10> op, string opstr>
439    : Fmt2RI12<op, (outs GPR:$rd), (ins GPR:$rj, simm12_addlike:$imm12), opstr,
440               "$rd, $rj, $imm12">;
441class LOAD_2RI14<bits<8> op, string opstr>
442    : Fmt2RI14<op, (outs GPR:$rd), (ins GPR:$rj, simm14_lsl2:$imm14), opstr,
443               "$rd, $rj, $imm14">;
444} // mayLoad = 1
445
446let mayStore = 1 in {
447class STORE_3R<bits<17> op, string opstr>
448    : Fmt3R<op, (outs), (ins GPR:$rd, GPR:$rj, GPR:$rk), opstr,
449            "$rd, $rj, $rk">;
450class STORE_2RI12<bits<10> op, string opstr>
451    : Fmt2RI12<op, (outs), (ins GPR:$rd, GPR:$rj, simm12_addlike:$imm12), opstr,
452               "$rd, $rj, $imm12">;
453class STORE_2RI14<bits<8> op, string opstr>
454    : Fmt2RI14<op, (outs), (ins GPR:$rd, GPR:$rj, simm14_lsl2:$imm14), opstr,
455               "$rd, $rj, $imm14">;
456} // mayStore = 1
457
458let mayLoad = 1, mayStore = 1, Constraints = "@earlyclobber $rd" in
459class AM_3R<bits<17> op, string opstr>
460    : Fmt3R<op, (outs GPR:$rd), (ins GPR:$rk, GPRMemAtomic:$rj), opstr,
461            "$rd, $rk, $rj">;
462
463let mayLoad = 1 in
464class LLBase<bits<8> op, string opstr>
465    : Fmt2RI14<op, (outs GPR:$rd), (ins GPR:$rj, simm14_lsl2:$imm14), opstr,
466               "$rd, $rj, $imm14">;
467
468let mayStore = 1, Constraints = "$rd = $dst" in
469class SCBase<bits<8> op, string opstr>
470    : Fmt2RI14<op, (outs GPR:$dst), (ins GPR:$rd, GPR:$rj, simm14_lsl2:$imm14),
471               opstr, "$rd, $rj, $imm14">;
472
473class IOCSRRD<bits<22> op, string opstr>
474    : Fmt2R<op, (outs GPR:$rd), (ins GPR:$rj), opstr, "$rd, $rj">;
475
476class IOCSRWR<bits<22> op, string opstr>
477    : Fmt2R<op, (outs), (ins GPR:$rd, GPR:$rj), opstr, "$rd, $rj">;
478
479//===----------------------------------------------------------------------===//
480// Basic Integer Instructions
481//===----------------------------------------------------------------------===//
482
483// Arithmetic Operation Instructions
484def ADD_W : ALU_3R<0b00000000000100000, "add.w">;
485def SUB_W : ALU_3R<0b00000000000100010, "sub.w">;
486def ADDI_W : ALU_2RI12<0b0000001010, "addi.w", simm12_addlike>;
487def ALSL_W : ALU_3RI2<0b000000000000010, "alsl.w", uimm2_plus1>;
488def LU12I_W : ALU_1RI20<0b0001010, "lu12i.w", simm20_lu12iw>;
489def SLT  : ALU_3R<0b00000000000100100, "slt">;
490def SLTU : ALU_3R<0b00000000000100101, "sltu">;
491def SLTI  : ALU_2RI12<0b0000001000, "slti", simm12>;
492def SLTUI : ALU_2RI12<0b0000001001, "sltui", simm12>;
493def PCADDI    : ALU_1RI20<0b0001100, "pcaddi", simm20>;
494def PCADDU12I : ALU_1RI20<0b0001110, "pcaddu12i", simm20>;
495def PCALAU12I : ALU_1RI20<0b0001101, "pcalau12i", simm20_pcalau12i>;
496def AND  : ALU_3R<0b00000000000101001, "and">;
497def OR   : ALU_3R<0b00000000000101010, "or">;
498def NOR  : ALU_3R<0b00000000000101000, "nor">;
499def XOR  : ALU_3R<0b00000000000101011, "xor">;
500def ANDN : ALU_3R<0b00000000000101101, "andn">;
501def ORN  : ALU_3R<0b00000000000101100, "orn">;
502def ANDI : ALU_2RI12<0b0000001101, "andi", uimm12>;
503def ORI  : ALU_2RI12<0b0000001110, "ori", uimm12_ori>;
504def XORI : ALU_2RI12<0b0000001111, "xori", uimm12>;
505def MUL_W   : ALU_3R<0b00000000000111000, "mul.w">;
506def MULH_W  : ALU_3R<0b00000000000111001, "mulh.w">;
507def MULH_WU : ALU_3R<0b00000000000111010, "mulh.wu">;
508let usesCustomInserter = true in {
509def DIV_W   : ALU_3R<0b00000000001000000, "div.w">;
510def MOD_W   : ALU_3R<0b00000000001000001, "mod.w">;
511def DIV_WU  : ALU_3R<0b00000000001000010, "div.wu">;
512def MOD_WU  : ALU_3R<0b00000000001000011, "mod.wu">;
513} // usesCustomInserter = true
514
515// Bit-shift Instructions
516def SLL_W  : ALU_3R<0b00000000000101110, "sll.w">;
517def SRL_W  : ALU_3R<0b00000000000101111, "srl.w">;
518def SRA_W  : ALU_3R<0b00000000000110000, "sra.w">;
519def ROTR_W : ALU_3R<0b00000000000110110, "rotr.w">;
520
521def SLLI_W  : ALU_2RI5<0b00000000010000001, "slli.w", uimm5>;
522def SRLI_W  : ALU_2RI5<0b00000000010001001, "srli.w", uimm5>;
523def SRAI_W  : ALU_2RI5<0b00000000010010001, "srai.w", uimm5>;
524def ROTRI_W : ALU_2RI5<0b00000000010011001, "rotri.w", uimm5>;
525
526// Bit-manipulation Instructions
527def EXT_W_B : ALU_2R<0b0000000000000000010111, "ext.w.b">;
528def EXT_W_H : ALU_2R<0b0000000000000000010110, "ext.w.h">;
529def CLO_W   : ALU_2R<0b0000000000000000000100, "clo.w">;
530def CLZ_W   : ALU_2R<0b0000000000000000000101, "clz.w">;
531def CTO_W   : ALU_2R<0b0000000000000000000110, "cto.w">;
532def CTZ_W   : ALU_2R<0b0000000000000000000111, "ctz.w">;
533def BYTEPICK_W : ALU_3RI2<0b000000000000100, "bytepick.w", uimm2>;
534def REVB_2H   : ALU_2R<0b0000000000000000001100, "revb.2h">;
535def BITREV_4B : ALU_2R<0b0000000000000000010010, "bitrev.4b">;
536def BITREV_W  : ALU_2R<0b0000000000000000010100, "bitrev.w">;
537let Constraints = "$rd = $dst" in {
538def BSTRINS_W  : FmtBSTR_W<0b000000000110, (outs GPR:$dst),
539                           (ins GPR:$rd, GPR:$rj, uimm5:$msbw, uimm5:$lsbw),
540                           "bstrins.w", "$rd, $rj, $msbw, $lsbw">;
541}
542def BSTRPICK_W : FmtBSTR_W<0b000000000111, (outs GPR:$rd),
543                           (ins GPR:$rj, uimm5:$msbw, uimm5:$lsbw),
544                           "bstrpick.w", "$rd, $rj, $msbw, $lsbw">;
545def MASKEQZ : ALU_3R<0b00000000000100110, "maskeqz">;
546def MASKNEZ : ALU_3R<0b00000000000100111, "masknez">;
547
548// Branch Instructions
549def BEQ  : BrCC_2RI16<0b010110, "beq">;
550def BNE  : BrCC_2RI16<0b010111, "bne">;
551def BLT  : BrCC_2RI16<0b011000, "blt">;
552def BGE  : BrCC_2RI16<0b011001, "bge">;
553def BLTU : BrCC_2RI16<0b011010, "bltu">;
554def BGEU : BrCC_2RI16<0b011011, "bgeu">;
555def BEQZ : BrCCZ_1RI21<0b010000, "beqz">;
556def BNEZ : BrCCZ_1RI21<0b010001, "bnez">;
557def B : Br_I26<0b010100, "b">;
558
559let isCall = 1, Defs=[R1] in
560def BL : FmtI26<0b010101, (outs), (ins simm26_symbol:$imm26), "bl", "$imm26">;
561def JIRL : Fmt2RI16<0b010011, (outs GPR:$rd),
562                    (ins GPR:$rj, simm16_lsl2:$imm16), "jirl",
563                    "$rd, $rj, $imm16">;
564
565// Common Memory Access Instructions
566def LD_B  : LOAD_2RI12<0b0010100000, "ld.b">;
567def LD_H  : LOAD_2RI12<0b0010100001, "ld.h">;
568def LD_W  : LOAD_2RI12<0b0010100010, "ld.w">;
569def LD_BU : LOAD_2RI12<0b0010101000, "ld.bu">;
570def LD_HU : LOAD_2RI12<0b0010101001, "ld.hu">;
571def ST_B : STORE_2RI12<0b0010100100, "st.b">;
572def ST_H : STORE_2RI12<0b0010100101, "st.h">;
573def ST_W : STORE_2RI12<0b0010100110, "st.w">;
574def PRELD : FmtPRELD<(outs), (ins uimm5:$imm5, GPR:$rj, simm12:$imm12), "preld",
575                     "$imm5, $rj, $imm12">;
576
577// Atomic Memory Access Instructions
578def LL_W : LLBase<0b00100000, "ll.w">;
579def SC_W : SCBase<0b00100001, "sc.w">;
580
581// Barrier Instructions
582def DBAR : MISC_I15<0b00111000011100100, "dbar">;
583def IBAR : MISC_I15<0b00111000011100101, "ibar">;
584
585// Other Miscellaneous Instructions
586def SYSCALL : MISC_I15<0b00000000001010110, "syscall">;
587def BREAK   : MISC_I15<0b00000000001010100, "break">;
588def RDTIMEL_W : RDTIME_2R<0b0000000000000000011000, "rdtimel.w">;
589def RDTIMEH_W : RDTIME_2R<0b0000000000000000011001, "rdtimeh.w">;
590def CPUCFG : ALU_2R<0b0000000000000000011011, "cpucfg">;
591
592// Cache Maintenance Instructions
593def CACOP : FmtCACOP<(outs), (ins uimm5:$op, GPR:$rj, simm12:$imm12), "cacop",
594                     "$op, $rj, $imm12">;
595
596/// LA64 instructions
597
598let Predicates = [IsLA64] in {
599
600// Arithmetic Operation Instructions for 64-bits
601def ADD_D : ALU_3R<0b00000000000100001, "add.d">;
602def SUB_D : ALU_3R<0b00000000000100011, "sub.d">;
603def ADDI_D : ALU_2RI12<0b0000001011, "addi.d", simm12_addlike>;
604def ADDU16I_D : ALU_2RI16<0b000100, "addu16i.d", simm16>;
605def ALSL_WU : ALU_3RI2<0b000000000000011, "alsl.wu", uimm2_plus1>;
606def ALSL_D  : ALU_3RI2<0b000000000010110, "alsl.d", uimm2_plus1>;
607let Constraints = "$rd = $dst" in {
608def LU32I_D : Fmt1RI20<0b0001011, (outs GPR:$dst),
609                       (ins GPR:$rd, simm20_lu32id:$imm20), "lu32i.d",
610                       "$rd, $imm20">;
611}
612def LU52I_D : ALU_2RI12<0b0000001100, "lu52i.d", simm12_lu52id>;
613def PCADDU18I : ALU_1RI20<0b0001111, "pcaddu18i", simm20>;
614def MUL_D     : ALU_3R<0b00000000000111011, "mul.d">;
615def MULH_D    : ALU_3R<0b00000000000111100, "mulh.d">;
616def MULH_DU   : ALU_3R<0b00000000000111101, "mulh.du">;
617def MULW_D_W  : ALU_3R<0b00000000000111110, "mulw.d.w">;
618def MULW_D_WU : ALU_3R<0b00000000000111111, "mulw.d.wu">;
619let usesCustomInserter = true in {
620def DIV_D     : ALU_3R<0b00000000001000100, "div.d">;
621def MOD_D     : ALU_3R<0b00000000001000101, "mod.d">;
622def DIV_DU    : ALU_3R<0b00000000001000110, "div.du">;
623def MOD_DU    : ALU_3R<0b00000000001000111, "mod.du">;
624} // usesCustomInserter = true
625
626// Bit-shift Instructions for 64-bits
627def SLL_D  : ALU_3R<0b00000000000110001, "sll.d">;
628def SRL_D  : ALU_3R<0b00000000000110010, "srl.d">;
629def SRA_D  : ALU_3R<0b00000000000110011, "sra.d">;
630def ROTR_D : ALU_3R<0b00000000000110111, "rotr.d">;
631def SLLI_D  : ALU_2RI6<0b0000000001000001, "slli.d", uimm6>;
632def SRLI_D  : ALU_2RI6<0b0000000001000101, "srli.d", uimm6>;
633def SRAI_D  : ALU_2RI6<0b0000000001001001, "srai.d", uimm6>;
634def ROTRI_D : ALU_2RI6<0b0000000001001101, "rotri.d", uimm6>;
635
636// Bit-manipulation Instructions for 64-bits
637def CLO_D : ALU_2R<0b0000000000000000001000, "clo.d">;
638def CLZ_D : ALU_2R<0b0000000000000000001001, "clz.d">;
639def CTO_D : ALU_2R<0b0000000000000000001010, "cto.d">;
640def CTZ_D : ALU_2R<0b0000000000000000001011, "ctz.d">;
641def BYTEPICK_D : ALU_3RI3<0b00000000000011, "bytepick.d", uimm3>;
642def REVB_4H   : ALU_2R<0b0000000000000000001101, "revb.4h">;
643def REVB_2W   : ALU_2R<0b0000000000000000001110, "revb.2w">;
644def REVB_D    : ALU_2R<0b0000000000000000001111, "revb.d">;
645def REVH_2W   : ALU_2R<0b0000000000000000010000, "revh.2w">;
646def REVH_D    : ALU_2R<0b0000000000000000010001, "revh.d">;
647def BITREV_8B : ALU_2R<0b0000000000000000010011, "bitrev.8b">;
648def BITREV_D  : ALU_2R<0b0000000000000000010101, "bitrev.d">;
649let Constraints = "$rd = $dst" in {
650def BSTRINS_D  : FmtBSTR_D<0b0000000010, (outs GPR:$dst),
651                           (ins GPR:$rd, GPR:$rj, uimm6:$msbd, uimm6:$lsbd),
652                           "bstrins.d", "$rd, $rj, $msbd, $lsbd">;
653}
654def BSTRPICK_D : FmtBSTR_D<0b0000000011, (outs GPR:$rd),
655                           (ins GPR:$rj, uimm6:$msbd, uimm6:$lsbd),
656                           "bstrpick.d", "$rd, $rj, $msbd, $lsbd">;
657
658// Common Memory Access Instructions for 64-bits
659def LD_WU : LOAD_2RI12<0b0010101010, "ld.wu">;
660def LD_D  : LOAD_2RI12<0b0010100011, "ld.d">;
661def ST_D : STORE_2RI12<0b0010100111, "st.d">;
662def LDX_B  : LOAD_3R<0b00111000000000000, "ldx.b">;
663def LDX_H  : LOAD_3R<0b00111000000001000, "ldx.h">;
664def LDX_W  : LOAD_3R<0b00111000000010000, "ldx.w">;
665def LDX_D  : LOAD_3R<0b00111000000011000, "ldx.d">;
666def LDX_BU : LOAD_3R<0b00111000001000000, "ldx.bu">;
667def LDX_HU : LOAD_3R<0b00111000001001000, "ldx.hu">;
668def LDX_WU : LOAD_3R<0b00111000001010000, "ldx.wu">;
669def STX_B : STORE_3R<0b00111000000100000, "stx.b">;
670def STX_H : STORE_3R<0b00111000000101000, "stx.h">;
671def STX_W : STORE_3R<0b00111000000110000, "stx.w">;
672def STX_D : STORE_3R<0b00111000000111000, "stx.d">;
673def LDPTR_W : LOAD_2RI14<0b00100100, "ldptr.w">;
674def LDPTR_D : LOAD_2RI14<0b00100110, "ldptr.d">;
675def STPTR_W : STORE_2RI14<0b00100101, "stptr.w">;
676def STPTR_D : STORE_2RI14<0b00100111, "stptr.d">;
677def PRELDX : FmtPRELDX<(outs), (ins uimm5:$imm5, GPR:$rj, GPR:$rk), "preldx",
678                       "$imm5, $rj, $rk">;
679
680// Bound Check Memory Access Instructions
681def LDGT_B : LOAD_3R<0b00111000011110000, "ldgt.b">;
682def LDGT_H : LOAD_3R<0b00111000011110001, "ldgt.h">;
683def LDGT_W : LOAD_3R<0b00111000011110010, "ldgt.w">;
684def LDGT_D : LOAD_3R<0b00111000011110011, "ldgt.d">;
685def LDLE_B : LOAD_3R<0b00111000011110100, "ldle.b">;
686def LDLE_H : LOAD_3R<0b00111000011110101, "ldle.h">;
687def LDLE_W : LOAD_3R<0b00111000011110110, "ldle.w">;
688def LDLE_D : LOAD_3R<0b00111000011110111, "ldle.d">;
689def STGT_B : STORE_3R<0b00111000011111000, "stgt.b">;
690def STGT_H : STORE_3R<0b00111000011111001, "stgt.h">;
691def STGT_W : STORE_3R<0b00111000011111010, "stgt.w">;
692def STGT_D : STORE_3R<0b00111000011111011, "stgt.d">;
693def STLE_B : STORE_3R<0b00111000011111100, "stle.b">;
694def STLE_H : STORE_3R<0b00111000011111101, "stle.h">;
695def STLE_W : STORE_3R<0b00111000011111110, "stle.w">;
696def STLE_D : STORE_3R<0b00111000011111111, "stle.d">;
697
698// Atomic Memory Access Instructions for 64-bits
699def AMSWAP_W    : AM_3R<0b00111000011000000, "amswap.w">;
700def AMSWAP_D    : AM_3R<0b00111000011000001, "amswap.d">;
701def AMADD_W     : AM_3R<0b00111000011000010, "amadd.w">;
702def AMADD_D     : AM_3R<0b00111000011000011, "amadd.d">;
703def AMAND_W     : AM_3R<0b00111000011000100, "amand.w">;
704def AMAND_D     : AM_3R<0b00111000011000101, "amand.d">;
705def AMOR_W      : AM_3R<0b00111000011000110, "amor.w">;
706def AMOR_D      : AM_3R<0b00111000011000111, "amor.d">;
707def AMXOR_W     : AM_3R<0b00111000011001000, "amxor.w">;
708def AMXOR_D     : AM_3R<0b00111000011001001, "amxor.d">;
709def AMMAX_W     : AM_3R<0b00111000011001010, "ammax.w">;
710def AMMAX_D     : AM_3R<0b00111000011001011, "ammax.d">;
711def AMMIN_W     : AM_3R<0b00111000011001100, "ammin.w">;
712def AMMIN_D     : AM_3R<0b00111000011001101, "ammin.d">;
713def AMMAX_WU    : AM_3R<0b00111000011001110, "ammax.wu">;
714def AMMAX_DU    : AM_3R<0b00111000011001111, "ammax.du">;
715def AMMIN_WU    : AM_3R<0b00111000011010000, "ammin.wu">;
716def AMMIN_DU    : AM_3R<0b00111000011010001, "ammin.du">;
717def AMSWAP_DB_W : AM_3R<0b00111000011010010, "amswap_db.w">;
718def AMSWAP_DB_D : AM_3R<0b00111000011010011, "amswap_db.d">;
719def AMADD_DB_W  : AM_3R<0b00111000011010100, "amadd_db.w">;
720def AMADD_DB_D  : AM_3R<0b00111000011010101, "amadd_db.d">;
721def AMAND_DB_W  : AM_3R<0b00111000011010110, "amand_db.w">;
722def AMAND_DB_D  : AM_3R<0b00111000011010111, "amand_db.d">;
723def AMOR_DB_W   : AM_3R<0b00111000011011000, "amor_db.w">;
724def AMOR_DB_D   : AM_3R<0b00111000011011001, "amor_db.d">;
725def AMXOR_DB_W  : AM_3R<0b00111000011011010, "amxor_db.w">;
726def AMXOR_DB_D  : AM_3R<0b00111000011011011, "amxor_db.d">;
727def AMMAX_DB_W  : AM_3R<0b00111000011011100, "ammax_db.w">;
728def AMMAX_DB_D  : AM_3R<0b00111000011011101, "ammax_db.d">;
729def AMMIN_DB_W  : AM_3R<0b00111000011011110, "ammin_db.w">;
730def AMMIN_DB_D  : AM_3R<0b00111000011011111, "ammin_db.d">;
731def AMMAX_DB_WU : AM_3R<0b00111000011100000, "ammax_db.wu">;
732def AMMAX_DB_DU : AM_3R<0b00111000011100001, "ammax_db.du">;
733def AMMIN_DB_WU : AM_3R<0b00111000011100010, "ammin_db.wu">;
734def AMMIN_DB_DU : AM_3R<0b00111000011100011, "ammin_db.du">;
735def LL_D : LLBase<0b00100010, "ll.d">;
736def SC_D : SCBase<0b00100011, "sc.d">;
737
738// CRC Check Instructions
739def CRC_W_B_W  : ALU_3R<0b00000000001001000, "crc.w.b.w">;
740def CRC_W_H_W  : ALU_3R<0b00000000001001001, "crc.w.h.w">;
741def CRC_W_W_W  : ALU_3R<0b00000000001001010, "crc.w.w.w">;
742def CRC_W_D_W  : ALU_3R<0b00000000001001011, "crc.w.d.w">;
743def CRCC_W_B_W : ALU_3R<0b00000000001001100, "crcc.w.b.w">;
744def CRCC_W_H_W : ALU_3R<0b00000000001001101, "crcc.w.h.w">;
745def CRCC_W_W_W : ALU_3R<0b00000000001001110, "crcc.w.w.w">;
746def CRCC_W_D_W : ALU_3R<0b00000000001001111, "crcc.w.d.w">;
747
748// Other Miscellaneous Instructions for 64-bits
749def ASRTLE_D : FmtASRT<0b00000000000000010, (outs), (ins GPR:$rj, GPR:$rk),
750                       "asrtle.d", "$rj, $rk">;
751def ASRTGT_D : FmtASRT<0b00000000000000011, (outs), (ins GPR:$rj, GPR:$rk),
752                       "asrtgt.d", "$rj, $rk">;
753def RDTIME_D : RDTIME_2R<0b0000000000000000011010, "rdtime.d">;
754} // Predicates = [IsLA64]
755
756//===----------------------------------------------------------------------===//
757// Pseudo-instructions and codegen patterns
758//
759// Naming convention: For 'generic' pattern classes, we use the naming
760// convention PatTy1Ty2.
761//===----------------------------------------------------------------------===//
762
763/// Generic pattern classes
764
765class PatGprGpr<SDPatternOperator OpNode, LAInst Inst>
766    : Pat<(OpNode GPR:$rj, GPR:$rk), (Inst GPR:$rj, GPR:$rk)>;
767class PatGprGpr_32<SDPatternOperator OpNode, LAInst Inst>
768    : Pat<(sext_inreg (OpNode GPR:$rj, GPR:$rk), i32), (Inst GPR:$rj, GPR:$rk)>;
769class PatGpr<SDPatternOperator OpNode, LAInst Inst>
770    : Pat<(OpNode GPR:$rj), (Inst GPR:$rj)>;
771
772class PatGprImm<SDPatternOperator OpNode, LAInst Inst, Operand ImmOpnd>
773    : Pat<(OpNode GPR:$rj, ImmOpnd:$imm),
774          (Inst GPR:$rj, ImmOpnd:$imm)>;
775class PatGprImm_32<SDPatternOperator OpNode, LAInst Inst, Operand ImmOpnd>
776    : Pat<(sext_inreg (OpNode GPR:$rj, ImmOpnd:$imm), i32),
777          (Inst GPR:$rj, ImmOpnd:$imm)>;
778
779/// Predicates
780def AddLike: PatFrags<(ops node:$A, node:$B),
781                      [(add node:$A, node:$B), (or node:$A, node:$B)], [{
782    return N->getOpcode() == ISD::ADD || isOrEquivalentToAdd(N);
783}]>;
784
785/// Simple arithmetic operations
786
787// Match both a plain shift and one where the shift amount is masked (this is
788// typically introduced when the legalizer promotes the shift amount and
789// zero-extends it). For LoongArch, the mask is unnecessary as shifts in the
790// base ISA only read the least significant 5 bits (LA32) or 6 bits (LA64).
791def shiftMaskGRLen
792    : ComplexPattern<GRLenVT, 1, "selectShiftMaskGRLen", [], [], 0>;
793def shiftMask32 : ComplexPattern<i64, 1, "selectShiftMask32", [], [], 0>;
794
795def sexti32 : ComplexPattern<i64, 1, "selectSExti32">;
796def zexti32 : ComplexPattern<i64, 1, "selectZExti32">;
797
798class shiftop<SDPatternOperator operator>
799    : PatFrag<(ops node:$val, node:$count),
800              (operator node:$val, (GRLenVT (shiftMaskGRLen node:$count)))>;
801class shiftopw<SDPatternOperator operator>
802    : PatFrag<(ops node:$val, node:$count),
803              (operator node:$val, (i64 (shiftMask32 node:$count)))>;
804
805let Predicates = [IsLA32] in {
806def : PatGprGpr<add, ADD_W>;
807def : PatGprImm<add, ADDI_W, simm12>;
808def : PatGprGpr<sub, SUB_W>;
809def : PatGprGpr<sdiv, DIV_W>;
810def : PatGprGpr<udiv, DIV_WU>;
811def : PatGprGpr<srem, MOD_W>;
812def : PatGprGpr<urem, MOD_WU>;
813def : PatGprGpr<mul, MUL_W>;
814def : PatGprGpr<mulhs, MULH_W>;
815def : PatGprGpr<mulhu, MULH_WU>;
816def : PatGprGpr<rotr, ROTR_W>;
817def : PatGprImm<rotr, ROTRI_W, uimm5>;
818} // Predicates = [IsLA32]
819
820let Predicates = [IsLA64] in {
821def : PatGprGpr<add, ADD_D>;
822def : PatGprGpr_32<add, ADD_W>;
823def : PatGprImm<add, ADDI_D, simm12>;
824def : PatGprImm_32<add, ADDI_W, simm12>;
825def : PatGprGpr<sub, SUB_D>;
826def : PatGprGpr_32<sub, SUB_W>;
827def : PatGprGpr<sdiv, DIV_D>;
828def : PatGprGpr<udiv, DIV_DU>;
829def : PatGprGpr<srem, MOD_D>;
830def : PatGprGpr<urem, MOD_DU>;
831def : PatGprGpr<rotr, ROTR_D>;
832def : PatGprGpr<loongarch_rotr_w, ROTR_W>;
833def : PatGprImm<rotr, ROTRI_D, uimm6>;
834def : PatGprImm_32<rotr, ROTRI_W, uimm5>;
835def : Pat<(loongarch_rotl_w GPR:$rj, uimm5:$imm),
836          (ROTRI_W GPR:$rj, (ImmSubFrom32 uimm5:$imm))>;
837def : Pat<(sext_inreg (loongarch_rotl_w GPR:$rj, uimm5:$imm), i32),
838          (ROTRI_W GPR:$rj, (ImmSubFrom32 uimm5:$imm))>;
839// TODO: Select "_W[U]" instructions for i32xi32 if only lower 32 bits of the
840// product are used.
841def : PatGprGpr<mul, MUL_D>;
842def : PatGprGpr<mulhs, MULH_D>;
843def : PatGprGpr<mulhu, MULH_DU>;
844// Select MULW_D_W for calculating the full 64 bits product of i32xi32 signed
845// multiplication.
846def : Pat<(i64 (mul (sext_inreg GPR:$rj, i32), (sext_inreg GPR:$rk, i32))),
847          (MULW_D_W GPR:$rj, GPR:$rk)>;
848// Select MULW_D_WU for calculating the full 64 bits product of i32xi32
849// unsigned multiplication.
850def : Pat<(i64 (mul (loongarch_bstrpick GPR:$rj, (i64 31), (i64 0)),
851                    (loongarch_bstrpick GPR:$rk, (i64 31), (i64 0)))),
852          (MULW_D_WU GPR:$rj, GPR:$rk)>;
853} // Predicates = [IsLA64]
854
855def : PatGprGpr<and, AND>;
856def : PatGprImm<and, ANDI, uimm12>;
857def : PatGprGpr<or, OR>;
858def : PatGprImm<or, ORI, uimm12>;
859def : PatGprGpr<xor, XOR>;
860def : PatGprImm<xor, XORI, uimm12>;
861def : Pat<(not GPR:$rj), (NOR GPR:$rj, R0)>;
862def : Pat<(not (or GPR:$rj, GPR:$rk)), (NOR GPR:$rj, GPR:$rk)>;
863def : Pat<(or GPR:$rj, (not GPR:$rk)), (ORN GPR:$rj, GPR:$rk)>;
864def : Pat<(and GPR:$rj, (not GPR:$rk)), (ANDN GPR:$rj, GPR:$rk)>;
865
866/// Traps
867
868// We lower `trap` to `amswap.w rd:$r0, rk:$r1, rj:$r0`, as this is guaranteed
869// to trap with an INE (non-existent on LA32, explicitly documented to INE on
870// LA64). And the resulting signal is different from `debugtrap` like on some
871// other existing ports so programs/porters might have an easier time.
872def PseudoUNIMP : Pseudo<(outs), (ins), [(trap)]>,
873                  PseudoInstExpansion<(AMSWAP_W R0, R1, R0)>;
874
875// We lower `debugtrap` to `break 0`, as this is guaranteed to exist and work,
876// even for LA32 Primary. Also, because so far the ISA does not provide a
877// specific trap instruction/kind exclusively for alerting the debugger,
878// every other project uses the generic immediate of 0 for this.
879def : Pat<(debugtrap), (BREAK 0)>;
880
881/// Bit counting operations
882
883let Predicates = [IsLA64] in {
884def : PatGpr<ctlz, CLZ_D>;
885def : PatGpr<cttz, CTZ_D>;
886def : Pat<(ctlz (not GPR:$rj)), (CLO_D GPR:$rj)>;
887def : Pat<(cttz (not GPR:$rj)), (CTO_D GPR:$rj)>;
888def : PatGpr<loongarch_clzw, CLZ_W>;
889def : PatGpr<loongarch_ctzw, CTZ_W>;
890def : Pat<(loongarch_clzw (not GPR:$rj)), (CLO_W GPR:$rj)>;
891def : Pat<(loongarch_ctzw (not GPR:$rj)), (CTO_W GPR:$rj)>;
892} // Predicates = [IsLA64]
893
894let Predicates = [IsLA32] in {
895def : PatGpr<ctlz, CLZ_W>;
896def : PatGpr<cttz, CTZ_W>;
897def : Pat<(ctlz (not GPR:$rj)), (CLO_W GPR:$rj)>;
898def : Pat<(cttz (not GPR:$rj)), (CTO_W GPR:$rj)>;
899} // Predicates = [IsLA32]
900
901/// FrameIndex calculations
902let Predicates = [IsLA32] in {
903def : Pat<(AddLike (i32 BaseAddr:$rj), simm12:$imm12),
904          (ADDI_W (i32 BaseAddr:$rj), simm12:$imm12)>;
905} // Predicates = [IsLA32]
906let Predicates = [IsLA64] in {
907def : Pat<(AddLike (i64 BaseAddr:$rj), simm12:$imm12),
908          (ADDI_D (i64 BaseAddr:$rj), simm12:$imm12)>;
909} // Predicates = [IsLA64]
910
911/// Shifted addition
912let Predicates = [IsLA32] in {
913def : Pat<(add GPR:$rk, (shl GPR:$rj, uimm2_plus1:$imm2)),
914          (ALSL_W GPR:$rj, GPR:$rk, uimm2_plus1:$imm2)>;
915} // Predicates = [IsLA32]
916let Predicates = [IsLA64] in {
917def : Pat<(add GPR:$rk, (shl GPR:$rj, uimm2_plus1:$imm2)),
918          (ALSL_D GPR:$rj, GPR:$rk, uimm2_plus1:$imm2)>;
919def : Pat<(loongarch_bstrpick (add GPR:$rk, (shl GPR:$rj, uimm2_plus1:$imm2)),
920                              (i64 31), (i64 0)),
921          (ALSL_WU GPR:$rj, GPR:$rk, uimm2_plus1:$imm2)>;
922} // Predicates = [IsLA64]
923
924/// Shift
925
926let Predicates = [IsLA32] in {
927def : PatGprGpr<shiftop<shl>, SLL_W>;
928def : PatGprGpr<shiftop<sra>, SRA_W>;
929def : PatGprGpr<shiftop<srl>, SRL_W>;
930def : PatGprImm<shl, SLLI_W, uimm5>;
931def : PatGprImm<sra, SRAI_W, uimm5>;
932def : PatGprImm<srl, SRLI_W, uimm5>;
933} // Predicates = [IsLA32]
934
935let Predicates = [IsLA64] in {
936def : PatGprGpr<shiftopw<loongarch_sll_w>, SLL_W>;
937def : PatGprGpr<shiftopw<loongarch_sra_w>, SRA_W>;
938def : PatGprGpr<shiftopw<loongarch_srl_w>, SRL_W>;
939def : PatGprGpr<shiftop<shl>, SLL_D>;
940def : PatGprGpr<shiftop<sra>, SRA_D>;
941def : PatGprGpr<shiftop<srl>, SRL_D>;
942def : PatGprImm<shl, SLLI_D, uimm6>;
943def : PatGprImm<sra, SRAI_D, uimm6>;
944def : PatGprImm<srl, SRLI_D, uimm6>;
945} // Predicates = [IsLA64]
946
947/// sext and zext
948
949def : Pat<(sext_inreg GPR:$rj, i8), (EXT_W_B GPR:$rj)>;
950def : Pat<(sext_inreg GPR:$rj, i16), (EXT_W_H GPR:$rj)>;
951
952let Predicates = [IsLA64] in {
953def : Pat<(sext_inreg GPR:$rj, i32), (ADDI_W GPR:$rj, 0)>;
954} // Predicates = [IsLA64]
955
956/// Setcc
957
958def : PatGprGpr<setlt, SLT>;
959def : PatGprImm<setlt, SLTI, simm12>;
960def : PatGprGpr<setult, SLTU>;
961def : PatGprImm<setult, SLTUI, simm12>;
962
963// Define pattern expansions for setcc operations that aren't directly
964// handled by a LoongArch instruction.
965def : Pat<(seteq GPR:$rj, 0), (SLTUI GPR:$rj, 1)>;
966def : Pat<(seteq GPR:$rj, GPR:$rk), (SLTUI (XOR GPR:$rj, GPR:$rk), 1)>;
967let Predicates = [IsLA32] in {
968def : Pat<(seteq GPR:$rj, simm12_plus1:$imm12),
969          (SLTUI (ADDI_W GPR:$rj, (NegImm simm12_plus1:$imm12)), 1)>;
970} // Predicates = [IsLA32]
971let Predicates = [IsLA64] in {
972def : Pat<(seteq GPR:$rj, simm12_plus1:$imm12),
973          (SLTUI (ADDI_D GPR:$rj, (NegImm simm12_plus1:$imm12)), 1)>;
974} // Predicates = [IsLA64]
975def : Pat<(setne GPR:$rj, 0), (SLTU R0, GPR:$rj)>;
976def : Pat<(setne GPR:$rj, GPR:$rk), (SLTU R0, (XOR GPR:$rj, GPR:$rk))>;
977let Predicates = [IsLA32] in {
978def : Pat<(setne GPR:$rj, simm12_plus1:$imm12),
979          (SLTU R0, (ADDI_W GPR:$rj, (NegImm simm12_plus1:$imm12)))>;
980} // Predicates = [IsLA32]
981let Predicates = [IsLA64] in {
982def : Pat<(setne GPR:$rj, simm12_plus1:$imm12),
983          (SLTU R0, (ADDI_D GPR:$rj, (NegImm simm12_plus1:$imm12)))>;
984} // Predicates = [IsLA64]
985def : Pat<(setugt GPR:$rj, GPR:$rk), (SLTU GPR:$rk, GPR:$rj)>;
986def : Pat<(setuge GPR:$rj, GPR:$rk), (XORI (SLTU GPR:$rj, GPR:$rk), 1)>;
987def : Pat<(setule GPR:$rj, GPR:$rk), (XORI (SLTU GPR:$rk, GPR:$rj), 1)>;
988def : Pat<(setgt GPR:$rj, GPR:$rk), (SLT GPR:$rk, GPR:$rj)>;
989def : Pat<(setge GPR:$rj, GPR:$rk), (XORI (SLT GPR:$rj, GPR:$rk), 1)>;
990def : Pat<(setle GPR:$rj, GPR:$rk), (XORI (SLT GPR:$rk, GPR:$rj), 1)>;
991
992/// Select
993
994def : Pat<(select GPR:$cond, GPR:$t, GPR:$f),
995          (OR (MASKEQZ GPR:$t, GPR:$cond), (MASKNEZ GPR:$f, GPR:$cond))>;
996
997/// Branches and jumps
998
999class BccPat<PatFrag CondOp, LAInst Inst>
1000    : Pat<(brcond (GRLenVT (CondOp GPR:$rj, GPR:$rd)), bb:$imm16),
1001          (Inst GPR:$rj, GPR:$rd, bb:$imm16)>;
1002
1003def : BccPat<seteq, BEQ>;
1004def : BccPat<setne, BNE>;
1005def : BccPat<setlt, BLT>;
1006def : BccPat<setge, BGE>;
1007def : BccPat<setult, BLTU>;
1008def : BccPat<setuge, BGEU>;
1009
1010class BccSwapPat<PatFrag CondOp, LAInst InstBcc>
1011    : Pat<(brcond (GRLenVT (CondOp GPR:$rd, GPR:$rj)), bb:$imm16),
1012          (InstBcc GPR:$rj, GPR:$rd, bb:$imm16)>;
1013
1014// Condition codes that don't have matching LoongArch branch instructions, but
1015// are trivially supported by swapping the two input operands.
1016def : BccSwapPat<setgt, BLT>;
1017def : BccSwapPat<setle, BGE>;
1018def : BccSwapPat<setugt, BLTU>;
1019def : BccSwapPat<setule, BGEU>;
1020
1021// An extra pattern is needed for a brcond without a setcc (i.e. where the
1022// condition was calculated elsewhere).
1023def : Pat<(brcond GPR:$rj, bb:$imm21), (BNEZ GPR:$rj, bb:$imm21)>;
1024
1025def : Pat<(brcond (GRLenVT (seteq GPR:$rj, 0)), bb:$imm21),
1026          (BEQZ GPR:$rj, bb:$imm21)>;
1027def : Pat<(brcond (GRLenVT (setne GPR:$rj, 0)), bb:$imm21),
1028          (BNEZ GPR:$rj, bb:$imm21)>;
1029
1030let isBarrier = 1, isBranch = 1, isTerminator = 1 in
1031def PseudoBR : Pseudo<(outs), (ins simm26_b:$imm26), [(br bb:$imm26)]>,
1032               PseudoInstExpansion<(B simm26_b:$imm26)>;
1033
1034let isBarrier = 1, isBranch = 1, isIndirectBranch = 1, isTerminator = 1 in
1035def PseudoBRIND : Pseudo<(outs), (ins GPR:$rj, simm16_lsl2:$imm16)>,
1036                  PseudoInstExpansion<(JIRL R0, GPR:$rj, simm16_lsl2:$imm16)>;
1037
1038def : Pat<(brind GPR:$rj), (PseudoBRIND GPR:$rj, 0)>;
1039def : Pat<(brind (add GPR:$rj, simm16_lsl2:$imm16)),
1040          (PseudoBRIND GPR:$rj, simm16_lsl2:$imm16)>;
1041
1042let isCall = 1, Defs = [R1] in
1043def PseudoCALL : Pseudo<(outs), (ins simm26_symbol:$func)>;
1044
1045def : Pat<(loongarch_call tglobaladdr:$func), (PseudoCALL tglobaladdr:$func)>;
1046def : Pat<(loongarch_call texternalsym:$func), (PseudoCALL texternalsym:$func)>;
1047
1048let isCall = 1, Defs = [R1] in
1049def PseudoCALLIndirect : Pseudo<(outs), (ins GPR:$rj),
1050                                [(loongarch_call GPR:$rj)]>,
1051                         PseudoInstExpansion<(JIRL R1, GPR:$rj, 0)>;
1052
1053let isCall = 1, Defs = [R1] in
1054def PseudoJIRL_CALL : Pseudo<(outs), (ins GPR:$rj, simm16_lsl2:$imm16)>,
1055                      PseudoInstExpansion<(JIRL R1, GPR:$rj,
1056                                           simm16_lsl2:$imm16)>;
1057
1058let isBarrier = 1, isReturn = 1, isTerminator = 1 in
1059def PseudoRET : Pseudo<(outs), (ins), [(loongarch_ret)]>,
1060                PseudoInstExpansion<(JIRL R0, R1, 0)>;
1061
1062let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1, Uses = [R3] in
1063def PseudoTAIL : Pseudo<(outs), (ins simm26_symbol:$dst)>;
1064
1065def : Pat<(loongarch_tail (iPTR tglobaladdr:$dst)),
1066          (PseudoTAIL tglobaladdr:$dst)>;
1067def : Pat<(loongarch_tail (iPTR texternalsym:$dst)),
1068          (PseudoTAIL texternalsym:$dst)>;
1069
1070let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1, Uses = [R3] in
1071def PseudoTAILIndirect : Pseudo<(outs), (ins GPRT:$rj),
1072                                [(loongarch_tail GPRT:$rj)]>,
1073                         PseudoInstExpansion<(JIRL R0, GPR:$rj, 0)>;
1074
1075let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1, Uses = [R3] in
1076def PseudoB_TAIL : Pseudo<(outs), (ins simm26_b:$imm26)>,
1077                   PseudoInstExpansion<(B simm26_b:$imm26)>;
1078
1079let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1, Uses = [R3] in
1080def PseudoJIRL_TAIL : Pseudo<(outs), (ins GPR:$rj, simm16_lsl2:$imm16)>,
1081                      PseudoInstExpansion<(JIRL R0, GPR:$rj,
1082                                           simm16_lsl2:$imm16)>;
1083
1084/// Load address (la*) macro instructions.
1085
1086// Define isCodeGenOnly = 0 to expose them to tablegened assembly parser.
1087let hasSideEffects = 0, mayLoad = 0, mayStore = 0, isCodeGenOnly = 0,
1088    isAsmParserOnly = 1 in {
1089def PseudoLA_ABS : Pseudo<(outs GPR:$dst), (ins bare_symbol:$src), [],
1090                          "la.abs", "$dst, $src">;
1091def PseudoLA_ABS_LARGE : Pseudo<(outs GPR:$dst),
1092                                (ins GPR:$tmp, bare_symbol:$src), [],
1093                                "la.abs", "$dst, $src">;
1094def PseudoLA_PCREL : Pseudo<(outs GPR:$dst), (ins bare_symbol:$src), [],
1095                            "la.pcrel", "$dst, $src">;
1096def PseudoLA_PCREL_LARGE : Pseudo<(outs GPR:$dst),
1097                                  (ins GPR:$tmp, bare_symbol:$src), [],
1098                                  "la.pcrel", "$dst, $tmp, $src">,
1099                           Requires<[IsLA64]>;
1100def PseudoLA_TLS_LE : Pseudo<(outs GPR:$dst), (ins bare_symbol:$src), [],
1101                             "la.tls.le", "$dst, $src">;
1102}
1103let hasSideEffects = 0, mayLoad = 1, mayStore = 0, isCodeGenOnly = 0,
1104    isAsmParserOnly = 1 in {
1105def PseudoLA_GOT : Pseudo<(outs GPR:$dst), (ins bare_symbol:$src), [],
1106                          "la.got", "$dst, $src">;
1107def PseudoLA_GOT_LARGE : Pseudo<(outs GPR:$dst),
1108                                (ins GPR:$tmp, bare_symbol:$src), [],
1109                                "la.got", "$dst, $tmp, $src">,
1110                         Requires<[IsLA64]>;
1111def PseudoLA_TLS_IE : Pseudo<(outs GPR:$dst), (ins bare_symbol:$src), [],
1112                             "la.tls.ie", "$dst, $src">;
1113def PseudoLA_TLS_IE_LARGE : Pseudo<(outs GPR:$dst),
1114                                   (ins GPR:$tmp, bare_symbol:$src), [],
1115                                   "la.tls.ie", "$dst, $tmp, $src">,
1116                            Requires<[IsLA64]>;
1117def PseudoLA_TLS_LD : Pseudo<(outs GPR:$dst), (ins bare_symbol:$src), [],
1118                             "la.tls.ld", "$dst, $src">;
1119def PseudoLA_TLS_LD_LARGE : Pseudo<(outs GPR:$dst),
1120                                   (ins GPR:$tmp, bare_symbol:$src), [],
1121                                   "la.tls.ld", "$dst, $tmp, $src">,
1122                            Requires<[IsLA64]>;
1123def PseudoLA_TLS_GD : Pseudo<(outs GPR:$dst), (ins bare_symbol:$src), [],
1124                             "la.tls.gd", "$dst, $src">;
1125def PseudoLA_TLS_GD_LARGE : Pseudo<(outs GPR:$dst),
1126                                   (ins GPR:$tmp, bare_symbol:$src), [],
1127                                   "la.tls.gd", "$dst, $tmp, $src">,
1128                            Requires<[IsLA64]>;
1129}
1130
1131// Load address inst alias: "la", "la.global" and "la.local".
1132// Default:
1133//     la = la.global = la.got
1134//     la.local = la.pcrel
1135// With feature "+la-global-with-pcrel":
1136//     la = la.global = la.pcrel
1137// With feature "+la-global-with-abs":
1138//     la = la.global = la.abs
1139// With feature "+la-local-with-abs":
1140//     la.local = la.abs
1141// With features "+la-global-with-pcrel,+la-global-with-abs"(disorder):
1142//     la = la.global = la.pcrel
1143// Note: To keep consistent with gnu-as behavior, the "la" can only have one
1144//       register operand.
1145def : InstAlias<"la $dst, $src", (PseudoLA_GOT GPR:$dst, bare_symbol:$src)>;
1146def : InstAlias<"la.global $dst, $src",
1147                (PseudoLA_GOT GPR:$dst, bare_symbol:$src)>;
1148def : InstAlias<"la.global $dst, $tmp, $src",
1149                (PseudoLA_GOT_LARGE GPR:$dst, GPR:$tmp, bare_symbol:$src)>;
1150def : InstAlias<"la.local $dst, $src",
1151                (PseudoLA_PCREL GPR:$dst, bare_symbol:$src)>;
1152def : InstAlias<"la.local $dst, $tmp, $src",
1153                (PseudoLA_PCREL_LARGE GPR:$dst, GPR:$tmp, bare_symbol:$src)>;
1154
1155// Note: Keep HasLaGlobalWithPcrel before HasLaGlobalWithAbs to ensure
1156// "la-global-with-pcrel" takes effect when bose "la-global-with-pcrel" and
1157// "la-global-with-abs" are enabled.
1158let Predicates = [HasLaGlobalWithPcrel] in {
1159def : InstAlias<"la $dst, $src", (PseudoLA_PCREL GPR:$dst, bare_symbol:$src)>;
1160def : InstAlias<"la.global $dst, $src",
1161                (PseudoLA_PCREL GPR:$dst, bare_symbol:$src)>;
1162def : InstAlias<"la.global $dst, $tmp, $src",
1163                (PseudoLA_PCREL_LARGE GPR:$dst, GPR:$tmp, bare_symbol:$src)>;
1164} // Predicates = [HasLaGlobalWithPcrel]
1165
1166let Predicates = [HasLaGlobalWithAbs] in {
1167def : InstAlias<"la $dst, $src", (PseudoLA_ABS GPR:$dst, bare_symbol:$src)>;
1168def : InstAlias<"la.global $dst, $src",
1169                (PseudoLA_ABS GPR:$dst, bare_symbol:$src)>;
1170def : InstAlias<"la.global $dst, $tmp, $src",
1171                (PseudoLA_ABS_LARGE GPR:$dst, GPR:$tmp, bare_symbol:$src)>;
1172} // Predicates = [HasLaGlobalWithAbs]
1173
1174let Predicates = [HasLaLocalWithAbs] in {
1175def : InstAlias<"la.local $dst, $src",
1176                (PseudoLA_ABS GPR:$dst, bare_symbol:$src)>;
1177def : InstAlias<"la.local $dst, $tmp, $src",
1178                (PseudoLA_ABS_LARGE GPR:$dst, GPR:$tmp, bare_symbol:$src)>;
1179} // Predicates = [HasLaLocalWithAbs]
1180
1181/// BSTRINS and BSTRPICK
1182
1183let Predicates = [IsLA32] in {
1184def : Pat<(loongarch_bstrins GPR:$rd, GPR:$rj, uimm5:$msbd, uimm5:$lsbd),
1185          (BSTRINS_W GPR:$rd, GPR:$rj, uimm5:$msbd, uimm5:$lsbd)>;
1186def : Pat<(loongarch_bstrpick GPR:$rj, uimm5:$msbd, uimm5:$lsbd),
1187          (BSTRPICK_W GPR:$rj, uimm5:$msbd, uimm5:$lsbd)>;
1188} // Predicates = [IsLA32]
1189
1190let Predicates = [IsLA64] in {
1191def : Pat<(loongarch_bstrins GPR:$rd, GPR:$rj, uimm6:$msbd, uimm6:$lsbd),
1192          (BSTRINS_D GPR:$rd, GPR:$rj, uimm6:$msbd, uimm6:$lsbd)>;
1193def : Pat<(loongarch_bstrpick GPR:$rj, uimm6:$msbd, uimm6:$lsbd),
1194          (BSTRPICK_D GPR:$rj, uimm6:$msbd, uimm6:$lsbd)>;
1195} // Predicates = [IsLA64]
1196
1197/// Byte-swapping and bit-reversal
1198
1199def : Pat<(loongarch_revb_2h GPR:$rj), (REVB_2H GPR:$rj)>;
1200def : Pat<(loongarch_bitrev_4b GPR:$rj), (BITREV_4B GPR:$rj)>;
1201
1202let Predicates = [IsLA32] in {
1203def : Pat<(bswap GPR:$rj), (ROTRI_W (REVB_2H GPR:$rj), 16)>;
1204def : Pat<(bitreverse GPR:$rj), (BITREV_W GPR:$rj)>;
1205def : Pat<(bswap (bitreverse GPR:$rj)), (BITREV_4B GPR:$rj)>;
1206def : Pat<(bitreverse (bswap GPR:$rj)), (BITREV_4B GPR:$rj)>;
1207} // Predicates = [IsLA32]
1208
1209let Predicates = [IsLA64] in {
1210def : Pat<(loongarch_revb_2w GPR:$rj), (REVB_2W GPR:$rj)>;
1211def : Pat<(bswap GPR:$rj), (REVB_D GPR:$rj)>;
1212def : Pat<(loongarch_bitrev_w GPR:$rj), (BITREV_W GPR:$rj)>;
1213def : Pat<(bitreverse GPR:$rj), (BITREV_D GPR:$rj)>;
1214def : Pat<(bswap (bitreverse GPR:$rj)), (BITREV_8B GPR:$rj)>;
1215def : Pat<(bitreverse (bswap GPR:$rj)), (BITREV_8B GPR:$rj)>;
1216} // Predicates = [IsLA64]
1217
1218/// Loads
1219
1220multiclass LdPat<PatFrag LoadOp, LAInst Inst, ValueType vt = GRLenVT> {
1221  def : Pat<(vt (LoadOp BaseAddr:$rj)), (Inst BaseAddr:$rj, 0)>;
1222  def : Pat<(vt (LoadOp (AddLike BaseAddr:$rj, simm12:$imm12))),
1223            (Inst BaseAddr:$rj, simm12:$imm12)>;
1224}
1225
1226defm : LdPat<sextloadi8, LD_B>;
1227defm : LdPat<extloadi8, LD_B>;
1228defm : LdPat<sextloadi16, LD_H>;
1229defm : LdPat<extloadi16, LD_H>;
1230defm : LdPat<load, LD_W>, Requires<[IsLA32]>;
1231defm : LdPat<zextloadi8, LD_BU>;
1232defm : LdPat<zextloadi16, LD_HU>;
1233let Predicates = [IsLA64] in {
1234defm : LdPat<sextloadi32, LD_W, i64>;
1235defm : LdPat<extloadi32, LD_W, i64>;
1236defm : LdPat<zextloadi32, LD_WU, i64>;
1237defm : LdPat<load, LD_D, i64>;
1238} // Predicates = [IsLA64]
1239
1240// LA64 register-register-addressed loads
1241let Predicates = [IsLA64] in {
1242class RegRegLdPat<PatFrag LoadOp, LAInst Inst, ValueType vt>
1243  : Pat<(vt (LoadOp (add NonFIBaseAddr:$rj, GPR:$rk))),
1244        (Inst NonFIBaseAddr:$rj, GPR:$rk)>;
1245
1246def : RegRegLdPat<extloadi8, LDX_B, i64>;
1247def : RegRegLdPat<sextloadi8, LDX_B, i64>;
1248def : RegRegLdPat<zextloadi8, LDX_BU, i64>;
1249def : RegRegLdPat<extloadi16, LDX_H, i64>;
1250def : RegRegLdPat<sextloadi16, LDX_H, i64>;
1251def : RegRegLdPat<zextloadi16, LDX_HU, i64>;
1252def : RegRegLdPat<extloadi32, LDX_W, i64>;
1253def : RegRegLdPat<sextloadi32, LDX_W, i64>;
1254def : RegRegLdPat<zextloadi32, LDX_WU, i64>;
1255def : RegRegLdPat<load, LDX_D, i64>;
1256} // Predicates = [IsLA64]
1257
1258/// Stores
1259
1260multiclass StPat<PatFrag StoreOp, LAInst Inst, RegisterClass StTy,
1261                 ValueType vt> {
1262  def : Pat<(StoreOp (vt StTy:$rd), BaseAddr:$rj),
1263            (Inst StTy:$rd, BaseAddr:$rj, 0)>;
1264  def : Pat<(StoreOp (vt StTy:$rd), (AddLike BaseAddr:$rj, simm12:$imm12)),
1265            (Inst StTy:$rd, BaseAddr:$rj, simm12:$imm12)>;
1266}
1267
1268defm : StPat<truncstorei8, ST_B, GPR, GRLenVT>;
1269defm : StPat<truncstorei16, ST_H, GPR, GRLenVT>;
1270defm : StPat<store, ST_W, GPR, i32>, Requires<[IsLA32]>;
1271let Predicates = [IsLA64] in {
1272defm : StPat<truncstorei32, ST_W, GPR, i64>;
1273defm : StPat<store, ST_D, GPR, i64>;
1274} // Predicates = [IsLA64]
1275
1276let Predicates = [IsLA64] in {
1277def : Pat<(i64 (sextloadi32 (AddLike BaseAddr:$rj, simm14_lsl2:$imm14))),
1278          (LDPTR_W BaseAddr:$rj, simm14_lsl2:$imm14)>;
1279def : Pat<(i64 (load (AddLike BaseAddr:$rj, simm14_lsl2:$imm14))),
1280          (LDPTR_D BaseAddr:$rj, simm14_lsl2:$imm14)>;
1281def : Pat<(truncstorei32 (i64 GPR:$rd),
1282                         (AddLike BaseAddr:$rj, simm14_lsl2:$imm14)),
1283          (STPTR_W GPR:$rd, BaseAddr:$rj, simm14_lsl2:$imm14)>;
1284def : Pat<(store (i64 GPR:$rd), (AddLike BaseAddr:$rj, simm14_lsl2:$imm14)),
1285          (STPTR_D GPR:$rd, BaseAddr:$rj, simm14_lsl2:$imm14)>;
1286} // Predicates = [IsLA64]
1287
1288// LA64 register-register-addressed stores
1289let Predicates = [IsLA64] in {
1290class RegRegStPat<PatFrag StoreOp, LAInst Inst, RegisterClass StTy,
1291                  ValueType vt>
1292  : Pat<(StoreOp (vt StTy:$rd), (add NonFIBaseAddr:$rj, GPR:$rk)),
1293        (Inst StTy:$rd, NonFIBaseAddr:$rj, GPR:$rk)>;
1294
1295def : RegRegStPat<truncstorei8, STX_B, GPR, i64>;
1296def : RegRegStPat<truncstorei16, STX_H, GPR, i64>;
1297def : RegRegStPat<truncstorei32, STX_W, GPR, i64>;
1298def : RegRegStPat<store, STX_D, GPR, i64>;
1299} // Predicates = [IsLA64]
1300
1301/// Atomic loads and stores
1302
1303def : Pat<(atomic_fence timm, timm), (DBAR 0)>;
1304
1305defm : LdPat<atomic_load_8, LD_B>;
1306defm : LdPat<atomic_load_16, LD_H>;
1307defm : LdPat<atomic_load_32, LD_W>;
1308
1309class release_seqcst_store<PatFrag base>
1310    : PatFrag<(ops node:$ptr, node:$val), (base node:$ptr, node:$val), [{
1311  AtomicOrdering Ordering = cast<AtomicSDNode>(N)->getSuccessOrdering();
1312  return isReleaseOrStronger(Ordering);
1313}]>;
1314
1315class unordered_monotonic_store<PatFrag base>
1316    : PatFrag<(ops node:$ptr, node:$val), (base node:$ptr, node:$val), [{
1317  AtomicOrdering Ordering = cast<AtomicSDNode>(N)->getSuccessOrdering();
1318  return !isReleaseOrStronger(Ordering);
1319}]>;
1320
1321def atomic_store_release_seqcst_32 : release_seqcst_store<atomic_store_32>;
1322def atomic_store_release_seqcst_64 : release_seqcst_store<atomic_store_64>;
1323def atomic_store_unordered_monotonic_32
1324    : unordered_monotonic_store<atomic_store_32>;
1325def atomic_store_unordered_monotonic_64
1326    : unordered_monotonic_store<atomic_store_64>;
1327
1328/// AtomicStores
1329
1330multiclass AtomicStPat<PatFrag StoreOp, LAInst Inst, RegisterClass StTy,
1331                       ValueType vt> {
1332  def : Pat<(StoreOp BaseAddr:$ptr, (vt StTy:$val)),
1333            (Inst StTy:$val, BaseAddr:$ptr, 0)>;
1334  def : Pat<(StoreOp (AddLike BaseAddr:$ptr, simm12:$imm12), (vt StTy:$val)),
1335            (Inst StTy:$val, BaseAddr:$ptr, simm12:$imm12)>;
1336}
1337
1338defm : AtomicStPat<atomic_store_8, ST_B, GPR, GRLenVT>;
1339defm : AtomicStPat<atomic_store_16, ST_H, GPR, GRLenVT>;
1340defm : AtomicStPat<atomic_store_unordered_monotonic_32, ST_W, GPR, i32>,
1341                   Requires<[IsLA32]>;
1342
1343def PseudoAtomicStoreW
1344  : Pseudo<(outs GPR:$dst), (ins GPR:$rj, GPR:$rk)>,
1345           PseudoInstExpansion<(AMSWAP_DB_W R0, GPR:$rk, GPRMemAtomic:$rj)>;
1346
1347def : Pat<(atomic_store_release_seqcst_32 GPR:$rj, GPR:$rk),
1348          (PseudoAtomicStoreW GPR:$rj, GPR:$rk)>;
1349
1350let Predicates = [IsLA64] in {
1351def PseudoAtomicStoreD
1352  : Pseudo<(outs GPR:$dst), (ins GPR:$rj, GPR:$rk)>,
1353           PseudoInstExpansion<(AMSWAP_DB_D R0, GPR:$rk, GPRMemAtomic:$rj)>;
1354
1355def : Pat<(atomic_store_release_seqcst_64 GPR:$rj, GPR:$rk),
1356          (PseudoAtomicStoreD GPR:$rj, GPR:$rk)>;
1357
1358defm : LdPat<atomic_load_64, LD_D>;
1359defm : AtomicStPat<atomic_store_unordered_monotonic_32, ST_W, GPR, i64>;
1360defm : AtomicStPat<atomic_store_unordered_monotonic_64, ST_D, GPR, i64>;
1361} // Predicates = [IsLA64]
1362
1363/// Atomic Ops
1364
1365class PseudoMaskedAM
1366    : Pseudo<(outs GPR:$res, GPR:$scratch),
1367             (ins GPR:$addr, GPR:$incr, GPR:$mask, grlenimm:$ordering)> {
1368  let Constraints = "@earlyclobber $res,@earlyclobber $scratch";
1369  let mayLoad = 1;
1370  let mayStore = 1;
1371  let hasSideEffects = 0;
1372  let Size = 36;
1373}
1374
1375def PseudoMaskedAtomicSwap32 : PseudoMaskedAM;
1376def PseudoMaskedAtomicLoadAdd32 : PseudoMaskedAM;
1377def PseudoMaskedAtomicLoadSub32 : PseudoMaskedAM;
1378def PseudoMaskedAtomicLoadNand32 : PseudoMaskedAM;
1379
1380class PseudoAM : Pseudo<(outs GPR:$res, GPR:$scratch),
1381                        (ins GPR:$addr, GPR:$incr, grlenimm:$ordering)> {
1382  let Constraints = "@earlyclobber $res,@earlyclobber $scratch";
1383  let mayLoad = 1;
1384  let mayStore = 1;
1385  let hasSideEffects = 0;
1386  let Size = 24;
1387}
1388
1389def PseudoAtomicSwap32 : PseudoAM;
1390def PseudoAtomicLoadNand32 : PseudoAM;
1391def PseudoAtomicLoadNand64 : PseudoAM;
1392def PseudoAtomicLoadAdd32 : PseudoAM;
1393def PseudoAtomicLoadSub32 : PseudoAM;
1394def PseudoAtomicLoadAnd32 : PseudoAM;
1395def PseudoAtomicLoadOr32 : PseudoAM;
1396def PseudoAtomicLoadXor32 : PseudoAM;
1397
1398multiclass PseudoBinPat<string Op, Pseudo BinInst> {
1399  def : Pat<(!cast<PatFrag>(Op#"_monotonic") GPR:$addr, GPR:$incr),
1400            (BinInst GPR:$addr, GPR:$incr, 2)>;
1401  def : Pat<(!cast<PatFrag>(Op#"_acquire") GPR:$addr, GPR:$incr),
1402            (BinInst GPR:$addr, GPR:$incr, 4)>;
1403  def : Pat<(!cast<PatFrag>(Op#"_release") GPR:$addr, GPR:$incr),
1404            (BinInst GPR:$addr, GPR:$incr, 5)>;
1405  def : Pat<(!cast<PatFrag>(Op#"_acq_rel") GPR:$addr, GPR:$incr),
1406            (BinInst GPR:$addr, GPR:$incr, 6)>;
1407  def : Pat<(!cast<PatFrag>(Op#"_seq_cst") GPR:$addr, GPR:$incr),
1408            (BinInst GPR:$addr, GPR:$incr, 7)>;
1409}
1410
1411class PseudoMaskedAMUMinUMax
1412    : Pseudo<(outs GPR:$res, GPR:$scratch1, GPR:$scratch2),
1413             (ins GPR:$addr, GPR:$incr, GPR:$mask, grlenimm:$ordering)> {
1414  let Constraints = "@earlyclobber $res,@earlyclobber $scratch1,"
1415                    "@earlyclobber $scratch2";
1416  let mayLoad = 1;
1417  let mayStore = 1;
1418  let hasSideEffects = 0;
1419  let Size = 48;
1420}
1421
1422def PseudoMaskedAtomicLoadUMax32 : PseudoMaskedAMUMinUMax;
1423def PseudoMaskedAtomicLoadUMin32 : PseudoMaskedAMUMinUMax;
1424
1425class PseudoMaskedAMMinMax
1426    : Pseudo<(outs GPR:$res, GPR:$scratch1, GPR:$scratch2),
1427             (ins GPR:$addr, GPR:$incr, GPR:$mask, grlenimm:$sextshamt,
1428              grlenimm:$ordering)> {
1429  let Constraints = "@earlyclobber $res,@earlyclobber $scratch1,"
1430                    "@earlyclobber $scratch2";
1431  let mayLoad = 1;
1432  let mayStore = 1;
1433  let hasSideEffects = 0;
1434  let Size = 56;
1435}
1436
1437def PseudoMaskedAtomicLoadMax32 : PseudoMaskedAMMinMax;
1438def PseudoMaskedAtomicLoadMin32 : PseudoMaskedAMMinMax;
1439
1440/// Compare and exchange
1441
1442class PseudoCmpXchg
1443    : Pseudo<(outs GPR:$res, GPR:$scratch),
1444             (ins GPR:$addr, GPR:$cmpval, GPR:$newval)> {
1445  let Constraints = "@earlyclobber $res,@earlyclobber $scratch";
1446  let mayLoad = 1;
1447  let mayStore = 1;
1448  let hasSideEffects = 0;
1449  let Size = 36;
1450}
1451
1452def PseudoCmpXchg32 : PseudoCmpXchg;
1453def PseudoCmpXchg64 : PseudoCmpXchg;
1454
1455def PseudoMaskedCmpXchg32
1456    : Pseudo<(outs GPR:$res, GPR:$scratch),
1457             (ins GPR:$addr, GPR:$cmpval, GPR:$newval, GPR:$mask,
1458              grlenimm:$ordering)> {
1459  let Constraints = "@earlyclobber $res,@earlyclobber $scratch";
1460  let mayLoad = 1;
1461  let mayStore = 1;
1462  let hasSideEffects = 0;
1463  let Size = 44;
1464}
1465
1466class PseudoMaskedAMMinMaxPat<Intrinsic intrin, Pseudo AMInst>
1467    : Pat<(intrin GPR:$addr, GPR:$incr, GPR:$mask, GPR:$shiftamt,
1468           timm:$ordering),
1469          (AMInst GPR:$addr, GPR:$incr, GPR:$mask, GPR:$shiftamt,
1470           timm:$ordering)>;
1471
1472class AtomicPat<Intrinsic intrin, Pseudo AMInst>
1473    : Pat<(intrin GPR:$addr, GPR:$incr, GPR:$mask, timm:$ordering),
1474          (AMInst GPR:$addr, GPR:$incr, GPR:$mask, timm:$ordering)>;
1475
1476let Predicates = [IsLA64] in {
1477def : AtomicPat<int_loongarch_masked_atomicrmw_xchg_i64,
1478                PseudoMaskedAtomicSwap32>;
1479def : Pat<(atomic_swap_32 GPR:$addr, GPR:$incr),
1480          (AMSWAP_DB_W GPR:$incr, GPR:$addr)>;
1481def : Pat<(atomic_swap_64 GPR:$addr, GPR:$incr),
1482          (AMSWAP_DB_D GPR:$incr, GPR:$addr)>;
1483def : Pat<(atomic_load_add_64 GPR:$rj, GPR:$rk),
1484          (AMADD_DB_D GPR:$rk, GPR:$rj)>;
1485def : AtomicPat<int_loongarch_masked_atomicrmw_add_i64,
1486                PseudoMaskedAtomicLoadAdd32>;
1487def : Pat<(atomic_load_sub_32 GPR:$rj, GPR:$rk),
1488          (AMADD_DB_W (SUB_W R0, GPR:$rk), GPR:$rj)>;
1489def : Pat<(atomic_load_sub_64 GPR:$rj, GPR:$rk),
1490          (AMADD_DB_D (SUB_D R0, GPR:$rk), GPR:$rj)>;
1491def : AtomicPat<int_loongarch_masked_atomicrmw_sub_i64,
1492                PseudoMaskedAtomicLoadSub32>;
1493defm : PseudoBinPat<"atomic_load_nand_64", PseudoAtomicLoadNand64>;
1494def : AtomicPat<int_loongarch_masked_atomicrmw_nand_i64,
1495                PseudoMaskedAtomicLoadNand32>;
1496def : Pat<(atomic_load_add_32 GPR:$rj, GPR:$rk),
1497          (AMADD_DB_W GPR:$rk, GPR:$rj)>;
1498def : Pat<(atomic_load_and_32 GPR:$rj, GPR:$rk),
1499          (AMAND_DB_W GPR:$rk, GPR:$rj)>;
1500def : Pat<(atomic_load_and_64 GPR:$rj, GPR:$rk),
1501          (AMAND_DB_D GPR:$rk, GPR:$rj)>;
1502def : Pat<(atomic_load_or_32 GPR:$rj, GPR:$rk),
1503          (AMOR_DB_W GPR:$rk, GPR:$rj)>;
1504def : Pat<(atomic_load_or_64 GPR:$rj, GPR:$rk),
1505          (AMOR_DB_D GPR:$rk, GPR:$rj)>;
1506def : Pat<(atomic_load_xor_32 GPR:$rj, GPR:$rk),
1507          (AMXOR_DB_W GPR:$rk, GPR:$rj)>;
1508def : Pat<(atomic_load_xor_64 GPR:$rj, GPR:$rk),
1509          (AMXOR_DB_D GPR:$rk, GPR:$rj)>;
1510
1511def : Pat<(atomic_load_umin_32 GPR:$rj, GPR:$rk),
1512          (AMMIN_DB_WU GPR:$rk, GPR:$rj)>;
1513def : Pat<(atomic_load_umin_64 GPR:$rj, GPR:$rk),
1514          (AMMIN_DB_DU GPR:$rk, GPR:$rj)>;
1515def : Pat<(atomic_load_umax_32 GPR:$rj, GPR:$rk),
1516          (AMMAX_DB_WU GPR:$rk, GPR:$rj)>;
1517def : Pat<(atomic_load_umax_64 GPR:$rj, GPR:$rk),
1518          (AMMAX_DB_DU GPR:$rk, GPR:$rj)>;
1519
1520def : Pat<(atomic_load_min_32 GPR:$rj, GPR:$rk),
1521          (AMMIN_DB_W GPR:$rk, GPR:$rj)>;
1522def : Pat<(atomic_load_min_64 GPR:$rj, GPR:$rk),
1523          (AMMIN_DB_D GPR:$rk, GPR:$rj)>;
1524def : Pat<(atomic_load_max_32 GPR:$rj, GPR:$rk),
1525          (AMMAX_DB_W GPR:$rk, GPR:$rj)>;
1526def : Pat<(atomic_load_max_64 GPR:$rj, GPR:$rk),
1527          (AMMAX_DB_D GPR:$rk, GPR:$rj)>;
1528
1529def : AtomicPat<int_loongarch_masked_atomicrmw_umax_i64,
1530                PseudoMaskedAtomicLoadUMax32>;
1531def : AtomicPat<int_loongarch_masked_atomicrmw_umin_i64,
1532                PseudoMaskedAtomicLoadUMin32>;
1533
1534def : Pat<(atomic_cmp_swap_64 GPR:$addr, GPR:$cmp, GPR:$new),
1535          (PseudoCmpXchg64 GPR:$addr, GPR:$cmp, GPR:$new)>;
1536def : Pat<(int_loongarch_masked_cmpxchg_i64
1537            GPR:$addr, GPR:$cmpval, GPR:$newval, GPR:$mask, timm:$ordering),
1538          (PseudoMaskedCmpXchg32
1539            GPR:$addr, GPR:$cmpval, GPR:$newval, GPR:$mask, timm:$ordering)>;
1540def : Pat<(atomic_cmp_swap_32 GPR:$addr, GPR:$cmp, GPR:$new),
1541          (PseudoCmpXchg32 GPR:$addr, GPR:$cmp, GPR:$new)>;
1542
1543def : PseudoMaskedAMMinMaxPat<int_loongarch_masked_atomicrmw_max_i64,
1544                              PseudoMaskedAtomicLoadMax32>;
1545def : PseudoMaskedAMMinMaxPat<int_loongarch_masked_atomicrmw_min_i64,
1546                              PseudoMaskedAtomicLoadMin32>;
1547} // Predicates = [IsLA64]
1548
1549defm : PseudoBinPat<"atomic_load_nand_32", PseudoAtomicLoadNand32>;
1550
1551let Predicates = [IsLA32] in {
1552def : AtomicPat<int_loongarch_masked_atomicrmw_xchg_i32,
1553                PseudoMaskedAtomicSwap32>;
1554defm : PseudoBinPat<"atomic_swap_32", PseudoAtomicSwap32>;
1555def : AtomicPat<int_loongarch_masked_atomicrmw_add_i32,
1556                PseudoMaskedAtomicLoadAdd32>;
1557def : AtomicPat<int_loongarch_masked_atomicrmw_sub_i32,
1558                PseudoMaskedAtomicLoadSub32>;
1559def : AtomicPat<int_loongarch_masked_atomicrmw_nand_i32,
1560                PseudoMaskedAtomicLoadNand32>;
1561defm : PseudoBinPat<"atomic_load_add_32", PseudoAtomicLoadAdd32>;
1562defm : PseudoBinPat<"atomic_load_sub_32", PseudoAtomicLoadSub32>;
1563defm : PseudoBinPat<"atomic_load_and_32", PseudoAtomicLoadAnd32>;
1564defm : PseudoBinPat<"atomic_load_or_32", PseudoAtomicLoadOr32>;
1565defm : PseudoBinPat<"atomic_load_xor_32", PseudoAtomicLoadXor32>;
1566} // Predicates = [IsLA32]
1567
1568/// Intrinsics
1569
1570def : Pat<(int_loongarch_cacop_d timm:$op, i64:$rj, timm:$imm12),
1571          (CACOP uimm5:$op, GPR:$rj, simm12:$imm12)>;
1572def : Pat<(int_loongarch_cacop_w i32:$op, i32:$rj, i32:$imm12),
1573          (CACOP uimm5:$op, GPR:$rj, simm12:$imm12)>;
1574def : Pat<(loongarch_dbar uimm15:$imm15), (DBAR uimm15:$imm15)>;
1575def : Pat<(loongarch_ibar uimm15:$imm15), (IBAR uimm15:$imm15)>;
1576def : Pat<(loongarch_break uimm15:$imm15), (BREAK uimm15:$imm15)>;
1577def : Pat<(loongarch_syscall uimm15:$imm15), (SYSCALL uimm15:$imm15)>;
1578
1579let Predicates = [IsLA64] in {
1580// CRC Check Instructions
1581def : PatGprGpr<loongarch_crc_w_b_w, CRC_W_B_W>;
1582def : PatGprGpr<loongarch_crc_w_h_w, CRC_W_H_W>;
1583def : PatGprGpr<loongarch_crc_w_w_w, CRC_W_W_W>;
1584def : PatGprGpr<loongarch_crc_w_d_w, CRC_W_D_W>;
1585def : PatGprGpr<loongarch_crcc_w_b_w, CRCC_W_B_W>;
1586def : PatGprGpr<loongarch_crcc_w_h_w, CRCC_W_H_W>;
1587def : PatGprGpr<loongarch_crcc_w_w_w, CRCC_W_W_W>;
1588def : PatGprGpr<loongarch_crcc_w_d_w, CRCC_W_D_W>;
1589} // Predicates = [IsLA64]
1590
1591/// Other pseudo-instructions
1592
1593// Pessimistically assume the stack pointer will be clobbered
1594let Defs = [R3], Uses = [R3] in {
1595def ADJCALLSTACKDOWN : Pseudo<(outs), (ins i32imm:$amt1, i32imm:$amt2),
1596                              [(callseq_start timm:$amt1, timm:$amt2)]>;
1597def ADJCALLSTACKUP   : Pseudo<(outs), (ins i32imm:$amt1, i32imm:$amt2),
1598                              [(callseq_end timm:$amt1, timm:$amt2)]>;
1599} // Defs = [R3], Uses = [R3]
1600
1601//===----------------------------------------------------------------------===//
1602// Assembler Pseudo Instructions
1603//===----------------------------------------------------------------------===//
1604
1605def : InstAlias<"nop", (ANDI R0, R0, 0)>;
1606def : InstAlias<"move $dst, $src", (OR GPR:$dst, GPR:$src, R0)>;
1607// `ret` is supported since binutils commit 20f2e2686c79a5ac (version 2.40 and
1608// later).
1609def : InstAlias<"ret", (JIRL R0, R1, 0)>;
1610def : InstAlias<"jr $rj", (JIRL R0, GPR:$rj, 0)>;
1611
1612// Branches implemented with alias.
1613// Always output the canonical mnemonic for the pseudo branch instructions.
1614// The GNU tools emit the canonical mnemonic for the branch pseudo instructions
1615// as well (e.g. "bgt" will be recognised by the assembler but never printed by
1616// objdump). Match this behaviour by setting a zero weight.
1617def : InstAlias<"bgt $rj, $rd, $imm16",
1618                (BLT GPR:$rd, GPR:$rj, simm16_lsl2_br:$imm16), 0>;
1619def : InstAlias<"bgtu $rj, $rd, $imm16",
1620                (BLTU GPR:$rd, GPR:$rj, simm16_lsl2_br:$imm16), 0>;
1621def : InstAlias<"ble $rj, $rd, $imm16",
1622                (BGE GPR:$rd, GPR:$rj, simm16_lsl2_br:$imm16), 0>;
1623def : InstAlias<"bleu $rj, $rd, $imm16",
1624                (BGEU GPR:$rd, GPR:$rj, simm16_lsl2_br:$imm16), 0>;
1625def : InstAlias<"bltz $rd, $imm16",
1626                (BLT GPR:$rd, R0, simm16_lsl2_br:$imm16), 0>;
1627def : InstAlias<"bgtz $rj, $imm16",
1628                (BLT R0, GPR:$rj, simm16_lsl2_br:$imm16), 0>;
1629def : InstAlias<"blez $rj, $imm16",
1630                (BGE R0, GPR:$rj, simm16_lsl2_br:$imm16), 0>;
1631def : InstAlias<"bgez $rd, $imm16",
1632                (BGE GPR:$rd, R0, simm16_lsl2_br:$imm16), 0>;
1633
1634// Load immediate.
1635let hasSideEffects = 0, mayLoad = 0, mayStore = 0, isCodeGenOnly = 0,
1636    isAsmParserOnly = 1 in {
1637def PseudoLI_W : Pseudo<(outs GPR:$rd), (ins imm32:$imm), [],
1638                        "li.w", "$rd, $imm">;
1639def PseudoLI_D : Pseudo<(outs GPR:$rd), (ins grlenimm:$imm), [],
1640                        "li.d", "$rd, $imm">, Requires<[IsLA64]>;
1641}
1642
1643//===----------------------------------------------------------------------===//
1644// Basic Floating-Point Instructions
1645//===----------------------------------------------------------------------===//
1646
1647include "LoongArchFloat32InstrInfo.td"
1648include "LoongArchFloat64InstrInfo.td"
1649
1650let Predicates = [HasBasicF], usesCustomInserter = 1 in {
1651  def WRFCSR : Pseudo<(outs), (ins uimm2:$fcsr, GPR:$src),
1652               [(loongarch_movgr2fcsr uimm2:$fcsr, GRLenVT:$src)]>;
1653  def RDFCSR : Pseudo<(outs GPR:$rd), (ins uimm2:$fcsr),
1654               [(set GPR:$rd, (loongarch_movfcsr2gr uimm2:$fcsr))]>;
1655}
1656
1657//===----------------------------------------------------------------------===//
1658// Privilege Instructions
1659//===----------------------------------------------------------------------===//
1660
1661// CSR Access Instructions
1662def CSRRD : FmtCSR<0b0000010000000, (outs GPR:$rd), (ins uimm14:$csr_num),
1663                   "csrrd", "$rd, $csr_num">;
1664let Constraints = "$rd = $dst" in {
1665def CSRWR : FmtCSR<0b0000010000001, (outs GPR:$dst),
1666                   (ins GPR:$rd, uimm14:$csr_num), "csrwr", "$rd, $csr_num">;
1667def CSRXCHG : FmtCSRXCHG<0b00000100, (outs GPR:$dst),
1668                         (ins GPR:$rd, GPR:$rj, uimm14:$csr_num),
1669                         "csrxchg", "$rd, $rj, $csr_num">;
1670} // Constraints = "$rd = $dst"
1671
1672// IOCSR Access Instructions
1673def IOCSRRD_B : IOCSRRD<0b0000011001001000000000, "iocsrrd.b">;
1674def IOCSRRD_H : IOCSRRD<0b0000011001001000000001, "iocsrrd.h">;
1675def IOCSRRD_W : IOCSRRD<0b0000011001001000000010, "iocsrrd.w">;
1676def IOCSRWR_B : IOCSRWR<0b0000011001001000000100, "iocsrwr.b">;
1677def IOCSRWR_H : IOCSRWR<0b0000011001001000000101, "iocsrwr.h">;
1678def IOCSRWR_W : IOCSRWR<0b0000011001001000000110, "iocsrwr.w">;
1679let Predicates = [IsLA64] in {
1680def IOCSRRD_D : IOCSRRD<0b0000011001001000000011, "iocsrrd.d">;
1681def IOCSRWR_D : IOCSRWR<0b0000011001001000000111, "iocsrwr.d">;
1682} // Predicates = [IsLA64]
1683
1684// TLB Maintenance Instructions
1685def TLBSRCH  : FmtI32<0b00000110010010000010100000000000, "tlbsrch">;
1686def TLBRD    : FmtI32<0b00000110010010000010110000000000, "tlbrd">;
1687def TLBWR    : FmtI32<0b00000110010010000011000000000000, "tlbwr">;
1688def TLBFILL  : FmtI32<0b00000110010010000011010000000000, "tlbfill">;
1689def TLBCLR   : FmtI32<0b00000110010010000010000000000000, "tlbclr">;
1690def TLBFLUSH : FmtI32<0b00000110010010000010010000000000, "tlbflush">;
1691def INVTLB : FmtINVTLB<(outs), (ins GPR:$rk, GPR:$rj, uimm5:$op), "invtlb",
1692                       "$op, $rj, $rk">;
1693
1694// Software Page Walking Instructions
1695def LDDIR : Fmt2RI8<0b00000110010000, (outs GPR:$rd),
1696                    (ins GPR:$rj, uimm8:$imm8), "lddir", "$rd, $rj, $imm8">;
1697def LDPTE : FmtLDPTE<(outs), (ins GPR:$rj, uimm8:$seq), "ldpte", "$rj, $seq">;
1698
1699
1700// Other Miscellaneous Instructions
1701def ERTN : FmtI32<0b00000110010010000011100000000000, "ertn">;
1702def DBCL : MISC_I15<0b00000000001010101, "dbcl">;
1703def IDLE : MISC_I15<0b00000110010010001, "idle">;
1704
1705//===----------------------------------------------------------------------===//
1706// Privilege Intrinsics
1707//===----------------------------------------------------------------------===//
1708
1709def : Pat<(loongarch_csrrd uimm14:$imm14), (CSRRD uimm14:$imm14)>;
1710def : Pat<(loongarch_csrwr GPR:$rd, uimm14:$imm14),
1711          (CSRWR GPR:$rd, uimm14:$imm14)>;
1712def : Pat<(loongarch_csrxchg GPR:$rd, GPR:$rj, uimm14:$imm14),
1713          (CSRXCHG GPR:$rd, GPR:$rj, uimm14:$imm14)>;
1714
1715def : Pat<(loongarch_iocsrrd_b GPR:$rj), (IOCSRRD_B GPR:$rj)>;
1716def : Pat<(loongarch_iocsrrd_h GPR:$rj), (IOCSRRD_H GPR:$rj)>;
1717def : Pat<(loongarch_iocsrrd_w GPR:$rj), (IOCSRRD_W GPR:$rj)>;
1718
1719def : Pat<(loongarch_iocsrwr_b GPR:$rd, GPR:$rj), (IOCSRWR_B GPR:$rd, GPR:$rj)>;
1720def : Pat<(loongarch_iocsrwr_h GPR:$rd, GPR:$rj), (IOCSRWR_H GPR:$rd, GPR:$rj)>;
1721def : Pat<(loongarch_iocsrwr_w GPR:$rd, GPR:$rj), (IOCSRWR_W GPR:$rd, GPR:$rj)>;
1722
1723def : Pat<(loongarch_cpucfg GPR:$rj), (CPUCFG GPR:$rj)>;
1724
1725let Predicates = [IsLA64] in {
1726def : Pat<(loongarch_iocsrrd_d GPR:$rj), (IOCSRRD_D GPR:$rj)>;
1727def : Pat<(loongarch_iocsrwr_d GPR:$rd, GPR:$rj), (IOCSRWR_D GPR:$rd, GPR:$rj)>;
1728def : Pat<(int_loongarch_asrtle_d GPR:$rj, GPR:$rk),
1729          (ASRTLE_D GPR:$rj, GPR:$rk)>;
1730def : Pat<(int_loongarch_asrtgt_d GPR:$rj, GPR:$rk),
1731          (ASRTGT_D GPR:$rj, GPR:$rk)>;
1732def : Pat<(int_loongarch_lddir_d GPR:$rj, timm:$imm8),
1733          (LDDIR GPR:$rj, uimm8:$imm8)>;
1734def : Pat<(int_loongarch_ldpte_d GPR:$rj, timm:$imm8),
1735          (LDPTE GPR:$rj, uimm8:$imm8)>;
1736} // Predicates = [IsLA64]
1737