X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FTransforms%2FIPO%2FGlobalDCE.cpp;h=0c844fe706503efa8bd3f44d1f7018c78d866c70;hb=2f69477cfd7ee5277dbfb4123c3e7ae2b5f64c21;hp=79434cac9674a0e7c36360acf0bd0154b90637f8;hpb=6726b6d75a8b679068a58cb954ba97cf9d1690ba;p=oota-llvm.git diff --git a/lib/Transforms/IPO/GlobalDCE.cpp b/lib/Transforms/IPO/GlobalDCE.cpp index 79434cac967..0c844fe7065 100644 --- a/lib/Transforms/IPO/GlobalDCE.cpp +++ b/lib/Transforms/IPO/GlobalDCE.cpp @@ -15,16 +15,19 @@ // //===----------------------------------------------------------------------===// -#define DEBUG_TYPE "globaldce" #include "llvm/Transforms/IPO.h" -#include "llvm/Constants.h" -#include "llvm/Module.h" -#include "llvm/Pass.h" +#include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/Statistic.h" -#include "llvm/Support/Compiler.h" -#include +#include "llvm/IR/Constants.h" +#include "llvm/IR/Instructions.h" +#include "llvm/IR/Module.h" +#include "llvm/Transforms/Utils/CtorUtils.h" +#include "llvm/Transforms/Utils/GlobalStatus.h" +#include "llvm/Pass.h" using namespace llvm; +#define DEBUG_TYPE "globaldce" + STATISTIC(NumAliases , "Number of global aliases removed"); STATISTIC(NumFunctions, "Number of functions removed"); STATISTIC(NumVariables, "Number of global variables removed"); @@ -32,15 +35,18 @@ STATISTIC(NumVariables, "Number of global variables removed"); namespace { struct GlobalDCE : public ModulePass { static char ID; // Pass identification, replacement for typeid - GlobalDCE() : ModulePass(&ID) {} + GlobalDCE() : ModulePass(ID) { + initializeGlobalDCEPass(*PassRegistry::getPassRegistry()); + } // run - Do the GlobalDCE pass on the specified module, optionally updating // the specified callgraph to reflect the changes. // - bool runOnModule(Module &M); + bool runOnModule(Module &M) override; private: - std::set AliveGlobals; + SmallPtrSet AliveGlobals; + SmallPtrSet SeenConstants; /// GlobalIsNeeded - mark the specific global value as needed, and /// recursively mark anything that it uses as also needed. @@ -51,21 +57,35 @@ namespace { }; } +/// Returns true if F contains only a single "ret" instruction. +static bool isEmptyFunction(Function *F) { + BasicBlock &Entry = F->getEntryBlock(); + if (Entry.size() != 1 || !isa(Entry.front())) + return false; + ReturnInst &RI = cast(Entry.front()); + return RI.getReturnValue() == nullptr; +} + char GlobalDCE::ID = 0; -static RegisterPass X("globaldce", "Dead Global Elimination"); +INITIALIZE_PASS(GlobalDCE, "globaldce", + "Dead Global Elimination", false, false) ModulePass *llvm::createGlobalDCEPass() { return new GlobalDCE(); } bool GlobalDCE::runOnModule(Module &M) { bool Changed = false; - + + // Remove empty functions from the global ctors list. + Changed |= optimizeGlobalCtorsList(M, isEmptyFunction); + // 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); + if (!I->isDeclaration() && !I->hasAvailableExternallyLinkage()) { + if (!I->isDiscardableIfUnused()) + GlobalIsNeeded(I); + } } for (Module::global_iterator I = M.global_begin(), E = M.global_end(); @@ -73,17 +93,19 @@ bool GlobalDCE::runOnModule(Module &M) { 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); + if (!I->isDeclaration() && !I->hasAvailableExternallyLinkage()) { + if (!I->isDiscardableIfUnused()) + GlobalIsNeeded(I); + } } 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()) + if (!I->isDiscardableIfUnused()) { GlobalIsNeeded(I); + } } // Now that all globals which are needed are in the AliveGlobals set, we loop @@ -92,10 +114,16 @@ bool GlobalDCE::runOnModule(Module &M) { // 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) + 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); + if (I->hasInitializer()) { + Constant *Init = I->getInitializer(); + I->setInitializer(nullptr); + if (isSafeToDestroyConstant(Init)) + Init->destroyConstant(); + } } // The second pass drops the bodies of functions which are dead... @@ -113,7 +141,7 @@ bool GlobalDCE::runOnModule(Module &M) { ++I) if (!AliveGlobals.count(I)) { DeadAliases.push_back(I); - I->setAliasee(0); + I->setAliasee(nullptr); } if (!DeadFunctions.empty()) { @@ -148,6 +176,7 @@ bool GlobalDCE::runOnModule(Module &M) { // Make sure that all memory is released AliveGlobals.clear(); + SeenConstants.clear(); return Changed; } @@ -155,13 +184,22 @@ bool GlobalDCE::runOnModule(Module &M) { /// 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; + if (!AliveGlobals.insert(G).second) + return; - // Otherwise insert it now, so we do not infinitely recurse - AliveGlobals.insert(I, G); + Module *M = G->getParent(); + if (Comdat *C = G->getComdat()) { + for (Function &F : *M) + if (F.getComdat() == C) + GlobalIsNeeded(&F); + for (GlobalVariable &GV : M->globals()) + if (GV.getComdat() == C) + GlobalIsNeeded(&GV); + for (GlobalAlias &GA : M->aliases()) + if (GA.getComdat() == C) + GlobalIsNeeded(&GA); + } if (GlobalVariable *GV = dyn_cast(G)) { // If this is a global variable, we must make sure to add any global values @@ -177,11 +215,15 @@ void GlobalDCE::GlobalIsNeeded(GlobalValue *G) { // 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... + + if (F->hasPrefixData()) + MarkUsedGlobalsAsNeeded(F->getPrefixData()); + + if (F->hasPrologueData()) + MarkUsedGlobalsAsNeeded(F->getPrologueData()); + 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); @@ -192,12 +234,15 @@ void GlobalDCE::GlobalIsNeeded(GlobalValue *G) { 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)); + return GlobalIsNeeded(GV); + + // 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) { + // If we've already processed this constant there's no need to do it again. + Constant *Op = dyn_cast(*I); + if (Op && SeenConstants.insert(Op).second) + MarkUsedGlobalsAsNeeded(Op); } }