| //===- 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); |
| } |