6060//
6161// ===---------------------------------------------------------------------===//
6262
63+ #include " llvm/CodeGen/GlobalMerge.h"
6364#include " llvm/ADT/BitVector.h"
6465#include " llvm/ADT/DenseMap.h"
6566#include " llvm/ADT/SetVector.h"
@@ -137,88 +138,99 @@ STATISTIC(NumMerged, "Number of globals merged");
137138
138139namespace {
139140
140- class GlobalMerge : public FunctionPass {
141- const TargetMachine *TM = nullptr ;
142-
143- // FIXME: Infer the maximum possible offset depending on the actual users
144- // (these max offsets are different for the users inside Thumb or ARM
145- // functions), see the code that passes in the offset in the ARM backend
146- // for more information.
147- unsigned MaxOffset;
148-
149- // / Whether we should try to optimize for size only.
150- // / Currently, this applies a dead simple heuristic: only consider globals
151- // / used in minsize functions for merging.
152- // / FIXME: This could learn about optsize, and be used in the cost model.
153- bool OnlyOptimizeForSize = false ;
154-
155- // / Whether we should merge global variables that have external linkage.
156- bool MergeExternalGlobals = false ;
141+ class GlobalMergeImpl {
142+ const TargetMachine *TM = nullptr ;
143+ GlobalMergeOptions Opt;
144+ bool IsMachO = false ;
145+
146+ private:
147+ bool doMerge (SmallVectorImpl<GlobalVariable *> &Globals, Module &M,
148+ bool isConst, unsigned AddrSpace) const ;
149+
150+ // / Merge everything in \p Globals for which the corresponding bit
151+ // / in \p GlobalSet is set.
152+ bool doMerge (const SmallVectorImpl<GlobalVariable *> &Globals,
153+ const BitVector &GlobalSet, Module &M, bool isConst,
154+ unsigned AddrSpace) const ;
155+
156+ // / Check if the given variable has been identified as must keep
157+ // / \pre setMustKeepGlobalVariables must have been called on the Module that
158+ // / contains GV
159+ bool isMustKeepGlobalVariable (const GlobalVariable *GV) const {
160+ return MustKeepGlobalVariables.count (GV);
161+ }
157162
158- bool IsMachO = false ;
163+ // / Collect every variables marked as "used" or used in a landing pad
164+ // / instruction for this Module.
165+ void setMustKeepGlobalVariables (Module &M);
159166
160- bool doMerge (SmallVectorImpl<GlobalVariable*> &Globals,
161- Module &M, bool isConst, unsigned AddrSpace) const ;
167+ // / Collect every variables marked as "used"
168+ void collectUsedGlobalVariables ( Module &M, StringRef Name) ;
162169
163- // / Merge everything in \p Globals for which the corresponding bit
164- // / in \p GlobalSet is set.
165- bool doMerge (const SmallVectorImpl<GlobalVariable *> &Globals,
166- const BitVector &GlobalSet, Module &M, bool isConst,
167- unsigned AddrSpace) const ;
170+ // / Keep track of the GlobalVariable that must not be merged away
171+ SmallSetVector<const GlobalVariable *, 16 > MustKeepGlobalVariables;
168172
169- // / Check if the given variable has been identified as must keep
170- // / \pre setMustKeepGlobalVariables must have been called on the Module that
171- // / contains GV
172- bool isMustKeepGlobalVariable (const GlobalVariable *GV) const {
173- return MustKeepGlobalVariables.count (GV);
174- }
173+ public:
174+ GlobalMergeImpl (const TargetMachine *TM, GlobalMergeOptions Opt)
175+ : TM(TM), Opt(Opt) {}
176+ bool run (Module &M);
177+ };
175178
176- // / Collect every variables marked as "used" or used in a landing pad
177- // / instruction for this Module.
178- void setMustKeepGlobalVariables (Module &M) ;
179+ class GlobalMerge : public FunctionPass {
180+ const TargetMachine *TM = nullptr ;
181+ GlobalMergeOptions Opt ;
179182
180- // / Collect every variables marked as "used"
181- void collectUsedGlobalVariables (Module &M, StringRef Name);
183+ public:
184+ static char ID; // Pass identification, replacement for typeid.
182185
183- // / Keep track of the GlobalVariable that must not be merged away
184- SmallSetVector<const GlobalVariable *, 16 > MustKeepGlobalVariables;
186+ explicit GlobalMerge () : FunctionPass(ID) {
187+ Opt.MaxOffset = GlobalMergeMaxOffset;
188+ initializeGlobalMergePass (*PassRegistry::getPassRegistry ());
189+ }
185190
186- public:
187- static char ID; // Pass identification, replacement for typeid.
191+ explicit GlobalMerge (const TargetMachine *TM, unsigned MaximalOffset,
192+ bool OnlyOptimizeForSize, bool MergeExternalGlobals)
193+ : FunctionPass(ID), TM(TM) {
194+ Opt.MaxOffset = MaximalOffset;
195+ Opt.SizeOnly = OnlyOptimizeForSize;
196+ Opt.MergeExternal = MergeExternalGlobals;
197+ initializeGlobalMergePass (*PassRegistry::getPassRegistry ());
198+ }
188199
189- explicit GlobalMerge ()
190- : FunctionPass(ID), MaxOffset(GlobalMergeMaxOffset) {
191- initializeGlobalMergePass (*PassRegistry::getPassRegistry ());
192- }
200+ bool doInitialization (Module &M) override {
201+ GlobalMergeImpl P (TM, Opt);
202+ return P.run (M);
203+ }
204+ bool runOnFunction (Function &F) override { return false ; }
193205
194- explicit GlobalMerge (const TargetMachine *TM, unsigned MaximalOffset,
195- bool OnlyOptimizeForSize, bool MergeExternalGlobals)
196- : FunctionPass(ID), TM(TM), MaxOffset(MaximalOffset),
197- OnlyOptimizeForSize(OnlyOptimizeForSize),
198- MergeExternalGlobals(MergeExternalGlobals) {
199- initializeGlobalMergePass (*PassRegistry::getPassRegistry ());
200- }
206+ StringRef getPassName () const override { return " Merge internal globals" ; }
201207
202- bool doInitialization (Module &M) override ;
203- bool runOnFunction (Function &F) override ;
204- bool doFinalization (Module &M) override ;
208+ void getAnalysisUsage (AnalysisUsage &AU) const override {
209+ AU.setPreservesCFG ();
210+ FunctionPass::getAnalysisUsage (AU);
211+ }
212+ };
205213
206- StringRef getPassName () const override { return " Merge internal globals " ; }
214+ } // end anonymous namespace
207215
208- void getAnalysisUsage (AnalysisUsage &AU) const override {
209- AU. setPreservesCFG ( );
210- FunctionPass::getAnalysisUsage (AU );
211- }
212- } ;
216+ PreservedAnalyses GlobalMergePass::run (Module &M, ModuleAnalysisManager &) {
217+ GlobalMergeImpl P (TM, Options );
218+ bool Changed = P. run (M );
219+ if (!Changed)
220+ return PreservedAnalyses::all () ;
213221
214- } // end anonymous namespace
222+ PreservedAnalyses PA;
223+ PA.preserveSet <CFGAnalyses>();
224+ return PA;
225+ }
215226
216227char GlobalMerge::ID = 0 ;
217228
218229INITIALIZE_PASS (GlobalMerge, DEBUG_TYPE, " Merge global variables" , false , false )
219230
220- bool GlobalMerge::doMerge(SmallVectorImpl<GlobalVariable*> &Globals,
221- Module &M, bool isConst, unsigned AddrSpace) const {
231+ bool GlobalMergeImpl::doMerge(SmallVectorImpl<GlobalVariable *> &Globals,
232+ Module &M, bool isConst,
233+ unsigned AddrSpace) const {
222234 auto &DL = M.getDataLayout ();
223235 // FIXME: Find better heuristics
224236 llvm::stable_sort (
@@ -333,7 +345,7 @@ bool GlobalMerge::doMerge(SmallVectorImpl<GlobalVariable*> &Globals,
333345 Function *ParentFn = I->getParent ()->getParent ();
334346
335347 // If we're only optimizing for size, ignore non-minsize functions.
336- if (OnlyOptimizeForSize && !ParentFn->hasMinSize ())
348+ if (Opt. SizeOnly && !ParentFn->hasMinSize ())
337349 continue ;
338350
339351 size_t UGSIdx = GlobalUsesByFunction[ParentFn];
@@ -434,9 +446,9 @@ bool GlobalMerge::doMerge(SmallVectorImpl<GlobalVariable*> &Globals,
434446 return Changed;
435447}
436448
437- bool GlobalMerge ::doMerge (const SmallVectorImpl<GlobalVariable *> &Globals,
438- const BitVector &GlobalSet, Module &M, bool isConst ,
439- unsigned AddrSpace) const {
449+ bool GlobalMergeImpl ::doMerge (const SmallVectorImpl<GlobalVariable *> &Globals,
450+ const BitVector &GlobalSet, Module &M,
451+ bool isConst, unsigned AddrSpace) const {
440452 assert (Globals.size () > 1 );
441453
442454 Type *Int32Ty = Type::getInt32Ty (M.getContext ());
@@ -467,7 +479,7 @@ bool GlobalMerge::doMerge(const SmallVectorImpl<GlobalVariable *> &Globals,
467479 unsigned Padding = alignTo (MergedSize, Alignment) - MergedSize;
468480 MergedSize += Padding;
469481 MergedSize += DL.getTypeAllocSize (Ty);
470- if (MergedSize > MaxOffset) {
482+ if (MergedSize > Opt. MaxOffset ) {
471483 break ;
472484 }
473485 if (Padding) {
@@ -563,7 +575,7 @@ bool GlobalMerge::doMerge(const SmallVectorImpl<GlobalVariable *> &Globals,
563575 return Changed;
564576}
565577
566- void GlobalMerge ::collectUsedGlobalVariables (Module &M, StringRef Name) {
578+ void GlobalMergeImpl ::collectUsedGlobalVariables (Module &M, StringRef Name) {
567579 // Extract global variables from llvm.used array
568580 const GlobalVariable *GV = M.getGlobalVariable (Name);
569581 if (!GV || !GV->hasInitializer ()) return ;
@@ -577,7 +589,7 @@ void GlobalMerge::collectUsedGlobalVariables(Module &M, StringRef Name) {
577589 MustKeepGlobalVariables.insert (G);
578590}
579591
580- void GlobalMerge ::setMustKeepGlobalVariables (Module &M) {
592+ void GlobalMergeImpl ::setMustKeepGlobalVariables (Module &M) {
581593 collectUsedGlobalVariables (M, " llvm.used" );
582594 collectUsedGlobalVariables (M, " llvm.compiler.used" );
583595
@@ -604,7 +616,7 @@ void GlobalMerge::setMustKeepGlobalVariables(Module &M) {
604616 }
605617}
606618
607- bool GlobalMerge::doInitialization (Module &M) {
619+ bool GlobalMergeImpl::run (Module &M) {
608620 if (!EnableGlobalMerge)
609621 return false ;
610622
@@ -632,7 +644,7 @@ bool GlobalMerge::doInitialization(Module &M) {
632644 if (TM && !TM->shouldAssumeDSOLocal (M, &GV))
633645 continue ;
634646
635- if (!(MergeExternalGlobals && GV.hasExternalLinkage ()) &&
647+ if (!(Opt. MergeExternal && GV.hasExternalLinkage ()) &&
636648 !GV.hasInternalLinkage ())
637649 continue ;
638650
@@ -659,7 +671,7 @@ bool GlobalMerge::doInitialization(Module &M) {
659671 continue ;
660672
661673 Type *Ty = GV.getValueType ();
662- if (DL.getTypeAllocSize (Ty) < MaxOffset) {
674+ if (DL.getTypeAllocSize (Ty) < Opt. MaxOffset ) {
663675 if (TM &&
664676 TargetLoweringObjectFile::getKindForGlobal (&GV, *TM).isBSS ())
665677 BSSGlobals[{AddressSpace, Section}].push_back (&GV);
@@ -686,15 +698,6 @@ bool GlobalMerge::doInitialization(Module &M) {
686698 return Changed;
687699}
688700
689- bool GlobalMerge::runOnFunction (Function &F) {
690- return false ;
691- }
692-
693- bool GlobalMerge::doFinalization (Module &M) {
694- MustKeepGlobalVariables.clear ();
695- return false ;
696- }
697-
698701Pass *llvm::createGlobalMergePass (const TargetMachine *TM, unsigned Offset,
699702 bool OnlyOptimizeForSize,
700703 bool MergeExternalByDefault) {
0 commit comments