LLVM 20.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 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};
107
108char LoongArchPreRAExpandPseudo::ID = 0;
109
110bool LoongArchPreRAExpandPseudo::runOnMachineFunction(MachineFunction &MF) {
111 TII =
112 static_cast<const LoongArchInstrInfo *>(MF.getSubtarget().getInstrInfo());
113 bool Modified = false;
114 for (auto &MBB : MF)
115 Modified |= expandMBB(MBB);
116 return Modified;
117}
118
119bool LoongArchPreRAExpandPseudo::expandMBB(MachineBasicBlock &MBB) {
120 bool Modified = false;
121
123 while (MBBI != E) {
124 MachineBasicBlock::iterator NMBBI = std::next(MBBI);
125 Modified |= expandMI(MBB, MBBI, NMBBI);
126 MBBI = NMBBI;
127 }
128
129 return Modified;
130}
131
132bool LoongArchPreRAExpandPseudo::expandMI(
134 MachineBasicBlock::iterator &NextMBBI) {
135 switch (MBBI->getOpcode()) {
136 case LoongArch::PseudoLA_PCREL:
137 return expandLoadAddressPcrel(MBB, MBBI, NextMBBI);
138 case LoongArch::PseudoLA_PCREL_LARGE:
139 return expandLoadAddressPcrel(MBB, MBBI, NextMBBI, /*Large=*/true);
140 case LoongArch::PseudoLA_GOT:
141 return expandLoadAddressGot(MBB, MBBI, NextMBBI);
142 case LoongArch::PseudoLA_GOT_LARGE:
143 return expandLoadAddressGot(MBB, MBBI, NextMBBI, /*Large=*/true);
144 case LoongArch::PseudoLA_TLS_LE:
145 return expandLoadAddressTLSLE(MBB, MBBI, NextMBBI);
146 case LoongArch::PseudoLA_TLS_IE:
147 return expandLoadAddressTLSIE(MBB, MBBI, NextMBBI);
148 case LoongArch::PseudoLA_TLS_IE_LARGE:
149 return expandLoadAddressTLSIE(MBB, MBBI, NextMBBI, /*Large=*/true);
150 case LoongArch::PseudoLA_TLS_LD:
151 return expandLoadAddressTLSLD(MBB, MBBI, NextMBBI);
152 case LoongArch::PseudoLA_TLS_LD_LARGE:
153 return expandLoadAddressTLSLD(MBB, MBBI, NextMBBI, /*Large=*/true);
154 case LoongArch::PseudoLA_TLS_GD:
155 return expandLoadAddressTLSGD(MBB, MBBI, NextMBBI);
156 case LoongArch::PseudoLA_TLS_GD_LARGE:
157 return expandLoadAddressTLSGD(MBB, MBBI, NextMBBI, /*Large=*/true);
158 case LoongArch::PseudoLA_TLS_DESC_PC:
159 return expandLoadAddressTLSDesc(MBB, MBBI, NextMBBI);
160 case LoongArch::PseudoLA_TLS_DESC_PC_LARGE:
161 return expandLoadAddressTLSDesc(MBB, MBBI, NextMBBI, /*Large=*/true);
162 case LoongArch::PseudoCALL:
163 case LoongArch::PseudoCALL_MEDIUM:
164 case LoongArch::PseudoCALL_LARGE:
165 return expandFunctionCALL(MBB, MBBI, NextMBBI, /*IsTailCall=*/false);
166 case LoongArch::PseudoTAIL:
167 case LoongArch::PseudoTAIL_MEDIUM:
168 case LoongArch::PseudoTAIL_LARGE:
169 return expandFunctionCALL(MBB, MBBI, NextMBBI, /*IsTailCall=*/true);
170 }
171 return false;
172}
173
174bool LoongArchPreRAExpandPseudo::expandPcalau12iInstPair(
176 MachineBasicBlock::iterator &NextMBBI, unsigned FlagsHi,
177 unsigned SecondOpcode, unsigned FlagsLo) {
179 MachineInstr &MI = *MBBI;
180 DebugLoc DL = MI.getDebugLoc();
181
182 Register DestReg = MI.getOperand(0).getReg();
183 Register ScratchReg =
184 MF->getRegInfo().createVirtualRegister(&LoongArch::GPRRegClass);
185 MachineOperand &Symbol = MI.getOperand(1);
186
187 BuildMI(MBB, MBBI, DL, TII->get(LoongArch::PCALAU12I), ScratchReg)
188 .addDisp(Symbol, 0, FlagsHi);
189
190 MachineInstr *SecondMI =
191 BuildMI(MBB, MBBI, DL, TII->get(SecondOpcode), DestReg)
192 .addReg(ScratchReg)
193 .addDisp(Symbol, 0, FlagsLo);
194
195 if (MI.hasOneMemOperand())
196 SecondMI->addMemOperand(*MF, *MI.memoperands_begin());
197
198 MI.eraseFromParent();
199 return true;
200}
201
202bool LoongArchPreRAExpandPseudo::expandLargeAddressLoad(
204 MachineBasicBlock::iterator &NextMBBI, unsigned LastOpcode,
205 unsigned IdentifyingMO) {
206 MachineInstr &MI = *MBBI;
207 return expandLargeAddressLoad(MBB, MBBI, NextMBBI, LastOpcode, IdentifyingMO,
208 MI.getOperand(2), MI.getOperand(0).getReg(),
209 true);
210}
211
212bool LoongArchPreRAExpandPseudo::expandLargeAddressLoad(
214 MachineBasicBlock::iterator &NextMBBI, unsigned LastOpcode,
215 unsigned IdentifyingMO, const MachineOperand &Symbol, Register DestReg,
216 bool EraseFromParent) {
217 // Code Sequence:
218 //
219 // Part1: pcalau12i $scratch, %MO1(sym)
220 // Part0: addi.d $dest, $zero, %MO0(sym)
221 // Part2: lu32i.d $dest, %MO2(sym)
222 // Part3: lu52i.d $dest, $dest, %MO3(sym)
223 // Fin: LastOpcode $dest, $dest, $scratch
224
225 unsigned MO0, MO1, MO2, MO3;
226 switch (IdentifyingMO) {
227 default:
228 llvm_unreachable("unsupported identifying MO");
230 MO0 = IdentifyingMO;
234 break;
238 // These cases relocate just like the GOT case, except for Part1.
240 MO1 = IdentifyingMO;
243 break;
245 MO0 = IdentifyingMO;
249 break;
250 }
251
253 MachineInstr &MI = *MBBI;
254 DebugLoc DL = MI.getDebugLoc();
255
257 "Large code model requires LA64");
258
259 Register TmpPart1 =
260 MF->getRegInfo().createVirtualRegister(&LoongArch::GPRRegClass);
261 Register TmpPart0 =
262 DestReg.isVirtual()
263 ? MF->getRegInfo().createVirtualRegister(&LoongArch::GPRRegClass)
264 : DestReg;
265 Register TmpParts02 =
266 DestReg.isVirtual()
267 ? MF->getRegInfo().createVirtualRegister(&LoongArch::GPRRegClass)
268 : DestReg;
269 Register TmpParts023 =
270 DestReg.isVirtual()
271 ? MF->getRegInfo().createVirtualRegister(&LoongArch::GPRRegClass)
272 : DestReg;
273
274 auto Part1 = BuildMI(MBB, MBBI, DL, TII->get(LoongArch::PCALAU12I), TmpPart1);
275 auto Part0 = BuildMI(MBB, MBBI, DL, TII->get(LoongArch::ADDI_D), TmpPart0)
276 .addReg(LoongArch::R0);
277 auto Part2 = BuildMI(MBB, MBBI, DL, TII->get(LoongArch::LU32I_D), TmpParts02)
278 // "rj" is needed due to InstrInfo pattern requirement.
279 .addReg(TmpPart0, RegState::Kill);
280 auto Part3 = BuildMI(MBB, MBBI, DL, TII->get(LoongArch::LU52I_D), TmpParts023)
281 .addReg(TmpParts02, RegState::Kill);
282 BuildMI(MBB, MBBI, DL, TII->get(LastOpcode), DestReg)
283 .addReg(TmpParts023)
284 .addReg(TmpPart1, RegState::Kill);
285
286 if (Symbol.getType() == MachineOperand::MO_ExternalSymbol) {
287 const char *SymName = Symbol.getSymbolName();
288 Part0.addExternalSymbol(SymName, MO0);
289 Part1.addExternalSymbol(SymName, MO1);
290 Part2.addExternalSymbol(SymName, MO2);
291 Part3.addExternalSymbol(SymName, MO3);
292 } else {
293 Part0.addDisp(Symbol, 0, MO0);
294 Part1.addDisp(Symbol, 0, MO1);
295 Part2.addDisp(Symbol, 0, MO2);
296 Part3.addDisp(Symbol, 0, MO3);
297 }
298
299 if (EraseFromParent)
300 MI.eraseFromParent();
301
302 return true;
303}
304
305bool LoongArchPreRAExpandPseudo::expandLoadAddressPcrel(
307 MachineBasicBlock::iterator &NextMBBI, bool Large) {
308 if (Large)
309 // Emit the 5-insn large address load sequence with the `%pc` family of
310 // relocs.
311 return expandLargeAddressLoad(MBB, MBBI, NextMBBI, LoongArch::ADD_D,
313
314 // Code Sequence:
315 // pcalau12i $rd, %pc_hi20(sym)
316 // addi.w/d $rd, $rd, %pc_lo12(sym)
318 const auto &STI = MF->getSubtarget<LoongArchSubtarget>();
319 unsigned SecondOpcode = STI.is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W;
320 return expandPcalau12iInstPair(MBB, MBBI, NextMBBI, LoongArchII::MO_PCREL_HI,
321 SecondOpcode, LoongArchII::MO_PCREL_LO);
322}
323
324bool LoongArchPreRAExpandPseudo::expandLoadAddressGot(
326 MachineBasicBlock::iterator &NextMBBI, bool Large) {
327 if (Large)
328 // Emit the 5-insn large address load sequence with the `%got_pc` family
329 // of relocs, loading the result from GOT with `ldx.d` in the end.
330 return expandLargeAddressLoad(MBB, MBBI, NextMBBI, LoongArch::LDX_D,
332
333 // Code Sequence:
334 // pcalau12i $rd, %got_pc_hi20(sym)
335 // ld.w/d $rd, $rd, %got_pc_lo12(sym)
337 const auto &STI = MF->getSubtarget<LoongArchSubtarget>();
338 unsigned SecondOpcode = STI.is64Bit() ? LoongArch::LD_D : LoongArch::LD_W;
339 return expandPcalau12iInstPair(MBB, MBBI, NextMBBI, LoongArchII::MO_GOT_PC_HI,
340 SecondOpcode, LoongArchII::MO_GOT_PC_LO);
341}
342
343bool LoongArchPreRAExpandPseudo::expandLoadAddressTLSLE(
345 MachineBasicBlock::iterator &NextMBBI) {
346 // Code Sequence:
347 // lu12i.w $rd, %le_hi20(sym)
348 // ori $rd, $rd, %le_lo12(sym)
349 //
350 // And additionally if generating code using the large code model:
351 //
352 // lu32i.d $rd, %le64_lo20(sym)
353 // lu52i.d $rd, $rd, %le64_hi12(sym)
355 MachineInstr &MI = *MBBI;
356 DebugLoc DL = MI.getDebugLoc();
357
358 bool Large = MF->getTarget().getCodeModel() == CodeModel::Large;
359 Register DestReg = MI.getOperand(0).getReg();
360 Register Parts01 =
361 Large ? MF->getRegInfo().createVirtualRegister(&LoongArch::GPRRegClass)
362 : DestReg;
363 Register Part1 =
364 MF->getRegInfo().createVirtualRegister(&LoongArch::GPRRegClass);
365 MachineOperand &Symbol = MI.getOperand(1);
366
367 BuildMI(MBB, MBBI, DL, TII->get(LoongArch::LU12I_W), Part1)
368 .addDisp(Symbol, 0, LoongArchII::MO_LE_HI);
369
370 BuildMI(MBB, MBBI, DL, TII->get(LoongArch::ORI), Parts01)
371 .addReg(Part1, RegState::Kill)
372 .addDisp(Symbol, 0, LoongArchII::MO_LE_LO);
373
374 if (Large) {
375 Register Parts012 =
376 MF->getRegInfo().createVirtualRegister(&LoongArch::GPRRegClass);
377
378 BuildMI(MBB, MBBI, DL, TII->get(LoongArch::LU32I_D), Parts012)
379 // "rj" is needed due to InstrInfo pattern requirement.
380 .addReg(Parts01, RegState::Kill)
381 .addDisp(Symbol, 0, LoongArchII::MO_LE64_LO);
382 BuildMI(MBB, MBBI, DL, TII->get(LoongArch::LU52I_D), DestReg)
383 .addReg(Parts012, RegState::Kill)
384 .addDisp(Symbol, 0, LoongArchII::MO_LE64_HI);
385 }
386
387 MI.eraseFromParent();
388 return true;
389}
390
391bool LoongArchPreRAExpandPseudo::expandLoadAddressTLSIE(
393 MachineBasicBlock::iterator &NextMBBI, bool Large) {
394 if (Large)
395 // Emit the 5-insn large address load sequence with the `%ie_pc` family
396 // of relocs, loading the result with `ldx.d` in the end.
397 return expandLargeAddressLoad(MBB, MBBI, NextMBBI, LoongArch::LDX_D,
399
400 // Code Sequence:
401 // pcalau12i $rd, %ie_pc_hi20(sym)
402 // ld.w/d $rd, $rd, %ie_pc_lo12(sym)
404 const auto &STI = MF->getSubtarget<LoongArchSubtarget>();
405 unsigned SecondOpcode = STI.is64Bit() ? LoongArch::LD_D : LoongArch::LD_W;
406 return expandPcalau12iInstPair(MBB, MBBI, NextMBBI, LoongArchII::MO_IE_PC_HI,
407 SecondOpcode, LoongArchII::MO_IE_PC_LO);
408}
409
410bool LoongArchPreRAExpandPseudo::expandLoadAddressTLSLD(
412 MachineBasicBlock::iterator &NextMBBI, bool Large) {
413 if (Large)
414 // Emit the 5-insn large address load sequence with the `%got_pc` family
415 // of relocs, with the `pcalau12i` insn relocated with `%ld_pc_hi20`.
416 return expandLargeAddressLoad(MBB, MBBI, NextMBBI, LoongArch::ADD_D,
418
419 // Code Sequence:
420 // pcalau12i $rd, %ld_pc_hi20(sym)
421 // addi.w/d $rd, $rd, %got_pc_lo12(sym)
423 const auto &STI = MF->getSubtarget<LoongArchSubtarget>();
424 unsigned SecondOpcode = STI.is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W;
425 return expandPcalau12iInstPair(MBB, MBBI, NextMBBI, LoongArchII::MO_LD_PC_HI,
426 SecondOpcode, LoongArchII::MO_GOT_PC_LO);
427}
428
429bool LoongArchPreRAExpandPseudo::expandLoadAddressTLSGD(
431 MachineBasicBlock::iterator &NextMBBI, bool Large) {
432 if (Large)
433 // Emit the 5-insn large address load sequence with the `%got_pc` family
434 // of relocs, with the `pcalau12i` insn relocated with `%gd_pc_hi20`.
435 return expandLargeAddressLoad(MBB, MBBI, NextMBBI, LoongArch::ADD_D,
437
438 // Code Sequence:
439 // pcalau12i $rd, %gd_pc_hi20(sym)
440 // addi.w/d $rd, $rd, %got_pc_lo12(sym)
442 const auto &STI = MF->getSubtarget<LoongArchSubtarget>();
443 unsigned SecondOpcode = STI.is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W;
444 return expandPcalau12iInstPair(MBB, MBBI, NextMBBI, LoongArchII::MO_GD_PC_HI,
445 SecondOpcode, LoongArchII::MO_GOT_PC_LO);
446}
447
448bool LoongArchPreRAExpandPseudo::expandLoadAddressTLSDesc(
450 MachineBasicBlock::iterator &NextMBBI, bool Large) {
452 MachineInstr &MI = *MBBI;
453 DebugLoc DL = MI.getDebugLoc();
454
455 const auto &STI = MF->getSubtarget<LoongArchSubtarget>();
456 unsigned ADD = STI.is64Bit() ? LoongArch::ADD_D : LoongArch::ADD_W;
457 unsigned ADDI = STI.is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W;
458 unsigned LD = STI.is64Bit() ? LoongArch::LD_D : LoongArch::LD_W;
459
460 Register DestReg = MI.getOperand(0).getReg();
461 Register Tmp1Reg =
462 MF->getRegInfo().createVirtualRegister(&LoongArch::GPRRegClass);
463 MachineOperand &Symbol = MI.getOperand(Large ? 2 : 1);
464
465 BuildMI(MBB, MBBI, DL, TII->get(LoongArch::PCALAU12I), Tmp1Reg)
467
468 if (Large) {
469 // Code Sequence:
470 //
471 // pcalau12i $a0, %desc_pc_hi20(sym)
472 // addi.d $a1, $zero, %desc_pc_lo12(sym)
473 // lu32i.d $a1, %desc64_pc_lo20(sym)
474 // lu52i.d $a1, $a1, %desc64_pc_hi12(sym)
475 // add.d $a0, $a0, $a1
476 // ld.d $ra, $a0, %desc_ld(sym)
477 // jirl $ra, $ra, %desc_call(sym)
478 // add.d $dst, $a0, $tp
480 "Large code model requires LA64");
481 Register Tmp2Reg =
482 MF->getRegInfo().createVirtualRegister(&LoongArch::GPRRegClass);
483 Register Tmp3Reg =
484 MF->getRegInfo().createVirtualRegister(&LoongArch::GPRRegClass);
485 Register Tmp4Reg =
486 MF->getRegInfo().createVirtualRegister(&LoongArch::GPRRegClass);
487 BuildMI(MBB, MBBI, DL, TII->get(LoongArch::ADDI_D), Tmp2Reg)
488 .addReg(LoongArch::R0)
490 BuildMI(MBB, MBBI, DL, TII->get(LoongArch::LU32I_D), Tmp3Reg)
491 .addReg(Tmp2Reg, RegState::Kill)
493 BuildMI(MBB, MBBI, DL, TII->get(LoongArch::LU52I_D), Tmp4Reg)
494 .addReg(Tmp3Reg)
496 BuildMI(MBB, MBBI, DL, TII->get(LoongArch::ADD_D), LoongArch::R4)
497 .addReg(Tmp1Reg)
498 .addReg(Tmp4Reg);
499 } else {
500 // Code Sequence:
501 // pcalau12i $a0, %desc_pc_hi20(sym)
502 // addi.w/d $a0, $a0, %desc_pc_lo12(sym)
503 // ld.w/d $ra, $a0, %desc_ld(sym)
504 // jirl $ra, $ra, %desc_ld(sym)
505 // add.d $dst, $a0, $tp
506 BuildMI(MBB, MBBI, DL, TII->get(ADDI), LoongArch::R4)
507 .addReg(Tmp1Reg)
509 }
510
511 BuildMI(MBB, MBBI, DL, TII->get(LD), LoongArch::R1)
512 .addReg(LoongArch::R4)
513 .addDisp(Symbol, 0, LoongArchII::MO_DESC_LD);
514 BuildMI(MBB, MBBI, DL, TII->get(LoongArch::PseudoDESC_CALL), LoongArch::R1)
515 .addReg(LoongArch::R1)
517 BuildMI(MBB, MBBI, DL, TII->get(ADD), DestReg)
518 .addReg(LoongArch::R4)
519 .addReg(LoongArch::R2);
520
521 MI.eraseFromParent();
522 return true;
523}
524
525bool LoongArchPreRAExpandPseudo::expandFunctionCALL(
527 MachineBasicBlock::iterator &NextMBBI, bool IsTailCall) {
529 MachineInstr &MI = *MBBI;
530 DebugLoc DL = MI.getDebugLoc();
531 const MachineOperand &Func = MI.getOperand(0);
533 unsigned Opcode;
534
535 switch (MF->getTarget().getCodeModel()) {
536 default:
537 report_fatal_error("Unsupported code model");
538 break;
539 case CodeModel::Small: {
540 // CALL:
541 // bl func
542 // TAIL:
543 // b func
544 Opcode = IsTailCall ? LoongArch::PseudoB_TAIL : LoongArch::BL;
545 CALL = BuildMI(MBB, MBBI, DL, TII->get(Opcode)).add(Func);
546 break;
547 }
548 case CodeModel::Medium: {
549 // CALL:
550 // pcaddu18i $ra, %call36(func)
551 // jirl $ra, $ra, 0
552 // TAIL:
553 // pcaddu18i $scratch, %call36(func)
554 // jirl $r0, $scratch, 0
555 Opcode =
556 IsTailCall ? LoongArch::PseudoJIRL_TAIL : LoongArch::PseudoJIRL_CALL;
557 Register ScratchReg =
558 IsTailCall
559 ? MF->getRegInfo().createVirtualRegister(&LoongArch::GPRRegClass)
560 : LoongArch::R1;
562 BuildMI(MBB, MBBI, DL, TII->get(LoongArch::PCADDU18I), ScratchReg);
563
564 CALL =
565 BuildMI(MBB, MBBI, DL, TII->get(Opcode)).addReg(ScratchReg).addImm(0);
566
567 if (Func.isSymbol())
568 MIB.addExternalSymbol(Func.getSymbolName(), LoongArchII::MO_CALL36);
569 else
570 MIB.addDisp(Func, 0, LoongArchII::MO_CALL36);
571 break;
572 }
573 case CodeModel::Large: {
574 // Emit the 5-insn large address load sequence, either directly or
575 // indirectly in case of going through the GOT, then JIRL_TAIL or
576 // JIRL_CALL to $addr.
577 Opcode =
578 IsTailCall ? LoongArch::PseudoJIRL_TAIL : LoongArch::PseudoJIRL_CALL;
579 Register AddrReg =
580 IsTailCall
581 ? MF->getRegInfo().createVirtualRegister(&LoongArch::GPRRegClass)
582 : LoongArch::R1;
583
584 bool UseGOT = Func.isGlobal() && !Func.getGlobal()->isDSOLocal();
586 unsigned LAOpcode = UseGOT ? LoongArch::LDX_D : LoongArch::ADD_D;
587 expandLargeAddressLoad(MBB, MBBI, NextMBBI, LAOpcode, MO, Func, AddrReg,
588 false);
589 CALL = BuildMI(MBB, MBBI, DL, TII->get(Opcode)).addReg(AddrReg).addImm(0);
590 break;
591 }
592 }
593
594 // Transfer implicit operands.
595 CALL.copyImplicitOps(MI);
596
597 // Transfer MI flags.
598 CALL.setMIFlags(MI.getFlags());
599
600 MI.eraseFromParent();
601 return true;
602}
603
604class LoongArchExpandPseudo : public MachineFunctionPass {
605public:
606 const LoongArchInstrInfo *TII;
607 static char ID;
608
609 LoongArchExpandPseudo() : MachineFunctionPass(ID) {
611 }
612
613 bool runOnMachineFunction(MachineFunction &MF) override;
614
615 StringRef getPassName() const override {
617 }
618
619private:
620 bool expandMBB(MachineBasicBlock &MBB);
625};
626
627char LoongArchExpandPseudo::ID = 0;
628
629bool LoongArchExpandPseudo::runOnMachineFunction(MachineFunction &MF) {
630 TII =
631 static_cast<const LoongArchInstrInfo *>(MF.getSubtarget().getInstrInfo());
632
633 bool Modified = false;
634 for (auto &MBB : MF)
635 Modified |= expandMBB(MBB);
636
637 return Modified;
638}
639
640bool LoongArchExpandPseudo::expandMBB(MachineBasicBlock &MBB) {
641 bool Modified = false;
642
644 while (MBBI != E) {
645 MachineBasicBlock::iterator NMBBI = std::next(MBBI);
646 Modified |= expandMI(MBB, MBBI, NMBBI);
647 MBBI = NMBBI;
648 }
649
650 return Modified;
651}
652
653bool LoongArchExpandPseudo::expandMI(MachineBasicBlock &MBB,
655 MachineBasicBlock::iterator &NextMBBI) {
656 switch (MBBI->getOpcode()) {
657 case LoongArch::PseudoCopyCFR:
658 return expandCopyCFR(MBB, MBBI, NextMBBI);
659 }
660
661 return false;
662}
663
664bool LoongArchExpandPseudo::expandCopyCFR(
666 MachineBasicBlock::iterator &NextMBBI) {
668 MachineInstr &MI = *MBBI;
669 DebugLoc DL = MI.getDebugLoc();
670
671 // Expand:
672 // MBB:
673 // fcmp.caf.s $dst, $fa0, $fa0 # set $dst 0(false)
674 // bceqz $src, SinkBB
675 // FalseBB:
676 // fcmp.cueq.s $dst, $fa0, $fa0 # set $dst 1(true)
677 // SinkBB:
678 // fallthrough
679
680 const BasicBlock *LLVM_BB = MBB.getBasicBlock();
681 auto *FalseBB = MF->CreateMachineBasicBlock(LLVM_BB);
682 auto *SinkBB = MF->CreateMachineBasicBlock(LLVM_BB);
683
684 MF->insert(++MBB.getIterator(), FalseBB);
685 MF->insert(++FalseBB->getIterator(), SinkBB);
686
687 Register DestReg = MI.getOperand(0).getReg();
688 Register SrcReg = MI.getOperand(1).getReg();
689 // DestReg = 0
690 BuildMI(MBB, MBBI, DL, TII->get(LoongArch::SET_CFR_FALSE), DestReg);
691 // Insert branch instruction.
692 BuildMI(MBB, MBBI, DL, TII->get(LoongArch::BCEQZ))
693 .addReg(SrcReg)
694 .addMBB(SinkBB);
695 // DestReg = 1
696 BuildMI(FalseBB, DL, TII->get(LoongArch::SET_CFR_TRUE), DestReg);
697
698 FalseBB->addSuccessor(SinkBB);
699
700 SinkBB->splice(SinkBB->end(), &MBB, MI, MBB.end());
701 SinkBB->transferSuccessors(&MBB);
702
703 MBB.addSuccessor(FalseBB);
704 MBB.addSuccessor(SinkBB);
705
706 NextMBBI = MBB.end();
707 MI.eraseFromParent();
708
709 // Make sure live-ins are correctly attached to this new basic block.
710 LivePhysRegs LiveRegs;
711 computeAndAddLiveIns(LiveRegs, *FalseBB);
712 computeAndAddLiveIns(LiveRegs, *SinkBB);
713
714 return true;
715}
716
717} // end namespace
718
719INITIALIZE_PASS(LoongArchPreRAExpandPseudo, "loongarch-prera-expand-pseudo",
721
722INITIALIZE_PASS(LoongArchExpandPseudo, "loongarch-expand-pseudo",
724
725namespace llvm {
726
728 return new LoongArchPreRAExpandPseudo();
729}
731 return new LoongArchExpandPseudo();
732}
733
734} // 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:256
LLVM Basic Block Representation.
Definition: BasicBlock.h:61
A debug info location.
Definition: DebugLoc.h:33
FunctionPass class - This class is used to implement most global optimizations.
Definition: Pass.h:310
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
constexpr bool isVirtual() const
Return true if the specified register number is in the virtual register namespace.
Definition: Register.h:91
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:132
#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:167
FunctionPass * createLoongArchPreRAExpandPseudoPass()
FunctionPass * createLoongArchExpandPseudoPass()
void computeAndAddLiveIns(LivePhysRegs &LiveRegs, MachineBasicBlock &MBB)
Convenience function combining computeLiveIns() and addLiveIns().