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