Index: lib/Transforms/IPO/GlobalDCE.cpp =================================================================== --- lib/Transforms/IPO/GlobalDCE.cpp +++ lib/Transforms/IPO/GlobalDCE.cpp @@ -44,21 +44,15 @@ // the specified callgraph to reflect the changes. // bool runOnModule(Module &M) override; - - private: - SmallPtrSet AliveGlobals; - SmallPtrSet SeenConstants; - std::unordered_multimap ComdatMembers; - - /// GlobalIsNeeded - mark the specific global value as needed, and - /// recursively mark anything that it uses as also needed. - void GlobalIsNeeded(GlobalValue *GV); - void MarkUsedGlobalsAsNeeded(Constant *C); - - bool RemoveUnusedGlobalValue(GlobalValue &GV); }; } +// Declarations. +static void +GlobalIsNeeded(GlobalValue *G, SmallPtrSet &AliveGlobals, + SmallPtrSet &SeenConstants, + std::unordered_multimap &ComdatMembers); + /// Returns true if F contains only a single "ret" instruction. static bool isEmptyFunction(Function *F) { BasicBlock &Entry = F->getEntryBlock(); @@ -74,9 +68,87 @@ ModulePass *llvm::createGlobalDCEPass() { return new GlobalDCE(); } -bool GlobalDCE::runOnModule(Module &M) { - if (skipModule(M)) +// RemoveUnusedGlobalValue - Loop over all of the uses of the specified +// GlobalValue, looking for the constant pointer ref that may be pointing to it. +// If found, check to see if the constant pointer ref is safe to destroy, and if +// so, nuke it. This will reduce the reference count on the global value, which +// might make it deader. +// +static bool RemoveUnusedGlobalValue(GlobalValue &GV) { + if (GV.use_empty()) return false; + GV.removeDeadConstantUsers(); + return GV.use_empty(); +} + +static void MarkUsedGlobalsAsNeeded( + Constant *C, SmallPtrSet &AliveGlobals, + SmallPtrSet &SeenConstants, + std::unordered_multimap &ComdatMembers) { + if (GlobalValue *GV = dyn_cast(C)) + return GlobalIsNeeded(GV, AliveGlobals, SeenConstants, ComdatMembers); + + // Loop over all of the operands of the constant, adding any globals they + // use to the list of needed globals. + for (Use &U : C->operands()) { + // If we've already processed this constant there's no need to do it again. + Constant *Op = dyn_cast(U); + if (Op && SeenConstants.insert(Op).second) + MarkUsedGlobalsAsNeeded(Op, AliveGlobals, SeenConstants, ComdatMembers); + } +} + +/// GlobalIsNeeded - the specific global value as needed, and +/// recursively mark anything that it uses as also needed. +static void GlobalIsNeeded( + GlobalValue *G, SmallPtrSet &AliveGlobals, + SmallPtrSet &SeenConstants, + std::unordered_multimap &ComdatMembers) { + // If the global is already in the set, no need to reprocess it. + if (!AliveGlobals.insert(G).second) + return; + + if (Comdat *C = G->getComdat()) { + for (auto &&CM : make_range(ComdatMembers.equal_range(C))) + GlobalIsNeeded(CM.second, AliveGlobals, SeenConstants, ComdatMembers); + } + + if (GlobalVariable *GV = dyn_cast(G)) { + // If this is a global variable, we must make sure to add any global values + // referenced by the initializer to the alive set. + if (GV->hasInitializer()) + MarkUsedGlobalsAsNeeded(GV->getInitializer(), AliveGlobals, SeenConstants, + ComdatMembers); + } else if (GlobalIndirectSymbol *GIS = dyn_cast(G)) { + // The target of a global alias or ifunc is needed. + MarkUsedGlobalsAsNeeded(GIS->getIndirectSymbol(), AliveGlobals, + SeenConstants, ComdatMembers); + } else { + // Otherwise this must be a function object. We have to scan the body of + // the function looking for constants and global values which are used as + // operands. Any operands of these types must be processed to ensure that + // any globals used will be marked as needed. + Function *F = cast(G); + + for (Use &U : F->operands()) + MarkUsedGlobalsAsNeeded(cast(U.get()), AliveGlobals, + SeenConstants, ComdatMembers); + + for (BasicBlock &BB : *F) + for (Instruction &I : BB) + for (Use &U : I.operands()) + if (GlobalValue *GV = dyn_cast(U)) + GlobalIsNeeded(GV, AliveGlobals, SeenConstants, ComdatMembers); + else if (Constant *C = dyn_cast(U)) + MarkUsedGlobalsAsNeeded(C, AliveGlobals, SeenConstants, + ComdatMembers); + } +} + +static bool runGlobalDCE(Module &M) { + SmallPtrSet AliveGlobals; + SmallPtrSet SeenConstants; + std::unordered_multimap ComdatMembers; bool Changed = false; @@ -100,7 +172,7 @@ // Functions with external linkage are needed if they have a body if (!F.isDeclaration() && !F.hasAvailableExternallyLinkage()) if (!F.isDiscardableIfUnused()) - GlobalIsNeeded(&F); + GlobalIsNeeded(&F, AliveGlobals, SeenConstants, ComdatMembers); } for (GlobalVariable &GV : M.globals()) { @@ -109,14 +181,14 @@ // initializer. if (!GV.isDeclaration() && !GV.hasAvailableExternallyLinkage()) if (!GV.isDiscardableIfUnused()) - GlobalIsNeeded(&GV); + GlobalIsNeeded(&GV, AliveGlobals, SeenConstants, ComdatMembers); } for (GlobalAlias &GA : M.aliases()) { Changed |= RemoveUnusedGlobalValue(GA); // Externally visible aliases are needed. if (!GA.isDiscardableIfUnused()) - GlobalIsNeeded(&GA); + GlobalIsNeeded(&GA, AliveGlobals, SeenConstants, ComdatMembers); } // Now that all globals which are needed are in the AliveGlobals set, we loop @@ -191,69 +263,8 @@ return Changed; } -/// GlobalIsNeeded - the specific global value as needed, and -/// recursively mark anything that it uses as also needed. -void GlobalDCE::GlobalIsNeeded(GlobalValue *G) { - // If the global is already in the set, no need to reprocess it. - if (!AliveGlobals.insert(G).second) - return; - - if (Comdat *C = G->getComdat()) { - for (auto &&CM : make_range(ComdatMembers.equal_range(C))) - GlobalIsNeeded(CM.second); - } - - if (GlobalVariable *GV = dyn_cast(G)) { - // If this is a global variable, we must make sure to add any global values - // referenced by the initializer to the alive set. - if (GV->hasInitializer()) - MarkUsedGlobalsAsNeeded(GV->getInitializer()); - } else if (GlobalIndirectSymbol *GIS = dyn_cast(G)) { - // The target of a global alias or ifunc is needed. - MarkUsedGlobalsAsNeeded(GIS->getIndirectSymbol()); - } else { - // Otherwise this must be a function object. We have to scan the body of - // the function looking for constants and global values which are used as - // operands. Any operands of these types must be processed to ensure that - // any globals used will be marked as needed. - Function *F = cast(G); - - for (Use &U : F->operands()) - MarkUsedGlobalsAsNeeded(cast(U.get())); - - for (BasicBlock &BB : *F) - for (Instruction &I : BB) - for (Use &U : I.operands()) - if (GlobalValue *GV = dyn_cast(U)) - GlobalIsNeeded(GV); - else if (Constant *C = dyn_cast(U)) - MarkUsedGlobalsAsNeeded(C); - } -} - -void GlobalDCE::MarkUsedGlobalsAsNeeded(Constant *C) { - if (GlobalValue *GV = dyn_cast(C)) - return GlobalIsNeeded(GV); - - // Loop over all of the operands of the constant, adding any globals they - // use to the list of needed globals. - for (Use &U : C->operands()) { - // If we've already processed this constant there's no need to do it again. - Constant *Op = dyn_cast(U); - if (Op && SeenConstants.insert(Op).second) - MarkUsedGlobalsAsNeeded(Op); - } -} - -// RemoveUnusedGlobalValue - Loop over all of the uses of the specified -// GlobalValue, looking for the constant pointer ref that may be pointing to it. -// If found, check to see if the constant pointer ref is safe to destroy, and if -// so, nuke it. This will reduce the reference count on the global value, which -// might make it deader. -// -bool GlobalDCE::RemoveUnusedGlobalValue(GlobalValue &GV) { - if (GV.use_empty()) +bool GlobalDCE::runOnModule(Module &M) { + if (skipModule(M)) return false; - GV.removeDeadConstantUsers(); - return GV.use_empty(); + return runGlobalDCE(M); }