Chris Lattner | 4816d63 | 2001-10-18 20:05:37 +0000 | [diff] [blame] | 1 | //===- ConstantMerge.cpp - Merge duplicate global constants -----------------=// |
| 2 | // |
| 3 | // This file defines the interface to a pass that merges duplicate global |
| 4 | // constants together into a single constant that is shared. This is useful |
| 5 | // because some passes (ie TraceValues) insert a lot of string constants into |
| 6 | // the program, regardless of whether or not they duplicate an existing string. |
| 7 | // |
| 8 | // Algorithm: ConstantMerge is designed to build up a map of available constants |
| 9 | // and elminate duplicates when it is initialized. |
| 10 | // |
| 11 | // The DynamicConstantMerge method is a superset of the ConstantMerge algorithm |
| 12 | // that checks for each method to see if constants have been added to the |
| 13 | // constant pool since it was last run... if so, it processes them. |
| 14 | // |
| 15 | //===----------------------------------------------------------------------===// |
| 16 | |
| 17 | #include "llvm/Transforms/ConstantMerge.h" |
| 18 | #include "llvm/GlobalVariable.h" |
Chris Lattner | d5d5678 | 2002-01-31 00:45:11 +0000 | [diff] [blame^] | 19 | #include "llvm/Module.h" |
| 20 | #include "llvm/Method.h" |
Chris Lattner | 4816d63 | 2001-10-18 20:05:37 +0000 | [diff] [blame] | 21 | |
| 22 | // mergeDuplicateConstants - Workhorse for the pass. This eliminates duplicate |
| 23 | // constants, starting at global ConstantNo, and adds vars to the map if they |
| 24 | // are new and unique. |
| 25 | // |
| 26 | static inline |
| 27 | bool mergeDuplicateConstants(Module *M, unsigned &ConstantNo, |
Chris Lattner | 7f74a56 | 2002-01-20 22:54:45 +0000 | [diff] [blame] | 28 | std::map<Constant*, GlobalVariable*> &CMap) { |
Chris Lattner | 4816d63 | 2001-10-18 20:05:37 +0000 | [diff] [blame] | 29 | Module::GlobalListType &GList = M->getGlobalList(); |
| 30 | if (GList.size() <= ConstantNo) return false; // No new constants |
| 31 | bool MadeChanges = false; |
| 32 | |
| 33 | for (; ConstantNo < GList.size(); ++ConstantNo) { |
| 34 | GlobalVariable *GV = GList[ConstantNo]; |
| 35 | if (GV->isConstant()) { // Only process constants |
| 36 | assert(GV->hasInitializer() && "Globals constants must have inits!"); |
Chris Lattner | 3462ae3 | 2001-12-03 22:26:30 +0000 | [diff] [blame] | 37 | Constant *Init = GV->getInitializer(); |
Chris Lattner | 4816d63 | 2001-10-18 20:05:37 +0000 | [diff] [blame] | 38 | |
| 39 | // Check to see if the initializer is already known... |
Chris Lattner | 7f74a56 | 2002-01-20 22:54:45 +0000 | [diff] [blame] | 40 | std::map<Constant*, GlobalVariable*>::iterator I = CMap.find(Init); |
Chris Lattner | 4816d63 | 2001-10-18 20:05:37 +0000 | [diff] [blame] | 41 | |
| 42 | if (I == CMap.end()) { // Nope, add it to the map |
Chris Lattner | 7f74a56 | 2002-01-20 22:54:45 +0000 | [diff] [blame] | 43 | CMap.insert(std::make_pair(Init, GV)); |
Chris Lattner | 4816d63 | 2001-10-18 20:05:37 +0000 | [diff] [blame] | 44 | } else { // Yup, this is a duplicate! |
| 45 | // Make all uses of the duplicate constant use the cannonical version... |
| 46 | GV->replaceAllUsesWith(I->second); |
| 47 | |
| 48 | // Remove and delete the global value from the module... |
| 49 | delete GList.remove(GList.begin()+ConstantNo); |
| 50 | |
| 51 | --ConstantNo; // Don't skip the next constant. |
| 52 | MadeChanges = true; |
| 53 | } |
| 54 | } |
| 55 | } |
| 56 | return MadeChanges; |
| 57 | } |
| 58 | |
| 59 | |
| 60 | // mergeDuplicateConstants - Static accessor for clients that don't want to |
| 61 | // deal with passes. |
| 62 | // |
| 63 | bool ConstantMerge::mergeDuplicateConstants(Module *M) { |
Chris Lattner | 7f74a56 | 2002-01-20 22:54:45 +0000 | [diff] [blame] | 64 | std::map<Constant*, GlobalVariable*> Constants; |
Chris Lattner | 4816d63 | 2001-10-18 20:05:37 +0000 | [diff] [blame] | 65 | unsigned LastConstantSeen = 0; |
| 66 | return ::mergeDuplicateConstants(M, LastConstantSeen, Constants); |
| 67 | } |
| 68 | |
| 69 | |
Chris Lattner | 0686e43 | 2002-01-21 07:31:50 +0000 | [diff] [blame] | 70 | // doInitialization - For this pass, process all of the globals in the |
Chris Lattner | 4816d63 | 2001-10-18 20:05:37 +0000 | [diff] [blame] | 71 | // module, eliminating duplicate constants. |
| 72 | // |
Chris Lattner | 0686e43 | 2002-01-21 07:31:50 +0000 | [diff] [blame] | 73 | bool ConstantMerge::doInitialization(Module *M) { |
Chris Lattner | 4816d63 | 2001-10-18 20:05:37 +0000 | [diff] [blame] | 74 | return ::mergeDuplicateConstants(M, LastConstantSeen, Constants); |
| 75 | } |
| 76 | |
| 77 | // doPerMethodWork - Check to see if any globals have been added to the |
| 78 | // global list for the module. If so, eliminate them. |
| 79 | // |
Chris Lattner | 0686e43 | 2002-01-21 07:31:50 +0000 | [diff] [blame] | 80 | bool DynamicConstantMerge::runOnMethod(Method *M) { |
Chris Lattner | 4816d63 | 2001-10-18 20:05:37 +0000 | [diff] [blame] | 81 | return ::mergeDuplicateConstants(M->getParent(), LastConstantSeen, Constants); |
| 82 | } |