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