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