LLVM 18.0.0git
TLSVariableHoist.cpp
Go to the documentation of this file.
1//===- TLSVariableHoist.cpp -------- Remove Redundant TLS Loads ---------===//
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 pass identifies/eliminate Redundant TLS Loads if related option is set.
10// The example: Please refer to the comment at the head of TLSVariableHoist.h.
11//
12//===----------------------------------------------------------------------===//
13
15#include "llvm/IR/BasicBlock.h"
16#include "llvm/IR/Dominators.h"
17#include "llvm/IR/Function.h"
18#include "llvm/IR/InstrTypes.h"
19#include "llvm/IR/Instruction.h"
22#include "llvm/IR/Module.h"
23#include "llvm/IR/Value.h"
25#include "llvm/Pass.h"
27#include "llvm/Support/Debug.h"
31#include <algorithm>
32#include <cassert>
33#include <cstdint>
34#include <iterator>
35#include <tuple>
36#include <utility>
37
38using namespace llvm;
39using namespace tlshoist;
40
41#define DEBUG_TYPE "tlshoist"
42
44 "tls-load-hoist", cl::init(false), cl::Hidden,
45 cl::desc("hoist the TLS loads in PIC model to eliminate redundant "
46 "TLS address calculation."));
47
48namespace {
49
50/// The TLS Variable hoist pass.
51class TLSVariableHoistLegacyPass : public FunctionPass {
52public:
53 static char ID; // Pass identification, replacement for typeid
54
55 TLSVariableHoistLegacyPass() : FunctionPass(ID) {
57 }
58
59 bool runOnFunction(Function &Fn) override;
60
61 StringRef getPassName() const override { return "TLS Variable Hoist"; }
62
63 void getAnalysisUsage(AnalysisUsage &AU) const override {
64 AU.setPreservesCFG();
67 }
68
69private:
71};
72
73} // end anonymous namespace
74
75char TLSVariableHoistLegacyPass::ID = 0;
76
77INITIALIZE_PASS_BEGIN(TLSVariableHoistLegacyPass, "tlshoist",
78 "TLS Variable Hoist", false, false)
81INITIALIZE_PASS_END(TLSVariableHoistLegacyPass, "tlshoist",
82 "TLS Variable Hoist", false, false)
83
85 return new TLSVariableHoistLegacyPass();
86}
87
88/// Perform the TLS Variable Hoist optimization for the given function.
89bool TLSVariableHoistLegacyPass::runOnFunction(Function &Fn) {
90 if (skipFunction(Fn))
91 return false;
92
93 LLVM_DEBUG(dbgs() << "********** Begin TLS Variable Hoist **********\n");
94 LLVM_DEBUG(dbgs() << "********** Function: " << Fn.getName() << '\n');
95
96 bool MadeChange =
97 Impl.runImpl(Fn, getAnalysis<DominatorTreeWrapperPass>().getDomTree(),
98 getAnalysis<LoopInfoWrapperPass>().getLoopInfo());
99
100 if (MadeChange) {
101 LLVM_DEBUG(dbgs() << "********** Function after TLS Variable Hoist: "
102 << Fn.getName() << '\n');
103 LLVM_DEBUG(dbgs() << Fn);
104 }
105 LLVM_DEBUG(dbgs() << "********** End TLS Variable Hoist **********\n");
106
107 return MadeChange;
108}
109
110void TLSVariableHoistPass::collectTLSCandidate(Instruction *Inst) {
111 // Skip all cast instructions. They are visited indirectly later on.
112 if (Inst->isCast())
113 return;
114
115 // Scan all operands.
116 for (unsigned Idx = 0, E = Inst->getNumOperands(); Idx != E; ++Idx) {
117 auto *GV = dyn_cast<GlobalVariable>(Inst->getOperand(Idx));
118 if (!GV || !GV->isThreadLocal())
119 continue;
120
121 // Add Candidate to TLSCandMap (GV --> Candidate).
122 TLSCandMap[GV].addUser(Inst, Idx);
123 }
124}
125
126void TLSVariableHoistPass::collectTLSCandidates(Function &Fn) {
127 // First, quickly check if there is TLS Variable.
128 Module *M = Fn.getParent();
129
130 bool HasTLS = llvm::any_of(
131 M->globals(), [](GlobalVariable &GV) { return GV.isThreadLocal(); });
132
133 // If non, directly return.
134 if (!HasTLS)
135 return;
136
137 TLSCandMap.clear();
138
139 // Then, collect TLS Variable info.
140 for (BasicBlock &BB : Fn) {
141 // Ignore unreachable basic blocks.
142 if (!DT->isReachableFromEntry(&BB))
143 continue;
144
145 for (Instruction &Inst : BB)
146 collectTLSCandidate(&Inst);
147 }
148}
149
151 if (Cand.Users.size() != 1)
152 return false;
153
154 BasicBlock *BB = Cand.Users[0].Inst->getParent();
155 if (LI->getLoopFor(BB))
156 return false;
157
158 return true;
159}
160
161Instruction *TLSVariableHoistPass::getNearestLoopDomInst(BasicBlock *BB,
162 Loop *L) {
163 assert(L && "Unexcepted Loop status!");
164
165 // Get the outermost loop.
166 while (Loop *Parent = L->getParentLoop())
167 L = Parent;
168
169 BasicBlock *PreHeader = L->getLoopPreheader();
170
171 // There is unique predecessor outside the loop.
172 if (PreHeader)
173 return PreHeader->getTerminator();
174
175 BasicBlock *Header = L->getHeader();
176 BasicBlock *Dom = Header;
177 for (BasicBlock *PredBB : predecessors(Header))
178 Dom = DT->findNearestCommonDominator(Dom, PredBB);
179
180 assert(Dom && "Not find dominator BB!");
182
183 return Term;
184}
185
186Instruction *TLSVariableHoistPass::getDomInst(Instruction *I1,
187 Instruction *I2) {
188 if (!I1)
189 return I2;
190 return DT->findNearestCommonDominator(I1, I2);
191}
192
193BasicBlock::iterator TLSVariableHoistPass::findInsertPos(Function &Fn,
194 GlobalVariable *GV,
195 BasicBlock *&PosBB) {
196 tlshoist::TLSCandidate &Cand = TLSCandMap[GV];
197
198 // We should hoist the TLS use out of loop, so choose its nearest instruction
199 // which dominate the loop and the outside loops (if exist).
200 Instruction *LastPos = nullptr;
201 for (auto &User : Cand.Users) {
202 BasicBlock *BB = User.Inst->getParent();
203 Instruction *Pos = User.Inst;
204 if (Loop *L = LI->getLoopFor(BB)) {
205 Pos = getNearestLoopDomInst(BB, L);
206 assert(Pos && "Not find insert position out of loop!");
207 }
208 Pos = getDomInst(LastPos, Pos);
209 LastPos = Pos;
210 }
211
212 assert(LastPos && "Unexpected insert position!");
213 BasicBlock *Parent = LastPos->getParent();
214 PosBB = Parent;
215 return LastPos->getIterator();
216}
217
218// Generate a bitcast (no type change) to replace the uses of TLS Candidate.
219Instruction *TLSVariableHoistPass::genBitCastInst(Function &Fn,
220 GlobalVariable *GV) {
221 BasicBlock *PosBB = &Fn.getEntryBlock();
222 BasicBlock::iterator Iter = findInsertPos(Fn, GV, PosBB);
223 Type *Ty = GV->getType();
224 auto *CastInst = new BitCastInst(GV, Ty, "tls_bitcast");
225 CastInst->insertInto(PosBB, Iter);
226 return CastInst;
227}
228
229bool TLSVariableHoistPass::tryReplaceTLSCandidate(Function &Fn,
230 GlobalVariable *GV) {
231
232 tlshoist::TLSCandidate &Cand = TLSCandMap[GV];
233
234 // If only used 1 time and not in loops, we no need to replace it.
235 if (oneUseOutsideLoop(Cand, LI))
236 return false;
237
238 // Generate a bitcast (no type change)
239 auto *CastInst = genBitCastInst(Fn, GV);
240
241 // to replace the uses of TLS Candidate
242 for (auto &User : Cand.Users)
243 User.Inst->setOperand(User.OpndIdx, CastInst);
244
245 return true;
246}
247
248bool TLSVariableHoistPass::tryReplaceTLSCandidates(Function &Fn) {
249 if (TLSCandMap.empty())
250 return false;
251
252 bool Replaced = false;
253 for (auto &GV2Cand : TLSCandMap) {
254 GlobalVariable *GV = GV2Cand.first;
255 Replaced |= tryReplaceTLSCandidate(Fn, GV);
256 }
257
258 return Replaced;
259}
260
261/// Optimize expensive TLS variables in the given function.
263 LoopInfo &LI) {
264 if (Fn.hasOptNone())
265 return false;
266
267 if (!TLSLoadHoist && !Fn.getAttributes().hasFnAttr("tls-load-hoist"))
268 return false;
269
270 this->LI = &LI;
271 this->DT = &DT;
272 assert(this->LI && this->DT && "Unexcepted requirement!");
273
274 // Collect all TLS variable candidates.
275 collectTLSCandidates(Fn);
276
277 bool MadeChange = tryReplaceTLSCandidates(Fn);
278
279 return MadeChange;
280}
281
284
285 auto &LI = AM.getResult<LoopAnalysis>(F);
286 auto &DT = AM.getResult<DominatorTreeAnalysis>(F);
287
288 if (!runImpl(F, DT, LI))
289 return PreservedAnalyses::all();
290
293 return PA;
294}
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
Returns the sub type a function will return at a given Idx Should correspond to the result type of an ExtractValue instruction executed with just that one unsigned Idx
#define LLVM_DEBUG(X)
Definition: Debug.h:101
#define F(x, y, z)
Definition: MD5.cpp:55
Module.h This file contains the declarations for the Module class.
#define INITIALIZE_PASS_DEPENDENCY(depName)
Definition: PassSupport.h:55
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
Definition: PassSupport.h:59
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
Definition: PassSupport.h:52
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file defines the SmallVector class.
TLS Variable Hoist
When an instruction is found to use only loop invariant operands that are safe to hoist,...
static bool oneUseOutsideLoop(tlshoist::TLSCandidate &Cand, LoopInfo *LI)
static cl::opt< bool > TLSLoadHoist("tls-load-hoist", cl::init(false), cl::Hidden, cl::desc("hoist the TLS loads in PIC model to eliminate redundant " "TLS address calculation."))
A container for analyses that lazily runs them and caches their results.
Definition: PassManager.h:620
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
Definition: PassManager.h:774
Represent the analysis usage information of a pass.
AnalysisUsage & addRequired()
void setPreservesCFG()
This function should be called by the pass, iff they do not:
Definition: Pass.cpp:269
bool hasFnAttr(Attribute::AttrKind Kind) const
Return true if the attribute exists for the function.
LLVM Basic Block Representation.
Definition: BasicBlock.h:56
InstListType::iterator iterator
Instruction iterators...
Definition: BasicBlock.h:87
const Instruction * getTerminator() const LLVM_READONLY
Returns the terminator instruction if the block is well formed or null if the block is not well forme...
Definition: BasicBlock.h:127
This class represents a no-op cast from one type to another.
Represents analyses that only rely on functions' control flow.
Definition: PassManager.h:113
This is the base class for all instructions that perform data casts.
Definition: InstrTypes.h:428
Analysis pass which computes a DominatorTree.
Definition: Dominators.h:279
Legacy analysis pass which computes a DominatorTree.
Definition: Dominators.h:314
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree.
Definition: Dominators.h:166
bool isReachableFromEntry(const Use &U) const
Provide an overload for a Use.
Definition: Dominators.cpp:321
Instruction * findNearestCommonDominator(Instruction *I1, Instruction *I2) const
Find the nearest instruction I that dominates both I1 and I2, in the sense that a result produced bef...
Definition: Dominators.cpp:344
FunctionPass class - This class is used to implement most global optimizations.
Definition: Pass.h:311
virtual bool runOnFunction(Function &F)=0
runOnFunction - Virtual method overriden by subclasses to do the per-function processing of the pass.
const BasicBlock & getEntryBlock() const
Definition: Function.h:747
AttributeList getAttributes() const
Return the attribute list for this Function.
Definition: Function.h:315
bool hasOptNone() const
Do not optimize this function (-O0).
Definition: Function.h:641
Module * getParent()
Get the module that this global value is contained inside of...
Definition: GlobalValue.h:652
PointerType * getType() const
Global values are always pointers.
Definition: GlobalValue.h:290
bool isCast() const
Definition: Instruction.h:203
const BasicBlock * getParent() const
Definition: Instruction.h:90
SymbolTableList< Instruction >::iterator insertInto(BasicBlock *ParentBB, SymbolTableList< Instruction >::iterator It)
Inserts an unlinked instruction into ParentBB at position It and returns the iterator of the inserted...
Definition: Instruction.cpp:99
Analysis pass that exposes the LoopInfo for a function.
Definition: LoopInfo.h:569
LoopT * getLoopFor(const BlockT *BB) const
Return the inner most loop that BB lives in.
The legacy pass manager's analysis pass to compute loop information.
Definition: LoopInfo.h:594
Represents a single loop in the control flow graph.
Definition: LoopInfo.h:47
bool empty() const
Definition: MapVector.h:79
void clear()
Definition: MapVector.h:88
A Module instance is used to store all the information related to an LLVM module.
Definition: Module.h:65
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
virtual void getAnalysisUsage(AnalysisUsage &) const
getAnalysisUsage - This function should be overriden by passes that need analysis information to do t...
Definition: Pass.cpp:98
virtual StringRef getPassName() const
getPassName - Return a nice clean name for a pass.
Definition: Pass.cpp:81
A set of analyses that are preserved following a run of a transformation pass.
Definition: PassManager.h:152
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Definition: PassManager.h:158
void preserveSet()
Mark an analysis set as preserved.
Definition: PassManager.h:188
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:50
bool runImpl(Function &F, DominatorTree &DT, LoopInfo &LI)
Optimize expensive TLS variables in the given function.
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM)
The instances of the Type class are immutable: once they are created, they are never changed.
Definition: Type.h:45
void setOperand(unsigned i, Value *Val)
Definition: User.h:174
Value * getOperand(unsigned i) const
Definition: User.h:169
unsigned getNumOperands() const
Definition: User.h:191
StringRef getName() const
Return a constant reference to the value's name.
Definition: Value.cpp:309
self_iterator getIterator()
Definition: ilist_node.h:82
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition: CallingConv.h:24
initializer< Ty > init(const Ty &Val)
Definition: CommandLine.h:445
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
FunctionPass * createTLSVariableHoistPass()
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
Definition: STLExtras.h:1734
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:163
auto predecessors(const MachineBasicBlock *BB)
void initializeTLSVariableHoistLegacyPassPass(PassRegistry &)
Keeps track of a TLS variable candidate and its users.
SmallVector< TLSUser, 8 > Users