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". 52279e3ee9SAhmed Bougacha // 53279e3ee9SAhmed Bougacha // However, merging globals can have tradeoffs: 54279e3ee9SAhmed Bougacha // - it confuses debuggers, tools, and users 55279e3ee9SAhmed Bougacha // - it makes linker optimizations less useful (order files, LOHs, ...) 56279e3ee9SAhmed Bougacha // - it forces usage of indexed addressing (which isn't necessarily "free") 57279e3ee9SAhmed Bougacha // - it can increase register pressure when the uses are disparate enough. 58279e3ee9SAhmed Bougacha // 59279e3ee9SAhmed Bougacha // We use heuristics to discover the best global grouping we can (cf cl::opts). 6096e92c1dSJiangning Liu // ===---------------------------------------------------------------------===// 6196e92c1dSJiangning Liu 6296e92c1dSJiangning Liu #include "llvm/Transforms/Scalar.h" 63279e3ee9SAhmed Bougacha #include "llvm/ADT/DenseMap.h" 64279e3ee9SAhmed Bougacha #include "llvm/ADT/SmallBitVector.h" 6596e92c1dSJiangning Liu #include "llvm/ADT/SmallPtrSet.h" 6696e92c1dSJiangning Liu #include "llvm/ADT/Statistic.h" 67d9903888SChandler Carruth #include "llvm/CodeGen/Passes.h" 6896e92c1dSJiangning Liu #include "llvm/IR/Attributes.h" 6996e92c1dSJiangning Liu #include "llvm/IR/Constants.h" 7096e92c1dSJiangning Liu #include "llvm/IR/DataLayout.h" 7196e92c1dSJiangning Liu #include "llvm/IR/DerivedTypes.h" 7296e92c1dSJiangning Liu #include "llvm/IR/Function.h" 7396e92c1dSJiangning Liu #include "llvm/IR/GlobalVariable.h" 7496e92c1dSJiangning Liu #include "llvm/IR/Instructions.h" 7596e92c1dSJiangning Liu #include "llvm/IR/Intrinsics.h" 7696e92c1dSJiangning Liu #include "llvm/IR/Module.h" 7796e92c1dSJiangning Liu #include "llvm/Pass.h" 7896e92c1dSJiangning Liu #include "llvm/Support/CommandLine.h" 79279e3ee9SAhmed Bougacha #include "llvm/Support/Debug.h" 80279e3ee9SAhmed Bougacha #include "llvm/Support/raw_ostream.h" 8196e92c1dSJiangning Liu #include "llvm/Target/TargetLowering.h" 8296e92c1dSJiangning Liu #include "llvm/Target/TargetLoweringObjectFile.h" 83d913448bSEric Christopher #include "llvm/Target/TargetSubtargetInfo.h" 84279e3ee9SAhmed Bougacha #include <algorithm> 8596e92c1dSJiangning Liu using namespace llvm; 8696e92c1dSJiangning Liu 8796e92c1dSJiangning Liu #define DEBUG_TYPE "global-merge" 8896e92c1dSJiangning Liu 89b96444efSAhmed Bougacha // FIXME: This is only useful as a last-resort way to disable the pass. 9096e92c1dSJiangning Liu static cl::opt<bool> 9196e92c1dSJiangning Liu EnableGlobalMerge("enable-global-merge", cl::Hidden, 92b96444efSAhmed Bougacha cl::desc("Enable the global merge pass"), 9396e92c1dSJiangning Liu cl::init(true)); 9496e92c1dSJiangning Liu 95279e3ee9SAhmed Bougacha static cl::opt<bool> GlobalMergeGroupByUse( 96279e3ee9SAhmed Bougacha "global-merge-group-by-use", cl::Hidden, 97279e3ee9SAhmed Bougacha cl::desc("Improve global merge pass to look at uses"), cl::init(true)); 98279e3ee9SAhmed Bougacha 99279e3ee9SAhmed Bougacha static cl::opt<bool> GlobalMergeIgnoreSingleUse( 100279e3ee9SAhmed Bougacha "global-merge-ignore-single-use", cl::Hidden, 101279e3ee9SAhmed Bougacha cl::desc("Improve global merge pass to ignore globals only used alone"), 102279e3ee9SAhmed Bougacha cl::init(true)); 103279e3ee9SAhmed Bougacha 10496e92c1dSJiangning Liu static cl::opt<bool> 10596e92c1dSJiangning Liu EnableGlobalMergeOnConst("global-merge-on-const", cl::Hidden, 10696e92c1dSJiangning Liu cl::desc("Enable global merge pass on constants"), 10796e92c1dSJiangning Liu cl::init(false)); 10896e92c1dSJiangning Liu 10996e92c1dSJiangning Liu // FIXME: this could be a transitional option, and we probably need to remove 11096e92c1dSJiangning Liu // it if only we are sure this optimization could always benefit all targets. 1118b954241SJohn Brawn static cl::opt<cl::boolOrDefault> 11296e92c1dSJiangning Liu EnableGlobalMergeOnExternal("global-merge-on-external", cl::Hidden, 1138b954241SJohn Brawn cl::desc("Enable global merge pass on external linkage")); 11496e92c1dSJiangning Liu 11596e92c1dSJiangning Liu STATISTIC(NumMerged, "Number of globals merged"); 11696e92c1dSJiangning Liu namespace { 11796e92c1dSJiangning Liu class GlobalMerge : public FunctionPass { 11896e92c1dSJiangning Liu const TargetMachine *TM; 119ed47b229SEric Christopher // FIXME: Infer the maximum possible offset depending on the actual users 120ed47b229SEric Christopher // (these max offsets are different for the users inside Thumb or ARM 121ed47b229SEric Christopher // functions), see the code that passes in the offset in the ARM backend 122ed47b229SEric Christopher // for more information. 123ed47b229SEric Christopher unsigned MaxOffset; 12496e92c1dSJiangning Liu 12582076412SAhmed Bougacha /// Whether we should try to optimize for size only. 12682076412SAhmed Bougacha /// Currently, this applies a dead simple heuristic: only consider globals 12782076412SAhmed Bougacha /// used in minsize functions for merging. 12882076412SAhmed Bougacha /// FIXME: This could learn about optsize, and be used in the cost model. 12982076412SAhmed Bougacha bool OnlyOptimizeForSize; 13082076412SAhmed Bougacha 1318b954241SJohn Brawn /// Whether we should merge global variables that have external linkage. 1328b954241SJohn Brawn bool MergeExternalGlobals; 1338b954241SJohn Brawn 13496e92c1dSJiangning Liu bool doMerge(SmallVectorImpl<GlobalVariable*> &Globals, 13596e92c1dSJiangning Liu Module &M, bool isConst, unsigned AddrSpace) const; 136279e3ee9SAhmed Bougacha /// \brief Merge everything in \p Globals for which the corresponding bit 137279e3ee9SAhmed Bougacha /// in \p GlobalSet is set. 138279e3ee9SAhmed Bougacha bool doMerge(SmallVectorImpl<GlobalVariable *> &Globals, 139279e3ee9SAhmed Bougacha const BitVector &GlobalSet, Module &M, bool isConst, 140279e3ee9SAhmed Bougacha unsigned AddrSpace) const; 14196e92c1dSJiangning Liu 14296e92c1dSJiangning Liu /// \brief Check if the given variable has been identified as must keep 14396e92c1dSJiangning Liu /// \pre setMustKeepGlobalVariables must have been called on the Module that 14496e92c1dSJiangning Liu /// contains GV 14596e92c1dSJiangning Liu bool isMustKeepGlobalVariable(const GlobalVariable *GV) const { 14696e92c1dSJiangning Liu return MustKeepGlobalVariables.count(GV); 14796e92c1dSJiangning Liu } 14896e92c1dSJiangning Liu 14996e92c1dSJiangning Liu /// Collect every variables marked as "used" or used in a landing pad 15096e92c1dSJiangning Liu /// instruction for this Module. 15196e92c1dSJiangning Liu void setMustKeepGlobalVariables(Module &M); 15296e92c1dSJiangning Liu 15396e92c1dSJiangning Liu /// Collect every variables marked as "used" 15496e92c1dSJiangning Liu void collectUsedGlobalVariables(Module &M); 15596e92c1dSJiangning Liu 15696e92c1dSJiangning Liu /// Keep track of the GlobalVariable that must not be merged away 15796e92c1dSJiangning Liu SmallPtrSet<const GlobalVariable *, 16> MustKeepGlobalVariables; 15896e92c1dSJiangning Liu 15996e92c1dSJiangning Liu public: 16096e92c1dSJiangning Liu static char ID; // Pass identification, replacement for typeid. 161ed47b229SEric Christopher explicit GlobalMerge(const TargetMachine *TM = nullptr, 16282076412SAhmed Bougacha unsigned MaximalOffset = 0, 1638b954241SJohn Brawn bool OnlyOptimizeForSize = false, 1648b954241SJohn Brawn bool MergeExternalGlobals = false) 165f6727b0dSMehdi Amini : FunctionPass(ID), TM(TM), MaxOffset(MaximalOffset), 1668b954241SJohn Brawn OnlyOptimizeForSize(OnlyOptimizeForSize), 1678b954241SJohn Brawn MergeExternalGlobals(MergeExternalGlobals) { 16896e92c1dSJiangning Liu initializeGlobalMergePass(*PassRegistry::getPassRegistry()); 16996e92c1dSJiangning Liu } 17096e92c1dSJiangning Liu 17196e92c1dSJiangning Liu bool doInitialization(Module &M) override; 17296e92c1dSJiangning Liu bool runOnFunction(Function &F) override; 17396e92c1dSJiangning Liu bool doFinalization(Module &M) override; 17496e92c1dSJiangning Liu 17596e92c1dSJiangning Liu const char *getPassName() const override { 17696e92c1dSJiangning Liu return "Merge internal globals"; 17796e92c1dSJiangning Liu } 17896e92c1dSJiangning Liu 17996e92c1dSJiangning Liu void getAnalysisUsage(AnalysisUsage &AU) const override { 18096e92c1dSJiangning Liu AU.setPreservesCFG(); 18196e92c1dSJiangning Liu FunctionPass::getAnalysisUsage(AU); 18296e92c1dSJiangning Liu } 18396e92c1dSJiangning Liu }; 18496e92c1dSJiangning Liu } // end anonymous namespace 18596e92c1dSJiangning Liu 18696e92c1dSJiangning Liu char GlobalMerge::ID = 0; 187ed47b229SEric Christopher INITIALIZE_PASS_BEGIN(GlobalMerge, "global-merge", "Merge global variables", 188ed47b229SEric Christopher false, false) 189ed47b229SEric Christopher INITIALIZE_PASS_END(GlobalMerge, "global-merge", "Merge global variables", 19096e92c1dSJiangning Liu false, false) 19196e92c1dSJiangning Liu 19296e92c1dSJiangning Liu bool GlobalMerge::doMerge(SmallVectorImpl<GlobalVariable*> &Globals, 19396e92c1dSJiangning Liu Module &M, bool isConst, unsigned AddrSpace) const { 194f6727b0dSMehdi Amini auto &DL = M.getDataLayout(); 19596e92c1dSJiangning Liu // FIXME: Find better heuristics 196f6727b0dSMehdi Amini std::stable_sort( 197f6727b0dSMehdi Amini Globals.begin(), Globals.end(), 198f6727b0dSMehdi Amini [&DL](const GlobalVariable *GV1, const GlobalVariable *GV2) { 19996e92c1dSJiangning Liu Type *Ty1 = cast<PointerType>(GV1->getType())->getElementType(); 20096e92c1dSJiangning Liu Type *Ty2 = cast<PointerType>(GV2->getType())->getElementType(); 20196e92c1dSJiangning Liu 202f6727b0dSMehdi Amini return (DL.getTypeAllocSize(Ty1) < DL.getTypeAllocSize(Ty2)); 20396e92c1dSJiangning Liu }); 20496e92c1dSJiangning Liu 205279e3ee9SAhmed Bougacha // If we want to just blindly group all globals together, do so. 206279e3ee9SAhmed Bougacha if (!GlobalMergeGroupByUse) { 207279e3ee9SAhmed Bougacha BitVector AllGlobals(Globals.size()); 208279e3ee9SAhmed Bougacha AllGlobals.set(); 209279e3ee9SAhmed Bougacha return doMerge(Globals, AllGlobals, M, isConst, AddrSpace); 210279e3ee9SAhmed Bougacha } 211279e3ee9SAhmed Bougacha 212279e3ee9SAhmed Bougacha // If we want to be smarter, look at all uses of each global, to try to 213279e3ee9SAhmed Bougacha // discover all sets of globals used together, and how many times each of 214*df005cbeSBenjamin Kramer // these sets occurred. 215279e3ee9SAhmed Bougacha // 216279e3ee9SAhmed Bougacha // Keep this reasonably efficient, by having an append-only list of all sets 217279e3ee9SAhmed Bougacha // discovered so far (UsedGlobalSet), and mapping each "together-ness" unit of 218279e3ee9SAhmed Bougacha // code (currently, a Function) to the set of globals seen so far that are 219279e3ee9SAhmed Bougacha // used together in that unit (GlobalUsesByFunction). 220279e3ee9SAhmed Bougacha // 221279e3ee9SAhmed Bougacha // When we look at the Nth global, we now that any new set is either: 222279e3ee9SAhmed Bougacha // - the singleton set {N}, containing this global only, or 223279e3ee9SAhmed Bougacha // - the union of {N} and a previously-discovered set, containing some 224279e3ee9SAhmed Bougacha // combination of the previous N-1 globals. 225279e3ee9SAhmed Bougacha // Using that knowledge, when looking at the Nth global, we can keep: 226279e3ee9SAhmed Bougacha // - a reference to the singleton set {N} (CurGVOnlySetIdx) 227279e3ee9SAhmed Bougacha // - a list mapping each previous set to its union with {N} (EncounteredUGS), 228279e3ee9SAhmed Bougacha // if it actually occurs. 229279e3ee9SAhmed Bougacha 230279e3ee9SAhmed Bougacha // We keep track of the sets of globals used together "close enough". 231279e3ee9SAhmed Bougacha struct UsedGlobalSet { 232279e3ee9SAhmed Bougacha UsedGlobalSet(size_t Size) : Globals(Size), UsageCount(1) {} 233279e3ee9SAhmed Bougacha BitVector Globals; 234279e3ee9SAhmed Bougacha unsigned UsageCount; 235279e3ee9SAhmed Bougacha }; 236279e3ee9SAhmed Bougacha 237279e3ee9SAhmed Bougacha // Each set is unique in UsedGlobalSets. 238279e3ee9SAhmed Bougacha std::vector<UsedGlobalSet> UsedGlobalSets; 239279e3ee9SAhmed Bougacha 240279e3ee9SAhmed Bougacha // Avoid repeating the create-global-set pattern. 241279e3ee9SAhmed Bougacha auto CreateGlobalSet = [&]() -> UsedGlobalSet & { 242279e3ee9SAhmed Bougacha UsedGlobalSets.emplace_back(Globals.size()); 243279e3ee9SAhmed Bougacha return UsedGlobalSets.back(); 244279e3ee9SAhmed Bougacha }; 245279e3ee9SAhmed Bougacha 246279e3ee9SAhmed Bougacha // The first set is the empty set. 247279e3ee9SAhmed Bougacha CreateGlobalSet().UsageCount = 0; 248279e3ee9SAhmed Bougacha 249279e3ee9SAhmed Bougacha // We define "close enough" to be "in the same function". 250279e3ee9SAhmed Bougacha // FIXME: Grouping uses by function is way too aggressive, so we should have 251279e3ee9SAhmed Bougacha // a better metric for distance between uses. 252279e3ee9SAhmed Bougacha // The obvious alternative would be to group by BasicBlock, but that's in 253279e3ee9SAhmed Bougacha // turn too conservative.. 254279e3ee9SAhmed Bougacha // Anything in between wouldn't be trivial to compute, so just stick with 255279e3ee9SAhmed Bougacha // per-function grouping. 256279e3ee9SAhmed Bougacha 257279e3ee9SAhmed Bougacha // The value type is an index into UsedGlobalSets. 258279e3ee9SAhmed Bougacha // The default (0) conveniently points to the empty set. 259279e3ee9SAhmed Bougacha DenseMap<Function *, size_t /*UsedGlobalSetIdx*/> GlobalUsesByFunction; 260279e3ee9SAhmed Bougacha 261279e3ee9SAhmed Bougacha // Now, look at each merge-eligible global in turn. 262279e3ee9SAhmed Bougacha 263279e3ee9SAhmed Bougacha // Keep track of the sets we already encountered to which we added the 264279e3ee9SAhmed Bougacha // current global. 265279e3ee9SAhmed Bougacha // Each element matches the same-index element in UsedGlobalSets. 266279e3ee9SAhmed Bougacha // This lets us efficiently tell whether a set has already been expanded to 267279e3ee9SAhmed Bougacha // include the current global. 268279e3ee9SAhmed Bougacha std::vector<size_t> EncounteredUGS; 269279e3ee9SAhmed Bougacha 270279e3ee9SAhmed Bougacha for (size_t GI = 0, GE = Globals.size(); GI != GE; ++GI) { 271279e3ee9SAhmed Bougacha GlobalVariable *GV = Globals[GI]; 272279e3ee9SAhmed Bougacha 273279e3ee9SAhmed Bougacha // Reset the encountered sets for this global... 274279e3ee9SAhmed Bougacha std::fill(EncounteredUGS.begin(), EncounteredUGS.end(), 0); 275279e3ee9SAhmed Bougacha // ...and grow it in case we created new sets for the previous global. 276279e3ee9SAhmed Bougacha EncounteredUGS.resize(UsedGlobalSets.size()); 277279e3ee9SAhmed Bougacha 278279e3ee9SAhmed Bougacha // We might need to create a set that only consists of the current global. 279279e3ee9SAhmed Bougacha // Keep track of its index into UsedGlobalSets. 280279e3ee9SAhmed Bougacha size_t CurGVOnlySetIdx = 0; 281279e3ee9SAhmed Bougacha 282279e3ee9SAhmed Bougacha // For each global, look at all its Uses. 283279e3ee9SAhmed Bougacha for (auto &U : GV->uses()) { 284279e3ee9SAhmed Bougacha // This Use might be a ConstantExpr. We're interested in Instruction 285279e3ee9SAhmed Bougacha // users, so look through ConstantExpr... 286279e3ee9SAhmed Bougacha Use *UI, *UE; 287279e3ee9SAhmed Bougacha if (ConstantExpr *CE = dyn_cast<ConstantExpr>(U.getUser())) { 2888379e298SOliver Stannard if (CE->use_empty()) 2898379e298SOliver Stannard continue; 290279e3ee9SAhmed Bougacha UI = &*CE->use_begin(); 291279e3ee9SAhmed Bougacha UE = nullptr; 292279e3ee9SAhmed Bougacha } else if (isa<Instruction>(U.getUser())) { 293279e3ee9SAhmed Bougacha UI = &U; 294279e3ee9SAhmed Bougacha UE = UI->getNext(); 295279e3ee9SAhmed Bougacha } else { 296279e3ee9SAhmed Bougacha continue; 297279e3ee9SAhmed Bougacha } 298279e3ee9SAhmed Bougacha 299279e3ee9SAhmed Bougacha // ...to iterate on all the instruction users of the global. 300279e3ee9SAhmed Bougacha // Note that we iterate on Uses and not on Users to be able to getNext(). 301279e3ee9SAhmed Bougacha for (; UI != UE; UI = UI->getNext()) { 302279e3ee9SAhmed Bougacha Instruction *I = dyn_cast<Instruction>(UI->getUser()); 303279e3ee9SAhmed Bougacha if (!I) 304279e3ee9SAhmed Bougacha continue; 305279e3ee9SAhmed Bougacha 306279e3ee9SAhmed Bougacha Function *ParentFn = I->getParent()->getParent(); 30782076412SAhmed Bougacha 30882076412SAhmed Bougacha // If we're only optimizing for size, ignore non-minsize functions. 30982076412SAhmed Bougacha if (OnlyOptimizeForSize && 31082076412SAhmed Bougacha !ParentFn->hasFnAttribute(Attribute::MinSize)) 31182076412SAhmed Bougacha continue; 31282076412SAhmed Bougacha 313279e3ee9SAhmed Bougacha size_t UGSIdx = GlobalUsesByFunction[ParentFn]; 314279e3ee9SAhmed Bougacha 315279e3ee9SAhmed Bougacha // If this is the first global the basic block uses, map it to the set 316279e3ee9SAhmed Bougacha // consisting of this global only. 317279e3ee9SAhmed Bougacha if (!UGSIdx) { 318279e3ee9SAhmed Bougacha // If that set doesn't exist yet, create it. 319279e3ee9SAhmed Bougacha if (!CurGVOnlySetIdx) { 320279e3ee9SAhmed Bougacha CurGVOnlySetIdx = UsedGlobalSets.size(); 321279e3ee9SAhmed Bougacha CreateGlobalSet().Globals.set(GI); 322279e3ee9SAhmed Bougacha } else { 323279e3ee9SAhmed Bougacha ++UsedGlobalSets[CurGVOnlySetIdx].UsageCount; 324279e3ee9SAhmed Bougacha } 325279e3ee9SAhmed Bougacha 326279e3ee9SAhmed Bougacha GlobalUsesByFunction[ParentFn] = CurGVOnlySetIdx; 327279e3ee9SAhmed Bougacha continue; 328279e3ee9SAhmed Bougacha } 329279e3ee9SAhmed Bougacha 330279e3ee9SAhmed Bougacha // If we already encountered this BB, just increment the counter. 331279e3ee9SAhmed Bougacha if (UsedGlobalSets[UGSIdx].Globals.test(GI)) { 332279e3ee9SAhmed Bougacha ++UsedGlobalSets[UGSIdx].UsageCount; 333279e3ee9SAhmed Bougacha continue; 334279e3ee9SAhmed Bougacha } 335279e3ee9SAhmed Bougacha 336279e3ee9SAhmed Bougacha // If not, the previous set wasn't actually used in this function. 337279e3ee9SAhmed Bougacha --UsedGlobalSets[UGSIdx].UsageCount; 338279e3ee9SAhmed Bougacha 339279e3ee9SAhmed Bougacha // If we already expanded the previous set to include this global, just 340279e3ee9SAhmed Bougacha // reuse that expanded set. 341279e3ee9SAhmed Bougacha if (size_t ExpandedIdx = EncounteredUGS[UGSIdx]) { 342279e3ee9SAhmed Bougacha ++UsedGlobalSets[ExpandedIdx].UsageCount; 343279e3ee9SAhmed Bougacha GlobalUsesByFunction[ParentFn] = ExpandedIdx; 344279e3ee9SAhmed Bougacha continue; 345279e3ee9SAhmed Bougacha } 346279e3ee9SAhmed Bougacha 347279e3ee9SAhmed Bougacha // If not, create a new set consisting of the union of the previous set 348279e3ee9SAhmed Bougacha // and this global. Mark it as encountered, so we can reuse it later. 349279e3ee9SAhmed Bougacha GlobalUsesByFunction[ParentFn] = EncounteredUGS[UGSIdx] = 350279e3ee9SAhmed Bougacha UsedGlobalSets.size(); 351279e3ee9SAhmed Bougacha 352279e3ee9SAhmed Bougacha UsedGlobalSet &NewUGS = CreateGlobalSet(); 353279e3ee9SAhmed Bougacha NewUGS.Globals.set(GI); 354279e3ee9SAhmed Bougacha NewUGS.Globals |= UsedGlobalSets[UGSIdx].Globals; 355279e3ee9SAhmed Bougacha } 356279e3ee9SAhmed Bougacha } 357279e3ee9SAhmed Bougacha } 358279e3ee9SAhmed Bougacha 359279e3ee9SAhmed Bougacha // Now we found a bunch of sets of globals used together. We accumulated 360279e3ee9SAhmed Bougacha // the number of times we encountered the sets (i.e., the number of blocks 361279e3ee9SAhmed Bougacha // that use that exact set of globals). 362279e3ee9SAhmed Bougacha // 363279e3ee9SAhmed Bougacha // Multiply that by the size of the set to give us a crude profitability 364279e3ee9SAhmed Bougacha // metric. 365279e3ee9SAhmed Bougacha std::sort(UsedGlobalSets.begin(), UsedGlobalSets.end(), 366279e3ee9SAhmed Bougacha [](const UsedGlobalSet &UGS1, const UsedGlobalSet &UGS2) { 367279e3ee9SAhmed Bougacha return UGS1.Globals.count() * UGS1.UsageCount < 368279e3ee9SAhmed Bougacha UGS2.Globals.count() * UGS2.UsageCount; 369279e3ee9SAhmed Bougacha }); 370279e3ee9SAhmed Bougacha 371279e3ee9SAhmed Bougacha // We can choose to merge all globals together, but ignore globals never used 372279e3ee9SAhmed Bougacha // with another global. This catches the obviously non-profitable cases of 373279e3ee9SAhmed Bougacha // having a single global, but is aggressive enough for any other case. 374279e3ee9SAhmed Bougacha if (GlobalMergeIgnoreSingleUse) { 375279e3ee9SAhmed Bougacha BitVector AllGlobals(Globals.size()); 376279e3ee9SAhmed Bougacha for (size_t i = 0, e = UsedGlobalSets.size(); i != e; ++i) { 377279e3ee9SAhmed Bougacha const UsedGlobalSet &UGS = UsedGlobalSets[e - i - 1]; 378279e3ee9SAhmed Bougacha if (UGS.UsageCount == 0) 379279e3ee9SAhmed Bougacha continue; 380279e3ee9SAhmed Bougacha if (UGS.Globals.count() > 1) 381279e3ee9SAhmed Bougacha AllGlobals |= UGS.Globals; 382279e3ee9SAhmed Bougacha } 383279e3ee9SAhmed Bougacha return doMerge(Globals, AllGlobals, M, isConst, AddrSpace); 384279e3ee9SAhmed Bougacha } 385279e3ee9SAhmed Bougacha 386279e3ee9SAhmed Bougacha // Starting from the sets with the best (=biggest) profitability, find a 387279e3ee9SAhmed Bougacha // good combination. 388279e3ee9SAhmed Bougacha // The ideal (and expensive) solution can only be found by trying all 389279e3ee9SAhmed Bougacha // combinations, looking for the one with the best profitability. 390279e3ee9SAhmed Bougacha // Don't be smart about it, and just pick the first compatible combination, 391279e3ee9SAhmed Bougacha // starting with the sets with the best profitability. 392279e3ee9SAhmed Bougacha BitVector PickedGlobals(Globals.size()); 393279e3ee9SAhmed Bougacha bool Changed = false; 394279e3ee9SAhmed Bougacha 395279e3ee9SAhmed Bougacha for (size_t i = 0, e = UsedGlobalSets.size(); i != e; ++i) { 396279e3ee9SAhmed Bougacha const UsedGlobalSet &UGS = UsedGlobalSets[e - i - 1]; 397279e3ee9SAhmed Bougacha if (UGS.UsageCount == 0) 398279e3ee9SAhmed Bougacha continue; 399279e3ee9SAhmed Bougacha if (PickedGlobals.anyCommon(UGS.Globals)) 400279e3ee9SAhmed Bougacha continue; 401279e3ee9SAhmed Bougacha PickedGlobals |= UGS.Globals; 402279e3ee9SAhmed Bougacha // If the set only contains one global, there's no point in merging. 403279e3ee9SAhmed Bougacha // Ignore the global for inclusion in other sets though, so keep it in 404279e3ee9SAhmed Bougacha // PickedGlobals. 405279e3ee9SAhmed Bougacha if (UGS.Globals.count() < 2) 406279e3ee9SAhmed Bougacha continue; 407279e3ee9SAhmed Bougacha Changed |= doMerge(Globals, UGS.Globals, M, isConst, AddrSpace); 408279e3ee9SAhmed Bougacha } 409279e3ee9SAhmed Bougacha 410279e3ee9SAhmed Bougacha return Changed; 411279e3ee9SAhmed Bougacha } 412279e3ee9SAhmed Bougacha 413279e3ee9SAhmed Bougacha bool GlobalMerge::doMerge(SmallVectorImpl<GlobalVariable *> &Globals, 414279e3ee9SAhmed Bougacha const BitVector &GlobalSet, Module &M, bool isConst, 415279e3ee9SAhmed Bougacha unsigned AddrSpace) const { 416279e3ee9SAhmed Bougacha 41796e92c1dSJiangning Liu Type *Int32Ty = Type::getInt32Ty(M.getContext()); 418f6727b0dSMehdi Amini auto &DL = M.getDataLayout(); 41996e92c1dSJiangning Liu 42096e92c1dSJiangning Liu assert(Globals.size() > 1); 42196e92c1dSJiangning Liu 422279e3ee9SAhmed Bougacha DEBUG(dbgs() << " Trying to merge set, starts with #" 423279e3ee9SAhmed Bougacha << GlobalSet.find_first() << "\n"); 424279e3ee9SAhmed Bougacha 425279e3ee9SAhmed Bougacha ssize_t i = GlobalSet.find_first(); 426279e3ee9SAhmed Bougacha while (i != -1) { 427279e3ee9SAhmed Bougacha ssize_t j = 0; 42896e92c1dSJiangning Liu uint64_t MergedSize = 0; 42996e92c1dSJiangning Liu std::vector<Type*> Tys; 43096e92c1dSJiangning Liu std::vector<Constant*> Inits; 43196e92c1dSJiangning Liu 43296e92c1dSJiangning Liu bool HasExternal = false; 43396e92c1dSJiangning Liu GlobalVariable *TheFirstExternal = 0; 434279e3ee9SAhmed Bougacha for (j = i; j != -1; j = GlobalSet.find_next(j)) { 43596e92c1dSJiangning Liu Type *Ty = Globals[j]->getType()->getElementType(); 436f6727b0dSMehdi Amini MergedSize += DL.getTypeAllocSize(Ty); 43796e92c1dSJiangning Liu if (MergedSize > MaxOffset) { 43896e92c1dSJiangning Liu break; 43996e92c1dSJiangning Liu } 44096e92c1dSJiangning Liu Tys.push_back(Ty); 44196e92c1dSJiangning Liu Inits.push_back(Globals[j]->getInitializer()); 44296e92c1dSJiangning Liu 44396e92c1dSJiangning Liu if (Globals[j]->hasExternalLinkage() && !HasExternal) { 44496e92c1dSJiangning Liu HasExternal = true; 44596e92c1dSJiangning Liu TheFirstExternal = Globals[j]; 44696e92c1dSJiangning Liu } 44796e92c1dSJiangning Liu } 44896e92c1dSJiangning Liu 44996e92c1dSJiangning Liu // If merged variables doesn't have external linkage, we needn't to expose 45096e92c1dSJiangning Liu // the symbol after merging. 45196e92c1dSJiangning Liu GlobalValue::LinkageTypes Linkage = HasExternal 45296e92c1dSJiangning Liu ? GlobalValue::ExternalLinkage 45396e92c1dSJiangning Liu : GlobalValue::InternalLinkage; 45496e92c1dSJiangning Liu 45596e92c1dSJiangning Liu StructType *MergedTy = StructType::get(M.getContext(), Tys); 45696e92c1dSJiangning Liu Constant *MergedInit = ConstantStruct::get(MergedTy, Inits); 45796e92c1dSJiangning Liu 458cccdadcaSBenjamin Kramer // If merged variables have external linkage, we use symbol name of the 459cccdadcaSBenjamin Kramer // first variable merged as the suffix of global symbol name. This would 460cccdadcaSBenjamin Kramer // be able to avoid the link-time naming conflict for globalm symbols. 46196e92c1dSJiangning Liu GlobalVariable *MergedGV = new GlobalVariable( 462cccdadcaSBenjamin Kramer M, MergedTy, isConst, Linkage, MergedInit, 463cccdadcaSBenjamin Kramer HasExternal ? "_MergedGlobals_" + TheFirstExternal->getName() 464cccdadcaSBenjamin Kramer : "_MergedGlobals", 465cccdadcaSBenjamin Kramer nullptr, GlobalVariable::NotThreadLocal, AddrSpace); 46696e92c1dSJiangning Liu 467279e3ee9SAhmed Bougacha for (ssize_t k = i, idx = 0; k != j; k = GlobalSet.find_next(k)) { 46896e92c1dSJiangning Liu GlobalValue::LinkageTypes Linkage = Globals[k]->getLinkage(); 46996e92c1dSJiangning Liu std::string Name = Globals[k]->getName(); 47096e92c1dSJiangning Liu 47196e92c1dSJiangning Liu Constant *Idx[2] = { 47296e92c1dSJiangning Liu ConstantInt::get(Int32Ty, 0), 473279e3ee9SAhmed Bougacha ConstantInt::get(Int32Ty, idx++) 47496e92c1dSJiangning Liu }; 4754a2e73b0SDavid Blaikie Constant *GEP = 4764a2e73b0SDavid Blaikie ConstantExpr::getInBoundsGetElementPtr(MergedTy, MergedGV, Idx); 47796e92c1dSJiangning Liu Globals[k]->replaceAllUsesWith(GEP); 47896e92c1dSJiangning Liu Globals[k]->eraseFromParent(); 47996e92c1dSJiangning Liu 48096e92c1dSJiangning Liu if (Linkage != GlobalValue::InternalLinkage) { 48196e92c1dSJiangning Liu // Generate a new alias... 48296e92c1dSJiangning Liu auto *PTy = cast<PointerType>(GEP->getType()); 483f64246beSDavid Blaikie GlobalAlias::create(PTy, Linkage, Name, GEP, &M); 48496e92c1dSJiangning Liu } 48596e92c1dSJiangning Liu 48696e92c1dSJiangning Liu NumMerged++; 48796e92c1dSJiangning Liu } 48896e92c1dSJiangning Liu i = j; 48996e92c1dSJiangning Liu } 49096e92c1dSJiangning Liu 49196e92c1dSJiangning Liu return true; 49296e92c1dSJiangning Liu } 49396e92c1dSJiangning Liu 49496e92c1dSJiangning Liu void GlobalMerge::collectUsedGlobalVariables(Module &M) { 49596e92c1dSJiangning Liu // Extract global variables from llvm.used array 49696e92c1dSJiangning Liu const GlobalVariable *GV = M.getGlobalVariable("llvm.used"); 49796e92c1dSJiangning Liu if (!GV || !GV->hasInitializer()) return; 49896e92c1dSJiangning Liu 49996e92c1dSJiangning Liu // Should be an array of 'i8*'. 50096e92c1dSJiangning Liu const ConstantArray *InitList = cast<ConstantArray>(GV->getInitializer()); 50196e92c1dSJiangning Liu 50296e92c1dSJiangning Liu for (unsigned i = 0, e = InitList->getNumOperands(); i != e; ++i) 50396e92c1dSJiangning Liu if (const GlobalVariable *G = 50496e92c1dSJiangning Liu dyn_cast<GlobalVariable>(InitList->getOperand(i)->stripPointerCasts())) 50596e92c1dSJiangning Liu MustKeepGlobalVariables.insert(G); 50696e92c1dSJiangning Liu } 50796e92c1dSJiangning Liu 50896e92c1dSJiangning Liu void GlobalMerge::setMustKeepGlobalVariables(Module &M) { 50996e92c1dSJiangning Liu collectUsedGlobalVariables(M); 51096e92c1dSJiangning Liu 51196e92c1dSJiangning Liu for (Module::iterator IFn = M.begin(), IEndFn = M.end(); IFn != IEndFn; 51296e92c1dSJiangning Liu ++IFn) { 51396e92c1dSJiangning Liu for (Function::iterator IBB = IFn->begin(), IEndBB = IFn->end(); 51496e92c1dSJiangning Liu IBB != IEndBB; ++IBB) { 51596e92c1dSJiangning Liu // Follow the invoke link to find the landing pad instruction 51696e92c1dSJiangning Liu const InvokeInst *II = dyn_cast<InvokeInst>(IBB->getTerminator()); 51796e92c1dSJiangning Liu if (!II) continue; 51896e92c1dSJiangning Liu 51996e92c1dSJiangning Liu const LandingPadInst *LPInst = II->getUnwindDest()->getLandingPadInst(); 52096e92c1dSJiangning Liu // Look for globals in the clauses of the landing pad instruction 52196e92c1dSJiangning Liu for (unsigned Idx = 0, NumClauses = LPInst->getNumClauses(); 52296e92c1dSJiangning Liu Idx != NumClauses; ++Idx) 52396e92c1dSJiangning Liu if (const GlobalVariable *GV = 52496e92c1dSJiangning Liu dyn_cast<GlobalVariable>(LPInst->getClause(Idx) 52596e92c1dSJiangning Liu ->stripPointerCasts())) 52696e92c1dSJiangning Liu MustKeepGlobalVariables.insert(GV); 52796e92c1dSJiangning Liu } 52896e92c1dSJiangning Liu } 52996e92c1dSJiangning Liu } 53096e92c1dSJiangning Liu 53196e92c1dSJiangning Liu bool GlobalMerge::doInitialization(Module &M) { 53296e92c1dSJiangning Liu if (!EnableGlobalMerge) 53396e92c1dSJiangning Liu return false; 53496e92c1dSJiangning Liu 535f6727b0dSMehdi Amini auto &DL = M.getDataLayout(); 53696e92c1dSJiangning Liu DenseMap<unsigned, SmallVector<GlobalVariable*, 16> > Globals, ConstGlobals, 53796e92c1dSJiangning Liu BSSGlobals; 53896e92c1dSJiangning Liu bool Changed = false; 53996e92c1dSJiangning Liu setMustKeepGlobalVariables(M); 54096e92c1dSJiangning Liu 54196e92c1dSJiangning Liu // Grab all non-const globals. 54296e92c1dSJiangning Liu for (Module::global_iterator I = M.global_begin(), 54396e92c1dSJiangning Liu E = M.global_end(); I != E; ++I) { 54496e92c1dSJiangning Liu // Merge is safe for "normal" internal or external globals only 54596e92c1dSJiangning Liu if (I->isDeclaration() || I->isThreadLocal() || I->hasSection()) 54696e92c1dSJiangning Liu continue; 54796e92c1dSJiangning Liu 5488b954241SJohn Brawn if (!(MergeExternalGlobals && I->hasExternalLinkage()) && 54996e92c1dSJiangning Liu !I->hasInternalLinkage()) 55096e92c1dSJiangning Liu continue; 55196e92c1dSJiangning Liu 55296e92c1dSJiangning Liu PointerType *PT = dyn_cast<PointerType>(I->getType()); 55396e92c1dSJiangning Liu assert(PT && "Global variable is not a pointer!"); 55496e92c1dSJiangning Liu 55596e92c1dSJiangning Liu unsigned AddressSpace = PT->getAddressSpace(); 55696e92c1dSJiangning Liu 55796e92c1dSJiangning Liu // Ignore fancy-aligned globals for now. 558f6727b0dSMehdi Amini unsigned Alignment = DL.getPreferredAlignment(I); 55996e92c1dSJiangning Liu Type *Ty = I->getType()->getElementType(); 560f6727b0dSMehdi Amini if (Alignment > DL.getABITypeAlignment(Ty)) 56196e92c1dSJiangning Liu continue; 56296e92c1dSJiangning Liu 56396e92c1dSJiangning Liu // Ignore all 'special' globals. 56496e92c1dSJiangning Liu if (I->getName().startswith("llvm.") || 56596e92c1dSJiangning Liu I->getName().startswith(".llvm.")) 56696e92c1dSJiangning Liu continue; 56796e92c1dSJiangning Liu 56896e92c1dSJiangning Liu // Ignore all "required" globals: 56996e92c1dSJiangning Liu if (isMustKeepGlobalVariable(I)) 57096e92c1dSJiangning Liu continue; 57196e92c1dSJiangning Liu 572f6727b0dSMehdi Amini if (DL.getTypeAllocSize(Ty) < MaxOffset) { 57396e92c1dSJiangning Liu if (TargetLoweringObjectFile::getKindForGlobal(I, *TM).isBSSLocal()) 57496e92c1dSJiangning Liu BSSGlobals[AddressSpace].push_back(I); 57596e92c1dSJiangning Liu else if (I->isConstant()) 57696e92c1dSJiangning Liu ConstGlobals[AddressSpace].push_back(I); 57796e92c1dSJiangning Liu else 57896e92c1dSJiangning Liu Globals[AddressSpace].push_back(I); 57996e92c1dSJiangning Liu } 58096e92c1dSJiangning Liu } 58196e92c1dSJiangning Liu 58296e92c1dSJiangning Liu for (DenseMap<unsigned, SmallVector<GlobalVariable*, 16> >::iterator 58396e92c1dSJiangning Liu I = Globals.begin(), E = Globals.end(); I != E; ++I) 58496e92c1dSJiangning Liu if (I->second.size() > 1) 58596e92c1dSJiangning Liu Changed |= doMerge(I->second, M, false, I->first); 58696e92c1dSJiangning Liu 58796e92c1dSJiangning Liu for (DenseMap<unsigned, SmallVector<GlobalVariable*, 16> >::iterator 58896e92c1dSJiangning Liu I = BSSGlobals.begin(), E = BSSGlobals.end(); I != E; ++I) 58996e92c1dSJiangning Liu if (I->second.size() > 1) 59096e92c1dSJiangning Liu Changed |= doMerge(I->second, M, false, I->first); 59196e92c1dSJiangning Liu 59296e92c1dSJiangning Liu if (EnableGlobalMergeOnConst) 59396e92c1dSJiangning Liu for (DenseMap<unsigned, SmallVector<GlobalVariable*, 16> >::iterator 59496e92c1dSJiangning Liu I = ConstGlobals.begin(), E = ConstGlobals.end(); I != E; ++I) 59596e92c1dSJiangning Liu if (I->second.size() > 1) 59696e92c1dSJiangning Liu Changed |= doMerge(I->second, M, true, I->first); 59796e92c1dSJiangning Liu 59896e92c1dSJiangning Liu return Changed; 59996e92c1dSJiangning Liu } 60096e92c1dSJiangning Liu 60196e92c1dSJiangning Liu bool GlobalMerge::runOnFunction(Function &F) { 60296e92c1dSJiangning Liu return false; 60396e92c1dSJiangning Liu } 60496e92c1dSJiangning Liu 60596e92c1dSJiangning Liu bool GlobalMerge::doFinalization(Module &M) { 60696e92c1dSJiangning Liu MustKeepGlobalVariables.clear(); 60796e92c1dSJiangning Liu return false; 60896e92c1dSJiangning Liu } 60996e92c1dSJiangning Liu 61082076412SAhmed Bougacha Pass *llvm::createGlobalMergePass(const TargetMachine *TM, unsigned Offset, 6118b954241SJohn Brawn bool OnlyOptimizeForSize, 6128b954241SJohn Brawn bool MergeExternalByDefault) { 6138b954241SJohn Brawn bool MergeExternal = (EnableGlobalMergeOnExternal == cl::BOU_UNSET) ? 6148b954241SJohn Brawn MergeExternalByDefault : (EnableGlobalMergeOnExternal == cl::BOU_TRUE); 6158b954241SJohn Brawn return new GlobalMerge(TM, Offset, OnlyOptimizeForSize, MergeExternal); 61696e92c1dSJiangning Liu } 617