[llvm-shlib] Fix the version naming style of libLLVM for Windows (#85710)
[llvm-project.git] / llvm / lib / Target / LoongArch / LoongArchExpandPseudoInsts.cpp
blobad39658f698e7b8ede8ed3297eec204c8c9f9b09
1 //===-- LoongArchExpandPseudoInsts.cpp - Expand pseudo instructions -------===//
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 a pass that expands pseudo instructions into target
10 // instructions.
12 //===----------------------------------------------------------------------===//
14 #include "LoongArch.h"
15 #include "LoongArchInstrInfo.h"
16 #include "LoongArchTargetMachine.h"
17 #include "MCTargetDesc/LoongArchBaseInfo.h"
18 #include "MCTargetDesc/LoongArchMCTargetDesc.h"
19 #include "llvm/CodeGen/LivePhysRegs.h"
20 #include "llvm/CodeGen/MachineFunctionPass.h"
21 #include "llvm/CodeGen/MachineInstrBuilder.h"
22 #include "llvm/CodeGen/MachineOperand.h"
23 #include "llvm/CodeGen/Register.h"
24 #include "llvm/MC/MCContext.h"
25 #include "llvm/Support/CodeGen.h"
26 #include "llvm/Support/ErrorHandling.h"
28 using namespace llvm;
30 #define LOONGARCH_PRERA_EXPAND_PSEUDO_NAME \
31 "LoongArch Pre-RA pseudo instruction expansion pass"
32 #define LOONGARCH_EXPAND_PSEUDO_NAME \
33 "LoongArch pseudo instruction expansion pass"
35 namespace {
37 class LoongArchPreRAExpandPseudo : public MachineFunctionPass {
38 public:
39 const LoongArchInstrInfo *TII;
40 static char ID;
42 LoongArchPreRAExpandPseudo() : MachineFunctionPass(ID) {
43 initializeLoongArchPreRAExpandPseudoPass(*PassRegistry::getPassRegistry());
46 bool runOnMachineFunction(MachineFunction &MF) override;
48 void getAnalysisUsage(AnalysisUsage &AU) const override {
49 AU.setPreservesCFG();
50 MachineFunctionPass::getAnalysisUsage(AU);
52 StringRef getPassName() const override {
53 return LOONGARCH_PRERA_EXPAND_PSEUDO_NAME;
56 private:
57 bool expandMBB(MachineBasicBlock &MBB);
58 bool expandMI(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
59 MachineBasicBlock::iterator &NextMBBI);
60 bool expandPcalau12iInstPair(MachineBasicBlock &MBB,
61 MachineBasicBlock::iterator MBBI,
62 MachineBasicBlock::iterator &NextMBBI,
63 unsigned FlagsHi, unsigned SecondOpcode,
64 unsigned FlagsLo);
65 bool expandLoadAddressPcrel(MachineBasicBlock &MBB,
66 MachineBasicBlock::iterator MBBI,
67 MachineBasicBlock::iterator &NextMBBI);
68 bool expandLoadAddressGot(MachineBasicBlock &MBB,
69 MachineBasicBlock::iterator MBBI,
70 MachineBasicBlock::iterator &NextMBBI);
71 bool expandLoadAddressTLSLE(MachineBasicBlock &MBB,
72 MachineBasicBlock::iterator MBBI,
73 MachineBasicBlock::iterator &NextMBBI);
74 bool expandLoadAddressTLSIE(MachineBasicBlock &MBB,
75 MachineBasicBlock::iterator MBBI,
76 MachineBasicBlock::iterator &NextMBBI);
77 bool expandLoadAddressTLSLD(MachineBasicBlock &MBB,
78 MachineBasicBlock::iterator MBBI,
79 MachineBasicBlock::iterator &NextMBBI);
80 bool expandLoadAddressTLSGD(MachineBasicBlock &MBB,
81 MachineBasicBlock::iterator MBBI,
82 MachineBasicBlock::iterator &NextMBBI);
85 char LoongArchPreRAExpandPseudo::ID = 0;
87 bool LoongArchPreRAExpandPseudo::runOnMachineFunction(MachineFunction &MF) {
88 TII =
89 static_cast<const LoongArchInstrInfo *>(MF.getSubtarget().getInstrInfo());
90 bool Modified = false;
91 for (auto &MBB : MF)
92 Modified |= expandMBB(MBB);
93 return Modified;
96 bool LoongArchPreRAExpandPseudo::expandMBB(MachineBasicBlock &MBB) {
97 bool Modified = false;
99 MachineBasicBlock::iterator MBBI = MBB.begin(), E = MBB.end();
100 while (MBBI != E) {
101 MachineBasicBlock::iterator NMBBI = std::next(MBBI);
102 Modified |= expandMI(MBB, MBBI, NMBBI);
103 MBBI = NMBBI;
106 return Modified;
109 bool LoongArchPreRAExpandPseudo::expandMI(
110 MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
111 MachineBasicBlock::iterator &NextMBBI) {
112 switch (MBBI->getOpcode()) {
113 case LoongArch::PseudoLA_PCREL:
114 return expandLoadAddressPcrel(MBB, MBBI, NextMBBI);
115 case LoongArch::PseudoLA_GOT:
116 return expandLoadAddressGot(MBB, MBBI, NextMBBI);
117 case LoongArch::PseudoLA_TLS_LE:
118 return expandLoadAddressTLSLE(MBB, MBBI, NextMBBI);
119 case LoongArch::PseudoLA_TLS_IE:
120 return expandLoadAddressTLSIE(MBB, MBBI, NextMBBI);
121 case LoongArch::PseudoLA_TLS_LD:
122 return expandLoadAddressTLSLD(MBB, MBBI, NextMBBI);
123 case LoongArch::PseudoLA_TLS_GD:
124 return expandLoadAddressTLSGD(MBB, MBBI, NextMBBI);
126 return false;
129 bool LoongArchPreRAExpandPseudo::expandPcalau12iInstPair(
130 MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
131 MachineBasicBlock::iterator &NextMBBI, unsigned FlagsHi,
132 unsigned SecondOpcode, unsigned FlagsLo) {
133 MachineFunction *MF = MBB.getParent();
134 MachineInstr &MI = *MBBI;
135 DebugLoc DL = MI.getDebugLoc();
137 Register DestReg = MI.getOperand(0).getReg();
138 Register ScratchReg =
139 MF->getRegInfo().createVirtualRegister(&LoongArch::GPRRegClass);
140 MachineOperand &Symbol = MI.getOperand(1);
142 BuildMI(MBB, MBBI, DL, TII->get(LoongArch::PCALAU12I), ScratchReg)
143 .addDisp(Symbol, 0, FlagsHi);
145 MachineInstr *SecondMI =
146 BuildMI(MBB, MBBI, DL, TII->get(SecondOpcode), DestReg)
147 .addReg(ScratchReg)
148 .addDisp(Symbol, 0, FlagsLo);
150 if (MI.hasOneMemOperand())
151 SecondMI->addMemOperand(*MF, *MI.memoperands_begin());
153 MI.eraseFromParent();
154 return true;
157 bool LoongArchPreRAExpandPseudo::expandLoadAddressPcrel(
158 MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
159 MachineBasicBlock::iterator &NextMBBI) {
160 // Code Sequence:
161 // pcalau12i $rd, %pc_hi20(sym)
162 // addi.w/d $rd, $rd, %pc_lo12(sym)
163 MachineFunction *MF = MBB.getParent();
164 const auto &STI = MF->getSubtarget<LoongArchSubtarget>();
165 unsigned SecondOpcode = STI.is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W;
166 return expandPcalau12iInstPair(MBB, MBBI, NextMBBI, LoongArchII::MO_PCREL_HI,
167 SecondOpcode, LoongArchII::MO_PCREL_LO);
170 bool LoongArchPreRAExpandPseudo::expandLoadAddressGot(
171 MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
172 MachineBasicBlock::iterator &NextMBBI) {
173 // Code Sequence:
174 // pcalau12i $rd, %got_pc_hi20(sym)
175 // ld.w/d $rd, $rd, %got_pc_lo12(sym)
176 MachineFunction *MF = MBB.getParent();
177 const auto &STI = MF->getSubtarget<LoongArchSubtarget>();
178 unsigned SecondOpcode = STI.is64Bit() ? LoongArch::LD_D : LoongArch::LD_W;
179 return expandPcalau12iInstPair(MBB, MBBI, NextMBBI, LoongArchII::MO_GOT_PC_HI,
180 SecondOpcode, LoongArchII::MO_GOT_PC_LO);
183 bool LoongArchPreRAExpandPseudo::expandLoadAddressTLSLE(
184 MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
185 MachineBasicBlock::iterator &NextMBBI) {
186 // Code Sequence:
187 // lu12i.w $rd, %le_hi20(sym)
188 // ori $rd, $rd, %le_lo12(sym)
190 // And additionally if generating code using the large code model:
192 // lu32i.d $rd, %le64_lo20(sym)
193 // lu52i.d $rd, $rd, %le64_hi12(sym)
194 MachineFunction *MF = MBB.getParent();
195 MachineInstr &MI = *MBBI;
196 DebugLoc DL = MI.getDebugLoc();
198 bool Large = MF->getTarget().getCodeModel() == CodeModel::Large;
199 Register DestReg = MI.getOperand(0).getReg();
200 Register Parts01 =
201 Large ? MF->getRegInfo().createVirtualRegister(&LoongArch::GPRRegClass)
202 : DestReg;
203 Register Part1 =
204 MF->getRegInfo().createVirtualRegister(&LoongArch::GPRRegClass);
205 MachineOperand &Symbol = MI.getOperand(1);
207 BuildMI(MBB, MBBI, DL, TII->get(LoongArch::LU12I_W), Part1)
208 .addDisp(Symbol, 0, LoongArchII::MO_LE_HI);
210 BuildMI(MBB, MBBI, DL, TII->get(LoongArch::ORI), Parts01)
211 .addReg(Part1, RegState::Kill)
212 .addDisp(Symbol, 0, LoongArchII::MO_LE_LO);
214 if (Large) {
215 Register Parts012 =
216 MF->getRegInfo().createVirtualRegister(&LoongArch::GPRRegClass);
218 BuildMI(MBB, MBBI, DL, TII->get(LoongArch::LU32I_D), Parts012)
219 // "rj" is needed due to InstrInfo pattern requirement.
220 .addReg(Parts01, RegState::Kill)
221 .addDisp(Symbol, 0, LoongArchII::MO_LE64_LO);
222 BuildMI(MBB, MBBI, DL, TII->get(LoongArch::LU52I_D), DestReg)
223 .addReg(Parts012, RegState::Kill)
224 .addDisp(Symbol, 0, LoongArchII::MO_LE64_HI);
227 MI.eraseFromParent();
228 return true;
231 bool LoongArchPreRAExpandPseudo::expandLoadAddressTLSIE(
232 MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
233 MachineBasicBlock::iterator &NextMBBI) {
234 // Code Sequence:
235 // pcalau12i $rd, %ie_pc_hi20(sym)
236 // ld.w/d $rd, $rd, %ie_pc_lo12(sym)
237 MachineFunction *MF = MBB.getParent();
238 const auto &STI = MF->getSubtarget<LoongArchSubtarget>();
239 unsigned SecondOpcode = STI.is64Bit() ? LoongArch::LD_D : LoongArch::LD_W;
240 return expandPcalau12iInstPair(MBB, MBBI, NextMBBI, LoongArchII::MO_IE_PC_HI,
241 SecondOpcode, LoongArchII::MO_IE_PC_LO);
244 bool LoongArchPreRAExpandPseudo::expandLoadAddressTLSLD(
245 MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
246 MachineBasicBlock::iterator &NextMBBI) {
247 // Code Sequence:
248 // pcalau12i $rd, %ld_pc_hi20(sym)
249 // addi.w/d $rd, $rd, %got_pc_lo12(sym)
250 MachineFunction *MF = MBB.getParent();
251 const auto &STI = MF->getSubtarget<LoongArchSubtarget>();
252 unsigned SecondOpcode = STI.is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W;
253 return expandPcalau12iInstPair(MBB, MBBI, NextMBBI, LoongArchII::MO_LD_PC_HI,
254 SecondOpcode, LoongArchII::MO_GOT_PC_LO);
257 bool LoongArchPreRAExpandPseudo::expandLoadAddressTLSGD(
258 MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
259 MachineBasicBlock::iterator &NextMBBI) {
260 // Code Sequence:
261 // pcalau12i $rd, %gd_pc_hi20(sym)
262 // addi.w/d $rd, $rd, %got_pc_lo12(sym)
263 MachineFunction *MF = MBB.getParent();
264 const auto &STI = MF->getSubtarget<LoongArchSubtarget>();
265 unsigned SecondOpcode = STI.is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W;
266 return expandPcalau12iInstPair(MBB, MBBI, NextMBBI, LoongArchII::MO_GD_PC_HI,
267 SecondOpcode, LoongArchII::MO_GOT_PC_LO);
270 class LoongArchExpandPseudo : public MachineFunctionPass {
271 public:
272 const LoongArchInstrInfo *TII;
273 static char ID;
275 LoongArchExpandPseudo() : MachineFunctionPass(ID) {
276 initializeLoongArchExpandPseudoPass(*PassRegistry::getPassRegistry());
279 bool runOnMachineFunction(MachineFunction &MF) override;
281 StringRef getPassName() const override {
282 return LOONGARCH_EXPAND_PSEUDO_NAME;
285 private:
286 bool expandMBB(MachineBasicBlock &MBB);
287 bool expandMI(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
288 MachineBasicBlock::iterator &NextMBBI);
289 bool expandCopyCFR(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
290 MachineBasicBlock::iterator &NextMBBI);
291 bool expandLargeAddressLoad(MachineBasicBlock &MBB,
292 MachineBasicBlock::iterator MBBI,
293 MachineBasicBlock::iterator &NextMBBI,
294 unsigned LastOpcode, unsigned IdentifyingMO);
295 bool expandLargeAddressLoad(MachineBasicBlock &MBB,
296 MachineBasicBlock::iterator MBBI,
297 MachineBasicBlock::iterator &NextMBBI,
298 unsigned LastOpcode, unsigned IdentifyingMO,
299 const MachineOperand &Symbol, Register DestReg,
300 bool EraseFromParent);
301 bool expandLoadAddressPcrelLarge(MachineBasicBlock &MBB,
302 MachineBasicBlock::iterator MBBI,
303 MachineBasicBlock::iterator &NextMBBI);
304 bool expandLoadAddressGotLarge(MachineBasicBlock &MBB,
305 MachineBasicBlock::iterator MBBI,
306 MachineBasicBlock::iterator &NextMBBI);
307 bool expandLoadAddressTLSIELarge(MachineBasicBlock &MBB,
308 MachineBasicBlock::iterator MBBI,
309 MachineBasicBlock::iterator &NextMBBI);
310 bool expandLoadAddressTLSLDLarge(MachineBasicBlock &MBB,
311 MachineBasicBlock::iterator MBBI,
312 MachineBasicBlock::iterator &NextMBBI);
313 bool expandLoadAddressTLSGDLarge(MachineBasicBlock &MBB,
314 MachineBasicBlock::iterator MBBI,
315 MachineBasicBlock::iterator &NextMBBI);
316 bool expandFunctionCALL(MachineBasicBlock &MBB,
317 MachineBasicBlock::iterator MBBI,
318 MachineBasicBlock::iterator &NextMBBI,
319 bool IsTailCall);
322 char LoongArchExpandPseudo::ID = 0;
324 bool LoongArchExpandPseudo::runOnMachineFunction(MachineFunction &MF) {
325 TII =
326 static_cast<const LoongArchInstrInfo *>(MF.getSubtarget().getInstrInfo());
328 bool Modified = false;
329 for (auto &MBB : MF)
330 Modified |= expandMBB(MBB);
332 return Modified;
335 bool LoongArchExpandPseudo::expandMBB(MachineBasicBlock &MBB) {
336 bool Modified = false;
338 MachineBasicBlock::iterator MBBI = MBB.begin(), E = MBB.end();
339 while (MBBI != E) {
340 MachineBasicBlock::iterator NMBBI = std::next(MBBI);
341 Modified |= expandMI(MBB, MBBI, NMBBI);
342 MBBI = NMBBI;
345 return Modified;
348 bool LoongArchExpandPseudo::expandMI(MachineBasicBlock &MBB,
349 MachineBasicBlock::iterator MBBI,
350 MachineBasicBlock::iterator &NextMBBI) {
351 switch (MBBI->getOpcode()) {
352 case LoongArch::PseudoCopyCFR:
353 return expandCopyCFR(MBB, MBBI, NextMBBI);
354 case LoongArch::PseudoLA_PCREL_LARGE:
355 return expandLoadAddressPcrelLarge(MBB, MBBI, NextMBBI);
356 case LoongArch::PseudoLA_GOT_LARGE:
357 return expandLoadAddressGotLarge(MBB, MBBI, NextMBBI);
358 case LoongArch::PseudoLA_TLS_IE_LARGE:
359 return expandLoadAddressTLSIELarge(MBB, MBBI, NextMBBI);
360 case LoongArch::PseudoLA_TLS_LD_LARGE:
361 return expandLoadAddressTLSLDLarge(MBB, MBBI, NextMBBI);
362 case LoongArch::PseudoLA_TLS_GD_LARGE:
363 return expandLoadAddressTLSGDLarge(MBB, MBBI, NextMBBI);
364 case LoongArch::PseudoCALL:
365 case LoongArch::PseudoCALL_MEDIUM:
366 case LoongArch::PseudoCALL_LARGE:
367 return expandFunctionCALL(MBB, MBBI, NextMBBI, /*IsTailCall=*/false);
368 case LoongArch::PseudoTAIL:
369 case LoongArch::PseudoTAIL_MEDIUM:
370 case LoongArch::PseudoTAIL_LARGE:
371 return expandFunctionCALL(MBB, MBBI, NextMBBI, /*IsTailCall=*/true);
374 return false;
377 bool LoongArchExpandPseudo::expandCopyCFR(
378 MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
379 MachineBasicBlock::iterator &NextMBBI) {
380 MachineFunction *MF = MBB.getParent();
381 MachineInstr &MI = *MBBI;
382 DebugLoc DL = MI.getDebugLoc();
384 // Expand:
385 // MBB:
386 // fcmp.caf.s $dst, $fa0, $fa0 # set $dst 0(false)
387 // bceqz $src, SinkBB
388 // FalseBB:
389 // fcmp.cueq.s $dst, $fa0, $fa0 # set $dst 1(true)
390 // SinkBB:
391 // fallthrough
393 const BasicBlock *LLVM_BB = MBB.getBasicBlock();
394 auto *FalseBB = MF->CreateMachineBasicBlock(LLVM_BB);
395 auto *SinkBB = MF->CreateMachineBasicBlock(LLVM_BB);
397 MF->insert(++MBB.getIterator(), FalseBB);
398 MF->insert(++FalseBB->getIterator(), SinkBB);
400 Register DestReg = MI.getOperand(0).getReg();
401 Register SrcReg = MI.getOperand(1).getReg();
402 // DestReg = 0
403 BuildMI(MBB, MBBI, DL, TII->get(LoongArch::SET_CFR_FALSE), DestReg);
404 // Insert branch instruction.
405 BuildMI(MBB, MBBI, DL, TII->get(LoongArch::BCEQZ))
406 .addReg(SrcReg)
407 .addMBB(SinkBB);
408 // DestReg = 1
409 BuildMI(FalseBB, DL, TII->get(LoongArch::SET_CFR_TRUE), DestReg);
411 FalseBB->addSuccessor(SinkBB);
413 SinkBB->splice(SinkBB->end(), &MBB, MI, MBB.end());
414 SinkBB->transferSuccessors(&MBB);
416 MBB.addSuccessor(FalseBB);
417 MBB.addSuccessor(SinkBB);
419 NextMBBI = MBB.end();
420 MI.eraseFromParent();
422 // Make sure live-ins are correctly attached to this new basic block.
423 LivePhysRegs LiveRegs;
424 computeAndAddLiveIns(LiveRegs, *FalseBB);
425 computeAndAddLiveIns(LiveRegs, *SinkBB);
427 return true;
430 bool LoongArchExpandPseudo::expandLargeAddressLoad(
431 MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
432 MachineBasicBlock::iterator &NextMBBI, unsigned LastOpcode,
433 unsigned IdentifyingMO) {
434 MachineInstr &MI = *MBBI;
435 return expandLargeAddressLoad(MBB, MBBI, NextMBBI, LastOpcode, IdentifyingMO,
436 MI.getOperand(2), MI.getOperand(0).getReg(),
437 true);
440 bool LoongArchExpandPseudo::expandLargeAddressLoad(
441 MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
442 MachineBasicBlock::iterator &NextMBBI, unsigned LastOpcode,
443 unsigned IdentifyingMO, const MachineOperand &Symbol, Register DestReg,
444 bool EraseFromParent) {
445 // Code Sequence:
447 // Part1: pcalau12i $dst, %MO1(sym)
448 // Part0: addi.d $t8, $zero, %MO0(sym)
449 // Part2: lu32i.d $t8, %MO2(sym)
450 // Part3: lu52i.d $t8, $t8, %MO3(sym)
451 // Fin: LastOpcode $dst, $t8, $dst
453 unsigned MO0, MO1, MO2, MO3;
454 switch (IdentifyingMO) {
455 default:
456 llvm_unreachable("unsupported identifying MO");
457 case LoongArchII::MO_PCREL_LO:
458 MO0 = IdentifyingMO;
459 MO1 = LoongArchII::MO_PCREL_HI;
460 MO2 = LoongArchII::MO_PCREL64_LO;
461 MO3 = LoongArchII::MO_PCREL64_HI;
462 break;
463 case LoongArchII::MO_GOT_PC_HI:
464 case LoongArchII::MO_LD_PC_HI:
465 case LoongArchII::MO_GD_PC_HI:
466 // These cases relocate just like the GOT case, except for Part1.
467 MO0 = LoongArchII::MO_GOT_PC_LO;
468 MO1 = IdentifyingMO;
469 MO2 = LoongArchII::MO_GOT_PC64_LO;
470 MO3 = LoongArchII::MO_GOT_PC64_HI;
471 break;
472 case LoongArchII::MO_IE_PC_LO:
473 MO0 = IdentifyingMO;
474 MO1 = LoongArchII::MO_IE_PC_HI;
475 MO2 = LoongArchII::MO_IE_PC64_LO;
476 MO3 = LoongArchII::MO_IE_PC64_HI;
477 break;
480 MachineInstr &MI = *MBBI;
481 DebugLoc DL = MI.getDebugLoc();
482 Register ScratchReg = LoongArch::R20; // $t8
484 assert(MBB.getParent()->getSubtarget<LoongArchSubtarget>().is64Bit() &&
485 "Large code model requires LA64");
487 auto Part1 = BuildMI(MBB, MBBI, DL, TII->get(LoongArch::PCALAU12I), DestReg);
488 auto Part0 = BuildMI(MBB, MBBI, DL, TII->get(LoongArch::ADDI_D), ScratchReg)
489 .addReg(LoongArch::R0);
490 auto Part2 = BuildMI(MBB, MBBI, DL, TII->get(LoongArch::LU32I_D), ScratchReg)
491 // "rj" is needed due to InstrInfo pattern requirement.
492 .addReg(ScratchReg);
493 auto Part3 = BuildMI(MBB, MBBI, DL, TII->get(LoongArch::LU52I_D), ScratchReg)
494 .addReg(ScratchReg);
495 BuildMI(MBB, MBBI, DL, TII->get(LastOpcode), DestReg)
496 .addReg(ScratchReg)
497 .addReg(DestReg);
499 if (Symbol.getType() == MachineOperand::MO_ExternalSymbol) {
500 const char *SymName = Symbol.getSymbolName();
501 Part0.addExternalSymbol(SymName, MO0);
502 Part1.addExternalSymbol(SymName, MO1);
503 Part2.addExternalSymbol(SymName, MO2);
504 Part3.addExternalSymbol(SymName, MO3);
505 } else {
506 Part0.addDisp(Symbol, 0, MO0);
507 Part1.addDisp(Symbol, 0, MO1);
508 Part2.addDisp(Symbol, 0, MO2);
509 Part3.addDisp(Symbol, 0, MO3);
512 if (EraseFromParent)
513 MI.eraseFromParent();
515 return true;
518 bool LoongArchExpandPseudo::expandLoadAddressPcrelLarge(
519 MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
520 MachineBasicBlock::iterator &NextMBBI) {
521 // Emit the 5-insn large address load sequence with the `%pc` family of
522 // relocs.
523 return expandLargeAddressLoad(MBB, MBBI, NextMBBI, LoongArch::ADD_D,
524 LoongArchII::MO_PCREL_LO);
527 bool LoongArchExpandPseudo::expandLoadAddressGotLarge(
528 MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
529 MachineBasicBlock::iterator &NextMBBI) {
530 // Emit the 5-insn large address load sequence with the `%got_pc` family
531 // of relocs, loading the result from GOT with `ldx.d` in the end.
532 return expandLargeAddressLoad(MBB, MBBI, NextMBBI, LoongArch::LDX_D,
533 LoongArchII::MO_GOT_PC_HI);
536 bool LoongArchExpandPseudo::expandLoadAddressTLSIELarge(
537 MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
538 MachineBasicBlock::iterator &NextMBBI) {
539 // Emit the 5-insn large address load sequence with the `%ie_pc` family
540 // of relocs, loading the result with `ldx.d` in the end.
541 return expandLargeAddressLoad(MBB, MBBI, NextMBBI, LoongArch::LDX_D,
542 LoongArchII::MO_IE_PC_LO);
545 bool LoongArchExpandPseudo::expandLoadAddressTLSLDLarge(
546 MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
547 MachineBasicBlock::iterator &NextMBBI) {
548 // Emit the 5-insn large address load sequence with the `%got_pc` family
549 // of relocs, with the `pcalau12i` insn relocated with `%ld_pc_hi20`.
550 return expandLargeAddressLoad(MBB, MBBI, NextMBBI, LoongArch::ADD_D,
551 LoongArchII::MO_LD_PC_HI);
554 bool LoongArchExpandPseudo::expandLoadAddressTLSGDLarge(
555 MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
556 MachineBasicBlock::iterator &NextMBBI) {
557 // Emit the 5-insn large address load sequence with the `%got_pc` family
558 // of relocs, with the `pcalau12i` insn relocated with `%gd_pc_hi20`.
559 return expandLargeAddressLoad(MBB, MBBI, NextMBBI, LoongArch::ADD_D,
560 LoongArchII::MO_GD_PC_HI);
563 bool LoongArchExpandPseudo::expandFunctionCALL(
564 MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
565 MachineBasicBlock::iterator &NextMBBI, bool IsTailCall) {
566 MachineFunction *MF = MBB.getParent();
567 MachineInstr &MI = *MBBI;
568 DebugLoc DL = MI.getDebugLoc();
569 const MachineOperand &Func = MI.getOperand(0);
570 MachineInstrBuilder CALL;
571 unsigned Opcode;
573 switch (MF->getTarget().getCodeModel()) {
574 default:
575 report_fatal_error("Unsupported code model");
576 break;
577 case CodeModel::Small: {
578 // CALL:
579 // bl func
580 // TAIL:
581 // b func
582 Opcode = IsTailCall ? LoongArch::PseudoB_TAIL : LoongArch::BL;
583 CALL = BuildMI(MBB, MBBI, DL, TII->get(Opcode)).add(Func);
584 break;
586 case CodeModel::Medium: {
587 // CALL:
588 // pcaddu18i $ra, %call36(func)
589 // jirl $ra, $ra, 0
590 // TAIL:
591 // pcaddu18i $t8, %call36(func)
592 // jr $t8
593 Opcode =
594 IsTailCall ? LoongArch::PseudoJIRL_TAIL : LoongArch::PseudoJIRL_CALL;
595 Register ScratchReg = IsTailCall ? LoongArch::R20 : LoongArch::R1;
596 MachineInstrBuilder MIB =
597 BuildMI(MBB, MBBI, DL, TII->get(LoongArch::PCADDU18I), ScratchReg);
599 CALL =
600 BuildMI(MBB, MBBI, DL, TII->get(Opcode)).addReg(ScratchReg).addImm(0);
602 if (Func.isSymbol())
603 MIB.addExternalSymbol(Func.getSymbolName(), LoongArchII::MO_CALL36);
604 else
605 MIB.addDisp(Func, 0, LoongArchII::MO_CALL36);
606 break;
608 case CodeModel::Large: {
609 // Emit the 5-insn large address load sequence, either directly or
610 // indirectly in case of going through the GOT, then JIRL_TAIL or
611 // JIRL_CALL to $addr.
612 Opcode =
613 IsTailCall ? LoongArch::PseudoJIRL_TAIL : LoongArch::PseudoJIRL_CALL;
614 Register AddrReg = IsTailCall ? LoongArch::R19 : LoongArch::R1;
616 bool UseGOT = Func.isGlobal() && !Func.getGlobal()->isDSOLocal();
617 unsigned MO = UseGOT ? LoongArchII::MO_GOT_PC_HI : LoongArchII::MO_PCREL_LO;
618 unsigned LAOpcode = UseGOT ? LoongArch::LDX_D : LoongArch::ADD_D;
619 expandLargeAddressLoad(MBB, MBBI, NextMBBI, LAOpcode, MO, Func, AddrReg,
620 false);
621 CALL = BuildMI(MBB, MBBI, DL, TII->get(Opcode)).addReg(AddrReg).addImm(0);
622 break;
626 // Transfer implicit operands.
627 CALL.copyImplicitOps(MI);
629 // Transfer MI flags.
630 CALL.setMIFlags(MI.getFlags());
632 MI.eraseFromParent();
633 return true;
636 } // end namespace
638 INITIALIZE_PASS(LoongArchPreRAExpandPseudo, "loongarch-prera-expand-pseudo",
639 LOONGARCH_PRERA_EXPAND_PSEUDO_NAME, false, false)
641 INITIALIZE_PASS(LoongArchExpandPseudo, "loongarch-expand-pseudo",
642 LOONGARCH_EXPAND_PSEUDO_NAME, false, false)
644 namespace llvm {
646 FunctionPass *createLoongArchPreRAExpandPseudoPass() {
647 return new LoongArchPreRAExpandPseudo();
649 FunctionPass *createLoongArchExpandPseudoPass() {
650 return new LoongArchExpandPseudo();
653 } // end namespace llvm