xref: /freebsd/contrib/llvm-project/llvm/lib/Target/LoongArch/LoongArchInstrInfo.cpp (revision 3ceba58a7509418b47b8fca2d2b6bbf088714e26)
1 //=- LoongArchInstrInfo.cpp - LoongArch Instruction Information -*- C++ -*-===//
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 contains the LoongArch implementation of the TargetInstrInfo class.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #include "LoongArchInstrInfo.h"
14 #include "LoongArch.h"
15 #include "LoongArchMachineFunctionInfo.h"
16 #include "LoongArchRegisterInfo.h"
17 #include "MCTargetDesc/LoongArchMCTargetDesc.h"
18 #include "MCTargetDesc/LoongArchMatInt.h"
19 #include "llvm/CodeGen/RegisterScavenging.h"
20 #include "llvm/MC/MCInstBuilder.h"
21 
22 using namespace llvm;
23 
24 #define GET_INSTRINFO_CTOR_DTOR
25 #include "LoongArchGenInstrInfo.inc"
26 
27 LoongArchInstrInfo::LoongArchInstrInfo(LoongArchSubtarget &STI)
28     : LoongArchGenInstrInfo(LoongArch::ADJCALLSTACKDOWN,
29                             LoongArch::ADJCALLSTACKUP),
30       STI(STI) {}
31 
32 MCInst LoongArchInstrInfo::getNop() const {
33   return MCInstBuilder(LoongArch::ANDI)
34       .addReg(LoongArch::R0)
35       .addReg(LoongArch::R0)
36       .addImm(0);
37 }
38 
39 void LoongArchInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
40                                      MachineBasicBlock::iterator MBBI,
41                                      const DebugLoc &DL, MCRegister DstReg,
42                                      MCRegister SrcReg, bool KillSrc) const {
43   if (LoongArch::GPRRegClass.contains(DstReg, SrcReg)) {
44     BuildMI(MBB, MBBI, DL, get(LoongArch::OR), DstReg)
45         .addReg(SrcReg, getKillRegState(KillSrc))
46         .addReg(LoongArch::R0);
47     return;
48   }
49 
50   // VR->VR copies.
51   if (LoongArch::LSX128RegClass.contains(DstReg, SrcReg)) {
52     BuildMI(MBB, MBBI, DL, get(LoongArch::VORI_B), DstReg)
53         .addReg(SrcReg, getKillRegState(KillSrc))
54         .addImm(0);
55     return;
56   }
57 
58   // XR->XR copies.
59   if (LoongArch::LASX256RegClass.contains(DstReg, SrcReg)) {
60     BuildMI(MBB, MBBI, DL, get(LoongArch::XVORI_B), DstReg)
61         .addReg(SrcReg, getKillRegState(KillSrc))
62         .addImm(0);
63     return;
64   }
65 
66   // GPR->CFR copy.
67   if (LoongArch::CFRRegClass.contains(DstReg) &&
68       LoongArch::GPRRegClass.contains(SrcReg)) {
69     BuildMI(MBB, MBBI, DL, get(LoongArch::MOVGR2CF), DstReg)
70         .addReg(SrcReg, getKillRegState(KillSrc));
71     return;
72   }
73   // CFR->GPR copy.
74   if (LoongArch::GPRRegClass.contains(DstReg) &&
75       LoongArch::CFRRegClass.contains(SrcReg)) {
76     BuildMI(MBB, MBBI, DL, get(LoongArch::MOVCF2GR), DstReg)
77         .addReg(SrcReg, getKillRegState(KillSrc));
78     return;
79   }
80   // CFR->CFR copy.
81   if (LoongArch::CFRRegClass.contains(DstReg, SrcReg)) {
82     BuildMI(MBB, MBBI, DL, get(LoongArch::PseudoCopyCFR), DstReg)
83         .addReg(SrcReg, getKillRegState(KillSrc));
84     return;
85   }
86 
87   // FPR->FPR copies.
88   unsigned Opc;
89   if (LoongArch::FPR32RegClass.contains(DstReg, SrcReg)) {
90     Opc = LoongArch::FMOV_S;
91   } else if (LoongArch::FPR64RegClass.contains(DstReg, SrcReg)) {
92     Opc = LoongArch::FMOV_D;
93   } else if (LoongArch::GPRRegClass.contains(DstReg) &&
94              LoongArch::FPR32RegClass.contains(SrcReg)) {
95     // FPR32 -> GPR copies
96     Opc = LoongArch::MOVFR2GR_S;
97   } else if (LoongArch::GPRRegClass.contains(DstReg) &&
98              LoongArch::FPR64RegClass.contains(SrcReg)) {
99     // FPR64 -> GPR copies
100     Opc = LoongArch::MOVFR2GR_D;
101   } else {
102     // TODO: support other copies.
103     llvm_unreachable("Impossible reg-to-reg copy");
104   }
105 
106   BuildMI(MBB, MBBI, DL, get(Opc), DstReg)
107       .addReg(SrcReg, getKillRegState(KillSrc));
108 }
109 
110 void LoongArchInstrInfo::storeRegToStackSlot(
111     MachineBasicBlock &MBB, MachineBasicBlock::iterator I, Register SrcReg,
112     bool IsKill, int FI, const TargetRegisterClass *RC,
113     const TargetRegisterInfo *TRI, Register VReg) const {
114   MachineFunction *MF = MBB.getParent();
115   MachineFrameInfo &MFI = MF->getFrameInfo();
116 
117   unsigned Opcode;
118   if (LoongArch::GPRRegClass.hasSubClassEq(RC))
119     Opcode = TRI->getRegSizeInBits(LoongArch::GPRRegClass) == 32
120                  ? LoongArch::ST_W
121                  : LoongArch::ST_D;
122   else if (LoongArch::FPR32RegClass.hasSubClassEq(RC))
123     Opcode = LoongArch::FST_S;
124   else if (LoongArch::FPR64RegClass.hasSubClassEq(RC))
125     Opcode = LoongArch::FST_D;
126   else if (LoongArch::LSX128RegClass.hasSubClassEq(RC))
127     Opcode = LoongArch::VST;
128   else if (LoongArch::LASX256RegClass.hasSubClassEq(RC))
129     Opcode = LoongArch::XVST;
130   else if (LoongArch::CFRRegClass.hasSubClassEq(RC))
131     Opcode = LoongArch::PseudoST_CFR;
132   else
133     llvm_unreachable("Can't store this register to stack slot");
134 
135   MachineMemOperand *MMO = MF->getMachineMemOperand(
136       MachinePointerInfo::getFixedStack(*MF, FI), MachineMemOperand::MOStore,
137       MFI.getObjectSize(FI), MFI.getObjectAlign(FI));
138 
139   BuildMI(MBB, I, DebugLoc(), get(Opcode))
140       .addReg(SrcReg, getKillRegState(IsKill))
141       .addFrameIndex(FI)
142       .addImm(0)
143       .addMemOperand(MMO);
144 }
145 
146 void LoongArchInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB,
147                                               MachineBasicBlock::iterator I,
148                                               Register DstReg, int FI,
149                                               const TargetRegisterClass *RC,
150                                               const TargetRegisterInfo *TRI,
151                                               Register VReg) const {
152   MachineFunction *MF = MBB.getParent();
153   MachineFrameInfo &MFI = MF->getFrameInfo();
154 
155   unsigned Opcode;
156   if (LoongArch::GPRRegClass.hasSubClassEq(RC))
157     Opcode = TRI->getRegSizeInBits(LoongArch::GPRRegClass) == 32
158                  ? LoongArch::LD_W
159                  : LoongArch::LD_D;
160   else if (LoongArch::FPR32RegClass.hasSubClassEq(RC))
161     Opcode = LoongArch::FLD_S;
162   else if (LoongArch::FPR64RegClass.hasSubClassEq(RC))
163     Opcode = LoongArch::FLD_D;
164   else if (LoongArch::LSX128RegClass.hasSubClassEq(RC))
165     Opcode = LoongArch::VLD;
166   else if (LoongArch::LASX256RegClass.hasSubClassEq(RC))
167     Opcode = LoongArch::XVLD;
168   else if (LoongArch::CFRRegClass.hasSubClassEq(RC))
169     Opcode = LoongArch::PseudoLD_CFR;
170   else
171     llvm_unreachable("Can't load this register from stack slot");
172 
173   MachineMemOperand *MMO = MF->getMachineMemOperand(
174       MachinePointerInfo::getFixedStack(*MF, FI), MachineMemOperand::MOLoad,
175       MFI.getObjectSize(FI), MFI.getObjectAlign(FI));
176 
177   BuildMI(MBB, I, DebugLoc(), get(Opcode), DstReg)
178       .addFrameIndex(FI)
179       .addImm(0)
180       .addMemOperand(MMO);
181 }
182 
183 void LoongArchInstrInfo::movImm(MachineBasicBlock &MBB,
184                                 MachineBasicBlock::iterator MBBI,
185                                 const DebugLoc &DL, Register DstReg,
186                                 uint64_t Val, MachineInstr::MIFlag Flag) const {
187   Register SrcReg = LoongArch::R0;
188 
189   if (!STI.is64Bit() && !isInt<32>(Val))
190     report_fatal_error("Should only materialize 32-bit constants for LA32");
191 
192   auto Seq = LoongArchMatInt::generateInstSeq(Val);
193   assert(!Seq.empty());
194 
195   for (auto &Inst : Seq) {
196     switch (Inst.Opc) {
197     case LoongArch::LU12I_W:
198       BuildMI(MBB, MBBI, DL, get(Inst.Opc), DstReg)
199           .addImm(Inst.Imm)
200           .setMIFlag(Flag);
201       break;
202     case LoongArch::ADDI_W:
203     case LoongArch::ORI:
204     case LoongArch::LU32I_D: // "rj" is needed due to InstrInfo pattern
205     case LoongArch::LU52I_D:
206       BuildMI(MBB, MBBI, DL, get(Inst.Opc), DstReg)
207           .addReg(SrcReg, RegState::Kill)
208           .addImm(Inst.Imm)
209           .setMIFlag(Flag);
210       break;
211     default:
212       assert(false && "Unknown insn emitted by LoongArchMatInt");
213     }
214 
215     // Only the first instruction has $zero as its source.
216     SrcReg = DstReg;
217   }
218 }
219 
220 unsigned LoongArchInstrInfo::getInstSizeInBytes(const MachineInstr &MI) const {
221   unsigned Opcode = MI.getOpcode();
222 
223   if (Opcode == TargetOpcode::INLINEASM ||
224       Opcode == TargetOpcode::INLINEASM_BR) {
225     const MachineFunction *MF = MI.getParent()->getParent();
226     const MCAsmInfo *MAI = MF->getTarget().getMCAsmInfo();
227     return getInlineAsmLength(MI.getOperand(0).getSymbolName(), *MAI);
228   }
229   return MI.getDesc().getSize();
230 }
231 
232 bool LoongArchInstrInfo::isAsCheapAsAMove(const MachineInstr &MI) const {
233   const unsigned Opcode = MI.getOpcode();
234   switch (Opcode) {
235   default:
236     break;
237   case LoongArch::ADDI_D:
238   case LoongArch::ORI:
239   case LoongArch::XORI:
240     return (MI.getOperand(1).isReg() &&
241             MI.getOperand(1).getReg() == LoongArch::R0) ||
242            (MI.getOperand(2).isImm() && MI.getOperand(2).getImm() == 0);
243   }
244   return MI.isAsCheapAsAMove();
245 }
246 
247 MachineBasicBlock *
248 LoongArchInstrInfo::getBranchDestBlock(const MachineInstr &MI) const {
249   assert(MI.getDesc().isBranch() && "Unexpected opcode!");
250   // The branch target is always the last operand.
251   return MI.getOperand(MI.getNumExplicitOperands() - 1).getMBB();
252 }
253 
254 static void parseCondBranch(MachineInstr &LastInst, MachineBasicBlock *&Target,
255                             SmallVectorImpl<MachineOperand> &Cond) {
256   // Block ends with fall-through condbranch.
257   assert(LastInst.getDesc().isConditionalBranch() &&
258          "Unknown conditional branch");
259   int NumOp = LastInst.getNumExplicitOperands();
260   Target = LastInst.getOperand(NumOp - 1).getMBB();
261 
262   Cond.push_back(MachineOperand::CreateImm(LastInst.getOpcode()));
263   for (int i = 0; i < NumOp - 1; i++)
264     Cond.push_back(LastInst.getOperand(i));
265 }
266 
267 bool LoongArchInstrInfo::analyzeBranch(MachineBasicBlock &MBB,
268                                        MachineBasicBlock *&TBB,
269                                        MachineBasicBlock *&FBB,
270                                        SmallVectorImpl<MachineOperand> &Cond,
271                                        bool AllowModify) const {
272   TBB = FBB = nullptr;
273   Cond.clear();
274 
275   // If the block has no terminators, it just falls into the block after it.
276   MachineBasicBlock::iterator I = MBB.getLastNonDebugInstr();
277   if (I == MBB.end() || !isUnpredicatedTerminator(*I))
278     return false;
279 
280   // Count the number of terminators and find the first unconditional or
281   // indirect branch.
282   MachineBasicBlock::iterator FirstUncondOrIndirectBr = MBB.end();
283   int NumTerminators = 0;
284   for (auto J = I.getReverse(); J != MBB.rend() && isUnpredicatedTerminator(*J);
285        J++) {
286     NumTerminators++;
287     if (J->getDesc().isUnconditionalBranch() ||
288         J->getDesc().isIndirectBranch()) {
289       FirstUncondOrIndirectBr = J.getReverse();
290     }
291   }
292 
293   // If AllowModify is true, we can erase any terminators after
294   // FirstUncondOrIndirectBR.
295   if (AllowModify && FirstUncondOrIndirectBr != MBB.end()) {
296     while (std::next(FirstUncondOrIndirectBr) != MBB.end()) {
297       std::next(FirstUncondOrIndirectBr)->eraseFromParent();
298       NumTerminators--;
299     }
300     I = FirstUncondOrIndirectBr;
301   }
302 
303   // Handle a single unconditional branch.
304   if (NumTerminators == 1 && I->getDesc().isUnconditionalBranch()) {
305     TBB = getBranchDestBlock(*I);
306     return false;
307   }
308 
309   // Handle a single conditional branch.
310   if (NumTerminators == 1 && I->getDesc().isConditionalBranch()) {
311     parseCondBranch(*I, TBB, Cond);
312     return false;
313   }
314 
315   // Handle a conditional branch followed by an unconditional branch.
316   if (NumTerminators == 2 && std::prev(I)->getDesc().isConditionalBranch() &&
317       I->getDesc().isUnconditionalBranch()) {
318     parseCondBranch(*std::prev(I), TBB, Cond);
319     FBB = getBranchDestBlock(*I);
320     return false;
321   }
322 
323   // Otherwise, we can't handle this.
324   return true;
325 }
326 
327 bool LoongArchInstrInfo::isBranchOffsetInRange(unsigned BranchOp,
328                                                int64_t BrOffset) const {
329   switch (BranchOp) {
330   default:
331     llvm_unreachable("Unknown branch instruction!");
332   case LoongArch::BEQ:
333   case LoongArch::BNE:
334   case LoongArch::BLT:
335   case LoongArch::BGE:
336   case LoongArch::BLTU:
337   case LoongArch::BGEU:
338     return isInt<18>(BrOffset);
339   case LoongArch::BEQZ:
340   case LoongArch::BNEZ:
341   case LoongArch::BCEQZ:
342   case LoongArch::BCNEZ:
343     return isInt<23>(BrOffset);
344   case LoongArch::B:
345   case LoongArch::PseudoBR:
346     return isInt<28>(BrOffset);
347   }
348 }
349 
350 unsigned LoongArchInstrInfo::removeBranch(MachineBasicBlock &MBB,
351                                           int *BytesRemoved) const {
352   if (BytesRemoved)
353     *BytesRemoved = 0;
354   MachineBasicBlock::iterator I = MBB.getLastNonDebugInstr();
355   if (I == MBB.end())
356     return 0;
357 
358   if (!I->getDesc().isBranch())
359     return 0;
360 
361   // Remove the branch.
362   if (BytesRemoved)
363     *BytesRemoved += getInstSizeInBytes(*I);
364   I->eraseFromParent();
365 
366   I = MBB.end();
367 
368   if (I == MBB.begin())
369     return 1;
370   --I;
371   if (!I->getDesc().isConditionalBranch())
372     return 1;
373 
374   // Remove the branch.
375   if (BytesRemoved)
376     *BytesRemoved += getInstSizeInBytes(*I);
377   I->eraseFromParent();
378   return 2;
379 }
380 
381 // Inserts a branch into the end of the specific MachineBasicBlock, returning
382 // the number of instructions inserted.
383 unsigned LoongArchInstrInfo::insertBranch(
384     MachineBasicBlock &MBB, MachineBasicBlock *TBB, MachineBasicBlock *FBB,
385     ArrayRef<MachineOperand> Cond, const DebugLoc &DL, int *BytesAdded) const {
386   if (BytesAdded)
387     *BytesAdded = 0;
388 
389   // Shouldn't be a fall through.
390   assert(TBB && "insertBranch must not be told to insert a fallthrough");
391   assert(Cond.size() <= 3 && Cond.size() != 1 &&
392          "LoongArch branch conditions have at most two components!");
393 
394   // Unconditional branch.
395   if (Cond.empty()) {
396     MachineInstr &MI = *BuildMI(&MBB, DL, get(LoongArch::PseudoBR)).addMBB(TBB);
397     if (BytesAdded)
398       *BytesAdded += getInstSizeInBytes(MI);
399     return 1;
400   }
401 
402   // Either a one or two-way conditional branch.
403   MachineInstrBuilder MIB = BuildMI(&MBB, DL, get(Cond[0].getImm()));
404   for (unsigned i = 1; i < Cond.size(); ++i)
405     MIB.add(Cond[i]);
406   MIB.addMBB(TBB);
407   if (BytesAdded)
408     *BytesAdded += getInstSizeInBytes(*MIB);
409 
410   // One-way conditional branch.
411   if (!FBB)
412     return 1;
413 
414   // Two-way conditional branch.
415   MachineInstr &MI = *BuildMI(&MBB, DL, get(LoongArch::PseudoBR)).addMBB(FBB);
416   if (BytesAdded)
417     *BytesAdded += getInstSizeInBytes(MI);
418   return 2;
419 }
420 
421 void LoongArchInstrInfo::insertIndirectBranch(MachineBasicBlock &MBB,
422                                               MachineBasicBlock &DestBB,
423                                               MachineBasicBlock &RestoreBB,
424                                               const DebugLoc &DL,
425                                               int64_t BrOffset,
426                                               RegScavenger *RS) const {
427   assert(RS && "RegScavenger required for long branching");
428   assert(MBB.empty() &&
429          "new block should be inserted for expanding unconditional branch");
430   assert(MBB.pred_size() == 1);
431 
432   MachineFunction *MF = MBB.getParent();
433   MachineRegisterInfo &MRI = MF->getRegInfo();
434   const TargetRegisterInfo *TRI = MF->getSubtarget().getRegisterInfo();
435   LoongArchMachineFunctionInfo *LAFI =
436       MF->getInfo<LoongArchMachineFunctionInfo>();
437 
438   if (!isInt<32>(BrOffset))
439     report_fatal_error(
440         "Branch offsets outside of the signed 32-bit range not supported");
441 
442   Register ScratchReg = MRI.createVirtualRegister(&LoongArch::GPRRegClass);
443   auto II = MBB.end();
444 
445   MachineInstr &PCALAU12I =
446       *BuildMI(MBB, II, DL, get(LoongArch::PCALAU12I), ScratchReg)
447            .addMBB(&DestBB, LoongArchII::MO_PCREL_HI);
448   MachineInstr &ADDI =
449       *BuildMI(MBB, II, DL,
450                get(STI.is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W),
451                ScratchReg)
452            .addReg(ScratchReg)
453            .addMBB(&DestBB, LoongArchII::MO_PCREL_LO);
454   BuildMI(MBB, II, DL, get(LoongArch::PseudoBRIND))
455       .addReg(ScratchReg, RegState::Kill)
456       .addImm(0);
457 
458   RS->enterBasicBlockEnd(MBB);
459   Register Scav = RS->scavengeRegisterBackwards(
460       LoongArch::GPRRegClass, PCALAU12I.getIterator(), /*RestoreAfter=*/false,
461       /*SPAdj=*/0, /*AllowSpill=*/false);
462   if (Scav != LoongArch::NoRegister)
463     RS->setRegUsed(Scav);
464   else {
465     // When there is no scavenged register, it needs to specify a register.
466     // Specify t8 register because it won't be used too often.
467     Scav = LoongArch::R20;
468     int FrameIndex = LAFI->getBranchRelaxationSpillFrameIndex();
469     if (FrameIndex == -1)
470       report_fatal_error("The function size is incorrectly estimated.");
471     storeRegToStackSlot(MBB, PCALAU12I, Scav, /*IsKill=*/true, FrameIndex,
472                         &LoongArch::GPRRegClass, TRI, Register());
473     TRI->eliminateFrameIndex(std::prev(PCALAU12I.getIterator()),
474                              /*SpAdj=*/0, /*FIOperandNum=*/1);
475     PCALAU12I.getOperand(1).setMBB(&RestoreBB);
476     ADDI.getOperand(2).setMBB(&RestoreBB);
477     loadRegFromStackSlot(RestoreBB, RestoreBB.end(), Scav, FrameIndex,
478                          &LoongArch::GPRRegClass, TRI, Register());
479     TRI->eliminateFrameIndex(RestoreBB.back(),
480                              /*SpAdj=*/0, /*FIOperandNum=*/1);
481   }
482   MRI.replaceRegWith(ScratchReg, Scav);
483   MRI.clearVirtRegs();
484 }
485 
486 static unsigned getOppositeBranchOpc(unsigned Opc) {
487   switch (Opc) {
488   default:
489     llvm_unreachable("Unrecognized conditional branch");
490   case LoongArch::BEQ:
491     return LoongArch::BNE;
492   case LoongArch::BNE:
493     return LoongArch::BEQ;
494   case LoongArch::BEQZ:
495     return LoongArch::BNEZ;
496   case LoongArch::BNEZ:
497     return LoongArch::BEQZ;
498   case LoongArch::BCEQZ:
499     return LoongArch::BCNEZ;
500   case LoongArch::BCNEZ:
501     return LoongArch::BCEQZ;
502   case LoongArch::BLT:
503     return LoongArch::BGE;
504   case LoongArch::BGE:
505     return LoongArch::BLT;
506   case LoongArch::BLTU:
507     return LoongArch::BGEU;
508   case LoongArch::BGEU:
509     return LoongArch::BLTU;
510   }
511 }
512 
513 bool LoongArchInstrInfo::reverseBranchCondition(
514     SmallVectorImpl<MachineOperand> &Cond) const {
515   assert((Cond.size() && Cond.size() <= 3) && "Invalid branch condition!");
516   Cond[0].setImm(getOppositeBranchOpc(Cond[0].getImm()));
517   return false;
518 }
519 
520 std::pair<unsigned, unsigned>
521 LoongArchInstrInfo::decomposeMachineOperandsTargetFlags(unsigned TF) const {
522   return std::make_pair(TF, 0u);
523 }
524 
525 ArrayRef<std::pair<unsigned, const char *>>
526 LoongArchInstrInfo::getSerializableDirectMachineOperandTargetFlags() const {
527   using namespace LoongArchII;
528   // TODO: Add more target flags.
529   static const std::pair<unsigned, const char *> TargetFlags[] = {
530       {MO_CALL, "loongarch-call"},
531       {MO_CALL_PLT, "loongarch-call-plt"},
532       {MO_PCREL_HI, "loongarch-pcrel-hi"},
533       {MO_PCREL_LO, "loongarch-pcrel-lo"},
534       {MO_PCREL64_LO, "loongarch-pcrel64-lo"},
535       {MO_PCREL64_HI, "loongarch-pcrel64-hi"},
536       {MO_GOT_PC_HI, "loongarch-got-pc-hi"},
537       {MO_GOT_PC_LO, "loongarch-got-pc-lo"},
538       {MO_GOT_PC64_LO, "loongarch-got-pc64-lo"},
539       {MO_GOT_PC64_HI, "loongarch-got-pc64-hi"},
540       {MO_LE_HI, "loongarch-le-hi"},
541       {MO_LE_LO, "loongarch-le-lo"},
542       {MO_LE64_LO, "loongarch-le64-lo"},
543       {MO_LE64_HI, "loongarch-le64-hi"},
544       {MO_IE_PC_HI, "loongarch-ie-pc-hi"},
545       {MO_IE_PC_LO, "loongarch-ie-pc-lo"},
546       {MO_IE_PC64_LO, "loongarch-ie-pc64-lo"},
547       {MO_IE_PC64_HI, "loongarch-ie-pc64-hi"},
548       {MO_DESC_PC_HI, "loongarch-desc-pc-hi"},
549       {MO_DESC_PC_LO, "loongarch-desc-pc-lo"},
550       {MO_DESC64_PC_LO, "loongarch-desc64-pc-lo"},
551       {MO_DESC64_PC_HI, "loongarch-desc64-pc-hi"},
552       {MO_DESC_LD, "loongarch-desc-ld"},
553       {MO_DESC_CALL, "loongarch-desc-call"},
554       {MO_LD_PC_HI, "loongarch-ld-pc-hi"},
555       {MO_GD_PC_HI, "loongarch-gd-pc-hi"}};
556   return ArrayRef(TargetFlags);
557 }
558 
559 // Returns true if this is the sext.w pattern, addi.w rd, rs, 0.
560 bool LoongArch::isSEXT_W(const MachineInstr &MI) {
561   return MI.getOpcode() == LoongArch::ADDI_W && MI.getOperand(1).isReg() &&
562          MI.getOperand(2).isImm() && MI.getOperand(2).getImm() == 0;
563 }
564