LLVM 20.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 <utility>
36
37using namespace llvm;
38using namespace tlshoist;
39
40#define DEBUG_TYPE "tlshoist"
41
43 "tls-load-hoist", cl::init(false), cl::Hidden,
44 cl::desc("hoist the TLS loads in PIC model to eliminate redundant "
45 "TLS address calculation."));
46
47namespace {
48
49/// The TLS Variable hoist pass.
50class TLSVariableHoistLegacyPass : public FunctionPass {
51public:
52 static char ID; // Pass identification, replacement for typeid
53
54 TLSVariableHoistLegacyPass() : FunctionPass(ID) {
56 }
57
58 bool runOnFunction(Function &Fn) override;
59
60 StringRef getPassName() const override { return "TLS Variable Hoist"; }
61
62 void getAnalysisUsage(AnalysisUsage &AU) const override {
63 AU.setPreservesCFG();
66 }
67
68private:
70};
71
72} // end anonymous namespace
73
74char TLSVariableHoistLegacyPass::ID = 0;
75
76INITIALIZE_PASS_BEGIN(TLSVariableHoistLegacyPass, "tlshoist",
77 "TLS Variable Hoist", false, false)
80INITIALIZE_PASS_END(TLSVariableHoistLegacyPass, "tlshoist",
81 "TLS Variable Hoist", false, false)
82
84 return new TLSVariableHoistLegacyPass();
85}
86
87/// Perform the TLS Variable Hoist optimization for the given function.
88bool TLSVariableHoistLegacyPass::runOnFunction(Function &Fn) {
89 if (skipFunction(Fn))
90 return false;
91
92 LLVM_DEBUG(dbgs() << "********** Begin TLS Variable Hoist **********\n");
93 LLVM_DEBUG(dbgs() << "********** Function: " << Fn.getName() << '\n');
94
95 bool MadeChange =
96 Impl.runImpl(Fn, getAnalysis<DominatorTreeWrapperPass>().getDomTree(),
97 getAnalysis<LoopInfoWrapperPass>().getLoopInfo());
98
99 if (MadeChange) {
100 LLVM_DEBUG(dbgs() << "********** Function after TLS Variable Hoist: "
101 << Fn.getName() << '\n');
102 LLVM_DEBUG(dbgs() << Fn);
103 }
104 LLVM_DEBUG(dbgs() << "********** End TLS Variable Hoist **********\n");
105
106 return MadeChange;
107}
108
109void TLSVariableHoistPass::collectTLSCandidate(Instruction *Inst) {
110 // Skip all cast instructions. They are visited indirectly later on.
111 if (Inst->isCast())
112 return;
113
114 // Scan all operands.
115 for (unsigned Idx = 0, E = Inst->getNumOperands(); Idx != E; ++Idx) {
116 auto *GV = dyn_cast<GlobalVariable>(Inst->getOperand(Idx));
117 if (!GV || !GV->isThreadLocal())
118 continue;
119
120 // Add Candidate to TLSCandMap (GV --> Candidate).
121 TLSCandMap[GV].addUser(Inst, Idx);
122 }
123}
124
125void TLSVariableHoistPass::collectTLSCandidates(Function &Fn) {
126 // First, quickly check if there is TLS Variable.
127 Module *M = Fn.getParent();
128
129 bool HasTLS = llvm::any_of(
130 M->globals(), [](GlobalVariable &GV) { return GV.isThreadLocal(); });
131
132 // If non, directly return.
133 if (!HasTLS)
134 return;
135
136 TLSCandMap.clear();
137
138 // Then, collect TLS Variable info.
139 for (BasicBlock &BB : Fn) {
140 // Ignore unreachable basic blocks.
141 if (!DT->isReachableFromEntry(&BB))
142 continue;
143
144 for (Instruction &Inst : BB)
145 collectTLSCandidate(&Inst);
146 }
147}
148
150 if (Cand.Users.size() != 1)
151 return false;
152
153 BasicBlock *BB = Cand.Users[0].Inst->getParent();
154 if (LI->getLoopFor(BB))
155 return false;
156
157 return true;
158}
159
160Instruction *TLSVariableHoistPass::getNearestLoopDomInst(BasicBlock *BB,
161 Loop *L) {
162 assert(L && "Unexcepted Loop status!");
163
164 // Get the outermost loop.
165 while (Loop *Parent = L->getParentLoop())
166 L = Parent;
167
168 BasicBlock *PreHeader = L->getLoopPreheader();
169
170 // There is unique predecessor outside the loop.
171 if (PreHeader)
172 return PreHeader->getTerminator();
173
174 BasicBlock *Header = L->getHeader();
175 BasicBlock *Dom = Header;
176 for (BasicBlock *PredBB : predecessors(Header))
177 Dom = DT->findNearestCommonDominator(Dom, PredBB);
178
179 assert(Dom && "Not find dominator BB!");
181
182 return Term;
183}
184
185Instruction *TLSVariableHoistPass::getDomInst(Instruction *I1,
186 Instruction *I2) {
187 if (!I1)
188 return I2;
189 return DT->findNearestCommonDominator(I1, I2);
190}
191
192BasicBlock::iterator TLSVariableHoistPass::findInsertPos(Function &Fn,
193 GlobalVariable *GV,
194 BasicBlock *&PosBB) {
195 tlshoist::TLSCandidate &Cand = TLSCandMap[GV];
196
197 // We should hoist the TLS use out of loop, so choose its nearest instruction
198 // which dominate the loop and the outside loops (if exist).
199 Instruction *LastPos = nullptr;
200 for (auto &User : Cand.Users) {
201 BasicBlock *BB = User.Inst->getParent();
202 Instruction *Pos = User.Inst;
203 if (Loop *L = LI->getLoopFor(BB)) {
204 Pos = getNearestLoopDomInst(BB, L);
205 assert(Pos && "Not find insert position out of loop!");
206 }
207 Pos = getDomInst(LastPos, Pos);
208 LastPos = Pos;
209 }
210
211 assert(LastPos && "Unexpected insert position!");
212 BasicBlock *Parent = LastPos->getParent();
213 PosBB = Parent;
214 return LastPos->getIterator();
215}
216
217// Generate a bitcast (no type change) to replace the uses of TLS Candidate.
218Instruction *TLSVariableHoistPass::genBitCastInst(Function &Fn,
219 GlobalVariable *GV) {
220 BasicBlock *PosBB = &Fn.getEntryBlock();
221 BasicBlock::iterator Iter = findInsertPos(Fn, GV, PosBB);
222 Type *Ty = GV->getType();
223 auto *CastInst = new BitCastInst(GV, Ty, "tls_bitcast");
224 CastInst->insertInto(PosBB, Iter);
225 return CastInst;
226}
227
228bool TLSVariableHoistPass::tryReplaceTLSCandidate(Function &Fn,
229 GlobalVariable *GV) {
230
231 tlshoist::TLSCandidate &Cand = TLSCandMap[GV];
232
233 // If only used 1 time and not in loops, we no need to replace it.
234 if (oneUseOutsideLoop(Cand, LI))
235 return false;
236
237 // Generate a bitcast (no type change)
238 auto *CastInst = genBitCastInst(Fn, GV);
239
240 // to replace the uses of TLS Candidate
241 for (auto &User : Cand.Users)
242 User.Inst->setOperand(User.OpndIdx, CastInst);
243
244 return true;
245}
246
247bool TLSVariableHoistPass::tryReplaceTLSCandidates(Function &Fn) {
248 if (TLSCandMap.empty())
249 return false;
250
251 bool Replaced = false;
252 for (auto &GV2Cand : TLSCandMap) {
253 GlobalVariable *GV = GV2Cand.first;
254 Replaced |= tryReplaceTLSCandidate(Fn, GV);
255 }
256
257 return Replaced;
258}
259
260/// Optimize expensive TLS variables in the given function.
262 LoopInfo &LI) {
263 if (Fn.hasOptNone())
264 return false;
265
266 if (!TLSLoadHoist && !Fn.getAttributes().hasFnAttr("tls-load-hoist"))
267 return false;
268
269 this->LI = &LI;
270 this->DT = &DT;
271 assert(this->LI && this->DT && "Unexcepted requirement!");
272
273 // Collect all TLS variable candidates.
274 collectTLSCandidates(Fn);
275
276 bool MadeChange = tryReplaceTLSCandidates(Fn);
277
278 return MadeChange;
279}
280
283
284 auto &LI = AM.getResult<LoopAnalysis>(F);
285 auto &DT = AM.getResult<DominatorTreeAnalysis>(F);
286
287 if (!runImpl(F, DT, LI))
288 return PreservedAnalyses::all();
289
292 return PA;
293}
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:57
#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:253
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
Definition: PassManager.h:405
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:256
bool hasFnAttr(Attribute::AttrKind Kind) const
Return true if the attribute exists for the function.
LLVM Basic Block Representation.
Definition: BasicBlock.h:61
InstListType::iterator iterator
Instruction iterators...
Definition: BasicBlock.h:177
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:239
This class represents a no-op cast from one type to another.
Represents analyses that only rely on functions' control flow.
Definition: Analysis.h:72
This is the base class for all instructions that perform data casts.
Definition: InstrTypes.h:530
Analysis pass which computes a DominatorTree.
Definition: Dominators.h:279
Legacy analysis pass which computes a DominatorTree.
Definition: Dominators.h:317
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree.
Definition: Dominators.h:162
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:310
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:807
AttributeList getAttributes() const
Return the attribute list for this Function.
Definition: Function.h:357
bool hasOptNone() const
Do not optimize this function (-O0).
Definition: Function.h:699
Module * getParent()
Get the module that this global value is contained inside of...
Definition: GlobalValue.h:656
PointerType * getType() const
Global values are always pointers.
Definition: GlobalValue.h:294
bool isCast() const
Definition: Instruction.h:282
InstListType::iterator insertInto(BasicBlock *ParentBB, InstListType::iterator It)
Inserts an unlinked instruction into ParentBB at position It and returns the iterator of the inserted...
Analysis pass that exposes the LoopInfo for a function.
Definition: LoopInfo.h:566
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:593
Represents a single loop in the control flow graph.
Definition: LoopInfo.h:39
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: Analysis.h:111
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Definition: Analysis.h:117
void preserveSet()
Mark an analysis set as preserved.
Definition: Analysis.h:146
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
const ParentTy * getParent() const
Definition: ilist_node.h:32
self_iterator getIterator()
Definition: ilist_node.h:132
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:443
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:1729
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