60
60
//
61
61
// ===---------------------------------------------------------------------===//
62
62
63
+ #include " llvm/CodeGen/GlobalMerge.h"
63
64
#include " llvm/ADT/BitVector.h"
64
65
#include " llvm/ADT/DenseMap.h"
65
66
#include " llvm/ADT/SetVector.h"
@@ -137,88 +138,99 @@ STATISTIC(NumMerged, "Number of globals merged");
137
138
138
139
namespace {
139
140
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
+ }
157
162
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);
159
166
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) ;
162
169
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;
168
172
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
+ };
175
178
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 ;
179
182
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.
182
185
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
+ }
185
190
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
+ }
188
199
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 ; }
193
205
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" ; }
201
207
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
+ };
205
213
206
- StringRef getPassName () const override { return " Merge internal globals " ; }
214
+ } // end anonymous namespace
207
215
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 () ;
213
221
214
- } // end anonymous namespace
222
+ PreservedAnalyses PA;
223
+ PA.preserveSet <CFGAnalyses>();
224
+ return PA;
225
+ }
215
226
216
227
char GlobalMerge::ID = 0 ;
217
228
218
229
INITIALIZE_PASS (GlobalMerge, DEBUG_TYPE, " Merge global variables" , false , false )
219
230
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 {
222
234
auto &DL = M.getDataLayout ();
223
235
// FIXME: Find better heuristics
224
236
llvm::stable_sort (
@@ -333,7 +345,7 @@ bool GlobalMerge::doMerge(SmallVectorImpl<GlobalVariable*> &Globals,
333
345
Function *ParentFn = I->getParent ()->getParent ();
334
346
335
347
// If we're only optimizing for size, ignore non-minsize functions.
336
- if (OnlyOptimizeForSize && !ParentFn->hasMinSize ())
348
+ if (Opt. SizeOnly && !ParentFn->hasMinSize ())
337
349
continue ;
338
350
339
351
size_t UGSIdx = GlobalUsesByFunction[ParentFn];
@@ -434,9 +446,9 @@ bool GlobalMerge::doMerge(SmallVectorImpl<GlobalVariable*> &Globals,
434
446
return Changed;
435
447
}
436
448
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 {
440
452
assert (Globals.size () > 1 );
441
453
442
454
Type *Int32Ty = Type::getInt32Ty (M.getContext ());
@@ -467,7 +479,7 @@ bool GlobalMerge::doMerge(const SmallVectorImpl<GlobalVariable *> &Globals,
467
479
unsigned Padding = alignTo (MergedSize, Alignment) - MergedSize;
468
480
MergedSize += Padding;
469
481
MergedSize += DL.getTypeAllocSize (Ty);
470
- if (MergedSize > MaxOffset) {
482
+ if (MergedSize > Opt. MaxOffset ) {
471
483
break ;
472
484
}
473
485
if (Padding) {
@@ -563,7 +575,7 @@ bool GlobalMerge::doMerge(const SmallVectorImpl<GlobalVariable *> &Globals,
563
575
return Changed;
564
576
}
565
577
566
- void GlobalMerge ::collectUsedGlobalVariables (Module &M, StringRef Name) {
578
+ void GlobalMergeImpl ::collectUsedGlobalVariables (Module &M, StringRef Name) {
567
579
// Extract global variables from llvm.used array
568
580
const GlobalVariable *GV = M.getGlobalVariable (Name);
569
581
if (!GV || !GV->hasInitializer ()) return ;
@@ -577,7 +589,7 @@ void GlobalMerge::collectUsedGlobalVariables(Module &M, StringRef Name) {
577
589
MustKeepGlobalVariables.insert (G);
578
590
}
579
591
580
- void GlobalMerge ::setMustKeepGlobalVariables (Module &M) {
592
+ void GlobalMergeImpl ::setMustKeepGlobalVariables (Module &M) {
581
593
collectUsedGlobalVariables (M, " llvm.used" );
582
594
collectUsedGlobalVariables (M, " llvm.compiler.used" );
583
595
@@ -604,7 +616,7 @@ void GlobalMerge::setMustKeepGlobalVariables(Module &M) {
604
616
}
605
617
}
606
618
607
- bool GlobalMerge::doInitialization (Module &M) {
619
+ bool GlobalMergeImpl::run (Module &M) {
608
620
if (!EnableGlobalMerge)
609
621
return false ;
610
622
@@ -632,7 +644,7 @@ bool GlobalMerge::doInitialization(Module &M) {
632
644
if (TM && !TM->shouldAssumeDSOLocal (M, &GV))
633
645
continue ;
634
646
635
- if (!(MergeExternalGlobals && GV.hasExternalLinkage ()) &&
647
+ if (!(Opt. MergeExternal && GV.hasExternalLinkage ()) &&
636
648
!GV.hasInternalLinkage ())
637
649
continue ;
638
650
@@ -659,7 +671,7 @@ bool GlobalMerge::doInitialization(Module &M) {
659
671
continue ;
660
672
661
673
Type *Ty = GV.getValueType ();
662
- if (DL.getTypeAllocSize (Ty) < MaxOffset) {
674
+ if (DL.getTypeAllocSize (Ty) < Opt. MaxOffset ) {
663
675
if (TM &&
664
676
TargetLoweringObjectFile::getKindForGlobal (&GV, *TM).isBSS ())
665
677
BSSGlobals[{AddressSpace, Section}].push_back (&GV);
@@ -686,15 +698,6 @@ bool GlobalMerge::doInitialization(Module &M) {
686
698
return Changed;
687
699
}
688
700
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
-
698
701
Pass *llvm::createGlobalMergePass (const TargetMachine *TM, unsigned Offset,
699
702
bool OnlyOptimizeForSize,
700
703
bool MergeExternalByDefault) {
0 commit comments