10b57cec5SDimitry Andric //===- GlobalMerge.cpp - Internal globals merging -------------------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // This pass merges globals with internal linkage into one. This way all the 100b57cec5SDimitry Andric // globals which were merged into a biggest one can be addressed using offsets 110b57cec5SDimitry Andric // from the same base pointer (no need for separate base pointer for each of the 120b57cec5SDimitry Andric // global). Such a transformation can significantly reduce the register pressure 130b57cec5SDimitry Andric // when many globals are involved. 140b57cec5SDimitry Andric // 150b57cec5SDimitry Andric // For example, consider the code which touches several global variables at 160b57cec5SDimitry Andric // once: 170b57cec5SDimitry Andric // 180b57cec5SDimitry Andric // static int foo[N], bar[N], baz[N]; 190b57cec5SDimitry Andric // 200b57cec5SDimitry Andric // for (i = 0; i < N; ++i) { 210b57cec5SDimitry Andric // foo[i] = bar[i] * baz[i]; 220b57cec5SDimitry Andric // } 230b57cec5SDimitry Andric // 240b57cec5SDimitry Andric // On ARM the addresses of 3 arrays should be kept in the registers, thus 250b57cec5SDimitry Andric // this code has quite large register pressure (loop body): 260b57cec5SDimitry Andric // 270b57cec5SDimitry Andric // ldr r1, [r5], #4 280b57cec5SDimitry Andric // ldr r2, [r6], #4 290b57cec5SDimitry Andric // mul r1, r2, r1 300b57cec5SDimitry Andric // str r1, [r0], #4 310b57cec5SDimitry Andric // 320b57cec5SDimitry Andric // Pass converts the code to something like: 330b57cec5SDimitry Andric // 340b57cec5SDimitry Andric // static struct { 350b57cec5SDimitry Andric // int foo[N]; 360b57cec5SDimitry Andric // int bar[N]; 370b57cec5SDimitry Andric // int baz[N]; 380b57cec5SDimitry Andric // } merged; 390b57cec5SDimitry Andric // 400b57cec5SDimitry Andric // for (i = 0; i < N; ++i) { 410b57cec5SDimitry Andric // merged.foo[i] = merged.bar[i] * merged.baz[i]; 420b57cec5SDimitry Andric // } 430b57cec5SDimitry Andric // 440b57cec5SDimitry Andric // and in ARM code this becomes: 450b57cec5SDimitry Andric // 460b57cec5SDimitry Andric // ldr r0, [r5, #40] 470b57cec5SDimitry Andric // ldr r1, [r5, #80] 480b57cec5SDimitry Andric // mul r0, r1, r0 490b57cec5SDimitry Andric // str r0, [r5], #4 500b57cec5SDimitry Andric // 510b57cec5SDimitry Andric // note that we saved 2 registers here almostly "for free". 520b57cec5SDimitry Andric // 530b57cec5SDimitry Andric // However, merging globals can have tradeoffs: 540b57cec5SDimitry Andric // - it confuses debuggers, tools, and users 550b57cec5SDimitry Andric // - it makes linker optimizations less useful (order files, LOHs, ...) 560b57cec5SDimitry Andric // - it forces usage of indexed addressing (which isn't necessarily "free") 570b57cec5SDimitry Andric // - it can increase register pressure when the uses are disparate enough. 580b57cec5SDimitry Andric // 590b57cec5SDimitry Andric // We use heuristics to discover the best global grouping we can (cf cl::opts). 600b57cec5SDimitry Andric // 610b57cec5SDimitry Andric // ===---------------------------------------------------------------------===// 620b57cec5SDimitry Andric 637a6dacacSDimitry Andric #include "llvm/CodeGen/GlobalMerge.h" 640b57cec5SDimitry Andric #include "llvm/ADT/BitVector.h" 650b57cec5SDimitry Andric #include "llvm/ADT/DenseMap.h" 66*0fca6ea1SDimitry Andric #include "llvm/ADT/MapVector.h" 67bdd1243dSDimitry Andric #include "llvm/ADT/SetVector.h" 680b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h" 690b57cec5SDimitry Andric #include "llvm/ADT/Statistic.h" 700b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h" 710b57cec5SDimitry Andric #include "llvm/ADT/Twine.h" 720b57cec5SDimitry Andric #include "llvm/CodeGen/Passes.h" 730b57cec5SDimitry Andric #include "llvm/IR/BasicBlock.h" 740b57cec5SDimitry Andric #include "llvm/IR/Constants.h" 750b57cec5SDimitry Andric #include "llvm/IR/DataLayout.h" 760b57cec5SDimitry Andric #include "llvm/IR/DerivedTypes.h" 770b57cec5SDimitry Andric #include "llvm/IR/Function.h" 780b57cec5SDimitry Andric #include "llvm/IR/GlobalAlias.h" 790b57cec5SDimitry Andric #include "llvm/IR/GlobalValue.h" 800b57cec5SDimitry Andric #include "llvm/IR/GlobalVariable.h" 810b57cec5SDimitry Andric #include "llvm/IR/Instruction.h" 820b57cec5SDimitry Andric #include "llvm/IR/Module.h" 830b57cec5SDimitry Andric #include "llvm/IR/Type.h" 840b57cec5SDimitry Andric #include "llvm/IR/Use.h" 850b57cec5SDimitry Andric #include "llvm/IR/User.h" 86480093f4SDimitry Andric #include "llvm/InitializePasses.h" 875ffd83dbSDimitry Andric #include "llvm/MC/SectionKind.h" 880b57cec5SDimitry Andric #include "llvm/Pass.h" 890b57cec5SDimitry Andric #include "llvm/Support/Casting.h" 900b57cec5SDimitry Andric #include "llvm/Support/CommandLine.h" 910b57cec5SDimitry Andric #include "llvm/Support/Debug.h" 920b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h" 930b57cec5SDimitry Andric #include "llvm/Target/TargetLoweringObjectFile.h" 940b57cec5SDimitry Andric #include "llvm/Target/TargetMachine.h" 9506c3fb27SDimitry Andric #include "llvm/TargetParser/Triple.h" 960b57cec5SDimitry Andric #include <algorithm> 970b57cec5SDimitry Andric #include <cassert> 980b57cec5SDimitry Andric #include <cstddef> 990b57cec5SDimitry Andric #include <cstdint> 1000b57cec5SDimitry Andric #include <string> 1010b57cec5SDimitry Andric #include <vector> 1020b57cec5SDimitry Andric 1030b57cec5SDimitry Andric using namespace llvm; 1040b57cec5SDimitry Andric 1050b57cec5SDimitry Andric #define DEBUG_TYPE "global-merge" 1060b57cec5SDimitry Andric 1070b57cec5SDimitry Andric // FIXME: This is only useful as a last-resort way to disable the pass. 1080b57cec5SDimitry Andric static cl::opt<bool> 1090b57cec5SDimitry Andric EnableGlobalMerge("enable-global-merge", cl::Hidden, 1100b57cec5SDimitry Andric cl::desc("Enable the global merge pass"), 1110b57cec5SDimitry Andric cl::init(true)); 1120b57cec5SDimitry Andric 1130b57cec5SDimitry Andric static cl::opt<unsigned> 1140b57cec5SDimitry Andric GlobalMergeMaxOffset("global-merge-max-offset", cl::Hidden, 1150b57cec5SDimitry Andric cl::desc("Set maximum offset for global merge pass"), 1160b57cec5SDimitry Andric cl::init(0)); 1170b57cec5SDimitry Andric 1180b57cec5SDimitry Andric static cl::opt<bool> GlobalMergeGroupByUse( 1190b57cec5SDimitry Andric "global-merge-group-by-use", cl::Hidden, 1200b57cec5SDimitry Andric cl::desc("Improve global merge pass to look at uses"), cl::init(true)); 1210b57cec5SDimitry Andric 1220b57cec5SDimitry Andric static cl::opt<bool> GlobalMergeIgnoreSingleUse( 1230b57cec5SDimitry Andric "global-merge-ignore-single-use", cl::Hidden, 1240b57cec5SDimitry Andric cl::desc("Improve global merge pass to ignore globals only used alone"), 1250b57cec5SDimitry Andric cl::init(true)); 1260b57cec5SDimitry Andric 1270b57cec5SDimitry Andric static cl::opt<bool> 1280b57cec5SDimitry Andric EnableGlobalMergeOnConst("global-merge-on-const", cl::Hidden, 1290b57cec5SDimitry Andric cl::desc("Enable global merge pass on constants"), 1300b57cec5SDimitry Andric cl::init(false)); 1310b57cec5SDimitry Andric 1320b57cec5SDimitry Andric // FIXME: this could be a transitional option, and we probably need to remove 1330b57cec5SDimitry Andric // it if only we are sure this optimization could always benefit all targets. 1340b57cec5SDimitry Andric static cl::opt<cl::boolOrDefault> 1350b57cec5SDimitry Andric EnableGlobalMergeOnExternal("global-merge-on-external", cl::Hidden, 1360b57cec5SDimitry Andric cl::desc("Enable global merge pass on external linkage")); 1370b57cec5SDimitry Andric 138*0fca6ea1SDimitry Andric static cl::opt<unsigned> 139*0fca6ea1SDimitry Andric GlobalMergeMinDataSize("global-merge-min-data-size", 140*0fca6ea1SDimitry Andric cl::desc("The minimum size in bytes of each global " 141*0fca6ea1SDimitry Andric "that should considered in merging."), 142*0fca6ea1SDimitry Andric cl::init(0), cl::Hidden); 143*0fca6ea1SDimitry Andric 1440b57cec5SDimitry Andric STATISTIC(NumMerged, "Number of globals merged"); 1450b57cec5SDimitry Andric 1460b57cec5SDimitry Andric namespace { 1470b57cec5SDimitry Andric 1487a6dacacSDimitry Andric class GlobalMergeImpl { 1490b57cec5SDimitry Andric const TargetMachine *TM = nullptr; 1507a6dacacSDimitry Andric GlobalMergeOptions Opt; 15106c3fb27SDimitry Andric bool IsMachO = false; 1520b57cec5SDimitry Andric 1537a6dacacSDimitry Andric private: 1547a6dacacSDimitry Andric bool doMerge(SmallVectorImpl<GlobalVariable *> &Globals, Module &M, 1557a6dacacSDimitry Andric bool isConst, unsigned AddrSpace) const; 1560b57cec5SDimitry Andric 1570b57cec5SDimitry Andric /// Merge everything in \p Globals for which the corresponding bit 1580b57cec5SDimitry Andric /// in \p GlobalSet is set. 1590b57cec5SDimitry Andric bool doMerge(const SmallVectorImpl<GlobalVariable *> &Globals, 1600b57cec5SDimitry Andric const BitVector &GlobalSet, Module &M, bool isConst, 1610b57cec5SDimitry Andric unsigned AddrSpace) const; 1620b57cec5SDimitry Andric 1630b57cec5SDimitry Andric /// Check if the given variable has been identified as must keep 1640b57cec5SDimitry Andric /// \pre setMustKeepGlobalVariables must have been called on the Module that 1650b57cec5SDimitry Andric /// contains GV 1660b57cec5SDimitry Andric bool isMustKeepGlobalVariable(const GlobalVariable *GV) const { 1670b57cec5SDimitry Andric return MustKeepGlobalVariables.count(GV); 1680b57cec5SDimitry Andric } 1690b57cec5SDimitry Andric 1700b57cec5SDimitry Andric /// Collect every variables marked as "used" or used in a landing pad 1710b57cec5SDimitry Andric /// instruction for this Module. 1720b57cec5SDimitry Andric void setMustKeepGlobalVariables(Module &M); 1730b57cec5SDimitry Andric 1740b57cec5SDimitry Andric /// Collect every variables marked as "used" 1750b57cec5SDimitry Andric void collectUsedGlobalVariables(Module &M, StringRef Name); 1760b57cec5SDimitry Andric 1770b57cec5SDimitry Andric /// Keep track of the GlobalVariable that must not be merged away 178bdd1243dSDimitry Andric SmallSetVector<const GlobalVariable *, 16> MustKeepGlobalVariables; 1790b57cec5SDimitry Andric 1800b57cec5SDimitry Andric public: 1817a6dacacSDimitry Andric GlobalMergeImpl(const TargetMachine *TM, GlobalMergeOptions Opt) 1827a6dacacSDimitry Andric : TM(TM), Opt(Opt) {} 1837a6dacacSDimitry Andric bool run(Module &M); 1847a6dacacSDimitry Andric }; 1857a6dacacSDimitry Andric 1867a6dacacSDimitry Andric class GlobalMerge : public FunctionPass { 1877a6dacacSDimitry Andric const TargetMachine *TM = nullptr; 1887a6dacacSDimitry Andric GlobalMergeOptions Opt; 1897a6dacacSDimitry Andric 1907a6dacacSDimitry Andric public: 1910b57cec5SDimitry Andric static char ID; // Pass identification, replacement for typeid. 1920b57cec5SDimitry Andric 1937a6dacacSDimitry Andric explicit GlobalMerge() : FunctionPass(ID) { 1947a6dacacSDimitry Andric Opt.MaxOffset = GlobalMergeMaxOffset; 1950b57cec5SDimitry Andric initializeGlobalMergePass(*PassRegistry::getPassRegistry()); 1960b57cec5SDimitry Andric } 1970b57cec5SDimitry Andric 1980b57cec5SDimitry Andric explicit GlobalMerge(const TargetMachine *TM, unsigned MaximalOffset, 1990b57cec5SDimitry Andric bool OnlyOptimizeForSize, bool MergeExternalGlobals) 2007a6dacacSDimitry Andric : FunctionPass(ID), TM(TM) { 2017a6dacacSDimitry Andric Opt.MaxOffset = MaximalOffset; 2027a6dacacSDimitry Andric Opt.SizeOnly = OnlyOptimizeForSize; 2037a6dacacSDimitry Andric Opt.MergeExternal = MergeExternalGlobals; 2040b57cec5SDimitry Andric initializeGlobalMergePass(*PassRegistry::getPassRegistry()); 2050b57cec5SDimitry Andric } 2060b57cec5SDimitry Andric 2077a6dacacSDimitry Andric bool doInitialization(Module &M) override { 208*0fca6ea1SDimitry Andric auto GetSmallDataLimit = [](Module &M) -> std::optional<uint64_t> { 209*0fca6ea1SDimitry Andric Metadata *SDL = M.getModuleFlag("SmallDataLimit"); 210*0fca6ea1SDimitry Andric if (!SDL) 211*0fca6ea1SDimitry Andric return std::nullopt; 212*0fca6ea1SDimitry Andric return mdconst::extract<ConstantInt>(SDL)->getZExtValue(); 213*0fca6ea1SDimitry Andric }; 214*0fca6ea1SDimitry Andric if (GlobalMergeMinDataSize.getNumOccurrences()) 215*0fca6ea1SDimitry Andric Opt.MinSize = GlobalMergeMinDataSize; 216*0fca6ea1SDimitry Andric else if (auto SDL = GetSmallDataLimit(M); SDL && *SDL > 0) 217*0fca6ea1SDimitry Andric Opt.MinSize = *SDL + 1; 218*0fca6ea1SDimitry Andric else 219*0fca6ea1SDimitry Andric Opt.MinSize = 0; 220*0fca6ea1SDimitry Andric 2217a6dacacSDimitry Andric GlobalMergeImpl P(TM, Opt); 2227a6dacacSDimitry Andric return P.run(M); 2237a6dacacSDimitry Andric } 2247a6dacacSDimitry Andric bool runOnFunction(Function &F) override { return false; } 2250b57cec5SDimitry Andric 2260b57cec5SDimitry Andric StringRef getPassName() const override { return "Merge internal globals"; } 2270b57cec5SDimitry Andric 2280b57cec5SDimitry Andric void getAnalysisUsage(AnalysisUsage &AU) const override { 2290b57cec5SDimitry Andric AU.setPreservesCFG(); 2300b57cec5SDimitry Andric FunctionPass::getAnalysisUsage(AU); 2310b57cec5SDimitry Andric } 2320b57cec5SDimitry Andric }; 2330b57cec5SDimitry Andric 2340b57cec5SDimitry Andric } // end anonymous namespace 2350b57cec5SDimitry Andric 2367a6dacacSDimitry Andric PreservedAnalyses GlobalMergePass::run(Module &M, ModuleAnalysisManager &) { 2377a6dacacSDimitry Andric GlobalMergeImpl P(TM, Options); 2387a6dacacSDimitry Andric bool Changed = P.run(M); 2397a6dacacSDimitry Andric if (!Changed) 2407a6dacacSDimitry Andric return PreservedAnalyses::all(); 2417a6dacacSDimitry Andric 2427a6dacacSDimitry Andric PreservedAnalyses PA; 2437a6dacacSDimitry Andric PA.preserveSet<CFGAnalyses>(); 2447a6dacacSDimitry Andric return PA; 2457a6dacacSDimitry Andric } 2467a6dacacSDimitry Andric 2470b57cec5SDimitry Andric char GlobalMerge::ID = 0; 2480b57cec5SDimitry Andric 2490b57cec5SDimitry Andric INITIALIZE_PASS(GlobalMerge, DEBUG_TYPE, "Merge global variables", false, false) 2500b57cec5SDimitry Andric 2517a6dacacSDimitry Andric bool GlobalMergeImpl::doMerge(SmallVectorImpl<GlobalVariable *> &Globals, 2527a6dacacSDimitry Andric Module &M, bool isConst, 2537a6dacacSDimitry Andric unsigned AddrSpace) const { 2540b57cec5SDimitry Andric auto &DL = M.getDataLayout(); 2550b57cec5SDimitry Andric // FIXME: Find better heuristics 2560b57cec5SDimitry Andric llvm::stable_sort( 2570b57cec5SDimitry Andric Globals, [&DL](const GlobalVariable *GV1, const GlobalVariable *GV2) { 258e8d8bef9SDimitry Andric // We don't support scalable global variables. 259bdd1243dSDimitry Andric return DL.getTypeAllocSize(GV1->getValueType()).getFixedValue() < 260bdd1243dSDimitry Andric DL.getTypeAllocSize(GV2->getValueType()).getFixedValue(); 2610b57cec5SDimitry Andric }); 2620b57cec5SDimitry Andric 2630b57cec5SDimitry Andric // If we want to just blindly group all globals together, do so. 2640b57cec5SDimitry Andric if (!GlobalMergeGroupByUse) { 2650b57cec5SDimitry Andric BitVector AllGlobals(Globals.size()); 2660b57cec5SDimitry Andric AllGlobals.set(); 2670b57cec5SDimitry Andric return doMerge(Globals, AllGlobals, M, isConst, AddrSpace); 2680b57cec5SDimitry Andric } 2690b57cec5SDimitry Andric 2700b57cec5SDimitry Andric // If we want to be smarter, look at all uses of each global, to try to 2710b57cec5SDimitry Andric // discover all sets of globals used together, and how many times each of 2720b57cec5SDimitry Andric // these sets occurred. 2730b57cec5SDimitry Andric // 2740b57cec5SDimitry Andric // Keep this reasonably efficient, by having an append-only list of all sets 2750b57cec5SDimitry Andric // discovered so far (UsedGlobalSet), and mapping each "together-ness" unit of 2760b57cec5SDimitry Andric // code (currently, a Function) to the set of globals seen so far that are 2770b57cec5SDimitry Andric // used together in that unit (GlobalUsesByFunction). 2780b57cec5SDimitry Andric // 2790b57cec5SDimitry Andric // When we look at the Nth global, we know that any new set is either: 2800b57cec5SDimitry Andric // - the singleton set {N}, containing this global only, or 2810b57cec5SDimitry Andric // - the union of {N} and a previously-discovered set, containing some 2820b57cec5SDimitry Andric // combination of the previous N-1 globals. 2830b57cec5SDimitry Andric // Using that knowledge, when looking at the Nth global, we can keep: 2840b57cec5SDimitry Andric // - a reference to the singleton set {N} (CurGVOnlySetIdx) 2850b57cec5SDimitry Andric // - a list mapping each previous set to its union with {N} (EncounteredUGS), 2860b57cec5SDimitry Andric // if it actually occurs. 2870b57cec5SDimitry Andric 2880b57cec5SDimitry Andric // We keep track of the sets of globals used together "close enough". 2890b57cec5SDimitry Andric struct UsedGlobalSet { 2900b57cec5SDimitry Andric BitVector Globals; 2910b57cec5SDimitry Andric unsigned UsageCount = 1; 2920b57cec5SDimitry Andric 2930b57cec5SDimitry Andric UsedGlobalSet(size_t Size) : Globals(Size) {} 2940b57cec5SDimitry Andric }; 2950b57cec5SDimitry Andric 2960b57cec5SDimitry Andric // Each set is unique in UsedGlobalSets. 2970b57cec5SDimitry Andric std::vector<UsedGlobalSet> UsedGlobalSets; 2980b57cec5SDimitry Andric 2990b57cec5SDimitry Andric // Avoid repeating the create-global-set pattern. 3000b57cec5SDimitry Andric auto CreateGlobalSet = [&]() -> UsedGlobalSet & { 3010b57cec5SDimitry Andric UsedGlobalSets.emplace_back(Globals.size()); 3020b57cec5SDimitry Andric return UsedGlobalSets.back(); 3030b57cec5SDimitry Andric }; 3040b57cec5SDimitry Andric 3050b57cec5SDimitry Andric // The first set is the empty set. 3060b57cec5SDimitry Andric CreateGlobalSet().UsageCount = 0; 3070b57cec5SDimitry Andric 3080b57cec5SDimitry Andric // We define "close enough" to be "in the same function". 3090b57cec5SDimitry Andric // FIXME: Grouping uses by function is way too aggressive, so we should have 3100b57cec5SDimitry Andric // a better metric for distance between uses. 3110b57cec5SDimitry Andric // The obvious alternative would be to group by BasicBlock, but that's in 3120b57cec5SDimitry Andric // turn too conservative.. 3130b57cec5SDimitry Andric // Anything in between wouldn't be trivial to compute, so just stick with 3140b57cec5SDimitry Andric // per-function grouping. 3150b57cec5SDimitry Andric 3160b57cec5SDimitry Andric // The value type is an index into UsedGlobalSets. 3170b57cec5SDimitry Andric // The default (0) conveniently points to the empty set. 3180b57cec5SDimitry Andric DenseMap<Function *, size_t /*UsedGlobalSetIdx*/> GlobalUsesByFunction; 3190b57cec5SDimitry Andric 3200b57cec5SDimitry Andric // Now, look at each merge-eligible global in turn. 3210b57cec5SDimitry Andric 3220b57cec5SDimitry Andric // Keep track of the sets we already encountered to which we added the 3230b57cec5SDimitry Andric // current global. 3240b57cec5SDimitry Andric // Each element matches the same-index element in UsedGlobalSets. 3250b57cec5SDimitry Andric // This lets us efficiently tell whether a set has already been expanded to 3260b57cec5SDimitry Andric // include the current global. 3270b57cec5SDimitry Andric std::vector<size_t> EncounteredUGS; 3280b57cec5SDimitry Andric 3290b57cec5SDimitry Andric for (size_t GI = 0, GE = Globals.size(); GI != GE; ++GI) { 3300b57cec5SDimitry Andric GlobalVariable *GV = Globals[GI]; 3310b57cec5SDimitry Andric 332*0fca6ea1SDimitry Andric // Reset the encountered sets for this global and grow it in case we created 333*0fca6ea1SDimitry Andric // new sets for the previous global. 334*0fca6ea1SDimitry Andric EncounteredUGS.assign(UsedGlobalSets.size(), 0); 3350b57cec5SDimitry Andric 3360b57cec5SDimitry Andric // We might need to create a set that only consists of the current global. 3370b57cec5SDimitry Andric // Keep track of its index into UsedGlobalSets. 3380b57cec5SDimitry Andric size_t CurGVOnlySetIdx = 0; 3390b57cec5SDimitry Andric 3400b57cec5SDimitry Andric // For each global, look at all its Uses. 3410b57cec5SDimitry Andric for (auto &U : GV->uses()) { 3420b57cec5SDimitry Andric // This Use might be a ConstantExpr. We're interested in Instruction 3430b57cec5SDimitry Andric // users, so look through ConstantExpr... 3440b57cec5SDimitry Andric Use *UI, *UE; 3450b57cec5SDimitry Andric if (ConstantExpr *CE = dyn_cast<ConstantExpr>(U.getUser())) { 3460b57cec5SDimitry Andric if (CE->use_empty()) 3470b57cec5SDimitry Andric continue; 3480b57cec5SDimitry Andric UI = &*CE->use_begin(); 3490b57cec5SDimitry Andric UE = nullptr; 3500b57cec5SDimitry Andric } else if (isa<Instruction>(U.getUser())) { 3510b57cec5SDimitry Andric UI = &U; 3520b57cec5SDimitry Andric UE = UI->getNext(); 3530b57cec5SDimitry Andric } else { 3540b57cec5SDimitry Andric continue; 3550b57cec5SDimitry Andric } 3560b57cec5SDimitry Andric 3570b57cec5SDimitry Andric // ...to iterate on all the instruction users of the global. 3580b57cec5SDimitry Andric // Note that we iterate on Uses and not on Users to be able to getNext(). 3590b57cec5SDimitry Andric for (; UI != UE; UI = UI->getNext()) { 3600b57cec5SDimitry Andric Instruction *I = dyn_cast<Instruction>(UI->getUser()); 3610b57cec5SDimitry Andric if (!I) 3620b57cec5SDimitry Andric continue; 3630b57cec5SDimitry Andric 3640b57cec5SDimitry Andric Function *ParentFn = I->getParent()->getParent(); 3650b57cec5SDimitry Andric 3660b57cec5SDimitry Andric // If we're only optimizing for size, ignore non-minsize functions. 3677a6dacacSDimitry Andric if (Opt.SizeOnly && !ParentFn->hasMinSize()) 3680b57cec5SDimitry Andric continue; 3690b57cec5SDimitry Andric 3700b57cec5SDimitry Andric size_t UGSIdx = GlobalUsesByFunction[ParentFn]; 3710b57cec5SDimitry Andric 3720b57cec5SDimitry Andric // If this is the first global the basic block uses, map it to the set 3730b57cec5SDimitry Andric // consisting of this global only. 3740b57cec5SDimitry Andric if (!UGSIdx) { 3750b57cec5SDimitry Andric // If that set doesn't exist yet, create it. 3760b57cec5SDimitry Andric if (!CurGVOnlySetIdx) { 3770b57cec5SDimitry Andric CurGVOnlySetIdx = UsedGlobalSets.size(); 3780b57cec5SDimitry Andric CreateGlobalSet().Globals.set(GI); 3790b57cec5SDimitry Andric } else { 3800b57cec5SDimitry Andric ++UsedGlobalSets[CurGVOnlySetIdx].UsageCount; 3810b57cec5SDimitry Andric } 3820b57cec5SDimitry Andric 3830b57cec5SDimitry Andric GlobalUsesByFunction[ParentFn] = CurGVOnlySetIdx; 3840b57cec5SDimitry Andric continue; 3850b57cec5SDimitry Andric } 3860b57cec5SDimitry Andric 3870b57cec5SDimitry Andric // If we already encountered this BB, just increment the counter. 3880b57cec5SDimitry Andric if (UsedGlobalSets[UGSIdx].Globals.test(GI)) { 3890b57cec5SDimitry Andric ++UsedGlobalSets[UGSIdx].UsageCount; 3900b57cec5SDimitry Andric continue; 3910b57cec5SDimitry Andric } 3920b57cec5SDimitry Andric 3930b57cec5SDimitry Andric // If not, the previous set wasn't actually used in this function. 3940b57cec5SDimitry Andric --UsedGlobalSets[UGSIdx].UsageCount; 3950b57cec5SDimitry Andric 3960b57cec5SDimitry Andric // If we already expanded the previous set to include this global, just 3970b57cec5SDimitry Andric // reuse that expanded set. 3980b57cec5SDimitry Andric if (size_t ExpandedIdx = EncounteredUGS[UGSIdx]) { 3990b57cec5SDimitry Andric ++UsedGlobalSets[ExpandedIdx].UsageCount; 4000b57cec5SDimitry Andric GlobalUsesByFunction[ParentFn] = ExpandedIdx; 4010b57cec5SDimitry Andric continue; 4020b57cec5SDimitry Andric } 4030b57cec5SDimitry Andric 4040b57cec5SDimitry Andric // If not, create a new set consisting of the union of the previous set 4050b57cec5SDimitry Andric // and this global. Mark it as encountered, so we can reuse it later. 4060b57cec5SDimitry Andric GlobalUsesByFunction[ParentFn] = EncounteredUGS[UGSIdx] = 4070b57cec5SDimitry Andric UsedGlobalSets.size(); 4080b57cec5SDimitry Andric 4090b57cec5SDimitry Andric UsedGlobalSet &NewUGS = CreateGlobalSet(); 4100b57cec5SDimitry Andric NewUGS.Globals.set(GI); 4110b57cec5SDimitry Andric NewUGS.Globals |= UsedGlobalSets[UGSIdx].Globals; 4120b57cec5SDimitry Andric } 4130b57cec5SDimitry Andric } 4140b57cec5SDimitry Andric } 4150b57cec5SDimitry Andric 4160b57cec5SDimitry Andric // Now we found a bunch of sets of globals used together. We accumulated 4170b57cec5SDimitry Andric // the number of times we encountered the sets (i.e., the number of blocks 4180b57cec5SDimitry Andric // that use that exact set of globals). 4190b57cec5SDimitry Andric // 4200b57cec5SDimitry Andric // Multiply that by the size of the set to give us a crude profitability 4210b57cec5SDimitry Andric // metric. 4220b57cec5SDimitry Andric llvm::stable_sort(UsedGlobalSets, 4230b57cec5SDimitry Andric [](const UsedGlobalSet &UGS1, const UsedGlobalSet &UGS2) { 4240b57cec5SDimitry Andric return UGS1.Globals.count() * UGS1.UsageCount < 4250b57cec5SDimitry Andric UGS2.Globals.count() * UGS2.UsageCount; 4260b57cec5SDimitry Andric }); 4270b57cec5SDimitry Andric 4280b57cec5SDimitry Andric // We can choose to merge all globals together, but ignore globals never used 4290b57cec5SDimitry Andric // with another global. This catches the obviously non-profitable cases of 4300b57cec5SDimitry Andric // having a single global, but is aggressive enough for any other case. 4310b57cec5SDimitry Andric if (GlobalMergeIgnoreSingleUse) { 4320b57cec5SDimitry Andric BitVector AllGlobals(Globals.size()); 4334824e7fdSDimitry Andric for (const UsedGlobalSet &UGS : llvm::reverse(UsedGlobalSets)) { 4340b57cec5SDimitry Andric if (UGS.UsageCount == 0) 4350b57cec5SDimitry Andric continue; 4360b57cec5SDimitry Andric if (UGS.Globals.count() > 1) 4370b57cec5SDimitry Andric AllGlobals |= UGS.Globals; 4380b57cec5SDimitry Andric } 4390b57cec5SDimitry Andric return doMerge(Globals, AllGlobals, M, isConst, AddrSpace); 4400b57cec5SDimitry Andric } 4410b57cec5SDimitry Andric 4420b57cec5SDimitry Andric // Starting from the sets with the best (=biggest) profitability, find a 4430b57cec5SDimitry Andric // good combination. 4440b57cec5SDimitry Andric // The ideal (and expensive) solution can only be found by trying all 4450b57cec5SDimitry Andric // combinations, looking for the one with the best profitability. 4460b57cec5SDimitry Andric // Don't be smart about it, and just pick the first compatible combination, 4470b57cec5SDimitry Andric // starting with the sets with the best profitability. 4480b57cec5SDimitry Andric BitVector PickedGlobals(Globals.size()); 4490b57cec5SDimitry Andric bool Changed = false; 4500b57cec5SDimitry Andric 4514824e7fdSDimitry Andric for (const UsedGlobalSet &UGS : llvm::reverse(UsedGlobalSets)) { 4520b57cec5SDimitry Andric if (UGS.UsageCount == 0) 4530b57cec5SDimitry Andric continue; 4540b57cec5SDimitry Andric if (PickedGlobals.anyCommon(UGS.Globals)) 4550b57cec5SDimitry Andric continue; 4560b57cec5SDimitry Andric PickedGlobals |= UGS.Globals; 4570b57cec5SDimitry Andric // If the set only contains one global, there's no point in merging. 4580b57cec5SDimitry Andric // Ignore the global for inclusion in other sets though, so keep it in 4590b57cec5SDimitry Andric // PickedGlobals. 4600b57cec5SDimitry Andric if (UGS.Globals.count() < 2) 4610b57cec5SDimitry Andric continue; 4620b57cec5SDimitry Andric Changed |= doMerge(Globals, UGS.Globals, M, isConst, AddrSpace); 4630b57cec5SDimitry Andric } 4640b57cec5SDimitry Andric 4650b57cec5SDimitry Andric return Changed; 4660b57cec5SDimitry Andric } 4670b57cec5SDimitry Andric 4687a6dacacSDimitry Andric bool GlobalMergeImpl::doMerge(const SmallVectorImpl<GlobalVariable *> &Globals, 4697a6dacacSDimitry Andric const BitVector &GlobalSet, Module &M, 4707a6dacacSDimitry Andric bool isConst, unsigned AddrSpace) const { 4710b57cec5SDimitry Andric assert(Globals.size() > 1); 4720b57cec5SDimitry Andric 4730b57cec5SDimitry Andric Type *Int32Ty = Type::getInt32Ty(M.getContext()); 4740b57cec5SDimitry Andric Type *Int8Ty = Type::getInt8Ty(M.getContext()); 4750b57cec5SDimitry Andric auto &DL = M.getDataLayout(); 4760b57cec5SDimitry Andric 4770b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << " Trying to merge set, starts with #" 4780b57cec5SDimitry Andric << GlobalSet.find_first() << "\n"); 4790b57cec5SDimitry Andric 4800b57cec5SDimitry Andric bool Changed = false; 4810b57cec5SDimitry Andric ssize_t i = GlobalSet.find_first(); 4820b57cec5SDimitry Andric while (i != -1) { 4830b57cec5SDimitry Andric ssize_t j = 0; 4840b57cec5SDimitry Andric uint64_t MergedSize = 0; 4850b57cec5SDimitry Andric std::vector<Type*> Tys; 4860b57cec5SDimitry Andric std::vector<Constant*> Inits; 4870b57cec5SDimitry Andric std::vector<unsigned> StructIdxs; 4880b57cec5SDimitry Andric 4890b57cec5SDimitry Andric bool HasExternal = false; 4900b57cec5SDimitry Andric StringRef FirstExternalName; 4918bcb0991SDimitry Andric Align MaxAlign; 4920b57cec5SDimitry Andric unsigned CurIdx = 0; 4930b57cec5SDimitry Andric for (j = i; j != -1; j = GlobalSet.find_next(j)) { 4940b57cec5SDimitry Andric Type *Ty = Globals[j]->getValueType(); 4950b57cec5SDimitry Andric 4960b57cec5SDimitry Andric // Make sure we use the same alignment AsmPrinter would use. 4975ffd83dbSDimitry Andric Align Alignment = DL.getPreferredAlign(Globals[j]); 4988bcb0991SDimitry Andric unsigned Padding = alignTo(MergedSize, Alignment) - MergedSize; 4990b57cec5SDimitry Andric MergedSize += Padding; 5000b57cec5SDimitry Andric MergedSize += DL.getTypeAllocSize(Ty); 5017a6dacacSDimitry Andric if (MergedSize > Opt.MaxOffset) { 5020b57cec5SDimitry Andric break; 5030b57cec5SDimitry Andric } 5040b57cec5SDimitry Andric if (Padding) { 5050b57cec5SDimitry Andric Tys.push_back(ArrayType::get(Int8Ty, Padding)); 5060b57cec5SDimitry Andric Inits.push_back(ConstantAggregateZero::get(Tys.back())); 5070b57cec5SDimitry Andric ++CurIdx; 5080b57cec5SDimitry Andric } 5090b57cec5SDimitry Andric Tys.push_back(Ty); 5100b57cec5SDimitry Andric Inits.push_back(Globals[j]->getInitializer()); 5110b57cec5SDimitry Andric StructIdxs.push_back(CurIdx++); 5120b57cec5SDimitry Andric 5138bcb0991SDimitry Andric MaxAlign = std::max(MaxAlign, Alignment); 5140b57cec5SDimitry Andric 5150b57cec5SDimitry Andric if (Globals[j]->hasExternalLinkage() && !HasExternal) { 5160b57cec5SDimitry Andric HasExternal = true; 5170b57cec5SDimitry Andric FirstExternalName = Globals[j]->getName(); 5180b57cec5SDimitry Andric } 5190b57cec5SDimitry Andric } 5200b57cec5SDimitry Andric 5210b57cec5SDimitry Andric // Exit early if there is only one global to merge. 5220b57cec5SDimitry Andric if (Tys.size() < 2) { 5230b57cec5SDimitry Andric i = j; 5240b57cec5SDimitry Andric continue; 5250b57cec5SDimitry Andric } 5260b57cec5SDimitry Andric 5270b57cec5SDimitry Andric // If merged variables doesn't have external linkage, we needn't to expose 5280b57cec5SDimitry Andric // the symbol after merging. 5290b57cec5SDimitry Andric GlobalValue::LinkageTypes Linkage = HasExternal 5300b57cec5SDimitry Andric ? GlobalValue::ExternalLinkage 5310b57cec5SDimitry Andric : GlobalValue::InternalLinkage; 5320b57cec5SDimitry Andric // Use a packed struct so we can control alignment. 5330b57cec5SDimitry Andric StructType *MergedTy = StructType::get(M.getContext(), Tys, true); 5340b57cec5SDimitry Andric Constant *MergedInit = ConstantStruct::get(MergedTy, Inits); 5350b57cec5SDimitry Andric 5360b57cec5SDimitry Andric // On Darwin external linkage needs to be preserved, otherwise 5370b57cec5SDimitry Andric // dsymutil cannot preserve the debug info for the merged 5380b57cec5SDimitry Andric // variables. If they have external linkage, use the symbol name 5390b57cec5SDimitry Andric // of the first variable merged as the suffix of global symbol 5400b57cec5SDimitry Andric // name. This avoids a link-time naming conflict for the 5410b57cec5SDimitry Andric // _MergedGlobals symbols. 5420b57cec5SDimitry Andric Twine MergedName = 5430b57cec5SDimitry Andric (IsMachO && HasExternal) 5440b57cec5SDimitry Andric ? "_MergedGlobals_" + FirstExternalName 5450b57cec5SDimitry Andric : "_MergedGlobals"; 5460b57cec5SDimitry Andric auto MergedLinkage = IsMachO ? Linkage : GlobalValue::PrivateLinkage; 5470b57cec5SDimitry Andric auto *MergedGV = new GlobalVariable( 5480b57cec5SDimitry Andric M, MergedTy, isConst, MergedLinkage, MergedInit, MergedName, nullptr, 5490b57cec5SDimitry Andric GlobalVariable::NotThreadLocal, AddrSpace); 5500b57cec5SDimitry Andric 5510b57cec5SDimitry Andric MergedGV->setAlignment(MaxAlign); 5520b57cec5SDimitry Andric MergedGV->setSection(Globals[i]->getSection()); 5530b57cec5SDimitry Andric 5540b57cec5SDimitry Andric const StructLayout *MergedLayout = DL.getStructLayout(MergedTy); 5550b57cec5SDimitry Andric for (ssize_t k = i, idx = 0; k != j; k = GlobalSet.find_next(k), ++idx) { 5560b57cec5SDimitry Andric GlobalValue::LinkageTypes Linkage = Globals[k]->getLinkage(); 5575ffd83dbSDimitry Andric std::string Name(Globals[k]->getName()); 55813138422SDimitry Andric GlobalValue::VisibilityTypes Visibility = Globals[k]->getVisibility(); 5590b57cec5SDimitry Andric GlobalValue::DLLStorageClassTypes DLLStorage = 5600b57cec5SDimitry Andric Globals[k]->getDLLStorageClass(); 5610b57cec5SDimitry Andric 5620b57cec5SDimitry Andric // Copy metadata while adjusting any debug info metadata by the original 5630b57cec5SDimitry Andric // global's offset within the merged global. 5640b57cec5SDimitry Andric MergedGV->copyMetadata(Globals[k], 5650b57cec5SDimitry Andric MergedLayout->getElementOffset(StructIdxs[idx])); 5660b57cec5SDimitry Andric 5670b57cec5SDimitry Andric Constant *Idx[2] = { 5680b57cec5SDimitry Andric ConstantInt::get(Int32Ty, 0), 5690b57cec5SDimitry Andric ConstantInt::get(Int32Ty, StructIdxs[idx]), 5700b57cec5SDimitry Andric }; 5710b57cec5SDimitry Andric Constant *GEP = 5720b57cec5SDimitry Andric ConstantExpr::getInBoundsGetElementPtr(MergedTy, MergedGV, Idx); 5730b57cec5SDimitry Andric Globals[k]->replaceAllUsesWith(GEP); 5740b57cec5SDimitry Andric Globals[k]->eraseFromParent(); 5750b57cec5SDimitry Andric 5760b57cec5SDimitry Andric // When the linkage is not internal we must emit an alias for the original 5770b57cec5SDimitry Andric // variable name as it may be accessed from another object. On non-Mach-O 5780b57cec5SDimitry Andric // we can also emit an alias for internal linkage as it's safe to do so. 5790b57cec5SDimitry Andric // It's not safe on Mach-O as the alias (and thus the portion of the 5800b57cec5SDimitry Andric // MergedGlobals variable) may be dead stripped at link time. 5810b57cec5SDimitry Andric if (Linkage != GlobalValue::InternalLinkage || !IsMachO) { 5820b57cec5SDimitry Andric GlobalAlias *GA = GlobalAlias::create(Tys[StructIdxs[idx]], AddrSpace, 5830b57cec5SDimitry Andric Linkage, Name, GEP, &M); 58413138422SDimitry Andric GA->setVisibility(Visibility); 5850b57cec5SDimitry Andric GA->setDLLStorageClass(DLLStorage); 5860b57cec5SDimitry Andric } 5870b57cec5SDimitry Andric 5880b57cec5SDimitry Andric NumMerged++; 5890b57cec5SDimitry Andric } 5900b57cec5SDimitry Andric Changed = true; 5910b57cec5SDimitry Andric i = j; 5920b57cec5SDimitry Andric } 5930b57cec5SDimitry Andric 5940b57cec5SDimitry Andric return Changed; 5950b57cec5SDimitry Andric } 5960b57cec5SDimitry Andric 5977a6dacacSDimitry Andric void GlobalMergeImpl::collectUsedGlobalVariables(Module &M, StringRef Name) { 5980b57cec5SDimitry Andric // Extract global variables from llvm.used array 5990b57cec5SDimitry Andric const GlobalVariable *GV = M.getGlobalVariable(Name); 6000b57cec5SDimitry Andric if (!GV || !GV->hasInitializer()) return; 6010b57cec5SDimitry Andric 6020b57cec5SDimitry Andric // Should be an array of 'i8*'. 6030b57cec5SDimitry Andric const ConstantArray *InitList = cast<ConstantArray>(GV->getInitializer()); 6040b57cec5SDimitry Andric 6050b57cec5SDimitry Andric for (unsigned i = 0, e = InitList->getNumOperands(); i != e; ++i) 6060b57cec5SDimitry Andric if (const GlobalVariable *G = 6070b57cec5SDimitry Andric dyn_cast<GlobalVariable>(InitList->getOperand(i)->stripPointerCasts())) 6080b57cec5SDimitry Andric MustKeepGlobalVariables.insert(G); 6090b57cec5SDimitry Andric } 6100b57cec5SDimitry Andric 6117a6dacacSDimitry Andric void GlobalMergeImpl::setMustKeepGlobalVariables(Module &M) { 6120b57cec5SDimitry Andric collectUsedGlobalVariables(M, "llvm.used"); 6130b57cec5SDimitry Andric collectUsedGlobalVariables(M, "llvm.compiler.used"); 6140b57cec5SDimitry Andric 6150b57cec5SDimitry Andric for (Function &F : M) { 6160b57cec5SDimitry Andric for (BasicBlock &BB : F) { 6170b57cec5SDimitry Andric Instruction *Pad = BB.getFirstNonPHI(); 6180b57cec5SDimitry Andric if (!Pad->isEHPad()) 6190b57cec5SDimitry Andric continue; 6200b57cec5SDimitry Andric 6210b57cec5SDimitry Andric // Keep globals used by landingpads and catchpads. 6220b57cec5SDimitry Andric for (const Use &U : Pad->operands()) { 6230b57cec5SDimitry Andric if (const GlobalVariable *GV = 6240b57cec5SDimitry Andric dyn_cast<GlobalVariable>(U->stripPointerCasts())) 6250b57cec5SDimitry Andric MustKeepGlobalVariables.insert(GV); 62681ad6265SDimitry Andric else if (const ConstantArray *CA = dyn_cast<ConstantArray>(U->stripPointerCasts())) { 62781ad6265SDimitry Andric for (const Use &Elt : CA->operands()) { 62881ad6265SDimitry Andric if (const GlobalVariable *GV = 62981ad6265SDimitry Andric dyn_cast<GlobalVariable>(Elt->stripPointerCasts())) 63081ad6265SDimitry Andric MustKeepGlobalVariables.insert(GV); 63181ad6265SDimitry Andric } 63281ad6265SDimitry Andric } 6330b57cec5SDimitry Andric } 6340b57cec5SDimitry Andric } 6350b57cec5SDimitry Andric } 6360b57cec5SDimitry Andric } 6370b57cec5SDimitry Andric 6387a6dacacSDimitry Andric bool GlobalMergeImpl::run(Module &M) { 6390b57cec5SDimitry Andric if (!EnableGlobalMerge) 6400b57cec5SDimitry Andric return false; 6410b57cec5SDimitry Andric 6420b57cec5SDimitry Andric IsMachO = Triple(M.getTargetTriple()).isOSBinFormatMachO(); 6430b57cec5SDimitry Andric 6440b57cec5SDimitry Andric auto &DL = M.getDataLayout(); 645*0fca6ea1SDimitry Andric MapVector<std::pair<unsigned, StringRef>, SmallVector<GlobalVariable *, 0>> 6460b57cec5SDimitry Andric Globals, ConstGlobals, BSSGlobals; 6470b57cec5SDimitry Andric bool Changed = false; 6480b57cec5SDimitry Andric setMustKeepGlobalVariables(M); 6490b57cec5SDimitry Andric 65081ad6265SDimitry Andric LLVM_DEBUG({ 65181ad6265SDimitry Andric dbgs() << "Number of GV that must be kept: " << 65281ad6265SDimitry Andric MustKeepGlobalVariables.size() << "\n"; 653bdd1243dSDimitry Andric for (const GlobalVariable *KeptGV : MustKeepGlobalVariables) 654bdd1243dSDimitry Andric dbgs() << "Kept: " << *KeptGV << "\n"; 65581ad6265SDimitry Andric }); 6560b57cec5SDimitry Andric // Grab all non-const globals. 6570b57cec5SDimitry Andric for (auto &GV : M.globals()) { 6580b57cec5SDimitry Andric // Merge is safe for "normal" internal or external globals only 6590b57cec5SDimitry Andric if (GV.isDeclaration() || GV.isThreadLocal() || GV.hasImplicitSection()) 6600b57cec5SDimitry Andric continue; 6610b57cec5SDimitry Andric 6620b57cec5SDimitry Andric // It's not safe to merge globals that may be preempted 663*0fca6ea1SDimitry Andric if (TM && !TM->shouldAssumeDSOLocal(&GV)) 6640b57cec5SDimitry Andric continue; 6650b57cec5SDimitry Andric 6667a6dacacSDimitry Andric if (!(Opt.MergeExternal && GV.hasExternalLinkage()) && 6670b57cec5SDimitry Andric !GV.hasInternalLinkage()) 6680b57cec5SDimitry Andric continue; 6690b57cec5SDimitry Andric 6700b57cec5SDimitry Andric PointerType *PT = dyn_cast<PointerType>(GV.getType()); 6710b57cec5SDimitry Andric assert(PT && "Global variable is not a pointer!"); 6720b57cec5SDimitry Andric 6730b57cec5SDimitry Andric unsigned AddressSpace = PT->getAddressSpace(); 6740b57cec5SDimitry Andric StringRef Section = GV.getSection(); 6750b57cec5SDimitry Andric 6760b57cec5SDimitry Andric // Ignore all 'special' globals. 6775f757f3fSDimitry Andric if (GV.getName().starts_with("llvm.") || GV.getName().starts_with(".llvm.")) 6780b57cec5SDimitry Andric continue; 6790b57cec5SDimitry Andric 6800b57cec5SDimitry Andric // Ignore all "required" globals: 6810b57cec5SDimitry Andric if (isMustKeepGlobalVariable(&GV)) 6820b57cec5SDimitry Andric continue; 6830b57cec5SDimitry Andric 68406c3fb27SDimitry Andric // Don't merge tagged globals, as each global should have its own unique 68506c3fb27SDimitry Andric // memory tag at runtime. TODO(hctim): This can be relaxed: constant globals 68606c3fb27SDimitry Andric // with compatible alignment and the same contents may be merged as long as 68706c3fb27SDimitry Andric // the globals occupy the same number of tag granules (i.e. `size_a / 16 == 68806c3fb27SDimitry Andric // size_b / 16`). 68906c3fb27SDimitry Andric if (GV.isTagged()) 69006c3fb27SDimitry Andric continue; 69106c3fb27SDimitry Andric 6920b57cec5SDimitry Andric Type *Ty = GV.getValueType(); 693*0fca6ea1SDimitry Andric TypeSize AllocSize = DL.getTypeAllocSize(Ty); 694*0fca6ea1SDimitry Andric if (AllocSize < Opt.MaxOffset && AllocSize >= Opt.MinSize) { 6950b57cec5SDimitry Andric if (TM && 6960b57cec5SDimitry Andric TargetLoweringObjectFile::getKindForGlobal(&GV, *TM).isBSS()) 6970b57cec5SDimitry Andric BSSGlobals[{AddressSpace, Section}].push_back(&GV); 6980b57cec5SDimitry Andric else if (GV.isConstant()) 6990b57cec5SDimitry Andric ConstGlobals[{AddressSpace, Section}].push_back(&GV); 7000b57cec5SDimitry Andric else 7010b57cec5SDimitry Andric Globals[{AddressSpace, Section}].push_back(&GV); 7020b57cec5SDimitry Andric } 7030b57cec5SDimitry Andric } 7040b57cec5SDimitry Andric 7050b57cec5SDimitry Andric for (auto &P : Globals) 7060b57cec5SDimitry Andric if (P.second.size() > 1) 7070b57cec5SDimitry Andric Changed |= doMerge(P.second, M, false, P.first.first); 7080b57cec5SDimitry Andric 7090b57cec5SDimitry Andric for (auto &P : BSSGlobals) 7100b57cec5SDimitry Andric if (P.second.size() > 1) 7110b57cec5SDimitry Andric Changed |= doMerge(P.second, M, false, P.first.first); 7120b57cec5SDimitry Andric 7130b57cec5SDimitry Andric if (EnableGlobalMergeOnConst) 7140b57cec5SDimitry Andric for (auto &P : ConstGlobals) 7150b57cec5SDimitry Andric if (P.second.size() > 1) 7160b57cec5SDimitry Andric Changed |= doMerge(P.second, M, true, P.first.first); 7170b57cec5SDimitry Andric 7180b57cec5SDimitry Andric return Changed; 7190b57cec5SDimitry Andric } 7200b57cec5SDimitry Andric 7210b57cec5SDimitry Andric Pass *llvm::createGlobalMergePass(const TargetMachine *TM, unsigned Offset, 7220b57cec5SDimitry Andric bool OnlyOptimizeForSize, 7230b57cec5SDimitry Andric bool MergeExternalByDefault) { 7240b57cec5SDimitry Andric bool MergeExternal = (EnableGlobalMergeOnExternal == cl::BOU_UNSET) ? 7250b57cec5SDimitry Andric MergeExternalByDefault : (EnableGlobalMergeOnExternal == cl::BOU_TRUE); 7260b57cec5SDimitry Andric return new GlobalMerge(TM, Offset, OnlyOptimizeForSize, MergeExternal); 7270b57cec5SDimitry Andric } 728