1 //===-- GlobalDCE.cpp - DCE unreachable internal functions ----------------===// 2 // 3 // This transform is designed to eliminate unreachable internal globals 4 // FIXME: GlobalDCE should update the callgraph, not destroy it! 5 // 6 //===----------------------------------------------------------------------===// 7 8 #include "llvm/Transforms/IPO/GlobalDCE.h" 9 #include "llvm/Module.h" 10 #include "llvm/Function.h" 11 #include "llvm/GlobalVariable.h" 12 #include "llvm/Analysis/CallGraph.h" 13 #include "Support/DepthFirstIterator.h" 14 #include "Support/StatisticReporter.h" 15 16 static Statistic<> NumRemoved("globaldce\t- Number of global values removed"); 17 18 static bool RemoveUnreachableFunctions(Module *M, CallGraph &CallGraph) { 19 // Calculate which functions are reachable from the external functions in the 20 // call graph. 21 // 22 std::set<CallGraphNode*> ReachableNodes(df_begin(&CallGraph), 23 df_end(&CallGraph)); 24 25 // Loop over the functions in the module twice. The first time is used to 26 // drop references that functions have to each other before they are deleted. 27 // The second pass removes the functions that need to be removed. 28 // 29 std::vector<CallGraphNode*> FunctionsToDelete; // Track unused functions 30 for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I) { 31 CallGraphNode *N = CallGraph[*I]; 32 if (!ReachableNodes.count(N)) { // Not reachable?? 33 (*I)->dropAllReferences(); 34 N->removeAllCalledMethods(); 35 FunctionsToDelete.push_back(N); 36 ++NumRemoved; 37 } 38 } 39 40 // Nothing to do if no unreachable functions have been found... 41 if (FunctionsToDelete.empty()) return false; 42 43 // Unreachables functions have been found and should have no references to 44 // them, delete them now. 45 // 46 for (std::vector<CallGraphNode*>::iterator I = FunctionsToDelete.begin(), 47 E = FunctionsToDelete.end(); I != E; ++I) 48 delete CallGraph.removeMethodFromModule(*I); 49 50 return true; 51 } 52 53 static bool RemoveUnreachableGlobalVariables(Module *M) { 54 bool Changed = false; 55 // Eliminate all global variables that are unused, and that are internal, or 56 // do not have an initializer. 57 // 58 for (Module::giterator I = M->gbegin(); I != M->gend(); ) 59 if (!(*I)->use_empty() || 60 ((*I)->hasExternalLinkage() && (*I)->hasInitializer())) 61 ++I; // Cannot eliminate global variable 62 else { 63 delete M->getGlobalList().remove(I); 64 ++NumRemoved; 65 Changed = true; 66 } 67 return Changed; 68 } 69 70 namespace { 71 struct GlobalDCE : public Pass { 72 const char *getPassName() const { return "Dead Global Elimination"; } 73 74 // run - Do the GlobalDCE pass on the specified module, optionally updating 75 // the specified callgraph to reflect the changes. 76 // 77 bool run(Module *M) { 78 return RemoveUnreachableFunctions(M, getAnalysis<CallGraph>()) | 79 RemoveUnreachableGlobalVariables(M); 80 } 81 82 // getAnalysisUsage - This function works on the call graph of a module. 83 // It is capable of updating the call graph to reflect the new state of the 84 // module. 85 // 86 virtual void getAnalysisUsage(AnalysisUsage &AU) const { 87 AU.addRequired(CallGraph::ID); 88 } 89 }; 90 } 91 92 Pass *createGlobalDCEPass() { return new GlobalDCE(); } 93