xref: /src/contrib/llvm-project/llvm/lib/CodeGen/GlobalMerge.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
1044eb2f6SDimitry Andric //===- GlobalMerge.cpp - Internal globals merging -------------------------===//
263faed5bSDimitry Andric //
3e6d15924SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4e6d15924SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5e6d15924SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
663faed5bSDimitry Andric //
763faed5bSDimitry Andric //===----------------------------------------------------------------------===//
8044eb2f6SDimitry Andric //
963faed5bSDimitry Andric // This pass merges globals with internal linkage into one. This way all the
1063faed5bSDimitry Andric // globals which were merged into a biggest one can be addressed using offsets
1163faed5bSDimitry Andric // from the same base pointer (no need for separate base pointer for each of the
1263faed5bSDimitry Andric // global). Such a transformation can significantly reduce the register pressure
1363faed5bSDimitry Andric // when many globals are involved.
1463faed5bSDimitry Andric //
1563faed5bSDimitry Andric // For example, consider the code which touches several global variables at
1663faed5bSDimitry Andric // once:
1763faed5bSDimitry Andric //
1863faed5bSDimitry Andric // static int foo[N], bar[N], baz[N];
1963faed5bSDimitry Andric //
2063faed5bSDimitry Andric // for (i = 0; i < N; ++i) {
2163faed5bSDimitry Andric //    foo[i] = bar[i] * baz[i];
2263faed5bSDimitry Andric // }
2363faed5bSDimitry Andric //
2463faed5bSDimitry Andric //  On ARM the addresses of 3 arrays should be kept in the registers, thus
2563faed5bSDimitry Andric //  this code has quite large register pressure (loop body):
2663faed5bSDimitry Andric //
2763faed5bSDimitry Andric //  ldr     r1, [r5], #4
2863faed5bSDimitry Andric //  ldr     r2, [r6], #4
2963faed5bSDimitry Andric //  mul     r1, r2, r1
3063faed5bSDimitry Andric //  str     r1, [r0], #4
3163faed5bSDimitry Andric //
3263faed5bSDimitry Andric //  Pass converts the code to something like:
3363faed5bSDimitry Andric //
3463faed5bSDimitry Andric //  static struct {
3563faed5bSDimitry Andric //    int foo[N];
3663faed5bSDimitry Andric //    int bar[N];
3763faed5bSDimitry Andric //    int baz[N];
3863faed5bSDimitry Andric //  } merged;
3963faed5bSDimitry Andric //
4063faed5bSDimitry Andric //  for (i = 0; i < N; ++i) {
4163faed5bSDimitry Andric //    merged.foo[i] = merged.bar[i] * merged.baz[i];
4263faed5bSDimitry Andric //  }
4363faed5bSDimitry Andric //
4463faed5bSDimitry Andric //  and in ARM code this becomes:
4563faed5bSDimitry Andric //
4663faed5bSDimitry Andric //  ldr     r0, [r5, #40]
4763faed5bSDimitry Andric //  ldr     r1, [r5, #80]
4863faed5bSDimitry Andric //  mul     r0, r1, r0
4963faed5bSDimitry Andric //  str     r0, [r5], #4
5063faed5bSDimitry Andric //
5163faed5bSDimitry Andric //  note that we saved 2 registers here almostly "for free".
525a5ac124SDimitry Andric //
535a5ac124SDimitry Andric // However, merging globals can have tradeoffs:
545a5ac124SDimitry Andric // - it confuses debuggers, tools, and users
555a5ac124SDimitry Andric // - it makes linker optimizations less useful (order files, LOHs, ...)
565a5ac124SDimitry Andric // - it forces usage of indexed addressing (which isn't necessarily "free")
575a5ac124SDimitry Andric // - it can increase register pressure when the uses are disparate enough.
585a5ac124SDimitry Andric //
595a5ac124SDimitry Andric // We use heuristics to discover the best global grouping we can (cf cl::opts).
60044eb2f6SDimitry Andric //
6163faed5bSDimitry Andric // ===---------------------------------------------------------------------===//
6263faed5bSDimitry Andric 
634df029ccSDimitry Andric #include "llvm/CodeGen/GlobalMerge.h"
64044eb2f6SDimitry Andric #include "llvm/ADT/BitVector.h"
655a5ac124SDimitry Andric #include "llvm/ADT/DenseMap.h"
66ac9a064cSDimitry Andric #include "llvm/ADT/MapVector.h"
67e3b55780SDimitry Andric #include "llvm/ADT/SetVector.h"
68044eb2f6SDimitry Andric #include "llvm/ADT/SmallVector.h"
694a16efa3SDimitry Andric #include "llvm/ADT/Statistic.h"
70044eb2f6SDimitry Andric #include "llvm/ADT/StringRef.h"
71044eb2f6SDimitry Andric #include "llvm/ADT/Twine.h"
7267c32a98SDimitry Andric #include "llvm/CodeGen/Passes.h"
73044eb2f6SDimitry Andric #include "llvm/IR/BasicBlock.h"
744a16efa3SDimitry Andric #include "llvm/IR/Constants.h"
754a16efa3SDimitry Andric #include "llvm/IR/DataLayout.h"
764a16efa3SDimitry Andric #include "llvm/IR/DerivedTypes.h"
774a16efa3SDimitry Andric #include "llvm/IR/Function.h"
78044eb2f6SDimitry Andric #include "llvm/IR/GlobalAlias.h"
79044eb2f6SDimitry Andric #include "llvm/IR/GlobalValue.h"
804a16efa3SDimitry Andric #include "llvm/IR/GlobalVariable.h"
81044eb2f6SDimitry Andric #include "llvm/IR/Instruction.h"
824a16efa3SDimitry Andric #include "llvm/IR/Module.h"
83044eb2f6SDimitry Andric #include "llvm/IR/Type.h"
84044eb2f6SDimitry Andric #include "llvm/IR/Use.h"
85044eb2f6SDimitry Andric #include "llvm/IR/User.h"
86706b4fc4SDimitry Andric #include "llvm/InitializePasses.h"
87cfca06d7SDimitry Andric #include "llvm/MC/SectionKind.h"
8863faed5bSDimitry Andric #include "llvm/Pass.h"
89044eb2f6SDimitry Andric #include "llvm/Support/Casting.h"
904a16efa3SDimitry Andric #include "llvm/Support/CommandLine.h"
915a5ac124SDimitry Andric #include "llvm/Support/Debug.h"
925a5ac124SDimitry Andric #include "llvm/Support/raw_ostream.h"
93eb11fae6SDimitry Andric #include "llvm/Target/TargetLoweringObjectFile.h"
94044eb2f6SDimitry Andric #include "llvm/Target/TargetMachine.h"
957fa27ce4SDimitry Andric #include "llvm/TargetParser/Triple.h"
965a5ac124SDimitry Andric #include <algorithm>
97044eb2f6SDimitry Andric #include <cassert>
98044eb2f6SDimitry Andric #include <cstddef>
99044eb2f6SDimitry Andric #include <cstdint>
100044eb2f6SDimitry Andric #include <string>
101044eb2f6SDimitry Andric #include <vector>
102044eb2f6SDimitry Andric 
10363faed5bSDimitry Andric using namespace llvm;
10463faed5bSDimitry Andric 
1055ca98fd9SDimitry Andric #define DEBUG_TYPE "global-merge"
1065ca98fd9SDimitry Andric 
1075a5ac124SDimitry Andric // FIXME: This is only useful as a last-resort way to disable the pass.
1085ca98fd9SDimitry Andric static cl::opt<bool>
1095ca98fd9SDimitry Andric EnableGlobalMerge("enable-global-merge", cl::Hidden,
1105a5ac124SDimitry Andric                   cl::desc("Enable the global merge pass"),
1115a5ac124SDimitry Andric                   cl::init(true));
1125a5ac124SDimitry Andric 
11301095a5dSDimitry Andric static cl::opt<unsigned>
11401095a5dSDimitry Andric GlobalMergeMaxOffset("global-merge-max-offset", cl::Hidden,
11501095a5dSDimitry Andric                      cl::desc("Set maximum offset for global merge pass"),
11601095a5dSDimitry Andric                      cl::init(0));
11701095a5dSDimitry Andric 
1185a5ac124SDimitry Andric static cl::opt<bool> GlobalMergeGroupByUse(
1195a5ac124SDimitry Andric     "global-merge-group-by-use", cl::Hidden,
1205a5ac124SDimitry Andric     cl::desc("Improve global merge pass to look at uses"), cl::init(true));
1215a5ac124SDimitry Andric 
1225a5ac124SDimitry Andric static cl::opt<bool> GlobalMergeIgnoreSingleUse(
1235a5ac124SDimitry Andric     "global-merge-ignore-single-use", cl::Hidden,
1245a5ac124SDimitry Andric     cl::desc("Improve global merge pass to ignore globals only used alone"),
1255ca98fd9SDimitry Andric     cl::init(true));
1265ca98fd9SDimitry Andric 
1274a16efa3SDimitry Andric static cl::opt<bool>
1284a16efa3SDimitry Andric EnableGlobalMergeOnConst("global-merge-on-const", cl::Hidden,
1294a16efa3SDimitry Andric                          cl::desc("Enable global merge pass on constants"),
1304a16efa3SDimitry Andric                          cl::init(false));
1314a16efa3SDimitry Andric 
1325ca98fd9SDimitry Andric // FIXME: this could be a transitional option, and we probably need to remove
1335ca98fd9SDimitry Andric // it if only we are sure this optimization could always benefit all targets.
134dd58ef01SDimitry Andric static cl::opt<cl::boolOrDefault>
1355ca98fd9SDimitry Andric EnableGlobalMergeOnExternal("global-merge-on-external", cl::Hidden,
136dd58ef01SDimitry Andric      cl::desc("Enable global merge pass on external linkage"));
1375ca98fd9SDimitry Andric 
138ac9a064cSDimitry Andric static cl::opt<unsigned>
139ac9a064cSDimitry Andric     GlobalMergeMinDataSize("global-merge-min-data-size",
140ac9a064cSDimitry Andric                            cl::desc("The minimum size in bytes of each global "
141ac9a064cSDimitry Andric                                     "that should considered in merging."),
142ac9a064cSDimitry Andric                            cl::init(0), cl::Hidden);
143ac9a064cSDimitry Andric 
14463faed5bSDimitry Andric STATISTIC(NumMerged, "Number of globals merged");
145044eb2f6SDimitry Andric 
14663faed5bSDimitry Andric namespace {
147044eb2f6SDimitry Andric 
1484df029ccSDimitry Andric class GlobalMergeImpl {
149044eb2f6SDimitry Andric   const TargetMachine *TM = nullptr;
1504df029ccSDimitry Andric   GlobalMergeOptions Opt;
1517fa27ce4SDimitry Andric   bool IsMachO = false;
15201095a5dSDimitry Andric 
1534df029ccSDimitry Andric private:
1544df029ccSDimitry Andric   bool doMerge(SmallVectorImpl<GlobalVariable *> &Globals, Module &M,
1554df029ccSDimitry Andric                bool isConst, unsigned AddrSpace) const;
156044eb2f6SDimitry Andric 
157eb11fae6SDimitry Andric   /// Merge everything in \p Globals for which the corresponding bit
1585a5ac124SDimitry Andric   /// in \p GlobalSet is set.
159dd58ef01SDimitry Andric   bool doMerge(const SmallVectorImpl<GlobalVariable *> &Globals,
1605a5ac124SDimitry Andric                const BitVector &GlobalSet, Module &M, bool isConst,
1615a5ac124SDimitry Andric                unsigned AddrSpace) const;
1624a16efa3SDimitry Andric 
163eb11fae6SDimitry Andric   /// Check if the given variable has been identified as must keep
1644a16efa3SDimitry Andric   /// \pre setMustKeepGlobalVariables must have been called on the Module that
1654a16efa3SDimitry Andric   ///      contains GV
isMustKeepGlobalVariable(const GlobalVariable * GV) const1664a16efa3SDimitry Andric   bool isMustKeepGlobalVariable(const GlobalVariable *GV) const {
1674a16efa3SDimitry Andric     return MustKeepGlobalVariables.count(GV);
1684a16efa3SDimitry Andric   }
1694a16efa3SDimitry Andric 
1704a16efa3SDimitry Andric   /// Collect every variables marked as "used" or used in a landing pad
1714a16efa3SDimitry Andric   /// instruction for this Module.
1724a16efa3SDimitry Andric   void setMustKeepGlobalVariables(Module &M);
1734a16efa3SDimitry Andric 
1744a16efa3SDimitry Andric   /// Collect every variables marked as "used"
175eb11fae6SDimitry Andric   void collectUsedGlobalVariables(Module &M, StringRef Name);
1764a16efa3SDimitry Andric 
1774a16efa3SDimitry Andric   /// Keep track of the GlobalVariable that must not be merged away
178e3b55780SDimitry Andric   SmallSetVector<const GlobalVariable *, 16> MustKeepGlobalVariables;
17963faed5bSDimitry Andric 
18063faed5bSDimitry Andric public:
GlobalMergeImpl(const TargetMachine * TM,GlobalMergeOptions Opt)1814df029ccSDimitry Andric   GlobalMergeImpl(const TargetMachine *TM, GlobalMergeOptions Opt)
1824df029ccSDimitry Andric       : TM(TM), Opt(Opt) {}
1834df029ccSDimitry Andric   bool run(Module &M);
1844df029ccSDimitry Andric };
1854df029ccSDimitry Andric 
1864df029ccSDimitry Andric class GlobalMerge : public FunctionPass {
1874df029ccSDimitry Andric   const TargetMachine *TM = nullptr;
1884df029ccSDimitry Andric   GlobalMergeOptions Opt;
1894df029ccSDimitry Andric 
1904df029ccSDimitry Andric public:
19163faed5bSDimitry Andric   static char ID; // Pass identification, replacement for typeid.
192044eb2f6SDimitry Andric 
GlobalMerge()1934df029ccSDimitry Andric   explicit GlobalMerge() : FunctionPass(ID) {
1944df029ccSDimitry Andric     Opt.MaxOffset = GlobalMergeMaxOffset;
19501095a5dSDimitry Andric     initializeGlobalMergePass(*PassRegistry::getPassRegistry());
19601095a5dSDimitry Andric   }
19701095a5dSDimitry Andric 
GlobalMerge(const TargetMachine * TM,unsigned MaximalOffset,bool OnlyOptimizeForSize,bool MergeExternalGlobals)19801095a5dSDimitry Andric   explicit GlobalMerge(const TargetMachine *TM, unsigned MaximalOffset,
19901095a5dSDimitry Andric                        bool OnlyOptimizeForSize, bool MergeExternalGlobals)
2004df029ccSDimitry Andric       : FunctionPass(ID), TM(TM) {
2014df029ccSDimitry Andric     Opt.MaxOffset = MaximalOffset;
2024df029ccSDimitry Andric     Opt.SizeOnly = OnlyOptimizeForSize;
2034df029ccSDimitry Andric     Opt.MergeExternal = MergeExternalGlobals;
20463faed5bSDimitry Andric     initializeGlobalMergePass(*PassRegistry::getPassRegistry());
20563faed5bSDimitry Andric   }
20663faed5bSDimitry Andric 
doInitialization(Module & M)2074df029ccSDimitry Andric   bool doInitialization(Module &M) override {
208ac9a064cSDimitry Andric     auto GetSmallDataLimit = [](Module &M) -> std::optional<uint64_t> {
209ac9a064cSDimitry Andric       Metadata *SDL = M.getModuleFlag("SmallDataLimit");
210ac9a064cSDimitry Andric       if (!SDL)
211ac9a064cSDimitry Andric         return std::nullopt;
212ac9a064cSDimitry Andric       return mdconst::extract<ConstantInt>(SDL)->getZExtValue();
213ac9a064cSDimitry Andric     };
214ac9a064cSDimitry Andric     if (GlobalMergeMinDataSize.getNumOccurrences())
215ac9a064cSDimitry Andric       Opt.MinSize = GlobalMergeMinDataSize;
216ac9a064cSDimitry Andric     else if (auto SDL = GetSmallDataLimit(M); SDL && *SDL > 0)
217ac9a064cSDimitry Andric       Opt.MinSize = *SDL + 1;
218ac9a064cSDimitry Andric     else
219ac9a064cSDimitry Andric       Opt.MinSize = 0;
220ac9a064cSDimitry Andric 
2214df029ccSDimitry Andric     GlobalMergeImpl P(TM, Opt);
2224df029ccSDimitry Andric     return P.run(M);
2234df029ccSDimitry Andric   }
runOnFunction(Function & F)2244df029ccSDimitry Andric   bool runOnFunction(Function &F) override { return false; }
22563faed5bSDimitry Andric 
getPassName() const226b915e9e0SDimitry Andric   StringRef getPassName() const override { return "Merge internal globals"; }
22763faed5bSDimitry Andric 
getAnalysisUsage(AnalysisUsage & AU) const2285ca98fd9SDimitry Andric   void getAnalysisUsage(AnalysisUsage &AU) const override {
22963faed5bSDimitry Andric     AU.setPreservesCFG();
23063faed5bSDimitry Andric     FunctionPass::getAnalysisUsage(AU);
23163faed5bSDimitry Andric   }
23263faed5bSDimitry Andric };
233044eb2f6SDimitry Andric 
23463faed5bSDimitry Andric } // end anonymous namespace
23563faed5bSDimitry Andric 
run(Module & M,ModuleAnalysisManager &)2364df029ccSDimitry Andric PreservedAnalyses GlobalMergePass::run(Module &M, ModuleAnalysisManager &) {
2374df029ccSDimitry Andric   GlobalMergeImpl P(TM, Options);
2384df029ccSDimitry Andric   bool Changed = P.run(M);
2394df029ccSDimitry Andric   if (!Changed)
2404df029ccSDimitry Andric     return PreservedAnalyses::all();
2414df029ccSDimitry Andric 
2424df029ccSDimitry Andric   PreservedAnalyses PA;
2434df029ccSDimitry Andric   PA.preserveSet<CFGAnalyses>();
2444df029ccSDimitry Andric   return PA;
2454df029ccSDimitry Andric }
2464df029ccSDimitry Andric 
24763faed5bSDimitry Andric char GlobalMerge::ID = 0;
248044eb2f6SDimitry Andric 
249ab44ce3dSDimitry Andric INITIALIZE_PASS(GlobalMerge, DEBUG_TYPE, "Merge global variables", false, false)
25063faed5bSDimitry Andric 
doMerge(SmallVectorImpl<GlobalVariable * > & Globals,Module & M,bool isConst,unsigned AddrSpace) const2514df029ccSDimitry Andric bool GlobalMergeImpl::doMerge(SmallVectorImpl<GlobalVariable *> &Globals,
2524df029ccSDimitry Andric                               Module &M, bool isConst,
2534df029ccSDimitry Andric                               unsigned AddrSpace) const {
254ee8648bdSDimitry Andric   auto &DL = M.getDataLayout();
25563faed5bSDimitry Andric   // FIXME: Find better heuristics
256e6d15924SDimitry Andric   llvm::stable_sort(
257e6d15924SDimitry Andric       Globals, [&DL](const GlobalVariable *GV1, const GlobalVariable *GV2) {
258b60736ecSDimitry Andric         // We don't support scalable global variables.
259e3b55780SDimitry Andric         return DL.getTypeAllocSize(GV1->getValueType()).getFixedValue() <
260e3b55780SDimitry Andric                DL.getTypeAllocSize(GV2->getValueType()).getFixedValue();
2615ca98fd9SDimitry Andric       });
26263faed5bSDimitry Andric 
2635a5ac124SDimitry Andric   // If we want to just blindly group all globals together, do so.
2645a5ac124SDimitry Andric   if (!GlobalMergeGroupByUse) {
2655a5ac124SDimitry Andric     BitVector AllGlobals(Globals.size());
2665a5ac124SDimitry Andric     AllGlobals.set();
2675a5ac124SDimitry Andric     return doMerge(Globals, AllGlobals, M, isConst, AddrSpace);
2685a5ac124SDimitry Andric   }
2695a5ac124SDimitry Andric 
2705a5ac124SDimitry Andric   // If we want to be smarter, look at all uses of each global, to try to
2715a5ac124SDimitry Andric   // discover all sets of globals used together, and how many times each of
272dd58ef01SDimitry Andric   // these sets occurred.
2735a5ac124SDimitry Andric   //
2745a5ac124SDimitry Andric   // Keep this reasonably efficient, by having an append-only list of all sets
2755a5ac124SDimitry Andric   // discovered so far (UsedGlobalSet), and mapping each "together-ness" unit of
2765a5ac124SDimitry Andric   // code (currently, a Function) to the set of globals seen so far that are
2775a5ac124SDimitry Andric   // used together in that unit (GlobalUsesByFunction).
2785a5ac124SDimitry Andric   //
279eb11fae6SDimitry Andric   // When we look at the Nth global, we know that any new set is either:
2805a5ac124SDimitry Andric   // - the singleton set {N}, containing this global only, or
2815a5ac124SDimitry Andric   // - the union of {N} and a previously-discovered set, containing some
2825a5ac124SDimitry Andric   //   combination of the previous N-1 globals.
2835a5ac124SDimitry Andric   // Using that knowledge, when looking at the Nth global, we can keep:
2845a5ac124SDimitry Andric   // - a reference to the singleton set {N} (CurGVOnlySetIdx)
2855a5ac124SDimitry Andric   // - a list mapping each previous set to its union with {N} (EncounteredUGS),
2865a5ac124SDimitry Andric   //   if it actually occurs.
2875a5ac124SDimitry Andric 
2885a5ac124SDimitry Andric   // We keep track of the sets of globals used together "close enough".
2895a5ac124SDimitry Andric   struct UsedGlobalSet {
2905a5ac124SDimitry Andric     BitVector Globals;
291044eb2f6SDimitry Andric     unsigned UsageCount = 1;
292044eb2f6SDimitry Andric 
293044eb2f6SDimitry Andric     UsedGlobalSet(size_t Size) : Globals(Size) {}
2945a5ac124SDimitry Andric   };
2955a5ac124SDimitry Andric 
2965a5ac124SDimitry Andric   // Each set is unique in UsedGlobalSets.
2975a5ac124SDimitry Andric   std::vector<UsedGlobalSet> UsedGlobalSets;
2985a5ac124SDimitry Andric 
2995a5ac124SDimitry Andric   // Avoid repeating the create-global-set pattern.
3005a5ac124SDimitry Andric   auto CreateGlobalSet = [&]() -> UsedGlobalSet & {
3015a5ac124SDimitry Andric     UsedGlobalSets.emplace_back(Globals.size());
3025a5ac124SDimitry Andric     return UsedGlobalSets.back();
3035a5ac124SDimitry Andric   };
3045a5ac124SDimitry Andric 
3055a5ac124SDimitry Andric   // The first set is the empty set.
3065a5ac124SDimitry Andric   CreateGlobalSet().UsageCount = 0;
3075a5ac124SDimitry Andric 
3085a5ac124SDimitry Andric   // We define "close enough" to be "in the same function".
3095a5ac124SDimitry Andric   // FIXME: Grouping uses by function is way too aggressive, so we should have
3105a5ac124SDimitry Andric   // a better metric for distance between uses.
3115a5ac124SDimitry Andric   // The obvious alternative would be to group by BasicBlock, but that's in
3125a5ac124SDimitry Andric   // turn too conservative..
3135a5ac124SDimitry Andric   // Anything in between wouldn't be trivial to compute, so just stick with
3145a5ac124SDimitry Andric   // per-function grouping.
3155a5ac124SDimitry Andric 
3165a5ac124SDimitry Andric   // The value type is an index into UsedGlobalSets.
3175a5ac124SDimitry Andric   // The default (0) conveniently points to the empty set.
3185a5ac124SDimitry Andric   DenseMap<Function *, size_t /*UsedGlobalSetIdx*/> GlobalUsesByFunction;
3195a5ac124SDimitry Andric 
3205a5ac124SDimitry Andric   // Now, look at each merge-eligible global in turn.
3215a5ac124SDimitry Andric 
3225a5ac124SDimitry Andric   // Keep track of the sets we already encountered to which we added the
3235a5ac124SDimitry Andric   // current global.
3245a5ac124SDimitry Andric   // Each element matches the same-index element in UsedGlobalSets.
3255a5ac124SDimitry Andric   // This lets us efficiently tell whether a set has already been expanded to
3265a5ac124SDimitry Andric   // include the current global.
3275a5ac124SDimitry Andric   std::vector<size_t> EncounteredUGS;
3285a5ac124SDimitry Andric 
3295a5ac124SDimitry Andric   for (size_t GI = 0, GE = Globals.size(); GI != GE; ++GI) {
3305a5ac124SDimitry Andric     GlobalVariable *GV = Globals[GI];
3315a5ac124SDimitry Andric 
332ac9a064cSDimitry Andric     // Reset the encountered sets for this global and grow it in case we created
333ac9a064cSDimitry Andric     // new sets for the previous global.
334ac9a064cSDimitry Andric     EncounteredUGS.assign(UsedGlobalSets.size(), 0);
3355a5ac124SDimitry Andric 
3365a5ac124SDimitry Andric     // We might need to create a set that only consists of the current global.
3375a5ac124SDimitry Andric     // Keep track of its index into UsedGlobalSets.
3385a5ac124SDimitry Andric     size_t CurGVOnlySetIdx = 0;
3395a5ac124SDimitry Andric 
3405a5ac124SDimitry Andric     // For each global, look at all its Uses.
3415a5ac124SDimitry Andric     for (auto &U : GV->uses()) {
3425a5ac124SDimitry Andric       // This Use might be a ConstantExpr.  We're interested in Instruction
3435a5ac124SDimitry Andric       // users, so look through ConstantExpr...
3445a5ac124SDimitry Andric       Use *UI, *UE;
3455a5ac124SDimitry Andric       if (ConstantExpr *CE = dyn_cast<ConstantExpr>(U.getUser())) {
34685d8b2bbSDimitry Andric         if (CE->use_empty())
34785d8b2bbSDimitry Andric           continue;
3485a5ac124SDimitry Andric         UI = &*CE->use_begin();
3495a5ac124SDimitry Andric         UE = nullptr;
3505a5ac124SDimitry Andric       } else if (isa<Instruction>(U.getUser())) {
3515a5ac124SDimitry Andric         UI = &U;
3525a5ac124SDimitry Andric         UE = UI->getNext();
3535a5ac124SDimitry Andric       } else {
3545a5ac124SDimitry Andric         continue;
3555a5ac124SDimitry Andric       }
3565a5ac124SDimitry Andric 
3575a5ac124SDimitry Andric       // ...to iterate on all the instruction users of the global.
3585a5ac124SDimitry Andric       // Note that we iterate on Uses and not on Users to be able to getNext().
3595a5ac124SDimitry Andric       for (; UI != UE; UI = UI->getNext()) {
3605a5ac124SDimitry Andric         Instruction *I = dyn_cast<Instruction>(UI->getUser());
3615a5ac124SDimitry Andric         if (!I)
3625a5ac124SDimitry Andric           continue;
3635a5ac124SDimitry Andric 
3645a5ac124SDimitry Andric         Function *ParentFn = I->getParent()->getParent();
36585d8b2bbSDimitry Andric 
36685d8b2bbSDimitry Andric         // If we're only optimizing for size, ignore non-minsize functions.
3674df029ccSDimitry Andric         if (Opt.SizeOnly && !ParentFn->hasMinSize())
36885d8b2bbSDimitry Andric           continue;
36985d8b2bbSDimitry Andric 
3705a5ac124SDimitry Andric         size_t UGSIdx = GlobalUsesByFunction[ParentFn];
3715a5ac124SDimitry Andric 
3725a5ac124SDimitry Andric         // If this is the first global the basic block uses, map it to the set
3735a5ac124SDimitry Andric         // consisting of this global only.
3745a5ac124SDimitry Andric         if (!UGSIdx) {
3755a5ac124SDimitry Andric           // If that set doesn't exist yet, create it.
3765a5ac124SDimitry Andric           if (!CurGVOnlySetIdx) {
3775a5ac124SDimitry Andric             CurGVOnlySetIdx = UsedGlobalSets.size();
3785a5ac124SDimitry Andric             CreateGlobalSet().Globals.set(GI);
3795a5ac124SDimitry Andric           } else {
3805a5ac124SDimitry Andric             ++UsedGlobalSets[CurGVOnlySetIdx].UsageCount;
3815a5ac124SDimitry Andric           }
3825a5ac124SDimitry Andric 
3835a5ac124SDimitry Andric           GlobalUsesByFunction[ParentFn] = CurGVOnlySetIdx;
3845a5ac124SDimitry Andric           continue;
3855a5ac124SDimitry Andric         }
3865a5ac124SDimitry Andric 
3875a5ac124SDimitry Andric         // If we already encountered this BB, just increment the counter.
3885a5ac124SDimitry Andric         if (UsedGlobalSets[UGSIdx].Globals.test(GI)) {
3895a5ac124SDimitry Andric           ++UsedGlobalSets[UGSIdx].UsageCount;
3905a5ac124SDimitry Andric           continue;
3915a5ac124SDimitry Andric         }
3925a5ac124SDimitry Andric 
3935a5ac124SDimitry Andric         // If not, the previous set wasn't actually used in this function.
3945a5ac124SDimitry Andric         --UsedGlobalSets[UGSIdx].UsageCount;
3955a5ac124SDimitry Andric 
3965a5ac124SDimitry Andric         // If we already expanded the previous set to include this global, just
3975a5ac124SDimitry Andric         // reuse that expanded set.
3985a5ac124SDimitry Andric         if (size_t ExpandedIdx = EncounteredUGS[UGSIdx]) {
3995a5ac124SDimitry Andric           ++UsedGlobalSets[ExpandedIdx].UsageCount;
4005a5ac124SDimitry Andric           GlobalUsesByFunction[ParentFn] = ExpandedIdx;
4015a5ac124SDimitry Andric           continue;
4025a5ac124SDimitry Andric         }
4035a5ac124SDimitry Andric 
4045a5ac124SDimitry Andric         // If not, create a new set consisting of the union of the previous set
4055a5ac124SDimitry Andric         // and this global.  Mark it as encountered, so we can reuse it later.
4065a5ac124SDimitry Andric         GlobalUsesByFunction[ParentFn] = EncounteredUGS[UGSIdx] =
4075a5ac124SDimitry Andric             UsedGlobalSets.size();
4085a5ac124SDimitry Andric 
4095a5ac124SDimitry Andric         UsedGlobalSet &NewUGS = CreateGlobalSet();
4105a5ac124SDimitry Andric         NewUGS.Globals.set(GI);
4115a5ac124SDimitry Andric         NewUGS.Globals |= UsedGlobalSets[UGSIdx].Globals;
4125a5ac124SDimitry Andric       }
4135a5ac124SDimitry Andric     }
4145a5ac124SDimitry Andric   }
4155a5ac124SDimitry Andric 
4165a5ac124SDimitry Andric   // Now we found a bunch of sets of globals used together.  We accumulated
4175a5ac124SDimitry Andric   // the number of times we encountered the sets (i.e., the number of blocks
4185a5ac124SDimitry Andric   // that use that exact set of globals).
4195a5ac124SDimitry Andric   //
4205a5ac124SDimitry Andric   // Multiply that by the size of the set to give us a crude profitability
4215a5ac124SDimitry Andric   // metric.
422e6d15924SDimitry Andric   llvm::stable_sort(UsedGlobalSets,
4235a5ac124SDimitry Andric                     [](const UsedGlobalSet &UGS1, const UsedGlobalSet &UGS2) {
4245a5ac124SDimitry Andric                       return UGS1.Globals.count() * UGS1.UsageCount <
4255a5ac124SDimitry Andric                              UGS2.Globals.count() * UGS2.UsageCount;
4265a5ac124SDimitry Andric                     });
4275a5ac124SDimitry Andric 
4285a5ac124SDimitry Andric   // We can choose to merge all globals together, but ignore globals never used
4295a5ac124SDimitry Andric   // with another global.  This catches the obviously non-profitable cases of
4305a5ac124SDimitry Andric   // having a single global, but is aggressive enough for any other case.
4315a5ac124SDimitry Andric   if (GlobalMergeIgnoreSingleUse) {
4325a5ac124SDimitry Andric     BitVector AllGlobals(Globals.size());
433f65dcba8SDimitry Andric     for (const UsedGlobalSet &UGS : llvm::reverse(UsedGlobalSets)) {
4345a5ac124SDimitry Andric       if (UGS.UsageCount == 0)
4355a5ac124SDimitry Andric         continue;
4365a5ac124SDimitry Andric       if (UGS.Globals.count() > 1)
4375a5ac124SDimitry Andric         AllGlobals |= UGS.Globals;
4385a5ac124SDimitry Andric     }
4395a5ac124SDimitry Andric     return doMerge(Globals, AllGlobals, M, isConst, AddrSpace);
4405a5ac124SDimitry Andric   }
4415a5ac124SDimitry Andric 
4425a5ac124SDimitry Andric   // Starting from the sets with the best (=biggest) profitability, find a
4435a5ac124SDimitry Andric   // good combination.
4445a5ac124SDimitry Andric   // The ideal (and expensive) solution can only be found by trying all
4455a5ac124SDimitry Andric   // combinations, looking for the one with the best profitability.
4465a5ac124SDimitry Andric   // Don't be smart about it, and just pick the first compatible combination,
4475a5ac124SDimitry Andric   // starting with the sets with the best profitability.
4485a5ac124SDimitry Andric   BitVector PickedGlobals(Globals.size());
4495a5ac124SDimitry Andric   bool Changed = false;
4505a5ac124SDimitry Andric 
451f65dcba8SDimitry Andric   for (const UsedGlobalSet &UGS : llvm::reverse(UsedGlobalSets)) {
4525a5ac124SDimitry Andric     if (UGS.UsageCount == 0)
4535a5ac124SDimitry Andric       continue;
4545a5ac124SDimitry Andric     if (PickedGlobals.anyCommon(UGS.Globals))
4555a5ac124SDimitry Andric       continue;
4565a5ac124SDimitry Andric     PickedGlobals |= UGS.Globals;
4575a5ac124SDimitry Andric     // If the set only contains one global, there's no point in merging.
4585a5ac124SDimitry Andric     // Ignore the global for inclusion in other sets though, so keep it in
4595a5ac124SDimitry Andric     // PickedGlobals.
4605a5ac124SDimitry Andric     if (UGS.Globals.count() < 2)
4615a5ac124SDimitry Andric       continue;
4625a5ac124SDimitry Andric     Changed |= doMerge(Globals, UGS.Globals, M, isConst, AddrSpace);
4635a5ac124SDimitry Andric   }
4645a5ac124SDimitry Andric 
4655a5ac124SDimitry Andric   return Changed;
4665a5ac124SDimitry Andric }
4675a5ac124SDimitry Andric 
doMerge(const SmallVectorImpl<GlobalVariable * > & Globals,const BitVector & GlobalSet,Module & M,bool isConst,unsigned AddrSpace) const4684df029ccSDimitry Andric bool GlobalMergeImpl::doMerge(const SmallVectorImpl<GlobalVariable *> &Globals,
4694df029ccSDimitry Andric                               const BitVector &GlobalSet, Module &M,
4704df029ccSDimitry Andric                               bool isConst, unsigned AddrSpace) const {
471dd58ef01SDimitry Andric   assert(Globals.size() > 1);
4725a5ac124SDimitry Andric 
47363faed5bSDimitry Andric   Type *Int32Ty = Type::getInt32Ty(M.getContext());
474eb11fae6SDimitry Andric   Type *Int8Ty = Type::getInt8Ty(M.getContext());
475ee8648bdSDimitry Andric   auto &DL = M.getDataLayout();
47663faed5bSDimitry Andric 
477eb11fae6SDimitry Andric   LLVM_DEBUG(dbgs() << " Trying to merge set, starts with #"
4785a5ac124SDimitry Andric                     << GlobalSet.find_first() << "\n");
4795a5ac124SDimitry Andric 
480eb11fae6SDimitry Andric   bool Changed = false;
4815a5ac124SDimitry Andric   ssize_t i = GlobalSet.find_first();
4825a5ac124SDimitry Andric   while (i != -1) {
4835a5ac124SDimitry Andric     ssize_t j = 0;
48463faed5bSDimitry Andric     uint64_t MergedSize = 0;
48563faed5bSDimitry Andric     std::vector<Type*> Tys;
48663faed5bSDimitry Andric     std::vector<Constant*> Inits;
487eb11fae6SDimitry Andric     std::vector<unsigned> StructIdxs;
4885ca98fd9SDimitry Andric 
489b915e9e0SDimitry Andric     bool HasExternal = false;
490b915e9e0SDimitry Andric     StringRef FirstExternalName;
4911d5ae102SDimitry Andric     Align MaxAlign;
492eb11fae6SDimitry Andric     unsigned CurIdx = 0;
4935a5ac124SDimitry Andric     for (j = i; j != -1; j = GlobalSet.find_next(j)) {
494dd58ef01SDimitry Andric       Type *Ty = Globals[j]->getValueType();
495d8e91e46SDimitry Andric 
496d8e91e46SDimitry Andric       // Make sure we use the same alignment AsmPrinter would use.
497cfca06d7SDimitry Andric       Align Alignment = DL.getPreferredAlign(Globals[j]);
4981d5ae102SDimitry Andric       unsigned Padding = alignTo(MergedSize, Alignment) - MergedSize;
499eb11fae6SDimitry Andric       MergedSize += Padding;
500ee8648bdSDimitry Andric       MergedSize += DL.getTypeAllocSize(Ty);
5014df029ccSDimitry Andric       if (MergedSize > Opt.MaxOffset) {
50263faed5bSDimitry Andric         break;
50363faed5bSDimitry Andric       }
504eb11fae6SDimitry Andric       if (Padding) {
505eb11fae6SDimitry Andric         Tys.push_back(ArrayType::get(Int8Ty, Padding));
506eb11fae6SDimitry Andric         Inits.push_back(ConstantAggregateZero::get(Tys.back()));
507eb11fae6SDimitry Andric         ++CurIdx;
508eb11fae6SDimitry Andric       }
50963faed5bSDimitry Andric       Tys.push_back(Ty);
51063faed5bSDimitry Andric       Inits.push_back(Globals[j]->getInitializer());
511eb11fae6SDimitry Andric       StructIdxs.push_back(CurIdx++);
512eb11fae6SDimitry Andric 
5131d5ae102SDimitry Andric       MaxAlign = std::max(MaxAlign, Alignment);
514b915e9e0SDimitry Andric 
515b915e9e0SDimitry Andric       if (Globals[j]->hasExternalLinkage() && !HasExternal) {
516b915e9e0SDimitry Andric         HasExternal = true;
517b915e9e0SDimitry Andric         FirstExternalName = Globals[j]->getName();
518b915e9e0SDimitry Andric       }
51963faed5bSDimitry Andric     }
52063faed5bSDimitry Andric 
521eb11fae6SDimitry Andric     // Exit early if there is only one global to merge.
522eb11fae6SDimitry Andric     if (Tys.size() < 2) {
523eb11fae6SDimitry Andric       i = j;
524eb11fae6SDimitry Andric       continue;
525eb11fae6SDimitry Andric     }
526eb11fae6SDimitry Andric 
527b915e9e0SDimitry Andric     // If merged variables doesn't have external linkage, we needn't to expose
528b915e9e0SDimitry Andric     // the symbol after merging.
529b915e9e0SDimitry Andric     GlobalValue::LinkageTypes Linkage = HasExternal
530b915e9e0SDimitry Andric                                             ? GlobalValue::ExternalLinkage
531b915e9e0SDimitry Andric                                             : GlobalValue::InternalLinkage;
532eb11fae6SDimitry Andric     // Use a packed struct so we can control alignment.
533eb11fae6SDimitry Andric     StructType *MergedTy = StructType::get(M.getContext(), Tys, true);
53463faed5bSDimitry Andric     Constant *MergedInit = ConstantStruct::get(MergedTy, Inits);
5355ca98fd9SDimitry Andric 
536b915e9e0SDimitry Andric     // On Darwin external linkage needs to be preserved, otherwise
537b915e9e0SDimitry Andric     // dsymutil cannot preserve the debug info for the merged
538b915e9e0SDimitry Andric     // variables.  If they have external linkage, use the symbol name
539b915e9e0SDimitry Andric     // of the first variable merged as the suffix of global symbol
540b915e9e0SDimitry Andric     // name.  This avoids a link-time naming conflict for the
541b915e9e0SDimitry Andric     // _MergedGlobals symbols.
542b915e9e0SDimitry Andric     Twine MergedName =
543b915e9e0SDimitry Andric         (IsMachO && HasExternal)
544b915e9e0SDimitry Andric             ? "_MergedGlobals_" + FirstExternalName
545b915e9e0SDimitry Andric             : "_MergedGlobals";
546b915e9e0SDimitry Andric     auto MergedLinkage = IsMachO ? Linkage : GlobalValue::PrivateLinkage;
547b915e9e0SDimitry Andric     auto *MergedGV = new GlobalVariable(
548b915e9e0SDimitry Andric         M, MergedTy, isConst, MergedLinkage, MergedInit, MergedName, nullptr,
549b915e9e0SDimitry Andric         GlobalVariable::NotThreadLocal, AddrSpace);
550b915e9e0SDimitry Andric 
551eb11fae6SDimitry Andric     MergedGV->setAlignment(MaxAlign);
552d8e91e46SDimitry Andric     MergedGV->setSection(Globals[i]->getSection());
5535ca98fd9SDimitry Andric 
554eb11fae6SDimitry Andric     const StructLayout *MergedLayout = DL.getStructLayout(MergedTy);
555dd58ef01SDimitry Andric     for (ssize_t k = i, idx = 0; k != j; k = GlobalSet.find_next(k), ++idx) {
5565ca98fd9SDimitry Andric       GlobalValue::LinkageTypes Linkage = Globals[k]->getLinkage();
557cfca06d7SDimitry Andric       std::string Name(Globals[k]->getName());
558cfca06d7SDimitry Andric       GlobalValue::VisibilityTypes Visibility = Globals[k]->getVisibility();
559eb11fae6SDimitry Andric       GlobalValue::DLLStorageClassTypes DLLStorage =
560eb11fae6SDimitry Andric           Globals[k]->getDLLStorageClass();
5615ca98fd9SDimitry Andric 
562b915e9e0SDimitry Andric       // Copy metadata while adjusting any debug info metadata by the original
563b915e9e0SDimitry Andric       // global's offset within the merged global.
564eb11fae6SDimitry Andric       MergedGV->copyMetadata(Globals[k],
565eb11fae6SDimitry Andric                              MergedLayout->getElementOffset(StructIdxs[idx]));
566b915e9e0SDimitry Andric 
56763faed5bSDimitry Andric       Constant *Idx[2] = {
56863faed5bSDimitry Andric           ConstantInt::get(Int32Ty, 0),
569eb11fae6SDimitry Andric           ConstantInt::get(Int32Ty, StructIdxs[idx]),
57063faed5bSDimitry Andric       };
5715a5ac124SDimitry Andric       Constant *GEP =
5725a5ac124SDimitry Andric           ConstantExpr::getInBoundsGetElementPtr(MergedTy, MergedGV, Idx);
57363faed5bSDimitry Andric       Globals[k]->replaceAllUsesWith(GEP);
57463faed5bSDimitry Andric       Globals[k]->eraseFromParent();
5755ca98fd9SDimitry Andric 
576dd58ef01SDimitry Andric       // When the linkage is not internal we must emit an alias for the original
577dd58ef01SDimitry Andric       // variable name as it may be accessed from another object. On non-Mach-O
578dd58ef01SDimitry Andric       // we can also emit an alias for internal linkage as it's safe to do so.
579dd58ef01SDimitry Andric       // It's not safe on Mach-O as the alias (and thus the portion of the
580dd58ef01SDimitry Andric       // MergedGlobals variable) may be dead stripped at link time.
58101095a5dSDimitry Andric       if (Linkage != GlobalValue::InternalLinkage || !IsMachO) {
582eb11fae6SDimitry Andric         GlobalAlias *GA = GlobalAlias::create(Tys[StructIdxs[idx]], AddrSpace,
583eb11fae6SDimitry Andric                                               Linkage, Name, GEP, &M);
584cfca06d7SDimitry Andric         GA->setVisibility(Visibility);
585eb11fae6SDimitry Andric         GA->setDLLStorageClass(DLLStorage);
5865ca98fd9SDimitry Andric       }
5875ca98fd9SDimitry Andric 
58863faed5bSDimitry Andric       NumMerged++;
58963faed5bSDimitry Andric     }
590eb11fae6SDimitry Andric     Changed = true;
59163faed5bSDimitry Andric     i = j;
59263faed5bSDimitry Andric   }
59363faed5bSDimitry Andric 
594eb11fae6SDimitry Andric   return Changed;
59563faed5bSDimitry Andric }
59663faed5bSDimitry Andric 
collectUsedGlobalVariables(Module & M,StringRef Name)5974df029ccSDimitry Andric void GlobalMergeImpl::collectUsedGlobalVariables(Module &M, StringRef Name) {
5984a16efa3SDimitry Andric   // Extract global variables from llvm.used array
599eb11fae6SDimitry Andric   const GlobalVariable *GV = M.getGlobalVariable(Name);
6004a16efa3SDimitry Andric   if (!GV || !GV->hasInitializer()) return;
6014a16efa3SDimitry Andric 
6024a16efa3SDimitry Andric   // Should be an array of 'i8*'.
60359d6cff9SDimitry Andric   const ConstantArray *InitList = cast<ConstantArray>(GV->getInitializer());
6044a16efa3SDimitry Andric 
6054a16efa3SDimitry Andric   for (unsigned i = 0, e = InitList->getNumOperands(); i != e; ++i)
6064a16efa3SDimitry Andric     if (const GlobalVariable *G =
6074a16efa3SDimitry Andric         dyn_cast<GlobalVariable>(InitList->getOperand(i)->stripPointerCasts()))
6084a16efa3SDimitry Andric       MustKeepGlobalVariables.insert(G);
6094a16efa3SDimitry Andric }
6104a16efa3SDimitry Andric 
setMustKeepGlobalVariables(Module & M)6114df029ccSDimitry Andric void GlobalMergeImpl::setMustKeepGlobalVariables(Module &M) {
612eb11fae6SDimitry Andric   collectUsedGlobalVariables(M, "llvm.used");
613eb11fae6SDimitry Andric   collectUsedGlobalVariables(M, "llvm.compiler.used");
6144a16efa3SDimitry Andric 
615b915e9e0SDimitry Andric   for (Function &F : M) {
616b915e9e0SDimitry Andric     for (BasicBlock &BB : F) {
617b915e9e0SDimitry Andric       Instruction *Pad = BB.getFirstNonPHI();
618b915e9e0SDimitry Andric       if (!Pad->isEHPad())
619b915e9e0SDimitry Andric         continue;
6204a16efa3SDimitry Andric 
621b915e9e0SDimitry Andric       // Keep globals used by landingpads and catchpads.
622b915e9e0SDimitry Andric       for (const Use &U : Pad->operands()) {
6234a16efa3SDimitry Andric         if (const GlobalVariable *GV =
624b915e9e0SDimitry Andric                 dyn_cast<GlobalVariable>(U->stripPointerCasts()))
6254a16efa3SDimitry Andric           MustKeepGlobalVariables.insert(GV);
626145449b1SDimitry Andric         else if (const ConstantArray *CA = dyn_cast<ConstantArray>(U->stripPointerCasts())) {
627145449b1SDimitry Andric           for (const Use &Elt : CA->operands()) {
628145449b1SDimitry Andric             if (const GlobalVariable *GV =
629145449b1SDimitry Andric                     dyn_cast<GlobalVariable>(Elt->stripPointerCasts()))
630145449b1SDimitry Andric               MustKeepGlobalVariables.insert(GV);
631145449b1SDimitry Andric           }
632145449b1SDimitry Andric         }
6334a16efa3SDimitry Andric       }
6344a16efa3SDimitry Andric     }
6354a16efa3SDimitry Andric   }
636b915e9e0SDimitry Andric }
63763faed5bSDimitry Andric 
run(Module & M)6384df029ccSDimitry Andric bool GlobalMergeImpl::run(Module &M) {
6395ca98fd9SDimitry Andric   if (!EnableGlobalMerge)
6405ca98fd9SDimitry Andric     return false;
6415ca98fd9SDimitry Andric 
64201095a5dSDimitry Andric   IsMachO = Triple(M.getTargetTriple()).isOSBinFormatMachO();
64301095a5dSDimitry Andric 
644ee8648bdSDimitry Andric   auto &DL = M.getDataLayout();
645ac9a064cSDimitry Andric   MapVector<std::pair<unsigned, StringRef>, SmallVector<GlobalVariable *, 0>>
646d8e91e46SDimitry Andric       Globals, ConstGlobals, BSSGlobals;
64763faed5bSDimitry Andric   bool Changed = false;
6484a16efa3SDimitry Andric   setMustKeepGlobalVariables(M);
64963faed5bSDimitry Andric 
650145449b1SDimitry Andric   LLVM_DEBUG({
651145449b1SDimitry Andric       dbgs() << "Number of GV that must be kept:  " <<
652145449b1SDimitry Andric                 MustKeepGlobalVariables.size() << "\n";
653e3b55780SDimitry Andric       for (const GlobalVariable *KeptGV : MustKeepGlobalVariables)
654e3b55780SDimitry Andric         dbgs() << "Kept: " << *KeptGV << "\n";
655145449b1SDimitry Andric   });
65663faed5bSDimitry Andric   // Grab all non-const globals.
657dd58ef01SDimitry Andric   for (auto &GV : M.globals()) {
6585ca98fd9SDimitry Andric     // Merge is safe for "normal" internal or external globals only
659d8e91e46SDimitry Andric     if (GV.isDeclaration() || GV.isThreadLocal() || GV.hasImplicitSection())
6605ca98fd9SDimitry Andric       continue;
6615ca98fd9SDimitry Andric 
662d288ef4cSDimitry Andric     // It's not safe to merge globals that may be preempted
663ac9a064cSDimitry Andric     if (TM && !TM->shouldAssumeDSOLocal(&GV))
664d288ef4cSDimitry Andric       continue;
665d288ef4cSDimitry Andric 
6664df029ccSDimitry Andric     if (!(Opt.MergeExternal && GV.hasExternalLinkage()) &&
667dd58ef01SDimitry Andric         !GV.hasInternalLinkage())
66863faed5bSDimitry Andric       continue;
66963faed5bSDimitry Andric 
670dd58ef01SDimitry Andric     PointerType *PT = dyn_cast<PointerType>(GV.getType());
6714a16efa3SDimitry Andric     assert(PT && "Global variable is not a pointer!");
6724a16efa3SDimitry Andric 
6734a16efa3SDimitry Andric     unsigned AddressSpace = PT->getAddressSpace();
674d8e91e46SDimitry Andric     StringRef Section = GV.getSection();
6754a16efa3SDimitry Andric 
67663faed5bSDimitry Andric     // Ignore all 'special' globals.
677312c0ed1SDimitry Andric     if (GV.getName().starts_with("llvm.") || GV.getName().starts_with(".llvm."))
67863faed5bSDimitry Andric       continue;
67963faed5bSDimitry Andric 
6804a16efa3SDimitry Andric     // Ignore all "required" globals:
681dd58ef01SDimitry Andric     if (isMustKeepGlobalVariable(&GV))
6824a16efa3SDimitry Andric       continue;
6834a16efa3SDimitry Andric 
6847fa27ce4SDimitry Andric     // Don't merge tagged globals, as each global should have its own unique
6857fa27ce4SDimitry Andric     // memory tag at runtime. TODO(hctim): This can be relaxed: constant globals
6867fa27ce4SDimitry Andric     // with compatible alignment and the same contents may be merged as long as
6877fa27ce4SDimitry Andric     // the globals occupy the same number of tag granules (i.e. `size_a / 16 ==
6887fa27ce4SDimitry Andric     // size_b / 16`).
6897fa27ce4SDimitry Andric     if (GV.isTagged())
6907fa27ce4SDimitry Andric       continue;
6917fa27ce4SDimitry Andric 
692eb11fae6SDimitry Andric     Type *Ty = GV.getValueType();
693ac9a064cSDimitry Andric     TypeSize AllocSize = DL.getTypeAllocSize(Ty);
694ac9a064cSDimitry Andric     if (AllocSize < Opt.MaxOffset && AllocSize >= Opt.MinSize) {
69501095a5dSDimitry Andric       if (TM &&
696d8e91e46SDimitry Andric           TargetLoweringObjectFile::getKindForGlobal(&GV, *TM).isBSS())
697d8e91e46SDimitry Andric         BSSGlobals[{AddressSpace, Section}].push_back(&GV);
698dd58ef01SDimitry Andric       else if (GV.isConstant())
699d8e91e46SDimitry Andric         ConstGlobals[{AddressSpace, Section}].push_back(&GV);
70063faed5bSDimitry Andric       else
701d8e91e46SDimitry Andric         Globals[{AddressSpace, Section}].push_back(&GV);
70263faed5bSDimitry Andric     }
70363faed5bSDimitry Andric   }
70463faed5bSDimitry Andric 
705dd58ef01SDimitry Andric   for (auto &P : Globals)
706dd58ef01SDimitry Andric     if (P.second.size() > 1)
707d8e91e46SDimitry Andric       Changed |= doMerge(P.second, M, false, P.first.first);
70863faed5bSDimitry Andric 
709dd58ef01SDimitry Andric   for (auto &P : BSSGlobals)
710dd58ef01SDimitry Andric     if (P.second.size() > 1)
711d8e91e46SDimitry Andric       Changed |= doMerge(P.second, M, false, P.first.first);
7124a16efa3SDimitry Andric 
7134a16efa3SDimitry Andric   if (EnableGlobalMergeOnConst)
714dd58ef01SDimitry Andric     for (auto &P : ConstGlobals)
715dd58ef01SDimitry Andric       if (P.second.size() > 1)
716d8e91e46SDimitry Andric         Changed |= doMerge(P.second, M, true, P.first.first);
71763faed5bSDimitry Andric 
71863faed5bSDimitry Andric   return Changed;
71963faed5bSDimitry Andric }
72063faed5bSDimitry Andric 
createGlobalMergePass(const TargetMachine * TM,unsigned Offset,bool OnlyOptimizeForSize,bool MergeExternalByDefault)72185d8b2bbSDimitry Andric Pass *llvm::createGlobalMergePass(const TargetMachine *TM, unsigned Offset,
722dd58ef01SDimitry Andric                                   bool OnlyOptimizeForSize,
723dd58ef01SDimitry Andric                                   bool MergeExternalByDefault) {
724dd58ef01SDimitry Andric   bool MergeExternal = (EnableGlobalMergeOnExternal == cl::BOU_UNSET) ?
725dd58ef01SDimitry Andric     MergeExternalByDefault : (EnableGlobalMergeOnExternal == cl::BOU_TRUE);
726dd58ef01SDimitry Andric   return new GlobalMerge(TM, Offset, OnlyOptimizeForSize, MergeExternal);
72763faed5bSDimitry Andric }
728