196e92c1dSJiangning Liu //===-- GlobalMerge.cpp - Internal globals merging -----------------------===// 296e92c1dSJiangning Liu // 396e92c1dSJiangning Liu // The LLVM Compiler Infrastructure 496e92c1dSJiangning Liu // 596e92c1dSJiangning Liu // This file is distributed under the University of Illinois Open Source 696e92c1dSJiangning Liu // License. See LICENSE.TXT for details. 796e92c1dSJiangning Liu // 896e92c1dSJiangning Liu //===----------------------------------------------------------------------===// 996e92c1dSJiangning Liu // This pass merges globals with internal linkage into one. This way all the 1096e92c1dSJiangning Liu // globals which were merged into a biggest one can be addressed using offsets 1196e92c1dSJiangning Liu // from the same base pointer (no need for separate base pointer for each of the 1296e92c1dSJiangning Liu // global). Such a transformation can significantly reduce the register pressure 1396e92c1dSJiangning Liu // when many globals are involved. 1496e92c1dSJiangning Liu // 1596e92c1dSJiangning Liu // For example, consider the code which touches several global variables at 1696e92c1dSJiangning Liu // once: 1796e92c1dSJiangning Liu // 1896e92c1dSJiangning Liu // static int foo[N], bar[N], baz[N]; 1996e92c1dSJiangning Liu // 2096e92c1dSJiangning Liu // for (i = 0; i < N; ++i) { 2196e92c1dSJiangning Liu // foo[i] = bar[i] * baz[i]; 2296e92c1dSJiangning Liu // } 2396e92c1dSJiangning Liu // 2496e92c1dSJiangning Liu // On ARM the addresses of 3 arrays should be kept in the registers, thus 2596e92c1dSJiangning Liu // this code has quite large register pressure (loop body): 2696e92c1dSJiangning Liu // 2796e92c1dSJiangning Liu // ldr r1, [r5], #4 2896e92c1dSJiangning Liu // ldr r2, [r6], #4 2996e92c1dSJiangning Liu // mul r1, r2, r1 3096e92c1dSJiangning Liu // str r1, [r0], #4 3196e92c1dSJiangning Liu // 3296e92c1dSJiangning Liu // Pass converts the code to something like: 3396e92c1dSJiangning Liu // 3496e92c1dSJiangning Liu // static struct { 3596e92c1dSJiangning Liu // int foo[N]; 3696e92c1dSJiangning Liu // int bar[N]; 3796e92c1dSJiangning Liu // int baz[N]; 3896e92c1dSJiangning Liu // } merged; 3996e92c1dSJiangning Liu // 4096e92c1dSJiangning Liu // for (i = 0; i < N; ++i) { 4196e92c1dSJiangning Liu // merged.foo[i] = merged.bar[i] * merged.baz[i]; 4296e92c1dSJiangning Liu // } 4396e92c1dSJiangning Liu // 4496e92c1dSJiangning Liu // and in ARM code this becomes: 4596e92c1dSJiangning Liu // 4696e92c1dSJiangning Liu // ldr r0, [r5, #40] 4796e92c1dSJiangning Liu // ldr r1, [r5, #80] 4896e92c1dSJiangning Liu // mul r0, r1, r0 4996e92c1dSJiangning Liu // str r0, [r5], #4 5096e92c1dSJiangning Liu // 5196e92c1dSJiangning Liu // note that we saved 2 registers here almostly "for free". 5296e92c1dSJiangning Liu // ===---------------------------------------------------------------------===// 5396e92c1dSJiangning Liu 5496e92c1dSJiangning Liu #include "llvm/Transforms/Scalar.h" 5596e92c1dSJiangning Liu #include "llvm/ADT/SmallPtrSet.h" 5696e92c1dSJiangning Liu #include "llvm/ADT/Statistic.h" 5796e92c1dSJiangning Liu #include "llvm/IR/Attributes.h" 5896e92c1dSJiangning Liu #include "llvm/IR/Constants.h" 5996e92c1dSJiangning Liu #include "llvm/IR/DataLayout.h" 6096e92c1dSJiangning Liu #include "llvm/IR/DerivedTypes.h" 6196e92c1dSJiangning Liu #include "llvm/IR/Function.h" 6296e92c1dSJiangning Liu #include "llvm/IR/GlobalVariable.h" 6396e92c1dSJiangning Liu #include "llvm/IR/Instructions.h" 6496e92c1dSJiangning Liu #include "llvm/IR/Intrinsics.h" 6596e92c1dSJiangning Liu #include "llvm/IR/Module.h" 6696e92c1dSJiangning Liu #include "llvm/Pass.h" 6796e92c1dSJiangning Liu #include "llvm/CodeGen/Passes.h" 6896e92c1dSJiangning Liu #include "llvm/Support/CommandLine.h" 6996e92c1dSJiangning Liu #include "llvm/Target/TargetLowering.h" 7096e92c1dSJiangning Liu #include "llvm/Target/TargetLoweringObjectFile.h" 7196e92c1dSJiangning Liu using namespace llvm; 7296e92c1dSJiangning Liu 7396e92c1dSJiangning Liu #define DEBUG_TYPE "global-merge" 7496e92c1dSJiangning Liu 7596e92c1dSJiangning Liu static cl::opt<bool> 7696e92c1dSJiangning Liu EnableGlobalMerge("enable-global-merge", cl::Hidden, 7796e92c1dSJiangning Liu cl::desc("Enable global merge pass"), 7896e92c1dSJiangning Liu cl::init(true)); 7996e92c1dSJiangning Liu 8096e92c1dSJiangning Liu static cl::opt<bool> 8196e92c1dSJiangning Liu EnableGlobalMergeOnConst("global-merge-on-const", cl::Hidden, 8296e92c1dSJiangning Liu cl::desc("Enable global merge pass on constants"), 8396e92c1dSJiangning Liu cl::init(false)); 8496e92c1dSJiangning Liu 8596e92c1dSJiangning Liu // FIXME: this could be a transitional option, and we probably need to remove 8696e92c1dSJiangning Liu // it if only we are sure this optimization could always benefit all targets. 8796e92c1dSJiangning Liu static cl::opt<bool> 8896e92c1dSJiangning Liu EnableGlobalMergeOnExternal("global-merge-on-external", cl::Hidden, 8996e92c1dSJiangning Liu cl::desc("Enable global merge pass on external linkage"), 9096e92c1dSJiangning Liu cl::init(false)); 9196e92c1dSJiangning Liu 9296e92c1dSJiangning Liu STATISTIC(NumMerged , "Number of globals merged"); 9396e92c1dSJiangning Liu namespace { 9496e92c1dSJiangning Liu class GlobalMerge : public FunctionPass { 9596e92c1dSJiangning Liu const TargetMachine *TM; 9696e92c1dSJiangning Liu 9796e92c1dSJiangning Liu bool doMerge(SmallVectorImpl<GlobalVariable*> &Globals, 9896e92c1dSJiangning Liu Module &M, bool isConst, unsigned AddrSpace) const; 9996e92c1dSJiangning Liu 10096e92c1dSJiangning Liu /// \brief Check if the given variable has been identified as must keep 10196e92c1dSJiangning Liu /// \pre setMustKeepGlobalVariables must have been called on the Module that 10296e92c1dSJiangning Liu /// contains GV 10396e92c1dSJiangning Liu bool isMustKeepGlobalVariable(const GlobalVariable *GV) const { 10496e92c1dSJiangning Liu return MustKeepGlobalVariables.count(GV); 10596e92c1dSJiangning Liu } 10696e92c1dSJiangning Liu 10796e92c1dSJiangning Liu /// Collect every variables marked as "used" or used in a landing pad 10896e92c1dSJiangning Liu /// instruction for this Module. 10996e92c1dSJiangning Liu void setMustKeepGlobalVariables(Module &M); 11096e92c1dSJiangning Liu 11196e92c1dSJiangning Liu /// Collect every variables marked as "used" 11296e92c1dSJiangning Liu void collectUsedGlobalVariables(Module &M); 11396e92c1dSJiangning Liu 11496e92c1dSJiangning Liu /// Keep track of the GlobalVariable that must not be merged away 11596e92c1dSJiangning Liu SmallPtrSet<const GlobalVariable *, 16> MustKeepGlobalVariables; 11696e92c1dSJiangning Liu 11796e92c1dSJiangning Liu public: 11896e92c1dSJiangning Liu static char ID; // Pass identification, replacement for typeid. 11996e92c1dSJiangning Liu explicit GlobalMerge(const TargetMachine *TM = nullptr) 12096e92c1dSJiangning Liu : FunctionPass(ID), TM(TM) { 12196e92c1dSJiangning Liu initializeGlobalMergePass(*PassRegistry::getPassRegistry()); 12296e92c1dSJiangning Liu } 12396e92c1dSJiangning Liu 12496e92c1dSJiangning Liu bool doInitialization(Module &M) override; 12596e92c1dSJiangning Liu bool runOnFunction(Function &F) override; 12696e92c1dSJiangning Liu bool doFinalization(Module &M) override; 12796e92c1dSJiangning Liu 12896e92c1dSJiangning Liu const char *getPassName() const override { 12996e92c1dSJiangning Liu return "Merge internal globals"; 13096e92c1dSJiangning Liu } 13196e92c1dSJiangning Liu 13296e92c1dSJiangning Liu void getAnalysisUsage(AnalysisUsage &AU) const override { 13396e92c1dSJiangning Liu AU.setPreservesCFG(); 13496e92c1dSJiangning Liu FunctionPass::getAnalysisUsage(AU); 13596e92c1dSJiangning Liu } 13696e92c1dSJiangning Liu }; 13796e92c1dSJiangning Liu } // end anonymous namespace 13896e92c1dSJiangning Liu 13996e92c1dSJiangning Liu char GlobalMerge::ID = 0; 14096e92c1dSJiangning Liu INITIALIZE_TM_PASS(GlobalMerge, "global-merge", "Merge global variables", 14196e92c1dSJiangning Liu false, false) 14296e92c1dSJiangning Liu 14396e92c1dSJiangning Liu bool GlobalMerge::doMerge(SmallVectorImpl<GlobalVariable*> &Globals, 14496e92c1dSJiangning Liu Module &M, bool isConst, unsigned AddrSpace) const { 14596e92c1dSJiangning Liu const TargetLowering *TLI = TM->getTargetLowering(); 14696e92c1dSJiangning Liu const DataLayout *DL = TLI->getDataLayout(); 14796e92c1dSJiangning Liu 14896e92c1dSJiangning Liu // FIXME: Infer the maximum possible offset depending on the actual users 14996e92c1dSJiangning Liu // (these max offsets are different for the users inside Thumb or ARM 15096e92c1dSJiangning Liu // functions) 15196e92c1dSJiangning Liu unsigned MaxOffset = TLI->getMaximalGlobalOffset(); 15296e92c1dSJiangning Liu 15396e92c1dSJiangning Liu // FIXME: Find better heuristics 15496e92c1dSJiangning Liu std::stable_sort(Globals.begin(), Globals.end(), 15596e92c1dSJiangning Liu [DL](const GlobalVariable *GV1, const GlobalVariable *GV2) { 15696e92c1dSJiangning Liu Type *Ty1 = cast<PointerType>(GV1->getType())->getElementType(); 15796e92c1dSJiangning Liu Type *Ty2 = cast<PointerType>(GV2->getType())->getElementType(); 15896e92c1dSJiangning Liu 15996e92c1dSJiangning Liu return (DL->getTypeAllocSize(Ty1) < DL->getTypeAllocSize(Ty2)); 16096e92c1dSJiangning Liu }); 16196e92c1dSJiangning Liu 16296e92c1dSJiangning Liu Type *Int32Ty = Type::getInt32Ty(M.getContext()); 16396e92c1dSJiangning Liu 16496e92c1dSJiangning Liu assert(Globals.size() > 1); 16596e92c1dSJiangning Liu 16696e92c1dSJiangning Liu // FIXME: This simple solution merges globals all together as maximum as 16796e92c1dSJiangning Liu // possible. However, with this solution it would be hard to remove dead 16896e92c1dSJiangning Liu // global symbols at link-time. An alternative solution could be checking 16996e92c1dSJiangning Liu // global symbols references function by function, and make the symbols 17096e92c1dSJiangning Liu // being referred in the same function merged and we would probably need 17196e92c1dSJiangning Liu // to introduce heuristic algorithm to solve the merge conflict from 17296e92c1dSJiangning Liu // different functions. 17396e92c1dSJiangning Liu for (size_t i = 0, e = Globals.size(); i != e; ) { 17496e92c1dSJiangning Liu size_t j = 0; 17596e92c1dSJiangning Liu uint64_t MergedSize = 0; 17696e92c1dSJiangning Liu std::vector<Type*> Tys; 17796e92c1dSJiangning Liu std::vector<Constant*> Inits; 17896e92c1dSJiangning Liu 17996e92c1dSJiangning Liu bool HasExternal = false; 18096e92c1dSJiangning Liu GlobalVariable *TheFirstExternal = 0; 18196e92c1dSJiangning Liu for (j = i; j != e; ++j) { 18296e92c1dSJiangning Liu Type *Ty = Globals[j]->getType()->getElementType(); 18396e92c1dSJiangning Liu MergedSize += DL->getTypeAllocSize(Ty); 18496e92c1dSJiangning Liu if (MergedSize > MaxOffset) { 18596e92c1dSJiangning Liu break; 18696e92c1dSJiangning Liu } 18796e92c1dSJiangning Liu Tys.push_back(Ty); 18896e92c1dSJiangning Liu Inits.push_back(Globals[j]->getInitializer()); 18996e92c1dSJiangning Liu 19096e92c1dSJiangning Liu if (Globals[j]->hasExternalLinkage() && !HasExternal) { 19196e92c1dSJiangning Liu HasExternal = true; 19296e92c1dSJiangning Liu TheFirstExternal = Globals[j]; 19396e92c1dSJiangning Liu } 19496e92c1dSJiangning Liu } 19596e92c1dSJiangning Liu 19696e92c1dSJiangning Liu // If merged variables doesn't have external linkage, we needn't to expose 19796e92c1dSJiangning Liu // the symbol after merging. 19896e92c1dSJiangning Liu GlobalValue::LinkageTypes Linkage = HasExternal 19996e92c1dSJiangning Liu ? GlobalValue::ExternalLinkage 20096e92c1dSJiangning Liu : GlobalValue::InternalLinkage; 20196e92c1dSJiangning Liu 20296e92c1dSJiangning Liu StructType *MergedTy = StructType::get(M.getContext(), Tys); 20396e92c1dSJiangning Liu Constant *MergedInit = ConstantStruct::get(MergedTy, Inits); 20496e92c1dSJiangning Liu 205*cccdadcaSBenjamin Kramer // If merged variables have external linkage, we use symbol name of the 206*cccdadcaSBenjamin Kramer // first variable merged as the suffix of global symbol name. This would 207*cccdadcaSBenjamin Kramer // be able to avoid the link-time naming conflict for globalm symbols. 20896e92c1dSJiangning Liu GlobalVariable *MergedGV = new GlobalVariable( 209*cccdadcaSBenjamin Kramer M, MergedTy, isConst, Linkage, MergedInit, 210*cccdadcaSBenjamin Kramer HasExternal ? "_MergedGlobals_" + TheFirstExternal->getName() 211*cccdadcaSBenjamin Kramer : "_MergedGlobals", 212*cccdadcaSBenjamin Kramer nullptr, GlobalVariable::NotThreadLocal, AddrSpace); 21396e92c1dSJiangning Liu 21496e92c1dSJiangning Liu for (size_t k = i; k < j; ++k) { 21596e92c1dSJiangning Liu GlobalValue::LinkageTypes Linkage = Globals[k]->getLinkage(); 21696e92c1dSJiangning Liu std::string Name = Globals[k]->getName(); 21796e92c1dSJiangning Liu 21896e92c1dSJiangning Liu Constant *Idx[2] = { 21996e92c1dSJiangning Liu ConstantInt::get(Int32Ty, 0), 22096e92c1dSJiangning Liu ConstantInt::get(Int32Ty, k-i) 22196e92c1dSJiangning Liu }; 22296e92c1dSJiangning Liu Constant *GEP = ConstantExpr::getInBoundsGetElementPtr(MergedGV, Idx); 22396e92c1dSJiangning Liu Globals[k]->replaceAllUsesWith(GEP); 22496e92c1dSJiangning Liu Globals[k]->eraseFromParent(); 22596e92c1dSJiangning Liu 22696e92c1dSJiangning Liu if (Linkage != GlobalValue::InternalLinkage) { 22796e92c1dSJiangning Liu // Generate a new alias... 22896e92c1dSJiangning Liu auto *PTy = cast<PointerType>(GEP->getType()); 22996e92c1dSJiangning Liu GlobalAlias::create(PTy->getElementType(), PTy->getAddressSpace(), 23096e92c1dSJiangning Liu Linkage, Name, GEP, &M); 23196e92c1dSJiangning Liu } 23296e92c1dSJiangning Liu 23396e92c1dSJiangning Liu NumMerged++; 23496e92c1dSJiangning Liu } 23596e92c1dSJiangning Liu i = j; 23696e92c1dSJiangning Liu } 23796e92c1dSJiangning Liu 23896e92c1dSJiangning Liu return true; 23996e92c1dSJiangning Liu } 24096e92c1dSJiangning Liu 24196e92c1dSJiangning Liu void GlobalMerge::collectUsedGlobalVariables(Module &M) { 24296e92c1dSJiangning Liu // Extract global variables from llvm.used array 24396e92c1dSJiangning Liu const GlobalVariable *GV = M.getGlobalVariable("llvm.used"); 24496e92c1dSJiangning Liu if (!GV || !GV->hasInitializer()) return; 24596e92c1dSJiangning Liu 24696e92c1dSJiangning Liu // Should be an array of 'i8*'. 24796e92c1dSJiangning Liu const ConstantArray *InitList = cast<ConstantArray>(GV->getInitializer()); 24896e92c1dSJiangning Liu 24996e92c1dSJiangning Liu for (unsigned i = 0, e = InitList->getNumOperands(); i != e; ++i) 25096e92c1dSJiangning Liu if (const GlobalVariable *G = 25196e92c1dSJiangning Liu dyn_cast<GlobalVariable>(InitList->getOperand(i)->stripPointerCasts())) 25296e92c1dSJiangning Liu MustKeepGlobalVariables.insert(G); 25396e92c1dSJiangning Liu } 25496e92c1dSJiangning Liu 25596e92c1dSJiangning Liu void GlobalMerge::setMustKeepGlobalVariables(Module &M) { 25696e92c1dSJiangning Liu collectUsedGlobalVariables(M); 25796e92c1dSJiangning Liu 25896e92c1dSJiangning Liu for (Module::iterator IFn = M.begin(), IEndFn = M.end(); IFn != IEndFn; 25996e92c1dSJiangning Liu ++IFn) { 26096e92c1dSJiangning Liu for (Function::iterator IBB = IFn->begin(), IEndBB = IFn->end(); 26196e92c1dSJiangning Liu IBB != IEndBB; ++IBB) { 26296e92c1dSJiangning Liu // Follow the invoke link to find the landing pad instruction 26396e92c1dSJiangning Liu const InvokeInst *II = dyn_cast<InvokeInst>(IBB->getTerminator()); 26496e92c1dSJiangning Liu if (!II) continue; 26596e92c1dSJiangning Liu 26696e92c1dSJiangning Liu const LandingPadInst *LPInst = II->getUnwindDest()->getLandingPadInst(); 26796e92c1dSJiangning Liu // Look for globals in the clauses of the landing pad instruction 26896e92c1dSJiangning Liu for (unsigned Idx = 0, NumClauses = LPInst->getNumClauses(); 26996e92c1dSJiangning Liu Idx != NumClauses; ++Idx) 27096e92c1dSJiangning Liu if (const GlobalVariable *GV = 27196e92c1dSJiangning Liu dyn_cast<GlobalVariable>(LPInst->getClause(Idx) 27296e92c1dSJiangning Liu ->stripPointerCasts())) 27396e92c1dSJiangning Liu MustKeepGlobalVariables.insert(GV); 27496e92c1dSJiangning Liu } 27596e92c1dSJiangning Liu } 27696e92c1dSJiangning Liu } 27796e92c1dSJiangning Liu 27896e92c1dSJiangning Liu bool GlobalMerge::doInitialization(Module &M) { 27996e92c1dSJiangning Liu if (!EnableGlobalMerge) 28096e92c1dSJiangning Liu return false; 28196e92c1dSJiangning Liu 28296e92c1dSJiangning Liu DenseMap<unsigned, SmallVector<GlobalVariable*, 16> > Globals, ConstGlobals, 28396e92c1dSJiangning Liu BSSGlobals; 28496e92c1dSJiangning Liu const TargetLowering *TLI = TM->getTargetLowering(); 28596e92c1dSJiangning Liu const DataLayout *DL = TLI->getDataLayout(); 28696e92c1dSJiangning Liu unsigned MaxOffset = TLI->getMaximalGlobalOffset(); 28796e92c1dSJiangning Liu bool Changed = false; 28896e92c1dSJiangning Liu setMustKeepGlobalVariables(M); 28996e92c1dSJiangning Liu 29096e92c1dSJiangning Liu // Grab all non-const globals. 29196e92c1dSJiangning Liu for (Module::global_iterator I = M.global_begin(), 29296e92c1dSJiangning Liu E = M.global_end(); I != E; ++I) { 29396e92c1dSJiangning Liu // Merge is safe for "normal" internal or external globals only 29496e92c1dSJiangning Liu if (I->isDeclaration() || I->isThreadLocal() || I->hasSection()) 29596e92c1dSJiangning Liu continue; 29696e92c1dSJiangning Liu 29796e92c1dSJiangning Liu if (!(EnableGlobalMergeOnExternal && I->hasExternalLinkage()) && 29896e92c1dSJiangning Liu !I->hasInternalLinkage()) 29996e92c1dSJiangning Liu continue; 30096e92c1dSJiangning Liu 30196e92c1dSJiangning Liu PointerType *PT = dyn_cast<PointerType>(I->getType()); 30296e92c1dSJiangning Liu assert(PT && "Global variable is not a pointer!"); 30396e92c1dSJiangning Liu 30496e92c1dSJiangning Liu unsigned AddressSpace = PT->getAddressSpace(); 30596e92c1dSJiangning Liu 30696e92c1dSJiangning Liu // Ignore fancy-aligned globals for now. 30796e92c1dSJiangning Liu unsigned Alignment = DL->getPreferredAlignment(I); 30896e92c1dSJiangning Liu Type *Ty = I->getType()->getElementType(); 30996e92c1dSJiangning Liu if (Alignment > DL->getABITypeAlignment(Ty)) 31096e92c1dSJiangning Liu continue; 31196e92c1dSJiangning Liu 31296e92c1dSJiangning Liu // Ignore all 'special' globals. 31396e92c1dSJiangning Liu if (I->getName().startswith("llvm.") || 31496e92c1dSJiangning Liu I->getName().startswith(".llvm.")) 31596e92c1dSJiangning Liu continue; 31696e92c1dSJiangning Liu 31796e92c1dSJiangning Liu // Ignore all "required" globals: 31896e92c1dSJiangning Liu if (isMustKeepGlobalVariable(I)) 31996e92c1dSJiangning Liu continue; 32096e92c1dSJiangning Liu 32196e92c1dSJiangning Liu if (DL->getTypeAllocSize(Ty) < MaxOffset) { 32296e92c1dSJiangning Liu if (TargetLoweringObjectFile::getKindForGlobal(I, *TM).isBSSLocal()) 32396e92c1dSJiangning Liu BSSGlobals[AddressSpace].push_back(I); 32496e92c1dSJiangning Liu else if (I->isConstant()) 32596e92c1dSJiangning Liu ConstGlobals[AddressSpace].push_back(I); 32696e92c1dSJiangning Liu else 32796e92c1dSJiangning Liu Globals[AddressSpace].push_back(I); 32896e92c1dSJiangning Liu } 32996e92c1dSJiangning Liu } 33096e92c1dSJiangning Liu 33196e92c1dSJiangning Liu for (DenseMap<unsigned, SmallVector<GlobalVariable*, 16> >::iterator 33296e92c1dSJiangning Liu I = Globals.begin(), E = Globals.end(); I != E; ++I) 33396e92c1dSJiangning Liu if (I->second.size() > 1) 33496e92c1dSJiangning Liu Changed |= doMerge(I->second, M, false, I->first); 33596e92c1dSJiangning Liu 33696e92c1dSJiangning Liu for (DenseMap<unsigned, SmallVector<GlobalVariable*, 16> >::iterator 33796e92c1dSJiangning Liu I = BSSGlobals.begin(), E = BSSGlobals.end(); I != E; ++I) 33896e92c1dSJiangning Liu if (I->second.size() > 1) 33996e92c1dSJiangning Liu Changed |= doMerge(I->second, M, false, I->first); 34096e92c1dSJiangning Liu 34196e92c1dSJiangning Liu if (EnableGlobalMergeOnConst) 34296e92c1dSJiangning Liu for (DenseMap<unsigned, SmallVector<GlobalVariable*, 16> >::iterator 34396e92c1dSJiangning Liu I = ConstGlobals.begin(), E = ConstGlobals.end(); I != E; ++I) 34496e92c1dSJiangning Liu if (I->second.size() > 1) 34596e92c1dSJiangning Liu Changed |= doMerge(I->second, M, true, I->first); 34696e92c1dSJiangning Liu 34796e92c1dSJiangning Liu return Changed; 34896e92c1dSJiangning Liu } 34996e92c1dSJiangning Liu 35096e92c1dSJiangning Liu bool GlobalMerge::runOnFunction(Function &F) { 35196e92c1dSJiangning Liu return false; 35296e92c1dSJiangning Liu } 35396e92c1dSJiangning Liu 35496e92c1dSJiangning Liu bool GlobalMerge::doFinalization(Module &M) { 35596e92c1dSJiangning Liu MustKeepGlobalVariables.clear(); 35696e92c1dSJiangning Liu return false; 35796e92c1dSJiangning Liu } 35896e92c1dSJiangning Liu 35996e92c1dSJiangning Liu Pass *llvm::createGlobalMergePass(const TargetMachine *TM) { 36096e92c1dSJiangning Liu return new GlobalMerge(TM); 36196e92c1dSJiangning Liu } 362