Chris Lattner | 475becb | 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 |
Chris Lattner | 2fbfdcf | 2002-04-07 20:49:59 +0000 | [diff] [blame] | 12 | // that checks for each function to see if constants have been added to the |
Chris Lattner | 475becb | 2001-10-18 20:05:37 +0000 | [diff] [blame] | 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 | 793c6b8 | 2002-01-31 00:45:11 +0000 | [diff] [blame] | 19 | #include "llvm/Module.h" |
Chris Lattner | 2fbfdcf | 2002-04-07 20:49:59 +0000 | [diff] [blame] | 20 | #include "llvm/Function.h" |
Chris Lattner | bd0ef77 | 2002-02-26 21:46:54 +0000 | [diff] [blame] | 21 | #include "llvm/Pass.h" |
Chris Lattner | 475becb | 2001-10-18 20:05:37 +0000 | [diff] [blame] | 22 | |
| 23 | // mergeDuplicateConstants - Workhorse for the pass. This eliminates duplicate |
| 24 | // constants, starting at global ConstantNo, and adds vars to the map if they |
| 25 | // are new and unique. |
| 26 | // |
| 27 | static inline |
| 28 | bool mergeDuplicateConstants(Module *M, unsigned &ConstantNo, |
Chris Lattner | 697954c | 2002-01-20 22:54:45 +0000 | [diff] [blame] | 29 | std::map<Constant*, GlobalVariable*> &CMap) { |
Chris Lattner | 475becb | 2001-10-18 20:05:37 +0000 | [diff] [blame] | 30 | Module::GlobalListType &GList = M->getGlobalList(); |
| 31 | if (GList.size() <= ConstantNo) return false; // No new constants |
| 32 | bool MadeChanges = false; |
| 33 | |
| 34 | for (; ConstantNo < GList.size(); ++ConstantNo) { |
| 35 | GlobalVariable *GV = GList[ConstantNo]; |
| 36 | if (GV->isConstant()) { // Only process constants |
| 37 | assert(GV->hasInitializer() && "Globals constants must have inits!"); |
Chris Lattner | e9bb2df | 2001-12-03 22:26:30 +0000 | [diff] [blame] | 38 | Constant *Init = GV->getInitializer(); |
Chris Lattner | 475becb | 2001-10-18 20:05:37 +0000 | [diff] [blame] | 39 | |
| 40 | // Check to see if the initializer is already known... |
Chris Lattner | 697954c | 2002-01-20 22:54:45 +0000 | [diff] [blame] | 41 | std::map<Constant*, GlobalVariable*>::iterator I = CMap.find(Init); |
Chris Lattner | 475becb | 2001-10-18 20:05:37 +0000 | [diff] [blame] | 42 | |
| 43 | if (I == CMap.end()) { // Nope, add it to the map |
Chris Lattner | 697954c | 2002-01-20 22:54:45 +0000 | [diff] [blame] | 44 | CMap.insert(std::make_pair(Init, GV)); |
Chris Lattner | 475becb | 2001-10-18 20:05:37 +0000 | [diff] [blame] | 45 | } else { // Yup, this is a duplicate! |
| 46 | // Make all uses of the duplicate constant use the cannonical version... |
| 47 | GV->replaceAllUsesWith(I->second); |
| 48 | |
| 49 | // Remove and delete the global value from the module... |
| 50 | delete GList.remove(GList.begin()+ConstantNo); |
| 51 | |
| 52 | --ConstantNo; // Don't skip the next constant. |
| 53 | MadeChanges = true; |
| 54 | } |
| 55 | } |
| 56 | } |
| 57 | return MadeChanges; |
| 58 | } |
| 59 | |
Chris Lattner | bd0ef77 | 2002-02-26 21:46:54 +0000 | [diff] [blame] | 60 | namespace { |
Chris Lattner | f57b845 | 2002-04-27 06:56:12 +0000 | [diff] [blame^] | 61 | // FIXME: ConstantMerge should not be a FunctionPass!!! |
| 62 | class ConstantMerge : public FunctionPass { |
Chris Lattner | bd0ef77 | 2002-02-26 21:46:54 +0000 | [diff] [blame] | 63 | protected: |
| 64 | std::map<Constant*, GlobalVariable*> Constants; |
| 65 | unsigned LastConstantSeen; |
| 66 | public: |
| 67 | inline ConstantMerge() : LastConstantSeen(0) {} |
| 68 | |
| 69 | // doInitialization - For this pass, process all of the globals in the |
| 70 | // module, eliminating duplicate constants. |
| 71 | // |
| 72 | bool doInitialization(Module *M) { |
| 73 | return ::mergeDuplicateConstants(M, LastConstantSeen, Constants); |
| 74 | } |
| 75 | |
Chris Lattner | f57b845 | 2002-04-27 06:56:12 +0000 | [diff] [blame^] | 76 | bool runOnFunction(Function *) { return false; } |
Chris Lattner | bd0ef77 | 2002-02-26 21:46:54 +0000 | [diff] [blame] | 77 | |
| 78 | // doFinalization - Clean up internal state for this module |
| 79 | // |
| 80 | bool doFinalization(Module *M) { |
| 81 | LastConstantSeen = 0; |
| 82 | Constants.clear(); |
| 83 | return false; |
| 84 | } |
| 85 | }; |
| 86 | |
| 87 | struct DynamicConstantMerge : public ConstantMerge { |
Chris Lattner | f57b845 | 2002-04-27 06:56:12 +0000 | [diff] [blame^] | 88 | // runOnFunction - Check to see if any globals have been added to the |
Chris Lattner | bd0ef77 | 2002-02-26 21:46:54 +0000 | [diff] [blame] | 89 | // global list for the module. If so, eliminate them. |
| 90 | // |
Chris Lattner | f57b845 | 2002-04-27 06:56:12 +0000 | [diff] [blame^] | 91 | bool runOnFunction(Function *F) { |
Chris Lattner | 2fbfdcf | 2002-04-07 20:49:59 +0000 | [diff] [blame] | 92 | return ::mergeDuplicateConstants(F->getParent(), LastConstantSeen, |
Chris Lattner | bd0ef77 | 2002-02-26 21:46:54 +0000 | [diff] [blame] | 93 | Constants); |
| 94 | } |
| 95 | }; |
Chris Lattner | 475becb | 2001-10-18 20:05:37 +0000 | [diff] [blame] | 96 | } |
| 97 | |
Chris Lattner | bd0ef77 | 2002-02-26 21:46:54 +0000 | [diff] [blame] | 98 | Pass *createConstantMergePass() { return new ConstantMerge(); } |
| 99 | Pass *createDynamicConstantMergePass() { return new DynamicConstantMerge(); } |