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 "LoongArchMachineFunctionInfo.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 extern cl::opt
<bool> LArchAnnotateTableJump
;
32 #define LOONGARCH_PRERA_EXPAND_PSEUDO_NAME \
33 "LoongArch Pre-RA pseudo instruction expansion pass"
34 #define LOONGARCH_EXPAND_PSEUDO_NAME \
35 "LoongArch pseudo instruction expansion pass"
39 class LoongArchPreRAExpandPseudo
: public MachineFunctionPass
{
41 const LoongArchInstrInfo
*TII
;
44 LoongArchPreRAExpandPseudo() : MachineFunctionPass(ID
) {
45 initializeLoongArchPreRAExpandPseudoPass(*PassRegistry::getPassRegistry());
48 bool runOnMachineFunction(MachineFunction
&MF
) override
;
50 void getAnalysisUsage(AnalysisUsage
&AU
) const override
{
52 MachineFunctionPass::getAnalysisUsage(AU
);
54 StringRef
getPassName() const override
{
55 return LOONGARCH_PRERA_EXPAND_PSEUDO_NAME
;
59 bool expandMBB(MachineBasicBlock
&MBB
);
60 bool expandMI(MachineBasicBlock
&MBB
, MachineBasicBlock::iterator MBBI
,
61 MachineBasicBlock::iterator
&NextMBBI
);
62 bool expandPcalau12iInstPair(MachineBasicBlock
&MBB
,
63 MachineBasicBlock::iterator MBBI
,
64 MachineBasicBlock::iterator
&NextMBBI
,
65 unsigned FlagsHi
, unsigned SecondOpcode
,
67 bool expandLargeAddressLoad(MachineBasicBlock
&MBB
,
68 MachineBasicBlock::iterator MBBI
,
69 MachineBasicBlock::iterator
&NextMBBI
,
70 unsigned LastOpcode
, unsigned IdentifyingMO
);
71 bool expandLargeAddressLoad(MachineBasicBlock
&MBB
,
72 MachineBasicBlock::iterator MBBI
,
73 MachineBasicBlock::iterator
&NextMBBI
,
74 unsigned LastOpcode
, unsigned IdentifyingMO
,
75 const MachineOperand
&Symbol
, Register DestReg
,
76 bool EraseFromParent
);
77 bool expandLoadAddressPcrel(MachineBasicBlock
&MBB
,
78 MachineBasicBlock::iterator MBBI
,
79 MachineBasicBlock::iterator
&NextMBBI
,
81 bool expandLoadAddressGot(MachineBasicBlock
&MBB
,
82 MachineBasicBlock::iterator MBBI
,
83 MachineBasicBlock::iterator
&NextMBBI
,
85 bool expandLoadAddressTLSLE(MachineBasicBlock
&MBB
,
86 MachineBasicBlock::iterator MBBI
,
87 MachineBasicBlock::iterator
&NextMBBI
);
88 bool expandLoadAddressTLSIE(MachineBasicBlock
&MBB
,
89 MachineBasicBlock::iterator MBBI
,
90 MachineBasicBlock::iterator
&NextMBBI
,
92 bool expandLoadAddressTLSLD(MachineBasicBlock
&MBB
,
93 MachineBasicBlock::iterator MBBI
,
94 MachineBasicBlock::iterator
&NextMBBI
,
96 bool expandLoadAddressTLSGD(MachineBasicBlock
&MBB
,
97 MachineBasicBlock::iterator MBBI
,
98 MachineBasicBlock::iterator
&NextMBBI
,
100 bool expandLoadAddressTLSDesc(MachineBasicBlock
&MBB
,
101 MachineBasicBlock::iterator MBBI
,
102 MachineBasicBlock::iterator
&NextMBBI
,
104 bool expandFunctionCALL(MachineBasicBlock
&MBB
,
105 MachineBasicBlock::iterator MBBI
,
106 MachineBasicBlock::iterator
&NextMBBI
,
108 void annotateTableJump(MachineBasicBlock
&MBB
,
109 MachineBasicBlock::iterator MBBI
);
112 char LoongArchPreRAExpandPseudo::ID
= 0;
114 bool LoongArchPreRAExpandPseudo::runOnMachineFunction(MachineFunction
&MF
) {
116 static_cast<const LoongArchInstrInfo
*>(MF
.getSubtarget().getInstrInfo());
117 bool Modified
= false;
119 Modified
|= expandMBB(MBB
);
123 bool LoongArchPreRAExpandPseudo::expandMBB(MachineBasicBlock
&MBB
) {
124 bool Modified
= false;
126 MachineBasicBlock::iterator MBBI
= MBB
.begin(), E
= MBB
.end();
128 MachineBasicBlock::iterator NMBBI
= std::next(MBBI
);
129 Modified
|= expandMI(MBB
, MBBI
, NMBBI
);
136 bool LoongArchPreRAExpandPseudo::expandMI(
137 MachineBasicBlock
&MBB
, MachineBasicBlock::iterator MBBI
,
138 MachineBasicBlock::iterator
&NextMBBI
) {
139 switch (MBBI
->getOpcode()) {
140 case LoongArch::PseudoLA_PCREL
:
141 return expandLoadAddressPcrel(MBB
, MBBI
, NextMBBI
);
142 case LoongArch::PseudoLA_PCREL_LARGE
:
143 return expandLoadAddressPcrel(MBB
, MBBI
, NextMBBI
, /*Large=*/true);
144 case LoongArch::PseudoLA_GOT
:
145 return expandLoadAddressGot(MBB
, MBBI
, NextMBBI
);
146 case LoongArch::PseudoLA_GOT_LARGE
:
147 return expandLoadAddressGot(MBB
, MBBI
, NextMBBI
, /*Large=*/true);
148 case LoongArch::PseudoLA_TLS_LE
:
149 return expandLoadAddressTLSLE(MBB
, MBBI
, NextMBBI
);
150 case LoongArch::PseudoLA_TLS_IE
:
151 return expandLoadAddressTLSIE(MBB
, MBBI
, NextMBBI
);
152 case LoongArch::PseudoLA_TLS_IE_LARGE
:
153 return expandLoadAddressTLSIE(MBB
, MBBI
, NextMBBI
, /*Large=*/true);
154 case LoongArch::PseudoLA_TLS_LD
:
155 return expandLoadAddressTLSLD(MBB
, MBBI
, NextMBBI
);
156 case LoongArch::PseudoLA_TLS_LD_LARGE
:
157 return expandLoadAddressTLSLD(MBB
, MBBI
, NextMBBI
, /*Large=*/true);
158 case LoongArch::PseudoLA_TLS_GD
:
159 return expandLoadAddressTLSGD(MBB
, MBBI
, NextMBBI
);
160 case LoongArch::PseudoLA_TLS_GD_LARGE
:
161 return expandLoadAddressTLSGD(MBB
, MBBI
, NextMBBI
, /*Large=*/true);
162 case LoongArch::PseudoLA_TLS_DESC
:
163 return expandLoadAddressTLSDesc(MBB
, MBBI
, NextMBBI
);
164 case LoongArch::PseudoLA_TLS_DESC_LARGE
:
165 return expandLoadAddressTLSDesc(MBB
, MBBI
, NextMBBI
, /*Large=*/true);
166 case LoongArch::PseudoCALL
:
167 case LoongArch::PseudoCALL_LARGE
:
168 return expandFunctionCALL(MBB
, MBBI
, NextMBBI
, /*IsTailCall=*/false);
169 case LoongArch::PseudoTAIL
:
170 case LoongArch::PseudoTAIL_LARGE
:
171 return expandFunctionCALL(MBB
, MBBI
, NextMBBI
, /*IsTailCall=*/true);
172 case LoongArch::PseudoBRIND
:
173 // If the PseudoBRIND is used to table jump, then emit a label to annotate
174 // the `jr` instruction, and save the instructions.
175 if (LArchAnnotateTableJump
)
176 annotateTableJump(MBB
, MBBI
);
182 bool LoongArchPreRAExpandPseudo::expandPcalau12iInstPair(
183 MachineBasicBlock
&MBB
, MachineBasicBlock::iterator MBBI
,
184 MachineBasicBlock::iterator
&NextMBBI
, unsigned FlagsHi
,
185 unsigned SecondOpcode
, unsigned FlagsLo
) {
186 MachineFunction
*MF
= MBB
.getParent();
187 MachineInstr
&MI
= *MBBI
;
188 DebugLoc DL
= MI
.getDebugLoc();
190 Register DestReg
= MI
.getOperand(0).getReg();
191 Register ScratchReg
=
192 MF
->getRegInfo().createVirtualRegister(&LoongArch::GPRRegClass
);
193 MachineOperand
&Symbol
= MI
.getOperand(1);
195 BuildMI(MBB
, MBBI
, DL
, TII
->get(LoongArch::PCALAU12I
), ScratchReg
)
196 .addDisp(Symbol
, 0, FlagsHi
);
198 MachineInstr
*SecondMI
=
199 BuildMI(MBB
, MBBI
, DL
, TII
->get(SecondOpcode
), DestReg
)
201 .addDisp(Symbol
, 0, FlagsLo
);
203 if (MI
.hasOneMemOperand())
204 SecondMI
->addMemOperand(*MF
, *MI
.memoperands_begin());
206 MI
.eraseFromParent();
210 bool LoongArchPreRAExpandPseudo::expandLargeAddressLoad(
211 MachineBasicBlock
&MBB
, MachineBasicBlock::iterator MBBI
,
212 MachineBasicBlock::iterator
&NextMBBI
, unsigned LastOpcode
,
213 unsigned IdentifyingMO
) {
214 MachineInstr
&MI
= *MBBI
;
215 return expandLargeAddressLoad(MBB
, MBBI
, NextMBBI
, LastOpcode
, IdentifyingMO
,
216 MI
.getOperand(2), MI
.getOperand(0).getReg(),
220 bool LoongArchPreRAExpandPseudo::expandLargeAddressLoad(
221 MachineBasicBlock
&MBB
, MachineBasicBlock::iterator MBBI
,
222 MachineBasicBlock::iterator
&NextMBBI
, unsigned LastOpcode
,
223 unsigned IdentifyingMO
, const MachineOperand
&Symbol
, Register DestReg
,
224 bool EraseFromParent
) {
227 // Part1: pcalau12i $scratch, %MO1(sym)
228 // Part0: addi.d $dest, $zero, %MO0(sym)
229 // Part2: lu32i.d $dest, %MO2(sym)
230 // Part3: lu52i.d $dest, $dest, %MO3(sym)
231 // Fin: LastOpcode $dest, $dest, $scratch
233 unsigned MO0
, MO1
, MO2
, MO3
;
234 switch (IdentifyingMO
) {
236 llvm_unreachable("unsupported identifying MO");
237 case LoongArchII::MO_PCREL_LO
:
239 MO1
= LoongArchII::MO_PCREL_HI
;
240 MO2
= LoongArchII::MO_PCREL64_LO
;
241 MO3
= LoongArchII::MO_PCREL64_HI
;
243 case LoongArchII::MO_GOT_PC_HI
:
244 case LoongArchII::MO_LD_PC_HI
:
245 case LoongArchII::MO_GD_PC_HI
:
246 // These cases relocate just like the GOT case, except for Part1.
247 MO0
= LoongArchII::MO_GOT_PC_LO
;
249 MO2
= LoongArchII::MO_GOT_PC64_LO
;
250 MO3
= LoongArchII::MO_GOT_PC64_HI
;
252 case LoongArchII::MO_IE_PC_LO
:
254 MO1
= LoongArchII::MO_IE_PC_HI
;
255 MO2
= LoongArchII::MO_IE_PC64_LO
;
256 MO3
= LoongArchII::MO_IE_PC64_HI
;
260 MachineFunction
*MF
= MBB
.getParent();
261 MachineInstr
&MI
= *MBBI
;
262 DebugLoc DL
= MI
.getDebugLoc();
264 assert(MF
->getSubtarget
<LoongArchSubtarget
>().is64Bit() &&
265 "Large code model requires LA64");
268 MF
->getRegInfo().createVirtualRegister(&LoongArch::GPRRegClass
);
271 ? MF
->getRegInfo().createVirtualRegister(&LoongArch::GPRRegClass
)
273 Register TmpParts02
=
275 ? MF
->getRegInfo().createVirtualRegister(&LoongArch::GPRRegClass
)
277 Register TmpParts023
=
279 ? MF
->getRegInfo().createVirtualRegister(&LoongArch::GPRRegClass
)
282 auto Part1
= BuildMI(MBB
, MBBI
, DL
, TII
->get(LoongArch::PCALAU12I
), TmpPart1
);
283 auto Part0
= BuildMI(MBB
, MBBI
, DL
, TII
->get(LoongArch::ADDI_D
), TmpPart0
)
284 .addReg(LoongArch::R0
);
285 auto Part2
= BuildMI(MBB
, MBBI
, DL
, TII
->get(LoongArch::LU32I_D
), TmpParts02
)
286 // "rj" is needed due to InstrInfo pattern requirement.
287 .addReg(TmpPart0
, RegState::Kill
);
288 auto Part3
= BuildMI(MBB
, MBBI
, DL
, TII
->get(LoongArch::LU52I_D
), TmpParts023
)
289 .addReg(TmpParts02
, RegState::Kill
);
290 BuildMI(MBB
, MBBI
, DL
, TII
->get(LastOpcode
), DestReg
)
292 .addReg(TmpPart1
, RegState::Kill
);
294 if (Symbol
.getType() == MachineOperand::MO_ExternalSymbol
) {
295 const char *SymName
= Symbol
.getSymbolName();
296 Part0
.addExternalSymbol(SymName
, MO0
);
297 Part1
.addExternalSymbol(SymName
, MO1
);
298 Part2
.addExternalSymbol(SymName
, MO2
);
299 Part3
.addExternalSymbol(SymName
, MO3
);
301 Part0
.addDisp(Symbol
, 0, MO0
);
302 Part1
.addDisp(Symbol
, 0, MO1
);
303 Part2
.addDisp(Symbol
, 0, MO2
);
304 Part3
.addDisp(Symbol
, 0, MO3
);
308 MI
.eraseFromParent();
313 bool LoongArchPreRAExpandPseudo::expandLoadAddressPcrel(
314 MachineBasicBlock
&MBB
, MachineBasicBlock::iterator MBBI
,
315 MachineBasicBlock::iterator
&NextMBBI
, bool Large
) {
317 // Emit the 5-insn large address load sequence with the `%pc` family of
319 return expandLargeAddressLoad(MBB
, MBBI
, NextMBBI
, LoongArch::ADD_D
,
320 LoongArchII::MO_PCREL_LO
);
323 // pcalau12i $rd, %pc_hi20(sym)
324 // addi.w/d $rd, $rd, %pc_lo12(sym)
325 MachineFunction
*MF
= MBB
.getParent();
326 const auto &STI
= MF
->getSubtarget
<LoongArchSubtarget
>();
327 unsigned SecondOpcode
= STI
.is64Bit() ? LoongArch::ADDI_D
: LoongArch::ADDI_W
;
328 return expandPcalau12iInstPair(MBB
, MBBI
, NextMBBI
, LoongArchII::MO_PCREL_HI
,
329 SecondOpcode
, LoongArchII::MO_PCREL_LO
);
332 bool LoongArchPreRAExpandPseudo::expandLoadAddressGot(
333 MachineBasicBlock
&MBB
, MachineBasicBlock::iterator MBBI
,
334 MachineBasicBlock::iterator
&NextMBBI
, bool Large
) {
336 // Emit the 5-insn large address load sequence with the `%got_pc` family
337 // of relocs, loading the result from GOT with `ldx.d` in the end.
338 return expandLargeAddressLoad(MBB
, MBBI
, NextMBBI
, LoongArch::LDX_D
,
339 LoongArchII::MO_GOT_PC_HI
);
342 // pcalau12i $rd, %got_pc_hi20(sym)
343 // ld.w/d $rd, $rd, %got_pc_lo12(sym)
344 MachineFunction
*MF
= MBB
.getParent();
345 const auto &STI
= MF
->getSubtarget
<LoongArchSubtarget
>();
346 unsigned SecondOpcode
= STI
.is64Bit() ? LoongArch::LD_D
: LoongArch::LD_W
;
347 return expandPcalau12iInstPair(MBB
, MBBI
, NextMBBI
, LoongArchII::MO_GOT_PC_HI
,
348 SecondOpcode
, LoongArchII::MO_GOT_PC_LO
);
351 bool LoongArchPreRAExpandPseudo::expandLoadAddressTLSLE(
352 MachineBasicBlock
&MBB
, MachineBasicBlock::iterator MBBI
,
353 MachineBasicBlock::iterator
&NextMBBI
) {
355 // lu12i.w $rd, %le_hi20_r(sym)
356 // add.w/d $rd, $rd, $tp, %le_add_r(sym)
357 // addi.w/d $rd, $rd, %le_lo12_r(sym)
359 // Code Sequence while using the large code model:
360 // lu12i.w $rd, %le_hi20(sym)
361 // ori $rd, $rd, %le_lo12(sym)
362 // lu32i.d $rd, %le64_lo20(sym)
363 // lu52i.d $rd, $rd, %le64_hi12(sym)
364 MachineFunction
*MF
= MBB
.getParent();
365 MachineInstr
&MI
= *MBBI
;
366 DebugLoc DL
= MI
.getDebugLoc();
368 bool Large
= MF
->getTarget().getCodeModel() == CodeModel::Large
;
369 Register DestReg
= MI
.getOperand(0).getReg();
371 MF
->getRegInfo().createVirtualRegister(&LoongArch::GPRRegClass
);
373 MF
->getRegInfo().createVirtualRegister(&LoongArch::GPRRegClass
);
374 MachineOperand
&Symbol
= MI
.getOperand(1);
377 BuildMI(MBB
, MBBI
, DL
, TII
->get(LoongArch::LU12I_W
), Part1
)
378 .addDisp(Symbol
, 0, LoongArchII::MO_LE_HI_R
);
380 const auto &STI
= MF
->getSubtarget
<LoongArchSubtarget
>();
381 unsigned AddOp
= STI
.is64Bit() ? LoongArch::PseudoAddTPRel_D
382 : LoongArch::PseudoAddTPRel_W
;
383 BuildMI(MBB
, MBBI
, DL
, TII
->get(AddOp
), Parts01
)
384 .addReg(Part1
, RegState::Kill
)
385 .addReg(LoongArch::R2
)
386 .addDisp(Symbol
, 0, LoongArchII::MO_LE_ADD_R
);
388 unsigned AddiOp
= STI
.is64Bit() ? LoongArch::ADDI_D
: LoongArch::ADDI_W
;
389 BuildMI(MBB
, MBBI
, DL
, TII
->get(AddiOp
), DestReg
)
390 .addReg(Parts01
, RegState::Kill
)
391 .addDisp(Symbol
, 0, LoongArchII::MO_LE_LO_R
);
393 BuildMI(MBB
, MBBI
, DL
, TII
->get(LoongArch::LU12I_W
), Part1
)
394 .addDisp(Symbol
, 0, LoongArchII::MO_LE_HI
);
396 BuildMI(MBB
, MBBI
, DL
, TII
->get(LoongArch::ORI
), Parts01
)
397 .addReg(Part1
, RegState::Kill
)
398 .addDisp(Symbol
, 0, LoongArchII::MO_LE_LO
);
401 MF
->getRegInfo().createVirtualRegister(&LoongArch::GPRRegClass
);
403 BuildMI(MBB
, MBBI
, DL
, TII
->get(LoongArch::LU32I_D
), Parts012
)
404 // "rj" is needed due to InstrInfo pattern requirement.
405 .addReg(Parts01
, RegState::Kill
)
406 .addDisp(Symbol
, 0, LoongArchII::MO_LE64_LO
);
407 BuildMI(MBB
, MBBI
, DL
, TII
->get(LoongArch::LU52I_D
), DestReg
)
408 .addReg(Parts012
, RegState::Kill
)
409 .addDisp(Symbol
, 0, LoongArchII::MO_LE64_HI
);
412 MI
.eraseFromParent();
416 bool LoongArchPreRAExpandPseudo::expandLoadAddressTLSIE(
417 MachineBasicBlock
&MBB
, MachineBasicBlock::iterator MBBI
,
418 MachineBasicBlock::iterator
&NextMBBI
, bool Large
) {
420 // Emit the 5-insn large address load sequence with the `%ie_pc` family
421 // of relocs, loading the result with `ldx.d` in the end.
422 return expandLargeAddressLoad(MBB
, MBBI
, NextMBBI
, LoongArch::LDX_D
,
423 LoongArchII::MO_IE_PC_LO
);
426 // pcalau12i $rd, %ie_pc_hi20(sym)
427 // ld.w/d $rd, $rd, %ie_pc_lo12(sym)
428 MachineFunction
*MF
= MBB
.getParent();
429 const auto &STI
= MF
->getSubtarget
<LoongArchSubtarget
>();
430 unsigned SecondOpcode
= STI
.is64Bit() ? LoongArch::LD_D
: LoongArch::LD_W
;
431 return expandPcalau12iInstPair(MBB
, MBBI
, NextMBBI
, LoongArchII::MO_IE_PC_HI
,
432 SecondOpcode
, LoongArchII::MO_IE_PC_LO
);
435 bool LoongArchPreRAExpandPseudo::expandLoadAddressTLSLD(
436 MachineBasicBlock
&MBB
, MachineBasicBlock::iterator MBBI
,
437 MachineBasicBlock::iterator
&NextMBBI
, bool Large
) {
439 // Emit the 5-insn large address load sequence with the `%got_pc` family
440 // of relocs, with the `pcalau12i` insn relocated with `%ld_pc_hi20`.
441 return expandLargeAddressLoad(MBB
, MBBI
, NextMBBI
, LoongArch::ADD_D
,
442 LoongArchII::MO_LD_PC_HI
);
445 // pcalau12i $rd, %ld_pc_hi20(sym)
446 // addi.w/d $rd, $rd, %got_pc_lo12(sym)
447 MachineFunction
*MF
= MBB
.getParent();
448 const auto &STI
= MF
->getSubtarget
<LoongArchSubtarget
>();
449 unsigned SecondOpcode
= STI
.is64Bit() ? LoongArch::ADDI_D
: LoongArch::ADDI_W
;
450 return expandPcalau12iInstPair(MBB
, MBBI
, NextMBBI
, LoongArchII::MO_LD_PC_HI
,
451 SecondOpcode
, LoongArchII::MO_GOT_PC_LO
);
454 bool LoongArchPreRAExpandPseudo::expandLoadAddressTLSGD(
455 MachineBasicBlock
&MBB
, MachineBasicBlock::iterator MBBI
,
456 MachineBasicBlock::iterator
&NextMBBI
, bool Large
) {
458 // Emit the 5-insn large address load sequence with the `%got_pc` family
459 // of relocs, with the `pcalau12i` insn relocated with `%gd_pc_hi20`.
460 return expandLargeAddressLoad(MBB
, MBBI
, NextMBBI
, LoongArch::ADD_D
,
461 LoongArchII::MO_GD_PC_HI
);
464 // pcalau12i $rd, %gd_pc_hi20(sym)
465 // addi.w/d $rd, $rd, %got_pc_lo12(sym)
466 MachineFunction
*MF
= MBB
.getParent();
467 const auto &STI
= MF
->getSubtarget
<LoongArchSubtarget
>();
468 unsigned SecondOpcode
= STI
.is64Bit() ? LoongArch::ADDI_D
: LoongArch::ADDI_W
;
469 return expandPcalau12iInstPair(MBB
, MBBI
, NextMBBI
, LoongArchII::MO_GD_PC_HI
,
470 SecondOpcode
, LoongArchII::MO_GOT_PC_LO
);
473 bool LoongArchPreRAExpandPseudo::expandLoadAddressTLSDesc(
474 MachineBasicBlock
&MBB
, MachineBasicBlock::iterator MBBI
,
475 MachineBasicBlock::iterator
&NextMBBI
, bool Large
) {
476 MachineFunction
*MF
= MBB
.getParent();
477 MachineInstr
&MI
= *MBBI
;
478 DebugLoc DL
= MI
.getDebugLoc();
480 const auto &STI
= MF
->getSubtarget
<LoongArchSubtarget
>();
481 unsigned ADD
= STI
.is64Bit() ? LoongArch::ADD_D
: LoongArch::ADD_W
;
482 unsigned ADDI
= STI
.is64Bit() ? LoongArch::ADDI_D
: LoongArch::ADDI_W
;
483 unsigned LD
= STI
.is64Bit() ? LoongArch::LD_D
: LoongArch::LD_W
;
485 Register DestReg
= MI
.getOperand(0).getReg();
487 MF
->getRegInfo().createVirtualRegister(&LoongArch::GPRRegClass
);
488 MachineOperand
&Symbol
= MI
.getOperand(Large
? 2 : 1);
490 BuildMI(MBB
, MBBI
, DL
, TII
->get(LoongArch::PCALAU12I
), Tmp1Reg
)
491 .addDisp(Symbol
, 0, LoongArchII::MO_DESC_PC_HI
);
496 // pcalau12i $a0, %desc_pc_hi20(sym)
497 // addi.d $a1, $zero, %desc_pc_lo12(sym)
498 // lu32i.d $a1, %desc64_pc_lo20(sym)
499 // lu52i.d $a1, $a1, %desc64_pc_hi12(sym)
500 // add.d $a0, $a0, $a1
501 // ld.d $ra, $a0, %desc_ld(sym)
502 // jirl $ra, $ra, %desc_call(sym)
503 // add.d $dst, $a0, $tp
504 assert(MBB
.getParent()->getSubtarget
<LoongArchSubtarget
>().is64Bit() &&
505 "Large code model requires LA64");
507 MF
->getRegInfo().createVirtualRegister(&LoongArch::GPRRegClass
);
509 MF
->getRegInfo().createVirtualRegister(&LoongArch::GPRRegClass
);
511 MF
->getRegInfo().createVirtualRegister(&LoongArch::GPRRegClass
);
512 BuildMI(MBB
, MBBI
, DL
, TII
->get(LoongArch::ADDI_D
), Tmp2Reg
)
513 .addReg(LoongArch::R0
)
514 .addDisp(Symbol
, 0, LoongArchII::MO_DESC_PC_LO
);
515 BuildMI(MBB
, MBBI
, DL
, TII
->get(LoongArch::LU32I_D
), Tmp3Reg
)
516 .addReg(Tmp2Reg
, RegState::Kill
)
517 .addDisp(Symbol
, 0, LoongArchII::MO_DESC64_PC_LO
);
518 BuildMI(MBB
, MBBI
, DL
, TII
->get(LoongArch::LU52I_D
), Tmp4Reg
)
520 .addDisp(Symbol
, 0, LoongArchII::MO_DESC64_PC_HI
);
521 BuildMI(MBB
, MBBI
, DL
, TII
->get(LoongArch::ADD_D
), LoongArch::R4
)
526 // pcalau12i $a0, %desc_pc_hi20(sym)
527 // addi.w/d $a0, $a0, %desc_pc_lo12(sym)
528 // ld.w/d $ra, $a0, %desc_ld(sym)
529 // jirl $ra, $ra, %desc_ld(sym)
530 // add.d $dst, $a0, $tp
531 BuildMI(MBB
, MBBI
, DL
, TII
->get(ADDI
), LoongArch::R4
)
533 .addDisp(Symbol
, 0, LoongArchII::MO_DESC_PC_LO
);
536 BuildMI(MBB
, MBBI
, DL
, TII
->get(LD
), LoongArch::R1
)
537 .addReg(LoongArch::R4
)
538 .addDisp(Symbol
, 0, LoongArchII::MO_DESC_LD
);
539 BuildMI(MBB
, MBBI
, DL
, TII
->get(LoongArch::PseudoDESC_CALL
), LoongArch::R1
)
540 .addReg(LoongArch::R1
)
541 .addDisp(Symbol
, 0, LoongArchII::MO_DESC_CALL
);
542 BuildMI(MBB
, MBBI
, DL
, TII
->get(ADD
), DestReg
)
543 .addReg(LoongArch::R4
)
544 .addReg(LoongArch::R2
);
546 MI
.eraseFromParent();
550 bool LoongArchPreRAExpandPseudo::expandFunctionCALL(
551 MachineBasicBlock
&MBB
, MachineBasicBlock::iterator MBBI
,
552 MachineBasicBlock::iterator
&NextMBBI
, bool IsTailCall
) {
553 MachineFunction
*MF
= MBB
.getParent();
554 MachineInstr
&MI
= *MBBI
;
555 DebugLoc DL
= MI
.getDebugLoc();
556 const MachineOperand
&Func
= MI
.getOperand(0);
557 MachineInstrBuilder CALL
;
560 switch (MF
->getTarget().getCodeModel()) {
562 report_fatal_error("Unexpected code model");
564 case CodeModel::Small
: {
569 Opcode
= IsTailCall
? LoongArch::PseudoB_TAIL
: LoongArch::BL
;
570 CALL
= BuildMI(MBB
, MBBI
, DL
, TII
->get(Opcode
)).add(Func
);
573 case CodeModel::Large
: {
574 // Emit the 5-insn large address load sequence, either directly or
575 // indirectly in case of going through the GOT, then JIRL_TAIL or
576 // JIRL_CALL to $addr.
578 IsTailCall
? LoongArch::PseudoJIRL_TAIL
: LoongArch::PseudoJIRL_CALL
;
581 ? MF
->getRegInfo().createVirtualRegister(&LoongArch::GPRRegClass
)
584 bool UseGOT
= Func
.getTargetFlags() == LoongArchII::MO_CALL_PLT
;
585 unsigned MO
= UseGOT
? LoongArchII::MO_GOT_PC_HI
: LoongArchII::MO_PCREL_LO
;
586 unsigned LAOpcode
= UseGOT
? LoongArch::LDX_D
: LoongArch::ADD_D
;
587 expandLargeAddressLoad(MBB
, MBBI
, NextMBBI
, LAOpcode
, MO
, Func
, AddrReg
,
589 CALL
= BuildMI(MBB
, MBBI
, DL
, TII
->get(Opcode
)).addReg(AddrReg
).addImm(0);
594 // Transfer implicit operands.
595 CALL
.copyImplicitOps(MI
);
597 // Transfer MI flags.
598 CALL
.setMIFlags(MI
.getFlags());
600 MI
.eraseFromParent();
604 void LoongArchPreRAExpandPseudo::annotateTableJump(
605 MachineBasicBlock
&MBB
, MachineBasicBlock::iterator MBBI
) {
606 MachineFunction
*MF
= MBB
.getParent();
607 MachineRegisterInfo
&MRI
= MBB
.getParent()->getRegInfo();
609 bool IsFound
= false;
611 std::function
<void(MachineInstr
*, int)> FindJTIMI
= [&](MachineInstr
*MInst
,
615 for (auto &MO
: MInst
->all_uses()) {
618 Register Reg
= MO
.getReg();
619 if (!Reg
.isVirtual())
621 MachineInstr
*DefMI
= MRI
.getVRegDef(Reg
);
624 for (unsigned Idx
= 0; Idx
< DefMI
->getNumOperands(); ++Idx
) {
625 MachineOperand
&MO
= DefMI
->getOperand(Idx
);
627 MBBI
->setPreInstrSymbol(
628 *MF
, MF
->getContext().createNamedTempSymbol("jrtb_"));
629 MF
->getInfo
<LoongArchMachineFunctionInfo
>()->setJumpInfo(&*MBBI
, &MO
);
634 FindJTIMI(DefMI
, --FindDepth
);
638 // FindDepth = 3, probably sufficient.
639 FindJTIMI(&*MBBI
, /*FindDepth=*/3);
642 class LoongArchExpandPseudo
: public MachineFunctionPass
{
644 const LoongArchInstrInfo
*TII
;
647 LoongArchExpandPseudo() : MachineFunctionPass(ID
) {
648 initializeLoongArchExpandPseudoPass(*PassRegistry::getPassRegistry());
651 bool runOnMachineFunction(MachineFunction
&MF
) override
;
653 StringRef
getPassName() const override
{
654 return LOONGARCH_EXPAND_PSEUDO_NAME
;
658 bool expandMBB(MachineBasicBlock
&MBB
);
659 bool expandMI(MachineBasicBlock
&MBB
, MachineBasicBlock::iterator MBBI
,
660 MachineBasicBlock::iterator
&NextMBBI
);
661 bool expandCopyCFR(MachineBasicBlock
&MBB
, MachineBasicBlock::iterator MBBI
,
662 MachineBasicBlock::iterator
&NextMBBI
);
663 bool expandFunctionCALL(MachineBasicBlock
&MBB
,
664 MachineBasicBlock::iterator MBBI
,
665 MachineBasicBlock::iterator
&NextMBBI
,
669 char LoongArchExpandPseudo::ID
= 0;
671 bool LoongArchExpandPseudo::runOnMachineFunction(MachineFunction
&MF
) {
673 static_cast<const LoongArchInstrInfo
*>(MF
.getSubtarget().getInstrInfo());
675 bool Modified
= false;
677 Modified
|= expandMBB(MBB
);
682 bool LoongArchExpandPseudo::expandMBB(MachineBasicBlock
&MBB
) {
683 bool Modified
= false;
685 MachineBasicBlock::iterator MBBI
= MBB
.begin(), E
= MBB
.end();
687 MachineBasicBlock::iterator NMBBI
= std::next(MBBI
);
688 Modified
|= expandMI(MBB
, MBBI
, NMBBI
);
695 bool LoongArchExpandPseudo::expandMI(MachineBasicBlock
&MBB
,
696 MachineBasicBlock::iterator MBBI
,
697 MachineBasicBlock::iterator
&NextMBBI
) {
698 switch (MBBI
->getOpcode()) {
699 case LoongArch::PseudoCopyCFR
:
700 return expandCopyCFR(MBB
, MBBI
, NextMBBI
);
701 case LoongArch::PseudoCALL_MEDIUM
:
702 return expandFunctionCALL(MBB
, MBBI
, NextMBBI
, /*IsTailCall=*/false);
703 case LoongArch::PseudoTAIL_MEDIUM
:
704 return expandFunctionCALL(MBB
, MBBI
, NextMBBI
, /*IsTailCall=*/true);
710 bool LoongArchExpandPseudo::expandCopyCFR(
711 MachineBasicBlock
&MBB
, MachineBasicBlock::iterator MBBI
,
712 MachineBasicBlock::iterator
&NextMBBI
) {
713 MachineFunction
*MF
= MBB
.getParent();
714 MachineInstr
&MI
= *MBBI
;
715 DebugLoc DL
= MI
.getDebugLoc();
719 // fcmp.caf.s $dst, $fa0, $fa0 # set $dst 0(false)
720 // bceqz $src, SinkBB
722 // fcmp.cueq.s $dst, $fa0, $fa0 # set $dst 1(true)
726 const BasicBlock
*LLVM_BB
= MBB
.getBasicBlock();
727 auto *FalseBB
= MF
->CreateMachineBasicBlock(LLVM_BB
);
728 auto *SinkBB
= MF
->CreateMachineBasicBlock(LLVM_BB
);
730 MF
->insert(++MBB
.getIterator(), FalseBB
);
731 MF
->insert(++FalseBB
->getIterator(), SinkBB
);
733 Register DestReg
= MI
.getOperand(0).getReg();
734 Register SrcReg
= MI
.getOperand(1).getReg();
736 BuildMI(MBB
, MBBI
, DL
, TII
->get(LoongArch::SET_CFR_FALSE
), DestReg
);
737 // Insert branch instruction.
738 BuildMI(MBB
, MBBI
, DL
, TII
->get(LoongArch::BCEQZ
))
742 BuildMI(FalseBB
, DL
, TII
->get(LoongArch::SET_CFR_TRUE
), DestReg
);
744 FalseBB
->addSuccessor(SinkBB
);
746 SinkBB
->splice(SinkBB
->end(), &MBB
, MI
, MBB
.end());
747 SinkBB
->transferSuccessors(&MBB
);
749 MBB
.addSuccessor(FalseBB
);
750 MBB
.addSuccessor(SinkBB
);
752 NextMBBI
= MBB
.end();
753 MI
.eraseFromParent();
755 // Make sure live-ins are correctly attached to this new basic block.
756 LivePhysRegs LiveRegs
;
757 computeAndAddLiveIns(LiveRegs
, *FalseBB
);
758 computeAndAddLiveIns(LiveRegs
, *SinkBB
);
763 bool LoongArchExpandPseudo::expandFunctionCALL(
764 MachineBasicBlock
&MBB
, MachineBasicBlock::iterator MBBI
,
765 MachineBasicBlock::iterator
&NextMBBI
, bool IsTailCall
) {
766 MachineFunction
*MF
= MBB
.getParent();
767 MachineInstr
&MI
= *MBBI
;
768 DebugLoc DL
= MI
.getDebugLoc();
769 const MachineOperand
&Func
= MI
.getOperand(0);
770 MachineInstrBuilder CALL
;
773 switch (MF
->getTarget().getCodeModel()) {
775 report_fatal_error("Unexpected code model");
777 case CodeModel::Medium
: {
779 // pcaddu18i $ra, %call36(func)
782 // pcaddu18i $t8, %call36(func)
785 IsTailCall
? LoongArch::PseudoJIRL_TAIL
: LoongArch::PseudoJIRL_CALL
;
786 Register ScratchReg
= IsTailCall
? LoongArch::R20
: LoongArch::R1
;
787 MachineInstrBuilder MIB
=
788 BuildMI(MBB
, MBBI
, DL
, TII
->get(LoongArch::PCADDU18I
), ScratchReg
);
791 BuildMI(MBB
, MBBI
, DL
, TII
->get(Opcode
)).addReg(ScratchReg
).addImm(0);
794 MIB
.addExternalSymbol(Func
.getSymbolName(), LoongArchII::MO_CALL36
);
796 MIB
.addDisp(Func
, 0, LoongArchII::MO_CALL36
);
801 // Transfer implicit operands.
802 CALL
.copyImplicitOps(MI
);
804 // Transfer MI flags.
805 CALL
.setMIFlags(MI
.getFlags());
807 MI
.eraseFromParent();
813 INITIALIZE_PASS(LoongArchPreRAExpandPseudo
, "loongarch-prera-expand-pseudo",
814 LOONGARCH_PRERA_EXPAND_PSEUDO_NAME
, false, false)
816 INITIALIZE_PASS(LoongArchExpandPseudo
, "loongarch-expand-pseudo",
817 LOONGARCH_EXPAND_PSEUDO_NAME
, false, false)
821 FunctionPass
*createLoongArchPreRAExpandPseudoPass() {
822 return new LoongArchPreRAExpandPseudo();
824 FunctionPass
*createLoongArchExpandPseudoPass() {
825 return new LoongArchExpandPseudo();
828 } // end namespace llvm