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