LLVM 24.0.0git
RISCVPreRAExpandPseudoInsts.cpp
Go to the documentation of this file.
1//===----------------------------------------------------------------------===//
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 one of the several passes that expand pseudo instructions
10// into target instructions. This pass is run before register allocation.
11//
12//===----------------------------------------------------------------------===//
13
14#include "RISCV.h"
16#include "RISCVInstrInfo.h"
17#include "RISCVSubtarget.h"
20#include "llvm/MC/MCContext.h"
21
22using namespace llvm;
23
24#define RISCV_PRERA_EXPAND_PSEUDO_NAME \
25 "RISC-V Pre-RA pseudo instruction expansion pass"
26
27namespace {
28
29class RISCVPreRAExpandPseudoImpl final : public RISCVExpandPseudoImplBase {
31 MachineBasicBlock::iterator &NextMBBI) const override;
32
33 bool expandAuipcInstPair(MachineBasicBlock &MBB,
34 MachineBasicBlock::iterator MBBI, unsigned FlagsHi,
35 unsigned SecondOpcode) const;
36
37 bool expandLoadLocalAddress(MachineBasicBlock &MBB,
39
40 bool expandLoadGlobalAddress(MachineBasicBlock &MBB,
42
43 bool expandLoadTLSIEAddress(MachineBasicBlock &MBB,
45
46 bool expandLoadTLSGDAddress(MachineBasicBlock &MBB,
48
49 bool expandLoadTLSDescAddress(MachineBasicBlock &MBB,
51};
52
53class RISCVPreRAExpandPseudoLegacy : public MachineFunctionPass {
54public:
55 static char ID;
56
57 RISCVPreRAExpandPseudoLegacy() : MachineFunctionPass(ID) {}
58
59 bool runOnMachineFunction(MachineFunction &MF) override {
60 return RISCVPreRAExpandPseudoImpl().run(MF);
61 }
62
63 MachineFunctionProperties getRequiredProperties() const override {
64 return MachineFunctionProperties().setIsSSA();
65 }
66
67 void getAnalysisUsage(AnalysisUsage &AU) const override {
68 AU.setPreservesCFG();
70 }
71 StringRef getPassName() const override {
73 }
74};
75
76} // anonymous namespace
77
78bool RISCVPreRAExpandPseudoImpl::expandMI(
80 MachineBasicBlock::iterator &NextMBBI) const {
81
82 switch (MBBI->getOpcode()) {
83 case RISCV::PseudoLLA:
84 return expandLoadLocalAddress(MBB, MBBI);
85 case RISCV::PseudoLGA:
86 return expandLoadGlobalAddress(MBB, MBBI);
87 case RISCV::PseudoLA_TLS_IE:
88 return expandLoadTLSIEAddress(MBB, MBBI);
89 case RISCV::PseudoLA_TLS_GD:
90 return expandLoadTLSGDAddress(MBB, MBBI);
91 case RISCV::PseudoLA_TLSDESC:
92 return expandLoadTLSDescAddress(MBB, MBBI);
93 }
94
95 return false;
96}
97
98bool RISCVPreRAExpandPseudoImpl::expandAuipcInstPair(
99 MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, unsigned FlagsHi,
100 unsigned SecondOpcode) const {
102 MachineInstr &MI = *MBBI;
103 DebugLoc DL = MI.getDebugLoc();
104
105 Register DestReg = MI.getOperand(0).getReg();
106 Register ScratchReg =
107 MF->getRegInfo().createVirtualRegister(&RISCV::GPRRegClass);
108
109 MachineOperand &Symbol = MI.getOperand(1);
110 Symbol.setTargetFlags(FlagsHi);
111 MCSymbol *AUIPCSymbol = MF->getContext().createNamedTempSymbol("pcrel_hi");
112
113 MachineInstr *MIAUIPC =
114 BuildMI(MBB, MBBI, DL, TII->get(RISCV::AUIPC), ScratchReg).add(Symbol);
115 MIAUIPC->setPreInstrSymbol(*MF, AUIPCSymbol);
116
117 MachineInstr *SecondMI =
118 BuildMI(MBB, MBBI, DL, TII->get(SecondOpcode), DestReg)
119 .addReg(ScratchReg)
120 .addSym(AUIPCSymbol, RISCVII::MO_PCREL_LO);
121
122 if (MI.hasOneMemOperand())
123 SecondMI->addMemOperand(*MF, *MI.memoperands_begin());
124
125 MI.eraseFromParent();
126 return true;
127}
128
129bool RISCVPreRAExpandPseudoImpl::expandLoadLocalAddress(
130 MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI) const {
131 return expandAuipcInstPair(MBB, MBBI, RISCVII::MO_PCREL_HI, RISCV::ADDI);
132}
133
134bool RISCVPreRAExpandPseudoImpl::expandLoadGlobalAddress(
135 MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI) const {
136 unsigned SecondOpcode = STI->is64Bit() ? RISCV::LD : RISCV::LW;
137 return expandAuipcInstPair(MBB, MBBI, RISCVII::MO_GOT_HI, SecondOpcode);
138}
139
140bool RISCVPreRAExpandPseudoImpl::expandLoadTLSIEAddress(
141 MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI) const {
142 unsigned SecondOpcode = STI->is64Bit() ? RISCV::LD : RISCV::LW;
143 return expandAuipcInstPair(MBB, MBBI, RISCVII::MO_TLS_GOT_HI, SecondOpcode);
144}
145
146bool RISCVPreRAExpandPseudoImpl::expandLoadTLSGDAddress(
147 MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI) const {
148 return expandAuipcInstPair(MBB, MBBI, RISCVII::MO_TLS_GD_HI, RISCV::ADDI);
149}
150
151bool RISCVPreRAExpandPseudoImpl::expandLoadTLSDescAddress(
152 MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI) const {
154 MachineInstr &MI = *MBBI;
155 DebugLoc DL = MI.getDebugLoc();
156
157 const auto &STI = MF->getSubtarget<RISCVSubtarget>();
158 unsigned SecondOpcode = STI.is64Bit() ? RISCV::LD : RISCV::LW;
159
160 Register FinalReg = MI.getOperand(0).getReg();
161 Register DestReg =
162 MF->getRegInfo().createVirtualRegister(&RISCV::GPRRegClass);
163 Register ScratchReg =
164 MF->getRegInfo().createVirtualRegister(&RISCV::GPRRegClass);
165
166 MachineOperand &Symbol = MI.getOperand(1);
167 Symbol.setTargetFlags(RISCVII::MO_TLSDESC_HI);
168 MCSymbol *AUIPCSymbol = MF->getContext().createNamedTempSymbol("tlsdesc_hi");
169
170 MachineInstr *MIAUIPC =
171 BuildMI(MBB, MBBI, DL, TII->get(RISCV::AUIPC), ScratchReg).add(Symbol);
172 MIAUIPC->setPreInstrSymbol(*MF, AUIPCSymbol);
173
174 BuildMI(MBB, MBBI, DL, TII->get(SecondOpcode), DestReg)
175 .addReg(ScratchReg)
176 .addSym(AUIPCSymbol, RISCVII::MO_TLSDESC_LOAD_LO);
177
178 BuildMI(MBB, MBBI, DL, TII->get(RISCV::ADDI), RISCV::X10)
179 .addReg(ScratchReg)
180 .addSym(AUIPCSymbol, RISCVII::MO_TLSDESC_ADD_LO);
181
182 BuildMI(MBB, MBBI, DL, TII->get(RISCV::PseudoTLSDESCCall), RISCV::X5)
183 .addReg(DestReg)
184 .addImm(0)
185 .addSym(AUIPCSymbol, RISCVII::MO_TLSDESC_CALL);
186
187 BuildMI(MBB, MBBI, DL, TII->get(RISCV::ADD), FinalReg)
188 .addReg(RISCV::X10)
189 .addReg(RISCV::X4);
190
191 MI.eraseFromParent();
192 return true;
193}
194
195char RISCVPreRAExpandPseudoLegacy::ID = 0;
196
197INITIALIZE_PASS(RISCVPreRAExpandPseudoLegacy, "riscv-pre-ra-expand-pseudo",
198 RISCV_PRERA_EXPAND_PSEUDO_NAME, false, false)
199
201 return new RISCVPreRAExpandPseudoLegacy();
202}
203
204PreservedAnalyses
207 MFPropsModifier _(*this, MF);
208 bool Changed = RISCVPreRAExpandPseudoImpl().run(MF);
209 if (!Changed)
210 return PreservedAnalyses::all();
211
214 return PA;
215}
MachineBasicBlock & MBB
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
MachineBasicBlock MachineBasicBlock::iterator MBBI
const HexagonInstrInfo * TII
#define _
IRTranslator LLVM IR MI
Promote Memory to Register
Definition Mem2Reg.cpp:110
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
Definition PassSupport.h:56
#define RISCV_PRERA_EXPAND_PSEUDO_NAME
Represent the analysis usage information of a pass.
LLVM_ABI void setPreservesCFG()
This function should be called by the pass, iff they do not:
Definition Pass.cpp:275
Represents analyses that only rely on functions' control flow.
Definition Analysis.h:73
FunctionPass class - This class is used to implement most global optimizations.
Definition Pass.h:314
LLVM_ABI MCSymbol * createNamedTempSymbol()
Create a temporary symbol with a unique name whose name cannot be omitted in the symbol table.
An RAII based helper class to modify MachineFunctionProperties when running pass.
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
MachineInstrBundleIterator< MachineInstr > iterator
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
Properties which a MachineFunction may have at a given point in time.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MCContext & getContext() const
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
const MachineInstrBuilder & addReg(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & add(const MachineOperand &MO) const
const MachineInstrBuilder & addSym(MCSymbol *Sym, unsigned char TargetFlags=0) const
LLVM_ABI void setPreInstrSymbol(MachineFunction &MF, MCSymbol *Symbol)
Set a symbol that will be emitted just prior to the instruction itself.
LLVM_ABI void addMemOperand(MachineFunction &MF, MachineMemOperand *MO)
Add a MachineMemOperand to the machine instruction.
LLVM_ABI Register createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
A set of analyses that are preserved following a run of a transformation pass.
Definition Analysis.h:112
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Definition Analysis.h:118
PreservedAnalyses & preserveSet()
Mark an analysis set as preserved.
Definition Analysis.h:151
PreservedAnalyses run(MachineFunction &MF, MachineFunctionAnalysisManager &MFAM)
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
Changed
This is an optimization pass for GlobalISel generic memory operations.
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
AnalysisManager< MachineFunction > MachineFunctionAnalysisManager
LLVM_ABI PreservedAnalyses getMachineFunctionPassPreservedAnalyses()
Returns the minimum set of Analyses that all machine function passes must preserve.
FunctionPass * createRISCVPreRAExpandPseudoLegacyPass()