//===- 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" #include "llvm/Module.h" #include "llvm/Method.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, std::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!"); Constant *Init = GV->getInitializer(); // Check to see if the initializer is already known... std::map::iterator I = CMap.find(Init); if (I == CMap.end()) { // Nope, add it to the map CMap.insert(std::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) { std::map Constants; unsigned LastConstantSeen = 0; return ::mergeDuplicateConstants(M, LastConstantSeen, Constants); } // doInitialization - For this pass, process all of the globals in the // module, eliminating duplicate constants. // bool ConstantMerge::doInitialization(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::runOnMethod(Method *M) { return ::mergeDuplicateConstants(M->getParent(), LastConstantSeen, Constants); }