LLVM 19.0.0git
LoongArchExpandPseudoInsts.cpp
Go to the documentation of this file.
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"
24#include "llvm/MC/MCContext.h"
27
28using 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
35namespace {
36
37class LoongArchPreRAExpandPseudo : public MachineFunctionPass {
38public:
40 static char ID;
41
42 LoongArchPreRAExpandPseudo() : MachineFunctionPass(ID) {
44 }
45
46 bool runOnMachineFunction(MachineFunction &MF) override;
47
48 void getAnalysisUsage(AnalysisUsage &AU) const override {
49 AU.setPreservesCFG();
51 }
52 StringRef getPassName() const override {
54 }
55
56private:
57 bool expandMBB(MachineBasicBlock &MBB);
60 bool expandPcalau12iInstPair(MachineBasicBlock &MBB,
63 unsigned FlagsHi, unsigned SecondOpcode,
64 unsigned FlagsLo);
65 bool expandLoadAddressPcrel(MachineBasicBlock &MBB,
68 bool expandLoadAddressGot(MachineBasicBlock &MBB,
71 bool expandLoadAddressTLSLE(MachineBasicBlock &MBB,
74 bool expandLoadAddressTLSIE(MachineBasicBlock &MBB,
77 bool expandLoadAddressTLSLD(MachineBasicBlock &MBB,
80 bool expandLoadAddressTLSGD(MachineBasicBlock &MBB,
83 bool expandLoadAddressTLSDesc(MachineBasicBlock &MBB,
86};
87
88char LoongArchPreRAExpandPseudo::ID = 0;
89
90bool 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
99bool LoongArchPreRAExpandPseudo::expandMBB(MachineBasicBlock &MBB) {
100 bool Modified = false;
101
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
112bool LoongArchPreRAExpandPseudo::expandMI(
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
134bool LoongArchPreRAExpandPseudo::expandPcalau12iInstPair(
136 MachineBasicBlock::iterator &NextMBBI, unsigned FlagsHi,
137 unsigned SecondOpcode, unsigned FlagsLo) {
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
162bool LoongArchPreRAExpandPseudo::expandLoadAddressPcrel(
164 MachineBasicBlock::iterator &NextMBBI) {
165 // Code Sequence:
166 // pcalau12i $rd, %pc_hi20(sym)
167 // addi.w/d $rd, $rd, %pc_lo12(sym)
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
175bool LoongArchPreRAExpandPseudo::expandLoadAddressGot(
177 MachineBasicBlock::iterator &NextMBBI) {
178 // Code Sequence:
179 // pcalau12i $rd, %got_pc_hi20(sym)
180 // ld.w/d $rd, $rd, %got_pc_lo12(sym)
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
188bool LoongArchPreRAExpandPseudo::expandLoadAddressTLSLE(
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)
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
236bool LoongArchPreRAExpandPseudo::expandLoadAddressTLSIE(
238 MachineBasicBlock::iterator &NextMBBI) {
239 // Code Sequence:
240 // pcalau12i $rd, %ie_pc_hi20(sym)
241 // ld.w/d $rd, $rd, %ie_pc_lo12(sym)
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
249bool LoongArchPreRAExpandPseudo::expandLoadAddressTLSLD(
251 MachineBasicBlock::iterator &NextMBBI) {
252 // Code Sequence:
253 // pcalau12i $rd, %ld_pc_hi20(sym)
254 // addi.w/d $rd, $rd, %got_pc_lo12(sym)
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
262bool LoongArchPreRAExpandPseudo::expandLoadAddressTLSGD(
264 MachineBasicBlock::iterator &NextMBBI) {
265 // Code Sequence:
266 // pcalau12i $rd, %gd_pc_hi20(sym)
267 // addi.w/d $rd, $rd, %got_pc_lo12(sym)
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
275bool LoongArchPreRAExpandPseudo::expandLoadAddressTLSDesc(
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
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)
300
301 BuildMI(MBB, MBBI, DL, TII->get(ADDI), LoongArch::R4)
302 .addReg(ScratchReg)
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)
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
321class LoongArchExpandPseudo : public MachineFunctionPass {
322public:
323 const LoongArchInstrInfo *TII;
324 static char ID;
325
326 LoongArchExpandPseudo() : MachineFunctionPass(ID) {
328 }
329
330 bool runOnMachineFunction(MachineFunction &MF) override;
331
332 StringRef getPassName() const override {
334 }
335
336private:
337 bool expandMBB(MachineBasicBlock &MBB);
342 bool expandLargeAddressLoad(MachineBasicBlock &MBB,
345 unsigned LastOpcode, unsigned IdentifyingMO);
346 bool expandLargeAddressLoad(MachineBasicBlock &MBB,
349 unsigned LastOpcode, unsigned IdentifyingMO,
350 const MachineOperand &Symbol, Register DestReg,
351 bool EraseFromParent);
352 bool expandLoadAddressPcrelLarge(MachineBasicBlock &MBB,
355 bool expandLoadAddressGotLarge(MachineBasicBlock &MBB,
358 bool expandLoadAddressTLSIELarge(MachineBasicBlock &MBB,
361 bool expandLoadAddressTLSLDLarge(MachineBasicBlock &MBB,
364 bool expandLoadAddressTLSGDLarge(MachineBasicBlock &MBB,
367 bool expandLoadAddressTLSDescPcLarge(MachineBasicBlock &MBB,
370 bool expandFunctionCALL(MachineBasicBlock &MBB,
373 bool IsTailCall);
374};
375
376char LoongArchExpandPseudo::ID = 0;
377
378bool 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
389bool LoongArchExpandPseudo::expandMBB(MachineBasicBlock &MBB) {
390 bool Modified = false;
391
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
402bool LoongArchExpandPseudo::expandMI(MachineBasicBlock &MBB,
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
433bool LoongArchExpandPseudo::expandCopyCFR(
435 MachineBasicBlock::iterator &NextMBBI) {
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
486bool LoongArchExpandPseudo::expandLargeAddressLoad(
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
496bool LoongArchExpandPseudo::expandLargeAddressLoad(
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");
514 MO0 = IdentifyingMO;
518 break;
522 // These cases relocate just like the GOT case, except for Part1.
524 MO1 = IdentifyingMO;
527 break;
529 MO0 = IdentifyingMO;
533 break;
534 }
535
536 MachineInstr &MI = *MBBI;
537 DebugLoc DL = MI.getDebugLoc();
538 Register ScratchReg = LoongArch::R20; // $t8
539
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
574bool LoongArchExpandPseudo::expandLoadAddressPcrelLarge(
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,
581}
582
583bool LoongArchExpandPseudo::expandLoadAddressGotLarge(
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,
590}
591
592bool LoongArchExpandPseudo::expandLoadAddressTLSIELarge(
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,
599}
600
601bool LoongArchExpandPseudo::expandLoadAddressTLSLDLarge(
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,
608}
609
610bool LoongArchExpandPseudo::expandLoadAddressTLSGDLarge(
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,
617}
618
619bool LoongArchExpandPseudo::expandLoadAddressTLSDescPcLarge(
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
640 "Large code model requires LA64");
641
642 BuildMI(MBB, MBBI, DL, TII->get(LoongArch::PCALAU12I), LoongArch::R4)
644 BuildMI(MBB, MBBI, DL, TII->get(LoongArch::ADDI_D), ScratchReg)
645 .addReg(LoongArch::R0)
647 BuildMI(MBB, MBBI, DL, TII->get(LoongArch::LU32I_D), ScratchReg)
648 .addReg(ScratchReg)
650 BuildMI(MBB, MBBI, DL, TII->get(LoongArch::LU52I_D), ScratchReg)
651 .addReg(ScratchReg)
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)
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
671bool LoongArchExpandPseudo::expandFunctionCALL(
673 MachineBasicBlock::iterator &NextMBBI, bool IsTailCall) {
675 MachineInstr &MI = *MBBI;
676 DebugLoc DL = MI.getDebugLoc();
677 const MachineOperand &Func = MI.getOperand(0);
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;
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.isGlobal() && !Func.getGlobal()->isDSOLocal();
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
746INITIALIZE_PASS(LoongArchPreRAExpandPseudo, "loongarch-prera-expand-pseudo",
748
749INITIALIZE_PASS(LoongArchExpandPseudo, "loongarch-expand-pseudo",
751
752namespace llvm {
753
755 return new LoongArchPreRAExpandPseudo();
756}
758 return new LoongArchExpandPseudo();
759}
760
761} // end namespace llvm
MachineBasicBlock & MBB
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
MachineBasicBlock MachineBasicBlock::iterator MBBI
static Expected< BitVector > expand(StringRef S, StringRef Original)
Definition: GlobPattern.cpp:21
const HexagonInstrInfo * TII
IRTranslator LLVM IR MI
This file implements the LivePhysRegs utility for tracking liveness of physical registers.
loongarch expand pseudo
#define LOONGARCH_PRERA_EXPAND_PSEUDO_NAME
#define LOONGARCH_EXPAND_PSEUDO_NAME
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
Definition: PassSupport.h:38
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
Represent the analysis usage information of a pass.
void setPreservesCFG()
This function should be called by the pass, iff they do not:
Definition: Pass.cpp:269
LLVM Basic Block Representation.
Definition: BasicBlock.h:60
A debug info location.
Definition: DebugLoc.h:33
FunctionPass class - This class is used to implement most global optimizations.
Definition: Pass.h:311
A set of physical registers with utility functions to track liveness when walking backward/forward th...
Definition: LivePhysRegs.h:52
const BasicBlock * getBasicBlock() const
Return the LLVM basic block that this instance corresponded to originally.
void addSuccessor(MachineBasicBlock *Succ, BranchProbability Prob=BranchProbability::getUnknown())
Add Succ as a successor of this MachineBasicBlock.
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
virtual bool runOnMachineFunction(MachineFunction &MF)=0
runOnMachineFunction - This method must be overloaded to perform the desired machine code transformat...
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
const LLVMTargetMachine & getTarget() const
getTarget - Return the target machine this machine code is compiled with
MachineBasicBlock * CreateMachineBasicBlock(const BasicBlock *BB=nullptr, std::optional< UniqueBBID > BBID=std::nullopt)
CreateMachineBasicBlock - Allocate a new MachineBasicBlock.
void insert(iterator MBBI, MachineBasicBlock *MBB)
const MachineInstrBuilder & addExternalSymbol(const char *FnName, unsigned TargetFlags=0) const
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & add(const MachineOperand &MO) const
const MachineInstrBuilder & addDisp(const MachineOperand &Disp, int64_t off, unsigned char TargetFlags=0) const
const MachineInstrBuilder & addReg(Register RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0) const
Representation of each machine instruction.
Definition: MachineInstr.h:69
void addMemOperand(MachineFunction &MF, MachineMemOperand *MO)
Add a MachineMemOperand to the machine instruction.
MachineOperand class - Representation of each machine instruction operand.
@ MO_ExternalSymbol
Name of external global symbol.
Register createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
virtual StringRef getPassName() const
getPassName - Return a nice clean name for a pass.
Definition: Pass.cpp:81
Wrapper class representing virtual and physical registers.
Definition: Register.h:19
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:50
CodeModel::Model getCodeModel() const
Returns the code model.
virtual const TargetInstrInfo * getInstrInfo() const
self_iterator getIterator()
Definition: ilist_node.h:109
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
TargetPassConfig.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition: CallingConv.h:24
@ Kill
The last use of a register.
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
void initializeLoongArchPreRAExpandPseudoPass(PassRegistry &)
void initializeLoongArchExpandPseudoPass(PassRegistry &)
void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
Definition: Error.cpp:156
FunctionPass * createLoongArchPreRAExpandPseudoPass()
FunctionPass * createLoongArchExpandPseudoPass()
void computeAndAddLiveIns(LivePhysRegs &LiveRegs, MachineBasicBlock &MBB)
Convenience function combining computeLiveIns() and addLiveIns().