1 //===-- LoongArchExpandPseudoInsts.cpp - Expand pseudo instructions -------===//
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
7 //===----------------------------------------------------------------------===//
9 // This file contains a pass that expands pseudo instructions into target
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"
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"
37 class LoongArchPreRAExpandPseudo
: public MachineFunctionPass
{
39 const LoongArchInstrInfo
*TII
;
42 LoongArchPreRAExpandPseudo() : MachineFunctionPass(ID
) {
43 initializeLoongArchPreRAExpandPseudoPass(*PassRegistry::getPassRegistry());
46 bool runOnMachineFunction(MachineFunction
&MF
) override
;
48 void getAnalysisUsage(AnalysisUsage
&AU
) const override
{
50 MachineFunctionPass::getAnalysisUsage(AU
);
52 StringRef
getPassName() const override
{
53 return LOONGARCH_PRERA_EXPAND_PSEUDO_NAME
;
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
,
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
) {
89 static_cast<const LoongArchInstrInfo
*>(MF
.getSubtarget().getInstrInfo());
90 bool Modified
= false;
92 Modified
|= expandMBB(MBB
);
96 bool LoongArchPreRAExpandPseudo::expandMBB(MachineBasicBlock
&MBB
) {
97 bool Modified
= false;
99 MachineBasicBlock::iterator MBBI
= MBB
.begin(), E
= MBB
.end();
101 MachineBasicBlock::iterator NMBBI
= std::next(MBBI
);
102 Modified
|= expandMI(MBB
, MBBI
, NMBBI
);
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
);
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
)
148 .addDisp(Symbol
, 0, FlagsLo
);
150 if (MI
.hasOneMemOperand())
151 SecondMI
->addMemOperand(*MF
, *MI
.memoperands_begin());
153 MI
.eraseFromParent();
157 bool LoongArchPreRAExpandPseudo::expandLoadAddressPcrel(
158 MachineBasicBlock
&MBB
, MachineBasicBlock::iterator MBBI
,
159 MachineBasicBlock::iterator
&NextMBBI
) {
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
) {
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
) {
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();
201 Large
? MF
->getRegInfo().createVirtualRegister(&LoongArch::GPRRegClass
)
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
);
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();
231 bool LoongArchPreRAExpandPseudo::expandLoadAddressTLSIE(
232 MachineBasicBlock
&MBB
, MachineBasicBlock::iterator MBBI
,
233 MachineBasicBlock::iterator
&NextMBBI
) {
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
) {
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
) {
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
{
272 const LoongArchInstrInfo
*TII
;
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
;
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
,
322 char LoongArchExpandPseudo::ID
= 0;
324 bool LoongArchExpandPseudo::runOnMachineFunction(MachineFunction
&MF
) {
326 static_cast<const LoongArchInstrInfo
*>(MF
.getSubtarget().getInstrInfo());
328 bool Modified
= false;
330 Modified
|= expandMBB(MBB
);
335 bool LoongArchExpandPseudo::expandMBB(MachineBasicBlock
&MBB
) {
336 bool Modified
= false;
338 MachineBasicBlock::iterator MBBI
= MBB
.begin(), E
= MBB
.end();
340 MachineBasicBlock::iterator NMBBI
= std::next(MBBI
);
341 Modified
|= expandMI(MBB
, MBBI
, NMBBI
);
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);
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();
386 // fcmp.caf.s $dst, $fa0, $fa0 # set $dst 0(false)
387 // bceqz $src, SinkBB
389 // fcmp.cueq.s $dst, $fa0, $fa0 # set $dst 1(true)
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();
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
))
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
);
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(),
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
) {
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
) {
456 llvm_unreachable("unsupported identifying MO");
457 case LoongArchII::MO_PCREL_LO
:
459 MO1
= LoongArchII::MO_PCREL_HI
;
460 MO2
= LoongArchII::MO_PCREL64_LO
;
461 MO3
= LoongArchII::MO_PCREL64_HI
;
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
;
469 MO2
= LoongArchII::MO_GOT_PC64_LO
;
470 MO3
= LoongArchII::MO_GOT_PC64_HI
;
472 case LoongArchII::MO_IE_PC_LO
:
474 MO1
= LoongArchII::MO_IE_PC_HI
;
475 MO2
= LoongArchII::MO_IE_PC64_LO
;
476 MO3
= LoongArchII::MO_IE_PC64_HI
;
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.
493 auto Part3
= BuildMI(MBB
, MBBI
, DL
, TII
->get(LoongArch::LU52I_D
), ScratchReg
)
495 BuildMI(MBB
, MBBI
, DL
, TII
->get(LastOpcode
), 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
);
506 Part0
.addDisp(Symbol
, 0, MO0
);
507 Part1
.addDisp(Symbol
, 0, MO1
);
508 Part2
.addDisp(Symbol
, 0, MO2
);
509 Part3
.addDisp(Symbol
, 0, MO3
);
513 MI
.eraseFromParent();
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
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
;
573 switch (MF
->getTarget().getCodeModel()) {
575 report_fatal_error("Unsupported code model");
577 case CodeModel::Small
: {
582 Opcode
= IsTailCall
? LoongArch::PseudoB_TAIL
: LoongArch::BL
;
583 CALL
= BuildMI(MBB
, MBBI
, DL
, TII
->get(Opcode
)).add(Func
);
586 case CodeModel::Medium
: {
588 // pcaddu18i $ra, %call36(func)
591 // pcaddu18i $t8, %call36(func)
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
);
600 BuildMI(MBB
, MBBI
, DL
, TII
->get(Opcode
)).addReg(ScratchReg
).addImm(0);
603 MIB
.addExternalSymbol(Func
.getSymbolName(), LoongArchII::MO_CALL36
);
605 MIB
.addDisp(Func
, 0, LoongArchII::MO_CALL36
);
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.
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
,
621 CALL
= BuildMI(MBB
, MBBI
, DL
, TII
->get(Opcode
)).addReg(AddrReg
).addImm(0);
626 // Transfer implicit operands.
627 CALL
.copyImplicitOps(MI
);
629 // Transfer MI flags.
630 CALL
.setMIFlags(MI
.getFlags());
632 MI
.eraseFromParent();
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)
646 FunctionPass
*createLoongArchPreRAExpandPseudoPass() {
647 return new LoongArchPreRAExpandPseudo();
649 FunctionPass
*createLoongArchExpandPseudoPass() {
650 return new LoongArchExpandPseudo();
653 } // end namespace llvm