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.
11 //
12 //===----------------------------------------------------------------------===//
13 
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"
27 
28 using namespace llvm;
29 
30 #define LOONGARCH_PRERA_EXPAND_PSEUDO_NAME                                     \
31   "LoongArch Pre-RA pseudo instruction expansion pass"
32 
33 namespace {
34 
35 class LoongArchPreRAExpandPseudo : public MachineFunctionPass {
36 public:
37   const LoongArchInstrInfo *TII;
38   static char ID;
39 
40   LoongArchPreRAExpandPseudo() : MachineFunctionPass(ID) {
41     initializeLoongArchPreRAExpandPseudoPass(*PassRegistry::getPassRegistry());
42   }
43 
44   bool runOnMachineFunction(MachineFunction &MF) override;
45 
46   void getAnalysisUsage(AnalysisUsage &AU) const override {
47     AU.setPreservesCFG();
48     MachineFunctionPass::getAnalysisUsage(AU);
49   }
50   StringRef getPassName() const override {
51     return LOONGARCH_PRERA_EXPAND_PSEUDO_NAME;
52   }
53 
54 private:
55   bool expandMBB(MachineBasicBlock &MBB);
56   bool expandMI(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
57                 MachineBasicBlock::iterator &NextMBBI);
58   bool expandPcalau12iInstPair(MachineBasicBlock &MBB,
59                                MachineBasicBlock::iterator MBBI,
60                                MachineBasicBlock::iterator &NextMBBI,
61                                unsigned FlagsHi, unsigned SecondOpcode,
62                                unsigned FlagsLo);
63   bool expandLargeAddressLoad(MachineBasicBlock &MBB,
64                               MachineBasicBlock::iterator MBBI,
65                               MachineBasicBlock::iterator &NextMBBI,
66                               unsigned LastOpcode, unsigned IdentifyingMO);
67   bool expandLargeAddressLoad(MachineBasicBlock &MBB,
68                               MachineBasicBlock::iterator MBBI,
69                               MachineBasicBlock::iterator &NextMBBI,
70                               unsigned LastOpcode, unsigned IdentifyingMO,
71                               const MachineOperand &Symbol, Register DestReg,
72                               bool EraseFromParent);
73   bool expandLoadAddressPcrel(MachineBasicBlock &MBB,
74                               MachineBasicBlock::iterator MBBI,
75                               MachineBasicBlock::iterator &NextMBBI,
76                               bool Large = false);
77   bool expandLoadAddressGot(MachineBasicBlock &MBB,
78                             MachineBasicBlock::iterator MBBI,
79                             MachineBasicBlock::iterator &NextMBBI,
80                             bool Large = false);
81   bool expandLoadAddressTLSLE(MachineBasicBlock &MBB,
82                               MachineBasicBlock::iterator MBBI,
83                               MachineBasicBlock::iterator &NextMBBI);
84   bool expandLoadAddressTLSIE(MachineBasicBlock &MBB,
85                               MachineBasicBlock::iterator MBBI,
86                               MachineBasicBlock::iterator &NextMBBI,
87                               bool Large = false);
88   bool expandLoadAddressTLSLD(MachineBasicBlock &MBB,
89                               MachineBasicBlock::iterator MBBI,
90                               MachineBasicBlock::iterator &NextMBBI,
91                               bool Large = false);
92   bool expandLoadAddressTLSGD(MachineBasicBlock &MBB,
93                               MachineBasicBlock::iterator MBBI,
94                               MachineBasicBlock::iterator &NextMBBI,
95                               bool Large = false);
96   bool expandFunctionCALL(MachineBasicBlock &MBB,
97                           MachineBasicBlock::iterator MBBI,
98                           MachineBasicBlock::iterator &NextMBBI,
99                           bool IsTailCall);
100 };
101 
102 char LoongArchPreRAExpandPseudo::ID = 0;
103 
104 bool LoongArchPreRAExpandPseudo::runOnMachineFunction(MachineFunction &MF) {
105   TII =
106       static_cast<const LoongArchInstrInfo *>(MF.getSubtarget().getInstrInfo());
107   bool Modified = false;
108   for (auto &MBB : MF)
109     Modified |= expandMBB(MBB);
110   return Modified;
111 }
112 
113 bool LoongArchPreRAExpandPseudo::expandMBB(MachineBasicBlock &MBB) {
114   bool Modified = false;
115 
116   MachineBasicBlock::iterator MBBI = MBB.begin(), E = MBB.end();
117   while (MBBI != E) {
118     MachineBasicBlock::iterator NMBBI = std::next(MBBI);
119     Modified |= expandMI(MBB, MBBI, NMBBI);
120     MBBI = NMBBI;
121   }
122 
123   return Modified;
124 }
125 
126 bool LoongArchPreRAExpandPseudo::expandMI(
127     MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
128     MachineBasicBlock::iterator &NextMBBI) {
129   switch (MBBI->getOpcode()) {
130   case LoongArch::PseudoLA_PCREL:
131     return expandLoadAddressPcrel(MBB, MBBI, NextMBBI);
132   case LoongArch::PseudoLA_PCREL_LARGE:
133     return expandLoadAddressPcrel(MBB, MBBI, NextMBBI, /*Large=*/true);
134   case LoongArch::PseudoLA_GOT:
135     return expandLoadAddressGot(MBB, MBBI, NextMBBI);
136   case LoongArch::PseudoLA_GOT_LARGE:
137     return expandLoadAddressGot(MBB, MBBI, NextMBBI, /*Large=*/true);
138   case LoongArch::PseudoLA_TLS_LE:
139     return expandLoadAddressTLSLE(MBB, MBBI, NextMBBI);
140   case LoongArch::PseudoLA_TLS_IE:
141     return expandLoadAddressTLSIE(MBB, MBBI, NextMBBI);
142   case LoongArch::PseudoLA_TLS_IE_LARGE:
143     return expandLoadAddressTLSIE(MBB, MBBI, NextMBBI, /*Large=*/true);
144   case LoongArch::PseudoLA_TLS_LD:
145     return expandLoadAddressTLSLD(MBB, MBBI, NextMBBI);
146   case LoongArch::PseudoLA_TLS_LD_LARGE:
147     return expandLoadAddressTLSLD(MBB, MBBI, NextMBBI, /*Large=*/true);
148   case LoongArch::PseudoLA_TLS_GD:
149     return expandLoadAddressTLSGD(MBB, MBBI, NextMBBI);
150   case LoongArch::PseudoLA_TLS_GD_LARGE:
151     return expandLoadAddressTLSGD(MBB, MBBI, NextMBBI, /*Large=*/true);
152   case LoongArch::PseudoCALL:
153     return expandFunctionCALL(MBB, MBBI, NextMBBI, /*IsTailCall=*/false);
154   case LoongArch::PseudoTAIL:
155     return expandFunctionCALL(MBB, MBBI, NextMBBI, /*IsTailCall=*/true);
156   }
157   return false;
158 }
159 
160 bool LoongArchPreRAExpandPseudo::expandPcalau12iInstPair(
161     MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
162     MachineBasicBlock::iterator &NextMBBI, unsigned FlagsHi,
163     unsigned SecondOpcode, unsigned FlagsLo) {
164   MachineFunction *MF = MBB.getParent();
165   MachineInstr &MI = *MBBI;
166   DebugLoc DL = MI.getDebugLoc();
167 
168   Register DestReg = MI.getOperand(0).getReg();
169   Register ScratchReg =
170       MF->getRegInfo().createVirtualRegister(&LoongArch::GPRRegClass);
171   MachineOperand &Symbol = MI.getOperand(1);
172 
173   BuildMI(MBB, MBBI, DL, TII->get(LoongArch::PCALAU12I), ScratchReg)
174       .addDisp(Symbol, 0, FlagsHi);
175 
176   MachineInstr *SecondMI =
177       BuildMI(MBB, MBBI, DL, TII->get(SecondOpcode), DestReg)
178           .addReg(ScratchReg)
179           .addDisp(Symbol, 0, FlagsLo);
180 
181   if (MI.hasOneMemOperand())
182     SecondMI->addMemOperand(*MF, *MI.memoperands_begin());
183 
184   MI.eraseFromParent();
185   return true;
186 }
187 
188 bool LoongArchPreRAExpandPseudo::expandLargeAddressLoad(
189     MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
190     MachineBasicBlock::iterator &NextMBBI, unsigned LastOpcode,
191     unsigned IdentifyingMO) {
192   MachineInstr &MI = *MBBI;
193   return expandLargeAddressLoad(MBB, MBBI, NextMBBI, LastOpcode, IdentifyingMO,
194                                 MI.getOperand(2), MI.getOperand(0).getReg(),
195                                 true);
196 }
197 
198 bool LoongArchPreRAExpandPseudo::expandLargeAddressLoad(
199     MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
200     MachineBasicBlock::iterator &NextMBBI, unsigned LastOpcode,
201     unsigned IdentifyingMO, const MachineOperand &Symbol, Register DestReg,
202     bool EraseFromParent) {
203   // Code Sequence:
204   //
205   // Part1: pcalau12i  $scratch, %MO1(sym)
206   // Part0: addi.d     $dest, $zero, %MO0(sym)
207   // Part2: lu32i.d    $dest, %MO2(sym)
208   // Part3: lu52i.d    $dest, $dest, %MO3(sym)
209   // Fin:   LastOpcode $dest, $dest, $scratch
210 
211   unsigned MO0, MO1, MO2, MO3;
212   switch (IdentifyingMO) {
213   default:
214     llvm_unreachable("unsupported identifying MO");
215   case LoongArchII::MO_PCREL_LO:
216     MO0 = IdentifyingMO;
217     MO1 = LoongArchII::MO_PCREL_HI;
218     MO2 = LoongArchII::MO_PCREL64_LO;
219     MO3 = LoongArchII::MO_PCREL64_HI;
220     break;
221   case LoongArchII::MO_GOT_PC_HI:
222   case LoongArchII::MO_LD_PC_HI:
223   case LoongArchII::MO_GD_PC_HI:
224     // These cases relocate just like the GOT case, except for Part1.
225     MO0 = LoongArchII::MO_GOT_PC_LO;
226     MO1 = IdentifyingMO;
227     MO2 = LoongArchII::MO_GOT_PC64_LO;
228     MO3 = LoongArchII::MO_GOT_PC64_HI;
229     break;
230   case LoongArchII::MO_IE_PC_LO:
231     MO0 = IdentifyingMO;
232     MO1 = LoongArchII::MO_IE_PC_HI;
233     MO2 = LoongArchII::MO_IE_PC64_LO;
234     MO3 = LoongArchII::MO_IE_PC64_HI;
235     break;
236   }
237 
238   MachineFunction *MF = MBB.getParent();
239   MachineInstr &MI = *MBBI;
240   DebugLoc DL = MI.getDebugLoc();
241 
242   assert(MF->getSubtarget<LoongArchSubtarget>().is64Bit() &&
243          "Large code model requires LA64");
244 
245   Register TmpPart1 =
246       MF->getRegInfo().createVirtualRegister(&LoongArch::GPRRegClass);
247   Register TmpPart0 =
248       DestReg.isVirtual()
249           ? MF->getRegInfo().createVirtualRegister(&LoongArch::GPRRegClass)
250           : DestReg;
251   Register TmpParts02 =
252       DestReg.isVirtual()
253           ? MF->getRegInfo().createVirtualRegister(&LoongArch::GPRRegClass)
254           : DestReg;
255   Register TmpParts023 =
256       DestReg.isVirtual()
257           ? MF->getRegInfo().createVirtualRegister(&LoongArch::GPRRegClass)
258           : DestReg;
259 
260   auto Part1 = BuildMI(MBB, MBBI, DL, TII->get(LoongArch::PCALAU12I), TmpPart1);
261   auto Part0 = BuildMI(MBB, MBBI, DL, TII->get(LoongArch::ADDI_D), TmpPart0)
262                    .addReg(LoongArch::R0);
263   auto Part2 = BuildMI(MBB, MBBI, DL, TII->get(LoongArch::LU32I_D), TmpParts02)
264                    // "rj" is needed due to InstrInfo pattern requirement.
265                    .addReg(TmpPart0, RegState::Kill);
266   auto Part3 = BuildMI(MBB, MBBI, DL, TII->get(LoongArch::LU52I_D), TmpParts023)
267                    .addReg(TmpParts02, RegState::Kill);
268   BuildMI(MBB, MBBI, DL, TII->get(LastOpcode), DestReg)
269       .addReg(TmpParts023)
270       .addReg(TmpPart1, RegState::Kill);
271 
272   if (Symbol.getType() == MachineOperand::MO_ExternalSymbol) {
273     const char *SymName = Symbol.getSymbolName();
274     Part0.addExternalSymbol(SymName, MO0);
275     Part1.addExternalSymbol(SymName, MO1);
276     Part2.addExternalSymbol(SymName, MO2);
277     Part3.addExternalSymbol(SymName, MO3);
278   } else {
279     Part0.addDisp(Symbol, 0, MO0);
280     Part1.addDisp(Symbol, 0, MO1);
281     Part2.addDisp(Symbol, 0, MO2);
282     Part3.addDisp(Symbol, 0, MO3);
283   }
284 
285   if (EraseFromParent)
286     MI.eraseFromParent();
287 
288   return true;
289 }
290 
291 bool LoongArchPreRAExpandPseudo::expandLoadAddressPcrel(
292     MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
293     MachineBasicBlock::iterator &NextMBBI, bool Large) {
294   if (Large)
295     // Emit the 5-insn large address load sequence with the `%pc` family of
296     // relocs.
297     return expandLargeAddressLoad(MBB, MBBI, NextMBBI, LoongArch::ADD_D,
298                                   LoongArchII::MO_PCREL_LO);
299 
300   // Code Sequence:
301   // pcalau12i $rd, %pc_hi20(sym)
302   // addi.w/d $rd, $rd, %pc_lo12(sym)
303   MachineFunction *MF = MBB.getParent();
304   const auto &STI = MF->getSubtarget<LoongArchSubtarget>();
305   unsigned SecondOpcode = STI.is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W;
306   return expandPcalau12iInstPair(MBB, MBBI, NextMBBI, LoongArchII::MO_PCREL_HI,
307                                  SecondOpcode, LoongArchII::MO_PCREL_LO);
308 }
309 
310 bool LoongArchPreRAExpandPseudo::expandLoadAddressGot(
311     MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
312     MachineBasicBlock::iterator &NextMBBI, bool Large) {
313   if (Large)
314     // Emit the 5-insn large address load sequence with the `%got_pc` family
315     // of relocs, loading the result from GOT with `ldx.d` in the end.
316     return expandLargeAddressLoad(MBB, MBBI, NextMBBI, LoongArch::LDX_D,
317                                   LoongArchII::MO_GOT_PC_HI);
318 
319   // Code Sequence:
320   // pcalau12i $rd, %got_pc_hi20(sym)
321   // ld.w/d $rd, $rd, %got_pc_lo12(sym)
322   MachineFunction *MF = MBB.getParent();
323   const auto &STI = MF->getSubtarget<LoongArchSubtarget>();
324   unsigned SecondOpcode = STI.is64Bit() ? LoongArch::LD_D : LoongArch::LD_W;
325   return expandPcalau12iInstPair(MBB, MBBI, NextMBBI, LoongArchII::MO_GOT_PC_HI,
326                                  SecondOpcode, LoongArchII::MO_GOT_PC_LO);
327 }
328 
329 bool LoongArchPreRAExpandPseudo::expandLoadAddressTLSLE(
330     MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
331     MachineBasicBlock::iterator &NextMBBI) {
332   // Code Sequence:
333   // lu12i.w $rd, %le_hi20(sym)
334   // ori $rd, $rd, %le_lo12(sym)
335   //
336   // And additionally if generating code using the large code model:
337   //
338   // lu32i.d $rd, %le64_lo20(sym)
339   // lu52i.d $rd, $rd, %le64_hi12(sym)
340   MachineFunction *MF = MBB.getParent();
341   MachineInstr &MI = *MBBI;
342   DebugLoc DL = MI.getDebugLoc();
343 
344   bool Large = MF->getTarget().getCodeModel() == CodeModel::Large;
345   Register DestReg = MI.getOperand(0).getReg();
346   Register Parts01 =
347       Large ? MF->getRegInfo().createVirtualRegister(&LoongArch::GPRRegClass)
348             : DestReg;
349   Register Part1 =
350       MF->getRegInfo().createVirtualRegister(&LoongArch::GPRRegClass);
351   MachineOperand &Symbol = MI.getOperand(1);
352 
353   BuildMI(MBB, MBBI, DL, TII->get(LoongArch::LU12I_W), Part1)
354       .addDisp(Symbol, 0, LoongArchII::MO_LE_HI);
355 
356   BuildMI(MBB, MBBI, DL, TII->get(LoongArch::ORI), Parts01)
357       .addReg(Part1, RegState::Kill)
358       .addDisp(Symbol, 0, LoongArchII::MO_LE_LO);
359 
360   if (Large) {
361     Register Parts012 =
362         MF->getRegInfo().createVirtualRegister(&LoongArch::GPRRegClass);
363 
364     BuildMI(MBB, MBBI, DL, TII->get(LoongArch::LU32I_D), Parts012)
365         // "rj" is needed due to InstrInfo pattern requirement.
366         .addReg(Parts01, RegState::Kill)
367         .addDisp(Symbol, 0, LoongArchII::MO_LE64_LO);
368     BuildMI(MBB, MBBI, DL, TII->get(LoongArch::LU52I_D), DestReg)
369         .addReg(Parts012, RegState::Kill)
370         .addDisp(Symbol, 0, LoongArchII::MO_LE64_HI);
371   }
372 
373   MI.eraseFromParent();
374   return true;
375 }
376 
377 bool LoongArchPreRAExpandPseudo::expandLoadAddressTLSIE(
378     MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
379     MachineBasicBlock::iterator &NextMBBI, bool Large) {
380   if (Large)
381     // Emit the 5-insn large address load sequence with the `%ie_pc` family
382     // of relocs, loading the result with `ldx.d` in the end.
383     return expandLargeAddressLoad(MBB, MBBI, NextMBBI, LoongArch::LDX_D,
384                                   LoongArchII::MO_IE_PC_LO);
385 
386   // Code Sequence:
387   // pcalau12i $rd, %ie_pc_hi20(sym)
388   // ld.w/d $rd, $rd, %ie_pc_lo12(sym)
389   MachineFunction *MF = MBB.getParent();
390   const auto &STI = MF->getSubtarget<LoongArchSubtarget>();
391   unsigned SecondOpcode = STI.is64Bit() ? LoongArch::LD_D : LoongArch::LD_W;
392   return expandPcalau12iInstPair(MBB, MBBI, NextMBBI, LoongArchII::MO_IE_PC_HI,
393                                  SecondOpcode, LoongArchII::MO_IE_PC_LO);
394 }
395 
396 bool LoongArchPreRAExpandPseudo::expandLoadAddressTLSLD(
397     MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
398     MachineBasicBlock::iterator &NextMBBI, bool Large) {
399   if (Large)
400     // Emit the 5-insn large address load sequence with the `%got_pc` family
401     // of relocs, with the `pcalau12i` insn relocated with `%ld_pc_hi20`.
402     return expandLargeAddressLoad(MBB, MBBI, NextMBBI, LoongArch::ADD_D,
403                                   LoongArchII::MO_LD_PC_HI);
404 
405   // Code Sequence:
406   // pcalau12i $rd, %ld_pc_hi20(sym)
407   // addi.w/d $rd, $rd, %got_pc_lo12(sym)
408   MachineFunction *MF = MBB.getParent();
409   const auto &STI = MF->getSubtarget<LoongArchSubtarget>();
410   unsigned SecondOpcode = STI.is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W;
411   return expandPcalau12iInstPair(MBB, MBBI, NextMBBI, LoongArchII::MO_LD_PC_HI,
412                                  SecondOpcode, LoongArchII::MO_GOT_PC_LO);
413 }
414 
415 bool LoongArchPreRAExpandPseudo::expandLoadAddressTLSGD(
416     MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
417     MachineBasicBlock::iterator &NextMBBI, bool Large) {
418   if (Large)
419     // Emit the 5-insn large address load sequence with the `%got_pc` family
420     // of relocs, with the `pcalau12i` insn relocated with `%gd_pc_hi20`.
421     return expandLargeAddressLoad(MBB, MBBI, NextMBBI, LoongArch::ADD_D,
422                                   LoongArchII::MO_GD_PC_HI);
423 
424   // Code Sequence:
425   // pcalau12i $rd, %gd_pc_hi20(sym)
426   // addi.w/d $rd, $rd, %got_pc_lo12(sym)
427   MachineFunction *MF = MBB.getParent();
428   const auto &STI = MF->getSubtarget<LoongArchSubtarget>();
429   unsigned SecondOpcode = STI.is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W;
430   return expandPcalau12iInstPair(MBB, MBBI, NextMBBI, LoongArchII::MO_GD_PC_HI,
431                                  SecondOpcode, LoongArchII::MO_GOT_PC_LO);
432 }
433 
434 bool LoongArchPreRAExpandPseudo::expandFunctionCALL(
435     MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
436     MachineBasicBlock::iterator &NextMBBI, bool IsTailCall) {
437   MachineFunction *MF = MBB.getParent();
438   MachineInstr &MI = *MBBI;
439   DebugLoc DL = MI.getDebugLoc();
440   const MachineOperand &Func = MI.getOperand(0);
441   MachineInstrBuilder CALL;
442   unsigned Opcode;
443 
444   switch (MF->getTarget().getCodeModel()) {
445   default:
446     report_fatal_error("Unsupported code model");
447     break;
448   case CodeModel::Small: {
449     // CALL:
450     // bl func
451     // TAIL:
452     // b func
453     Opcode = IsTailCall ? LoongArch::PseudoB_TAIL : LoongArch::BL;
454     CALL = BuildMI(MBB, MBBI, DL, TII->get(Opcode)).add(Func);
455     break;
456   }
457   case CodeModel::Medium: {
458     // CALL:
459     // pcalau12i  $ra, %pc_hi20(func)
460     // jirl       $ra, $ra, %pc_lo12(func)
461     // TAIL:
462     // pcalau12i  $scratch, %pc_hi20(func)
463     // jirl       $r0, $scratch, %pc_lo12(func)
464     Opcode =
465         IsTailCall ? LoongArch::PseudoJIRL_TAIL : LoongArch::PseudoJIRL_CALL;
466     Register ScratchReg =
467         IsTailCall
468             ? MF->getRegInfo().createVirtualRegister(&LoongArch::GPRRegClass)
469             : LoongArch::R1;
470     MachineInstrBuilder MIB =
471         BuildMI(MBB, MBBI, DL, TII->get(LoongArch::PCALAU12I), ScratchReg);
472     CALL = BuildMI(MBB, MBBI, DL, TII->get(Opcode)).addReg(ScratchReg);
473     if (Func.isSymbol()) {
474       const char *FnName = Func.getSymbolName();
475       MIB.addExternalSymbol(FnName, LoongArchII::MO_PCREL_HI);
476       CALL.addExternalSymbol(FnName, LoongArchII::MO_PCREL_LO);
477       break;
478     }
479     assert(Func.isGlobal() && "Expected a GlobalValue at this time");
480     const GlobalValue *GV = Func.getGlobal();
481     MIB.addGlobalAddress(GV, 0, LoongArchII::MO_PCREL_HI);
482     CALL.addGlobalAddress(GV, 0, LoongArchII::MO_PCREL_LO);
483     break;
484   }
485   case CodeModel::Large: {
486     // Emit the 5-insn large address load sequence, either directly or
487     // indirectly in case of going through the GOT, then JIRL_TAIL or
488     // JIRL_CALL to $addr.
489     Opcode =
490         IsTailCall ? LoongArch::PseudoJIRL_TAIL : LoongArch::PseudoJIRL_CALL;
491     Register AddrReg =
492         IsTailCall
493             ? MF->getRegInfo().createVirtualRegister(&LoongArch::GPRRegClass)
494             : LoongArch::R1;
495 
496     bool UseGOT = Func.isGlobal() && !Func.getGlobal()->isDSOLocal();
497     unsigned MO = UseGOT ? LoongArchII::MO_GOT_PC_HI : LoongArchII::MO_PCREL_LO;
498     unsigned LAOpcode = UseGOT ? LoongArch::LDX_D : LoongArch::ADD_D;
499     expandLargeAddressLoad(MBB, MBBI, NextMBBI, LAOpcode, MO, Func, AddrReg,
500                            false);
501     CALL = BuildMI(MBB, MBBI, DL, TII->get(Opcode)).addReg(AddrReg).addImm(0);
502     break;
503   }
504   }
505 
506   // Transfer implicit operands.
507   CALL.copyImplicitOps(MI);
508 
509   // Transfer MI flags.
510   CALL.setMIFlags(MI.getFlags());
511 
512   MI.eraseFromParent();
513   return true;
514 }
515 
516 } // end namespace
517 
518 INITIALIZE_PASS(LoongArchPreRAExpandPseudo, "loongarch-prera-expand-pseudo",
519                 LOONGARCH_PRERA_EXPAND_PSEUDO_NAME, false, false)
520 
521 namespace llvm {
522 
523 FunctionPass *createLoongArchPreRAExpandPseudoPass() {
524   return new LoongArchPreRAExpandPseudo();
525 }
526 
527 } // end namespace llvm
528