LLVM 17.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"
22#include "llvm/MC/MCContext.h"
24
25using namespace llvm;
26
27#define LOONGARCH_PRERA_EXPAND_PSEUDO_NAME \
28 "LoongArch Pre-RA pseudo instruction expansion pass"
29
30namespace {
31
32class LoongArchPreRAExpandPseudo : public MachineFunctionPass {
33public:
35 static char ID;
36
37 LoongArchPreRAExpandPseudo() : MachineFunctionPass(ID) {
39 }
40
41 bool runOnMachineFunction(MachineFunction &MF) override;
42
43 void getAnalysisUsage(AnalysisUsage &AU) const override {
44 AU.setPreservesCFG();
46 }
47 StringRef getPassName() const override {
49 }
50
51private:
52 bool expandMBB(MachineBasicBlock &MBB);
55 bool expandPcalau12iInstPair(MachineBasicBlock &MBB,
58 unsigned FlagsHi, unsigned SecondOpcode,
59 unsigned FlagsLo);
60 bool expandLoadAddressPcrel(MachineBasicBlock &MBB,
63 bool expandLoadAddressGot(MachineBasicBlock &MBB,
66 bool expandLoadAddressTLSLE(MachineBasicBlock &MBB,
69 bool expandLoadAddressTLSIE(MachineBasicBlock &MBB,
72 bool expandLoadAddressTLSLD(MachineBasicBlock &MBB,
75 bool expandLoadAddressTLSGD(MachineBasicBlock &MBB,
78 bool expandFunctionCALL(MachineBasicBlock &MBB,
81 bool IsTailCall);
82};
83
84char LoongArchPreRAExpandPseudo::ID = 0;
85
86bool LoongArchPreRAExpandPseudo::runOnMachineFunction(MachineFunction &MF) {
87 TII =
88 static_cast<const LoongArchInstrInfo *>(MF.getSubtarget().getInstrInfo());
89 bool Modified = false;
90 for (auto &MBB : MF)
91 Modified |= expandMBB(MBB);
92 return Modified;
93}
94
95bool LoongArchPreRAExpandPseudo::expandMBB(MachineBasicBlock &MBB) {
96 bool Modified = false;
97
99 while (MBBI != E) {
100 MachineBasicBlock::iterator NMBBI = std::next(MBBI);
101 Modified |= expandMI(MBB, MBBI, NMBBI);
102 MBBI = NMBBI;
103 }
104
105 return Modified;
106}
107
108bool LoongArchPreRAExpandPseudo::expandMI(
110 MachineBasicBlock::iterator &NextMBBI) {
111 switch (MBBI->getOpcode()) {
112 case LoongArch::PseudoLA_PCREL:
113 return expandLoadAddressPcrel(MBB, MBBI, NextMBBI);
114 case LoongArch::PseudoLA_GOT:
115 return expandLoadAddressGot(MBB, MBBI, NextMBBI);
116 case LoongArch::PseudoLA_TLS_LE:
117 return expandLoadAddressTLSLE(MBB, MBBI, NextMBBI);
118 case LoongArch::PseudoLA_TLS_IE:
119 return expandLoadAddressTLSIE(MBB, MBBI, NextMBBI);
120 case LoongArch::PseudoLA_TLS_LD:
121 return expandLoadAddressTLSLD(MBB, MBBI, NextMBBI);
122 case LoongArch::PseudoLA_TLS_GD:
123 return expandLoadAddressTLSGD(MBB, MBBI, NextMBBI);
124 case LoongArch::PseudoCALL:
125 return expandFunctionCALL(MBB, MBBI, NextMBBI, /*IsTailCall=*/false);
126 case LoongArch::PseudoTAIL:
127 return expandFunctionCALL(MBB, MBBI, NextMBBI, /*IsTailCall=*/true);
128 }
129 return false;
130}
131
132bool LoongArchPreRAExpandPseudo::expandPcalau12iInstPair(
134 MachineBasicBlock::iterator &NextMBBI, unsigned FlagsHi,
135 unsigned SecondOpcode, unsigned FlagsLo) {
137 MachineInstr &MI = *MBBI;
138 DebugLoc DL = MI.getDebugLoc();
139
140 Register DestReg = MI.getOperand(0).getReg();
141 Register ScratchReg =
142 MF->getRegInfo().createVirtualRegister(&LoongArch::GPRRegClass);
143 MachineOperand &Symbol = MI.getOperand(1);
144
145 BuildMI(MBB, MBBI, DL, TII->get(LoongArch::PCALAU12I), ScratchReg)
146 .addDisp(Symbol, 0, FlagsHi);
147
148 MachineInstr *SecondMI =
149 BuildMI(MBB, MBBI, DL, TII->get(SecondOpcode), DestReg)
150 .addReg(ScratchReg)
151 .addDisp(Symbol, 0, FlagsLo);
152
153 if (MI.hasOneMemOperand())
154 SecondMI->addMemOperand(*MF, *MI.memoperands_begin());
155
156 MI.eraseFromParent();
157 return true;
158}
159
160bool LoongArchPreRAExpandPseudo::expandLoadAddressPcrel(
162 MachineBasicBlock::iterator &NextMBBI) {
163 // Code Sequence:
164 // pcalau12i $rd, %pc_hi20(sym)
165 // addi.w/d $rd, $rd, %pc_lo12(sym)
167 const auto &STI = MF->getSubtarget<LoongArchSubtarget>();
168 unsigned SecondOpcode = STI.is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W;
169 return expandPcalau12iInstPair(MBB, MBBI, NextMBBI, LoongArchII::MO_PCREL_HI,
170 SecondOpcode, LoongArchII::MO_PCREL_LO);
171}
172
173bool LoongArchPreRAExpandPseudo::expandLoadAddressGot(
175 MachineBasicBlock::iterator &NextMBBI) {
176 // Code Sequence:
177 // pcalau12i $rd, %got_pc_hi20(sym)
178 // ld.w/d $rd, $rd, %got_pc_lo12(sym)
180 const auto &STI = MF->getSubtarget<LoongArchSubtarget>();
181 unsigned SecondOpcode = STI.is64Bit() ? LoongArch::LD_D : LoongArch::LD_W;
182 return expandPcalau12iInstPair(MBB, MBBI, NextMBBI, LoongArchII::MO_GOT_PC_HI,
183 SecondOpcode, LoongArchII::MO_GOT_PC_LO);
184}
185
186bool LoongArchPreRAExpandPseudo::expandLoadAddressTLSLE(
188 MachineBasicBlock::iterator &NextMBBI) {
189 // Code Sequence:
190 // lu12i.w $rd, %le_hi20(sym)
191 // ori $rd, $rd, %le_lo12(sym)
193 MachineInstr &MI = *MBBI;
194 DebugLoc DL = MI.getDebugLoc();
195
196 Register DestReg = MI.getOperand(0).getReg();
197 Register ScratchReg =
198 MF->getRegInfo().createVirtualRegister(&LoongArch::GPRRegClass);
199 MachineOperand &Symbol = MI.getOperand(1);
200
201 BuildMI(MBB, MBBI, DL, TII->get(LoongArch::LU12I_W), ScratchReg)
202 .addDisp(Symbol, 0, LoongArchII::MO_LE_HI);
203
204 BuildMI(MBB, MBBI, DL, TII->get(LoongArch::ORI), DestReg)
205 .addReg(ScratchReg)
206 .addDisp(Symbol, 0, LoongArchII::MO_LE_LO);
207
208 MI.eraseFromParent();
209 return true;
210}
211
212bool LoongArchPreRAExpandPseudo::expandLoadAddressTLSIE(
214 MachineBasicBlock::iterator &NextMBBI) {
215 // Code Sequence:
216 // pcalau12i $rd, %ie_pc_hi20(sym)
217 // ld.w/d $rd, $rd, %ie_pc_lo12(sym)
219 const auto &STI = MF->getSubtarget<LoongArchSubtarget>();
220 unsigned SecondOpcode = STI.is64Bit() ? LoongArch::LD_D : LoongArch::LD_W;
221 return expandPcalau12iInstPair(MBB, MBBI, NextMBBI, LoongArchII::MO_IE_PC_HI,
222 SecondOpcode, LoongArchII::MO_IE_PC_LO);
223}
224
225bool LoongArchPreRAExpandPseudo::expandLoadAddressTLSLD(
227 MachineBasicBlock::iterator &NextMBBI) {
228 // Code Sequence:
229 // pcalau12i $rd, %ld_pc_hi20(sym)
230 // addi.w/d $rd, $rd, %got_pc_lo12(sym)
232 const auto &STI = MF->getSubtarget<LoongArchSubtarget>();
233 unsigned SecondOpcode = STI.is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W;
234 return expandPcalau12iInstPair(MBB, MBBI, NextMBBI, LoongArchII::MO_LD_PC_HI,
235 SecondOpcode, LoongArchII::MO_GOT_PC_LO);
236}
237
238bool LoongArchPreRAExpandPseudo::expandLoadAddressTLSGD(
240 MachineBasicBlock::iterator &NextMBBI) {
241 // Code Sequence:
242 // pcalau12i $rd, %gd_pc_hi20(sym)
243 // addi.w/d $rd, $rd, %got_pc_lo12(sym)
245 const auto &STI = MF->getSubtarget<LoongArchSubtarget>();
246 unsigned SecondOpcode = STI.is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W;
247 return expandPcalau12iInstPair(MBB, MBBI, NextMBBI, LoongArchII::MO_GD_PC_HI,
248 SecondOpcode, LoongArchII::MO_GOT_PC_LO);
249}
250
251bool LoongArchPreRAExpandPseudo::expandFunctionCALL(
253 MachineBasicBlock::iterator &NextMBBI, bool IsTailCall) {
255 MachineInstr &MI = *MBBI;
256 DebugLoc DL = MI.getDebugLoc();
257 const MachineOperand &Func = MI.getOperand(0);
259 unsigned Opcode;
260
261 switch (MF->getTarget().getCodeModel()) {
262 default:
263 report_fatal_error("Unsupported code model");
264 break;
265 case CodeModel::Small: {
266 // CALL:
267 // bl func
268 // TAIL:
269 // b func
270 Opcode = IsTailCall ? LoongArch::PseudoB_TAIL : LoongArch::BL;
271 CALL = BuildMI(MBB, MBBI, DL, TII->get(Opcode)).add(Func);
272 break;
273 }
274 case CodeModel::Medium: {
275 // CALL:
276 // pcalau12i $ra, %pc_hi20(func)
277 // jirl $ra, $ra, %pc_lo12(func)
278 // TAIL:
279 // pcalau12i $scratch, %pc_hi20(func)
280 // jirl $r0, $scratch, %pc_lo12(func)
281 Opcode =
282 IsTailCall ? LoongArch::PseudoJIRL_TAIL : LoongArch::PseudoJIRL_CALL;
283 Register ScratchReg =
284 IsTailCall
285 ? MF->getRegInfo().createVirtualRegister(&LoongArch::GPRRegClass)
286 : LoongArch::R1;
288 BuildMI(MBB, MBBI, DL, TII->get(LoongArch::PCALAU12I), ScratchReg);
289 CALL = BuildMI(MBB, MBBI, DL, TII->get(Opcode)).addReg(ScratchReg);
290 if (Func.isSymbol()) {
291 const char *FnName = Func.getSymbolName();
293 CALL.addExternalSymbol(FnName, LoongArchII::MO_PCREL_LO);
294 break;
295 }
296 assert(Func.isGlobal() && "Expected a GlobalValue at this time");
297 const GlobalValue *GV = Func.getGlobal();
299 CALL.addGlobalAddress(GV, 0, LoongArchII::MO_PCREL_LO);
300 break;
301 }
302 }
303
304 // Transfer implicit operands.
305 CALL.copyImplicitOps(MI);
306
307 // Transfer MI flags.
308 CALL.setMIFlags(MI.getFlags());
309
310 MI.eraseFromParent();
311 return true;
312}
313
314} // end namespace
315
316INITIALIZE_PASS(LoongArchPreRAExpandPseudo, "loongarch-prera-expand-pseudo",
318
319namespace llvm {
320
322 return new LoongArchPreRAExpandPseudo();
323}
324
325} // end namespace llvm
MachineBasicBlock & MBB
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
MachineBasicBlock MachineBasicBlock::iterator MBBI
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
const HexagonInstrInfo * TII
IRTranslator LLVM IR MI
This file implements the LivePhysRegs utility for tracking liveness of physical registers.
#define LOONGARCH_PRERA_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:265
A debug info location.
Definition: DebugLoc.h:33
FunctionPass class - This class is used to implement most global optimizations.
Definition: Pass.h:308
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
const MachineInstrBuilder & addExternalSymbol(const char *FnName, unsigned TargetFlags=0) const
const MachineInstrBuilder & add(const MachineOperand &MO) const
const MachineInstrBuilder & addGlobalAddress(const GlobalValue *GV, int64_t Offset=0, unsigned TargetFlags=0) const
const MachineInstrBuilder & addDisp(const MachineOperand &Disp, int64_t off, unsigned char TargetFlags=0) const
const MachineInstrBuilder & addReg(Register RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
Representation of each machine instruction.
Definition: MachineInstr.h:68
void addMemOperand(MachineFunction &MF, MachineMemOperand *MO)
Add a MachineMemOperand to the machine instruction.
MachineOperand class - Representation of each machine instruction operand.
Register createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
virtual StringRef getPassName() const
getPassName - Return a nice clean name for a pass.
Definition: Pass.cpp:81
Wrapper class representing virtual and physical registers.
Definition: Register.h:19
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:50
CodeModel::Model getCodeModel() const
Returns the code model.
virtual const TargetInstrInfo * getInstrInfo() const
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition: CallingConv.h:24
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 report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
Definition: Error.cpp:145
FunctionPass * createLoongArchPreRAExpandPseudoPass()