Implement DCE of global values
authorChris Lattner <sabre@nondot.org>
Mon, 26 Nov 2001 18:42:17 +0000 (18:42 +0000)
committerChris Lattner <sabre@nondot.org>
Mon, 26 Nov 2001 18:42:17 +0000 (18:42 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@1360 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/Transforms/IPO/GlobalDCE.h [new file with mode: 0644]
lib/Transforms/IPO/GlobalDCE.cpp [new file with mode: 0644]
lib/Transforms/IPO/Makefile [new file with mode: 0644]

diff --git a/include/llvm/Transforms/IPO/GlobalDCE.h b/include/llvm/Transforms/IPO/GlobalDCE.h
new file mode 100644 (file)
index 0000000..5491751
--- /dev/null
@@ -0,0 +1,21 @@
+//===-- Transforms/IPO/GlobalDCE.h - DCE global values -----------*- C++ -*--=//
+//
+// This transform is designed to eliminate unreachable internal globals
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TRANSFORM_IPO_GLOBALDCE_H
+#define LLVM_TRANSFORM_IPO_GLOBALDCE_H
+
+namespace cfg { class CallGraph; }
+class Module;
+
+struct GlobalDCE { 
+
+  // run - Do the GlobalDCE pass on the specified module, optionally updating
+  // the specified callgraph to reflect the changes.
+  //
+  bool run(Module *M, cfg::CallGraph *CG = 0);
+};
+
+#endif
diff --git a/lib/Transforms/IPO/GlobalDCE.cpp b/lib/Transforms/IPO/GlobalDCE.cpp
new file mode 100644 (file)
index 0000000..24945c0
--- /dev/null
@@ -0,0 +1,59 @@
+//===-- GlobalDCE.cpp - DCE unreachable internal methods ---------*- C++ -*--=//
+//
+// This transform is designed to eliminate unreachable internal globals
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Transforms/IPO/GlobalDCE.h"
+#include "llvm/Analysis/CallGraph.h"
+#include "llvm/Support/DepthFirstIterator.h"
+#include "llvm/Module.h"
+#include "llvm/Method.h"
+#include <set>
+
+static bool RemoveUnreachableMethods(Module *M, cfg::CallGraph *CG) {
+  // Create a call graph if one is not already available...
+  cfg::CallGraph &CallGraph = CG ? *CG : *new cfg::CallGraph(M);
+  
+  // Calculate which methods are reachable from the external methods in the call
+  // graph.
+  //
+  set<cfg::CallGraphNode*> ReachableNodes(df_begin(&CallGraph),
+                                         df_end(&CallGraph));
+
+  // Loop over the methods in the module twice.  The first time is used to drop
+  // references that methods have to each other before they are deleted.  The
+  // second pass removes the methods that need to be removed.
+  //
+  vector<cfg::CallGraphNode*> MethodsToDelete;   // Track unused methods
+  for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I) {
+    cfg::CallGraphNode *N = CallGraph[*I];
+    if (!ReachableNodes.count(N)) {              // Not reachable??
+      (*I)->dropAllReferences();
+      N->removeAllCalledMethods();
+      MethodsToDelete.push_back(N);
+    }
+  }
+
+  // Nothing to do if no unreachable methods have been found...
+  if (MethodsToDelete.empty()) {
+    // Free the created call graph if it was not passed in
+    if (&CallGraph != CG) delete &CallGraph;
+    return false;
+  }
+
+  // Unreachables methods have been found and should have no references to them,
+  // delete them now.
+  //
+  for (vector<cfg::CallGraphNode*>::iterator I = MethodsToDelete.begin(),
+        E = MethodsToDelete.end(); I != E; ++I)
+    delete CallGraph.removeMethodFromModule(*I);
+
+  // Free the created call graph if it was not passed in
+  if (&CallGraph != CG) delete &CallGraph;
+  return true;
+}
+
+bool GlobalDCE::run(Module *M, cfg::CallGraph *CG = 0) {
+  return RemoveUnreachableMethods(M, CG);
+}
diff --git a/lib/Transforms/IPO/Makefile b/lib/Transforms/IPO/Makefile
new file mode 100644 (file)
index 0000000..778d2eb
--- /dev/null
@@ -0,0 +1,6 @@
+LEVEL = ../../..
+
+LIBRARYNAME = ipo
+
+include $(LEVEL)/Makefile.common
+