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