[analyzer][NFC] Factor out SymbolManager::get<*> (#121781)
[llvm-project.git] / llvm / lib / Target / LoongArch / LoongArchExpandPseudoInsts.cpp
blob0218934ea3344a77c51fdc488f15815ed92828a2
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 "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"
28 using namespace llvm;
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"
37 namespace {
39 class LoongArchPreRAExpandPseudo : public MachineFunctionPass {
40 public:
41 const LoongArchInstrInfo *TII;
42 static char ID;
44 LoongArchPreRAExpandPseudo() : MachineFunctionPass(ID) {
45 initializeLoongArchPreRAExpandPseudoPass(*PassRegistry::getPassRegistry());
48 bool runOnMachineFunction(MachineFunction &MF) override;
50 void getAnalysisUsage(AnalysisUsage &AU) const override {
51 AU.setPreservesCFG();
52 MachineFunctionPass::getAnalysisUsage(AU);
54 StringRef getPassName() const override {
55 return LOONGARCH_PRERA_EXPAND_PSEUDO_NAME;
58 private:
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,
66 unsigned FlagsLo);
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,
80 bool Large = false);
81 bool expandLoadAddressGot(MachineBasicBlock &MBB,
82 MachineBasicBlock::iterator MBBI,
83 MachineBasicBlock::iterator &NextMBBI,
84 bool Large = false);
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,
91 bool Large = false);
92 bool expandLoadAddressTLSLD(MachineBasicBlock &MBB,
93 MachineBasicBlock::iterator MBBI,
94 MachineBasicBlock::iterator &NextMBBI,
95 bool Large = false);
96 bool expandLoadAddressTLSGD(MachineBasicBlock &MBB,
97 MachineBasicBlock::iterator MBBI,
98 MachineBasicBlock::iterator &NextMBBI,
99 bool Large = false);
100 bool expandLoadAddressTLSDesc(MachineBasicBlock &MBB,
101 MachineBasicBlock::iterator MBBI,
102 MachineBasicBlock::iterator &NextMBBI,
103 bool Large = false);
104 bool expandFunctionCALL(MachineBasicBlock &MBB,
105 MachineBasicBlock::iterator MBBI,
106 MachineBasicBlock::iterator &NextMBBI,
107 bool IsTailCall);
108 void annotateTableJump(MachineBasicBlock &MBB,
109 MachineBasicBlock::iterator MBBI);
112 char LoongArchPreRAExpandPseudo::ID = 0;
114 bool LoongArchPreRAExpandPseudo::runOnMachineFunction(MachineFunction &MF) {
115 TII =
116 static_cast<const LoongArchInstrInfo *>(MF.getSubtarget().getInstrInfo());
117 bool Modified = false;
118 for (auto &MBB : MF)
119 Modified |= expandMBB(MBB);
120 return Modified;
123 bool LoongArchPreRAExpandPseudo::expandMBB(MachineBasicBlock &MBB) {
124 bool Modified = false;
126 MachineBasicBlock::iterator MBBI = MBB.begin(), E = MBB.end();
127 while (MBBI != E) {
128 MachineBasicBlock::iterator NMBBI = std::next(MBBI);
129 Modified |= expandMI(MBB, MBBI, NMBBI);
130 MBBI = NMBBI;
133 return Modified;
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);
177 break;
179 return false;
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)
200 .addReg(ScratchReg)
201 .addDisp(Symbol, 0, FlagsLo);
203 if (MI.hasOneMemOperand())
204 SecondMI->addMemOperand(*MF, *MI.memoperands_begin());
206 MI.eraseFromParent();
207 return true;
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(),
217 true);
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) {
225 // Code Sequence:
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) {
235 default:
236 llvm_unreachable("unsupported identifying MO");
237 case LoongArchII::MO_PCREL_LO:
238 MO0 = IdentifyingMO;
239 MO1 = LoongArchII::MO_PCREL_HI;
240 MO2 = LoongArchII::MO_PCREL64_LO;
241 MO3 = LoongArchII::MO_PCREL64_HI;
242 break;
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;
248 MO1 = IdentifyingMO;
249 MO2 = LoongArchII::MO_GOT_PC64_LO;
250 MO3 = LoongArchII::MO_GOT_PC64_HI;
251 break;
252 case LoongArchII::MO_IE_PC_LO:
253 MO0 = IdentifyingMO;
254 MO1 = LoongArchII::MO_IE_PC_HI;
255 MO2 = LoongArchII::MO_IE_PC64_LO;
256 MO3 = LoongArchII::MO_IE_PC64_HI;
257 break;
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");
267 Register TmpPart1 =
268 MF->getRegInfo().createVirtualRegister(&LoongArch::GPRRegClass);
269 Register TmpPart0 =
270 DestReg.isVirtual()
271 ? MF->getRegInfo().createVirtualRegister(&LoongArch::GPRRegClass)
272 : DestReg;
273 Register TmpParts02 =
274 DestReg.isVirtual()
275 ? MF->getRegInfo().createVirtualRegister(&LoongArch::GPRRegClass)
276 : DestReg;
277 Register TmpParts023 =
278 DestReg.isVirtual()
279 ? MF->getRegInfo().createVirtualRegister(&LoongArch::GPRRegClass)
280 : DestReg;
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)
291 .addReg(TmpParts023)
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);
300 } else {
301 Part0.addDisp(Symbol, 0, MO0);
302 Part1.addDisp(Symbol, 0, MO1);
303 Part2.addDisp(Symbol, 0, MO2);
304 Part3.addDisp(Symbol, 0, MO3);
307 if (EraseFromParent)
308 MI.eraseFromParent();
310 return true;
313 bool LoongArchPreRAExpandPseudo::expandLoadAddressPcrel(
314 MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
315 MachineBasicBlock::iterator &NextMBBI, bool Large) {
316 if (Large)
317 // Emit the 5-insn large address load sequence with the `%pc` family of
318 // relocs.
319 return expandLargeAddressLoad(MBB, MBBI, NextMBBI, LoongArch::ADD_D,
320 LoongArchII::MO_PCREL_LO);
322 // Code Sequence:
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) {
335 if (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);
341 // Code Sequence:
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) {
354 // Code Sequence:
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();
370 Register Parts01 =
371 MF->getRegInfo().createVirtualRegister(&LoongArch::GPRRegClass);
372 Register Part1 =
373 MF->getRegInfo().createVirtualRegister(&LoongArch::GPRRegClass);
374 MachineOperand &Symbol = MI.getOperand(1);
376 if (!Large) {
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);
392 } else {
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);
400 Register Parts012 =
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();
413 return true;
416 bool LoongArchPreRAExpandPseudo::expandLoadAddressTLSIE(
417 MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
418 MachineBasicBlock::iterator &NextMBBI, bool Large) {
419 if (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);
425 // Code Sequence:
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) {
438 if (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);
444 // Code Sequence:
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) {
457 if (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);
463 // Code Sequence:
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();
486 Register Tmp1Reg =
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);
493 if (Large) {
494 // Code Sequence:
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");
506 Register Tmp2Reg =
507 MF->getRegInfo().createVirtualRegister(&LoongArch::GPRRegClass);
508 Register Tmp3Reg =
509 MF->getRegInfo().createVirtualRegister(&LoongArch::GPRRegClass);
510 Register Tmp4Reg =
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)
519 .addReg(Tmp3Reg)
520 .addDisp(Symbol, 0, LoongArchII::MO_DESC64_PC_HI);
521 BuildMI(MBB, MBBI, DL, TII->get(LoongArch::ADD_D), LoongArch::R4)
522 .addReg(Tmp1Reg)
523 .addReg(Tmp4Reg);
524 } else {
525 // Code Sequence:
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)
532 .addReg(Tmp1Reg)
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();
547 return true;
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;
558 unsigned Opcode;
560 switch (MF->getTarget().getCodeModel()) {
561 default:
562 report_fatal_error("Unexpected code model");
563 break;
564 case CodeModel::Small: {
565 // CALL:
566 // bl func
567 // TAIL:
568 // b func
569 Opcode = IsTailCall ? LoongArch::PseudoB_TAIL : LoongArch::BL;
570 CALL = BuildMI(MBB, MBBI, DL, TII->get(Opcode)).add(Func);
571 break;
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.
577 Opcode =
578 IsTailCall ? LoongArch::PseudoJIRL_TAIL : LoongArch::PseudoJIRL_CALL;
579 Register AddrReg =
580 IsTailCall
581 ? MF->getRegInfo().createVirtualRegister(&LoongArch::GPRRegClass)
582 : LoongArch::R1;
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,
588 false);
589 CALL = BuildMI(MBB, MBBI, DL, TII->get(Opcode)).addReg(AddrReg).addImm(0);
590 break;
594 // Transfer implicit operands.
595 CALL.copyImplicitOps(MI);
597 // Transfer MI flags.
598 CALL.setMIFlags(MI.getFlags());
600 MI.eraseFromParent();
601 return true;
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,
612 int FindDepth) {
613 if (FindDepth < 0)
614 return;
615 for (auto &MO : MInst->all_uses()) {
616 if (IsFound)
617 return;
618 Register Reg = MO.getReg();
619 if (!Reg.isVirtual())
620 continue;
621 MachineInstr *DefMI = MRI.getVRegDef(Reg);
622 if (!DefMI)
623 continue;
624 for (unsigned Idx = 0; Idx < DefMI->getNumOperands(); ++Idx) {
625 MachineOperand &MO = DefMI->getOperand(Idx);
626 if (MO.isJTI()) {
627 MBBI->setPreInstrSymbol(
628 *MF, MF->getContext().createNamedTempSymbol("jrtb_"));
629 MF->getInfo<LoongArchMachineFunctionInfo>()->setJumpInfo(&*MBBI, &MO);
630 IsFound = true;
631 return;
634 FindJTIMI(DefMI, --FindDepth);
638 // FindDepth = 3, probably sufficient.
639 FindJTIMI(&*MBBI, /*FindDepth=*/3);
642 class LoongArchExpandPseudo : public MachineFunctionPass {
643 public:
644 const LoongArchInstrInfo *TII;
645 static char ID;
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;
657 private:
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,
666 bool IsTailCall);
669 char LoongArchExpandPseudo::ID = 0;
671 bool LoongArchExpandPseudo::runOnMachineFunction(MachineFunction &MF) {
672 TII =
673 static_cast<const LoongArchInstrInfo *>(MF.getSubtarget().getInstrInfo());
675 bool Modified = false;
676 for (auto &MBB : MF)
677 Modified |= expandMBB(MBB);
679 return Modified;
682 bool LoongArchExpandPseudo::expandMBB(MachineBasicBlock &MBB) {
683 bool Modified = false;
685 MachineBasicBlock::iterator MBBI = MBB.begin(), E = MBB.end();
686 while (MBBI != E) {
687 MachineBasicBlock::iterator NMBBI = std::next(MBBI);
688 Modified |= expandMI(MBB, MBBI, NMBBI);
689 MBBI = NMBBI;
692 return Modified;
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);
707 return false;
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();
717 // Expand:
718 // MBB:
719 // fcmp.caf.s $dst, $fa0, $fa0 # set $dst 0(false)
720 // bceqz $src, SinkBB
721 // FalseBB:
722 // fcmp.cueq.s $dst, $fa0, $fa0 # set $dst 1(true)
723 // SinkBB:
724 // fallthrough
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();
735 // DestReg = 0
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))
739 .addReg(SrcReg)
740 .addMBB(SinkBB);
741 // DestReg = 1
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);
760 return true;
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;
771 unsigned Opcode;
773 switch (MF->getTarget().getCodeModel()) {
774 default:
775 report_fatal_error("Unexpected code model");
776 break;
777 case CodeModel::Medium: {
778 // CALL:
779 // pcaddu18i $ra, %call36(func)
780 // jirl $ra, $ra, 0
781 // TAIL:
782 // pcaddu18i $t8, %call36(func)
783 // jirl $r0, $t8, 0
784 Opcode =
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);
790 CALL =
791 BuildMI(MBB, MBBI, DL, TII->get(Opcode)).addReg(ScratchReg).addImm(0);
793 if (Func.isSymbol())
794 MIB.addExternalSymbol(Func.getSymbolName(), LoongArchII::MO_CALL36);
795 else
796 MIB.addDisp(Func, 0, LoongArchII::MO_CALL36);
797 break;
801 // Transfer implicit operands.
802 CALL.copyImplicitOps(MI);
804 // Transfer MI flags.
805 CALL.setMIFlags(MI.getFlags());
807 MI.eraseFromParent();
808 return true;
811 } // end namespace
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)
819 namespace llvm {
821 FunctionPass *createLoongArchPreRAExpandPseudoPass() {
822 return new LoongArchPreRAExpandPseudo();
824 FunctionPass *createLoongArchExpandPseudoPass() {
825 return new LoongArchExpandPseudo();
828 } // end namespace llvm