X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FTransforms%2FIPO%2FGlobalDCE.cpp;h=09f9e7c4f68a6e55ea516bf7ca0be5a1c85cd782;hb=7eb28f3786543f63cb9a4099655e6d456fca71f7;hp=c7fddc99139139af669e6d3260e8260e09e5eaea;hpb=b12b75365a11e0a626b9826bff4e68272d808f19;p=oota-llvm.git diff --git a/lib/Transforms/IPO/GlobalDCE.cpp b/lib/Transforms/IPO/GlobalDCE.cpp index c7fddc99139..09f9e7c4f68 100644 --- a/lib/Transforms/IPO/GlobalDCE.cpp +++ b/lib/Transforms/IPO/GlobalDCE.cpp @@ -1,256 +1,216 @@ //===-- GlobalDCE.cpp - DCE unreachable internal functions ----------------===// // -// This transform is designed to eliminate unreachable internal globals -// FIXME: GlobalDCE should update the callgraph, not destroy it! +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// 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. // //===----------------------------------------------------------------------===// +#define DEBUG_TYPE "globaldce" #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 "Support/Statistic.h" -#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"); +#include "llvm/Module.h" +#include "llvm/Pass.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/Support/Compiler.h" +#include +using namespace llvm; - 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)); +STATISTIC(NumAliases , "Number of global aliases removed"); +STATISTIC(NumFunctions, "Number of functions removed"); +STATISTIC(NumVariables, "Number of global variables removed"); - // 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); +namespace { + struct VISIBILITY_HIDDEN GlobalDCE : public ModulePass { + static char ID; // Pass identification, replacement for typeid + GlobalDCE() : ModulePass(&ID) {} - // 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()) - 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 runOnModule(Module &M); private: - std::vector WorkList; + std::set AliveGlobals; - inline bool RemoveIfDead(GlobalValue *GV); - void DestroyInitializer(Constant *C); + /// 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 RemoveUnreachableGlobalVariables(Module &M); - bool RemoveUnusedConstantPointerRef(GlobalValue &GV); - bool SafeToDestroyConstant(Constant *C); + bool RemoveUnusedGlobalValue(GlobalValue &GV); }; - RegisterOpt X("globaldce", "Dead Global Elimination"); } -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); +char GlobalDCE::ID = 0; +static RegisterPass X("globaldce", "Dead Global Elimination"); - // 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 = std::find(WorkList.erase(I), WorkList.end(), GV); +ModulePass *llvm::createGlobalDCEPass() { return new GlobalDCE(); } - return true; - } - } else { - Function *F = cast(GV); - // FIXME: TODO +bool GlobalDCE::runOnModule(Module &M) { + bool Changed = false; + + // Loop over the module, adding globals which are obviously necessary. + for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) { + Changed |= RemoveUnusedGlobalValue(*I); + // Functions with external linkage are needed if they have a body + if (!I->hasLocalLinkage() && !I->hasLinkOnceLinkage() && + !I->isDeclaration() && !I->hasAvailableExternallyLinkage()) + GlobalIsNeeded(I); + } + for (Module::global_iterator I = M.global_begin(), E = M.global_end(); + I != E; ++I) { + Changed |= RemoveUnusedGlobalValue(*I); + // Externally visible & appending globals are needed, if they have an + // initializer. + if (!I->hasLocalLinkage() && !I->hasLinkOnceLinkage() && + !I->isDeclaration() && !I->hasAvailableExternallyLinkage()) + GlobalIsNeeded(I); } - 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; + for (Module::alias_iterator I = M.alias_begin(), E = M.alias_end(); + I != E; ++I) { + Changed |= RemoveUnusedGlobalValue(*I); + // Externally visible aliases are needed. + if (!I->hasLocalLinkage() && !I->hasLinkOnceLinkage()) + GlobalIsNeeded(I); + } - // If this is a CPR, the global value referred to may be dead now! Add it 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. // - 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()); + // The first pass is to drop initializers of global variables which are dead. + std::vector DeadGlobalVars; // Keep track of dead globals + for (Module::global_iterator I = M.global_begin(), E = M.global_end(); I != E; ++I) + if (!AliveGlobals.count(I)) { + DeadGlobalVars.push_back(I); // Keep track of dead globals + I->setInitializer(0); + } - // Destroy the actual constant... - C->destroyConstant(); - ++NumConsts; + // 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->isDeclaration()) + I->deleteBody(); + } - 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()); + // The third pass drops targets of aliases which are dead... + std::vector DeadAliases; + for (Module::alias_iterator I = M.alias_begin(), E = M.alias_end(); I != E; + ++I) + if (!AliveGlobals.count(I)) { + DeadAliases.push_back(I); + I->setAliasee(0); + } - // Loop over the subconstants, destroying them as well. - for (unsigned i = 0, e = SubConstants.size(); i != e; ++i) - DestroyInitializer(cast(SubConstants[i])); + if (!DeadFunctions.empty()) { + // Now that all interferences have been dropped, delete the actual objects + // themselves. + for (unsigned i = 0, e = DeadFunctions.size(); i != e; ++i) { + RemoveUnusedGlobalValue(*DeadFunctions[i]); + M.getFunctionList().erase(DeadFunctions[i]); } + NumFunctions += DeadFunctions.size(); + Changed = true; } -} - -bool GlobalDCE::RemoveUnreachableGlobalVariables(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... - // - for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) { - Changed |= RemoveUnusedConstantPointerRef(*I); - WorkList.push_back(I); - } - for (Module::giterator I = M.gbegin(), E = M.gend(); I != E; ++I) { - Changed |= RemoveUnusedConstantPointerRef(*I); - WorkList.push_back(I); + if (!DeadGlobalVars.empty()) { + for (unsigned i = 0, e = DeadGlobalVars.size(); i != e; ++i) { + RemoveUnusedGlobalValue(*DeadGlobalVars[i]); + M.getGlobalList().erase(DeadGlobalVars[i]); + } + NumVariables += DeadGlobalVars.size(); + Changed = true; } - // 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. - // - while (!WorkList.empty()) { - GlobalValue *GV = WorkList.back(); - WorkList.pop_back(); - - Changed |= RemoveIfDead(GV); + // Now delete any dead aliases. + if (!DeadAliases.empty()) { + for (unsigned i = 0, e = DeadAliases.size(); i != e; ++i) { + RemoveUnusedGlobalValue(*DeadAliases[i]); + M.getAliasList().erase(DeadAliases[i]); + } + NumAliases += DeadAliases.size(); + Changed = true; } - // Make sure that all memory is free'd from the worklist... - std::vector().swap(WorkList); + // Make sure that all memory is released + AliveGlobals.clear(); + + // Remove dead metadata. + Changed |= M.getContext().RemoveDeadMetadata(); return Changed; } +/// GlobalIsNeeded - 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.find(G); + + // If the global is already in the set, no need to reprocess it. + if (I != AliveGlobals.end()) 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 if (GlobalAlias *GA = dyn_cast(G)) { + // The target of a global alias is needed. + MarkUsedGlobalsAsNeeded(GA->getAliasee()); + } 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 (GlobalValue *GV = dyn_cast(C)) + GlobalIsNeeded(GV); + 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 +// 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::RemoveUnusedConstantPointerRef(GlobalValue &GV) { - for (Value::use_iterator I = GV.use_begin(), E = GV.use_end(); I != E; ++I) - if (ConstantPointerRef *CPR = dyn_cast(*I)) - if (SafeToDestroyConstant(CPR)) { // Only if unreferenced... - CPR->destroyConstant(); - ++NumCPRs; - return true; - } - - return false; -} - -// SafeToDestroyConstant - It is safe to destroy a constant iff it is only used -// by constants itself. Note that constants cannot be cyclic, so this test is -// pretty easy to implement recursively. -// -bool GlobalDCE::SafeToDestroyConstant(Constant *C) { - for (Value::use_iterator I = C->use_begin(), E = C->use_end(); I != E; ++I) - if (Constant *User = dyn_cast(*I)) { - if (!SafeToDestroyConstant(User)) return false; - } else { - return false; - } - - return true; +bool GlobalDCE::RemoveUnusedGlobalValue(GlobalValue &GV) { + if (GV.use_empty()) return false; + GV.removeDeadConstantUsers(); + return GV.use_empty(); }