LLVM 17.0.0git
GlobalDCE.cpp
Go to the documentation of this file.
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
19#include "llvm/ADT/Statistic.h"
23#include "llvm/IR/Module.h"
25#include "llvm/Pass.h"
27#include "llvm/Transforms/IPO.h"
30
31using namespace llvm;
32
33#define DEBUG_TYPE "globaldce"
34
35static cl::opt<bool>
36 ClEnableVFE("enable-vfe", cl::Hidden, cl::init(true),
37 cl::desc("Enable virtual function elimination"));
38
39STATISTIC(NumAliases , "Number of global aliases removed");
40STATISTIC(NumFunctions, "Number of functions removed");
41STATISTIC(NumIFuncs, "Number of indirect functions removed");
42STATISTIC(NumVariables, "Number of global variables removed");
43STATISTIC(NumVFuncs, "Number of virtual functions removed");
44
45/// Returns true if F is effectively empty.
46static bool isEmptyFunction(Function *F) {
47 // Skip external functions.
48 if (F->isDeclaration())
49 return false;
50 BasicBlock &Entry = F->getEntryBlock();
51 for (auto &I : Entry) {
52 if (I.isDebugOrPseudoInst())
53 continue;
54 if (auto *RI = dyn_cast<ReturnInst>(&I))
55 return !RI->getReturnValue();
56 break;
57 }
58 return false;
59}
60
61/// Compute the set of GlobalValue that depends from V.
62/// The recursion stops as soon as a GlobalValue is met.
63void GlobalDCEPass::ComputeDependencies(Value *V,
65 if (auto *I = dyn_cast<Instruction>(V)) {
66 Function *Parent = I->getParent()->getParent();
67 Deps.insert(Parent);
68 } else if (auto *GV = dyn_cast<GlobalValue>(V)) {
69 Deps.insert(GV);
70 } else if (auto *CE = dyn_cast<Constant>(V)) {
71 // Avoid walking the whole tree of a big ConstantExprs multiple times.
72 auto Where = ConstantDependenciesCache.find(CE);
73 if (Where != ConstantDependenciesCache.end()) {
74 auto const &K = Where->second;
75 Deps.insert(K.begin(), K.end());
76 } else {
77 SmallPtrSetImpl<GlobalValue *> &LocalDeps = ConstantDependenciesCache[CE];
78 for (User *CEUser : CE->users())
79 ComputeDependencies(CEUser, LocalDeps);
80 Deps.insert(LocalDeps.begin(), LocalDeps.end());
81 }
82 }
83}
84
85void GlobalDCEPass::UpdateGVDependencies(GlobalValue &GV) {
87 for (User *User : GV.users())
88 ComputeDependencies(User, Deps);
89 Deps.erase(&GV); // Remove self-reference.
90 for (GlobalValue *GVU : Deps) {
91 // If this is a dep from a vtable to a virtual function, and we have
92 // complete information about all virtual call sites which could call
93 // though this vtable, then skip it, because the call site information will
94 // be more precise.
95 if (VFESafeVTables.count(GVU) && isa<Function>(&GV)) {
96 LLVM_DEBUG(dbgs() << "Ignoring dep " << GVU->getName() << " -> "
97 << GV.getName() << "\n");
98 continue;
99 }
100 GVDependencies[GVU].insert(&GV);
101 }
102}
103
104/// Mark Global value as Live
105void GlobalDCEPass::MarkLive(GlobalValue &GV,
107 auto const Ret = AliveGlobals.insert(&GV);
108 if (!Ret.second)
109 return;
110
111 if (Updates)
112 Updates->push_back(&GV);
113 if (Comdat *C = GV.getComdat()) {
114 for (auto &&CM : make_range(ComdatMembers.equal_range(C))) {
115 MarkLive(*CM.second, Updates); // Recursion depth is only two because only
116 // globals in the same comdat are visited.
117 }
118 }
119}
120
121void GlobalDCEPass::ScanVTables(Module &M) {
123 LLVM_DEBUG(dbgs() << "Building type info -> vtable map\n");
124
125 auto *LTOPostLinkMD =
126 cast_or_null<ConstantAsMetadata>(M.getModuleFlag("LTOPostLink"));
127 bool LTOPostLink =
128 LTOPostLinkMD && !cast<ConstantInt>(LTOPostLinkMD->getValue())->isZero();
129
130 for (GlobalVariable &GV : M.globals()) {
131 Types.clear();
132 GV.getMetadata(LLVMContext::MD_type, Types);
133 if (GV.isDeclaration() || Types.empty())
134 continue;
135
136 // Use the typeid metadata on the vtable to build a mapping from typeids to
137 // the list of (GV, offset) pairs which are the possible vtables for that
138 // typeid.
139 for (MDNode *Type : Types) {
140 Metadata *TypeID = Type->getOperand(1).get();
141
143 cast<ConstantInt>(
144 cast<ConstantAsMetadata>(Type->getOperand(0))->getValue())
145 ->getZExtValue();
146
147 TypeIdMap[TypeID].insert(std::make_pair(&GV, Offset));
148 }
149
150 // If the type corresponding to the vtable is private to this translation
151 // unit, we know that we can see all virtual functions which might use it,
152 // so VFE is safe.
153 if (auto GO = dyn_cast<GlobalObject>(&GV)) {
154 GlobalObject::VCallVisibility TypeVis = GO->getVCallVisibility();
156 (LTOPostLink &&
158 LLVM_DEBUG(dbgs() << GV.getName() << " is safe for VFE\n");
159 VFESafeVTables.insert(&GV);
160 }
161 }
162 }
163}
164
165void GlobalDCEPass::ScanVTableLoad(Function *Caller, Metadata *TypeId,
166 uint64_t CallOffset) {
167 for (const auto &VTableInfo : TypeIdMap[TypeId]) {
168 GlobalVariable *VTable = VTableInfo.first;
169 uint64_t VTableOffset = VTableInfo.second;
170
171 Constant *Ptr =
172 getPointerAtOffset(VTable->getInitializer(), VTableOffset + CallOffset,
173 *Caller->getParent(), VTable);
174 if (!Ptr) {
175 LLVM_DEBUG(dbgs() << "can't find pointer in vtable!\n");
176 VFESafeVTables.erase(VTable);
177 continue;
178 }
179
180 auto Callee = dyn_cast<Function>(Ptr->stripPointerCasts());
181 if (!Callee) {
182 LLVM_DEBUG(dbgs() << "vtable entry is not function pointer!\n");
183 VFESafeVTables.erase(VTable);
184 continue;
185 }
186
187 LLVM_DEBUG(dbgs() << "vfunc dep " << Caller->getName() << " -> "
188 << Callee->getName() << "\n");
189 GVDependencies[Caller].insert(Callee);
190 }
191}
192
193void GlobalDCEPass::ScanTypeCheckedLoadIntrinsics(Module &M) {
194 LLVM_DEBUG(dbgs() << "Scanning type.checked.load intrinsics\n");
195 Function *TypeCheckedLoadFunc =
196 M.getFunction(Intrinsic::getName(Intrinsic::type_checked_load));
197
198 if (!TypeCheckedLoadFunc)
199 return;
200
201 for (auto *U : TypeCheckedLoadFunc->users()) {
202 auto CI = dyn_cast<CallInst>(U);
203 if (!CI)
204 continue;
205
206 auto *Offset = dyn_cast<ConstantInt>(CI->getArgOperand(1));
207 Value *TypeIdValue = CI->getArgOperand(2);
208 auto *TypeId = cast<MetadataAsValue>(TypeIdValue)->getMetadata();
209
210 if (Offset) {
211 ScanVTableLoad(CI->getFunction(), TypeId, Offset->getZExtValue());
212 } else {
213 // type.checked.load with a non-constant offset, so assume every entry in
214 // every matching vtable is used.
215 for (const auto &VTableInfo : TypeIdMap[TypeId]) {
216 VFESafeVTables.erase(VTableInfo.first);
217 }
218 }
219 }
220}
221
222void GlobalDCEPass::AddVirtualFunctionDependencies(Module &M) {
223 if (!ClEnableVFE)
224 return;
225
226 // If the Virtual Function Elim module flag is present and set to zero, then
227 // the vcall_visibility metadata was inserted for another optimization (WPD)
228 // and we may not have type checked loads on all accesses to the vtable.
229 // Don't attempt VFE in that case.
230 auto *Val = mdconst::dyn_extract_or_null<ConstantInt>(
231 M.getModuleFlag("Virtual Function Elim"));
232 if (!Val || Val->isZero())
233 return;
234
235 ScanVTables(M);
236
237 if (VFESafeVTables.empty())
238 return;
239
240 ScanTypeCheckedLoadIntrinsics(M);
241
243 dbgs() << "VFE safe vtables:\n";
244 for (auto *VTable : VFESafeVTables)
245 dbgs() << " " << VTable->getName() << "\n";
246 );
247}
248
250 bool Changed = false;
251
252 // The algorithm first computes the set L of global variables that are
253 // trivially live. Then it walks the initialization of these variables to
254 // compute the globals used to initialize them, which effectively builds a
255 // directed graph where nodes are global variables, and an edge from A to B
256 // means B is used to initialize A. Finally, it propagates the liveness
257 // information through the graph starting from the nodes in L. Nodes note
258 // marked as alive are discarded.
259
260 // Remove empty functions from the global ctors list.
261 Changed |= optimizeGlobalCtorsList(
262 M, [](uint32_t, Function *F) { return isEmptyFunction(F); });
263
264 // Collect the set of members for each comdat.
265 for (Function &F : M)
266 if (Comdat *C = F.getComdat())
267 ComdatMembers.insert(std::make_pair(C, &F));
268 for (GlobalVariable &GV : M.globals())
269 if (Comdat *C = GV.getComdat())
270 ComdatMembers.insert(std::make_pair(C, &GV));
271 for (GlobalAlias &GA : M.aliases())
272 if (Comdat *C = GA.getComdat())
273 ComdatMembers.insert(std::make_pair(C, &GA));
274
275 // Add dependencies between virtual call sites and the virtual functions they
276 // might call, if we have that information.
277 AddVirtualFunctionDependencies(M);
278
279 // Loop over the module, adding globals which are obviously necessary.
280 for (GlobalObject &GO : M.global_objects()) {
281 GO.removeDeadConstantUsers();
282 // Functions with external linkage are needed if they have a body.
283 // Externally visible & appending globals are needed, if they have an
284 // initializer.
285 if (!GO.isDeclaration())
286 if (!GO.isDiscardableIfUnused())
287 MarkLive(GO);
288
289 UpdateGVDependencies(GO);
290 }
291
292 // Compute direct dependencies of aliases.
293 for (GlobalAlias &GA : M.aliases()) {
294 GA.removeDeadConstantUsers();
295 // Externally visible aliases are needed.
296 if (!GA.isDiscardableIfUnused())
297 MarkLive(GA);
298
299 UpdateGVDependencies(GA);
300 }
301
302 // Compute direct dependencies of ifuncs.
303 for (GlobalIFunc &GIF : M.ifuncs()) {
304 GIF.removeDeadConstantUsers();
305 // Externally visible ifuncs are needed.
306 if (!GIF.isDiscardableIfUnused())
307 MarkLive(GIF);
308
309 UpdateGVDependencies(GIF);
310 }
311
312 // Propagate liveness from collected Global Values through the computed
313 // dependencies.
314 SmallVector<GlobalValue *, 8> NewLiveGVs{AliveGlobals.begin(),
315 AliveGlobals.end()};
316 while (!NewLiveGVs.empty()) {
317 GlobalValue *LGV = NewLiveGVs.pop_back_val();
318 for (auto *GVD : GVDependencies[LGV])
319 MarkLive(*GVD, &NewLiveGVs);
320 }
321
322 // Now that all globals which are needed are in the AliveGlobals set, we loop
323 // through the program, deleting those which are not alive.
324 //
325
326 // The first pass is to drop initializers of global variables which are dead.
327 std::vector<GlobalVariable *> DeadGlobalVars; // Keep track of dead globals
328 for (GlobalVariable &GV : M.globals())
329 if (!AliveGlobals.count(&GV)) {
330 DeadGlobalVars.push_back(&GV); // Keep track of dead globals
331 if (GV.hasInitializer()) {
332 Constant *Init = GV.getInitializer();
333 GV.setInitializer(nullptr);
335 Init->destroyConstant();
336 }
337 }
338
339 // The second pass drops the bodies of functions which are dead...
340 std::vector<Function *> DeadFunctions;
341 for (Function &F : M)
342 if (!AliveGlobals.count(&F)) {
343 DeadFunctions.push_back(&F); // Keep track of dead globals
344 if (!F.isDeclaration())
345 F.deleteBody();
346 }
347
348 // The third pass drops targets of aliases which are dead...
349 std::vector<GlobalAlias*> DeadAliases;
350 for (GlobalAlias &GA : M.aliases())
351 if (!AliveGlobals.count(&GA)) {
352 DeadAliases.push_back(&GA);
353 GA.setAliasee(nullptr);
354 }
355
356 // The fourth pass drops targets of ifuncs which are dead...
357 std::vector<GlobalIFunc*> DeadIFuncs;
358 for (GlobalIFunc &GIF : M.ifuncs())
359 if (!AliveGlobals.count(&GIF)) {
360 DeadIFuncs.push_back(&GIF);
361 GIF.setResolver(nullptr);
362 }
363
364 // Now that all interferences have been dropped, delete the actual objects
365 // themselves.
366 auto EraseUnusedGlobalValue = [&](GlobalValue *GV) {
368 GV->eraseFromParent();
369 Changed = true;
370 };
371
372 NumFunctions += DeadFunctions.size();
373 for (Function *F : DeadFunctions) {
374 if (!F->use_empty()) {
375 // Virtual functions might still be referenced by one or more vtables,
376 // but if we've proven them to be unused then it's safe to replace the
377 // virtual function pointers with null, allowing us to remove the
378 // function itself.
379 ++NumVFuncs;
380
381 // Detect vfuncs that are referenced as "relative pointers" which are used
382 // in Swift vtables, i.e. entries in the form of:
383 //
384 // i32 trunc (i64 sub (i64 ptrtoint @f, i64 ptrtoint ...)) to i32)
385 //
386 // In this case, replace the whole "sub" expression with constant 0 to
387 // avoid leaving a weird sub(0, symbol) expression behind.
389
390 F->replaceNonMetadataUsesWith(ConstantPointerNull::get(F->getType()));
391 }
392 EraseUnusedGlobalValue(F);
393 }
394
395 NumVariables += DeadGlobalVars.size();
396 for (GlobalVariable *GV : DeadGlobalVars)
397 EraseUnusedGlobalValue(GV);
398
399 NumAliases += DeadAliases.size();
400 for (GlobalAlias *GA : DeadAliases)
401 EraseUnusedGlobalValue(GA);
402
403 NumIFuncs += DeadIFuncs.size();
404 for (GlobalIFunc *GIF : DeadIFuncs)
405 EraseUnusedGlobalValue(GIF);
406
407 // Make sure that all memory is released
408 AliveGlobals.clear();
409 ConstantDependenciesCache.clear();
410 GVDependencies.clear();
411 ComdatMembers.clear();
412 TypeIdMap.clear();
413 VFESafeVTables.clear();
414
415 if (Changed)
417 return PreservedAnalyses::all();
418}
amdgpu Simplify well known AMD library false FunctionCallee Callee
#define LLVM_DEBUG(X)
Definition: Debug.h:101
static bool isEmptyFunction(Function *F)
Returns true if F is effectively empty.
Definition: GlobalDCE.cpp:46
static cl::opt< bool > ClEnableVFE("enable-vfe", cl::Hidden, cl::init(true), cl::desc("Enable virtual function elimination"))
#define F(x, y, z)
Definition: MD5.cpp:55
#define I(x, y, z)
Definition: MD5.cpp:58
Module.h This file contains the declarations for the Module class.
ModuleAnalysisManager MAM
This file defines the SmallPtrSet class.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
Definition: Statistic.h:167
A container for analyses that lazily runs them and caches their results.
Definition: PassManager.h:620
LLVM Basic Block Representation.
Definition: BasicBlock.h:56
static ConstantPointerNull * get(PointerType *T)
Static factory methods - Return objects of the specified value.
Definition: Constants.cpp:1698
This is an important base class in LLVM.
Definition: Constant.h:41
void removeDeadConstantUsers() const
If there are any dead constant users dangling off of this constant, remove them.
Definition: Constants.cpp:708
PreservedAnalyses run(Module &M, ModuleAnalysisManager &)
Definition: GlobalDCE.cpp:249
bool isDeclaration() const
Return true if the primary definition of this global value is outside of the current translation unit...
Definition: Globals.cpp:275
const Comdat * getComdat() const
Definition: Globals.cpp:185
void eraseFromParent()
This method unlinks 'this' from the containing module and deletes it.
Definition: Globals.cpp:88
Metadata node.
Definition: Metadata.h:943
Root of the metadata hierarchy.
Definition: Metadata.h:61
A Module instance is used to store all the information related to an LLVM module.
Definition: Module.h:65
A set of analyses that are preserved following a run of a transformation pass.
Definition: PassManager.h:152
static PreservedAnalyses none()
Convenience factory function for the empty preserved set.
Definition: PassManager.h:155
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Definition: PassManager.h:158
A templated base class for SmallPtrSet which provides the typesafe interface that is common across al...
Definition: SmallPtrSet.h:344
bool erase(PtrType Ptr)
erase - If the set contains the specified pointer, remove it and return true, otherwise return false.
Definition: SmallPtrSet.h:379
iterator end() const
Definition: SmallPtrSet.h:408
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
Definition: SmallPtrSet.h:365
iterator begin() const
Definition: SmallPtrSet.h:403
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
Definition: SmallPtrSet.h:450
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Definition: SmallVector.h:577
void push_back(const T &Elt)
Definition: SmallVector.h:416
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1200
The instances of the Type class are immutable: once they are created, they are never changed.
Definition: Type.h:45
TypeID
Definitions of all of the base types for the Type system.
Definition: Type.h:54
LLVM Value Representation.
Definition: Value.h:74
iterator_range< user_iterator > users()
Definition: Value.h:421
MDNode * getMetadata(unsigned KindID) const
Get the current metadata attachments for the given kind, if any.
Definition: Metadata.cpp:1288
StringRef getName() const
Return a constant reference to the value's name.
Definition: Value.cpp:308
@ C
The default llvm calling convention, compatible with C.
Definition: CallingConv.h:34
StringRef getName(ID id)
Return the LLVM name for an intrinsic, such as "llvm.ppc.altivec.lvx".
Definition: Function.cpp:979
@ CE
Windows NT (Windows on ARM)
initializer< Ty > init(const Ty &Val)
Definition: CommandLine.h:445
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
@ Offset
Definition: DWP.cpp:406
void replaceRelativePointerUsersWithZero(Function *F)
Finds the same "relative pointer" pattern as described above, where the target is F,...
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
bool isSafeToDestroyConstant(const Constant *C)
It is safe to destroy a constant iff it is only used by constants itself.
bool optimizeGlobalCtorsList(Module &M, function_ref< bool(uint32_t, Function *)> ShouldRemove)
Call "ShouldRemove" for every entry in M's global_ctor list and remove the entries for which it retur...
Definition: CtorUtils.cpp:113
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:163
Constant * getPointerAtOffset(Constant *I, uint64_t Offset, Module &M, Constant *TopLevelGlobal=nullptr)
Processes a Constant recursively looking into elements of arrays, structs and expressions to find a t...