[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