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" 71*d913448bSEric Christopher #include "llvm/Target/TargetSubtargetInfo.h" 7296e92c1dSJiangning Liu using namespace llvm; 7396e92c1dSJiangning Liu 7496e92c1dSJiangning Liu #define DEBUG_TYPE "global-merge" 7596e92c1dSJiangning Liu 7696e92c1dSJiangning Liu static cl::opt<bool> 7796e92c1dSJiangning Liu EnableGlobalMerge("enable-global-merge", cl::Hidden, 7896e92c1dSJiangning Liu cl::desc("Enable global merge pass"), 7996e92c1dSJiangning Liu cl::init(true)); 8096e92c1dSJiangning Liu 8196e92c1dSJiangning Liu static cl::opt<bool> 8296e92c1dSJiangning Liu EnableGlobalMergeOnConst("global-merge-on-const", cl::Hidden, 8396e92c1dSJiangning Liu cl::desc("Enable global merge pass on constants"), 8496e92c1dSJiangning Liu cl::init(false)); 8596e92c1dSJiangning Liu 8696e92c1dSJiangning Liu // FIXME: this could be a transitional option, and we probably need to remove 8796e92c1dSJiangning Liu // it if only we are sure this optimization could always benefit all targets. 8896e92c1dSJiangning Liu static cl::opt<bool> 8996e92c1dSJiangning Liu EnableGlobalMergeOnExternal("global-merge-on-external", cl::Hidden, 9096e92c1dSJiangning Liu cl::desc("Enable global merge pass on external linkage"), 9196e92c1dSJiangning Liu cl::init(false)); 9296e92c1dSJiangning Liu 9396e92c1dSJiangning Liu STATISTIC(NumMerged , "Number of globals merged"); 9496e92c1dSJiangning Liu namespace { 9596e92c1dSJiangning Liu class GlobalMerge : public FunctionPass { 9696e92c1dSJiangning Liu const TargetMachine *TM; 9796e92c1dSJiangning Liu 9896e92c1dSJiangning Liu bool doMerge(SmallVectorImpl<GlobalVariable*> &Globals, 9996e92c1dSJiangning Liu Module &M, bool isConst, unsigned AddrSpace) const; 10096e92c1dSJiangning Liu 10196e92c1dSJiangning Liu /// \brief Check if the given variable has been identified as must keep 10296e92c1dSJiangning Liu /// \pre setMustKeepGlobalVariables must have been called on the Module that 10396e92c1dSJiangning Liu /// contains GV 10496e92c1dSJiangning Liu bool isMustKeepGlobalVariable(const GlobalVariable *GV) const { 10596e92c1dSJiangning Liu return MustKeepGlobalVariables.count(GV); 10696e92c1dSJiangning Liu } 10796e92c1dSJiangning Liu 10896e92c1dSJiangning Liu /// Collect every variables marked as "used" or used in a landing pad 10996e92c1dSJiangning Liu /// instruction for this Module. 11096e92c1dSJiangning Liu void setMustKeepGlobalVariables(Module &M); 11196e92c1dSJiangning Liu 11296e92c1dSJiangning Liu /// Collect every variables marked as "used" 11396e92c1dSJiangning Liu void collectUsedGlobalVariables(Module &M); 11496e92c1dSJiangning Liu 11596e92c1dSJiangning Liu /// Keep track of the GlobalVariable that must not be merged away 11696e92c1dSJiangning Liu SmallPtrSet<const GlobalVariable *, 16> MustKeepGlobalVariables; 11796e92c1dSJiangning Liu 11896e92c1dSJiangning Liu public: 11996e92c1dSJiangning Liu static char ID; // Pass identification, replacement for typeid. 12096e92c1dSJiangning Liu explicit GlobalMerge(const TargetMachine *TM = nullptr) 12196e92c1dSJiangning Liu : FunctionPass(ID), TM(TM) { 12296e92c1dSJiangning Liu initializeGlobalMergePass(*PassRegistry::getPassRegistry()); 12396e92c1dSJiangning Liu } 12496e92c1dSJiangning Liu 12596e92c1dSJiangning Liu bool doInitialization(Module &M) override; 12696e92c1dSJiangning Liu bool runOnFunction(Function &F) override; 12796e92c1dSJiangning Liu bool doFinalization(Module &M) override; 12896e92c1dSJiangning Liu 12996e92c1dSJiangning Liu const char *getPassName() const override { 13096e92c1dSJiangning Liu return "Merge internal globals"; 13196e92c1dSJiangning Liu } 13296e92c1dSJiangning Liu 13396e92c1dSJiangning Liu void getAnalysisUsage(AnalysisUsage &AU) const override { 13496e92c1dSJiangning Liu AU.setPreservesCFG(); 13596e92c1dSJiangning Liu FunctionPass::getAnalysisUsage(AU); 13696e92c1dSJiangning Liu } 13796e92c1dSJiangning Liu }; 13896e92c1dSJiangning Liu } // end anonymous namespace 13996e92c1dSJiangning Liu 14096e92c1dSJiangning Liu char GlobalMerge::ID = 0; 14196e92c1dSJiangning Liu INITIALIZE_TM_PASS(GlobalMerge, "global-merge", "Merge global variables", 14296e92c1dSJiangning Liu false, false) 14396e92c1dSJiangning Liu 14496e92c1dSJiangning Liu bool GlobalMerge::doMerge(SmallVectorImpl<GlobalVariable*> &Globals, 14596e92c1dSJiangning Liu Module &M, bool isConst, unsigned AddrSpace) const { 146*d913448bSEric Christopher const TargetLowering *TLI = TM->getSubtargetImpl()->getTargetLowering(); 14796e92c1dSJiangning Liu const DataLayout *DL = TLI->getDataLayout(); 14896e92c1dSJiangning Liu 14996e92c1dSJiangning Liu // FIXME: Infer the maximum possible offset depending on the actual users 15096e92c1dSJiangning Liu // (these max offsets are different for the users inside Thumb or ARM 15196e92c1dSJiangning Liu // functions) 15296e92c1dSJiangning Liu unsigned MaxOffset = TLI->getMaximalGlobalOffset(); 15396e92c1dSJiangning Liu 15496e92c1dSJiangning Liu // FIXME: Find better heuristics 15596e92c1dSJiangning Liu std::stable_sort(Globals.begin(), Globals.end(), 15696e92c1dSJiangning Liu [DL](const GlobalVariable *GV1, const GlobalVariable *GV2) { 15796e92c1dSJiangning Liu Type *Ty1 = cast<PointerType>(GV1->getType())->getElementType(); 15896e92c1dSJiangning Liu Type *Ty2 = cast<PointerType>(GV2->getType())->getElementType(); 15996e92c1dSJiangning Liu 16096e92c1dSJiangning Liu return (DL->getTypeAllocSize(Ty1) < DL->getTypeAllocSize(Ty2)); 16196e92c1dSJiangning Liu }); 16296e92c1dSJiangning Liu 16396e92c1dSJiangning Liu Type *Int32Ty = Type::getInt32Ty(M.getContext()); 16496e92c1dSJiangning Liu 16596e92c1dSJiangning Liu assert(Globals.size() > 1); 16696e92c1dSJiangning Liu 16796e92c1dSJiangning Liu // FIXME: This simple solution merges globals all together as maximum as 16896e92c1dSJiangning Liu // possible. However, with this solution it would be hard to remove dead 16996e92c1dSJiangning Liu // global symbols at link-time. An alternative solution could be checking 17096e92c1dSJiangning Liu // global symbols references function by function, and make the symbols 17196e92c1dSJiangning Liu // being referred in the same function merged and we would probably need 17296e92c1dSJiangning Liu // to introduce heuristic algorithm to solve the merge conflict from 17396e92c1dSJiangning Liu // different functions. 17496e92c1dSJiangning Liu for (size_t i = 0, e = Globals.size(); i != e; ) { 17596e92c1dSJiangning Liu size_t j = 0; 17696e92c1dSJiangning Liu uint64_t MergedSize = 0; 17796e92c1dSJiangning Liu std::vector<Type*> Tys; 17896e92c1dSJiangning Liu std::vector<Constant*> Inits; 17996e92c1dSJiangning Liu 18096e92c1dSJiangning Liu bool HasExternal = false; 18196e92c1dSJiangning Liu GlobalVariable *TheFirstExternal = 0; 18296e92c1dSJiangning Liu for (j = i; j != e; ++j) { 18396e92c1dSJiangning Liu Type *Ty = Globals[j]->getType()->getElementType(); 18496e92c1dSJiangning Liu MergedSize += DL->getTypeAllocSize(Ty); 18596e92c1dSJiangning Liu if (MergedSize > MaxOffset) { 18696e92c1dSJiangning Liu break; 18796e92c1dSJiangning Liu } 18896e92c1dSJiangning Liu Tys.push_back(Ty); 18996e92c1dSJiangning Liu Inits.push_back(Globals[j]->getInitializer()); 19096e92c1dSJiangning Liu 19196e92c1dSJiangning Liu if (Globals[j]->hasExternalLinkage() && !HasExternal) { 19296e92c1dSJiangning Liu HasExternal = true; 19396e92c1dSJiangning Liu TheFirstExternal = Globals[j]; 19496e92c1dSJiangning Liu } 19596e92c1dSJiangning Liu } 19696e92c1dSJiangning Liu 19796e92c1dSJiangning Liu // If merged variables doesn't have external linkage, we needn't to expose 19896e92c1dSJiangning Liu // the symbol after merging. 19996e92c1dSJiangning Liu GlobalValue::LinkageTypes Linkage = HasExternal 20096e92c1dSJiangning Liu ? GlobalValue::ExternalLinkage 20196e92c1dSJiangning Liu : GlobalValue::InternalLinkage; 20296e92c1dSJiangning Liu 20396e92c1dSJiangning Liu StructType *MergedTy = StructType::get(M.getContext(), Tys); 20496e92c1dSJiangning Liu Constant *MergedInit = ConstantStruct::get(MergedTy, Inits); 20596e92c1dSJiangning Liu 206cccdadcaSBenjamin Kramer // If merged variables have external linkage, we use symbol name of the 207cccdadcaSBenjamin Kramer // first variable merged as the suffix of global symbol name. This would 208cccdadcaSBenjamin Kramer // be able to avoid the link-time naming conflict for globalm symbols. 20996e92c1dSJiangning Liu GlobalVariable *MergedGV = new GlobalVariable( 210cccdadcaSBenjamin Kramer M, MergedTy, isConst, Linkage, MergedInit, 211cccdadcaSBenjamin Kramer HasExternal ? "_MergedGlobals_" + TheFirstExternal->getName() 212cccdadcaSBenjamin Kramer : "_MergedGlobals", 213cccdadcaSBenjamin Kramer nullptr, GlobalVariable::NotThreadLocal, AddrSpace); 21496e92c1dSJiangning Liu 21596e92c1dSJiangning Liu for (size_t k = i; k < j; ++k) { 21696e92c1dSJiangning Liu GlobalValue::LinkageTypes Linkage = Globals[k]->getLinkage(); 21796e92c1dSJiangning Liu std::string Name = Globals[k]->getName(); 21896e92c1dSJiangning Liu 21996e92c1dSJiangning Liu Constant *Idx[2] = { 22096e92c1dSJiangning Liu ConstantInt::get(Int32Ty, 0), 22196e92c1dSJiangning Liu ConstantInt::get(Int32Ty, k-i) 22296e92c1dSJiangning Liu }; 22396e92c1dSJiangning Liu Constant *GEP = ConstantExpr::getInBoundsGetElementPtr(MergedGV, Idx); 22496e92c1dSJiangning Liu Globals[k]->replaceAllUsesWith(GEP); 22596e92c1dSJiangning Liu Globals[k]->eraseFromParent(); 22696e92c1dSJiangning Liu 22796e92c1dSJiangning Liu if (Linkage != GlobalValue::InternalLinkage) { 22896e92c1dSJiangning Liu // Generate a new alias... 22996e92c1dSJiangning Liu auto *PTy = cast<PointerType>(GEP->getType()); 23096e92c1dSJiangning Liu GlobalAlias::create(PTy->getElementType(), PTy->getAddressSpace(), 23196e92c1dSJiangning Liu Linkage, Name, GEP, &M); 23296e92c1dSJiangning Liu } 23396e92c1dSJiangning Liu 23496e92c1dSJiangning Liu NumMerged++; 23596e92c1dSJiangning Liu } 23696e92c1dSJiangning Liu i = j; 23796e92c1dSJiangning Liu } 23896e92c1dSJiangning Liu 23996e92c1dSJiangning Liu return true; 24096e92c1dSJiangning Liu } 24196e92c1dSJiangning Liu 24296e92c1dSJiangning Liu void GlobalMerge::collectUsedGlobalVariables(Module &M) { 24396e92c1dSJiangning Liu // Extract global variables from llvm.used array 24496e92c1dSJiangning Liu const GlobalVariable *GV = M.getGlobalVariable("llvm.used"); 24596e92c1dSJiangning Liu if (!GV || !GV->hasInitializer()) return; 24696e92c1dSJiangning Liu 24796e92c1dSJiangning Liu // Should be an array of 'i8*'. 24896e92c1dSJiangning Liu const ConstantArray *InitList = cast<ConstantArray>(GV->getInitializer()); 24996e92c1dSJiangning Liu 25096e92c1dSJiangning Liu for (unsigned i = 0, e = InitList->getNumOperands(); i != e; ++i) 25196e92c1dSJiangning Liu if (const GlobalVariable *G = 25296e92c1dSJiangning Liu dyn_cast<GlobalVariable>(InitList->getOperand(i)->stripPointerCasts())) 25396e92c1dSJiangning Liu MustKeepGlobalVariables.insert(G); 25496e92c1dSJiangning Liu } 25596e92c1dSJiangning Liu 25696e92c1dSJiangning Liu void GlobalMerge::setMustKeepGlobalVariables(Module &M) { 25796e92c1dSJiangning Liu collectUsedGlobalVariables(M); 25896e92c1dSJiangning Liu 25996e92c1dSJiangning Liu for (Module::iterator IFn = M.begin(), IEndFn = M.end(); IFn != IEndFn; 26096e92c1dSJiangning Liu ++IFn) { 26196e92c1dSJiangning Liu for (Function::iterator IBB = IFn->begin(), IEndBB = IFn->end(); 26296e92c1dSJiangning Liu IBB != IEndBB; ++IBB) { 26396e92c1dSJiangning Liu // Follow the invoke link to find the landing pad instruction 26496e92c1dSJiangning Liu const InvokeInst *II = dyn_cast<InvokeInst>(IBB->getTerminator()); 26596e92c1dSJiangning Liu if (!II) continue; 26696e92c1dSJiangning Liu 26796e92c1dSJiangning Liu const LandingPadInst *LPInst = II->getUnwindDest()->getLandingPadInst(); 26896e92c1dSJiangning Liu // Look for globals in the clauses of the landing pad instruction 26996e92c1dSJiangning Liu for (unsigned Idx = 0, NumClauses = LPInst->getNumClauses(); 27096e92c1dSJiangning Liu Idx != NumClauses; ++Idx) 27196e92c1dSJiangning Liu if (const GlobalVariable *GV = 27296e92c1dSJiangning Liu dyn_cast<GlobalVariable>(LPInst->getClause(Idx) 27396e92c1dSJiangning Liu ->stripPointerCasts())) 27496e92c1dSJiangning Liu MustKeepGlobalVariables.insert(GV); 27596e92c1dSJiangning Liu } 27696e92c1dSJiangning Liu } 27796e92c1dSJiangning Liu } 27896e92c1dSJiangning Liu 27996e92c1dSJiangning Liu bool GlobalMerge::doInitialization(Module &M) { 28096e92c1dSJiangning Liu if (!EnableGlobalMerge) 28196e92c1dSJiangning Liu return false; 28296e92c1dSJiangning Liu 28396e92c1dSJiangning Liu DenseMap<unsigned, SmallVector<GlobalVariable*, 16> > Globals, ConstGlobals, 28496e92c1dSJiangning Liu BSSGlobals; 285*d913448bSEric Christopher const TargetLowering *TLI = TM->getSubtargetImpl()->getTargetLowering(); 28696e92c1dSJiangning Liu const DataLayout *DL = TLI->getDataLayout(); 28796e92c1dSJiangning Liu unsigned MaxOffset = TLI->getMaximalGlobalOffset(); 28896e92c1dSJiangning Liu bool Changed = false; 28996e92c1dSJiangning Liu setMustKeepGlobalVariables(M); 29096e92c1dSJiangning Liu 29196e92c1dSJiangning Liu // Grab all non-const globals. 29296e92c1dSJiangning Liu for (Module::global_iterator I = M.global_begin(), 29396e92c1dSJiangning Liu E = M.global_end(); I != E; ++I) { 29496e92c1dSJiangning Liu // Merge is safe for "normal" internal or external globals only 29596e92c1dSJiangning Liu if (I->isDeclaration() || I->isThreadLocal() || I->hasSection()) 29696e92c1dSJiangning Liu continue; 29796e92c1dSJiangning Liu 29896e92c1dSJiangning Liu if (!(EnableGlobalMergeOnExternal && I->hasExternalLinkage()) && 29996e92c1dSJiangning Liu !I->hasInternalLinkage()) 30096e92c1dSJiangning Liu continue; 30196e92c1dSJiangning Liu 30296e92c1dSJiangning Liu PointerType *PT = dyn_cast<PointerType>(I->getType()); 30396e92c1dSJiangning Liu assert(PT && "Global variable is not a pointer!"); 30496e92c1dSJiangning Liu 30596e92c1dSJiangning Liu unsigned AddressSpace = PT->getAddressSpace(); 30696e92c1dSJiangning Liu 30796e92c1dSJiangning Liu // Ignore fancy-aligned globals for now. 30896e92c1dSJiangning Liu unsigned Alignment = DL->getPreferredAlignment(I); 30996e92c1dSJiangning Liu Type *Ty = I->getType()->getElementType(); 31096e92c1dSJiangning Liu if (Alignment > DL->getABITypeAlignment(Ty)) 31196e92c1dSJiangning Liu continue; 31296e92c1dSJiangning Liu 31396e92c1dSJiangning Liu // Ignore all 'special' globals. 31496e92c1dSJiangning Liu if (I->getName().startswith("llvm.") || 31596e92c1dSJiangning Liu I->getName().startswith(".llvm.")) 31696e92c1dSJiangning Liu continue; 31796e92c1dSJiangning Liu 31896e92c1dSJiangning Liu // Ignore all "required" globals: 31996e92c1dSJiangning Liu if (isMustKeepGlobalVariable(I)) 32096e92c1dSJiangning Liu continue; 32196e92c1dSJiangning Liu 32296e92c1dSJiangning Liu if (DL->getTypeAllocSize(Ty) < MaxOffset) { 32396e92c1dSJiangning Liu if (TargetLoweringObjectFile::getKindForGlobal(I, *TM).isBSSLocal()) 32496e92c1dSJiangning Liu BSSGlobals[AddressSpace].push_back(I); 32596e92c1dSJiangning Liu else if (I->isConstant()) 32696e92c1dSJiangning Liu ConstGlobals[AddressSpace].push_back(I); 32796e92c1dSJiangning Liu else 32896e92c1dSJiangning Liu Globals[AddressSpace].push_back(I); 32996e92c1dSJiangning Liu } 33096e92c1dSJiangning Liu } 33196e92c1dSJiangning Liu 33296e92c1dSJiangning Liu for (DenseMap<unsigned, SmallVector<GlobalVariable*, 16> >::iterator 33396e92c1dSJiangning Liu I = Globals.begin(), E = Globals.end(); I != E; ++I) 33496e92c1dSJiangning Liu if (I->second.size() > 1) 33596e92c1dSJiangning Liu Changed |= doMerge(I->second, M, false, I->first); 33696e92c1dSJiangning Liu 33796e92c1dSJiangning Liu for (DenseMap<unsigned, SmallVector<GlobalVariable*, 16> >::iterator 33896e92c1dSJiangning Liu I = BSSGlobals.begin(), E = BSSGlobals.end(); I != E; ++I) 33996e92c1dSJiangning Liu if (I->second.size() > 1) 34096e92c1dSJiangning Liu Changed |= doMerge(I->second, M, false, I->first); 34196e92c1dSJiangning Liu 34296e92c1dSJiangning Liu if (EnableGlobalMergeOnConst) 34396e92c1dSJiangning Liu for (DenseMap<unsigned, SmallVector<GlobalVariable*, 16> >::iterator 34496e92c1dSJiangning Liu I = ConstGlobals.begin(), E = ConstGlobals.end(); I != E; ++I) 34596e92c1dSJiangning Liu if (I->second.size() > 1) 34696e92c1dSJiangning Liu Changed |= doMerge(I->second, M, true, I->first); 34796e92c1dSJiangning Liu 34896e92c1dSJiangning Liu return Changed; 34996e92c1dSJiangning Liu } 35096e92c1dSJiangning Liu 35196e92c1dSJiangning Liu bool GlobalMerge::runOnFunction(Function &F) { 35296e92c1dSJiangning Liu return false; 35396e92c1dSJiangning Liu } 35496e92c1dSJiangning Liu 35596e92c1dSJiangning Liu bool GlobalMerge::doFinalization(Module &M) { 35696e92c1dSJiangning Liu MustKeepGlobalVariables.clear(); 35796e92c1dSJiangning Liu return false; 35896e92c1dSJiangning Liu } 35996e92c1dSJiangning Liu 36096e92c1dSJiangning Liu Pass *llvm::createGlobalMergePass(const TargetMachine *TM) { 36196e92c1dSJiangning Liu return new GlobalMerge(TM); 36296e92c1dSJiangning Liu } 363