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
22using namespace llvm;
23
24#define GET_INSTRINFO_CTOR_DTOR
25#include "LoongArchGenInstrInfo.inc"
26
27LoongArchInstrInfo::LoongArchInstrInfo(LoongArchSubtarget &STI)
28 : LoongArchGenInstrInfo(LoongArch::ADJCALLSTACKDOWN,
29 LoongArch::ADJCALLSTACKUP),
30 STI(STI) {}
31
32MCInst LoongArchInstrInfo::getNop() const {
33 return MCInstBuilder(LoongArch::ANDI)
34 .addReg(LoongArch::R0)
35 .addReg(LoongArch::R0)
36 .addImm(0);
37}
38
39void 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(B: 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(B: 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(B: 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(B: 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(B: 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(B: 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(B: KillSrc));
108}
109
110void 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 PtrInfo: MachinePointerInfo::getFixedStack(MF&: *MF, FI), F: MachineMemOperand::MOStore,
137 Size: MFI.getObjectSize(ObjectIdx: FI), BaseAlignment: MFI.getObjectAlign(ObjectIdx: FI));
138
139 BuildMI(MBB, I, DebugLoc(), get(Opcode))
140 .addReg(SrcReg, getKillRegState(B: IsKill))
141 .addFrameIndex(FI)
142 .addImm(0)
143 .addMemOperand(MMO);
144}
145
146void 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 PtrInfo: MachinePointerInfo::getFixedStack(MF&: *MF, FI), F: MachineMemOperand::MOLoad,
175 Size: MFI.getObjectSize(ObjectIdx: FI), BaseAlignment: MFI.getObjectAlign(ObjectIdx: FI));
176
177 BuildMI(MBB, I, DebugLoc(), get(Opcode), DstReg)
178 .addFrameIndex(FI)
179 .addImm(0)
180 .addMemOperand(MMO);
181}
182
183void 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>(x: Val))
190 report_fatal_error(reason: "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
220unsigned 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(i: 0).getSymbolName(), *MAI);
228 }
229 return MI.getDesc().getSize();
230}
231
232MachineBasicBlock *
233LoongArchInstrInfo::getBranchDestBlock(const MachineInstr &MI) const {
234 assert(MI.getDesc().isBranch() && "Unexpected opcode!");
235 // The branch target is always the last operand.
236 return MI.getOperand(i: MI.getNumExplicitOperands() - 1).getMBB();
237}
238
239static void parseCondBranch(MachineInstr &LastInst, MachineBasicBlock *&Target,
240 SmallVectorImpl<MachineOperand> &Cond) {
241 // Block ends with fall-through condbranch.
242 assert(LastInst.getDesc().isConditionalBranch() &&
243 "Unknown conditional branch");
244 int NumOp = LastInst.getNumExplicitOperands();
245 Target = LastInst.getOperand(i: NumOp - 1).getMBB();
246
247 Cond.push_back(Elt: MachineOperand::CreateImm(Val: LastInst.getOpcode()));
248 for (int i = 0; i < NumOp - 1; i++)
249 Cond.push_back(Elt: LastInst.getOperand(i));
250}
251
252bool LoongArchInstrInfo::analyzeBranch(MachineBasicBlock &MBB,
253 MachineBasicBlock *&TBB,
254 MachineBasicBlock *&FBB,
255 SmallVectorImpl<MachineOperand> &Cond,
256 bool AllowModify) const {
257 TBB = FBB = nullptr;
258 Cond.clear();
259
260 // If the block has no terminators, it just falls into the block after it.
261 MachineBasicBlock::iterator I = MBB.getLastNonDebugInstr();
262 if (I == MBB.end() || !isUnpredicatedTerminator(*I))
263 return false;
264
265 // Count the number of terminators and find the first unconditional or
266 // indirect branch.
267 MachineBasicBlock::iterator FirstUncondOrIndirectBr = MBB.end();
268 int NumTerminators = 0;
269 for (auto J = I.getReverse(); J != MBB.rend() && isUnpredicatedTerminator(*J);
270 J++) {
271 NumTerminators++;
272 if (J->getDesc().isUnconditionalBranch() ||
273 J->getDesc().isIndirectBranch()) {
274 FirstUncondOrIndirectBr = J.getReverse();
275 }
276 }
277
278 // If AllowModify is true, we can erase any terminators after
279 // FirstUncondOrIndirectBR.
280 if (AllowModify && FirstUncondOrIndirectBr != MBB.end()) {
281 while (std::next(x: FirstUncondOrIndirectBr) != MBB.end()) {
282 std::next(x: FirstUncondOrIndirectBr)->eraseFromParent();
283 NumTerminators--;
284 }
285 I = FirstUncondOrIndirectBr;
286 }
287
288 // Handle a single unconditional branch.
289 if (NumTerminators == 1 && I->getDesc().isUnconditionalBranch()) {
290 TBB = getBranchDestBlock(MI: *I);
291 return false;
292 }
293
294 // Handle a single conditional branch.
295 if (NumTerminators == 1 && I->getDesc().isConditionalBranch()) {
296 parseCondBranch(LastInst&: *I, Target&: TBB, Cond);
297 return false;
298 }
299
300 // Handle a conditional branch followed by an unconditional branch.
301 if (NumTerminators == 2 && std::prev(x: I)->getDesc().isConditionalBranch() &&
302 I->getDesc().isUnconditionalBranch()) {
303 parseCondBranch(LastInst&: *std::prev(x: I), Target&: TBB, Cond);
304 FBB = getBranchDestBlock(MI: *I);
305 return false;
306 }
307
308 // Otherwise, we can't handle this.
309 return true;
310}
311
312bool LoongArchInstrInfo::isBranchOffsetInRange(unsigned BranchOp,
313 int64_t BrOffset) const {
314 switch (BranchOp) {
315 default:
316 llvm_unreachable("Unknown branch instruction!");
317 case LoongArch::BEQ:
318 case LoongArch::BNE:
319 case LoongArch::BLT:
320 case LoongArch::BGE:
321 case LoongArch::BLTU:
322 case LoongArch::BGEU:
323 return isInt<18>(x: BrOffset);
324 case LoongArch::BEQZ:
325 case LoongArch::BNEZ:
326 case LoongArch::BCEQZ:
327 case LoongArch::BCNEZ:
328 return isInt<23>(x: BrOffset);
329 case LoongArch::B:
330 case LoongArch::PseudoBR:
331 return isInt<28>(x: BrOffset);
332 }
333}
334
335unsigned LoongArchInstrInfo::removeBranch(MachineBasicBlock &MBB,
336 int *BytesRemoved) const {
337 if (BytesRemoved)
338 *BytesRemoved = 0;
339 MachineBasicBlock::iterator I = MBB.getLastNonDebugInstr();
340 if (I == MBB.end())
341 return 0;
342
343 if (!I->getDesc().isBranch())
344 return 0;
345
346 // Remove the branch.
347 if (BytesRemoved)
348 *BytesRemoved += getInstSizeInBytes(MI: *I);
349 I->eraseFromParent();
350
351 I = MBB.end();
352
353 if (I == MBB.begin())
354 return 1;
355 --I;
356 if (!I->getDesc().isConditionalBranch())
357 return 1;
358
359 // Remove the branch.
360 if (BytesRemoved)
361 *BytesRemoved += getInstSizeInBytes(MI: *I);
362 I->eraseFromParent();
363 return 2;
364}
365
366// Inserts a branch into the end of the specific MachineBasicBlock, returning
367// the number of instructions inserted.
368unsigned LoongArchInstrInfo::insertBranch(
369 MachineBasicBlock &MBB, MachineBasicBlock *TBB, MachineBasicBlock *FBB,
370 ArrayRef<MachineOperand> Cond, const DebugLoc &DL, int *BytesAdded) const {
371 if (BytesAdded)
372 *BytesAdded = 0;
373
374 // Shouldn't be a fall through.
375 assert(TBB && "insertBranch must not be told to insert a fallthrough");
376 assert(Cond.size() <= 3 && Cond.size() != 1 &&
377 "LoongArch branch conditions have at most two components!");
378
379 // Unconditional branch.
380 if (Cond.empty()) {
381 MachineInstr &MI = *BuildMI(&MBB, DL, get(LoongArch::PseudoBR)).addMBB(TBB);
382 if (BytesAdded)
383 *BytesAdded += getInstSizeInBytes(MI);
384 return 1;
385 }
386
387 // Either a one or two-way conditional branch.
388 MachineInstrBuilder MIB = BuildMI(&MBB, DL, get(Cond[0].getImm()));
389 for (unsigned i = 1; i < Cond.size(); ++i)
390 MIB.add(MO: Cond[i]);
391 MIB.addMBB(MBB: TBB);
392 if (BytesAdded)
393 *BytesAdded += getInstSizeInBytes(MI: *MIB);
394
395 // One-way conditional branch.
396 if (!FBB)
397 return 1;
398
399 // Two-way conditional branch.
400 MachineInstr &MI = *BuildMI(&MBB, DL, get(LoongArch::PseudoBR)).addMBB(FBB);
401 if (BytesAdded)
402 *BytesAdded += getInstSizeInBytes(MI);
403 return 2;
404}
405
406void LoongArchInstrInfo::insertIndirectBranch(MachineBasicBlock &MBB,
407 MachineBasicBlock &DestBB,
408 MachineBasicBlock &RestoreBB,
409 const DebugLoc &DL,
410 int64_t BrOffset,
411 RegScavenger *RS) const {
412 assert(RS && "RegScavenger required for long branching");
413 assert(MBB.empty() &&
414 "new block should be inserted for expanding unconditional branch");
415 assert(MBB.pred_size() == 1);
416
417 MachineFunction *MF = MBB.getParent();
418 MachineRegisterInfo &MRI = MF->getRegInfo();
419 const TargetRegisterInfo *TRI = MF->getSubtarget().getRegisterInfo();
420 LoongArchMachineFunctionInfo *LAFI =
421 MF->getInfo<LoongArchMachineFunctionInfo>();
422
423 if (!isInt<32>(x: BrOffset))
424 report_fatal_error(
425 reason: "Branch offsets outside of the signed 32-bit range not supported");
426
427 Register ScratchReg = MRI.createVirtualRegister(&LoongArch::GPRRegClass);
428 auto II = MBB.end();
429
430 MachineInstr &PCALAU12I =
431 *BuildMI(MBB, II, DL, get(LoongArch::PCALAU12I), ScratchReg)
432 .addMBB(&DestBB, LoongArchII::MO_PCREL_HI);
433 MachineInstr &ADDI =
434 *BuildMI(MBB, II, DL,
435 get(STI.is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W),
436 ScratchReg)
437 .addReg(ScratchReg)
438 .addMBB(&DestBB, LoongArchII::MO_PCREL_LO);
439 BuildMI(MBB, II, DL, get(LoongArch::PseudoBRIND))
440 .addReg(ScratchReg, RegState::Kill)
441 .addImm(0);
442
443 RS->enterBasicBlockEnd(MBB);
444 Register Scav = RS->scavengeRegisterBackwards(
445 LoongArch::GPRRegClass, PCALAU12I.getIterator(), /*RestoreAfter=*/false,
446 /*SPAdj=*/0, /*AllowSpill=*/false);
447 if (Scav != LoongArch::NoRegister)
448 RS->setRegUsed(Reg: Scav);
449 else {
450 // When there is no scavenged register, it needs to specify a register.
451 // Specify t8 register because it won't be used too often.
452 Scav = LoongArch::R20;
453 int FrameIndex = LAFI->getBranchRelaxationSpillFrameIndex();
454 if (FrameIndex == -1)
455 report_fatal_error(reason: "The function size is incorrectly estimated.");
456 storeRegToStackSlot(MBB, PCALAU12I, Scav, /*IsKill=*/true, FrameIndex,
457 &LoongArch::GPRRegClass, TRI, Register());
458 TRI->eliminateFrameIndex(MI: std::prev(x: PCALAU12I.getIterator()),
459 /*SpAdj=*/SPAdj: 0, /*FIOperandNum=*/1);
460 PCALAU12I.getOperand(i: 1).setMBB(&RestoreBB);
461 ADDI.getOperand(i: 2).setMBB(&RestoreBB);
462 loadRegFromStackSlot(RestoreBB, RestoreBB.end(), Scav, FrameIndex,
463 &LoongArch::GPRRegClass, TRI, Register());
464 TRI->eliminateFrameIndex(MI: RestoreBB.back(),
465 /*SpAdj=*/SPAdj: 0, /*FIOperandNum=*/1);
466 }
467 MRI.replaceRegWith(FromReg: ScratchReg, ToReg: Scav);
468 MRI.clearVirtRegs();
469}
470
471static unsigned getOppositeBranchOpc(unsigned Opc) {
472 switch (Opc) {
473 default:
474 llvm_unreachable("Unrecognized conditional branch");
475 case LoongArch::BEQ:
476 return LoongArch::BNE;
477 case LoongArch::BNE:
478 return LoongArch::BEQ;
479 case LoongArch::BEQZ:
480 return LoongArch::BNEZ;
481 case LoongArch::BNEZ:
482 return LoongArch::BEQZ;
483 case LoongArch::BCEQZ:
484 return LoongArch::BCNEZ;
485 case LoongArch::BCNEZ:
486 return LoongArch::BCEQZ;
487 case LoongArch::BLT:
488 return LoongArch::BGE;
489 case LoongArch::BGE:
490 return LoongArch::BLT;
491 case LoongArch::BLTU:
492 return LoongArch::BGEU;
493 case LoongArch::BGEU:
494 return LoongArch::BLTU;
495 }
496}
497
498bool LoongArchInstrInfo::reverseBranchCondition(
499 SmallVectorImpl<MachineOperand> &Cond) const {
500 assert((Cond.size() && Cond.size() <= 3) && "Invalid branch condition!");
501 Cond[0].setImm(getOppositeBranchOpc(Opc: Cond[0].getImm()));
502 return false;
503}
504
505std::pair<unsigned, unsigned>
506LoongArchInstrInfo::decomposeMachineOperandsTargetFlags(unsigned TF) const {
507 return std::make_pair(x&: TF, y: 0u);
508}
509
510ArrayRef<std::pair<unsigned, const char *>>
511LoongArchInstrInfo::getSerializableDirectMachineOperandTargetFlags() const {
512 using namespace LoongArchII;
513 // TODO: Add more target flags.
514 static const std::pair<unsigned, const char *> TargetFlags[] = {
515 {MO_CALL, "loongarch-call"},
516 {MO_CALL_PLT, "loongarch-call-plt"},
517 {MO_PCREL_HI, "loongarch-pcrel-hi"},
518 {MO_PCREL_LO, "loongarch-pcrel-lo"},
519 {MO_PCREL64_LO, "loongarch-pcrel64-lo"},
520 {MO_PCREL64_HI, "loongarch-pcrel64-hi"},
521 {MO_GOT_PC_HI, "loongarch-got-pc-hi"},
522 {MO_GOT_PC_LO, "loongarch-got-pc-lo"},
523 {MO_GOT_PC64_LO, "loongarch-got-pc64-lo"},
524 {MO_GOT_PC64_HI, "loongarch-got-pc64-hi"},
525 {MO_LE_HI, "loongarch-le-hi"},
526 {MO_LE_LO, "loongarch-le-lo"},
527 {MO_LE64_LO, "loongarch-le64-lo"},
528 {MO_LE64_HI, "loongarch-le64-hi"},
529 {MO_IE_PC_HI, "loongarch-ie-pc-hi"},
530 {MO_IE_PC_LO, "loongarch-ie-pc-lo"},
531 {MO_IE_PC64_LO, "loongarch-ie-pc64-lo"},
532 {MO_IE_PC64_HI, "loongarch-ie-pc64-hi"},
533 {MO_LD_PC_HI, "loongarch-ld-pc-hi"},
534 {MO_GD_PC_HI, "loongarch-gd-pc-hi"}};
535 return ArrayRef(TargetFlags);
536}
537

source code of llvm/lib/Target/LoongArch/LoongArchInstrInfo.cpp