34#define DEBUG_TYPE "globaldce"
41 bool runOnModule(
Module &M)
override {
47 auto PA = Impl.run(M,
MAM);
48 return !PA.areAllPreserved();
56char GlobalDCELegacyPass::ID = 0;
63STATISTIC(NumAliases ,
"Number of global aliases removed");
64STATISTIC(NumFunctions,
"Number of functions removed");
65STATISTIC(NumIFuncs,
"Number of indirect functions removed");
66STATISTIC(NumVariables,
"Number of global variables removed");
67STATISTIC(NumVFuncs,
"Number of virtual functions removed");
72 if (
F->isDeclaration())
75 for (
auto &
I : Entry) {
79 return !RI->getReturnValue();
87void GlobalDCEPass::ComputeDependencies(
Value *
V,
90 Function *Parent =
I->getParent()->getParent();
96 auto Where = ConstantDependenciesCache.find(CE);
97 if (Where == ConstantDependenciesCache.end()) {
100 SmallPtrSet<GlobalValue *, 8> LocalDeps;
101 for (User *CEUser :
CE->users())
102 ComputeDependencies(CEUser, LocalDeps);
104 ConstantDependenciesCache.try_emplace(CE, std::move(LocalDeps)).first;
110void GlobalDCEPass::UpdateGVDependencies(
GlobalValue &GV) {
111 SmallPtrSet<GlobalValue *, 8> Deps;
112 for (User *User : GV.
users())
113 ComputeDependencies(User, Deps);
115 for (GlobalValue *GVU : Deps) {
125 GVDependencies[GVU].insert(&GV);
132 auto const Ret = AliveGlobals.insert(&GV);
139 for (
auto &&CM :
make_range(ComdatMembers.equal_range(
C))) {
140 MarkLive(*CM.second, Updates);
146void GlobalDCEPass::ScanVTables(
Module &M) {
150 for (GlobalVariable &GV :
M.globals()) {
159 for (MDNode *
Type : Types) {
178 VFESafeVTables.insert(&GV);
185 for (
const auto &VTableInfo : TypeIdMap[TypeId]) {
186 GlobalVariable *
VTable = VTableInfo.first;
187 uint64_t VTableOffset = VTableInfo.second;
191 *
Caller->getParent(), VTable);
194 VFESafeVTables.erase(VTable);
201 VFESafeVTables.erase(VTable);
206 <<
Callee->getName() <<
"\n");
211void GlobalDCEPass::ScanTypeCheckedLoadIntrinsics(
Module &M) {
216 &M, Intrinsic::type_checked_load_relative);
220 DenseSet<std::tuple<Function *, Metadata *, uint64_t>> ScannedLoads;
222 auto scan = [&](
Function *CheckedLoadFunc) {
223 if (!CheckedLoadFunc)
226 for (
auto *U : CheckedLoadFunc->users()) {
232 Value *TypeIdValue = CI->getArgOperand(2);
237 .insert({CI->getFunction(), TypeId,
Offset->getZExtValue()})
239 ScanVTableLoad(CI->getFunction(), TypeId,
Offset->getZExtValue());
243 for (
const auto &VTableInfo : TypeIdMap[TypeId]) {
244 VFESafeVTables.erase(VTableInfo.first);
250 scan(TypeCheckedLoadFunc);
251 scan(TypeCheckedLoadRelativeFunc);
254void GlobalDCEPass::AddVirtualFunctionDependencies(
Module &M) {
263 M.getModuleFlag(
"Virtual Function Elim"));
264 if (!Val || Val->isZero())
269 if (VFESafeVTables.empty())
272 ScanTypeCheckedLoadIntrinsics(M);
275 dbgs() <<
"VFE safe vtables:\n";
276 for (
auto *VTable : VFESafeVTables)
305 ComdatMembers.insert(std::make_pair(
C, &
F));
308 ComdatMembers.insert(std::make_pair(
C, &GV));
310 if (
Comdat *
C = GA.getComdat())
311 ComdatMembers.insert(std::make_pair(
C, &GA));
315 AddVirtualFunctionDependencies(M);
319 GO.removeDeadConstantUsers();
323 if (!GO.isDeclaration())
324 if (!GO.isDiscardableIfUnused())
327 UpdateGVDependencies(GO);
332 GA.removeDeadConstantUsers();
334 if (!GA.isDiscardableIfUnused())
337 UpdateGVDependencies(GA);
342 GIF.removeDeadConstantUsers();
344 if (!GIF.isDiscardableIfUnused())
347 UpdateGVDependencies(GIF);
354 while (!NewLiveGVs.
empty()) {
356 for (
auto *GVD : GVDependencies[LGV])
357 MarkLive(*GVD, &NewLiveGVs);
363 if (
auto It = VFuncDependencies.find(
F); It != VFuncDependencies.end()) {
364 for (
auto [VTable, VFunc] : It->second) {
365 if (AliveGlobals.contains(VTable))
366 MarkLive(*VFunc, &NewLiveGVs);
368 PendingVFuncs[VTable].push_back(VFunc);
376 if (
auto It = PendingVFuncs.find(VT); It != PendingVFuncs.end()) {
377 for (
auto *VFunc : It->second)
378 MarkLive(*VFunc, &NewLiveGVs);
388 std::vector<GlobalVariable *> DeadGlobalVars;
390 if (!AliveGlobals.count(&GV)) {
391 DeadGlobalVars.push_back(&GV);
392 if (GV.hasInitializer()) {
394 GV.setInitializer(
nullptr);
396 Init->destroyConstant();
401 std::vector<Function *> DeadFunctions;
403 if (!AliveGlobals.count(&
F)) {
404 DeadFunctions.push_back(&
F);
405 if (!
F.isDeclaration())
410 std::vector<GlobalAlias*> DeadAliases;
412 if (!AliveGlobals.count(&GA)) {
413 DeadAliases.push_back(&GA);
414 GA.setAliasee(
nullptr);
418 std::vector<GlobalIFunc*> DeadIFuncs;
420 if (!AliveGlobals.count(&GIF)) {
421 DeadIFuncs.push_back(&GIF);
422 GIF.setResolver(
nullptr);
427 auto EraseUnusedGlobalValue = [&](
GlobalValue *GV) {
433 NumFunctions += DeadFunctions.size();
435 if (!
F->use_empty()) {
453 EraseUnusedGlobalValue(
F);
456 NumVariables += DeadGlobalVars.size();
458 EraseUnusedGlobalValue(GV);
460 NumAliases += DeadAliases.size();
462 EraseUnusedGlobalValue(GA);
464 NumIFuncs += DeadIFuncs.size();
466 EraseUnusedGlobalValue(GIF);
469 AliveGlobals.clear();
470 ConstantDependenciesCache.clear();
471 GVDependencies.clear();
472 VFuncDependencies.clear();
473 PendingVFuncs.clear();
474 ComdatMembers.clear();
476 VFESafeVTables.clear();
485 static_cast<PassInfoMixin<GlobalDCEPass> *
>(
this)->
printPipeline(
486 OS, MapClassName2PassName);
488 OS <<
"<vfe-linkage-unit-visibility>";
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
This file defines the DenseSet and SmallDenseSet classes.
static bool isEmptyFunction(Function *F)
Returns true if F is effectively empty.
Module.h This file contains the declarations for the Module class.
ModuleAnalysisManager MAM
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
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)
LLVM Basic Block Representation.
static LLVM_ABI ConstantPointerNull * get(PointerType *T)
Static factory methods - Return objects of the specified value.
This is an important base class in LLVM.
const Constant * stripPointerCasts() const
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.
LLVM_ABI void printPipeline(raw_ostream &OS, function_ref< StringRef(StringRef)> MapClassName2PassName)
LLVM_ABI PreservedAnalyses run(Module &M, ModuleAnalysisManager &)
@ VCallVisibilityLinkageUnit
@ VCallVisibilityTranslationUnit
LLVM_ABI bool isDeclaration() const
Return true if the primary definition of this global value is outside of the current translation unit...
LLVM_ABI const Comdat * getComdat() const
LLVM_ABI void eraseFromParent()
This method unlinks 'this' from the containing module and deletes it.
ModulePass class - This class is used to implement unstructured interprocedural optimizations and ana...
A Module instance is used to store all the information related to an LLVM module.
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses none()
Convenience factory function for the empty preserved set.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
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.
Represent a constant reference to a string, i.e.
LLVM Value Representation.
iterator_range< user_iterator > users()
LLVM_ABI MDNode * getMetadata(StringRef Kind) const LLVM_READONLY
Get the current metadata attachments for the given kind, if any.
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
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.
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)
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.
This is an optimization pass for GlobalISel generic memory operations.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
LLVM_ABI ModulePass * createGlobalDCEPass()
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
const IPOOptions & getIPOOptions(const LLVMContext &C)
LLVM_ABI bool isSafeToDestroyConstant(const Constant *C)
It is safe to destroy a constant iff it is only used by constants itself.
LLVM_ABI 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.
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...
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
LLVM_ABI 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.
LLVM_ABI 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...