llvm.org GIT mirror llvm / 194c9f4
Global DCE performance improvement Change the original algorithm so that it scales better when meeting very large bitcode where every instruction does not implies a global. The target query is "how to you get all the globals referenced by another global"? Before this patch, it was doing this by walking the body (or the initializer) and collecting the references. What this patch is doing, it precomputing the answer to this query for the whole module by walking the use-list of every global instead. Patch by: Serge Guelton <serge.guelton@telecom-bretagne.eu> Differential Revision: https://reviews.llvm.org/D28549 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@293328 91177308-0d34-0410-b5e6-96231b3b80d8 Mehdi Amini 2 years ago
2 changed file(s) with 103 addition(s) and 69 deletion(s). Raw diff Collapse all Expand all
1717 #ifndef LLVM_TRANSFORMS_IPO_GLOBALDCE_H
1818 #define LLVM_TRANSFORMS_IPO_GLOBALDCE_H
1919
20 #include "llvm/ADT/DenseMap.h"
21 #include "llvm/ADT/SmallSet.h"
2022 #include "llvm/IR/Module.h"
2123 #include "llvm/IR/PassManager.h"
2224 #include
3032
3133 private:
3234 SmallPtrSet AliveGlobals;
33 SmallPtrSet SeenConstants;
35
36 /// Global -> Global that uses this global.
37 std::unordered_multimap GVDependencies;
38
39 /// Constant -> Globals that use this global cache.
40 std::unordered_map>
41 ConstantDependenciesCache;
42
43 /// Comdat -> Globals in that Comdat section.
3444 std::unordered_multimap ComdatMembers;
3545
36 /// Mark the specific global value as needed, and
37 /// recursively mark anything that it uses as also needed.
38 void GlobalIsNeeded(GlobalValue *GV);
39 void MarkUsedGlobalsAsNeeded(Constant *C);
46 void UpdateGVDependencies(GlobalValue &GV);
47 void MarkLive(GlobalValue &GV,
48 SmallVectorImpl *Updates = nullptr);
4049 bool RemoveUnusedGlobalValue(GlobalValue &GV);
50
51 void ComputeDependencies(Value *V, SmallPtrSetImpl &U);
4152 };
4253
4354 }
2424 #include "llvm/Transforms/IPO.h"
2525 #include "llvm/Transforms/Utils/CtorUtils.h"
2626 #include "llvm/Transforms/Utils/GlobalStatus.h"
27 #include
27
2828 using namespace llvm;
2929
3030 #define DEBUG_TYPE "globaldce"
8484 return RI.getReturnValue() == nullptr;
8585 }
8686
87 /// Compute the set of GlobalValue that depends from V.
88 /// The recursion stops as soon as a GlobalValue is met.
89 void GlobalDCEPass::ComputeDependencies(Value *V,
90 SmallPtrSetImpl &Deps) {
91 if (auto *I = dyn_cast(V)) {
92 Function *Parent = I->getParent()->getParent();
93 Deps.insert(Parent);
94 } else if (auto *GV = dyn_cast(V)) {
95 Deps.insert(GV);
96 } else if (auto *CE = dyn_cast(V)) {
97 // Avoid walking the whole tree of a big ConstantExprs multiple times.
98 auto Where = ConstantDependenciesCache.find(CE);
99 if (Where != ConstantDependenciesCache.end()) {
100 auto const &K = Where->second;
101 Deps.insert(K.begin(), K.end());
102 } else {
103 SmallPtrSetImpl &LocalDeps = ConstantDependenciesCache[CE];
104 for (User *CEUser : CE->users())
105 ComputeDependencies(CEUser, LocalDeps);
106 Deps.insert(LocalDeps.begin(), LocalDeps.end());
107 }
108 }
109 }
110
111 void GlobalDCEPass::UpdateGVDependencies(GlobalValue &GV) {
112 SmallPtrSet Deps;
113 for (User *User : GV.users())
114 ComputeDependencies(User, Deps);
115 Deps.erase(&GV); // Remove self-reference.
116 for (GlobalValue *GVU : Deps) {
117 GVDependencies.insert(std::make_pair(GVU, &GV));
118 }
119 }
120
121 /// Mark Global value as Live
122 void GlobalDCEPass::MarkLive(GlobalValue &GV,
123 SmallVectorImpl *Updates) {
124 auto const Ret = AliveGlobals.insert(&GV);
125 if (!Ret.second)
126 return;
127
128 if (Updates)
129 Updates->push_back(&GV);
130 if (Comdat *C = GV.getComdat()) {
131 for (auto &&CM : make_range(ComdatMembers.equal_range(C)))
132 MarkLive(*CM.second, Updates); // Recursion depth is only two because only
133 // globals in the same comdat are visited.
134 }
135 }
136
87137 PreservedAnalyses GlobalDCEPass::run(Module &M, ModuleAnalysisManager &MAM) {
88138 bool Changed = false;
139
140 // The algorithm first computes the set L of global variables that are
141 // trivially live. Then it walks the initialization of these variables to
142 // compute the globals used to initialize them, which effectively builds a
143 // directed graph where nodes are global variables, and an edge from A to B
144 // means B is used to initialize A. Finally, it propagates the liveness
145 // information through the graph starting from the nodes in L. Nodes note
146 // marked as alive are discarded.
89147
90148 // Remove empty functions from the global ctors list.
91149 Changed |= optimizeGlobalCtorsList(M, isEmptyFunction);
109167 // initializer.
110168 if (!GO.isDeclaration() && !GO.hasAvailableExternallyLinkage())
111169 if (!GO.isDiscardableIfUnused())
112 GlobalIsNeeded(&GO);
113 }
114
170 MarkLive(GO);
171
172 UpdateGVDependencies(GO);
173 }
174
175 // Compute direct dependencies of aliases.
115176 for (GlobalAlias &GA : M.aliases()) {
116177 Changed |= RemoveUnusedGlobalValue(GA);
117178 // Externally visible aliases are needed.
118179 if (!GA.isDiscardableIfUnused())
119 GlobalIsNeeded(&GA);
120 }
121
180 MarkLive(GA);
181
182 UpdateGVDependencies(GA);
183 }
184
185 // Compute direct dependencies of ifuncs.
122186 for (GlobalIFunc &GIF : M.ifuncs()) {
123187 Changed |= RemoveUnusedGlobalValue(GIF);
124188 // Externally visible ifuncs are needed.
125189 if (!GIF.isDiscardableIfUnused())
126 GlobalIsNeeded(&GIF);
190 MarkLive(GIF);
191
192 UpdateGVDependencies(GIF);
193 }
194
195 // Propagate liveness from collected Global Values through the computed
196 // dependencies.
197 SmallVector NewLiveGVs{AliveGlobals.begin(),
198 AliveGlobals.end()};
199 while (!NewLiveGVs.empty()) {
200 GlobalValue *LGV = NewLiveGVs.pop_back_val();
201 for (auto &&GVD : make_range(GVDependencies.equal_range(LGV)))
202 MarkLive(*GVD.second, &NewLiveGVs);
127203 }
128204
129205 // Now that all globals which are needed are in the AliveGlobals set, we loop
160236 GA.setAliasee(nullptr);
161237 }
162238
163 // The third pass drops targets of ifuncs which are dead...
239 // The fourth pass drops targets of ifuncs which are dead...
164240 std::vector DeadIFuncs;
165241 for (GlobalIFunc &GIF : M.ifuncs())
166242 if (!AliveGlobals.count(&GIF)) {
194270
195271 // Make sure that all memory is released
196272 AliveGlobals.clear();
197 SeenConstants.clear();
273 ConstantDependenciesCache.clear();
274 GVDependencies.clear();
198275 ComdatMembers.clear();
199276
200277 if (Changed)
201278 return PreservedAnalyses::none();
202279 return PreservedAnalyses::all();
203 }
204
205 /// GlobalIsNeeded - the specific global value as needed, and
206 /// recursively mark anything that it uses as also needed.
207 void GlobalDCEPass::GlobalIsNeeded(GlobalValue *G) {
208 // If the global is already in the set, no need to reprocess it.
209 if (!AliveGlobals.insert(G).second)
210 return;
211
212 if (Comdat *C = G->getComdat()) {
213 for (auto &&CM : make_range(ComdatMembers.equal_range(C)))
214 GlobalIsNeeded(CM.second);
215 }
216
217 if (GlobalVariable *GV = dyn_cast(G)) {
218 // If this is a global variable, we must make sure to add any global values
219 // referenced by the initializer to the alive set.
220 if (GV->hasInitializer())
221 MarkUsedGlobalsAsNeeded(GV->getInitializer());
222 } else if (GlobalIndirectSymbol *GIS = dyn_cast(G)) {
223 // The target of a global alias or ifunc is needed.
224 MarkUsedGlobalsAsNeeded(GIS->getIndirectSymbol());
225 } else {
226 // Otherwise this must be a function object. We have to scan the body of
227 // the function looking for constants and global values which are used as
228 // operands. Any operands of these types must be processed to ensure that
229 // any globals used will be marked as needed.
230 Function *F = cast(G);
231
232 for (Use &U : F->operands())
233 MarkUsedGlobalsAsNeeded(cast(U.get()));
234
235 for (BasicBlock &BB : *F)
236 for (Instruction &I : BB)
237 for (Use &U : I.operands())
238 if (GlobalValue *GV = dyn_cast(U))
239 GlobalIsNeeded(GV);
240 else if (Constant *C = dyn_cast(U))
241 MarkUsedGlobalsAsNeeded(C);
242 }
243 }
244
245 void GlobalDCEPass::MarkUsedGlobalsAsNeeded(Constant *C) {
246 if (GlobalValue *GV = dyn_cast(C))
247 return GlobalIsNeeded(GV);
248
249 // Loop over all of the operands of the constant, adding any globals they
250 // use to the list of needed globals.
251 for (Use &U : C->operands()) {
252 // If we've already processed this constant there's no need to do it again.
253 Constant *Op = dyn_cast(U);
254 if (Op && SeenConstants.insert(Op).second)
255 MarkUsedGlobalsAsNeeded(Op);
256 }
257280 }
258281
259282 // RemoveUnusedGlobalValue - Loop over all of the uses of the specified