xref: /llvm-project/llvm/lib/Target/LoongArch/LoongArchExpandPseudoInsts.cpp (revision 0288d065eecb1208971dc4cdcc71731e34c6fca0)
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 "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"
27 
28 using namespace llvm;
29 
30 extern cl::opt<bool> LArchAnnotateTableJump;
31 
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"
36 
37 namespace {
38 
39 class LoongArchPreRAExpandPseudo : public MachineFunctionPass {
40 public:
41   const LoongArchInstrInfo *TII;
42   static char ID;
43 
44   LoongArchPreRAExpandPseudo() : MachineFunctionPass(ID) {
45     initializeLoongArchPreRAExpandPseudoPass(*PassRegistry::getPassRegistry());
46   }
47 
48   bool runOnMachineFunction(MachineFunction &MF) override;
49 
50   void getAnalysisUsage(AnalysisUsage &AU) const override {
51     AU.setPreservesCFG();
52     MachineFunctionPass::getAnalysisUsage(AU);
53   }
54   StringRef getPassName() const override {
55     return LOONGARCH_PRERA_EXPAND_PSEUDO_NAME;
56   }
57 
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);
110 };
111 
112 char LoongArchPreRAExpandPseudo::ID = 0;
113 
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;
121 }
122 
123 bool LoongArchPreRAExpandPseudo::expandMBB(MachineBasicBlock &MBB) {
124   bool Modified = false;
125 
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;
131   }
132 
133   return Modified;
134 }
135 
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;
178   }
179   return false;
180 }
181 
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();
189 
190   const auto &STI = MF->getSubtarget<LoongArchSubtarget>();
191   bool EnableRelax = STI.hasFeature(LoongArch::FeatureRelax);
192 
193   Register DestReg = MI.getOperand(0).getReg();
194   Register ScratchReg =
195       MF->getRegInfo().createVirtualRegister(&LoongArch::GPRRegClass);
196   MachineOperand &Symbol = MI.getOperand(1);
197 
198   BuildMI(MBB, MBBI, DL, TII->get(LoongArch::PCALAU12I), ScratchReg)
199       .addDisp(Symbol, 0, LoongArchII::encodeFlags(FlagsHi, EnableRelax));
200 
201   MachineInstr *SecondMI =
202       BuildMI(MBB, MBBI, DL, TII->get(SecondOpcode), DestReg)
203           .addReg(ScratchReg)
204           .addDisp(Symbol, 0, LoongArchII::encodeFlags(FlagsLo, EnableRelax));
205 
206   if (MI.hasOneMemOperand())
207     SecondMI->addMemOperand(*MF, *MI.memoperands_begin());
208 
209   MI.eraseFromParent();
210   return true;
211 }
212 
213 bool LoongArchPreRAExpandPseudo::expandLargeAddressLoad(
214     MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
215     MachineBasicBlock::iterator &NextMBBI, unsigned LastOpcode,
216     unsigned IdentifyingMO) {
217   MachineInstr &MI = *MBBI;
218   return expandLargeAddressLoad(MBB, MBBI, NextMBBI, LastOpcode, IdentifyingMO,
219                                 MI.getOperand(2), MI.getOperand(0).getReg(),
220                                 true);
221 }
222 
223 bool LoongArchPreRAExpandPseudo::expandLargeAddressLoad(
224     MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
225     MachineBasicBlock::iterator &NextMBBI, unsigned LastOpcode,
226     unsigned IdentifyingMO, const MachineOperand &Symbol, Register DestReg,
227     bool EraseFromParent) {
228   // Code Sequence:
229   //
230   // Part1: pcalau12i  $scratch, %MO1(sym)
231   // Part0: addi.d     $dest, $zero, %MO0(sym)
232   // Part2: lu32i.d    $dest, %MO2(sym)
233   // Part3: lu52i.d    $dest, $dest, %MO3(sym)
234   // Fin:   LastOpcode $dest, $dest, $scratch
235 
236   unsigned MO0, MO1, MO2, MO3;
237   switch (IdentifyingMO) {
238   default:
239     llvm_unreachable("unsupported identifying MO");
240   case LoongArchII::MO_PCREL_LO:
241     MO0 = IdentifyingMO;
242     MO1 = LoongArchII::MO_PCREL_HI;
243     MO2 = LoongArchII::MO_PCREL64_LO;
244     MO3 = LoongArchII::MO_PCREL64_HI;
245     break;
246   case LoongArchII::MO_GOT_PC_HI:
247   case LoongArchII::MO_LD_PC_HI:
248   case LoongArchII::MO_GD_PC_HI:
249     // These cases relocate just like the GOT case, except for Part1.
250     MO0 = LoongArchII::MO_GOT_PC_LO;
251     MO1 = IdentifyingMO;
252     MO2 = LoongArchII::MO_GOT_PC64_LO;
253     MO3 = LoongArchII::MO_GOT_PC64_HI;
254     break;
255   case LoongArchII::MO_IE_PC_LO:
256     MO0 = IdentifyingMO;
257     MO1 = LoongArchII::MO_IE_PC_HI;
258     MO2 = LoongArchII::MO_IE_PC64_LO;
259     MO3 = LoongArchII::MO_IE_PC64_HI;
260     break;
261   }
262 
263   MachineFunction *MF = MBB.getParent();
264   MachineInstr &MI = *MBBI;
265   DebugLoc DL = MI.getDebugLoc();
266 
267   assert(MF->getSubtarget<LoongArchSubtarget>().is64Bit() &&
268          "Large code model requires LA64");
269 
270   Register TmpPart1 =
271       MF->getRegInfo().createVirtualRegister(&LoongArch::GPRRegClass);
272   Register TmpPart0 =
273       DestReg.isVirtual()
274           ? MF->getRegInfo().createVirtualRegister(&LoongArch::GPRRegClass)
275           : DestReg;
276   Register TmpParts02 =
277       DestReg.isVirtual()
278           ? MF->getRegInfo().createVirtualRegister(&LoongArch::GPRRegClass)
279           : DestReg;
280   Register TmpParts023 =
281       DestReg.isVirtual()
282           ? MF->getRegInfo().createVirtualRegister(&LoongArch::GPRRegClass)
283           : DestReg;
284 
285   auto Part1 = BuildMI(MBB, MBBI, DL, TII->get(LoongArch::PCALAU12I), TmpPart1);
286   auto Part0 = BuildMI(MBB, MBBI, DL, TII->get(LoongArch::ADDI_D), TmpPart0)
287                    .addReg(LoongArch::R0);
288   auto Part2 = BuildMI(MBB, MBBI, DL, TII->get(LoongArch::LU32I_D), TmpParts02)
289                    // "rj" is needed due to InstrInfo pattern requirement.
290                    .addReg(TmpPart0, RegState::Kill);
291   auto Part3 = BuildMI(MBB, MBBI, DL, TII->get(LoongArch::LU52I_D), TmpParts023)
292                    .addReg(TmpParts02, RegState::Kill);
293   BuildMI(MBB, MBBI, DL, TII->get(LastOpcode), DestReg)
294       .addReg(TmpParts023)
295       .addReg(TmpPart1, RegState::Kill);
296 
297   if (Symbol.getType() == MachineOperand::MO_ExternalSymbol) {
298     const char *SymName = Symbol.getSymbolName();
299     Part0.addExternalSymbol(SymName, MO0);
300     Part1.addExternalSymbol(SymName, MO1);
301     Part2.addExternalSymbol(SymName, MO2);
302     Part3.addExternalSymbol(SymName, MO3);
303   } else {
304     Part0.addDisp(Symbol, 0, MO0);
305     Part1.addDisp(Symbol, 0, MO1);
306     Part2.addDisp(Symbol, 0, MO2);
307     Part3.addDisp(Symbol, 0, MO3);
308   }
309 
310   if (EraseFromParent)
311     MI.eraseFromParent();
312 
313   return true;
314 }
315 
316 bool LoongArchPreRAExpandPseudo::expandLoadAddressPcrel(
317     MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
318     MachineBasicBlock::iterator &NextMBBI, bool Large) {
319   if (Large)
320     // Emit the 5-insn large address load sequence with the `%pc` family of
321     // relocs.
322     return expandLargeAddressLoad(MBB, MBBI, NextMBBI, LoongArch::ADD_D,
323                                   LoongArchII::MO_PCREL_LO);
324 
325   // Code Sequence:
326   // pcalau12i $rd, %pc_hi20(sym)
327   // addi.w/d $rd, $rd, %pc_lo12(sym)
328   MachineFunction *MF = MBB.getParent();
329   const auto &STI = MF->getSubtarget<LoongArchSubtarget>();
330   unsigned SecondOpcode = STI.is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W;
331   return expandPcalau12iInstPair(MBB, MBBI, NextMBBI, LoongArchII::MO_PCREL_HI,
332                                  SecondOpcode, LoongArchII::MO_PCREL_LO);
333 }
334 
335 bool LoongArchPreRAExpandPseudo::expandLoadAddressGot(
336     MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
337     MachineBasicBlock::iterator &NextMBBI, bool Large) {
338   if (Large)
339     // Emit the 5-insn large address load sequence with the `%got_pc` family
340     // of relocs, loading the result from GOT with `ldx.d` in the end.
341     return expandLargeAddressLoad(MBB, MBBI, NextMBBI, LoongArch::LDX_D,
342                                   LoongArchII::MO_GOT_PC_HI);
343 
344   // Code Sequence:
345   // pcalau12i $rd, %got_pc_hi20(sym)
346   // ld.w/d $rd, $rd, %got_pc_lo12(sym)
347   MachineFunction *MF = MBB.getParent();
348   const auto &STI = MF->getSubtarget<LoongArchSubtarget>();
349   unsigned SecondOpcode = STI.is64Bit() ? LoongArch::LD_D : LoongArch::LD_W;
350   return expandPcalau12iInstPair(MBB, MBBI, NextMBBI, LoongArchII::MO_GOT_PC_HI,
351                                  SecondOpcode, LoongArchII::MO_GOT_PC_LO);
352 }
353 
354 bool LoongArchPreRAExpandPseudo::expandLoadAddressTLSLE(
355     MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
356     MachineBasicBlock::iterator &NextMBBI) {
357   // Code Sequence:
358   // lu12i.w $rd, %le_hi20_r(sym)
359   // add.w/d $rd, $rd, $tp, %le_add_r(sym)
360   // addi.w/d $rd, $rd, %le_lo12_r(sym)
361   //
362   // Code Sequence while using the large code model:
363   // lu12i.w $rd, %le_hi20(sym)
364   // ori $rd, $rd, %le_lo12(sym)
365   // lu32i.d $rd, %le64_lo20(sym)
366   // lu52i.d $rd, $rd, %le64_hi12(sym)
367   MachineFunction *MF = MBB.getParent();
368   MachineInstr &MI = *MBBI;
369   DebugLoc DL = MI.getDebugLoc();
370 
371   bool Large = MF->getTarget().getCodeModel() == CodeModel::Large;
372   Register DestReg = MI.getOperand(0).getReg();
373   Register Parts01 =
374       MF->getRegInfo().createVirtualRegister(&LoongArch::GPRRegClass);
375   Register Part1 =
376       MF->getRegInfo().createVirtualRegister(&LoongArch::GPRRegClass);
377   MachineOperand &Symbol = MI.getOperand(1);
378 
379   if (!Large) {
380     BuildMI(MBB, MBBI, DL, TII->get(LoongArch::LU12I_W), Part1)
381         .addDisp(Symbol, 0, LoongArchII::MO_LE_HI_R);
382 
383     const auto &STI = MF->getSubtarget<LoongArchSubtarget>();
384     unsigned AddOp = STI.is64Bit() ? LoongArch::PseudoAddTPRel_D
385                                    : LoongArch::PseudoAddTPRel_W;
386     BuildMI(MBB, MBBI, DL, TII->get(AddOp), Parts01)
387         .addReg(Part1, RegState::Kill)
388         .addReg(LoongArch::R2)
389         .addDisp(Symbol, 0, LoongArchII::MO_LE_ADD_R);
390 
391     unsigned AddiOp = STI.is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W;
392     BuildMI(MBB, MBBI, DL, TII->get(AddiOp), DestReg)
393         .addReg(Parts01, RegState::Kill)
394         .addDisp(Symbol, 0, LoongArchII::MO_LE_LO_R);
395   } else {
396     BuildMI(MBB, MBBI, DL, TII->get(LoongArch::LU12I_W), Part1)
397         .addDisp(Symbol, 0, LoongArchII::MO_LE_HI);
398 
399     BuildMI(MBB, MBBI, DL, TII->get(LoongArch::ORI), Parts01)
400         .addReg(Part1, RegState::Kill)
401         .addDisp(Symbol, 0, LoongArchII::MO_LE_LO);
402 
403     Register Parts012 =
404         MF->getRegInfo().createVirtualRegister(&LoongArch::GPRRegClass);
405 
406     BuildMI(MBB, MBBI, DL, TII->get(LoongArch::LU32I_D), Parts012)
407         // "rj" is needed due to InstrInfo pattern requirement.
408         .addReg(Parts01, RegState::Kill)
409         .addDisp(Symbol, 0, LoongArchII::MO_LE64_LO);
410     BuildMI(MBB, MBBI, DL, TII->get(LoongArch::LU52I_D), DestReg)
411         .addReg(Parts012, RegState::Kill)
412         .addDisp(Symbol, 0, LoongArchII::MO_LE64_HI);
413   }
414 
415   MI.eraseFromParent();
416   return true;
417 }
418 
419 bool LoongArchPreRAExpandPseudo::expandLoadAddressTLSIE(
420     MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
421     MachineBasicBlock::iterator &NextMBBI, bool Large) {
422   if (Large)
423     // Emit the 5-insn large address load sequence with the `%ie_pc` family
424     // of relocs, loading the result with `ldx.d` in the end.
425     return expandLargeAddressLoad(MBB, MBBI, NextMBBI, LoongArch::LDX_D,
426                                   LoongArchII::MO_IE_PC_LO);
427 
428   // Code Sequence:
429   // pcalau12i $rd, %ie_pc_hi20(sym)
430   // ld.w/d $rd, $rd, %ie_pc_lo12(sym)
431   MachineFunction *MF = MBB.getParent();
432   const auto &STI = MF->getSubtarget<LoongArchSubtarget>();
433   unsigned SecondOpcode = STI.is64Bit() ? LoongArch::LD_D : LoongArch::LD_W;
434   return expandPcalau12iInstPair(MBB, MBBI, NextMBBI, LoongArchII::MO_IE_PC_HI,
435                                  SecondOpcode, LoongArchII::MO_IE_PC_LO);
436 }
437 
438 bool LoongArchPreRAExpandPseudo::expandLoadAddressTLSLD(
439     MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
440     MachineBasicBlock::iterator &NextMBBI, bool Large) {
441   if (Large)
442     // Emit the 5-insn large address load sequence with the `%got_pc` family
443     // of relocs, with the `pcalau12i` insn relocated with `%ld_pc_hi20`.
444     return expandLargeAddressLoad(MBB, MBBI, NextMBBI, LoongArch::ADD_D,
445                                   LoongArchII::MO_LD_PC_HI);
446 
447   // Code Sequence:
448   // pcalau12i $rd, %ld_pc_hi20(sym)
449   // addi.w/d $rd, $rd, %got_pc_lo12(sym)
450   MachineFunction *MF = MBB.getParent();
451   const auto &STI = MF->getSubtarget<LoongArchSubtarget>();
452   unsigned SecondOpcode = STI.is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W;
453   return expandPcalau12iInstPair(MBB, MBBI, NextMBBI, LoongArchII::MO_LD_PC_HI,
454                                  SecondOpcode, LoongArchII::MO_GOT_PC_LO);
455 }
456 
457 bool LoongArchPreRAExpandPseudo::expandLoadAddressTLSGD(
458     MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
459     MachineBasicBlock::iterator &NextMBBI, bool Large) {
460   if (Large)
461     // Emit the 5-insn large address load sequence with the `%got_pc` family
462     // of relocs, with the `pcalau12i` insn relocated with `%gd_pc_hi20`.
463     return expandLargeAddressLoad(MBB, MBBI, NextMBBI, LoongArch::ADD_D,
464                                   LoongArchII::MO_GD_PC_HI);
465 
466   // Code Sequence:
467   // pcalau12i $rd, %gd_pc_hi20(sym)
468   // addi.w/d $rd, $rd, %got_pc_lo12(sym)
469   MachineFunction *MF = MBB.getParent();
470   const auto &STI = MF->getSubtarget<LoongArchSubtarget>();
471   unsigned SecondOpcode = STI.is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W;
472   return expandPcalau12iInstPair(MBB, MBBI, NextMBBI, LoongArchII::MO_GD_PC_HI,
473                                  SecondOpcode, LoongArchII::MO_GOT_PC_LO);
474 }
475 
476 bool LoongArchPreRAExpandPseudo::expandLoadAddressTLSDesc(
477     MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
478     MachineBasicBlock::iterator &NextMBBI, bool Large) {
479   MachineFunction *MF = MBB.getParent();
480   MachineInstr &MI = *MBBI;
481   DebugLoc DL = MI.getDebugLoc();
482 
483   const auto &STI = MF->getSubtarget<LoongArchSubtarget>();
484   unsigned ADD = STI.is64Bit() ? LoongArch::ADD_D : LoongArch::ADD_W;
485   unsigned ADDI = STI.is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W;
486   unsigned LD = STI.is64Bit() ? LoongArch::LD_D : LoongArch::LD_W;
487   bool EnableRelax = STI.hasFeature(LoongArch::FeatureRelax);
488 
489   Register DestReg = MI.getOperand(0).getReg();
490   Register Tmp1Reg =
491       MF->getRegInfo().createVirtualRegister(&LoongArch::GPRRegClass);
492   MachineOperand &Symbol = MI.getOperand(Large ? 2 : 1);
493 
494   BuildMI(MBB, MBBI, DL, TII->get(LoongArch::PCALAU12I), Tmp1Reg)
495       .addDisp(Symbol, 0,
496                LoongArchII::encodeFlags(LoongArchII::MO_DESC_PC_HI,
497                                         EnableRelax && !Large));
498 
499   if (Large) {
500     // Code Sequence:
501     //
502     // pcalau12i  $a0, %desc_pc_hi20(sym)
503     // addi.d     $a1, $zero, %desc_pc_lo12(sym)
504     // lu32i.d    $a1, %desc64_pc_lo20(sym)
505     // lu52i.d    $a1, $a1, %desc64_pc_hi12(sym)
506     // add.d      $a0, $a0, $a1
507     // ld.d       $ra, $a0, %desc_ld(sym)
508     // jirl       $ra, $ra, %desc_call(sym)
509     // add.d      $dst, $a0, $tp
510     assert(MBB.getParent()->getSubtarget<LoongArchSubtarget>().is64Bit() &&
511            "Large code model requires LA64");
512     Register Tmp2Reg =
513         MF->getRegInfo().createVirtualRegister(&LoongArch::GPRRegClass);
514     Register Tmp3Reg =
515         MF->getRegInfo().createVirtualRegister(&LoongArch::GPRRegClass);
516     Register Tmp4Reg =
517         MF->getRegInfo().createVirtualRegister(&LoongArch::GPRRegClass);
518     BuildMI(MBB, MBBI, DL, TII->get(LoongArch::ADDI_D), Tmp2Reg)
519         .addReg(LoongArch::R0)
520         .addDisp(Symbol, 0, LoongArchII::MO_DESC_PC_LO);
521     BuildMI(MBB, MBBI, DL, TII->get(LoongArch::LU32I_D), Tmp3Reg)
522         .addReg(Tmp2Reg, RegState::Kill)
523         .addDisp(Symbol, 0, LoongArchII::MO_DESC64_PC_LO);
524     BuildMI(MBB, MBBI, DL, TII->get(LoongArch::LU52I_D), Tmp4Reg)
525         .addReg(Tmp3Reg)
526         .addDisp(Symbol, 0, LoongArchII::MO_DESC64_PC_HI);
527     BuildMI(MBB, MBBI, DL, TII->get(LoongArch::ADD_D), LoongArch::R4)
528         .addReg(Tmp1Reg)
529         .addReg(Tmp4Reg);
530   } else {
531     // Code Sequence:
532     // pcalau12i $a0, %desc_pc_hi20(sym)
533     // addi.w/d  $a0, $a0, %desc_pc_lo12(sym)
534     // ld.w/d    $ra, $a0, %desc_ld(sym)
535     // jirl      $ra, $ra, %desc_call(sym)
536     // add.w/d   $dst, $a0, $tp
537     BuildMI(MBB, MBBI, DL, TII->get(ADDI), LoongArch::R4)
538         .addReg(Tmp1Reg)
539         .addDisp(
540             Symbol, 0,
541             LoongArchII::encodeFlags(LoongArchII::MO_DESC_PC_LO, EnableRelax));
542   }
543 
544   BuildMI(MBB, MBBI, DL, TII->get(LD), LoongArch::R1)
545       .addReg(LoongArch::R4)
546       .addDisp(Symbol, 0,
547                LoongArchII::encodeFlags(LoongArchII::MO_DESC_LD,
548                                         EnableRelax && !Large));
549   BuildMI(MBB, MBBI, DL, TII->get(LoongArch::PseudoDESC_CALL), LoongArch::R1)
550       .addReg(LoongArch::R1)
551       .addDisp(Symbol, 0,
552                LoongArchII::encodeFlags(LoongArchII::MO_DESC_CALL,
553                                         EnableRelax && !Large));
554   BuildMI(MBB, MBBI, DL, TII->get(ADD), DestReg)
555       .addReg(LoongArch::R4)
556       .addReg(LoongArch::R2);
557 
558   MI.eraseFromParent();
559   return true;
560 }
561 
562 bool LoongArchPreRAExpandPseudo::expandFunctionCALL(
563     MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
564     MachineBasicBlock::iterator &NextMBBI, bool IsTailCall) {
565   MachineFunction *MF = MBB.getParent();
566   MachineInstr &MI = *MBBI;
567   DebugLoc DL = MI.getDebugLoc();
568   const MachineOperand &Func = MI.getOperand(0);
569   MachineInstrBuilder CALL;
570   unsigned Opcode;
571 
572   switch (MF->getTarget().getCodeModel()) {
573   default:
574     report_fatal_error("Unexpected code model");
575     break;
576   case CodeModel::Small: {
577     // CALL:
578     // bl func
579     // TAIL:
580     // b func
581     Opcode = IsTailCall ? LoongArch::PseudoB_TAIL : LoongArch::BL;
582     CALL = BuildMI(MBB, MBBI, DL, TII->get(Opcode)).add(Func);
583     break;
584   }
585   case CodeModel::Large: {
586     // Emit the 5-insn large address load sequence, either directly or
587     // indirectly in case of going through the GOT, then JIRL_TAIL or
588     // JIRL_CALL to $addr.
589     Opcode =
590         IsTailCall ? LoongArch::PseudoJIRL_TAIL : LoongArch::PseudoJIRL_CALL;
591     Register AddrReg =
592         IsTailCall
593             ? MF->getRegInfo().createVirtualRegister(&LoongArch::GPRRegClass)
594             : LoongArch::R1;
595 
596     bool UseGOT = Func.getTargetFlags() == LoongArchII::MO_CALL_PLT;
597     unsigned MO = UseGOT ? LoongArchII::MO_GOT_PC_HI : LoongArchII::MO_PCREL_LO;
598     unsigned LAOpcode = UseGOT ? LoongArch::LDX_D : LoongArch::ADD_D;
599     expandLargeAddressLoad(MBB, MBBI, NextMBBI, LAOpcode, MO, Func, AddrReg,
600                            false);
601     CALL = BuildMI(MBB, MBBI, DL, TII->get(Opcode)).addReg(AddrReg).addImm(0);
602     break;
603   }
604   }
605 
606   // Transfer implicit operands.
607   CALL.copyImplicitOps(MI);
608 
609   // Transfer MI flags.
610   CALL.setMIFlags(MI.getFlags());
611 
612   MI.eraseFromParent();
613   return true;
614 }
615 
616 void LoongArchPreRAExpandPseudo::annotateTableJump(
617     MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI) {
618   MachineFunction *MF = MBB.getParent();
619   MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
620 
621   bool IsFound = false;
622 
623   std::function<void(MachineInstr *, int)> FindJTIMI = [&](MachineInstr *MInst,
624                                                            int FindDepth) {
625     if (FindDepth < 0)
626       return;
627     for (auto &MO : MInst->all_uses()) {
628       if (IsFound)
629         return;
630       Register Reg = MO.getReg();
631       if (!Reg.isVirtual())
632         continue;
633       MachineInstr *DefMI = MRI.getVRegDef(Reg);
634       if (!DefMI)
635         continue;
636       for (unsigned Idx = 0; Idx < DefMI->getNumOperands(); ++Idx) {
637         MachineOperand &MO = DefMI->getOperand(Idx);
638         if (MO.isJTI()) {
639           MBBI->setPreInstrSymbol(
640               *MF, MF->getContext().createNamedTempSymbol("jrtb_"));
641           MF->getInfo<LoongArchMachineFunctionInfo>()->setJumpInfo(&*MBBI, &MO);
642           IsFound = true;
643           return;
644         }
645       }
646       FindJTIMI(DefMI, --FindDepth);
647     }
648   };
649 
650   // FindDepth = 3, probably sufficient.
651   FindJTIMI(&*MBBI, /*FindDepth=*/3);
652 }
653 
654 class LoongArchExpandPseudo : public MachineFunctionPass {
655 public:
656   const LoongArchInstrInfo *TII;
657   static char ID;
658 
659   LoongArchExpandPseudo() : MachineFunctionPass(ID) {
660     initializeLoongArchExpandPseudoPass(*PassRegistry::getPassRegistry());
661   }
662 
663   bool runOnMachineFunction(MachineFunction &MF) override;
664 
665   StringRef getPassName() const override {
666     return LOONGARCH_EXPAND_PSEUDO_NAME;
667   }
668 
669 private:
670   bool expandMBB(MachineBasicBlock &MBB);
671   bool expandMI(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
672                 MachineBasicBlock::iterator &NextMBBI);
673   bool expandCopyCFR(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
674                      MachineBasicBlock::iterator &NextMBBI);
675   bool expandFunctionCALL(MachineBasicBlock &MBB,
676                           MachineBasicBlock::iterator MBBI,
677                           MachineBasicBlock::iterator &NextMBBI,
678                           bool IsTailCall);
679 };
680 
681 char LoongArchExpandPseudo::ID = 0;
682 
683 bool LoongArchExpandPseudo::runOnMachineFunction(MachineFunction &MF) {
684   TII =
685       static_cast<const LoongArchInstrInfo *>(MF.getSubtarget().getInstrInfo());
686 
687   bool Modified = false;
688   for (auto &MBB : MF)
689     Modified |= expandMBB(MBB);
690 
691   return Modified;
692 }
693 
694 bool LoongArchExpandPseudo::expandMBB(MachineBasicBlock &MBB) {
695   bool Modified = false;
696 
697   MachineBasicBlock::iterator MBBI = MBB.begin(), E = MBB.end();
698   while (MBBI != E) {
699     MachineBasicBlock::iterator NMBBI = std::next(MBBI);
700     Modified |= expandMI(MBB, MBBI, NMBBI);
701     MBBI = NMBBI;
702   }
703 
704   return Modified;
705 }
706 
707 bool LoongArchExpandPseudo::expandMI(MachineBasicBlock &MBB,
708                                      MachineBasicBlock::iterator MBBI,
709                                      MachineBasicBlock::iterator &NextMBBI) {
710   switch (MBBI->getOpcode()) {
711   case LoongArch::PseudoCopyCFR:
712     return expandCopyCFR(MBB, MBBI, NextMBBI);
713   case LoongArch::PseudoCALL_MEDIUM:
714     return expandFunctionCALL(MBB, MBBI, NextMBBI, /*IsTailCall=*/false);
715   case LoongArch::PseudoTAIL_MEDIUM:
716     return expandFunctionCALL(MBB, MBBI, NextMBBI, /*IsTailCall=*/true);
717   }
718 
719   return false;
720 }
721 
722 bool LoongArchExpandPseudo::expandCopyCFR(
723     MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
724     MachineBasicBlock::iterator &NextMBBI) {
725   MachineFunction *MF = MBB.getParent();
726   MachineInstr &MI = *MBBI;
727   DebugLoc DL = MI.getDebugLoc();
728 
729   // Expand:
730   // MBB:
731   //    fcmp.caf.s  $dst, $fa0, $fa0 # set $dst 0(false)
732   //    bceqz $src, SinkBB
733   // FalseBB:
734   //    fcmp.cueq.s $dst, $fa0, $fa0 # set $dst 1(true)
735   // SinkBB:
736   //    fallthrough
737 
738   const BasicBlock *LLVM_BB = MBB.getBasicBlock();
739   auto *FalseBB = MF->CreateMachineBasicBlock(LLVM_BB);
740   auto *SinkBB = MF->CreateMachineBasicBlock(LLVM_BB);
741 
742   MF->insert(++MBB.getIterator(), FalseBB);
743   MF->insert(++FalseBB->getIterator(), SinkBB);
744 
745   Register DestReg = MI.getOperand(0).getReg();
746   Register SrcReg = MI.getOperand(1).getReg();
747   // DestReg = 0
748   BuildMI(MBB, MBBI, DL, TII->get(LoongArch::SET_CFR_FALSE), DestReg);
749   // Insert branch instruction.
750   BuildMI(MBB, MBBI, DL, TII->get(LoongArch::BCEQZ))
751       .addReg(SrcReg)
752       .addMBB(SinkBB);
753   // DestReg = 1
754   BuildMI(FalseBB, DL, TII->get(LoongArch::SET_CFR_TRUE), DestReg);
755 
756   FalseBB->addSuccessor(SinkBB);
757 
758   SinkBB->splice(SinkBB->end(), &MBB, MI, MBB.end());
759   SinkBB->transferSuccessors(&MBB);
760 
761   MBB.addSuccessor(FalseBB);
762   MBB.addSuccessor(SinkBB);
763 
764   NextMBBI = MBB.end();
765   MI.eraseFromParent();
766 
767   // Make sure live-ins are correctly attached to this new basic block.
768   LivePhysRegs LiveRegs;
769   computeAndAddLiveIns(LiveRegs, *FalseBB);
770   computeAndAddLiveIns(LiveRegs, *SinkBB);
771 
772   return true;
773 }
774 
775 bool LoongArchExpandPseudo::expandFunctionCALL(
776     MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
777     MachineBasicBlock::iterator &NextMBBI, bool IsTailCall) {
778   MachineFunction *MF = MBB.getParent();
779   MachineInstr &MI = *MBBI;
780   DebugLoc DL = MI.getDebugLoc();
781   const MachineOperand &Func = MI.getOperand(0);
782   MachineInstrBuilder CALL;
783   unsigned Opcode;
784 
785   switch (MF->getTarget().getCodeModel()) {
786   default:
787     report_fatal_error("Unexpected code model");
788     break;
789   case CodeModel::Medium: {
790     // CALL:
791     // pcaddu18i $ra, %call36(func)
792     // jirl      $ra, $ra, 0
793     // TAIL:
794     // pcaddu18i $t8, %call36(func)
795     // jirl      $r0, $t8, 0
796     Opcode =
797         IsTailCall ? LoongArch::PseudoJIRL_TAIL : LoongArch::PseudoJIRL_CALL;
798     Register ScratchReg = IsTailCall ? LoongArch::R20 : LoongArch::R1;
799     MachineInstrBuilder MIB =
800         BuildMI(MBB, MBBI, DL, TII->get(LoongArch::PCADDU18I), ScratchReg);
801 
802     CALL =
803         BuildMI(MBB, MBBI, DL, TII->get(Opcode)).addReg(ScratchReg).addImm(0);
804 
805     if (Func.isSymbol())
806       MIB.addExternalSymbol(Func.getSymbolName(), LoongArchII::MO_CALL36);
807     else
808       MIB.addDisp(Func, 0, LoongArchII::MO_CALL36);
809     break;
810   }
811   }
812 
813   // Transfer implicit operands.
814   CALL.copyImplicitOps(MI);
815 
816   // Transfer MI flags.
817   CALL.setMIFlags(MI.getFlags());
818 
819   MI.eraseFromParent();
820   return true;
821 }
822 
823 } // end namespace
824 
825 INITIALIZE_PASS(LoongArchPreRAExpandPseudo, "loongarch-prera-expand-pseudo",
826                 LOONGARCH_PRERA_EXPAND_PSEUDO_NAME, false, false)
827 
828 INITIALIZE_PASS(LoongArchExpandPseudo, "loongarch-expand-pseudo",
829                 LOONGARCH_EXPAND_PSEUDO_NAME, false, false)
830 
831 namespace llvm {
832 
833 FunctionPass *createLoongArchPreRAExpandPseudoPass() {
834   return new LoongArchPreRAExpandPseudo();
835 }
836 FunctionPass *createLoongArchExpandPseudoPass() {
837   return new LoongArchExpandPseudo();
838 }
839 
840 } // end namespace llvm
841