1 | //===-- GlobalDCE.cpp - DCE unreachable internal functions ----------------===// |
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 transform is designed to eliminate unreachable internal globals from the |
10 | // program. It uses an aggressive algorithm, searching out globals that are |
11 | // known to be alive. After it finds all of the globals which are needed, it |
12 | // deletes whatever is left over. This allows it to delete recursive chunks of |
13 | // the program which are unreachable. |
14 | // |
15 | //===----------------------------------------------------------------------===// |
16 | |
17 | #include "llvm/Transforms/IPO/GlobalDCE.h" |
18 | #include "llvm/ADT/SmallPtrSet.h" |
19 | #include "llvm/ADT/Statistic.h" |
20 | #include "llvm/Analysis/TypeMetadataUtils.h" |
21 | #include "llvm/IR/Instructions.h" |
22 | #include "llvm/IR/IntrinsicInst.h" |
23 | #include "llvm/IR/Module.h" |
24 | #include "llvm/Support/CommandLine.h" |
25 | #include "llvm/Transforms/IPO.h" |
26 | #include "llvm/Transforms/Utils/CtorUtils.h" |
27 | #include "llvm/Transforms/Utils/GlobalStatus.h" |
28 | |
29 | using namespace llvm; |
30 | |
31 | #define DEBUG_TYPE "globaldce" |
32 | |
33 | static cl::opt<bool> |
34 | ClEnableVFE("enable-vfe" , cl::Hidden, cl::init(Val: true), |
35 | cl::desc("Enable virtual function elimination" )); |
36 | |
37 | STATISTIC(NumAliases , "Number of global aliases removed" ); |
38 | STATISTIC(NumFunctions, "Number of functions removed" ); |
39 | STATISTIC(NumIFuncs, "Number of indirect functions removed" ); |
40 | STATISTIC(NumVariables, "Number of global variables removed" ); |
41 | STATISTIC(NumVFuncs, "Number of virtual functions removed" ); |
42 | |
43 | /// Returns true if F is effectively empty. |
44 | static bool isEmptyFunction(Function *F) { |
45 | // Skip external functions. |
46 | if (F->isDeclaration()) |
47 | return false; |
48 | BasicBlock &Entry = F->getEntryBlock(); |
49 | for (auto &I : Entry) { |
50 | if (I.isDebugOrPseudoInst()) |
51 | continue; |
52 | if (auto *RI = dyn_cast<ReturnInst>(Val: &I)) |
53 | return !RI->getReturnValue(); |
54 | break; |
55 | } |
56 | return false; |
57 | } |
58 | |
59 | /// Compute the set of GlobalValue that depends from V. |
60 | /// The recursion stops as soon as a GlobalValue is met. |
61 | void GlobalDCEPass::ComputeDependencies(Value *V, |
62 | SmallPtrSetImpl<GlobalValue *> &Deps) { |
63 | if (auto *I = dyn_cast<Instruction>(Val: V)) { |
64 | Function *Parent = I->getParent()->getParent(); |
65 | Deps.insert(Ptr: Parent); |
66 | } else if (auto *GV = dyn_cast<GlobalValue>(Val: V)) { |
67 | Deps.insert(Ptr: GV); |
68 | } else if (auto *CE = dyn_cast<Constant>(Val: V)) { |
69 | // Avoid walking the whole tree of a big ConstantExprs multiple times. |
70 | auto [Where, Inserted] = ConstantDependenciesCache.try_emplace(k: CE); |
71 | SmallPtrSetImpl<GlobalValue *> &LocalDeps = Where->second; |
72 | if (Inserted) { |
73 | for (User *CEUser : CE->users()) |
74 | ComputeDependencies(V: CEUser, Deps&: LocalDeps); |
75 | } |
76 | Deps.insert_range(R&: LocalDeps); |
77 | } |
78 | } |
79 | |
80 | void GlobalDCEPass::UpdateGVDependencies(GlobalValue &GV) { |
81 | SmallPtrSet<GlobalValue *, 8> Deps; |
82 | for (User *User : GV.users()) |
83 | ComputeDependencies(V: User, Deps); |
84 | Deps.erase(Ptr: &GV); // Remove self-reference. |
85 | for (GlobalValue *GVU : Deps) { |
86 | // If this is a dep from a vtable to a virtual function, and we have |
87 | // complete information about all virtual call sites which could call |
88 | // though this vtable, then skip it, because the call site information will |
89 | // be more precise. |
90 | if (VFESafeVTables.count(Ptr: GVU) && isa<Function>(Val: &GV)) { |
91 | LLVM_DEBUG(dbgs() << "Ignoring dep " << GVU->getName() << " -> " |
92 | << GV.getName() << "\n" ); |
93 | continue; |
94 | } |
95 | GVDependencies[GVU].insert(Ptr: &GV); |
96 | } |
97 | } |
98 | |
99 | /// Mark Global value as Live |
100 | void GlobalDCEPass::MarkLive(GlobalValue &GV, |
101 | SmallVectorImpl<GlobalValue *> *Updates) { |
102 | auto const Ret = AliveGlobals.insert(Ptr: &GV); |
103 | if (!Ret.second) |
104 | return; |
105 | |
106 | if (Updates) |
107 | Updates->push_back(Elt: &GV); |
108 | if (Comdat *C = GV.getComdat()) { |
109 | for (auto &&CM : make_range(p: ComdatMembers.equal_range(x: C))) { |
110 | MarkLive(GV&: *CM.second, Updates); // Recursion depth is only two because only |
111 | // globals in the same comdat are visited. |
112 | } |
113 | } |
114 | } |
115 | |
116 | void GlobalDCEPass::ScanVTables(Module &M) { |
117 | SmallVector<MDNode *, 2> Types; |
118 | LLVM_DEBUG(dbgs() << "Building type info -> vtable map\n" ); |
119 | |
120 | for (GlobalVariable &GV : M.globals()) { |
121 | Types.clear(); |
122 | GV.getMetadata(KindID: LLVMContext::MD_type, MDs&: Types); |
123 | if (GV.isDeclaration() || Types.empty()) |
124 | continue; |
125 | |
126 | // Use the typeid metadata on the vtable to build a mapping from typeids to |
127 | // the list of (GV, offset) pairs which are the possible vtables for that |
128 | // typeid. |
129 | for (MDNode *Type : Types) { |
130 | Metadata *TypeID = Type->getOperand(I: 1).get(); |
131 | |
132 | uint64_t Offset = |
133 | cast<ConstantInt>( |
134 | Val: cast<ConstantAsMetadata>(Val: Type->getOperand(I: 0))->getValue()) |
135 | ->getZExtValue(); |
136 | |
137 | TypeIdMap[TypeID].insert(V: std::make_pair(x: &GV, y&: Offset)); |
138 | } |
139 | |
140 | // If the type corresponding to the vtable is private to this translation |
141 | // unit, we know that we can see all virtual functions which might use it, |
142 | // so VFE is safe. |
143 | if (auto GO = dyn_cast<GlobalObject>(Val: &GV)) { |
144 | GlobalObject::VCallVisibility TypeVis = GO->getVCallVisibility(); |
145 | if (TypeVis == GlobalObject::VCallVisibilityTranslationUnit || |
146 | (InLTOPostLink && |
147 | TypeVis == GlobalObject::VCallVisibilityLinkageUnit)) { |
148 | LLVM_DEBUG(dbgs() << GV.getName() << " is safe for VFE\n" ); |
149 | VFESafeVTables.insert(Ptr: &GV); |
150 | } |
151 | } |
152 | } |
153 | } |
154 | |
155 | void GlobalDCEPass::ScanVTableLoad(Function *Caller, Metadata *TypeId, |
156 | uint64_t CallOffset) { |
157 | for (const auto &VTableInfo : TypeIdMap[TypeId]) { |
158 | GlobalVariable *VTable = VTableInfo.first; |
159 | uint64_t VTableOffset = VTableInfo.second; |
160 | |
161 | Constant *Ptr = |
162 | getPointerAtOffset(I: VTable->getInitializer(), Offset: VTableOffset + CallOffset, |
163 | M&: *Caller->getParent(), TopLevelGlobal: VTable); |
164 | if (!Ptr) { |
165 | LLVM_DEBUG(dbgs() << "can't find pointer in vtable!\n" ); |
166 | VFESafeVTables.erase(Ptr: VTable); |
167 | continue; |
168 | } |
169 | |
170 | auto Callee = dyn_cast<Function>(Val: Ptr->stripPointerCasts()); |
171 | if (!Callee) { |
172 | LLVM_DEBUG(dbgs() << "vtable entry is not function pointer!\n" ); |
173 | VFESafeVTables.erase(Ptr: VTable); |
174 | continue; |
175 | } |
176 | |
177 | LLVM_DEBUG(dbgs() << "vfunc dep " << Caller->getName() << " -> " |
178 | << Callee->getName() << "\n" ); |
179 | GVDependencies[Caller].insert(Ptr: Callee); |
180 | } |
181 | } |
182 | |
183 | void GlobalDCEPass::ScanTypeCheckedLoadIntrinsics(Module &M) { |
184 | LLVM_DEBUG(dbgs() << "Scanning type.checked.load intrinsics\n" ); |
185 | Function *TypeCheckedLoadFunc = |
186 | Intrinsic::getDeclarationIfExists(M: &M, id: Intrinsic::type_checked_load); |
187 | Function *TypeCheckedLoadRelativeFunc = Intrinsic::getDeclarationIfExists( |
188 | M: &M, id: Intrinsic::type_checked_load_relative); |
189 | |
190 | auto scan = [&](Function *CheckedLoadFunc) { |
191 | if (!CheckedLoadFunc) |
192 | return; |
193 | |
194 | for (auto *U : CheckedLoadFunc->users()) { |
195 | auto CI = dyn_cast<CallInst>(Val: U); |
196 | if (!CI) |
197 | continue; |
198 | |
199 | auto *Offset = dyn_cast<ConstantInt>(Val: CI->getArgOperand(i: 1)); |
200 | Value *TypeIdValue = CI->getArgOperand(i: 2); |
201 | auto *TypeId = cast<MetadataAsValue>(Val: TypeIdValue)->getMetadata(); |
202 | |
203 | if (Offset) { |
204 | ScanVTableLoad(Caller: CI->getFunction(), TypeId, CallOffset: Offset->getZExtValue()); |
205 | } else { |
206 | // type.checked.load with a non-constant offset, so assume every entry |
207 | // in every matching vtable is used. |
208 | for (const auto &VTableInfo : TypeIdMap[TypeId]) { |
209 | VFESafeVTables.erase(Ptr: VTableInfo.first); |
210 | } |
211 | } |
212 | } |
213 | }; |
214 | |
215 | scan(TypeCheckedLoadFunc); |
216 | scan(TypeCheckedLoadRelativeFunc); |
217 | } |
218 | |
219 | void GlobalDCEPass::AddVirtualFunctionDependencies(Module &M) { |
220 | if (!ClEnableVFE) |
221 | return; |
222 | |
223 | // If the Virtual Function Elim module flag is present and set to zero, then |
224 | // the vcall_visibility metadata was inserted for another optimization (WPD) |
225 | // and we may not have type checked loads on all accesses to the vtable. |
226 | // Don't attempt VFE in that case. |
227 | auto *Val = mdconst::dyn_extract_or_null<ConstantInt>( |
228 | MD: M.getModuleFlag(Key: "Virtual Function Elim" )); |
229 | if (!Val || Val->isZero()) |
230 | return; |
231 | |
232 | ScanVTables(M); |
233 | |
234 | if (VFESafeVTables.empty()) |
235 | return; |
236 | |
237 | ScanTypeCheckedLoadIntrinsics(M); |
238 | |
239 | LLVM_DEBUG( |
240 | dbgs() << "VFE safe vtables:\n" ; |
241 | for (auto *VTable : VFESafeVTables) |
242 | dbgs() << " " << VTable->getName() << "\n" ; |
243 | ); |
244 | } |
245 | |
246 | PreservedAnalyses GlobalDCEPass::run(Module &M, ModuleAnalysisManager &MAM) { |
247 | bool Changed = false; |
248 | |
249 | // The algorithm first computes the set L of global variables that are |
250 | // trivially live. Then it walks the initialization of these variables to |
251 | // compute the globals used to initialize them, which effectively builds a |
252 | // directed graph where nodes are global variables, and an edge from A to B |
253 | // means B is used to initialize A. Finally, it propagates the liveness |
254 | // information through the graph starting from the nodes in L. Nodes note |
255 | // marked as alive are discarded. |
256 | |
257 | // Remove empty functions from the global ctors list. |
258 | Changed |= optimizeGlobalCtorsList( |
259 | M, ShouldRemove: [](uint32_t, Function *F) { return isEmptyFunction(F); }); |
260 | |
261 | // Collect the set of members for each comdat. |
262 | for (Function &F : M) |
263 | if (Comdat *C = F.getComdat()) |
264 | ComdatMembers.insert(x: std::make_pair(x&: C, y: &F)); |
265 | for (GlobalVariable &GV : M.globals()) |
266 | if (Comdat *C = GV.getComdat()) |
267 | ComdatMembers.insert(x: std::make_pair(x&: C, y: &GV)); |
268 | for (GlobalAlias &GA : M.aliases()) |
269 | if (Comdat *C = GA.getComdat()) |
270 | ComdatMembers.insert(x: std::make_pair(x&: C, y: &GA)); |
271 | |
272 | // Add dependencies between virtual call sites and the virtual functions they |
273 | // might call, if we have that information. |
274 | AddVirtualFunctionDependencies(M); |
275 | |
276 | // Loop over the module, adding globals which are obviously necessary. |
277 | for (GlobalObject &GO : M.global_objects()) { |
278 | GO.removeDeadConstantUsers(); |
279 | // Functions with external linkage are needed if they have a body. |
280 | // Externally visible & appending globals are needed, if they have an |
281 | // initializer. |
282 | if (!GO.isDeclaration()) |
283 | if (!GO.isDiscardableIfUnused()) |
284 | MarkLive(GV&: GO); |
285 | |
286 | UpdateGVDependencies(GV&: GO); |
287 | } |
288 | |
289 | // Compute direct dependencies of aliases. |
290 | for (GlobalAlias &GA : M.aliases()) { |
291 | GA.removeDeadConstantUsers(); |
292 | // Externally visible aliases are needed. |
293 | if (!GA.isDiscardableIfUnused()) |
294 | MarkLive(GV&: GA); |
295 | |
296 | UpdateGVDependencies(GV&: GA); |
297 | } |
298 | |
299 | // Compute direct dependencies of ifuncs. |
300 | for (GlobalIFunc &GIF : M.ifuncs()) { |
301 | GIF.removeDeadConstantUsers(); |
302 | // Externally visible ifuncs are needed. |
303 | if (!GIF.isDiscardableIfUnused()) |
304 | MarkLive(GV&: GIF); |
305 | |
306 | UpdateGVDependencies(GV&: GIF); |
307 | } |
308 | |
309 | // Propagate liveness from collected Global Values through the computed |
310 | // dependencies. |
311 | SmallVector<GlobalValue *, 8> NewLiveGVs{AliveGlobals.begin(), |
312 | AliveGlobals.end()}; |
313 | while (!NewLiveGVs.empty()) { |
314 | GlobalValue *LGV = NewLiveGVs.pop_back_val(); |
315 | for (auto *GVD : GVDependencies[LGV]) |
316 | MarkLive(GV&: *GVD, Updates: &NewLiveGVs); |
317 | } |
318 | |
319 | // Now that all globals which are needed are in the AliveGlobals set, we loop |
320 | // through the program, deleting those which are not alive. |
321 | // |
322 | |
323 | // The first pass is to drop initializers of global variables which are dead. |
324 | std::vector<GlobalVariable *> DeadGlobalVars; // Keep track of dead globals |
325 | for (GlobalVariable &GV : M.globals()) |
326 | if (!AliveGlobals.count(Ptr: &GV)) { |
327 | DeadGlobalVars.push_back(x: &GV); // Keep track of dead globals |
328 | if (GV.hasInitializer()) { |
329 | Constant *Init = GV.getInitializer(); |
330 | GV.setInitializer(nullptr); |
331 | if (isSafeToDestroyConstant(C: Init)) |
332 | Init->destroyConstant(); |
333 | } |
334 | } |
335 | |
336 | // The second pass drops the bodies of functions which are dead... |
337 | std::vector<Function *> DeadFunctions; |
338 | for (Function &F : M) |
339 | if (!AliveGlobals.count(Ptr: &F)) { |
340 | DeadFunctions.push_back(x: &F); // Keep track of dead globals |
341 | if (!F.isDeclaration()) |
342 | F.deleteBody(); |
343 | } |
344 | |
345 | // The third pass drops targets of aliases which are dead... |
346 | std::vector<GlobalAlias*> DeadAliases; |
347 | for (GlobalAlias &GA : M.aliases()) |
348 | if (!AliveGlobals.count(Ptr: &GA)) { |
349 | DeadAliases.push_back(x: &GA); |
350 | GA.setAliasee(nullptr); |
351 | } |
352 | |
353 | // The fourth pass drops targets of ifuncs which are dead... |
354 | std::vector<GlobalIFunc*> DeadIFuncs; |
355 | for (GlobalIFunc &GIF : M.ifuncs()) |
356 | if (!AliveGlobals.count(Ptr: &GIF)) { |
357 | DeadIFuncs.push_back(x: &GIF); |
358 | GIF.setResolver(nullptr); |
359 | } |
360 | |
361 | // Now that all interferences have been dropped, delete the actual objects |
362 | // themselves. |
363 | auto EraseUnusedGlobalValue = [&](GlobalValue *GV) { |
364 | GV->removeDeadConstantUsers(); |
365 | GV->eraseFromParent(); |
366 | Changed = true; |
367 | }; |
368 | |
369 | NumFunctions += DeadFunctions.size(); |
370 | for (Function *F : DeadFunctions) { |
371 | if (!F->use_empty()) { |
372 | // Virtual functions might still be referenced by one or more vtables, |
373 | // but if we've proven them to be unused then it's safe to replace the |
374 | // virtual function pointers with null, allowing us to remove the |
375 | // function itself. |
376 | ++NumVFuncs; |
377 | |
378 | // Detect vfuncs that are referenced as "relative pointers" which are used |
379 | // in Swift vtables, i.e. entries in the form of: |
380 | // |
381 | // i32 trunc (i64 sub (i64 ptrtoint @f, i64 ptrtoint ...)) to i32) |
382 | // |
383 | // In this case, replace the whole "sub" expression with constant 0 to |
384 | // avoid leaving a weird sub(0, symbol) expression behind. |
385 | replaceRelativePointerUsersWithZero(C: F); |
386 | |
387 | F->replaceNonMetadataUsesWith(V: ConstantPointerNull::get(T: F->getType())); |
388 | } |
389 | EraseUnusedGlobalValue(F); |
390 | } |
391 | |
392 | NumVariables += DeadGlobalVars.size(); |
393 | for (GlobalVariable *GV : DeadGlobalVars) |
394 | EraseUnusedGlobalValue(GV); |
395 | |
396 | NumAliases += DeadAliases.size(); |
397 | for (GlobalAlias *GA : DeadAliases) |
398 | EraseUnusedGlobalValue(GA); |
399 | |
400 | NumIFuncs += DeadIFuncs.size(); |
401 | for (GlobalIFunc *GIF : DeadIFuncs) |
402 | EraseUnusedGlobalValue(GIF); |
403 | |
404 | // Make sure that all memory is released |
405 | AliveGlobals.clear(); |
406 | ConstantDependenciesCache.clear(); |
407 | GVDependencies.clear(); |
408 | ComdatMembers.clear(); |
409 | TypeIdMap.clear(); |
410 | VFESafeVTables.clear(); |
411 | |
412 | if (Changed) |
413 | return PreservedAnalyses::none(); |
414 | return PreservedAnalyses::all(); |
415 | } |
416 | |
417 | void GlobalDCEPass::printPipeline( |
418 | raw_ostream &OS, function_ref<StringRef(StringRef)> MapClassName2PassName) { |
419 | static_cast<PassInfoMixin<GlobalDCEPass> *>(this)->printPipeline( |
420 | OS, MapClassName2PassName); |
421 | if (InLTOPostLink) |
422 | OS << "<vfe-linkage-unit-visibility>" ; |
423 | } |
424 | |