[PATCH] D19782: [IPO/GlobalDCE] Convert the pass to use static functions.
Justin Bogner via llvm-commits
llvm-commits at lists.llvm.org
Sun May 1 20:17:35 PDT 2016
Davide Italiano <dccitaliano at gmail.com> writes:
> davide created this revision.
> davide added a reviewer: bogner.
> davide added a subscriber: llvm-commits.
>
> In preparation for porting GlobalDCE to the new PM.
This ends up with quite a bit of state being carried around in
arguments. I suspect a port that puts the state into the new style pass
and makes the old-style one a wrapper with a "GlobalDCEPass Impl" member
will read better. See GVN, SROA, or Reassociate for examples.
> http://reviews.llvm.org/D19782
>
> Files:
> lib/Transforms/IPO/GlobalDCE.cpp
>
> 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<GlobalValue*, 32> AliveGlobals;
> - SmallPtrSet<Constant *, 8> SeenConstants;
> - std::unordered_multimap<Comdat *, GlobalValue *> 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<GlobalValue *, 32> &AliveGlobals,
> + SmallPtrSet<Constant *, 8> &SeenConstants,
> + std::unordered_multimap<Comdat *, GlobalValue *> &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<GlobalValue *, 32> &AliveGlobals,
> + SmallPtrSet<Constant *, 8> &SeenConstants,
> + std::unordered_multimap<Comdat *, GlobalValue *> &ComdatMembers) {
> + if (GlobalValue *GV = dyn_cast<GlobalValue>(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<Constant>(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<GlobalValue *, 32> &AliveGlobals,
> + SmallPtrSet<Constant *, 8> &SeenConstants,
> + std::unordered_multimap<Comdat *, GlobalValue *> &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<GlobalVariable>(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<GlobalIndirectSymbol>(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<Function>(G);
> +
> + for (Use &U : F->operands())
> + MarkUsedGlobalsAsNeeded(cast<Constant>(U.get()), AliveGlobals,
> + SeenConstants, ComdatMembers);
> +
> + for (BasicBlock &BB : *F)
> + for (Instruction &I : BB)
> + for (Use &U : I.operands())
> + if (GlobalValue *GV = dyn_cast<GlobalValue>(U))
> + GlobalIsNeeded(GV, AliveGlobals, SeenConstants, ComdatMembers);
> + else if (Constant *C = dyn_cast<Constant>(U))
> + MarkUsedGlobalsAsNeeded(C, AliveGlobals, SeenConstants,
> + ComdatMembers);
> + }
> +}
> +
> +static bool runGlobalDCE(Module &M) {
> + SmallPtrSet<GlobalValue *, 32> AliveGlobals;
> + SmallPtrSet<Constant *, 8> SeenConstants;
> + std::unordered_multimap<Comdat *, GlobalValue *> ComdatMembers;
>
> bool Changed = false;
>
> @@ -100,23 +172,23 @@
> // 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()) {
> Changed |= RemoveUnusedGlobalValue(GV);
> // Externally visible & appending globals are needed, if they have an
> // 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<GlobalVariable>(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<GlobalIndirectSymbol>(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<Function>(G);
> -
> - for (Use &U : F->operands())
> - MarkUsedGlobalsAsNeeded(cast<Constant>(U.get()));
> -
> - for (BasicBlock &BB : *F)
> - for (Instruction &I : BB)
> - for (Use &U : I.operands())
> - if (GlobalValue *GV = dyn_cast<GlobalValue>(U))
> - GlobalIsNeeded(GV);
> - else if (Constant *C = dyn_cast<Constant>(U))
> - MarkUsedGlobalsAsNeeded(C);
> - }
> -}
> -
> -void GlobalDCE::MarkUsedGlobalsAsNeeded(Constant *C) {
> - if (GlobalValue *GV = dyn_cast<GlobalValue>(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<Constant>(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);
> }
More information about the llvm-commits
mailing list