Chris Lattner | 30474bb | 2001-11-26 18:42:17 +0000 | [diff] [blame] | 1 | //===-- GlobalDCE.cpp - DCE unreachable internal methods ---------*- C++ -*--=// |
| 2 | // |
| 3 | // This transform is designed to eliminate unreachable internal globals |
| 4 | // |
| 5 | //===----------------------------------------------------------------------===// |
| 6 | |
| 7 | #include "llvm/Transforms/IPO/GlobalDCE.h" |
| 8 | #include "llvm/Analysis/CallGraph.h" |
| 9 | #include "llvm/Support/DepthFirstIterator.h" |
| 10 | #include "llvm/Module.h" |
| 11 | #include "llvm/Method.h" |
| 12 | #include <set> |
| 13 | |
| 14 | static bool RemoveUnreachableMethods(Module *M, cfg::CallGraph *CG) { |
| 15 | // Create a call graph if one is not already available... |
| 16 | cfg::CallGraph &CallGraph = CG ? *CG : *new cfg::CallGraph(M); |
| 17 | |
| 18 | // Calculate which methods are reachable from the external methods in the call |
| 19 | // graph. |
| 20 | // |
| 21 | set<cfg::CallGraphNode*> ReachableNodes(df_begin(&CallGraph), |
| 22 | df_end(&CallGraph)); |
| 23 | |
| 24 | // Loop over the methods in the module twice. The first time is used to drop |
| 25 | // references that methods have to each other before they are deleted. The |
| 26 | // second pass removes the methods that need to be removed. |
| 27 | // |
| 28 | vector<cfg::CallGraphNode*> MethodsToDelete; // Track unused methods |
| 29 | for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I) { |
| 30 | cfg::CallGraphNode *N = CallGraph[*I]; |
| 31 | if (!ReachableNodes.count(N)) { // Not reachable?? |
| 32 | (*I)->dropAllReferences(); |
| 33 | N->removeAllCalledMethods(); |
| 34 | MethodsToDelete.push_back(N); |
| 35 | } |
| 36 | } |
| 37 | |
| 38 | // Nothing to do if no unreachable methods have been found... |
| 39 | if (MethodsToDelete.empty()) { |
| 40 | // Free the created call graph if it was not passed in |
| 41 | if (&CallGraph != CG) delete &CallGraph; |
| 42 | return false; |
| 43 | } |
| 44 | |
| 45 | // Unreachables methods have been found and should have no references to them, |
| 46 | // delete them now. |
| 47 | // |
| 48 | for (vector<cfg::CallGraphNode*>::iterator I = MethodsToDelete.begin(), |
| 49 | E = MethodsToDelete.end(); I != E; ++I) |
| 50 | delete CallGraph.removeMethodFromModule(*I); |
| 51 | |
| 52 | // Free the created call graph if it was not passed in |
| 53 | if (&CallGraph != CG) delete &CallGraph; |
| 54 | return true; |
| 55 | } |
| 56 | |
| 57 | bool GlobalDCE::run(Module *M, cfg::CallGraph *CG = 0) { |
| 58 | return RemoveUnreachableMethods(M, CG); |
| 59 | } |