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