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 "LoongArchMachineFunctionInfo.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
28using namespace llvm;
29
30extern cl::opt<bool> LArchAnnotateTableJump;
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:
41 const LoongArchInstrInfo *TII;
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();
50 MachineFunctionPass::getAnalysisUsage(AU);
51 }
52 StringRef getPassName() const override {
53 return LOONGARCH_PRERA_EXPAND_PSEUDO_NAME;
54 }
55
56private:
57 bool expandMBB(MachineBasicBlock &MBB);
58 bool expandMI(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
59 MachineBasicBlock::iterator &NextMBBI);
60 bool expandPcaxxu12iInstPair(MachineBasicBlock &MBB,
61 MachineBasicBlock::iterator MBBI,
62 MachineBasicBlock::iterator &NextMBBI,
63 unsigned OpcodeHi, unsigned OpcodeLo,
64 unsigned FlagsHi, unsigned FlagsLo);
65 bool expandLargeAddressLoad(MachineBasicBlock &MBB,
66 MachineBasicBlock::iterator MBBI,
67 MachineBasicBlock::iterator &NextMBBI,
68 unsigned LastOpcode, unsigned IdentifyingMO);
69 bool expandLargeAddressLoad(MachineBasicBlock &MBB,
70 MachineBasicBlock::iterator MBBI,
71 MachineBasicBlock::iterator &NextMBBI,
72 unsigned LastOpcode, unsigned IdentifyingMO,
73 const MachineOperand &Symbol, Register DestReg,
74 bool EraseFromParent);
75 bool expandLoadAddressPcrel(MachineBasicBlock &MBB,
76 MachineBasicBlock::iterator MBBI,
77 MachineBasicBlock::iterator &NextMBBI,
78 bool Large = false);
79 bool expandLoadAddressGot(MachineBasicBlock &MBB,
80 MachineBasicBlock::iterator MBBI,
81 MachineBasicBlock::iterator &NextMBBI,
82 bool Large = false);
83 bool expandLoadAddressTLSLE(MachineBasicBlock &MBB,
84 MachineBasicBlock::iterator MBBI,
85 MachineBasicBlock::iterator &NextMBBI);
86 bool expandLoadAddressTLSIE(MachineBasicBlock &MBB,
87 MachineBasicBlock::iterator MBBI,
88 MachineBasicBlock::iterator &NextMBBI,
89 bool Large = false);
90 bool expandLoadAddressTLSLD(MachineBasicBlock &MBB,
91 MachineBasicBlock::iterator MBBI,
92 MachineBasicBlock::iterator &NextMBBI,
93 bool Large = false);
94 bool expandLoadAddressTLSGD(MachineBasicBlock &MBB,
95 MachineBasicBlock::iterator MBBI,
96 MachineBasicBlock::iterator &NextMBBI,
97 bool Large = false);
98 bool expandLoadAddressTLSDesc(MachineBasicBlock &MBB,
99 MachineBasicBlock::iterator MBBI,
100 MachineBasicBlock::iterator &NextMBBI,
101 bool Large = false);
102 bool expandFunctionCALL(MachineBasicBlock &MBB,
103 MachineBasicBlock::iterator MBBI,
104 MachineBasicBlock::iterator &NextMBBI,
105 bool IsTailCall);
106 void annotateTableJump(MachineBasicBlock &MBB,
107 MachineBasicBlock::iterator MBBI);
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(x: MBBI);
127 Modified |= expandMI(MBB, MBBI, NextMBBI&: NMBBI);
128 MBBI = NMBBI;
129 }
130
131 return Modified;
132}
133
134bool LoongArchPreRAExpandPseudo::expandMI(
135 MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
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.
173 if (LArchAnnotateTableJump)
174 annotateTableJump(MBB, MBBI);
175 break;
176 }
177 return false;
178}
179
180bool LoongArchPreRAExpandPseudo::expandPcaxxu12iInstPair(
181 MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
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(Feature: LoongArch::FeatureRelax);
190
191 Register DestReg = MI.getOperand(i: 0).getReg();
192 Register ScratchReg =
193 MF->getRegInfo().createVirtualRegister(RegClass: &LoongArch::GPRRegClass);
194 MachineOperand &Symbol = MI.getOperand(i: 1);
195
196 MachineInstr *FirstMI =
197 BuildMI(BB&: MBB, I: MBBI, MIMD: DL, MCID: TII->get(Opcode: OpcodeHi), DestReg: ScratchReg)
198 .addDisp(Disp: Symbol, off: 0, TargetFlags: LoongArchII::encodeFlags(Flags: FlagsHi, Relax: EnableRelax));
199
200 MachineInstr *SecondMI = nullptr;
201 FlagsLo = LoongArchII::encodeFlags(Flags: FlagsLo, Relax: EnableRelax);
202
203 if (OpcodeHi == LoongArch::PCALAU12I) {
204 SecondMI = BuildMI(BB&: MBB, I: MBBI, MIMD: DL, MCID: TII->get(Opcode: OpcodeLo), DestReg)
205 .addReg(RegNo: ScratchReg)
206 .addDisp(Disp: Symbol, off: 0, TargetFlags: FlagsLo);
207 } else {
208 MCSymbol *PCAddSymbol = MF->getContext().createNamedTempSymbol(Name: "pcadd_hi");
209 FirstMI->setPreInstrSymbol(MF&: *MF, Symbol: PCAddSymbol);
210 SecondMI = BuildMI(BB&: MBB, I: MBBI, MIMD: DL, MCID: TII->get(Opcode: OpcodeLo), DestReg)
211 .addReg(RegNo: ScratchReg)
212 .addSym(Sym: PCAddSymbol, TargetFlags: FlagsLo);
213 }
214
215 if (MI.hasOneMemOperand())
216 SecondMI->addMemOperand(MF&: *MF, MO: *MI.memoperands_begin());
217
218 MI.eraseFromParent();
219 return true;
220}
221
222bool LoongArchPreRAExpandPseudo::expandLargeAddressLoad(
223 MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
224 MachineBasicBlock::iterator &NextMBBI, unsigned LastOpcode,
225 unsigned IdentifyingMO) {
226 MachineInstr &MI = *MBBI;
227 return expandLargeAddressLoad(MBB, MBBI, NextMBBI, LastOpcode, IdentifyingMO,
228 Symbol: MI.getOperand(i: 2), DestReg: MI.getOperand(i: 0).getReg(),
229 EraseFromParent: true);
230}
231
232bool LoongArchPreRAExpandPseudo::expandLargeAddressLoad(
233 MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
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");
249 case LoongArchII::MO_PCREL_LO:
250 MO0 = IdentifyingMO;
251 MO1 = LoongArchII::MO_PCREL_HI;
252 MO2 = LoongArchII::MO_PCREL64_LO;
253 MO3 = LoongArchII::MO_PCREL64_HI;
254 break;
255 case LoongArchII::MO_GOT_PC_HI:
256 case LoongArchII::MO_LD_PC_HI:
257 case LoongArchII::MO_GD_PC_HI:
258 // These cases relocate just like the GOT case, except for Part1.
259 MO0 = LoongArchII::MO_GOT_PC_LO;
260 MO1 = IdentifyingMO;
261 MO2 = LoongArchII::MO_GOT_PC64_LO;
262 MO3 = LoongArchII::MO_GOT_PC64_HI;
263 break;
264 case LoongArchII::MO_IE_PC_LO:
265 MO0 = IdentifyingMO;
266 MO1 = LoongArchII::MO_IE_PC_HI;
267 MO2 = LoongArchII::MO_IE_PC64_LO;
268 MO3 = LoongArchII::MO_IE_PC64_HI;
269 break;
270 }
271
272 MachineFunction *MF = MBB.getParent();
273 MachineInstr &MI = *MBBI;
274 DebugLoc DL = MI.getDebugLoc();
275
276 assert(MF->getSubtarget<LoongArchSubtarget>().is64Bit() &&
277 "Large code model requires LA64");
278
279 Register TmpPart1 =
280 MF->getRegInfo().createVirtualRegister(RegClass: &LoongArch::GPRRegClass);
281 Register TmpPart0 =
282 DestReg.isVirtual()
283 ? MF->getRegInfo().createVirtualRegister(RegClass: &LoongArch::GPRRegClass)
284 : DestReg;
285 Register TmpParts02 =
286 DestReg.isVirtual()
287 ? MF->getRegInfo().createVirtualRegister(RegClass: &LoongArch::GPRRegClass)
288 : DestReg;
289 Register TmpParts023 =
290 DestReg.isVirtual()
291 ? MF->getRegInfo().createVirtualRegister(RegClass: &LoongArch::GPRRegClass)
292 : DestReg;
293
294 auto Part1 = BuildMI(BB&: MBB, I: MBBI, MIMD: DL, MCID: TII->get(Opcode: LoongArch::PCALAU12I), DestReg: TmpPart1);
295 auto Part0 = BuildMI(BB&: MBB, I: MBBI, MIMD: DL, MCID: TII->get(Opcode: LoongArch::ADDI_D), DestReg: TmpPart0)
296 .addReg(RegNo: LoongArch::R0);
297 auto Part2 = BuildMI(BB&: MBB, I: MBBI, MIMD: DL, MCID: TII->get(Opcode: LoongArch::LU32I_D), DestReg: TmpParts02)
298 // "rj" is needed due to InstrInfo pattern requirement.
299 .addReg(RegNo: TmpPart0, Flags: RegState::Kill);
300 auto Part3 = BuildMI(BB&: MBB, I: MBBI, MIMD: DL, MCID: TII->get(Opcode: LoongArch::LU52I_D), DestReg: TmpParts023)
301 .addReg(RegNo: TmpParts02, Flags: RegState::Kill);
302 BuildMI(BB&: MBB, I: MBBI, MIMD: DL, MCID: TII->get(Opcode: LastOpcode), DestReg)
303 .addReg(RegNo: TmpParts023)
304 .addReg(RegNo: TmpPart1, Flags: RegState::Kill);
305
306 if (Symbol.getType() == MachineOperand::MO_ExternalSymbol) {
307 const char *SymName = Symbol.getSymbolName();
308 Part0.addExternalSymbol(FnName: SymName, TargetFlags: MO0);
309 Part1.addExternalSymbol(FnName: SymName, TargetFlags: MO1);
310 Part2.addExternalSymbol(FnName: SymName, TargetFlags: MO2);
311 Part3.addExternalSymbol(FnName: SymName, TargetFlags: MO3);
312 } else {
313 Part0.addDisp(Disp: Symbol, off: 0, TargetFlags: MO0);
314 Part1.addDisp(Disp: Symbol, off: 0, TargetFlags: MO1);
315 Part2.addDisp(Disp: Symbol, off: 0, TargetFlags: MO2);
316 Part3.addDisp(Disp: Symbol, off: 0, TargetFlags: MO3);
317 }
318
319 if (EraseFromParent)
320 MI.eraseFromParent();
321
322 return true;
323}
324
325bool LoongArchPreRAExpandPseudo::expandLoadAddressPcrel(
326 MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
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, LastOpcode: LoongArch::ADD_D,
332 IdentifyingMO: LoongArchII::MO_PCREL_LO);
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(Feature: LoongArch::Feature32S);
347 unsigned OpcodeHi = Has32S ? LoongArch::PCALAU12I : LoongArch::PCADDU12I;
348 unsigned OpcodeLo = STI.is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W;
349 unsigned FlagsHi =
350 Has32S ? LoongArchII::MO_PCREL_HI : LoongArchII::MO_PCADD_HI;
351 unsigned FlagsLo =
352 Has32S ? LoongArchII::MO_PCREL_LO : LoongArchII::MO_PCADD_LO;
353 return expandPcaxxu12iInstPair(MBB, MBBI, NextMBBI, OpcodeHi, OpcodeLo,
354 FlagsHi, FlagsLo);
355}
356
357bool LoongArchPreRAExpandPseudo::expandLoadAddressGot(
358 MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
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, LastOpcode: LoongArch::LDX_D,
364 IdentifyingMO: LoongArchII::MO_GOT_PC_HI);
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(Feature: LoongArch::Feature32S);
379 unsigned OpcodeHi = Has32S ? LoongArch::PCALAU12I : LoongArch::PCADDU12I;
380 unsigned OpcodeLo = STI.is64Bit() ? LoongArch::LD_D : LoongArch::LD_W;
381 unsigned FlagsHi =
382 Has32S ? LoongArchII::MO_GOT_PC_HI : LoongArchII::MO_GOT_PCADD_HI;
383 unsigned FlagsLo =
384 Has32S ? LoongArchII::MO_GOT_PC_LO : LoongArchII::MO_GOT_PCADD_LO;
385 return expandPcaxxu12iInstPair(MBB, MBBI, NextMBBI, OpcodeHi, OpcodeLo,
386 FlagsHi, FlagsLo);
387}
388
389bool LoongArchPreRAExpandPseudo::expandLoadAddressTLSLE(
390 MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
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(i: 0).getReg();
408 Register Parts01 =
409 MF->getRegInfo().createVirtualRegister(RegClass: &LoongArch::GPRRegClass);
410 Register Part1 =
411 MF->getRegInfo().createVirtualRegister(RegClass: &LoongArch::GPRRegClass);
412 MachineOperand &Symbol = MI.getOperand(i: 1);
413
414 if (!Large) {
415 BuildMI(BB&: MBB, I: MBBI, MIMD: DL, MCID: TII->get(Opcode: LoongArch::LU12I_W), DestReg: Part1)
416 .addDisp(Disp: Symbol, off: 0, TargetFlags: 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(BB&: MBB, I: MBBI, MIMD: DL, MCID: TII->get(Opcode: AddOp), DestReg: Parts01)
422 .addReg(RegNo: Part1, Flags: RegState::Kill)
423 .addReg(RegNo: LoongArch::R2)
424 .addDisp(Disp: Symbol, off: 0, TargetFlags: LoongArchII::MO_LE_ADD_R);
425
426 unsigned AddiOp = STI.is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W;
427 BuildMI(BB&: MBB, I: MBBI, MIMD: DL, MCID: TII->get(Opcode: AddiOp), DestReg)
428 .addReg(RegNo: Parts01, Flags: RegState::Kill)
429 .addDisp(Disp: Symbol, off: 0, TargetFlags: LoongArchII::MO_LE_LO_R);
430 } else {
431 BuildMI(BB&: MBB, I: MBBI, MIMD: DL, MCID: TII->get(Opcode: LoongArch::LU12I_W), DestReg: Part1)
432 .addDisp(Disp: Symbol, off: 0, TargetFlags: LoongArchII::MO_LE_HI);
433
434 BuildMI(BB&: MBB, I: MBBI, MIMD: DL, MCID: TII->get(Opcode: LoongArch::ORI), DestReg: Parts01)
435 .addReg(RegNo: Part1, Flags: RegState::Kill)
436 .addDisp(Disp: Symbol, off: 0, TargetFlags: LoongArchII::MO_LE_LO);
437
438 Register Parts012 =
439 MF->getRegInfo().createVirtualRegister(RegClass: &LoongArch::GPRRegClass);
440
441 BuildMI(BB&: MBB, I: MBBI, MIMD: DL, MCID: TII->get(Opcode: LoongArch::LU32I_D), DestReg: Parts012)
442 // "rj" is needed due to InstrInfo pattern requirement.
443 .addReg(RegNo: Parts01, Flags: RegState::Kill)
444 .addDisp(Disp: Symbol, off: 0, TargetFlags: LoongArchII::MO_LE64_LO);
445 BuildMI(BB&: MBB, I: MBBI, MIMD: DL, MCID: TII->get(Opcode: LoongArch::LU52I_D), DestReg)
446 .addReg(RegNo: Parts012, Flags: RegState::Kill)
447 .addDisp(Disp: Symbol, off: 0, TargetFlags: LoongArchII::MO_LE64_HI);
448 }
449
450 MI.eraseFromParent();
451 return true;
452}
453
454bool LoongArchPreRAExpandPseudo::expandLoadAddressTLSIE(
455 MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
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, LastOpcode: LoongArch::LDX_D,
461 IdentifyingMO: LoongArchII::MO_IE_PC_LO);
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(Feature: LoongArch::Feature32S);
476 unsigned OpcodeHi = Has32S ? LoongArch::PCALAU12I : LoongArch::PCADDU12I;
477 unsigned OpcodeLo = STI.is64Bit() ? LoongArch::LD_D : LoongArch::LD_W;
478 unsigned FlagsHi =
479 Has32S ? LoongArchII::MO_IE_PC_HI : LoongArchII::MO_IE_PCADD_HI;
480 unsigned FlagsLo =
481 Has32S ? LoongArchII::MO_IE_PC_LO : LoongArchII::MO_IE_PCADD_LO;
482 return expandPcaxxu12iInstPair(MBB, MBBI, NextMBBI, OpcodeHi, OpcodeLo,
483 FlagsHi, FlagsLo);
484}
485
486bool LoongArchPreRAExpandPseudo::expandLoadAddressTLSLD(
487 MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
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, LastOpcode: LoongArch::ADD_D,
493 IdentifyingMO: LoongArchII::MO_LD_PC_HI);
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(Feature: LoongArch::Feature32S);
508 unsigned OpcodeHi = Has32S ? LoongArch::PCALAU12I : LoongArch::PCADDU12I;
509 unsigned OpcodeLo = STI.is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W;
510 unsigned FlagsHi =
511 Has32S ? LoongArchII::MO_LD_PC_HI : LoongArchII::MO_LD_PCADD_HI;
512 unsigned FlagsLo =
513 Has32S ? LoongArchII::MO_GOT_PC_LO : LoongArchII::MO_LD_PCADD_LO;
514 return expandPcaxxu12iInstPair(MBB, MBBI, NextMBBI, OpcodeHi, OpcodeLo,
515 FlagsHi, FlagsLo);
516}
517
518bool LoongArchPreRAExpandPseudo::expandLoadAddressTLSGD(
519 MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
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, LastOpcode: LoongArch::ADD_D,
525 IdentifyingMO: LoongArchII::MO_GD_PC_HI);
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(Feature: LoongArch::Feature32S);
540 unsigned OpcodeHi = Has32S ? LoongArch::PCALAU12I : LoongArch::PCADDU12I;
541 unsigned OpcodeLo = STI.is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W;
542 unsigned FlagsHi =
543 Has32S ? LoongArchII::MO_GD_PC_HI : LoongArchII::MO_GD_PCADD_HI;
544 unsigned FlagsLo =
545 Has32S ? LoongArchII::MO_GOT_PC_LO : LoongArchII::MO_GD_PCADD_LO;
546 return expandPcaxxu12iInstPair(MBB, MBBI, NextMBBI, OpcodeHi, OpcodeLo,
547 FlagsHi, FlagsLo);
548}
549
550bool LoongArchPreRAExpandPseudo::expandLoadAddressTLSDesc(
551 MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
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(Feature: LoongArch::Feature32S);
559 bool EnableRelax = STI.hasFeature(Feature: 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 =
565 Has32S ? LoongArchII::MO_DESC_PC_HI : LoongArchII::MO_DESC_PCADD_HI;
566
567 Register DestReg = MI.getOperand(i: 0).getReg();
568 Register Tmp1Reg =
569 MF->getRegInfo().createVirtualRegister(RegClass: &LoongArch::GPRRegClass);
570 MachineOperand &Symbol = MI.getOperand(i: Large ? 2 : 1);
571
572 MachineInstr *PCAMI =
573 BuildMI(BB&: MBB, I: MBBI, MIMD: DL, MCID: TII->get(Opcode: PCA), DestReg: Tmp1Reg)
574 .addDisp(Disp: Symbol, off: 0,
575 TargetFlags: LoongArchII::encodeFlags(Flags: MO, Relax: 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(RegClass: &LoongArch::GPRRegClass);
592 Register Tmp3Reg =
593 MF->getRegInfo().createVirtualRegister(RegClass: &LoongArch::GPRRegClass);
594 Register Tmp4Reg =
595 MF->getRegInfo().createVirtualRegister(RegClass: &LoongArch::GPRRegClass);
596 BuildMI(BB&: MBB, I: MBBI, MIMD: DL, MCID: TII->get(Opcode: LoongArch::ADDI_D), DestReg: Tmp2Reg)
597 .addReg(RegNo: LoongArch::R0)
598 .addDisp(Disp: Symbol, off: 0, TargetFlags: LoongArchII::MO_DESC_PC_LO);
599 BuildMI(BB&: MBB, I: MBBI, MIMD: DL, MCID: TII->get(Opcode: LoongArch::LU32I_D), DestReg: Tmp3Reg)
600 .addReg(RegNo: Tmp2Reg, Flags: RegState::Kill)
601 .addDisp(Disp: Symbol, off: 0, TargetFlags: LoongArchII::MO_DESC64_PC_LO);
602 BuildMI(BB&: MBB, I: MBBI, MIMD: DL, MCID: TII->get(Opcode: LoongArch::LU52I_D), DestReg: Tmp4Reg)
603 .addReg(RegNo: Tmp3Reg)
604 .addDisp(Disp: Symbol, off: 0, TargetFlags: LoongArchII::MO_DESC64_PC_HI);
605 BuildMI(BB&: MBB, I: MBBI, MIMD: DL, MCID: TII->get(Opcode: LoongArch::ADD_D), DestReg: LoongArch::R4)
606 .addReg(RegNo: Tmp1Reg)
607 .addReg(RegNo: 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(BB&: MBB, I: MBBI, MIMD: DL, MCID: TII->get(Opcode: ADDI), DestReg: LoongArch::R4)
627 .addReg(RegNo: Tmp1Reg)
628 .addDisp(Disp: Symbol, off: 0,
629 TargetFlags: LoongArchII::encodeFlags(Flags: LoongArchII::MO_DESC_PC_LO,
630 Relax: EnableRelax));
631 } else {
632 MCSymbol *PCASymbol = MF->getContext().createNamedTempSymbol(Name: "pcadd_hi");
633 PCAMI->setPreInstrSymbol(MF&: *MF, Symbol: PCASymbol);
634 BuildMI(BB&: MBB, I: MBBI, MIMD: DL, MCID: TII->get(Opcode: ADDI), DestReg: LoongArch::R4)
635 .addReg(RegNo: Tmp1Reg)
636 .addSym(Sym: PCASymbol, TargetFlags: LoongArchII::encodeFlags(
637 Flags: LoongArchII::MO_DESC_PCADD_LO, Relax: EnableRelax));
638 }
639 }
640
641 BuildMI(BB&: MBB, I: MBBI, MIMD: DL, MCID: TII->get(Opcode: LD), DestReg: LoongArch::R1)
642 .addReg(RegNo: LoongArch::R4)
643 .addDisp(Disp: Symbol, off: 0,
644 TargetFlags: LoongArchII::encodeFlags(Flags: LoongArchII::MO_DESC_LD,
645 Relax: EnableRelax && !Large));
646 BuildMI(BB&: MBB, I: MBBI, MIMD: DL, MCID: TII->get(Opcode: LoongArch::PseudoDESC_CALL), DestReg: LoongArch::R1)
647 .addReg(RegNo: LoongArch::R1)
648 .addDisp(Disp: Symbol, off: 0,
649 TargetFlags: LoongArchII::encodeFlags(Flags: LoongArchII::MO_DESC_CALL,
650 Relax: EnableRelax && !Large));
651 BuildMI(BB&: MBB, I: MBBI, MIMD: DL, MCID: TII->get(Opcode: ADD), DestReg)
652 .addReg(RegNo: LoongArch::R4)
653 .addReg(RegNo: LoongArch::R2);
654
655 MI.eraseFromParent();
656 return true;
657}
658
659bool LoongArchPreRAExpandPseudo::expandFunctionCALL(
660 MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
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(i: 0);
666 MachineInstrBuilder CALL;
667 unsigned Opcode;
668
669 switch (MF->getTarget().getCodeModel()) {
670 default:
671 report_fatal_error(reason: "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(BB&: MBB, I: MBBI, MIMD: DL, MCID: TII->get(Opcode)).add(MO: 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(RegClass: &LoongArch::GPRRegClass)
691 : LoongArch::R1;
692
693 bool UseGOT = Func.getTargetFlags() == LoongArchII::MO_CALL_PLT;
694 unsigned MO = UseGOT ? LoongArchII::MO_GOT_PC_HI : LoongArchII::MO_PCREL_LO;
695 unsigned LAOpcode = UseGOT ? LoongArch::LDX_D : LoongArch::ADD_D;
696 expandLargeAddressLoad(MBB, MBBI, NextMBBI, LastOpcode: LAOpcode, IdentifyingMO: MO, Symbol: Func, DestReg: AddrReg,
697 EraseFromParent: false);
698 CALL = BuildMI(BB&: MBB, I: MBBI, MIMD: DL, MCID: TII->get(Opcode)).addReg(RegNo: AddrReg).addImm(Val: 0);
699 break;
700 }
701 }
702
703 // Transfer implicit operands.
704 CALL.copyImplicitOps(OtherMI: MI);
705
706 // Transfer MI flags.
707 CALL.setMIFlags(MI.getFlags());
708
709 MI.eraseFromParent();
710 return true;
711}
712
713void LoongArchPreRAExpandPseudo::annotateTableJump(
714 MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI) {
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(i: Idx);
735 if (MO.isJTI()) {
736 MBBI->setPreInstrSymbol(
737 MF&: *MF, Symbol: MF->getContext().createNamedTempSymbol(Name: "jrtb_"));
738 MF->getInfo<LoongArchMachineFunctionInfo>()->setJumpInfo(
739 JrMI: &*MBBI, JTIIdx: 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 {
762 return LOONGARCH_EXPAND_PSEUDO_NAME;
763 }
764
765private:
766 bool expandMBB(MachineBasicBlock &MBB);
767 bool expandMI(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
768 MachineBasicBlock::iterator &NextMBBI);
769 bool expandCopyCFR(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
770 MachineBasicBlock::iterator &NextMBBI);
771 bool expandFunctionCALL(MachineBasicBlock &MBB,
772 MachineBasicBlock::iterator MBBI,
773 MachineBasicBlock::iterator &NextMBBI,
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(x: MBBI);
796 Modified |= expandMI(MBB, MBBI, NextMBBI&: NMBBI);
797 MBBI = NMBBI;
798 }
799
800 return Modified;
801}
802
803bool LoongArchExpandPseudo::expandMI(MachineBasicBlock &MBB,
804 MachineBasicBlock::iterator MBBI,
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(
819 MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
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(BB: LLVM_BB);
836 auto *SinkBB = MF->CreateMachineBasicBlock(BB: LLVM_BB);
837
838 MF->insert(MBBI: ++MBB.getIterator(), MBB: FalseBB);
839 MF->insert(MBBI: ++FalseBB->getIterator(), MBB: SinkBB);
840
841 Register DestReg = MI.getOperand(i: 0).getReg();
842 Register SrcReg = MI.getOperand(i: 1).getReg();
843 // DestReg = 0
844 BuildMI(BB&: MBB, I: MBBI, MIMD: DL, MCID: TII->get(Opcode: LoongArch::SET_CFR_FALSE), DestReg);
845 // Insert branch instruction.
846 BuildMI(BB&: MBB, I: MBBI, MIMD: DL, MCID: TII->get(Opcode: LoongArch::BCEQZ))
847 .addReg(RegNo: SrcReg)
848 .addMBB(MBB: SinkBB);
849 // DestReg = 1
850 BuildMI(BB: FalseBB, MIMD: DL, MCID: TII->get(Opcode: LoongArch::SET_CFR_TRUE), DestReg);
851
852 FalseBB->addSuccessor(Succ: SinkBB);
853
854 SinkBB->splice(Where: SinkBB->end(), Other: &MBB, From: MI, To: MBB.end());
855 SinkBB->transferSuccessors(FromMBB: &MBB);
856
857 MBB.addSuccessor(Succ: FalseBB);
858 MBB.addSuccessor(Succ: SinkBB);
859
860 NextMBBI = MBB.end();
861 MI.eraseFromParent();
862
863 // Make sure live-ins are correctly attached to this new basic block.
864 LivePhysRegs LiveRegs;
865 computeAndAddLiveIns(LiveRegs, MBB&: *FalseBB);
866 computeAndAddLiveIns(LiveRegs, MBB&: *SinkBB);
867
868 return true;
869}
870
871bool LoongArchExpandPseudo::expandFunctionCALL(
872 MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
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(i: 0);
878 MachineInstrBuilder CALL;
879 unsigned Opcode;
880
881 switch (MF->getTarget().getCodeModel()) {
882 default:
883 report_fatal_error(reason: "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(BB&: MBB, I: MBBI, MIMD: DL, MCID: TII->get(Opcode: PC), DestReg: ScratchReg);
908
909 CALL =
910 BuildMI(BB&: MBB, I: MBBI, MIMD: DL, MCID: TII->get(Opcode)).addReg(RegNo: ScratchReg).addImm(Val: 0);
911
912 if (Func.isSymbol())
913 MIB.addExternalSymbol(FnName: Func.getSymbolName(), TargetFlags: MO);
914 else
915 MIB.addDisp(Disp: Func, off: 0, TargetFlags: MO);
916 break;
917 }
918 }
919
920 // Transfer implicit operands.
921 CALL.copyImplicitOps(OtherMI: 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",
933 LOONGARCH_PRERA_EXPAND_PSEUDO_NAME, false, false)
934
935INITIALIZE_PASS(LoongArchExpandPseudo, "loongarch-expand-pseudo",
936 LOONGARCH_EXPAND_PSEUDO_NAME, false, false)
937
938namespace llvm {
939
940FunctionPass *createLoongArchPreRAExpandPseudoPass() {
941 return new LoongArchPreRAExpandPseudo();
942}
943FunctionPass *createLoongArchExpandPseudoPass() {
944 return new LoongArchExpandPseudo();
945}
946
947} // end namespace llvm
948