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