LLVM 23.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
35namespace {
36class GlobalDCELegacyPass : public ModulePass {
37public:
38 static char ID; // Pass identification, replacement for typeid
39 GlobalDCELegacyPass() : ModulePass(ID) {}
40 bool runOnModule(Module &M) override {
41 if (skipModule(M))
42 return false;
43 // Note: GlobalDCEPass does not use any analyses, so we're safe to call the
44 // new-pm style pass with a default-initialized analysis manager here
46 auto PA = Impl.run(M, MAM);
47 return !PA.areAllPreserved();
48 }
49
50private:
51 GlobalDCEPass Impl;
52};
53} // namespace
54
55char GlobalDCELegacyPass::ID = 0;
56INITIALIZE_PASS(GlobalDCELegacyPass, "globaldce", "Dead Global Elimination",
57 false, false)
58
59// Public interface to the GlobalDCEPass.
60ModulePass *llvm::createGlobalDCEPass() { return new GlobalDCELegacyPass(); }
61
62static cl::opt<bool>
63 ClEnableVFE("enable-vfe", cl::Hidden, cl::init(true),
64 cl::desc("Enable virtual function elimination"));
65
66STATISTIC(NumAliases , "Number of global aliases removed");
67STATISTIC(NumFunctions, "Number of functions removed");
68STATISTIC(NumIFuncs, "Number of indirect functions removed");
69STATISTIC(NumVariables, "Number of global variables removed");
70STATISTIC(NumVFuncs, "Number of virtual functions removed");
71
72/// Returns true if F is effectively empty.
73static bool isEmptyFunction(Function *F) {
74 // Skip external functions.
75 if (F->isDeclaration())
76 return false;
77 BasicBlock &Entry = F->getEntryBlock();
78 for (auto &I : Entry) {
79 if (I.isDebugOrPseudoInst())
80 continue;
81 if (auto *RI = dyn_cast<ReturnInst>(&I))
82 return !RI->getReturnValue();
83 break;
84 }
85 return false;
86}
87
88/// Compute the set of GlobalValue that depends from V.
89/// The recursion stops as soon as a GlobalValue is met.
90void GlobalDCEPass::ComputeDependencies(Value *V,
92 if (auto *I = dyn_cast<Instruction>(V)) {
93 Function *Parent = I->getParent()->getParent();
94 Deps.insert(Parent);
95 } else if (auto *GV = dyn_cast<GlobalValue>(V)) {
96 Deps.insert(GV);
97 } else if (auto *CE = dyn_cast<Constant>(V)) {
98 // Avoid walking the whole tree of a big ConstantExprs multiple times.
99 auto [Where, Inserted] = ConstantDependenciesCache.try_emplace(CE);
100 SmallPtrSetImpl<GlobalValue *> &LocalDeps = Where->second;
101 if (Inserted) {
102 for (User *CEUser : CE->users())
103 ComputeDependencies(CEUser, LocalDeps);
104 }
105 Deps.insert_range(LocalDeps);
106 }
107}
108
109void GlobalDCEPass::UpdateGVDependencies(GlobalValue &GV) {
110 SmallPtrSet<GlobalValue *, 8> Deps;
111 for (User *User : GV.users())
112 ComputeDependencies(User, Deps);
113 Deps.erase(&GV); // Remove self-reference.
114 for (GlobalValue *GVU : Deps) {
115 // If this is a dep from a vtable to a virtual function, and we have
116 // complete information about all virtual call sites which could call
117 // though this vtable, then skip it, because the call site information will
118 // be more precise.
119 if (VFESafeVTables.count(GVU) && isa<Function>(&GV)) {
120 LLVM_DEBUG(dbgs() << "Ignoring dep " << GVU->getName() << " -> "
121 << GV.getName() << "\n");
122 continue;
123 }
124 GVDependencies[GVU].insert(&GV);
125 }
126}
127
128/// Mark Global value as Live
129void GlobalDCEPass::MarkLive(GlobalValue &GV,
131 auto const Ret = AliveGlobals.insert(&GV);
132 if (!Ret.second)
133 return;
134
135 if (Updates)
136 Updates->push_back(&GV);
137 if (Comdat *C = GV.getComdat()) {
138 for (auto &&CM : make_range(ComdatMembers.equal_range(C))) {
139 MarkLive(*CM.second, Updates); // Recursion depth is only two because only
140 // globals in the same comdat are visited.
141 }
142 }
143}
144
145void GlobalDCEPass::ScanVTables(Module &M) {
147 LLVM_DEBUG(dbgs() << "Building type info -> vtable map\n");
148
149 for (GlobalVariable &GV : M.globals()) {
150 Types.clear();
151 GV.getMetadata(LLVMContext::MD_type, Types);
152 if (GV.isDeclaration() || Types.empty())
153 continue;
154
155 // Use the typeid metadata on the vtable to build a mapping from typeids to
156 // the list of (GV, offset) pairs which are the possible vtables for that
157 // typeid.
158 for (MDNode *Type : Types) {
159 Metadata *TypeID = Type->getOperand(1).get();
160
161 uint64_t Offset =
163 cast<ConstantAsMetadata>(Type->getOperand(0))->getValue())
164 ->getZExtValue();
165
166 TypeIdMap[TypeID].insert(std::make_pair(&GV, Offset));
167 }
168
169 // If the type corresponding to the vtable is private to this translation
170 // unit, we know that we can see all virtual functions which might use it,
171 // so VFE is safe.
172 GlobalObject::VCallVisibility TypeVis = GV.getVCallVisibility();
174 (InLTOPostLink &&
176 LLVM_DEBUG(dbgs() << GV.getName() << " is safe for VFE\n");
177 VFESafeVTables.insert(&GV);
178 }
179 }
180}
181
182void GlobalDCEPass::ScanVTableLoad(Function *Caller, Metadata *TypeId,
183 uint64_t CallOffset) {
184 for (const auto &VTableInfo : TypeIdMap[TypeId]) {
185 GlobalVariable *VTable = VTableInfo.first;
186 uint64_t VTableOffset = VTableInfo.second;
187
188 Constant *Ptr =
189 getPointerAtOffset(VTable->getInitializer(), VTableOffset + CallOffset,
190 *Caller->getParent(), VTable);
191 if (!Ptr) {
192 LLVM_DEBUG(dbgs() << "can't find pointer in vtable!\n");
193 VFESafeVTables.erase(VTable);
194 continue;
195 }
196
198 if (!Callee) {
199 LLVM_DEBUG(dbgs() << "vtable entry is not function pointer!\n");
200 VFESafeVTables.erase(VTable);
201 continue;
202 }
203
204 LLVM_DEBUG(dbgs() << "vfunc dep " << Caller->getName() << " -> "
205 << Callee->getName() << "\n");
206 GVDependencies[Caller].insert(Callee);
207 }
208}
209
210void GlobalDCEPass::ScanTypeCheckedLoadIntrinsics(Module &M) {
211 LLVM_DEBUG(dbgs() << "Scanning type.checked.load intrinsics\n");
212 Function *TypeCheckedLoadFunc =
213 Intrinsic::getDeclarationIfExists(&M, Intrinsic::type_checked_load);
214 Function *TypeCheckedLoadRelativeFunc = Intrinsic::getDeclarationIfExists(
215 &M, Intrinsic::type_checked_load_relative);
216
217 auto scan = [&](Function *CheckedLoadFunc) {
218 if (!CheckedLoadFunc)
219 return;
220
221 for (auto *U : CheckedLoadFunc->users()) {
222 auto CI = dyn_cast<CallInst>(U);
223 if (!CI)
224 continue;
225
226 auto *Offset = dyn_cast<ConstantInt>(CI->getArgOperand(1));
227 Value *TypeIdValue = CI->getArgOperand(2);
228 auto *TypeId = cast<MetadataAsValue>(TypeIdValue)->getMetadata();
229
230 if (Offset) {
231 ScanVTableLoad(CI->getFunction(), TypeId, Offset->getZExtValue());
232 } else {
233 // type.checked.load with a non-constant offset, so assume every entry
234 // in every matching vtable is used.
235 for (const auto &VTableInfo : TypeIdMap[TypeId]) {
236 VFESafeVTables.erase(VTableInfo.first);
237 }
238 }
239 }
240 };
241
242 scan(TypeCheckedLoadFunc);
243 scan(TypeCheckedLoadRelativeFunc);
244}
245
246void GlobalDCEPass::AddVirtualFunctionDependencies(Module &M) {
247 if (!ClEnableVFE)
248 return;
249
250 // If the Virtual Function Elim module flag is present and set to zero, then
251 // the vcall_visibility metadata was inserted for another optimization (WPD)
252 // and we may not have type checked loads on all accesses to the vtable.
253 // Don't attempt VFE in that case.
255 M.getModuleFlag("Virtual Function Elim"));
256 if (!Val || Val->isZero())
257 return;
258
259 ScanVTables(M);
260
261 if (VFESafeVTables.empty())
262 return;
263
264 ScanTypeCheckedLoadIntrinsics(M);
265
267 dbgs() << "VFE safe vtables:\n";
268 for (auto *VTable : VFESafeVTables)
269 dbgs() << " " << VTable->getName() << "\n";
270 );
271}
272
274 bool Changed = false;
275
276 // The algorithm first computes the set L of global variables that are
277 // trivially live. Then it walks the initialization of these variables to
278 // compute the globals used to initialize them, which effectively builds a
279 // directed graph where nodes are global variables, and an edge from A to B
280 // means B is used to initialize A. Finally, it propagates the liveness
281 // information through the graph starting from the nodes in L. Nodes note
282 // marked as alive are discarded.
283
284 // Remove empty functions from the global ctors list.
286 M, [](uint32_t, Function *F) { return isEmptyFunction(F); });
287
288 // Collect the set of members for each comdat.
289 for (Function &F : M)
290 if (Comdat *C = F.getComdat())
291 ComdatMembers.insert(std::make_pair(C, &F));
292 for (GlobalVariable &GV : M.globals())
293 if (Comdat *C = GV.getComdat())
294 ComdatMembers.insert(std::make_pair(C, &GV));
295 for (GlobalAlias &GA : M.aliases())
296 if (Comdat *C = GA.getComdat())
297 ComdatMembers.insert(std::make_pair(C, &GA));
298
299 // Add dependencies between virtual call sites and the virtual functions they
300 // might call, if we have that information.
301 AddVirtualFunctionDependencies(M);
302
303 // Loop over the module, adding globals which are obviously necessary.
304 for (GlobalObject &GO : M.global_objects()) {
305 GO.removeDeadConstantUsers();
306 // Functions with external linkage are needed if they have a body.
307 // Externally visible & appending globals are needed, if they have an
308 // initializer.
309 if (!GO.isDeclaration())
310 if (!GO.isDiscardableIfUnused())
311 MarkLive(GO);
312
313 UpdateGVDependencies(GO);
314 }
315
316 // Compute direct dependencies of aliases.
317 for (GlobalAlias &GA : M.aliases()) {
318 GA.removeDeadConstantUsers();
319 // Externally visible aliases are needed.
320 if (!GA.isDiscardableIfUnused())
321 MarkLive(GA);
322
323 UpdateGVDependencies(GA);
324 }
325
326 // Compute direct dependencies of ifuncs.
327 for (GlobalIFunc &GIF : M.ifuncs()) {
328 GIF.removeDeadConstantUsers();
329 // Externally visible ifuncs are needed.
330 if (!GIF.isDiscardableIfUnused())
331 MarkLive(GIF);
332
333 UpdateGVDependencies(GIF);
334 }
335
336 // Propagate liveness from collected Global Values through the computed
337 // dependencies.
338 SmallVector<GlobalValue *, 8> NewLiveGVs{AliveGlobals.begin(),
339 AliveGlobals.end()};
340 while (!NewLiveGVs.empty()) {
341 GlobalValue *LGV = NewLiveGVs.pop_back_val();
342 for (auto *GVD : GVDependencies[LGV])
343 MarkLive(*GVD, &NewLiveGVs);
344 }
345
346 // Now that all globals which are needed are in the AliveGlobals set, we loop
347 // through the program, deleting those which are not alive.
348 //
349
350 // The first pass is to drop initializers of global variables which are dead.
351 std::vector<GlobalVariable *> DeadGlobalVars; // Keep track of dead globals
352 for (GlobalVariable &GV : M.globals())
353 if (!AliveGlobals.count(&GV)) {
354 DeadGlobalVars.push_back(&GV); // Keep track of dead globals
355 if (GV.hasInitializer()) {
356 Constant *Init = GV.getInitializer();
357 GV.setInitializer(nullptr);
359 Init->destroyConstant();
360 }
361 }
362
363 // The second pass drops the bodies of functions which are dead...
364 std::vector<Function *> DeadFunctions;
365 for (Function &F : M)
366 if (!AliveGlobals.count(&F)) {
367 DeadFunctions.push_back(&F); // Keep track of dead globals
368 if (!F.isDeclaration())
369 F.deleteBody();
370 }
371
372 // The third pass drops targets of aliases which are dead...
373 std::vector<GlobalAlias*> DeadAliases;
374 for (GlobalAlias &GA : M.aliases())
375 if (!AliveGlobals.count(&GA)) {
376 DeadAliases.push_back(&GA);
377 GA.setAliasee(nullptr);
378 }
379
380 // The fourth pass drops targets of ifuncs which are dead...
381 std::vector<GlobalIFunc*> DeadIFuncs;
382 for (GlobalIFunc &GIF : M.ifuncs())
383 if (!AliveGlobals.count(&GIF)) {
384 DeadIFuncs.push_back(&GIF);
385 GIF.setResolver(nullptr);
386 }
387
388 // Now that all interferences have been dropped, delete the actual objects
389 // themselves.
390 auto EraseUnusedGlobalValue = [&](GlobalValue *GV) {
392 GV->eraseFromParent();
393 Changed = true;
394 };
395
396 NumFunctions += DeadFunctions.size();
397 for (Function *F : DeadFunctions) {
398 if (!F->use_empty()) {
399 // Virtual functions might still be referenced by one or more vtables,
400 // but if we've proven them to be unused then it's safe to replace the
401 // virtual function pointers with null, allowing us to remove the
402 // function itself.
403 ++NumVFuncs;
404
405 // Detect vfuncs that are referenced as "relative pointers" which are used
406 // in Swift vtables, i.e. entries in the form of:
407 //
408 // i32 trunc (i64 sub (i64 ptrtoint @f, i64 ptrtoint ...)) to i32)
409 //
410 // In this case, replace the whole "sub" expression with constant 0 to
411 // avoid leaving a weird sub(0, symbol) expression behind.
413
414 F->replaceNonMetadataUsesWith(ConstantPointerNull::get(F->getType()));
415 }
416 EraseUnusedGlobalValue(F);
417 }
418
419 NumVariables += DeadGlobalVars.size();
420 for (GlobalVariable *GV : DeadGlobalVars)
421 EraseUnusedGlobalValue(GV);
422
423 NumAliases += DeadAliases.size();
424 for (GlobalAlias *GA : DeadAliases)
425 EraseUnusedGlobalValue(GA);
426
427 NumIFuncs += DeadIFuncs.size();
428 for (GlobalIFunc *GIF : DeadIFuncs)
429 EraseUnusedGlobalValue(GIF);
430
431 // Make sure that all memory is released
432 AliveGlobals.clear();
433 ConstantDependenciesCache.clear();
434 GVDependencies.clear();
435 ComdatMembers.clear();
436 TypeIdMap.clear();
437 VFESafeVTables.clear();
438
439 if (Changed)
441 return PreservedAnalyses::all();
442}
443
445 raw_ostream &OS, function_ref<StringRef(StringRef)> MapClassName2PassName) {
446 static_cast<PassInfoMixin<GlobalDCEPass> *>(this)->printPipeline(
447 OS, MapClassName2PassName);
448 if (InLTOPostLink)
449 OS << "<vfe-linkage-unit-visibility>";
450}
dxil translate DXIL Translate Metadata
static bool isEmptyFunction(Function *F)
Returns true if F is effectively empty.
Definition GlobalDCE.cpp:73
static cl::opt< bool > ClEnableVFE("enable-vfe", cl::Hidden, cl::init(true), cl::desc("Enable virtual function elimination"))
Module.h This file contains the declarations for the Module class.
#define F(x, y, z)
Definition MD5.cpp:54
#define I(x, y, z)
Definition MD5.cpp:57
Type::TypeID TypeID
ModuleAnalysisManager MAM
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
Definition PassSupport.h:56
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:171
#define LLVM_DEBUG(...)
Definition Debug.h:114
LLVM Basic Block Representation.
Definition BasicBlock.h:62
static LLVM_ABI ConstantPointerNull * get(PointerType *T)
Static factory methods - Return objects of the specified value.
This is an important base class in LLVM.
Definition Constant.h:43
const Constant * stripPointerCasts() const
Definition Constant.h:219
LLVM_ABI void removeDeadConstantUsers() const
If there are any dead constant users dangling off of this constant, remove them.
Pass to remove unused function declarations.
Definition GlobalDCE.h:38
LLVM_ABI void printPipeline(raw_ostream &OS, function_ref< StringRef(StringRef)> MapClassName2PassName)
LLVM_ABI PreservedAnalyses run(Module &M, ModuleAnalysisManager &)
LLVM_ABI bool isDeclaration() const
Return true if the primary definition of this global value is outside of the current translation unit...
Definition Globals.cpp:331
LLVM_ABI const Comdat * getComdat() const
Definition Globals.cpp:204
LLVM_ABI void eraseFromParent()
This method unlinks 'this' from the containing module and deletes it.
Definition Globals.cpp:96
Root of the metadata hierarchy.
Definition Metadata.h:64
ModulePass class - This class is used to implement unstructured interprocedural optimizations and ana...
Definition Pass.h:255
A Module instance is used to store all the information related to an LLVM module.
Definition Module.h:67
A set of analyses that are preserved following a run of a transformation pass.
Definition Analysis.h:112
static PreservedAnalyses none()
Convenience factory function for the empty preserved set.
Definition Analysis.h:115
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Definition Analysis.h:118
A templated base class for SmallPtrSet which provides the typesafe interface that is common across al...
bool erase(PtrType Ptr)
Remove pointer from the set.
void insert_range(Range &&R)
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StringRef - Represent a constant reference to a string, i.e.
Definition StringRef.h:55
LLVM Value Representation.
Definition Value.h:75
iterator_range< user_iterator > users()
Definition Value.h:427
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
Definition Value.cpp:322
MDNode * getMetadata(unsigned KindID) const
Get the current metadata attachments for the given kind, if any.
Definition Value.h:577
An efficient, type-erasing, non-owning reference to a callable.
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition raw_ostream.h:53
Changed
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition CallingConv.h:24
@ C
The default llvm calling convention, compatible with C.
Definition CallingConv.h:34
LLVM_ABI Function * getDeclarationIfExists(const Module *M, ID id)
Look up the Function declaration of the intrinsic id in the Module M and return it if it exists.
@ CE
Windows NT (Windows on ARM)
Definition MCAsmInfo.h:48
initializer< Ty > init(const Ty &Val)
std::enable_if_t< detail::IsValidPointer< X, Y >::value, X * > dyn_extract_or_null(Y &&MD)
Extract a Value from Metadata, if any, allowing null.
Definition Metadata.h:709
This is an optimization pass for GlobalISel generic memory operations.
@ Offset
Definition DWP.cpp:532
FunctionAddr VTableAddr Value
Definition InstrProf.h:137
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
LLVM_ABI ModulePass * createGlobalDCEPass()
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...
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:207
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
Definition Casting.h:547
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
void replaceRelativePointerUsersWithZero(Constant *C)
Finds the same "relative pointer" pattern as described above, where the target is C,...
AnalysisManager< Module > ModuleAnalysisManager
Convenience typedef for the Module analysis manager.
Definition MIRParser.h:39
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...
A CRTP mix-in to automatically provide informational APIs needed for passes.
Definition PassManager.h:70