diff --git a/lib/Transforms/IPO/GlobalDCE.cpp b/lib/Transforms/IPO/GlobalDCE.cpp index 5ce79625b84..2e18c43bac3 100644 --- a/lib/Transforms/IPO/GlobalDCE.cpp +++ b/lib/Transforms/IPO/GlobalDCE.cpp @@ -1,93 +1,39 @@ //===-- GlobalDCE.cpp - DCE unreachable internal functions ----------------===// // -// This transform is designed to eliminate unreachable internal globals -// FIXME: GlobalDCE should update the callgraph, not destroy it! +// This transform is designed to eliminate unreachable internal globals from the +// program. It uses an aggressive algorithm, searching out globals that are +// known to be alive. After it finds all of the globals which are needed, it +// deletes whatever is left over. This allows it to delete recursive chunks of +// the program which are unreachable. // //===----------------------------------------------------------------------===// #include "llvm/Transforms/IPO.h" -#include "llvm/Module.h" #include "llvm/Constants.h" -#include "llvm/DerivedTypes.h" -#include "llvm/Analysis/CallGraph.h" -#include "Support/DepthFirstIterator.h" +#include "llvm/Module.h" +#include "llvm/Pass.h" #include "Support/Statistic.h" -#include +#include namespace { Statistic<> NumFunctions("globaldce","Number of functions removed"); Statistic<> NumVariables("globaldce","Number of global variables removed"); Statistic<> NumCPRs("globaldce", "Number of const pointer refs removed"); - Statistic<> NumConsts("globaldce", "Number of init constants removed"); - bool RemoveUnreachableFunctions(Module &M, CallGraph &CallGraph) { - // Calculate which functions are reachable from the external functions in - // the call graph. - // - std::set ReachableNodes(df_begin(&CallGraph), - df_end(&CallGraph)); - - // Loop over the functions in the module twice. The first time is used to - // drop references that functions have to each other before they are - // deleted. The second pass removes the functions that need to be removed. - // - std::vector FunctionsToDelete; // Track unused functions - for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) { - CallGraphNode *N = CallGraph[I]; - - if (!ReachableNodes.count(N)) { // Not reachable?? - I->dropAllReferences(); - N->removeAllCalledFunctions(); - FunctionsToDelete.push_back(N); - ++NumFunctions; - } - } - - // Nothing to do if no unreachable functions have been found... - if (FunctionsToDelete.empty()) return false; - - // Unreachable functions have been found and should have no references to - // them, delete them now. - // - for (std::vector::iterator I = FunctionsToDelete.begin(), - E = FunctionsToDelete.end(); I != E; ++I) - delete CallGraph.removeFunctionFromModule(*I); - - // Walk the function list, removing prototypes for functions which are not - // used. - for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) - if (I->use_size() == 0 && I->isExternal()) { - CallGraph[I]->removeAllCalledFunctions(); - delete CallGraph.removeFunctionFromModule(I); - } - - return true; - } - struct GlobalDCE : public Pass { // run - Do the GlobalDCE pass on the specified module, optionally updating // the specified callgraph to reflect the changes. // - bool run(Module &M) { - return RemoveUnreachableFunctions(M, getAnalysis()) | - RemoveUnreachableGlobalVariables(M); - } - - // getAnalysisUsage - This function works on the call graph of a module. - // It is capable of updating the call graph to reflect the new state of the - // module. - // - virtual void getAnalysisUsage(AnalysisUsage &AU) const { - AU.addRequired(); - } + bool run(Module &M); private: - std::vector WorkList; + std::set AliveGlobals; - inline bool RemoveIfDead(GlobalValue *GV); - void DestroyInitializer(Constant *C); + /// MarkGlobalIsNeeded - 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 RemoveUnreachableGlobalVariables(Module &M); bool RemoveUnusedConstantPointerRef(GlobalValue &GV); bool SafeToDestroyConstant(Constant *C); }; @@ -96,135 +42,116 @@ namespace { Pass *createGlobalDCEPass() { return new GlobalDCE(); } - -// RemoveIfDead - If this global value is dead, remove it from the current -// module and return true. -// -bool GlobalDCE::RemoveIfDead(GlobalValue *GV) { - // If there is only one use of the global value, it might be a - // ConstantPointerRef... which means that this global might actually be - // dead. - if (GV->use_size() == 1) - RemoveUnusedConstantPointerRef(*GV); - - if (!GV->use_empty()) return false; - - if (GlobalVariable *GVar = dyn_cast(GV)) { - // Eliminate all global variables that are unused, and that are internal, or - // do not have an initializer. - // - if (GVar->hasInternalLinkage() || GVar->isExternal()) { - Constant *Init = GVar->hasInitializer() ? GVar->getInitializer() : 0; - GV->getParent()->getGlobalList().erase(GVar); - ++NumVariables; - - // If there was an initializer for the global variable, try to destroy it - // now. - if (Init) DestroyInitializer(Init); - - // If the global variable is still on the worklist, remove it now. - std::vector::iterator I = std::find(WorkList.begin(), - WorkList.end(), GV); - while (I != WorkList.end()) { - I = WorkList.erase(I); - I = std::find(I, WorkList.end(), GV); - } - - return true; - } - } else { - Function *F = cast(GV); - // FIXME: TODO - - } - return false; -} - -// DestroyInitializer - A global variable was just destroyed and C is its -// initializer. If we can, destroy C and all of the constants it refers to. -// -void GlobalDCE::DestroyInitializer(Constant *C) { - // Cannot destroy constants still being used, and cannot destroy primitive - // types. - if (!C->use_empty() || C->getType()->isPrimitiveType()) return; - - // If this is a CPR, the global value referred to may be dead now! Add it to - // the worklist. - // - if (ConstantPointerRef *CPR = dyn_cast(C)) { - WorkList.push_back(CPR->getValue()); - C->destroyConstant(); - ++NumCPRs; - } else { - bool DestroyContents = true; - - // As an optimization to the GlobalDCE algorithm, do attempt to destroy the - // contents of an array of primitive types, because we know that this will - // never succeed, and there could be a lot of them. - // - if (ConstantArray *CA = dyn_cast(C)) - if (CA->getType()->getElementType()->isPrimitiveType()) - DestroyContents = false; // Nothing we can do with the subcontents - - // All other constants refer to other constants. Destroy them if possible - // as well. - // - std::vector SubConstants; - if (DestroyContents) SubConstants.insert(SubConstants.end(), - C->op_begin(), C->op_end()); - - // Destroy the actual constant... - C->destroyConstant(); - ++NumConsts; - - if (DestroyContents) { - // Remove duplicates from SubConstants, so that we do not call - // DestroyInitializer on the same constant twice (the first call might - // delete it, so this would be bad) - // - std::sort(SubConstants.begin(), SubConstants.end()); - SubConstants.erase(std::unique(SubConstants.begin(), SubConstants.end()), - SubConstants.end()); - - // Loop over the subconstants, destroying them as well. - for (unsigned i = 0, e = SubConstants.size(); i != e; ++i) - DestroyInitializer(cast(SubConstants[i])); - } - } -} - -bool GlobalDCE::RemoveUnreachableGlobalVariables(Module &M) { +bool GlobalDCE::run(Module &M) { bool Changed = false; - WorkList.reserve(M.gsize()); - - // Insert all of the globals into the WorkList, making sure to run - // RemoveUnusedConstantPointerRef at least once on all globals... - // + // Loop over the module, adding globals which are obviously necessary. for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) { Changed |= RemoveUnusedConstantPointerRef(*I); - WorkList.push_back(I); + // Functions with external linkage are needed if they have a body + if (I->hasExternalLinkage() && !I->isExternal()) + GlobalIsNeeded(I); } + for (Module::giterator I = M.gbegin(), E = M.gend(); I != E; ++I) { Changed |= RemoveUnusedConstantPointerRef(*I); - WorkList.push_back(I); + // Externally visible globals are needed, if they have an initializer. + if (I->hasExternalLinkage() && !I->isExternal()) + GlobalIsNeeded(I); } - // Loop over the worklist, deleting global objects that we can. Whenever we - // delete something that might make something else dead, it gets added to the - // worklist. + + // Now that all globals which are needed are in the AliveGlobals set, we loop + // through the program, deleting those which are not alive. // - while (!WorkList.empty()) { - GlobalValue *GV = WorkList.back(); - WorkList.pop_back(); - Changed |= RemoveIfDead(GV); + // The first pass is to drop initializers of global variables which are dead. + std::vector DeadGlobalVars; // Keep track of dead globals + for (Module::giterator I = M.gbegin(), E = M.gend(); I != E; ++I) + if (!AliveGlobals.count(I)) { + DeadGlobalVars.push_back(I); // Keep track of dead globals + I->setInitializer(0); + } + + + // The second pass drops the bodies of functions which are dead... + std::vector DeadFunctions; + for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) + if (!AliveGlobals.count(I)) { + DeadFunctions.push_back(I); // Keep track of dead globals + if (!I->isExternal()) + I->deleteBody(); + } + + if (!DeadFunctions.empty()) { + // Now that all interreferences have been dropped, delete the actual objects + // themselves. + for (unsigned i = 0, e = DeadFunctions.size(); i != e; ++i) { + RemoveUnusedConstantPointerRef(*DeadFunctions[i]); + M.getFunctionList().erase(DeadFunctions[i]); + } + NumFunctions += DeadFunctions.size(); + Changed = true; } - // Make sure that all memory is free'd from the worklist... - std::vector().swap(WorkList); + if (!DeadGlobalVars.empty()) { + for (unsigned i = 0, e = DeadGlobalVars.size(); i != e; ++i) { + RemoveUnusedConstantPointerRef(*DeadGlobalVars[i]); + M.getGlobalList().erase(DeadGlobalVars[i]); + } + NumVariables += DeadGlobalVars.size(); + Changed = true; + } + + // Make sure that all memory is released + AliveGlobals.clear(); return Changed; } +/// MarkGlobalIsNeeded - the specific global value as needed, and +/// recursively mark anything that it uses as also needed. +void GlobalDCE::GlobalIsNeeded(GlobalValue *G) { + std::set::iterator I = AliveGlobals.lower_bound(G); + + // If the global is already in the set, no need to reprocess it. + if (I != AliveGlobals.end() && *I == G) return; + + // Otherwise insert it now, so we do not infinitely recurse + AliveGlobals.insert(I, G); + + 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 { + // 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 all basic blocks... + for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) + // For all instructions... + for (BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; ++I) + // For all operands... + for (User::op_iterator U = I->op_begin(), E = I->op_end(); U != E; ++U) + if (GlobalValue *GV = dyn_cast(*U)) + GlobalIsNeeded(GV); + else if (Constant *C = dyn_cast(*U)) + MarkUsedGlobalsAsNeeded(C); + } +} + +void GlobalDCE::MarkUsedGlobalsAsNeeded(Constant *C) { + if (ConstantPointerRef *CPR = dyn_cast(C)) + GlobalIsNeeded(CPR->getValue()); + else { + // Loop over all of the operands of the constant, adding any globals they + // use to the list of needed globals. + for (User::op_iterator I = C->op_begin(), E = C->op_end(); I != E; ++I) + MarkUsedGlobalsAsNeeded(cast(*I)); + } +} // RemoveUnusedConstantPointerRef - Loop over all of the uses of the specified // GlobalValue, looking for the constant pointer ref that may be pointing to it.