Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/llvm/lib/Target/LoongArch/LoongArchExpandPseudoInsts.cpp
35269 views
1
//===-- LoongArchExpandPseudoInsts.cpp - Expand pseudo instructions -------===//
2
//
3
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4
// See https://llvm.org/LICENSE.txt for license information.
5
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6
//
7
//===----------------------------------------------------------------------===//
8
//
9
// This file contains a pass that expands pseudo instructions into target
10
// instructions.
11
//
12
//===----------------------------------------------------------------------===//
13
14
#include "LoongArch.h"
15
#include "LoongArchInstrInfo.h"
16
#include "LoongArchTargetMachine.h"
17
#include "MCTargetDesc/LoongArchBaseInfo.h"
18
#include "MCTargetDesc/LoongArchMCTargetDesc.h"
19
#include "llvm/CodeGen/LivePhysRegs.h"
20
#include "llvm/CodeGen/MachineFunctionPass.h"
21
#include "llvm/CodeGen/MachineInstrBuilder.h"
22
#include "llvm/CodeGen/MachineOperand.h"
23
#include "llvm/CodeGen/Register.h"
24
#include "llvm/MC/MCContext.h"
25
#include "llvm/Support/CodeGen.h"
26
#include "llvm/Support/ErrorHandling.h"
27
28
using namespace llvm;
29
30
#define LOONGARCH_PRERA_EXPAND_PSEUDO_NAME \
31
"LoongArch Pre-RA pseudo instruction expansion pass"
32
#define LOONGARCH_EXPAND_PSEUDO_NAME \
33
"LoongArch pseudo instruction expansion pass"
34
35
namespace {
36
37
class LoongArchPreRAExpandPseudo : public MachineFunctionPass {
38
public:
39
const LoongArchInstrInfo *TII;
40
static char ID;
41
42
LoongArchPreRAExpandPseudo() : MachineFunctionPass(ID) {
43
initializeLoongArchPreRAExpandPseudoPass(*PassRegistry::getPassRegistry());
44
}
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
56
private:
57
bool expandMBB(MachineBasicBlock &MBB);
58
bool expandMI(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
59
MachineBasicBlock::iterator &NextMBBI);
60
bool expandPcalau12iInstPair(MachineBasicBlock &MBB,
61
MachineBasicBlock::iterator MBBI,
62
MachineBasicBlock::iterator &NextMBBI,
63
unsigned FlagsHi, unsigned SecondOpcode,
64
unsigned FlagsLo);
65
bool expandLoadAddressPcrel(MachineBasicBlock &MBB,
66
MachineBasicBlock::iterator MBBI,
67
MachineBasicBlock::iterator &NextMBBI);
68
bool expandLoadAddressGot(MachineBasicBlock &MBB,
69
MachineBasicBlock::iterator MBBI,
70
MachineBasicBlock::iterator &NextMBBI);
71
bool expandLoadAddressTLSLE(MachineBasicBlock &MBB,
72
MachineBasicBlock::iterator MBBI,
73
MachineBasicBlock::iterator &NextMBBI);
74
bool expandLoadAddressTLSIE(MachineBasicBlock &MBB,
75
MachineBasicBlock::iterator MBBI,
76
MachineBasicBlock::iterator &NextMBBI);
77
bool expandLoadAddressTLSLD(MachineBasicBlock &MBB,
78
MachineBasicBlock::iterator MBBI,
79
MachineBasicBlock::iterator &NextMBBI);
80
bool expandLoadAddressTLSGD(MachineBasicBlock &MBB,
81
MachineBasicBlock::iterator MBBI,
82
MachineBasicBlock::iterator &NextMBBI);
83
bool expandLoadAddressTLSDesc(MachineBasicBlock &MBB,
84
MachineBasicBlock::iterator MBBI,
85
MachineBasicBlock::iterator &NextMBBI);
86
};
87
88
char LoongArchPreRAExpandPseudo::ID = 0;
89
90
bool LoongArchPreRAExpandPseudo::runOnMachineFunction(MachineFunction &MF) {
91
TII =
92
static_cast<const LoongArchInstrInfo *>(MF.getSubtarget().getInstrInfo());
93
bool Modified = false;
94
for (auto &MBB : MF)
95
Modified |= expandMBB(MBB);
96
return Modified;
97
}
98
99
bool LoongArchPreRAExpandPseudo::expandMBB(MachineBasicBlock &MBB) {
100
bool Modified = false;
101
102
MachineBasicBlock::iterator MBBI = MBB.begin(), E = MBB.end();
103
while (MBBI != E) {
104
MachineBasicBlock::iterator NMBBI = std::next(MBBI);
105
Modified |= expandMI(MBB, MBBI, NMBBI);
106
MBBI = NMBBI;
107
}
108
109
return Modified;
110
}
111
112
bool LoongArchPreRAExpandPseudo::expandMI(
113
MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
114
MachineBasicBlock::iterator &NextMBBI) {
115
switch (MBBI->getOpcode()) {
116
case LoongArch::PseudoLA_PCREL:
117
return expandLoadAddressPcrel(MBB, MBBI, NextMBBI);
118
case LoongArch::PseudoLA_GOT:
119
return expandLoadAddressGot(MBB, MBBI, NextMBBI);
120
case LoongArch::PseudoLA_TLS_LE:
121
return expandLoadAddressTLSLE(MBB, MBBI, NextMBBI);
122
case LoongArch::PseudoLA_TLS_IE:
123
return expandLoadAddressTLSIE(MBB, MBBI, NextMBBI);
124
case LoongArch::PseudoLA_TLS_LD:
125
return expandLoadAddressTLSLD(MBB, MBBI, NextMBBI);
126
case LoongArch::PseudoLA_TLS_GD:
127
return expandLoadAddressTLSGD(MBB, MBBI, NextMBBI);
128
case LoongArch::PseudoLA_TLS_DESC_PC:
129
return expandLoadAddressTLSDesc(MBB, MBBI, NextMBBI);
130
}
131
return false;
132
}
133
134
bool LoongArchPreRAExpandPseudo::expandPcalau12iInstPair(
135
MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
136
MachineBasicBlock::iterator &NextMBBI, unsigned FlagsHi,
137
unsigned SecondOpcode, unsigned FlagsLo) {
138
MachineFunction *MF = MBB.getParent();
139
MachineInstr &MI = *MBBI;
140
DebugLoc DL = MI.getDebugLoc();
141
142
Register DestReg = MI.getOperand(0).getReg();
143
Register ScratchReg =
144
MF->getRegInfo().createVirtualRegister(&LoongArch::GPRRegClass);
145
MachineOperand &Symbol = MI.getOperand(1);
146
147
BuildMI(MBB, MBBI, DL, TII->get(LoongArch::PCALAU12I), ScratchReg)
148
.addDisp(Symbol, 0, FlagsHi);
149
150
MachineInstr *SecondMI =
151
BuildMI(MBB, MBBI, DL, TII->get(SecondOpcode), DestReg)
152
.addReg(ScratchReg)
153
.addDisp(Symbol, 0, FlagsLo);
154
155
if (MI.hasOneMemOperand())
156
SecondMI->addMemOperand(*MF, *MI.memoperands_begin());
157
158
MI.eraseFromParent();
159
return true;
160
}
161
162
bool LoongArchPreRAExpandPseudo::expandLoadAddressPcrel(
163
MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
164
MachineBasicBlock::iterator &NextMBBI) {
165
// Code Sequence:
166
// pcalau12i $rd, %pc_hi20(sym)
167
// addi.w/d $rd, $rd, %pc_lo12(sym)
168
MachineFunction *MF = MBB.getParent();
169
const auto &STI = MF->getSubtarget<LoongArchSubtarget>();
170
unsigned SecondOpcode = STI.is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W;
171
return expandPcalau12iInstPair(MBB, MBBI, NextMBBI, LoongArchII::MO_PCREL_HI,
172
SecondOpcode, LoongArchII::MO_PCREL_LO);
173
}
174
175
bool LoongArchPreRAExpandPseudo::expandLoadAddressGot(
176
MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
177
MachineBasicBlock::iterator &NextMBBI) {
178
// Code Sequence:
179
// pcalau12i $rd, %got_pc_hi20(sym)
180
// ld.w/d $rd, $rd, %got_pc_lo12(sym)
181
MachineFunction *MF = MBB.getParent();
182
const auto &STI = MF->getSubtarget<LoongArchSubtarget>();
183
unsigned SecondOpcode = STI.is64Bit() ? LoongArch::LD_D : LoongArch::LD_W;
184
return expandPcalau12iInstPair(MBB, MBBI, NextMBBI, LoongArchII::MO_GOT_PC_HI,
185
SecondOpcode, LoongArchII::MO_GOT_PC_LO);
186
}
187
188
bool LoongArchPreRAExpandPseudo::expandLoadAddressTLSLE(
189
MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
190
MachineBasicBlock::iterator &NextMBBI) {
191
// Code Sequence:
192
// lu12i.w $rd, %le_hi20(sym)
193
// ori $rd, $rd, %le_lo12(sym)
194
//
195
// And additionally if generating code using the large code model:
196
//
197
// lu32i.d $rd, %le64_lo20(sym)
198
// lu52i.d $rd, $rd, %le64_hi12(sym)
199
MachineFunction *MF = MBB.getParent();
200
MachineInstr &MI = *MBBI;
201
DebugLoc DL = MI.getDebugLoc();
202
203
bool Large = MF->getTarget().getCodeModel() == CodeModel::Large;
204
Register DestReg = MI.getOperand(0).getReg();
205
Register Parts01 =
206
Large ? MF->getRegInfo().createVirtualRegister(&LoongArch::GPRRegClass)
207
: DestReg;
208
Register Part1 =
209
MF->getRegInfo().createVirtualRegister(&LoongArch::GPRRegClass);
210
MachineOperand &Symbol = MI.getOperand(1);
211
212
BuildMI(MBB, MBBI, DL, TII->get(LoongArch::LU12I_W), Part1)
213
.addDisp(Symbol, 0, LoongArchII::MO_LE_HI);
214
215
BuildMI(MBB, MBBI, DL, TII->get(LoongArch::ORI), Parts01)
216
.addReg(Part1, RegState::Kill)
217
.addDisp(Symbol, 0, LoongArchII::MO_LE_LO);
218
219
if (Large) {
220
Register Parts012 =
221
MF->getRegInfo().createVirtualRegister(&LoongArch::GPRRegClass);
222
223
BuildMI(MBB, MBBI, DL, TII->get(LoongArch::LU32I_D), Parts012)
224
// "rj" is needed due to InstrInfo pattern requirement.
225
.addReg(Parts01, RegState::Kill)
226
.addDisp(Symbol, 0, LoongArchII::MO_LE64_LO);
227
BuildMI(MBB, MBBI, DL, TII->get(LoongArch::LU52I_D), DestReg)
228
.addReg(Parts012, RegState::Kill)
229
.addDisp(Symbol, 0, LoongArchII::MO_LE64_HI);
230
}
231
232
MI.eraseFromParent();
233
return true;
234
}
235
236
bool LoongArchPreRAExpandPseudo::expandLoadAddressTLSIE(
237
MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
238
MachineBasicBlock::iterator &NextMBBI) {
239
// Code Sequence:
240
// pcalau12i $rd, %ie_pc_hi20(sym)
241
// ld.w/d $rd, $rd, %ie_pc_lo12(sym)
242
MachineFunction *MF = MBB.getParent();
243
const auto &STI = MF->getSubtarget<LoongArchSubtarget>();
244
unsigned SecondOpcode = STI.is64Bit() ? LoongArch::LD_D : LoongArch::LD_W;
245
return expandPcalau12iInstPair(MBB, MBBI, NextMBBI, LoongArchII::MO_IE_PC_HI,
246
SecondOpcode, LoongArchII::MO_IE_PC_LO);
247
}
248
249
bool LoongArchPreRAExpandPseudo::expandLoadAddressTLSLD(
250
MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
251
MachineBasicBlock::iterator &NextMBBI) {
252
// Code Sequence:
253
// pcalau12i $rd, %ld_pc_hi20(sym)
254
// addi.w/d $rd, $rd, %got_pc_lo12(sym)
255
MachineFunction *MF = MBB.getParent();
256
const auto &STI = MF->getSubtarget<LoongArchSubtarget>();
257
unsigned SecondOpcode = STI.is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W;
258
return expandPcalau12iInstPair(MBB, MBBI, NextMBBI, LoongArchII::MO_LD_PC_HI,
259
SecondOpcode, LoongArchII::MO_GOT_PC_LO);
260
}
261
262
bool LoongArchPreRAExpandPseudo::expandLoadAddressTLSGD(
263
MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
264
MachineBasicBlock::iterator &NextMBBI) {
265
// Code Sequence:
266
// pcalau12i $rd, %gd_pc_hi20(sym)
267
// addi.w/d $rd, $rd, %got_pc_lo12(sym)
268
MachineFunction *MF = MBB.getParent();
269
const auto &STI = MF->getSubtarget<LoongArchSubtarget>();
270
unsigned SecondOpcode = STI.is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W;
271
return expandPcalau12iInstPair(MBB, MBBI, NextMBBI, LoongArchII::MO_GD_PC_HI,
272
SecondOpcode, LoongArchII::MO_GOT_PC_LO);
273
}
274
275
bool LoongArchPreRAExpandPseudo::expandLoadAddressTLSDesc(
276
MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
277
MachineBasicBlock::iterator &NextMBBI) {
278
// Code Sequence:
279
// pcalau12i $a0, %desc_pc_hi20(sym)
280
// addi.w/d $a0, $a0, %desc_pc_lo12(sym)
281
// ld.w/d $ra, $a0, %desc_ld(sym)
282
// jirl $ra, $ra, %desc_ld(sym)
283
// add.d $dst, $a0, $tp
284
MachineFunction *MF = MBB.getParent();
285
MachineInstr &MI = *MBBI;
286
DebugLoc DL = MI.getDebugLoc();
287
288
const auto &STI = MF->getSubtarget<LoongArchSubtarget>();
289
unsigned ADD = STI.is64Bit() ? LoongArch::ADD_D : LoongArch::ADD_W;
290
unsigned ADDI = STI.is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W;
291
unsigned LD = STI.is64Bit() ? LoongArch::LD_D : LoongArch::LD_W;
292
293
Register DestReg = MI.getOperand(0).getReg();
294
Register ScratchReg =
295
MF->getRegInfo().createVirtualRegister(&LoongArch::GPRRegClass);
296
MachineOperand &Symbol = MI.getOperand(1);
297
298
BuildMI(MBB, MBBI, DL, TII->get(LoongArch::PCALAU12I), ScratchReg)
299
.addDisp(Symbol, 0, LoongArchII::MO_DESC_PC_HI);
300
301
BuildMI(MBB, MBBI, DL, TII->get(ADDI), LoongArch::R4)
302
.addReg(ScratchReg)
303
.addDisp(Symbol, 0, LoongArchII::MO_DESC_PC_LO);
304
305
BuildMI(MBB, MBBI, DL, TII->get(LD), LoongArch::R1)
306
.addReg(LoongArch::R4)
307
.addDisp(Symbol, 0, LoongArchII::MO_DESC_LD);
308
309
BuildMI(MBB, MBBI, DL, TII->get(LoongArch::PseudoDESC_CALL), LoongArch::R1)
310
.addReg(LoongArch::R1)
311
.addDisp(Symbol, 0, LoongArchII::MO_DESC_CALL);
312
313
BuildMI(MBB, MBBI, DL, TII->get(ADD), DestReg)
314
.addReg(LoongArch::R4)
315
.addReg(LoongArch::R2);
316
317
MI.eraseFromParent();
318
return true;
319
}
320
321
class LoongArchExpandPseudo : public MachineFunctionPass {
322
public:
323
const LoongArchInstrInfo *TII;
324
static char ID;
325
326
LoongArchExpandPseudo() : MachineFunctionPass(ID) {
327
initializeLoongArchExpandPseudoPass(*PassRegistry::getPassRegistry());
328
}
329
330
bool runOnMachineFunction(MachineFunction &MF) override;
331
332
StringRef getPassName() const override {
333
return LOONGARCH_EXPAND_PSEUDO_NAME;
334
}
335
336
private:
337
bool expandMBB(MachineBasicBlock &MBB);
338
bool expandMI(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
339
MachineBasicBlock::iterator &NextMBBI);
340
bool expandCopyCFR(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
341
MachineBasicBlock::iterator &NextMBBI);
342
bool expandLargeAddressLoad(MachineBasicBlock &MBB,
343
MachineBasicBlock::iterator MBBI,
344
MachineBasicBlock::iterator &NextMBBI,
345
unsigned LastOpcode, unsigned IdentifyingMO);
346
bool expandLargeAddressLoad(MachineBasicBlock &MBB,
347
MachineBasicBlock::iterator MBBI,
348
MachineBasicBlock::iterator &NextMBBI,
349
unsigned LastOpcode, unsigned IdentifyingMO,
350
const MachineOperand &Symbol, Register DestReg,
351
bool EraseFromParent);
352
bool expandLoadAddressPcrelLarge(MachineBasicBlock &MBB,
353
MachineBasicBlock::iterator MBBI,
354
MachineBasicBlock::iterator &NextMBBI);
355
bool expandLoadAddressGotLarge(MachineBasicBlock &MBB,
356
MachineBasicBlock::iterator MBBI,
357
MachineBasicBlock::iterator &NextMBBI);
358
bool expandLoadAddressTLSIELarge(MachineBasicBlock &MBB,
359
MachineBasicBlock::iterator MBBI,
360
MachineBasicBlock::iterator &NextMBBI);
361
bool expandLoadAddressTLSLDLarge(MachineBasicBlock &MBB,
362
MachineBasicBlock::iterator MBBI,
363
MachineBasicBlock::iterator &NextMBBI);
364
bool expandLoadAddressTLSGDLarge(MachineBasicBlock &MBB,
365
MachineBasicBlock::iterator MBBI,
366
MachineBasicBlock::iterator &NextMBBI);
367
bool expandLoadAddressTLSDescPcLarge(MachineBasicBlock &MBB,
368
MachineBasicBlock::iterator MBBI,
369
MachineBasicBlock::iterator &NextMBBI);
370
bool expandFunctionCALL(MachineBasicBlock &MBB,
371
MachineBasicBlock::iterator MBBI,
372
MachineBasicBlock::iterator &NextMBBI,
373
bool IsTailCall);
374
};
375
376
char LoongArchExpandPseudo::ID = 0;
377
378
bool LoongArchExpandPseudo::runOnMachineFunction(MachineFunction &MF) {
379
TII =
380
static_cast<const LoongArchInstrInfo *>(MF.getSubtarget().getInstrInfo());
381
382
bool Modified = false;
383
for (auto &MBB : MF)
384
Modified |= expandMBB(MBB);
385
386
return Modified;
387
}
388
389
bool LoongArchExpandPseudo::expandMBB(MachineBasicBlock &MBB) {
390
bool Modified = false;
391
392
MachineBasicBlock::iterator MBBI = MBB.begin(), E = MBB.end();
393
while (MBBI != E) {
394
MachineBasicBlock::iterator NMBBI = std::next(MBBI);
395
Modified |= expandMI(MBB, MBBI, NMBBI);
396
MBBI = NMBBI;
397
}
398
399
return Modified;
400
}
401
402
bool LoongArchExpandPseudo::expandMI(MachineBasicBlock &MBB,
403
MachineBasicBlock::iterator MBBI,
404
MachineBasicBlock::iterator &NextMBBI) {
405
switch (MBBI->getOpcode()) {
406
case LoongArch::PseudoCopyCFR:
407
return expandCopyCFR(MBB, MBBI, NextMBBI);
408
case LoongArch::PseudoLA_PCREL_LARGE:
409
return expandLoadAddressPcrelLarge(MBB, MBBI, NextMBBI);
410
case LoongArch::PseudoLA_GOT_LARGE:
411
return expandLoadAddressGotLarge(MBB, MBBI, NextMBBI);
412
case LoongArch::PseudoLA_TLS_IE_LARGE:
413
return expandLoadAddressTLSIELarge(MBB, MBBI, NextMBBI);
414
case LoongArch::PseudoLA_TLS_LD_LARGE:
415
return expandLoadAddressTLSLDLarge(MBB, MBBI, NextMBBI);
416
case LoongArch::PseudoLA_TLS_GD_LARGE:
417
return expandLoadAddressTLSGDLarge(MBB, MBBI, NextMBBI);
418
case LoongArch::PseudoLA_TLS_DESC_PC_LARGE:
419
return expandLoadAddressTLSDescPcLarge(MBB, MBBI, NextMBBI);
420
case LoongArch::PseudoCALL:
421
case LoongArch::PseudoCALL_MEDIUM:
422
case LoongArch::PseudoCALL_LARGE:
423
return expandFunctionCALL(MBB, MBBI, NextMBBI, /*IsTailCall=*/false);
424
case LoongArch::PseudoTAIL:
425
case LoongArch::PseudoTAIL_MEDIUM:
426
case LoongArch::PseudoTAIL_LARGE:
427
return expandFunctionCALL(MBB, MBBI, NextMBBI, /*IsTailCall=*/true);
428
}
429
430
return false;
431
}
432
433
bool LoongArchExpandPseudo::expandCopyCFR(
434
MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
435
MachineBasicBlock::iterator &NextMBBI) {
436
MachineFunction *MF = MBB.getParent();
437
MachineInstr &MI = *MBBI;
438
DebugLoc DL = MI.getDebugLoc();
439
440
// Expand:
441
// MBB:
442
// fcmp.caf.s $dst, $fa0, $fa0 # set $dst 0(false)
443
// bceqz $src, SinkBB
444
// FalseBB:
445
// fcmp.cueq.s $dst, $fa0, $fa0 # set $dst 1(true)
446
// SinkBB:
447
// fallthrough
448
449
const BasicBlock *LLVM_BB = MBB.getBasicBlock();
450
auto *FalseBB = MF->CreateMachineBasicBlock(LLVM_BB);
451
auto *SinkBB = MF->CreateMachineBasicBlock(LLVM_BB);
452
453
MF->insert(++MBB.getIterator(), FalseBB);
454
MF->insert(++FalseBB->getIterator(), SinkBB);
455
456
Register DestReg = MI.getOperand(0).getReg();
457
Register SrcReg = MI.getOperand(1).getReg();
458
// DestReg = 0
459
BuildMI(MBB, MBBI, DL, TII->get(LoongArch::SET_CFR_FALSE), DestReg);
460
// Insert branch instruction.
461
BuildMI(MBB, MBBI, DL, TII->get(LoongArch::BCEQZ))
462
.addReg(SrcReg)
463
.addMBB(SinkBB);
464
// DestReg = 1
465
BuildMI(FalseBB, DL, TII->get(LoongArch::SET_CFR_TRUE), DestReg);
466
467
FalseBB->addSuccessor(SinkBB);
468
469
SinkBB->splice(SinkBB->end(), &MBB, MI, MBB.end());
470
SinkBB->transferSuccessors(&MBB);
471
472
MBB.addSuccessor(FalseBB);
473
MBB.addSuccessor(SinkBB);
474
475
NextMBBI = MBB.end();
476
MI.eraseFromParent();
477
478
// Make sure live-ins are correctly attached to this new basic block.
479
LivePhysRegs LiveRegs;
480
computeAndAddLiveIns(LiveRegs, *FalseBB);
481
computeAndAddLiveIns(LiveRegs, *SinkBB);
482
483
return true;
484
}
485
486
bool LoongArchExpandPseudo::expandLargeAddressLoad(
487
MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
488
MachineBasicBlock::iterator &NextMBBI, unsigned LastOpcode,
489
unsigned IdentifyingMO) {
490
MachineInstr &MI = *MBBI;
491
return expandLargeAddressLoad(MBB, MBBI, NextMBBI, LastOpcode, IdentifyingMO,
492
MI.getOperand(2), MI.getOperand(0).getReg(),
493
true);
494
}
495
496
bool LoongArchExpandPseudo::expandLargeAddressLoad(
497
MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
498
MachineBasicBlock::iterator &NextMBBI, unsigned LastOpcode,
499
unsigned IdentifyingMO, const MachineOperand &Symbol, Register DestReg,
500
bool EraseFromParent) {
501
// Code Sequence:
502
//
503
// Part1: pcalau12i $dst, %MO1(sym)
504
// Part0: addi.d $t8, $zero, %MO0(sym)
505
// Part2: lu32i.d $t8, %MO2(sym)
506
// Part3: lu52i.d $t8, $t8, %MO3(sym)
507
// Fin: LastOpcode $dst, $t8, $dst
508
509
unsigned MO0, MO1, MO2, MO3;
510
switch (IdentifyingMO) {
511
default:
512
llvm_unreachable("unsupported identifying MO");
513
case LoongArchII::MO_PCREL_LO:
514
MO0 = IdentifyingMO;
515
MO1 = LoongArchII::MO_PCREL_HI;
516
MO2 = LoongArchII::MO_PCREL64_LO;
517
MO3 = LoongArchII::MO_PCREL64_HI;
518
break;
519
case LoongArchII::MO_GOT_PC_HI:
520
case LoongArchII::MO_LD_PC_HI:
521
case LoongArchII::MO_GD_PC_HI:
522
// These cases relocate just like the GOT case, except for Part1.
523
MO0 = LoongArchII::MO_GOT_PC_LO;
524
MO1 = IdentifyingMO;
525
MO2 = LoongArchII::MO_GOT_PC64_LO;
526
MO3 = LoongArchII::MO_GOT_PC64_HI;
527
break;
528
case LoongArchII::MO_IE_PC_LO:
529
MO0 = IdentifyingMO;
530
MO1 = LoongArchII::MO_IE_PC_HI;
531
MO2 = LoongArchII::MO_IE_PC64_LO;
532
MO3 = LoongArchII::MO_IE_PC64_HI;
533
break;
534
}
535
536
MachineInstr &MI = *MBBI;
537
DebugLoc DL = MI.getDebugLoc();
538
Register ScratchReg = LoongArch::R20; // $t8
539
540
assert(MBB.getParent()->getSubtarget<LoongArchSubtarget>().is64Bit() &&
541
"Large code model requires LA64");
542
543
auto Part1 = BuildMI(MBB, MBBI, DL, TII->get(LoongArch::PCALAU12I), DestReg);
544
auto Part0 = BuildMI(MBB, MBBI, DL, TII->get(LoongArch::ADDI_D), ScratchReg)
545
.addReg(LoongArch::R0);
546
auto Part2 = BuildMI(MBB, MBBI, DL, TII->get(LoongArch::LU32I_D), ScratchReg)
547
// "rj" is needed due to InstrInfo pattern requirement.
548
.addReg(ScratchReg);
549
auto Part3 = BuildMI(MBB, MBBI, DL, TII->get(LoongArch::LU52I_D), ScratchReg)
550
.addReg(ScratchReg);
551
BuildMI(MBB, MBBI, DL, TII->get(LastOpcode), DestReg)
552
.addReg(ScratchReg)
553
.addReg(DestReg);
554
555
if (Symbol.getType() == MachineOperand::MO_ExternalSymbol) {
556
const char *SymName = Symbol.getSymbolName();
557
Part0.addExternalSymbol(SymName, MO0);
558
Part1.addExternalSymbol(SymName, MO1);
559
Part2.addExternalSymbol(SymName, MO2);
560
Part3.addExternalSymbol(SymName, MO3);
561
} else {
562
Part0.addDisp(Symbol, 0, MO0);
563
Part1.addDisp(Symbol, 0, MO1);
564
Part2.addDisp(Symbol, 0, MO2);
565
Part3.addDisp(Symbol, 0, MO3);
566
}
567
568
if (EraseFromParent)
569
MI.eraseFromParent();
570
571
return true;
572
}
573
574
bool LoongArchExpandPseudo::expandLoadAddressPcrelLarge(
575
MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
576
MachineBasicBlock::iterator &NextMBBI) {
577
// Emit the 5-insn large address load sequence with the `%pc` family of
578
// relocs.
579
return expandLargeAddressLoad(MBB, MBBI, NextMBBI, LoongArch::ADD_D,
580
LoongArchII::MO_PCREL_LO);
581
}
582
583
bool LoongArchExpandPseudo::expandLoadAddressGotLarge(
584
MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
585
MachineBasicBlock::iterator &NextMBBI) {
586
// Emit the 5-insn large address load sequence with the `%got_pc` family
587
// of relocs, loading the result from GOT with `ldx.d` in the end.
588
return expandLargeAddressLoad(MBB, MBBI, NextMBBI, LoongArch::LDX_D,
589
LoongArchII::MO_GOT_PC_HI);
590
}
591
592
bool LoongArchExpandPseudo::expandLoadAddressTLSIELarge(
593
MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
594
MachineBasicBlock::iterator &NextMBBI) {
595
// Emit the 5-insn large address load sequence with the `%ie_pc` family
596
// of relocs, loading the result with `ldx.d` in the end.
597
return expandLargeAddressLoad(MBB, MBBI, NextMBBI, LoongArch::LDX_D,
598
LoongArchII::MO_IE_PC_LO);
599
}
600
601
bool LoongArchExpandPseudo::expandLoadAddressTLSLDLarge(
602
MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
603
MachineBasicBlock::iterator &NextMBBI) {
604
// Emit the 5-insn large address load sequence with the `%got_pc` family
605
// of relocs, with the `pcalau12i` insn relocated with `%ld_pc_hi20`.
606
return expandLargeAddressLoad(MBB, MBBI, NextMBBI, LoongArch::ADD_D,
607
LoongArchII::MO_LD_PC_HI);
608
}
609
610
bool LoongArchExpandPseudo::expandLoadAddressTLSGDLarge(
611
MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
612
MachineBasicBlock::iterator &NextMBBI) {
613
// Emit the 5-insn large address load sequence with the `%got_pc` family
614
// of relocs, with the `pcalau12i` insn relocated with `%gd_pc_hi20`.
615
return expandLargeAddressLoad(MBB, MBBI, NextMBBI, LoongArch::ADD_D,
616
LoongArchII::MO_GD_PC_HI);
617
}
618
619
bool LoongArchExpandPseudo::expandLoadAddressTLSDescPcLarge(
620
MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
621
MachineBasicBlock::iterator &NextMBBI) {
622
// Code Sequence:
623
//
624
// pcalau12i $a0, %desc_pc_hi20(sym)
625
// addi.d $t8, $zero, %desc_pc_lo12(sym)
626
// lu32i.d $t8, %desc64_pc_lo20(sym)
627
// lu52i.d $t8, $t8, %desc64_pc_hi12(sym)
628
// add.d $a0, $a0, $t8
629
// ld.d $ra, $a0, %desc_ld(sym)
630
// jirl $ra, $ra, %desc_call(sym)
631
// add.d $dst, $a0, $tp
632
633
MachineInstr &MI = *MBBI;
634
DebugLoc DL = MI.getDebugLoc();
635
Register DestReg = MI.getOperand(0).getReg();
636
MachineOperand &Symbol = MI.getOperand(2);
637
Register ScratchReg = LoongArch::R20; // $t8
638
639
assert(MBB.getParent()->getSubtarget<LoongArchSubtarget>().is64Bit() &&
640
"Large code model requires LA64");
641
642
BuildMI(MBB, MBBI, DL, TII->get(LoongArch::PCALAU12I), LoongArch::R4)
643
.addDisp(Symbol, 0, LoongArchII::MO_DESC_PC_HI);
644
BuildMI(MBB, MBBI, DL, TII->get(LoongArch::ADDI_D), ScratchReg)
645
.addReg(LoongArch::R0)
646
.addDisp(Symbol, 0, LoongArchII::MO_DESC_PC_LO);
647
BuildMI(MBB, MBBI, DL, TII->get(LoongArch::LU32I_D), ScratchReg)
648
.addReg(ScratchReg)
649
.addDisp(Symbol, 0, LoongArchII::MO_DESC64_PC_LO);
650
BuildMI(MBB, MBBI, DL, TII->get(LoongArch::LU52I_D), ScratchReg)
651
.addReg(ScratchReg)
652
.addDisp(Symbol, 0, LoongArchII::MO_DESC64_PC_HI);
653
BuildMI(MBB, MBBI, DL, TII->get(LoongArch::ADD_D), LoongArch::R4)
654
.addReg(ScratchReg)
655
.addReg(LoongArch::R4);
656
BuildMI(MBB, MBBI, DL, TII->get(LoongArch::LD_D), LoongArch::R1)
657
.addReg(LoongArch::R4)
658
.addDisp(Symbol, 0, LoongArchII::MO_DESC_LD);
659
BuildMI(MBB, MBBI, DL, TII->get(LoongArch::PseudoDESC_CALL), LoongArch::R1)
660
.addReg(LoongArch::R1)
661
.addDisp(Symbol, 0, LoongArchII::MO_DESC_CALL);
662
BuildMI(MBB, MBBI, DL, TII->get(LoongArch::ADD_D), DestReg)
663
.addReg(LoongArch::R4)
664
.addReg(LoongArch::R2);
665
666
MI.eraseFromParent();
667
668
return true;
669
}
670
671
bool LoongArchExpandPseudo::expandFunctionCALL(
672
MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
673
MachineBasicBlock::iterator &NextMBBI, bool IsTailCall) {
674
MachineFunction *MF = MBB.getParent();
675
MachineInstr &MI = *MBBI;
676
DebugLoc DL = MI.getDebugLoc();
677
const MachineOperand &Func = MI.getOperand(0);
678
MachineInstrBuilder CALL;
679
unsigned Opcode;
680
681
switch (MF->getTarget().getCodeModel()) {
682
default:
683
report_fatal_error("Unsupported code model");
684
break;
685
case CodeModel::Small: {
686
// CALL:
687
// bl func
688
// TAIL:
689
// b func
690
Opcode = IsTailCall ? LoongArch::PseudoB_TAIL : LoongArch::BL;
691
CALL = BuildMI(MBB, MBBI, DL, TII->get(Opcode)).add(Func);
692
break;
693
}
694
case CodeModel::Medium: {
695
// CALL:
696
// pcaddu18i $ra, %call36(func)
697
// jirl $ra, $ra, 0
698
// TAIL:
699
// pcaddu18i $t8, %call36(func)
700
// jr $t8
701
Opcode =
702
IsTailCall ? LoongArch::PseudoJIRL_TAIL : LoongArch::PseudoJIRL_CALL;
703
Register ScratchReg = IsTailCall ? LoongArch::R20 : LoongArch::R1;
704
MachineInstrBuilder MIB =
705
BuildMI(MBB, MBBI, DL, TII->get(LoongArch::PCADDU18I), ScratchReg);
706
707
CALL =
708
BuildMI(MBB, MBBI, DL, TII->get(Opcode)).addReg(ScratchReg).addImm(0);
709
710
if (Func.isSymbol())
711
MIB.addExternalSymbol(Func.getSymbolName(), LoongArchII::MO_CALL36);
712
else
713
MIB.addDisp(Func, 0, LoongArchII::MO_CALL36);
714
break;
715
}
716
case CodeModel::Large: {
717
// Emit the 5-insn large address load sequence, either directly or
718
// indirectly in case of going through the GOT, then JIRL_TAIL or
719
// JIRL_CALL to $addr.
720
Opcode =
721
IsTailCall ? LoongArch::PseudoJIRL_TAIL : LoongArch::PseudoJIRL_CALL;
722
Register AddrReg = IsTailCall ? LoongArch::R19 : LoongArch::R1;
723
724
bool UseGOT = Func.getTargetFlags() == LoongArchII::MO_CALL_PLT;
725
unsigned MO = UseGOT ? LoongArchII::MO_GOT_PC_HI : LoongArchII::MO_PCREL_LO;
726
unsigned LAOpcode = UseGOT ? LoongArch::LDX_D : LoongArch::ADD_D;
727
expandLargeAddressLoad(MBB, MBBI, NextMBBI, LAOpcode, MO, Func, AddrReg,
728
false);
729
CALL = BuildMI(MBB, MBBI, DL, TII->get(Opcode)).addReg(AddrReg).addImm(0);
730
break;
731
}
732
}
733
734
// Transfer implicit operands.
735
CALL.copyImplicitOps(MI);
736
737
// Transfer MI flags.
738
CALL.setMIFlags(MI.getFlags());
739
740
MI.eraseFromParent();
741
return true;
742
}
743
744
} // end namespace
745
746
INITIALIZE_PASS(LoongArchPreRAExpandPseudo, "loongarch-prera-expand-pseudo",
747
LOONGARCH_PRERA_EXPAND_PSEUDO_NAME, false, false)
748
749
INITIALIZE_PASS(LoongArchExpandPseudo, "loongarch-expand-pseudo",
750
LOONGARCH_EXPAND_PSEUDO_NAME, false, false)
751
752
namespace llvm {
753
754
FunctionPass *createLoongArchPreRAExpandPseudoPass() {
755
return new LoongArchPreRAExpandPseudo();
756
}
757
FunctionPass *createLoongArchExpandPseudoPass() {
758
return new LoongArchExpandPseudo();
759
}
760
761
} // end namespace llvm
762
763