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 if (auto GO = dyn_cast<GlobalObject>(&GV)) {
173 GlobalObject::VCallVisibility TypeVis = GO->getVCallVisibility();
175 (InLTOPostLink &&
177 LLVM_DEBUG(dbgs() << GV.getName() << " is safe for VFE\n");
178 VFESafeVTables.insert(&GV);
179 }
180 }
181 }
182}
183
184void GlobalDCEPass::ScanVTableLoad(Function *Caller, Metadata *TypeId,
185 uint64_t CallOffset) {
186 for (const auto &VTableInfo : TypeIdMap[TypeId]) {
187 GlobalVariable *VTable = VTableInfo.first;
188 uint64_t VTableOffset = VTableInfo.second;
189
190 Constant *Ptr =
191 getPointerAtOffset(VTable->getInitializer(), VTableOffset + CallOffset,
192 *Caller->getParent(), VTable);
193 if (!Ptr) {
194 LLVM_DEBUG(dbgs() << "can't find pointer in vtable!\n");
195 VFESafeVTables.erase(VTable);
196 continue;
197 }
198
200 if (!Callee) {
201 LLVM_DEBUG(dbgs() << "vtable entry is not function pointer!\n");
202 VFESafeVTables.erase(VTable);
203 continue;
204 }
205
206 LLVM_DEBUG(dbgs() << "vfunc dep " << Caller->getName() << " -> "
207 << Callee->getName() << "\n");
208 GVDependencies[Caller].insert(Callee);
209 }
210}
211
212void GlobalDCEPass::ScanTypeCheckedLoadIntrinsics(Module &M) {
213 LLVM_DEBUG(dbgs() << "Scanning type.checked.load intrinsics\n");
214 Function *TypeCheckedLoadFunc =
215 Intrinsic::getDeclarationIfExists(&M, Intrinsic::type_checked_load);
216 Function *TypeCheckedLoadRelativeFunc = Intrinsic::getDeclarationIfExists(
217 &M, Intrinsic::type_checked_load_relative);
218
219 auto scan = [&](Function *CheckedLoadFunc) {
220 if (!CheckedLoadFunc)
221 return;
222
223 for (auto *U : CheckedLoadFunc->users()) {
224 auto CI = dyn_cast<CallInst>(U);
225 if (!CI)
226 continue;
227
228 auto *Offset = dyn_cast<ConstantInt>(CI->getArgOperand(1));
229 Value *TypeIdValue = CI->getArgOperand(2);
230 auto *TypeId = cast<MetadataAsValue>(TypeIdValue)->getMetadata();
231
232 if (Offset) {
233 ScanVTableLoad(CI->getFunction(), TypeId, Offset->getZExtValue());
234 } else {
235 // type.checked.load with a non-constant offset, so assume every entry
236 // in every matching vtable is used.
237 for (const auto &VTableInfo : TypeIdMap[TypeId]) {
238 VFESafeVTables.erase(VTableInfo.first);
239 }
240 }
241 }
242 };
243
244 scan(TypeCheckedLoadFunc);
245 scan(TypeCheckedLoadRelativeFunc);
246}
247
248void GlobalDCEPass::AddVirtualFunctionDependencies(Module &M) {
249 if (!ClEnableVFE)
250 return;
251
252 // If the Virtual Function Elim module flag is present and set to zero, then
253 // the vcall_visibility metadata was inserted for another optimization (WPD)
254 // and we may not have type checked loads on all accesses to the vtable.
255 // Don't attempt VFE in that case.
257 M.getModuleFlag("Virtual Function Elim"));
258 if (!Val || Val->isZero())
259 return;
260
261 ScanVTables(M);
262
263 if (VFESafeVTables.empty())
264 return;
265
266 ScanTypeCheckedLoadIntrinsics(M);
267
269 dbgs() << "VFE safe vtables:\n";
270 for (auto *VTable : VFESafeVTables)
271 dbgs() << " " << VTable->getName() << "\n";
272 );
273}
274
276 bool Changed = false;
277
278 // The algorithm first computes the set L of global variables that are
279 // trivially live. Then it walks the initialization of these variables to
280 // compute the globals used to initialize them, which effectively builds a
281 // directed graph where nodes are global variables, and an edge from A to B
282 // means B is used to initialize A. Finally, it propagates the liveness
283 // information through the graph starting from the nodes in L. Nodes note
284 // marked as alive are discarded.
285
286 // Remove empty functions from the global ctors list.
288 M, [](uint32_t, Function *F) { return isEmptyFunction(F); });
289
290 // Collect the set of members for each comdat.
291 for (Function &F : M)
292 if (Comdat *C = F.getComdat())
293 ComdatMembers.insert(std::make_pair(C, &F));
294 for (GlobalVariable &GV : M.globals())
295 if (Comdat *C = GV.getComdat())
296 ComdatMembers.insert(std::make_pair(C, &GV));
297 for (GlobalAlias &GA : M.aliases())
298 if (Comdat *C = GA.getComdat())
299 ComdatMembers.insert(std::make_pair(C, &GA));
300
301 // Add dependencies between virtual call sites and the virtual functions they
302 // might call, if we have that information.
303 AddVirtualFunctionDependencies(M);
304
305 // Loop over the module, adding globals which are obviously necessary.
306 for (GlobalObject &GO : M.global_objects()) {
307 GO.removeDeadConstantUsers();
308 // Functions with external linkage are needed if they have a body.
309 // Externally visible & appending globals are needed, if they have an
310 // initializer.
311 if (!GO.isDeclaration())
312 if (!GO.isDiscardableIfUnused())
313 MarkLive(GO);
314
315 UpdateGVDependencies(GO);
316 }
317
318 // Compute direct dependencies of aliases.
319 for (GlobalAlias &GA : M.aliases()) {
320 GA.removeDeadConstantUsers();
321 // Externally visible aliases are needed.
322 if (!GA.isDiscardableIfUnused())
323 MarkLive(GA);
324
325 UpdateGVDependencies(GA);
326 }
327
328 // Compute direct dependencies of ifuncs.
329 for (GlobalIFunc &GIF : M.ifuncs()) {
330 GIF.removeDeadConstantUsers();
331 // Externally visible ifuncs are needed.
332 if (!GIF.isDiscardableIfUnused())
333 MarkLive(GIF);
334
335 UpdateGVDependencies(GIF);
336 }
337
338 // Propagate liveness from collected Global Values through the computed
339 // dependencies.
340 SmallVector<GlobalValue *, 8> NewLiveGVs{AliveGlobals.begin(),
341 AliveGlobals.end()};
342 while (!NewLiveGVs.empty()) {
343 GlobalValue *LGV = NewLiveGVs.pop_back_val();
344 for (auto *GVD : GVDependencies[LGV])
345 MarkLive(*GVD, &NewLiveGVs);
346 }
347
348 // Now that all globals which are needed are in the AliveGlobals set, we loop
349 // through the program, deleting those which are not alive.
350 //
351
352 // The first pass is to drop initializers of global variables which are dead.
353 std::vector<GlobalVariable *> DeadGlobalVars; // Keep track of dead globals
354 for (GlobalVariable &GV : M.globals())
355 if (!AliveGlobals.count(&GV)) {
356 DeadGlobalVars.push_back(&GV); // Keep track of dead globals
357 if (GV.hasInitializer()) {
358 Constant *Init = GV.getInitializer();
359 GV.setInitializer(nullptr);
361 Init->destroyConstant();
362 }
363 }
364
365 // The second pass drops the bodies of functions which are dead...
366 std::vector<Function *> DeadFunctions;
367 for (Function &F : M)
368 if (!AliveGlobals.count(&F)) {
369 DeadFunctions.push_back(&F); // Keep track of dead globals
370 if (!F.isDeclaration())
371 F.deleteBody();
372 }
373
374 // The third pass drops targets of aliases which are dead...
375 std::vector<GlobalAlias*> DeadAliases;
376 for (GlobalAlias &GA : M.aliases())
377 if (!AliveGlobals.count(&GA)) {
378 DeadAliases.push_back(&GA);
379 GA.setAliasee(nullptr);
380 }
381
382 // The fourth pass drops targets of ifuncs which are dead...
383 std::vector<GlobalIFunc*> DeadIFuncs;
384 for (GlobalIFunc &GIF : M.ifuncs())
385 if (!AliveGlobals.count(&GIF)) {
386 DeadIFuncs.push_back(&GIF);
387 GIF.setResolver(nullptr);
388 }
389
390 // Now that all interferences have been dropped, delete the actual objects
391 // themselves.
392 auto EraseUnusedGlobalValue = [&](GlobalValue *GV) {
394 GV->eraseFromParent();
395 Changed = true;
396 };
397
398 NumFunctions += DeadFunctions.size();
399 for (Function *F : DeadFunctions) {
400 if (!F->use_empty()) {
401 // Virtual functions might still be referenced by one or more vtables,
402 // but if we've proven them to be unused then it's safe to replace the
403 // virtual function pointers with null, allowing us to remove the
404 // function itself.
405 ++NumVFuncs;
406
407 // Detect vfuncs that are referenced as "relative pointers" which are used
408 // in Swift vtables, i.e. entries in the form of:
409 //
410 // i32 trunc (i64 sub (i64 ptrtoint @f, i64 ptrtoint ...)) to i32)
411 //
412 // In this case, replace the whole "sub" expression with constant 0 to
413 // avoid leaving a weird sub(0, symbol) expression behind.
415
416 F->replaceNonMetadataUsesWith(ConstantPointerNull::get(F->getType()));
417 }
418 EraseUnusedGlobalValue(F);
419 }
420
421 NumVariables += DeadGlobalVars.size();
422 for (GlobalVariable *GV : DeadGlobalVars)
423 EraseUnusedGlobalValue(GV);
424
425 NumAliases += DeadAliases.size();
426 for (GlobalAlias *GA : DeadAliases)
427 EraseUnusedGlobalValue(GA);
428
429 NumIFuncs += DeadIFuncs.size();
430 for (GlobalIFunc *GIF : DeadIFuncs)
431 EraseUnusedGlobalValue(GIF);
432
433 // Make sure that all memory is released
434 AliveGlobals.clear();
435 ConstantDependenciesCache.clear();
436 GVDependencies.clear();
437 ComdatMembers.clear();
438 TypeIdMap.clear();
439 VFESafeVTables.clear();
440
441 if (Changed)
443 return PreservedAnalyses::all();
444}
445
447 raw_ostream &OS, function_ref<StringRef(StringRef)> MapClassName2PassName) {
448 static_cast<PassInfoMixin<GlobalDCEPass> *>(this)->printPipeline(
449 OS, MapClassName2PassName);
450 if (InLTOPostLink)
451 OS << "<vfe-linkage-unit-visibility>";
452}
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:329
LLVM_ABI const Comdat * getComdat() const
Definition Globals.cpp:202
LLVM_ABI void eraseFromParent()
This method unlinks 'this' from the containing module and deletes it.
Definition Globals.cpp:94
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.
Definition Types.h:26
@ 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