LLVM 23.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
31
32#define LOONGARCH_PRERA_EXPAND_PSEUDO_NAME \
33 "LoongArch Pre-RA pseudo instruction expansion pass"
34#define LOONGARCH_EXPAND_PSEUDO_NAME \
35 "LoongArch pseudo instruction expansion pass"
36
37namespace {
38
39class LoongArchPreRAExpandPseudo : public MachineFunctionPass {
40public:
42 static char ID;
43
44 LoongArchPreRAExpandPseudo() : MachineFunctionPass(ID) {}
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 expandPcaxxu12iInstPair(MachineBasicBlock &MBB,
63 unsigned OpcodeHi, unsigned OpcodeLo,
64 unsigned FlagsHi, unsigned FlagsLo);
65 bool expandLargeAddressLoad(MachineBasicBlock &MBB,
68 unsigned LastOpcode, unsigned IdentifyingMO);
69 bool expandLargeAddressLoad(MachineBasicBlock &MBB,
72 unsigned LastOpcode, unsigned IdentifyingMO,
73 const MachineOperand &Symbol, Register DestReg,
74 bool EraseFromParent);
75 bool expandLoadAddressPcrel(MachineBasicBlock &MBB,
78 bool Large = false);
79 bool expandLoadAddressGot(MachineBasicBlock &MBB,
82 bool Large = false);
83 bool expandLoadAddressTLSLE(MachineBasicBlock &MBB,
86 bool expandLoadAddressTLSIE(MachineBasicBlock &MBB,
89 bool Large = false);
90 bool expandLoadAddressTLSLD(MachineBasicBlock &MBB,
93 bool Large = false);
94 bool expandLoadAddressTLSGD(MachineBasicBlock &MBB,
97 bool Large = false);
98 bool expandLoadAddressTLSDesc(MachineBasicBlock &MBB,
101 bool Large = false);
102 bool expandFunctionCALL(MachineBasicBlock &MBB,
105 bool IsTailCall);
106 void annotateTableJump(MachineBasicBlock &MBB,
108};
109
110char LoongArchPreRAExpandPseudo::ID = 0;
111
112bool LoongArchPreRAExpandPseudo::runOnMachineFunction(MachineFunction &MF) {
113 TII =
114 static_cast<const LoongArchInstrInfo *>(MF.getSubtarget().getInstrInfo());
115 bool Modified = false;
116 for (auto &MBB : MF)
117 Modified |= expandMBB(MBB);
118 return Modified;
119}
120
121bool LoongArchPreRAExpandPseudo::expandMBB(MachineBasicBlock &MBB) {
122 bool Modified = false;
123
124 MachineBasicBlock::iterator MBBI = MBB.begin(), E = MBB.end();
125 while (MBBI != E) {
126 MachineBasicBlock::iterator NMBBI = std::next(MBBI);
127 Modified |= expandMI(MBB, MBBI, NMBBI);
128 MBBI = NMBBI;
129 }
130
131 return Modified;
132}
133
134bool LoongArchPreRAExpandPseudo::expandMI(
136 MachineBasicBlock::iterator &NextMBBI) {
137 switch (MBBI->getOpcode()) {
138 case LoongArch::PseudoLA_PCREL:
139 return expandLoadAddressPcrel(MBB, MBBI, NextMBBI);
140 case LoongArch::PseudoLA_PCREL_LARGE:
141 return expandLoadAddressPcrel(MBB, MBBI, NextMBBI, /*Large=*/true);
142 case LoongArch::PseudoLA_GOT:
143 return expandLoadAddressGot(MBB, MBBI, NextMBBI);
144 case LoongArch::PseudoLA_GOT_LARGE:
145 return expandLoadAddressGot(MBB, MBBI, NextMBBI, /*Large=*/true);
146 case LoongArch::PseudoLA_TLS_LE:
147 return expandLoadAddressTLSLE(MBB, MBBI, NextMBBI);
148 case LoongArch::PseudoLA_TLS_IE:
149 return expandLoadAddressTLSIE(MBB, MBBI, NextMBBI);
150 case LoongArch::PseudoLA_TLS_IE_LARGE:
151 return expandLoadAddressTLSIE(MBB, MBBI, NextMBBI, /*Large=*/true);
152 case LoongArch::PseudoLA_TLS_LD:
153 return expandLoadAddressTLSLD(MBB, MBBI, NextMBBI);
154 case LoongArch::PseudoLA_TLS_LD_LARGE:
155 return expandLoadAddressTLSLD(MBB, MBBI, NextMBBI, /*Large=*/true);
156 case LoongArch::PseudoLA_TLS_GD:
157 return expandLoadAddressTLSGD(MBB, MBBI, NextMBBI);
158 case LoongArch::PseudoLA_TLS_GD_LARGE:
159 return expandLoadAddressTLSGD(MBB, MBBI, NextMBBI, /*Large=*/true);
160 case LoongArch::PseudoLA_TLS_DESC:
161 return expandLoadAddressTLSDesc(MBB, MBBI, NextMBBI);
162 case LoongArch::PseudoLA_TLS_DESC_LARGE:
163 return expandLoadAddressTLSDesc(MBB, MBBI, NextMBBI, /*Large=*/true);
164 case LoongArch::PseudoCALL_SMALL:
165 case LoongArch::PseudoCALL_LARGE:
166 return expandFunctionCALL(MBB, MBBI, NextMBBI, /*IsTailCall=*/false);
167 case LoongArch::PseudoTAIL_SMALL:
168 case LoongArch::PseudoTAIL_LARGE:
169 return expandFunctionCALL(MBB, MBBI, NextMBBI, /*IsTailCall=*/true);
170 case LoongArch::PseudoBRIND:
171 // If the PseudoBRIND is used to table jump, then emit a label to annotate
172 // the `jr` instruction, and save the instructions.
174 annotateTableJump(MBB, MBBI);
175 break;
176 }
177 return false;
178}
179
180bool LoongArchPreRAExpandPseudo::expandPcaxxu12iInstPair(
182 MachineBasicBlock::iterator &NextMBBI, unsigned OpcodeHi, unsigned OpcodeLo,
183 unsigned FlagsHi, unsigned FlagsLo) {
184 MachineFunction *MF = MBB.getParent();
185 MachineInstr &MI = *MBBI;
186 DebugLoc DL = MI.getDebugLoc();
187
188 const auto &STI = MF->getSubtarget<LoongArchSubtarget>();
189 bool EnableRelax = STI.hasFeature(LoongArch::FeatureRelax);
190
191 Register DestReg = MI.getOperand(0).getReg();
192 Register ScratchReg =
193 MF->getRegInfo().createVirtualRegister(&LoongArch::GPRRegClass);
194 MachineOperand &Symbol = MI.getOperand(1);
195
196 MachineInstr *FirstMI =
197 BuildMI(MBB, MBBI, DL, TII->get(OpcodeHi), ScratchReg)
198 .addDisp(Symbol, 0, LoongArchII::encodeFlags(FlagsHi, EnableRelax));
199
200 MachineInstr *SecondMI = nullptr;
201 FlagsLo = LoongArchII::encodeFlags(FlagsLo, EnableRelax);
202
203 if (OpcodeHi == LoongArch::PCALAU12I) {
204 SecondMI = BuildMI(MBB, MBBI, DL, TII->get(OpcodeLo), DestReg)
205 .addReg(ScratchReg)
206 .addDisp(Symbol, 0, FlagsLo);
207 } else {
208 MCSymbol *PCAddSymbol = MF->getContext().createNamedTempSymbol("pcadd_hi");
209 FirstMI->setPreInstrSymbol(*MF, PCAddSymbol);
210 SecondMI = BuildMI(MBB, MBBI, DL, TII->get(OpcodeLo), DestReg)
211 .addReg(ScratchReg)
212 .addSym(PCAddSymbol, FlagsLo);
213 }
214
215 if (MI.hasOneMemOperand())
216 SecondMI->addMemOperand(*MF, *MI.memoperands_begin());
217
218 MI.eraseFromParent();
219 return true;
220}
221
222bool LoongArchPreRAExpandPseudo::expandLargeAddressLoad(
224 MachineBasicBlock::iterator &NextMBBI, unsigned LastOpcode,
225 unsigned IdentifyingMO) {
226 MachineInstr &MI = *MBBI;
227 return expandLargeAddressLoad(MBB, MBBI, NextMBBI, LastOpcode, IdentifyingMO,
228 MI.getOperand(2), MI.getOperand(0).getReg(),
229 true);
230}
231
232bool LoongArchPreRAExpandPseudo::expandLargeAddressLoad(
234 MachineBasicBlock::iterator &NextMBBI, unsigned LastOpcode,
235 unsigned IdentifyingMO, const MachineOperand &Symbol, Register DestReg,
236 bool EraseFromParent) {
237 // Code Sequence:
238 //
239 // Part1: pcalau12i $scratch, %MO1(sym)
240 // Part0: addi.d $dest, $zero, %MO0(sym)
241 // Part2: lu32i.d $dest, %MO2(sym)
242 // Part3: lu52i.d $dest, $dest, %MO3(sym)
243 // Fin: LastOpcode $dest, $dest, $scratch
244
245 unsigned MO0, MO1, MO2, MO3;
246 switch (IdentifyingMO) {
247 default:
248 llvm_unreachable("unsupported identifying MO");
250 MO0 = IdentifyingMO;
254 break;
258 // These cases relocate just like the GOT case, except for Part1.
260 MO1 = IdentifyingMO;
263 break;
265 MO0 = IdentifyingMO;
269 break;
270 }
271
272 MachineFunction *MF = MBB.getParent();
273 MachineInstr &MI = *MBBI;
274 DebugLoc DL = MI.getDebugLoc();
275
277 "Large code model requires LA64");
278
279 Register TmpPart1 =
280 MF->getRegInfo().createVirtualRegister(&LoongArch::GPRRegClass);
281 Register TmpPart0 =
282 DestReg.isVirtual()
283 ? MF->getRegInfo().createVirtualRegister(&LoongArch::GPRRegClass)
284 : DestReg;
285 Register TmpParts02 =
286 DestReg.isVirtual()
287 ? MF->getRegInfo().createVirtualRegister(&LoongArch::GPRRegClass)
288 : DestReg;
289 Register TmpParts023 =
290 DestReg.isVirtual()
291 ? MF->getRegInfo().createVirtualRegister(&LoongArch::GPRRegClass)
292 : DestReg;
293
294 auto Part1 = BuildMI(MBB, MBBI, DL, TII->get(LoongArch::PCALAU12I), TmpPart1);
295 auto Part0 = BuildMI(MBB, MBBI, DL, TII->get(LoongArch::ADDI_D), TmpPart0)
296 .addReg(LoongArch::R0);
297 auto Part2 = BuildMI(MBB, MBBI, DL, TII->get(LoongArch::LU32I_D), TmpParts02)
298 // "rj" is needed due to InstrInfo pattern requirement.
299 .addReg(TmpPart0, RegState::Kill);
300 auto Part3 = BuildMI(MBB, MBBI, DL, TII->get(LoongArch::LU52I_D), TmpParts023)
301 .addReg(TmpParts02, RegState::Kill);
302 BuildMI(MBB, MBBI, DL, TII->get(LastOpcode), DestReg)
303 .addReg(TmpParts023)
304 .addReg(TmpPart1, RegState::Kill);
305
306 if (Symbol.getType() == MachineOperand::MO_ExternalSymbol) {
307 const char *SymName = Symbol.getSymbolName();
308 Part0.addExternalSymbol(SymName, MO0);
309 Part1.addExternalSymbol(SymName, MO1);
310 Part2.addExternalSymbol(SymName, MO2);
311 Part3.addExternalSymbol(SymName, MO3);
312 } else {
313 Part0.addDisp(Symbol, 0, MO0);
314 Part1.addDisp(Symbol, 0, MO1);
315 Part2.addDisp(Symbol, 0, MO2);
316 Part3.addDisp(Symbol, 0, MO3);
317 }
318
319 if (EraseFromParent)
320 MI.eraseFromParent();
321
322 return true;
323}
324
325bool LoongArchPreRAExpandPseudo::expandLoadAddressPcrel(
327 MachineBasicBlock::iterator &NextMBBI, bool Large) {
328 if (Large)
329 // Emit the 5-insn large address load sequence with the `%pc` family of
330 // relocs.
331 return expandLargeAddressLoad(MBB, MBBI, NextMBBI, LoongArch::ADD_D,
333
334 // Code Sequence:
335 //
336 // for la32r expands to:
337 // .Lpcadd_hi:
338 // pcaddu12i $rd, %pcadd_hi20(sym)
339 // addi.w $rd, $rd, %pcadd_lo12(.Lpcadd_hi)
340 //
341 // for la32s and la64 expands to:
342 // pcalau12i $rd, %pc_hi20(sym)
343 // addi.w/d $rd, $rd, %pc_lo12(sym)
344 MachineFunction *MF = MBB.getParent();
345 const auto &STI = MF->getSubtarget<LoongArchSubtarget>();
346 bool Has32S = STI.hasFeature(LoongArch::Feature32S);
347 unsigned OpcodeHi = Has32S ? LoongArch::PCALAU12I : LoongArch::PCADDU12I;
348 unsigned OpcodeLo = STI.is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W;
349 unsigned FlagsHi =
351 unsigned FlagsLo =
353 return expandPcaxxu12iInstPair(MBB, MBBI, NextMBBI, OpcodeHi, OpcodeLo,
354 FlagsHi, FlagsLo);
355}
356
357bool LoongArchPreRAExpandPseudo::expandLoadAddressGot(
359 MachineBasicBlock::iterator &NextMBBI, bool Large) {
360 if (Large)
361 // Emit the 5-insn large address load sequence with the `%got_pc` family
362 // of relocs, loading the result from GOT with `ldx.d` in the end.
363 return expandLargeAddressLoad(MBB, MBBI, NextMBBI, LoongArch::LDX_D,
365
366 // Code Sequence:
367 //
368 // for la32r expands to:
369 // .Lpcadd_hi:
370 // pcaddu12i $rd, %got_pcadd_hi20(sym)
371 // ld.w $rd, $rd, %got_pcadd_lo12(.Lpcadd_hi)
372 //
373 // for la32s and la64 expands to:
374 // pcalau12i $rd, %got_pc_hi20(sym)
375 // ld.w/d $rd, $rd, %got_pc_lo12(sym)
376 MachineFunction *MF = MBB.getParent();
377 const auto &STI = MF->getSubtarget<LoongArchSubtarget>();
378 bool Has32S = STI.hasFeature(LoongArch::Feature32S);
379 unsigned OpcodeHi = Has32S ? LoongArch::PCALAU12I : LoongArch::PCADDU12I;
380 unsigned OpcodeLo = STI.is64Bit() ? LoongArch::LD_D : LoongArch::LD_W;
381 unsigned FlagsHi =
383 unsigned FlagsLo =
385 return expandPcaxxu12iInstPair(MBB, MBBI, NextMBBI, OpcodeHi, OpcodeLo,
386 FlagsHi, FlagsLo);
387}
388
389bool LoongArchPreRAExpandPseudo::expandLoadAddressTLSLE(
391 MachineBasicBlock::iterator &NextMBBI) {
392 // Code Sequence:
393 // lu12i.w $rd, %le_hi20_r(sym)
394 // add.w/d $rd, $rd, $tp, %le_add_r(sym)
395 // addi.w/d $rd, $rd, %le_lo12_r(sym)
396 //
397 // Code Sequence while using the large code model:
398 // lu12i.w $rd, %le_hi20(sym)
399 // ori $rd, $rd, %le_lo12(sym)
400 // lu32i.d $rd, %le64_lo20(sym)
401 // lu52i.d $rd, $rd, %le64_hi12(sym)
402 MachineFunction *MF = MBB.getParent();
403 MachineInstr &MI = *MBBI;
404 DebugLoc DL = MI.getDebugLoc();
405
406 bool Large = MF->getTarget().getCodeModel() == CodeModel::Large;
407 Register DestReg = MI.getOperand(0).getReg();
408 Register Parts01 =
409 MF->getRegInfo().createVirtualRegister(&LoongArch::GPRRegClass);
410 Register Part1 =
411 MF->getRegInfo().createVirtualRegister(&LoongArch::GPRRegClass);
412 MachineOperand &Symbol = MI.getOperand(1);
413
414 if (!Large) {
415 BuildMI(MBB, MBBI, DL, TII->get(LoongArch::LU12I_W), Part1)
416 .addDisp(Symbol, 0, LoongArchII::MO_LE_HI_R);
417
418 const auto &STI = MF->getSubtarget<LoongArchSubtarget>();
419 unsigned AddOp = STI.is64Bit() ? LoongArch::PseudoAddTPRel_D
420 : LoongArch::PseudoAddTPRel_W;
421 BuildMI(MBB, MBBI, DL, TII->get(AddOp), Parts01)
422 .addReg(Part1, RegState::Kill)
423 .addReg(LoongArch::R2)
425
426 unsigned AddiOp = STI.is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W;
427 BuildMI(MBB, MBBI, DL, TII->get(AddiOp), DestReg)
428 .addReg(Parts01, RegState::Kill)
429 .addDisp(Symbol, 0, LoongArchII::MO_LE_LO_R);
430 } else {
431 BuildMI(MBB, MBBI, DL, TII->get(LoongArch::LU12I_W), Part1)
432 .addDisp(Symbol, 0, LoongArchII::MO_LE_HI);
433
434 BuildMI(MBB, MBBI, DL, TII->get(LoongArch::ORI), Parts01)
435 .addReg(Part1, RegState::Kill)
436 .addDisp(Symbol, 0, LoongArchII::MO_LE_LO);
437
438 Register Parts012 =
439 MF->getRegInfo().createVirtualRegister(&LoongArch::GPRRegClass);
440
441 BuildMI(MBB, MBBI, DL, TII->get(LoongArch::LU32I_D), Parts012)
442 // "rj" is needed due to InstrInfo pattern requirement.
443 .addReg(Parts01, RegState::Kill)
444 .addDisp(Symbol, 0, LoongArchII::MO_LE64_LO);
445 BuildMI(MBB, MBBI, DL, TII->get(LoongArch::LU52I_D), DestReg)
446 .addReg(Parts012, RegState::Kill)
447 .addDisp(Symbol, 0, LoongArchII::MO_LE64_HI);
448 }
449
450 MI.eraseFromParent();
451 return true;
452}
453
454bool LoongArchPreRAExpandPseudo::expandLoadAddressTLSIE(
456 MachineBasicBlock::iterator &NextMBBI, bool Large) {
457 if (Large)
458 // Emit the 5-insn large address load sequence with the `%ie_pc` family
459 // of relocs, loading the result with `ldx.d` in the end.
460 return expandLargeAddressLoad(MBB, MBBI, NextMBBI, LoongArch::LDX_D,
462
463 // Code Sequence:
464 //
465 // for la32r expands to:
466 // .Lpcadd_hi:
467 // pcaddu12i $rd, %ie_pcadd_hi20(sym)
468 // ld.w $rd, $rd, %ie_pcadd_lo12(.Lpcadd_hi)
469 //
470 // for la32s and la64 expands to:
471 // pcalau12i $rd, %ie_pc_hi20(sym)
472 // ld.w/d $rd, $rd, %ie_pc_lo12(sym)
473 MachineFunction *MF = MBB.getParent();
474 const auto &STI = MF->getSubtarget<LoongArchSubtarget>();
475 bool Has32S = STI.hasFeature(LoongArch::Feature32S);
476 unsigned OpcodeHi = Has32S ? LoongArch::PCALAU12I : LoongArch::PCADDU12I;
477 unsigned OpcodeLo = STI.is64Bit() ? LoongArch::LD_D : LoongArch::LD_W;
478 unsigned FlagsHi =
480 unsigned FlagsLo =
482 return expandPcaxxu12iInstPair(MBB, MBBI, NextMBBI, OpcodeHi, OpcodeLo,
483 FlagsHi, FlagsLo);
484}
485
486bool LoongArchPreRAExpandPseudo::expandLoadAddressTLSLD(
488 MachineBasicBlock::iterator &NextMBBI, bool Large) {
489 if (Large)
490 // Emit the 5-insn large address load sequence with the `%got_pc` family
491 // of relocs, with the `pcalau12i` insn relocated with `%ld_pc_hi20`.
492 return expandLargeAddressLoad(MBB, MBBI, NextMBBI, LoongArch::ADD_D,
494
495 // Code Sequence:
496 //
497 // for la32r expands to:
498 // .Lpcadd_hi:
499 // pcaddu12i $rd, %ld_pcadd_hi20(sym)
500 // addi.w $rd, $rd, %ld_pcadd_lo12(.Lpcadd_hi)
501 //
502 // for la32s and la64 expands to:
503 // pcalau12i $rd, %ld_pc_hi20(sym)
504 // addi.w/d $rd, $rd, %got_pc_lo12(sym)
505 MachineFunction *MF = MBB.getParent();
506 const auto &STI = MF->getSubtarget<LoongArchSubtarget>();
507 bool Has32S = STI.hasFeature(LoongArch::Feature32S);
508 unsigned OpcodeHi = Has32S ? LoongArch::PCALAU12I : LoongArch::PCADDU12I;
509 unsigned OpcodeLo = STI.is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W;
510 unsigned FlagsHi =
512 unsigned FlagsLo =
514 return expandPcaxxu12iInstPair(MBB, MBBI, NextMBBI, OpcodeHi, OpcodeLo,
515 FlagsHi, FlagsLo);
516}
517
518bool LoongArchPreRAExpandPseudo::expandLoadAddressTLSGD(
520 MachineBasicBlock::iterator &NextMBBI, bool Large) {
521 if (Large)
522 // Emit the 5-insn large address load sequence with the `%got_pc` family
523 // of relocs, with the `pcalau12i` insn relocated with `%gd_pc_hi20`.
524 return expandLargeAddressLoad(MBB, MBBI, NextMBBI, LoongArch::ADD_D,
526
527 // Code Sequence:
528 //
529 // for la32r expands to:
530 // .Lpcadd_hi:
531 // pcaddu12i $rd, %gd_pcadd_hi20(sym)
532 // addi.w $rd, $rd, %gd_pcadd_lo12(.Lpcadd_hi)
533 //
534 // for la32s and la64 expands to:
535 // pcalau12i $rd, %gd_pc_hi20(sym)
536 // addi.w/d $rd, $rd, %got_pc_lo12(sym)
537 MachineFunction *MF = MBB.getParent();
538 const auto &STI = MF->getSubtarget<LoongArchSubtarget>();
539 bool Has32S = STI.hasFeature(LoongArch::Feature32S);
540 unsigned OpcodeHi = Has32S ? LoongArch::PCALAU12I : LoongArch::PCADDU12I;
541 unsigned OpcodeLo = STI.is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W;
542 unsigned FlagsHi =
544 unsigned FlagsLo =
546 return expandPcaxxu12iInstPair(MBB, MBBI, NextMBBI, OpcodeHi, OpcodeLo,
547 FlagsHi, FlagsLo);
548}
549
550bool LoongArchPreRAExpandPseudo::expandLoadAddressTLSDesc(
552 MachineBasicBlock::iterator &NextMBBI, bool Large) {
553 MachineFunction *MF = MBB.getParent();
554 MachineInstr &MI = *MBBI;
555 DebugLoc DL = MI.getDebugLoc();
556
557 const auto &STI = MF->getSubtarget<LoongArchSubtarget>();
558 bool Has32S = STI.hasFeature(LoongArch::Feature32S);
559 bool EnableRelax = STI.hasFeature(LoongArch::FeatureRelax);
560 unsigned PCA = Has32S ? LoongArch::PCALAU12I : LoongArch::PCADDU12I;
561 unsigned ADD = STI.is64Bit() ? LoongArch::ADD_D : LoongArch::ADD_W;
562 unsigned ADDI = STI.is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W;
563 unsigned LD = STI.is64Bit() ? LoongArch::LD_D : LoongArch::LD_W;
564 unsigned MO =
566
567 Register DestReg = MI.getOperand(0).getReg();
568 Register Tmp1Reg =
569 MF->getRegInfo().createVirtualRegister(&LoongArch::GPRRegClass);
570 MachineOperand &Symbol = MI.getOperand(Large ? 2 : 1);
571
572 MachineInstr *PCAMI =
573 BuildMI(MBB, MBBI, DL, TII->get(PCA), Tmp1Reg)
574 .addDisp(Symbol, 0,
575 LoongArchII::encodeFlags(MO, EnableRelax && !Large));
576
577 if (Large) {
578 // Code Sequence:
579 //
580 // pcalau12i $a0, %desc_pc_hi20(sym)
581 // addi.d $a1, $zero, %desc_pc_lo12(sym)
582 // lu32i.d $a1, %desc64_pc_lo20(sym)
583 // lu52i.d $a1, $a1, %desc64_pc_hi12(sym)
584 // add.d $a0, $a0, $a1
585 // ld.d $ra, $a0, %desc_ld(sym)
586 // jirl $ra, $ra, %desc_call(sym)
587 // add.d $dst, $a0, $tp
588 assert(MBB.getParent()->getSubtarget<LoongArchSubtarget>().is64Bit() &&
589 "Large code model requires LA64");
590 Register Tmp2Reg =
591 MF->getRegInfo().createVirtualRegister(&LoongArch::GPRRegClass);
592 Register Tmp3Reg =
593 MF->getRegInfo().createVirtualRegister(&LoongArch::GPRRegClass);
594 Register Tmp4Reg =
595 MF->getRegInfo().createVirtualRegister(&LoongArch::GPRRegClass);
596 BuildMI(MBB, MBBI, DL, TII->get(LoongArch::ADDI_D), Tmp2Reg)
597 .addReg(LoongArch::R0)
599 BuildMI(MBB, MBBI, DL, TII->get(LoongArch::LU32I_D), Tmp3Reg)
600 .addReg(Tmp2Reg, RegState::Kill)
602 BuildMI(MBB, MBBI, DL, TII->get(LoongArch::LU52I_D), Tmp4Reg)
603 .addReg(Tmp3Reg)
605 BuildMI(MBB, MBBI, DL, TII->get(LoongArch::ADD_D), LoongArch::R4)
606 .addReg(Tmp1Reg)
607 .addReg(Tmp4Reg);
608 } else {
609 // Code Sequence:
610 //
611 // for la32r expands to:
612 // .Lpcadd_hi:
613 // pcaddu12i $a0, %desc_pcadd_hi20(sym)
614 // addi.w $a0, $a0, %desc_pcadd_lo12(.Lpcadd_hi)
615 // ld.w $ra, $a0, %desc_ld(sym)
616 // jirl $ra, $ra, %desc_call(sym)
617 // add.w $dst, $a0, $tp
618 //
619 // for la32s and la64 expands to:
620 // pcalau12i $a0, %desc_pc_hi20(sym)
621 // addi.w/d $a0, $a0, %desc_pc_lo12(sym)
622 // ld.w/d $ra, $a0, %desc_ld(sym)
623 // jirl $ra, $ra, %desc_call(sym)
624 // add.w/d $dst, $a0, $tp
625 if (Has32S) {
626 BuildMI(MBB, MBBI, DL, TII->get(ADDI), LoongArch::R4)
627 .addReg(Tmp1Reg)
628 .addDisp(Symbol, 0,
630 EnableRelax));
631 } else {
632 MCSymbol *PCASymbol = MF->getContext().createNamedTempSymbol("pcadd_hi");
633 PCAMI->setPreInstrSymbol(*MF, PCASymbol);
634 BuildMI(MBB, MBBI, DL, TII->get(ADDI), LoongArch::R4)
635 .addReg(Tmp1Reg)
637 LoongArchII::MO_DESC_PCADD_LO, EnableRelax));
638 }
639 }
640
641 BuildMI(MBB, MBBI, DL, TII->get(LD), LoongArch::R1)
642 .addReg(LoongArch::R4)
643 .addDisp(Symbol, 0,
645 EnableRelax && !Large));
646 BuildMI(MBB, MBBI, DL, TII->get(LoongArch::PseudoDESC_CALL), LoongArch::R1)
647 .addReg(LoongArch::R1)
648 .addDisp(Symbol, 0,
650 EnableRelax && !Large));
651 BuildMI(MBB, MBBI, DL, TII->get(ADD), DestReg)
652 .addReg(LoongArch::R4)
653 .addReg(LoongArch::R2);
654
655 MI.eraseFromParent();
656 return true;
657}
658
659bool LoongArchPreRAExpandPseudo::expandFunctionCALL(
661 MachineBasicBlock::iterator &NextMBBI, bool IsTailCall) {
662 MachineFunction *MF = MBB.getParent();
663 MachineInstr &MI = *MBBI;
664 DebugLoc DL = MI.getDebugLoc();
665 const MachineOperand &Func = MI.getOperand(0);
667 unsigned Opcode;
668
669 switch (MF->getTarget().getCodeModel()) {
670 default:
671 report_fatal_error("Unexpected code model");
672 break;
673 case CodeModel::Small: {
674 // CALL:
675 // bl func
676 // TAIL:
677 // b func
678 Opcode = IsTailCall ? LoongArch::PseudoB_TAIL : LoongArch::BL;
679 CALL = BuildMI(MBB, MBBI, DL, TII->get(Opcode)).add(Func);
680 break;
681 }
682 case CodeModel::Large: {
683 // Emit the 5-insn large address load sequence, either directly or
684 // indirectly in case of going through the GOT, then JIRL_TAIL or
685 // JIRL_CALL to $addr.
686 Opcode =
687 IsTailCall ? LoongArch::PseudoJIRL_TAIL : LoongArch::PseudoJIRL_CALL;
688 Register AddrReg =
689 IsTailCall
690 ? MF->getRegInfo().createVirtualRegister(&LoongArch::GPRRegClass)
691 : LoongArch::R1;
692
693 bool UseGOT = Func.getTargetFlags() == LoongArchII::MO_CALL_PLT;
695 unsigned LAOpcode = UseGOT ? LoongArch::LDX_D : LoongArch::ADD_D;
696 expandLargeAddressLoad(MBB, MBBI, NextMBBI, LAOpcode, MO, Func, AddrReg,
697 false);
698 CALL = BuildMI(MBB, MBBI, DL, TII->get(Opcode)).addReg(AddrReg).addImm(0);
699 break;
700 }
701 }
702
703 // Transfer implicit operands.
704 CALL.copyImplicitOps(MI);
705
706 // Transfer MI flags.
707 CALL.setMIFlags(MI.getFlags());
708
709 MI.eraseFromParent();
710 return true;
711}
712
713void LoongArchPreRAExpandPseudo::annotateTableJump(
715 MachineFunction *MF = MBB.getParent();
716 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
717
718 bool IsFound = false;
719
720 std::function<void(MachineInstr *, int)> FindJTIMI = [&](MachineInstr *MInst,
721 int FindDepth) {
722 if (FindDepth < 0)
723 return;
724 for (auto &MO : MInst->all_uses()) {
725 if (IsFound)
726 return;
727 Register Reg = MO.getReg();
728 if (!Reg.isVirtual())
729 continue;
730 MachineInstr *DefMI = MRI.getVRegDef(Reg);
731 if (!DefMI)
732 continue;
733 for (unsigned Idx = 0; Idx < DefMI->getNumOperands(); ++Idx) {
734 MachineOperand &MO = DefMI->getOperand(Idx);
735 if (MO.isJTI()) {
736 MBBI->setPreInstrSymbol(
737 *MF, MF->getContext().createNamedTempSymbol("jrtb_"));
738 MF->getInfo<LoongArchMachineFunctionInfo>()->setJumpInfo(
739 &*MBBI, MO.getIndex());
740 IsFound = true;
741 return;
742 }
743 }
744 FindJTIMI(DefMI, --FindDepth);
745 }
746 };
747
748 // FindDepth = 4, probably sufficient.
749 FindJTIMI(&*MBBI, /*FindDepth=*/4);
750}
751
752class LoongArchExpandPseudo : public MachineFunctionPass {
753public:
754 const LoongArchInstrInfo *TII;
755 static char ID;
756
757 LoongArchExpandPseudo() : MachineFunctionPass(ID) {}
758
759 bool runOnMachineFunction(MachineFunction &MF) override;
760
761 StringRef getPassName() const override {
763 }
764
765private:
766 bool expandMBB(MachineBasicBlock &MBB);
771 bool expandFunctionCALL(MachineBasicBlock &MBB,
774 bool IsTailCall);
775};
776
777char LoongArchExpandPseudo::ID = 0;
778
779bool LoongArchExpandPseudo::runOnMachineFunction(MachineFunction &MF) {
780 TII =
781 static_cast<const LoongArchInstrInfo *>(MF.getSubtarget().getInstrInfo());
782
783 bool Modified = false;
784 for (auto &MBB : MF)
785 Modified |= expandMBB(MBB);
786
787 return Modified;
788}
789
790bool LoongArchExpandPseudo::expandMBB(MachineBasicBlock &MBB) {
791 bool Modified = false;
792
793 MachineBasicBlock::iterator MBBI = MBB.begin(), E = MBB.end();
794 while (MBBI != E) {
795 MachineBasicBlock::iterator NMBBI = std::next(MBBI);
796 Modified |= expandMI(MBB, MBBI, NMBBI);
797 MBBI = NMBBI;
798 }
799
800 return Modified;
801}
802
803bool LoongArchExpandPseudo::expandMI(MachineBasicBlock &MBB,
805 MachineBasicBlock::iterator &NextMBBI) {
806 switch (MBBI->getOpcode()) {
807 case LoongArch::PseudoCopyCFR:
808 return expandCopyCFR(MBB, MBBI, NextMBBI);
809 case LoongArch::PseudoCALL_MEDIUM:
810 return expandFunctionCALL(MBB, MBBI, NextMBBI, /*IsTailCall=*/false);
811 case LoongArch::PseudoTAIL_MEDIUM:
812 return expandFunctionCALL(MBB, MBBI, NextMBBI, /*IsTailCall=*/true);
813 }
814
815 return false;
816}
817
818bool LoongArchExpandPseudo::expandCopyCFR(
820 MachineBasicBlock::iterator &NextMBBI) {
821 MachineFunction *MF = MBB.getParent();
822 MachineInstr &MI = *MBBI;
823 DebugLoc DL = MI.getDebugLoc();
824
825 // Expand:
826 // MBB:
827 // fcmp.caf.s $dst, $fa0, $fa0 # set $dst 0(false)
828 // bceqz $src, SinkBB
829 // FalseBB:
830 // fcmp.cueq.s $dst, $fa0, $fa0 # set $dst 1(true)
831 // SinkBB:
832 // fallthrough
833
834 const BasicBlock *LLVM_BB = MBB.getBasicBlock();
835 auto *FalseBB = MF->CreateMachineBasicBlock(LLVM_BB);
836 auto *SinkBB = MF->CreateMachineBasicBlock(LLVM_BB);
837
838 MF->insert(++MBB.getIterator(), FalseBB);
839 MF->insert(++FalseBB->getIterator(), SinkBB);
840
841 Register DestReg = MI.getOperand(0).getReg();
842 Register SrcReg = MI.getOperand(1).getReg();
843 // DestReg = 0
844 BuildMI(MBB, MBBI, DL, TII->get(LoongArch::SET_CFR_FALSE), DestReg);
845 // Insert branch instruction.
846 BuildMI(MBB, MBBI, DL, TII->get(LoongArch::BCEQZ))
847 .addReg(SrcReg)
848 .addMBB(SinkBB);
849 // DestReg = 1
850 BuildMI(FalseBB, DL, TII->get(LoongArch::SET_CFR_TRUE), DestReg);
851
852 FalseBB->addSuccessor(SinkBB);
853
854 SinkBB->splice(SinkBB->end(), &MBB, MI, MBB.end());
855 SinkBB->transferSuccessors(&MBB);
856
857 MBB.addSuccessor(FalseBB);
858 MBB.addSuccessor(SinkBB);
859
860 NextMBBI = MBB.end();
861 MI.eraseFromParent();
862
863 // Make sure live-ins are correctly attached to this new basic block.
867
868 return true;
869}
870
871bool LoongArchExpandPseudo::expandFunctionCALL(
873 MachineBasicBlock::iterator &NextMBBI, bool IsTailCall) {
874 MachineFunction *MF = MBB.getParent();
875 MachineInstr &MI = *MBBI;
876 DebugLoc DL = MI.getDebugLoc();
877 const MachineOperand &Func = MI.getOperand(0);
879 unsigned Opcode;
880
881 switch (MF->getTarget().getCodeModel()) {
882 default:
883 report_fatal_error("Unexpected code model");
884 break;
885 case CodeModel::Medium: {
886 // for la32 expands to:
887 // CALL:
888 // pcaddu12i $ra, %call30(func)
889 // jirl $ra, $ra, 0
890 // TAIL:
891 // pcaddu12i $t8, %call30(func)
892 // jirl $r0, $t8, 0
893 //
894 // for la64 expands to:
895 // CALL:
896 // pcaddu18i $ra, %call36(func)
897 // jirl $ra, $ra, 0
898 // TAIL:
899 // pcaddu18i $t8, %call36(func)
900 // jirl $r0, $t8, 0
901 Opcode =
902 IsTailCall ? LoongArch::PseudoJIRL_TAIL : LoongArch::PseudoJIRL_CALL;
903 Register ScratchReg = IsTailCall ? LoongArch::R20 : LoongArch::R1;
904 bool Is64Bit = MF->getSubtarget<LoongArchSubtarget>().is64Bit();
905 unsigned PC = Is64Bit ? LoongArch::PCADDU18I : LoongArch::PCADDU12I;
906 unsigned MO = Is64Bit ? LoongArchII::MO_CALL36 : LoongArchII::MO_CALL30;
907 MachineInstrBuilder MIB = BuildMI(MBB, MBBI, DL, TII->get(PC), ScratchReg);
908
909 CALL =
910 BuildMI(MBB, MBBI, DL, TII->get(Opcode)).addReg(ScratchReg).addImm(0);
911
912 if (Func.isSymbol())
913 MIB.addExternalSymbol(Func.getSymbolName(), MO);
914 else
915 MIB.addDisp(Func, 0, MO);
916 break;
917 }
918 }
919
920 // Transfer implicit operands.
921 CALL.copyImplicitOps(MI);
922
923 // Transfer MI flags.
924 CALL.setMIFlags(MI.getFlags());
925
926 MI.eraseFromParent();
927 return true;
928}
929
930} // end namespace
931
932INITIALIZE_PASS(LoongArchPreRAExpandPseudo, "loongarch-prera-expand-pseudo",
934
935INITIALIZE_PASS(LoongArchExpandPseudo, "loongarch-expand-pseudo",
937
938namespace llvm {
939
941 return new LoongArchPreRAExpandPseudo();
942}
944 return new LoongArchExpandPseudo();
945}
946
947} // end namespace llvm
unsigned const MachineRegisterInfo * MRI
MachineInstrBuilder MachineInstrBuilder & DefMI
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock & MBB
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
MachineBasicBlock MachineBasicBlock::iterator MBBI
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
const HexagonInstrInfo * TII
IRTranslator LLVM IR MI
This file implements the LivePhysRegs utility for tracking liveness of physical registers.
cl::opt< bool > LArchAnnotateTableJump("loongarch-annotate-tablejump", cl::Hidden, cl::desc("Annotate table jump instruction to correlate it with the jump table."), cl::init(false))
#define LOONGARCH_PRERA_EXPAND_PSEUDO_NAME
#define LOONGARCH_EXPAND_PSEUDO_NAME
Register Reg
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
Definition PassSupport.h:56
static bool is64Bit(const char *name)
Represent the analysis usage information of a pass.
LLVM_ABI void setPreservesCFG()
This function should be called by the pass, iff they do not:
Definition Pass.cpp:270
LLVM Basic Block Representation.
Definition BasicBlock.h:62
A debug info location.
Definition DebugLoc.h:123
FunctionPass class - This class is used to implement most global optimizations.
Definition Pass.h:314
A set of physical registers with utility functions to track liveness when walking backward/forward th...
LoongArchMachineFunctionInfo - This class is derived from MachineFunctionInfo and contains private Lo...
LLVM_ABI MCSymbol * createNamedTempSymbol()
Create a temporary symbol with a unique name whose name cannot be omitted in the symbol table.
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
Definition MCSymbol.h:42
MachineInstrBundleIterator< MachineInstr > iterator
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.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MCContext & getContext() const
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
MachineBasicBlock * CreateMachineBasicBlock(const BasicBlock *BB=nullptr, std::optional< UniqueBBID > BBID=std::nullopt)
CreateMachineInstr - Allocate a new MachineInstr.
void insert(iterator MBBI, MachineBasicBlock *MBB)
const TargetMachine & getTarget() const
getTarget - Return the target machine this machine code is compiled with
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 & addSym(MCSymbol *Sym, unsigned char TargetFlags=0) 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.
LLVM_ABI void setPreInstrSymbol(MachineFunction &MF, MCSymbol *Symbol)
Set a symbol that will be emitted just prior to the instruction itself.
filtered_mop_range all_uses()
Returns an iterator range over all operands that are (explicit or implicit) register uses.
LLVM_ABI void addMemOperand(MachineFunction &MF, MachineMemOperand *MO)
Add a MachineMemOperand to the machine instruction.
MachineOperand class - Representation of each machine instruction operand.
bool isJTI() const
isJTI - Tests if this is a MO_JumpTableIndex operand.
@ MO_ExternalSymbol
Name of external global symbol.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
LLVM_ABI Register createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
Wrapper class representing virtual and physical registers.
Definition Register.h:20
constexpr bool isVirtual() const
Return true if the specified register number is in the virtual register namespace.
Definition Register.h:79
StringRef - Represent a constant reference to a string, i.e.
Definition StringRef.h:55
CodeModel::Model getCodeModel() const
Returns the code model.
#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
static unsigned encodeFlags(unsigned Flags, bool Relax)
@ Kill
The last use of a register.
This is an optimization pass for GlobalISel generic memory operations.
Definition Types.h:26
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
Definition Error.cpp:167
FunctionPass * createLoongArchPreRAExpandPseudoPass()
FunctionPass * createLoongArchExpandPseudoPass()
void computeAndAddLiveIns(LivePhysRegs &LiveRegs, MachineBasicBlock &MBB)
Convenience function combining computeLiveIns() and addLiveIns().