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. 11196e92c1dSJiangning Liu static cl::opt<bool> 11296e92c1dSJiangning Liu EnableGlobalMergeOnExternal("global-merge-on-external", cl::Hidden, 11396e92c1dSJiangning Liu cl::desc("Enable global merge pass on external linkage"), 11496e92c1dSJiangning Liu cl::init(false)); 11596e92c1dSJiangning Liu 11696e92c1dSJiangning Liu STATISTIC(NumMerged, "Number of globals merged"); 11796e92c1dSJiangning Liu namespace { 11896e92c1dSJiangning Liu class GlobalMerge : public FunctionPass { 11996e92c1dSJiangning Liu const TargetMachine *TM; 120ed47b229SEric Christopher const DataLayout *DL; 121ed47b229SEric Christopher // FIXME: Infer the maximum possible offset depending on the actual users 122ed47b229SEric Christopher // (these max offsets are different for the users inside Thumb or ARM 123ed47b229SEric Christopher // functions), see the code that passes in the offset in the ARM backend 124ed47b229SEric Christopher // for more information. 125ed47b229SEric Christopher unsigned MaxOffset; 12696e92c1dSJiangning Liu 12796e92c1dSJiangning Liu bool doMerge(SmallVectorImpl<GlobalVariable*> &Globals, 12896e92c1dSJiangning Liu Module &M, bool isConst, unsigned AddrSpace) const; 129279e3ee9SAhmed Bougacha /// \brief Merge everything in \p Globals for which the corresponding bit 130279e3ee9SAhmed Bougacha /// in \p GlobalSet is set. 131279e3ee9SAhmed Bougacha bool doMerge(SmallVectorImpl<GlobalVariable *> &Globals, 132279e3ee9SAhmed Bougacha const BitVector &GlobalSet, Module &M, bool isConst, 133279e3ee9SAhmed Bougacha unsigned AddrSpace) const; 13496e92c1dSJiangning Liu 13596e92c1dSJiangning Liu /// \brief Check if the given variable has been identified as must keep 13696e92c1dSJiangning Liu /// \pre setMustKeepGlobalVariables must have been called on the Module that 13796e92c1dSJiangning Liu /// contains GV 13896e92c1dSJiangning Liu bool isMustKeepGlobalVariable(const GlobalVariable *GV) const { 13996e92c1dSJiangning Liu return MustKeepGlobalVariables.count(GV); 14096e92c1dSJiangning Liu } 14196e92c1dSJiangning Liu 14296e92c1dSJiangning Liu /// Collect every variables marked as "used" or used in a landing pad 14396e92c1dSJiangning Liu /// instruction for this Module. 14496e92c1dSJiangning Liu void setMustKeepGlobalVariables(Module &M); 14596e92c1dSJiangning Liu 14696e92c1dSJiangning Liu /// Collect every variables marked as "used" 14796e92c1dSJiangning Liu void collectUsedGlobalVariables(Module &M); 14896e92c1dSJiangning Liu 14996e92c1dSJiangning Liu /// Keep track of the GlobalVariable that must not be merged away 15096e92c1dSJiangning Liu SmallPtrSet<const GlobalVariable *, 16> MustKeepGlobalVariables; 15196e92c1dSJiangning Liu 15296e92c1dSJiangning Liu public: 15396e92c1dSJiangning Liu static char ID; // Pass identification, replacement for typeid. 154ed47b229SEric Christopher explicit GlobalMerge(const TargetMachine *TM = nullptr, 155ed47b229SEric Christopher unsigned MaximalOffset = 0) 156ed47b229SEric Christopher : FunctionPass(ID), TM(TM), DL(TM->getDataLayout()), 157ed47b229SEric Christopher MaxOffset(MaximalOffset) { 15896e92c1dSJiangning Liu initializeGlobalMergePass(*PassRegistry::getPassRegistry()); 15996e92c1dSJiangning Liu } 16096e92c1dSJiangning Liu 16196e92c1dSJiangning Liu bool doInitialization(Module &M) override; 16296e92c1dSJiangning Liu bool runOnFunction(Function &F) override; 16396e92c1dSJiangning Liu bool doFinalization(Module &M) override; 16496e92c1dSJiangning Liu 16596e92c1dSJiangning Liu const char *getPassName() const override { 16696e92c1dSJiangning Liu return "Merge internal globals"; 16796e92c1dSJiangning Liu } 16896e92c1dSJiangning Liu 16996e92c1dSJiangning Liu void getAnalysisUsage(AnalysisUsage &AU) const override { 17096e92c1dSJiangning Liu AU.setPreservesCFG(); 17196e92c1dSJiangning Liu FunctionPass::getAnalysisUsage(AU); 17296e92c1dSJiangning Liu } 17396e92c1dSJiangning Liu }; 17496e92c1dSJiangning Liu } // end anonymous namespace 17596e92c1dSJiangning Liu 17696e92c1dSJiangning Liu char GlobalMerge::ID = 0; 177ed47b229SEric Christopher INITIALIZE_PASS_BEGIN(GlobalMerge, "global-merge", "Merge global variables", 178ed47b229SEric Christopher false, false) 179ed47b229SEric Christopher INITIALIZE_PASS_END(GlobalMerge, "global-merge", "Merge global variables", 18096e92c1dSJiangning Liu false, false) 18196e92c1dSJiangning Liu 18296e92c1dSJiangning Liu bool GlobalMerge::doMerge(SmallVectorImpl<GlobalVariable*> &Globals, 18396e92c1dSJiangning Liu Module &M, bool isConst, unsigned AddrSpace) const { 18496e92c1dSJiangning Liu // FIXME: Find better heuristics 18596e92c1dSJiangning Liu std::stable_sort(Globals.begin(), Globals.end(), 186ed47b229SEric Christopher [this](const GlobalVariable *GV1, const GlobalVariable *GV2) { 18796e92c1dSJiangning Liu Type *Ty1 = cast<PointerType>(GV1->getType())->getElementType(); 18896e92c1dSJiangning Liu Type *Ty2 = cast<PointerType>(GV2->getType())->getElementType(); 18996e92c1dSJiangning Liu 19096e92c1dSJiangning Liu return (DL->getTypeAllocSize(Ty1) < DL->getTypeAllocSize(Ty2)); 19196e92c1dSJiangning Liu }); 19296e92c1dSJiangning Liu 193279e3ee9SAhmed Bougacha // If we want to just blindly group all globals together, do so. 194279e3ee9SAhmed Bougacha if (!GlobalMergeGroupByUse) { 195279e3ee9SAhmed Bougacha BitVector AllGlobals(Globals.size()); 196279e3ee9SAhmed Bougacha AllGlobals.set(); 197279e3ee9SAhmed Bougacha return doMerge(Globals, AllGlobals, M, isConst, AddrSpace); 198279e3ee9SAhmed Bougacha } 199279e3ee9SAhmed Bougacha 200279e3ee9SAhmed Bougacha // If we want to be smarter, look at all uses of each global, to try to 201279e3ee9SAhmed Bougacha // discover all sets of globals used together, and how many times each of 202279e3ee9SAhmed Bougacha // these sets occured. 203279e3ee9SAhmed Bougacha // 204279e3ee9SAhmed Bougacha // Keep this reasonably efficient, by having an append-only list of all sets 205279e3ee9SAhmed Bougacha // discovered so far (UsedGlobalSet), and mapping each "together-ness" unit of 206279e3ee9SAhmed Bougacha // code (currently, a Function) to the set of globals seen so far that are 207279e3ee9SAhmed Bougacha // used together in that unit (GlobalUsesByFunction). 208279e3ee9SAhmed Bougacha // 209279e3ee9SAhmed Bougacha // When we look at the Nth global, we now that any new set is either: 210279e3ee9SAhmed Bougacha // - the singleton set {N}, containing this global only, or 211279e3ee9SAhmed Bougacha // - the union of {N} and a previously-discovered set, containing some 212279e3ee9SAhmed Bougacha // combination of the previous N-1 globals. 213279e3ee9SAhmed Bougacha // Using that knowledge, when looking at the Nth global, we can keep: 214279e3ee9SAhmed Bougacha // - a reference to the singleton set {N} (CurGVOnlySetIdx) 215279e3ee9SAhmed Bougacha // - a list mapping each previous set to its union with {N} (EncounteredUGS), 216279e3ee9SAhmed Bougacha // if it actually occurs. 217279e3ee9SAhmed Bougacha 218279e3ee9SAhmed Bougacha // We keep track of the sets of globals used together "close enough". 219279e3ee9SAhmed Bougacha struct UsedGlobalSet { 220279e3ee9SAhmed Bougacha UsedGlobalSet(size_t Size) : Globals(Size), UsageCount(1) {} 221279e3ee9SAhmed Bougacha BitVector Globals; 222279e3ee9SAhmed Bougacha unsigned UsageCount; 223279e3ee9SAhmed Bougacha }; 224279e3ee9SAhmed Bougacha 225279e3ee9SAhmed Bougacha // Each set is unique in UsedGlobalSets. 226279e3ee9SAhmed Bougacha std::vector<UsedGlobalSet> UsedGlobalSets; 227279e3ee9SAhmed Bougacha 228279e3ee9SAhmed Bougacha // Avoid repeating the create-global-set pattern. 229279e3ee9SAhmed Bougacha auto CreateGlobalSet = [&]() -> UsedGlobalSet & { 230279e3ee9SAhmed Bougacha UsedGlobalSets.emplace_back(Globals.size()); 231279e3ee9SAhmed Bougacha return UsedGlobalSets.back(); 232279e3ee9SAhmed Bougacha }; 233279e3ee9SAhmed Bougacha 234279e3ee9SAhmed Bougacha // The first set is the empty set. 235279e3ee9SAhmed Bougacha CreateGlobalSet().UsageCount = 0; 236279e3ee9SAhmed Bougacha 237279e3ee9SAhmed Bougacha // We define "close enough" to be "in the same function". 238279e3ee9SAhmed Bougacha // FIXME: Grouping uses by function is way too aggressive, so we should have 239279e3ee9SAhmed Bougacha // a better metric for distance between uses. 240279e3ee9SAhmed Bougacha // The obvious alternative would be to group by BasicBlock, but that's in 241279e3ee9SAhmed Bougacha // turn too conservative.. 242279e3ee9SAhmed Bougacha // Anything in between wouldn't be trivial to compute, so just stick with 243279e3ee9SAhmed Bougacha // per-function grouping. 244279e3ee9SAhmed Bougacha 245279e3ee9SAhmed Bougacha // The value type is an index into UsedGlobalSets. 246279e3ee9SAhmed Bougacha // The default (0) conveniently points to the empty set. 247279e3ee9SAhmed Bougacha DenseMap<Function *, size_t /*UsedGlobalSetIdx*/> GlobalUsesByFunction; 248279e3ee9SAhmed Bougacha 249279e3ee9SAhmed Bougacha // Now, look at each merge-eligible global in turn. 250279e3ee9SAhmed Bougacha 251279e3ee9SAhmed Bougacha // Keep track of the sets we already encountered to which we added the 252279e3ee9SAhmed Bougacha // current global. 253279e3ee9SAhmed Bougacha // Each element matches the same-index element in UsedGlobalSets. 254279e3ee9SAhmed Bougacha // This lets us efficiently tell whether a set has already been expanded to 255279e3ee9SAhmed Bougacha // include the current global. 256279e3ee9SAhmed Bougacha std::vector<size_t> EncounteredUGS; 257279e3ee9SAhmed Bougacha 258279e3ee9SAhmed Bougacha for (size_t GI = 0, GE = Globals.size(); GI != GE; ++GI) { 259279e3ee9SAhmed Bougacha GlobalVariable *GV = Globals[GI]; 260279e3ee9SAhmed Bougacha 261279e3ee9SAhmed Bougacha // Reset the encountered sets for this global... 262279e3ee9SAhmed Bougacha std::fill(EncounteredUGS.begin(), EncounteredUGS.end(), 0); 263279e3ee9SAhmed Bougacha // ...and grow it in case we created new sets for the previous global. 264279e3ee9SAhmed Bougacha EncounteredUGS.resize(UsedGlobalSets.size()); 265279e3ee9SAhmed Bougacha 266279e3ee9SAhmed Bougacha // We might need to create a set that only consists of the current global. 267279e3ee9SAhmed Bougacha // Keep track of its index into UsedGlobalSets. 268279e3ee9SAhmed Bougacha size_t CurGVOnlySetIdx = 0; 269279e3ee9SAhmed Bougacha 270279e3ee9SAhmed Bougacha // For each global, look at all its Uses. 271279e3ee9SAhmed Bougacha for (auto &U : GV->uses()) { 272279e3ee9SAhmed Bougacha // This Use might be a ConstantExpr. We're interested in Instruction 273279e3ee9SAhmed Bougacha // users, so look through ConstantExpr... 274279e3ee9SAhmed Bougacha Use *UI, *UE; 275279e3ee9SAhmed Bougacha if (ConstantExpr *CE = dyn_cast<ConstantExpr>(U.getUser())) { 276279e3ee9SAhmed Bougacha UI = &*CE->use_begin(); 277279e3ee9SAhmed Bougacha UE = nullptr; 278279e3ee9SAhmed Bougacha } else if (isa<Instruction>(U.getUser())) { 279279e3ee9SAhmed Bougacha UI = &U; 280279e3ee9SAhmed Bougacha UE = UI->getNext(); 281279e3ee9SAhmed Bougacha } else { 282279e3ee9SAhmed Bougacha continue; 283279e3ee9SAhmed Bougacha } 284279e3ee9SAhmed Bougacha 285279e3ee9SAhmed Bougacha // ...to iterate on all the instruction users of the global. 286279e3ee9SAhmed Bougacha // Note that we iterate on Uses and not on Users to be able to getNext(). 287279e3ee9SAhmed Bougacha for (; UI != UE; UI = UI->getNext()) { 288279e3ee9SAhmed Bougacha Instruction *I = dyn_cast<Instruction>(UI->getUser()); 289279e3ee9SAhmed Bougacha if (!I) 290279e3ee9SAhmed Bougacha continue; 291279e3ee9SAhmed Bougacha 292279e3ee9SAhmed Bougacha Function *ParentFn = I->getParent()->getParent(); 293279e3ee9SAhmed Bougacha size_t UGSIdx = GlobalUsesByFunction[ParentFn]; 294279e3ee9SAhmed Bougacha 295279e3ee9SAhmed Bougacha // If this is the first global the basic block uses, map it to the set 296279e3ee9SAhmed Bougacha // consisting of this global only. 297279e3ee9SAhmed Bougacha if (!UGSIdx) { 298279e3ee9SAhmed Bougacha // If that set doesn't exist yet, create it. 299279e3ee9SAhmed Bougacha if (!CurGVOnlySetIdx) { 300279e3ee9SAhmed Bougacha CurGVOnlySetIdx = UsedGlobalSets.size(); 301279e3ee9SAhmed Bougacha CreateGlobalSet().Globals.set(GI); 302279e3ee9SAhmed Bougacha } else { 303279e3ee9SAhmed Bougacha ++UsedGlobalSets[CurGVOnlySetIdx].UsageCount; 304279e3ee9SAhmed Bougacha } 305279e3ee9SAhmed Bougacha 306279e3ee9SAhmed Bougacha GlobalUsesByFunction[ParentFn] = CurGVOnlySetIdx; 307279e3ee9SAhmed Bougacha continue; 308279e3ee9SAhmed Bougacha } 309279e3ee9SAhmed Bougacha 310279e3ee9SAhmed Bougacha // If we already encountered this BB, just increment the counter. 311279e3ee9SAhmed Bougacha if (UsedGlobalSets[UGSIdx].Globals.test(GI)) { 312279e3ee9SAhmed Bougacha ++UsedGlobalSets[UGSIdx].UsageCount; 313279e3ee9SAhmed Bougacha continue; 314279e3ee9SAhmed Bougacha } 315279e3ee9SAhmed Bougacha 316279e3ee9SAhmed Bougacha // If not, the previous set wasn't actually used in this function. 317279e3ee9SAhmed Bougacha --UsedGlobalSets[UGSIdx].UsageCount; 318279e3ee9SAhmed Bougacha 319279e3ee9SAhmed Bougacha // If we already expanded the previous set to include this global, just 320279e3ee9SAhmed Bougacha // reuse that expanded set. 321279e3ee9SAhmed Bougacha if (size_t ExpandedIdx = EncounteredUGS[UGSIdx]) { 322279e3ee9SAhmed Bougacha ++UsedGlobalSets[ExpandedIdx].UsageCount; 323279e3ee9SAhmed Bougacha GlobalUsesByFunction[ParentFn] = ExpandedIdx; 324279e3ee9SAhmed Bougacha continue; 325279e3ee9SAhmed Bougacha } 326279e3ee9SAhmed Bougacha 327279e3ee9SAhmed Bougacha // If not, create a new set consisting of the union of the previous set 328279e3ee9SAhmed Bougacha // and this global. Mark it as encountered, so we can reuse it later. 329279e3ee9SAhmed Bougacha GlobalUsesByFunction[ParentFn] = EncounteredUGS[UGSIdx] = 330279e3ee9SAhmed Bougacha UsedGlobalSets.size(); 331279e3ee9SAhmed Bougacha 332279e3ee9SAhmed Bougacha UsedGlobalSet &NewUGS = CreateGlobalSet(); 333279e3ee9SAhmed Bougacha NewUGS.Globals.set(GI); 334279e3ee9SAhmed Bougacha NewUGS.Globals |= UsedGlobalSets[UGSIdx].Globals; 335279e3ee9SAhmed Bougacha } 336279e3ee9SAhmed Bougacha } 337279e3ee9SAhmed Bougacha } 338279e3ee9SAhmed Bougacha 339279e3ee9SAhmed Bougacha // Now we found a bunch of sets of globals used together. We accumulated 340279e3ee9SAhmed Bougacha // the number of times we encountered the sets (i.e., the number of blocks 341279e3ee9SAhmed Bougacha // that use that exact set of globals). 342279e3ee9SAhmed Bougacha // 343279e3ee9SAhmed Bougacha // Multiply that by the size of the set to give us a crude profitability 344279e3ee9SAhmed Bougacha // metric. 345279e3ee9SAhmed Bougacha std::sort(UsedGlobalSets.begin(), UsedGlobalSets.end(), 346279e3ee9SAhmed Bougacha [](const UsedGlobalSet &UGS1, const UsedGlobalSet &UGS2) { 347279e3ee9SAhmed Bougacha return UGS1.Globals.count() * UGS1.UsageCount < 348279e3ee9SAhmed Bougacha UGS2.Globals.count() * UGS2.UsageCount; 349279e3ee9SAhmed Bougacha }); 350279e3ee9SAhmed Bougacha 351279e3ee9SAhmed Bougacha // We can choose to merge all globals together, but ignore globals never used 352279e3ee9SAhmed Bougacha // with another global. This catches the obviously non-profitable cases of 353279e3ee9SAhmed Bougacha // having a single global, but is aggressive enough for any other case. 354279e3ee9SAhmed Bougacha if (GlobalMergeIgnoreSingleUse) { 355279e3ee9SAhmed Bougacha BitVector AllGlobals(Globals.size()); 356279e3ee9SAhmed Bougacha for (size_t i = 0, e = UsedGlobalSets.size(); i != e; ++i) { 357279e3ee9SAhmed Bougacha const UsedGlobalSet &UGS = UsedGlobalSets[e - i - 1]; 358279e3ee9SAhmed Bougacha if (UGS.UsageCount == 0) 359279e3ee9SAhmed Bougacha continue; 360279e3ee9SAhmed Bougacha if (UGS.Globals.count() > 1) 361279e3ee9SAhmed Bougacha AllGlobals |= UGS.Globals; 362279e3ee9SAhmed Bougacha } 363279e3ee9SAhmed Bougacha return doMerge(Globals, AllGlobals, M, isConst, AddrSpace); 364279e3ee9SAhmed Bougacha } 365279e3ee9SAhmed Bougacha 366279e3ee9SAhmed Bougacha // Starting from the sets with the best (=biggest) profitability, find a 367279e3ee9SAhmed Bougacha // good combination. 368279e3ee9SAhmed Bougacha // The ideal (and expensive) solution can only be found by trying all 369279e3ee9SAhmed Bougacha // combinations, looking for the one with the best profitability. 370279e3ee9SAhmed Bougacha // Don't be smart about it, and just pick the first compatible combination, 371279e3ee9SAhmed Bougacha // starting with the sets with the best profitability. 372279e3ee9SAhmed Bougacha BitVector PickedGlobals(Globals.size()); 373279e3ee9SAhmed Bougacha bool Changed = false; 374279e3ee9SAhmed Bougacha 375279e3ee9SAhmed Bougacha for (size_t i = 0, e = UsedGlobalSets.size(); i != e; ++i) { 376279e3ee9SAhmed Bougacha const UsedGlobalSet &UGS = UsedGlobalSets[e - i - 1]; 377279e3ee9SAhmed Bougacha if (UGS.UsageCount == 0) 378279e3ee9SAhmed Bougacha continue; 379279e3ee9SAhmed Bougacha if (PickedGlobals.anyCommon(UGS.Globals)) 380279e3ee9SAhmed Bougacha continue; 381279e3ee9SAhmed Bougacha PickedGlobals |= UGS.Globals; 382279e3ee9SAhmed Bougacha // If the set only contains one global, there's no point in merging. 383279e3ee9SAhmed Bougacha // Ignore the global for inclusion in other sets though, so keep it in 384279e3ee9SAhmed Bougacha // PickedGlobals. 385279e3ee9SAhmed Bougacha if (UGS.Globals.count() < 2) 386279e3ee9SAhmed Bougacha continue; 387279e3ee9SAhmed Bougacha Changed |= doMerge(Globals, UGS.Globals, M, isConst, AddrSpace); 388279e3ee9SAhmed Bougacha } 389279e3ee9SAhmed Bougacha 390279e3ee9SAhmed Bougacha return Changed; 391279e3ee9SAhmed Bougacha } 392279e3ee9SAhmed Bougacha 393279e3ee9SAhmed Bougacha bool GlobalMerge::doMerge(SmallVectorImpl<GlobalVariable *> &Globals, 394279e3ee9SAhmed Bougacha const BitVector &GlobalSet, Module &M, bool isConst, 395279e3ee9SAhmed Bougacha unsigned AddrSpace) const { 396279e3ee9SAhmed Bougacha 39796e92c1dSJiangning Liu Type *Int32Ty = Type::getInt32Ty(M.getContext()); 39896e92c1dSJiangning Liu 39996e92c1dSJiangning Liu assert(Globals.size() > 1); 40096e92c1dSJiangning Liu 401279e3ee9SAhmed Bougacha DEBUG(dbgs() << " Trying to merge set, starts with #" 402279e3ee9SAhmed Bougacha << GlobalSet.find_first() << "\n"); 403279e3ee9SAhmed Bougacha 404279e3ee9SAhmed Bougacha ssize_t i = GlobalSet.find_first(); 405279e3ee9SAhmed Bougacha while (i != -1) { 406279e3ee9SAhmed Bougacha ssize_t j = 0; 40796e92c1dSJiangning Liu uint64_t MergedSize = 0; 40896e92c1dSJiangning Liu std::vector<Type*> Tys; 40996e92c1dSJiangning Liu std::vector<Constant*> Inits; 41096e92c1dSJiangning Liu 41196e92c1dSJiangning Liu bool HasExternal = false; 41296e92c1dSJiangning Liu GlobalVariable *TheFirstExternal = 0; 413279e3ee9SAhmed Bougacha for (j = i; j != -1; j = GlobalSet.find_next(j)) { 41496e92c1dSJiangning Liu Type *Ty = Globals[j]->getType()->getElementType(); 41596e92c1dSJiangning Liu MergedSize += DL->getTypeAllocSize(Ty); 41696e92c1dSJiangning Liu if (MergedSize > MaxOffset) { 41796e92c1dSJiangning Liu break; 41896e92c1dSJiangning Liu } 41996e92c1dSJiangning Liu Tys.push_back(Ty); 42096e92c1dSJiangning Liu Inits.push_back(Globals[j]->getInitializer()); 42196e92c1dSJiangning Liu 42296e92c1dSJiangning Liu if (Globals[j]->hasExternalLinkage() && !HasExternal) { 42396e92c1dSJiangning Liu HasExternal = true; 42496e92c1dSJiangning Liu TheFirstExternal = Globals[j]; 42596e92c1dSJiangning Liu } 42696e92c1dSJiangning Liu } 42796e92c1dSJiangning Liu 42896e92c1dSJiangning Liu // If merged variables doesn't have external linkage, we needn't to expose 42996e92c1dSJiangning Liu // the symbol after merging. 43096e92c1dSJiangning Liu GlobalValue::LinkageTypes Linkage = HasExternal 43196e92c1dSJiangning Liu ? GlobalValue::ExternalLinkage 43296e92c1dSJiangning Liu : GlobalValue::InternalLinkage; 43396e92c1dSJiangning Liu 43496e92c1dSJiangning Liu StructType *MergedTy = StructType::get(M.getContext(), Tys); 43596e92c1dSJiangning Liu Constant *MergedInit = ConstantStruct::get(MergedTy, Inits); 43696e92c1dSJiangning Liu 437cccdadcaSBenjamin Kramer // If merged variables have external linkage, we use symbol name of the 438cccdadcaSBenjamin Kramer // first variable merged as the suffix of global symbol name. This would 439cccdadcaSBenjamin Kramer // be able to avoid the link-time naming conflict for globalm symbols. 44096e92c1dSJiangning Liu GlobalVariable *MergedGV = new GlobalVariable( 441cccdadcaSBenjamin Kramer M, MergedTy, isConst, Linkage, MergedInit, 442cccdadcaSBenjamin Kramer HasExternal ? "_MergedGlobals_" + TheFirstExternal->getName() 443cccdadcaSBenjamin Kramer : "_MergedGlobals", 444cccdadcaSBenjamin Kramer nullptr, GlobalVariable::NotThreadLocal, AddrSpace); 44596e92c1dSJiangning Liu 446279e3ee9SAhmed Bougacha for (ssize_t k = i, idx = 0; k != j; k = GlobalSet.find_next(k)) { 44796e92c1dSJiangning Liu GlobalValue::LinkageTypes Linkage = Globals[k]->getLinkage(); 44896e92c1dSJiangning Liu std::string Name = Globals[k]->getName(); 44996e92c1dSJiangning Liu 45096e92c1dSJiangning Liu Constant *Idx[2] = { 45196e92c1dSJiangning Liu ConstantInt::get(Int32Ty, 0), 452279e3ee9SAhmed Bougacha ConstantInt::get(Int32Ty, idx++) 45396e92c1dSJiangning Liu }; 4544a2e73b0SDavid Blaikie Constant *GEP = 4554a2e73b0SDavid Blaikie ConstantExpr::getInBoundsGetElementPtr(MergedTy, MergedGV, Idx); 45696e92c1dSJiangning Liu Globals[k]->replaceAllUsesWith(GEP); 45796e92c1dSJiangning Liu Globals[k]->eraseFromParent(); 45896e92c1dSJiangning Liu 45996e92c1dSJiangning Liu if (Linkage != GlobalValue::InternalLinkage) { 46096e92c1dSJiangning Liu // Generate a new alias... 46196e92c1dSJiangning Liu auto *PTy = cast<PointerType>(GEP->getType()); 462*f64246beSDavid Blaikie GlobalAlias::create(PTy, Linkage, Name, GEP, &M); 46396e92c1dSJiangning Liu } 46496e92c1dSJiangning Liu 46596e92c1dSJiangning Liu NumMerged++; 46696e92c1dSJiangning Liu } 46796e92c1dSJiangning Liu i = j; 46896e92c1dSJiangning Liu } 46996e92c1dSJiangning Liu 47096e92c1dSJiangning Liu return true; 47196e92c1dSJiangning Liu } 47296e92c1dSJiangning Liu 47396e92c1dSJiangning Liu void GlobalMerge::collectUsedGlobalVariables(Module &M) { 47496e92c1dSJiangning Liu // Extract global variables from llvm.used array 47596e92c1dSJiangning Liu const GlobalVariable *GV = M.getGlobalVariable("llvm.used"); 47696e92c1dSJiangning Liu if (!GV || !GV->hasInitializer()) return; 47796e92c1dSJiangning Liu 47896e92c1dSJiangning Liu // Should be an array of 'i8*'. 47996e92c1dSJiangning Liu const ConstantArray *InitList = cast<ConstantArray>(GV->getInitializer()); 48096e92c1dSJiangning Liu 48196e92c1dSJiangning Liu for (unsigned i = 0, e = InitList->getNumOperands(); i != e; ++i) 48296e92c1dSJiangning Liu if (const GlobalVariable *G = 48396e92c1dSJiangning Liu dyn_cast<GlobalVariable>(InitList->getOperand(i)->stripPointerCasts())) 48496e92c1dSJiangning Liu MustKeepGlobalVariables.insert(G); 48596e92c1dSJiangning Liu } 48696e92c1dSJiangning Liu 48796e92c1dSJiangning Liu void GlobalMerge::setMustKeepGlobalVariables(Module &M) { 48896e92c1dSJiangning Liu collectUsedGlobalVariables(M); 48996e92c1dSJiangning Liu 49096e92c1dSJiangning Liu for (Module::iterator IFn = M.begin(), IEndFn = M.end(); IFn != IEndFn; 49196e92c1dSJiangning Liu ++IFn) { 49296e92c1dSJiangning Liu for (Function::iterator IBB = IFn->begin(), IEndBB = IFn->end(); 49396e92c1dSJiangning Liu IBB != IEndBB; ++IBB) { 49496e92c1dSJiangning Liu // Follow the invoke link to find the landing pad instruction 49596e92c1dSJiangning Liu const InvokeInst *II = dyn_cast<InvokeInst>(IBB->getTerminator()); 49696e92c1dSJiangning Liu if (!II) continue; 49796e92c1dSJiangning Liu 49896e92c1dSJiangning Liu const LandingPadInst *LPInst = II->getUnwindDest()->getLandingPadInst(); 49996e92c1dSJiangning Liu // Look for globals in the clauses of the landing pad instruction 50096e92c1dSJiangning Liu for (unsigned Idx = 0, NumClauses = LPInst->getNumClauses(); 50196e92c1dSJiangning Liu Idx != NumClauses; ++Idx) 50296e92c1dSJiangning Liu if (const GlobalVariable *GV = 50396e92c1dSJiangning Liu dyn_cast<GlobalVariable>(LPInst->getClause(Idx) 50496e92c1dSJiangning Liu ->stripPointerCasts())) 50596e92c1dSJiangning Liu MustKeepGlobalVariables.insert(GV); 50696e92c1dSJiangning Liu } 50796e92c1dSJiangning Liu } 50896e92c1dSJiangning Liu } 50996e92c1dSJiangning Liu 51096e92c1dSJiangning Liu bool GlobalMerge::doInitialization(Module &M) { 51196e92c1dSJiangning Liu if (!EnableGlobalMerge) 51296e92c1dSJiangning Liu return false; 51396e92c1dSJiangning Liu 51496e92c1dSJiangning Liu DenseMap<unsigned, SmallVector<GlobalVariable*, 16> > Globals, ConstGlobals, 51596e92c1dSJiangning Liu BSSGlobals; 51696e92c1dSJiangning Liu bool Changed = false; 51796e92c1dSJiangning Liu setMustKeepGlobalVariables(M); 51896e92c1dSJiangning Liu 51996e92c1dSJiangning Liu // Grab all non-const globals. 52096e92c1dSJiangning Liu for (Module::global_iterator I = M.global_begin(), 52196e92c1dSJiangning Liu E = M.global_end(); I != E; ++I) { 52296e92c1dSJiangning Liu // Merge is safe for "normal" internal or external globals only 52396e92c1dSJiangning Liu if (I->isDeclaration() || I->isThreadLocal() || I->hasSection()) 52496e92c1dSJiangning Liu continue; 52596e92c1dSJiangning Liu 52696e92c1dSJiangning Liu if (!(EnableGlobalMergeOnExternal && I->hasExternalLinkage()) && 52796e92c1dSJiangning Liu !I->hasInternalLinkage()) 52896e92c1dSJiangning Liu continue; 52996e92c1dSJiangning Liu 53096e92c1dSJiangning Liu PointerType *PT = dyn_cast<PointerType>(I->getType()); 53196e92c1dSJiangning Liu assert(PT && "Global variable is not a pointer!"); 53296e92c1dSJiangning Liu 53396e92c1dSJiangning Liu unsigned AddressSpace = PT->getAddressSpace(); 53496e92c1dSJiangning Liu 53596e92c1dSJiangning Liu // Ignore fancy-aligned globals for now. 53696e92c1dSJiangning Liu unsigned Alignment = DL->getPreferredAlignment(I); 53796e92c1dSJiangning Liu Type *Ty = I->getType()->getElementType(); 53896e92c1dSJiangning Liu if (Alignment > DL->getABITypeAlignment(Ty)) 53996e92c1dSJiangning Liu continue; 54096e92c1dSJiangning Liu 54196e92c1dSJiangning Liu // Ignore all 'special' globals. 54296e92c1dSJiangning Liu if (I->getName().startswith("llvm.") || 54396e92c1dSJiangning Liu I->getName().startswith(".llvm.")) 54496e92c1dSJiangning Liu continue; 54596e92c1dSJiangning Liu 54696e92c1dSJiangning Liu // Ignore all "required" globals: 54796e92c1dSJiangning Liu if (isMustKeepGlobalVariable(I)) 54896e92c1dSJiangning Liu continue; 54996e92c1dSJiangning Liu 55096e92c1dSJiangning Liu if (DL->getTypeAllocSize(Ty) < MaxOffset) { 55196e92c1dSJiangning Liu if (TargetLoweringObjectFile::getKindForGlobal(I, *TM).isBSSLocal()) 55296e92c1dSJiangning Liu BSSGlobals[AddressSpace].push_back(I); 55396e92c1dSJiangning Liu else if (I->isConstant()) 55496e92c1dSJiangning Liu ConstGlobals[AddressSpace].push_back(I); 55596e92c1dSJiangning Liu else 55696e92c1dSJiangning Liu Globals[AddressSpace].push_back(I); 55796e92c1dSJiangning Liu } 55896e92c1dSJiangning Liu } 55996e92c1dSJiangning Liu 56096e92c1dSJiangning Liu for (DenseMap<unsigned, SmallVector<GlobalVariable*, 16> >::iterator 56196e92c1dSJiangning Liu I = Globals.begin(), E = Globals.end(); I != E; ++I) 56296e92c1dSJiangning Liu if (I->second.size() > 1) 56396e92c1dSJiangning Liu Changed |= doMerge(I->second, M, false, I->first); 56496e92c1dSJiangning Liu 56596e92c1dSJiangning Liu for (DenseMap<unsigned, SmallVector<GlobalVariable*, 16> >::iterator 56696e92c1dSJiangning Liu I = BSSGlobals.begin(), E = BSSGlobals.end(); I != E; ++I) 56796e92c1dSJiangning Liu if (I->second.size() > 1) 56896e92c1dSJiangning Liu Changed |= doMerge(I->second, M, false, I->first); 56996e92c1dSJiangning Liu 57096e92c1dSJiangning Liu if (EnableGlobalMergeOnConst) 57196e92c1dSJiangning Liu for (DenseMap<unsigned, SmallVector<GlobalVariable*, 16> >::iterator 57296e92c1dSJiangning Liu I = ConstGlobals.begin(), E = ConstGlobals.end(); I != E; ++I) 57396e92c1dSJiangning Liu if (I->second.size() > 1) 57496e92c1dSJiangning Liu Changed |= doMerge(I->second, M, true, I->first); 57596e92c1dSJiangning Liu 57696e92c1dSJiangning Liu return Changed; 57796e92c1dSJiangning Liu } 57896e92c1dSJiangning Liu 57996e92c1dSJiangning Liu bool GlobalMerge::runOnFunction(Function &F) { 58096e92c1dSJiangning Liu return false; 58196e92c1dSJiangning Liu } 58296e92c1dSJiangning Liu 58396e92c1dSJiangning Liu bool GlobalMerge::doFinalization(Module &M) { 58496e92c1dSJiangning Liu MustKeepGlobalVariables.clear(); 58596e92c1dSJiangning Liu return false; 58696e92c1dSJiangning Liu } 58796e92c1dSJiangning Liu 588ed47b229SEric Christopher Pass *llvm::createGlobalMergePass(const TargetMachine *TM, unsigned Offset) { 589ed47b229SEric Christopher return new GlobalMerge(TM, Offset); 59096e92c1dSJiangning Liu } 591