Revert " [LoongArch][ISel] Check the number of sign bits in `PatGprGpr_32` (#107432)"
[llvm-project.git] / llvm / lib / Target / LoongArch / LoongArchInstrInfo.cpp
bloba85b054a85d724313f6d31e7e2d179f2dd052816
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.
11 //===----------------------------------------------------------------------===//
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"
22 using namespace llvm;
24 #define GET_INSTRINFO_CTOR_DTOR
25 #include "LoongArchGenInstrInfo.inc"
27 LoongArchInstrInfo::LoongArchInstrInfo(LoongArchSubtarget &STI)
28 : LoongArchGenInstrInfo(LoongArch::ADJCALLSTACKDOWN,
29 LoongArch::ADJCALLSTACKUP),
30 STI(STI) {}
32 MCInst LoongArchInstrInfo::getNop() const {
33 return MCInstBuilder(LoongArch::ANDI)
34 .addReg(LoongArch::R0)
35 .addReg(LoongArch::R0)
36 .addImm(0);
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;
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;
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;
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;
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;
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;
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");
106 BuildMI(MBB, MBBI, DL, get(Opc), DstReg)
107 .addReg(SrcReg, getKillRegState(KillSrc));
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();
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");
135 MachineMemOperand *MMO = MF->getMachineMemOperand(
136 MachinePointerInfo::getFixedStack(*MF, FI), MachineMemOperand::MOStore,
137 MFI.getObjectSize(FI), MFI.getObjectAlign(FI));
139 BuildMI(MBB, I, DebugLoc(), get(Opcode))
140 .addReg(SrcReg, getKillRegState(IsKill))
141 .addFrameIndex(FI)
142 .addImm(0)
143 .addMemOperand(MMO);
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();
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");
173 MachineMemOperand *MMO = MF->getMachineMemOperand(
174 MachinePointerInfo::getFixedStack(*MF, FI), MachineMemOperand::MOLoad,
175 MFI.getObjectSize(FI), MFI.getObjectAlign(FI));
177 BuildMI(MBB, I, DebugLoc(), get(Opcode), DstReg)
178 .addFrameIndex(FI)
179 .addImm(0)
180 .addMemOperand(MMO);
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;
189 if (!STI.is64Bit() && !isInt<32>(Val))
190 report_fatal_error("Should only materialize 32-bit constants for LA32");
192 auto Seq = LoongArchMatInt::generateInstSeq(Val);
193 assert(!Seq.empty());
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");
215 // Only the first instruction has $zero as its source.
216 SrcReg = DstReg;
220 unsigned LoongArchInstrInfo::getInstSizeInBytes(const MachineInstr &MI) const {
221 unsigned Opcode = MI.getOpcode();
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);
229 return MI.getDesc().getSize();
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);
244 return MI.isAsCheapAsAMove();
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();
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();
262 Cond.push_back(MachineOperand::CreateImm(LastInst.getOpcode()));
263 for (int i = 0; i < NumOp - 1; i++)
264 Cond.push_back(LastInst.getOperand(i));
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();
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;
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();
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--;
300 I = FirstUncondOrIndirectBr;
303 // Handle a single unconditional branch.
304 if (NumTerminators == 1 && I->getDesc().isUnconditionalBranch()) {
305 TBB = getBranchDestBlock(*I);
306 return false;
309 // Handle a single conditional branch.
310 if (NumTerminators == 1 && I->getDesc().isConditionalBranch()) {
311 parseCondBranch(*I, TBB, Cond);
312 return false;
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;
323 // Otherwise, we can't handle this.
324 return true;
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);
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;
358 if (!I->getDesc().isBranch())
359 return 0;
361 // Remove the branch.
362 if (BytesRemoved)
363 *BytesRemoved += getInstSizeInBytes(*I);
364 I->eraseFromParent();
366 I = MBB.end();
368 if (I == MBB.begin())
369 return 1;
370 --I;
371 if (!I->getDesc().isConditionalBranch())
372 return 1;
374 // Remove the branch.
375 if (BytesRemoved)
376 *BytesRemoved += getInstSizeInBytes(*I);
377 I->eraseFromParent();
378 return 2;
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;
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!");
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;
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);
410 // One-way conditional branch.
411 if (!FBB)
412 return 1;
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;
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);
432 MachineFunction *MF = MBB.getParent();
433 MachineRegisterInfo &MRI = MF->getRegInfo();
434 const TargetRegisterInfo *TRI = MF->getSubtarget().getRegisterInfo();
435 LoongArchMachineFunctionInfo *LAFI =
436 MF->getInfo<LoongArchMachineFunctionInfo>();
438 if (!isInt<32>(BrOffset))
439 report_fatal_error(
440 "Branch offsets outside of the signed 32-bit range not supported");
442 Register ScratchReg = MRI.createVirtualRegister(&LoongArch::GPRRegClass);
443 auto II = MBB.end();
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);
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);
482 MRI.replaceRegWith(ScratchReg, Scav);
483 MRI.clearVirtRegs();
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;
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;
520 std::pair<unsigned, unsigned>
521 LoongArchInstrInfo::decomposeMachineOperandsTargetFlags(unsigned TF) const {
522 return std::make_pair(TF, 0u);
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);
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;