Initial checkin
authorChris Lattner <sabre@nondot.org>
Thu, 18 Oct 2001 20:05:37 +0000 (20:05 +0000)
committerChris Lattner <sabre@nondot.org>
Thu, 18 Oct 2001 20:05:37 +0000 (20:05 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@897 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Transforms/IPO/ConstantMerge.cpp [new file with mode: 0644]

diff --git a/lib/Transforms/IPO/ConstantMerge.cpp b/lib/Transforms/IPO/ConstantMerge.cpp
new file mode 100644 (file)
index 0000000..3564a81
--- /dev/null
@@ -0,0 +1,80 @@
+//===- ConstantMerge.cpp - Merge duplicate global constants -----------------=//
+//
+// This file defines the interface to a pass that merges duplicate global
+// constants together into a single constant that is shared.  This is useful
+// because some passes (ie TraceValues) insert a lot of string constants into
+// the program, regardless of whether or not they duplicate an existing string.
+//
+// Algorithm: ConstantMerge is designed to build up a map of available constants
+// and elminate duplicates when it is initialized.
+//
+// The DynamicConstantMerge method is a superset of the ConstantMerge algorithm
+// that checks for each method to see if constants have been added to the
+// constant pool since it was last run... if so, it processes them.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Transforms/ConstantMerge.h"
+#include "llvm/GlobalVariable.h"
+
+// mergeDuplicateConstants - Workhorse for the pass.  This eliminates duplicate
+// constants, starting at global ConstantNo, and adds vars to the map if they
+// are new and unique.
+//
+static inline 
+bool mergeDuplicateConstants(Module *M, unsigned &ConstantNo,
+                             map<ConstPoolVal*, GlobalVariable*> &CMap) {
+  Module::GlobalListType &GList = M->getGlobalList();
+  if (GList.size() <= ConstantNo) return false;   // No new constants
+  bool MadeChanges = false;
+  
+  for (; ConstantNo < GList.size(); ++ConstantNo) {
+    GlobalVariable *GV = GList[ConstantNo];
+    if (GV->isConstant()) {  // Only process constants
+      assert(GV->hasInitializer() && "Globals constants must have inits!");
+      ConstPoolVal *Init = GV->getInitializer();
+
+      // Check to see if the initializer is already known...
+      map<ConstPoolVal*, GlobalVariable*>::iterator I = CMap.find(Init);
+
+      if (I == CMap.end()) {    // Nope, add it to the map
+        CMap.insert(make_pair(Init, GV));
+      } else {                  // Yup, this is a duplicate!
+        // Make all uses of the duplicate constant use the cannonical version...
+        GV->replaceAllUsesWith(I->second);
+
+        // Remove and delete the global value from the module...
+        delete GList.remove(GList.begin()+ConstantNo);
+
+        --ConstantNo;  // Don't skip the next constant.
+        MadeChanges = true;
+      }
+    }
+  }
+  return MadeChanges;
+}
+
+
+// mergeDuplicateConstants - Static accessor for clients that don't want to
+// deal with passes.
+//
+bool ConstantMerge::mergeDuplicateConstants(Module *M) {
+  map<ConstPoolVal*, GlobalVariable*> Constants;
+  unsigned LastConstantSeen = 0;
+  return ::mergeDuplicateConstants(M, LastConstantSeen, Constants);
+}
+
+
+// doPassInitialization - For this pass, process all of the globals in the
+// module, eliminating duplicate constants.
+//
+bool ConstantMerge::doPassInitialization(Module *M) {
+  return ::mergeDuplicateConstants(M, LastConstantSeen, Constants);
+}
+
+// doPerMethodWork - Check to see if any globals have been added to the 
+// global list for the module.  If so, eliminate them.
+//
+bool DynamicConstantMerge::doPerMethodWork(Method *M) {
+  return ::mergeDuplicateConstants(M->getParent(), LastConstantSeen, Constants);
+}