diff --git a/lib/Transforms/IPO/ConstantMerge.cpp b/lib/Transforms/IPO/ConstantMerge.cpp new file mode 100644 index 000000000000..3564a814c8f5 --- /dev/null +++ b/lib/Transforms/IPO/ConstantMerge.cpp @@ -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 &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::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 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); +}