LLVM: lib/CodeGen/GlobalMerge.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
97#include
98#include
99#include
100#include
101#include
102#include
103
104using namespace llvm;
105
106#define DEBUG_TYPE "global-merge"
107
108
111 cl::desc("Enable the global merge pass"),
113
116 cl::desc("Set maximum offset for global merge pass"),
118
120 "global-merge-group-by-use", cl::Hidden,
121 cl::desc("Improve global merge pass to look at uses"), cl::init(true));
122
124 "global-merge-all-const", cl::Hidden,
125 cl::desc("Merge all const globals without looking at uses"),
127
129 "global-merge-ignore-single-use", cl::Hidden,
130 cl::desc("Improve global merge pass to ignore globals only used alone"),
132
135 cl::desc("Enable global merge pass on constants"),
137
138
139
142 cl::desc("Enable global merge pass on external linkage"));
143
146 cl::desc("The minimum size in bytes of each global "
147 "that should considered in merging."),
149
150STATISTIC(NumMerged, "Number of globals merged");
151
152namespace {
153
154class GlobalMergeImpl {
157 bool IsMachO = false;
158
159private:
161 bool isConst, unsigned AddrSpace) const;
162
163
164
167 unsigned AddrSpace) const;
168
169
170
171
172 bool isMustKeepGlobalVariable(const GlobalVariable *GV) const {
173 return MustKeepGlobalVariables.count(GV);
174 }
175
176
177
178 void setMustKeepGlobalVariables(Module &M);
179
180
182
183
184 SmallSetVector<const GlobalVariable *, 16> MustKeepGlobalVariables;
185
186public:
187 GlobalMergeImpl(const TargetMachine *TM, GlobalMergeOptions Opt)
188 : TM(TM), Opt(Opt) {}
190};
191
193 const TargetMachine *TM = nullptr;
194 GlobalMergeOptions Opt;
195
196public:
197 static char ID;
198
199 explicit GlobalMerge() : FunctionPass(ID) {
204 }
205
206 explicit GlobalMerge(const TargetMachine *TM, unsigned MaximalOffset,
207 bool OnlyOptimizeForSize, bool MergeExternalGlobals,
208 bool MergeConstantGlobals, bool MergeConstAggressive)
209 : FunctionPass(ID), TM(TM) {
210 Opt.MaxOffset = MaximalOffset;
211 Opt.SizeOnly = OnlyOptimizeForSize;
212 Opt.MergeExternal = MergeExternalGlobals;
213 Opt.MergeConstantGlobals = MergeConstantGlobals;
214 Opt.MergeConstAggressive = MergeConstAggressive;
216 }
217
218 bool doInitialization(Module &M) override {
219 auto GetSmallDataLimit = [](Module &M) -> std::optional<uint64_t> {
220 Metadata *SDL = M.getModuleFlag("SmallDataLimit");
221 if (!SDL)
222 return std::nullopt;
224 };
227 else if (auto SDL = GetSmallDataLimit(M); SDL && *SDL > 0)
228 Opt.MinSize = *SDL + 1;
229 else
230 Opt.MinSize = 0;
231
232 GlobalMergeImpl P(TM, Opt);
233 return P.run(M);
234 }
235 bool runOnFunction(Function &F) override { return false; }
236
237 StringRef getPassName() const override { return "Merge internal globals"; }
238
239 void getAnalysisUsage(AnalysisUsage &AU) const override {
241 FunctionPass::getAnalysisUsage(AU);
242 }
243};
244
245}
246
248 GlobalMergeImpl P(TM, Options);
252
255 return PA;
256}
257
258char GlobalMerge::ID = 0;
259
261
263 Module &M, bool isConst,
264 unsigned AddrSpace) const {
265 auto &DL = M.getDataLayout();
266
269
270 return DL.getTypeAllocSize(GV1->getValueType()).getFixedValue() <
271 DL.getTypeAllocSize(GV2->getValueType()).getFixedValue();
272 });
273
274
276 BitVector AllGlobals(Globals.size(), true);
277 return doMerge(Globals, AllGlobals, M, isConst, AddrSpace);
278 }
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299 struct UsedGlobalSet {
300 BitVector Globals;
301 unsigned UsageCount = 1;
302
303 UsedGlobalSet(size_t Size) : Globals(Size) {}
304 };
305
306
307 std::vector UsedGlobalSets;
308
309
310 auto CreateGlobalSet = [&]() -> UsedGlobalSet & {
311 UsedGlobalSets.emplace_back(Globals.size());
312 return UsedGlobalSets.back();
313 };
314
315
316 CreateGlobalSet().UsageCount = 0;
317
318
319
320
321
322
323
324
325
326
327
328 DenseMap<Function *, size_t > GlobalUsesByFunction;
329
330
331
332
333
334
335
336
337 std::vector<size_t> EncounteredUGS;
338
339 for (size_t GI = 0, GE = Globals.size(); GI != GE; ++GI) {
341
342
343
344 EncounteredUGS.assign(UsedGlobalSets.size(), 0);
345
346
347
348 size_t CurGVOnlySetIdx = 0;
349
350
351 for (auto &U : GV->uses()) {
352
353
354 Use *UI, *UE;
356 if (CE->use_empty())
357 continue;
358 UI = &*CE->use_begin();
359 UE = nullptr;
361 UI = &U;
362 UE = UI->getNext();
363 } else {
364 continue;
365 }
366
367
368
369 for (; UI != UE; UI = UI->getNext()) {
371 if ()
372 continue;
373
375
376
378 continue;
379
380 size_t UGSIdx = GlobalUsesByFunction[ParentFn];
381
382
383
384 if (!UGSIdx) {
385
386 if (!CurGVOnlySetIdx) {
387 CurGVOnlySetIdx = UsedGlobalSets.size();
388 CreateGlobalSet().Globals.set(GI);
389 } else {
390 ++UsedGlobalSets[CurGVOnlySetIdx].UsageCount;
391 }
392
393 GlobalUsesByFunction[ParentFn] = CurGVOnlySetIdx;
394 continue;
395 }
396
397
398
399 if (UsedGlobalSets[UGSIdx].Globals.test(GI)) {
400 ++UsedGlobalSets[UGSIdx].UsageCount;
401 continue;
402 }
403
404
405 --UsedGlobalSets[UGSIdx].UsageCount;
406
407
408
409 if (size_t ExpandedIdx = EncounteredUGS[UGSIdx]) {
410 ++UsedGlobalSets[ExpandedIdx].UsageCount;
411 GlobalUsesByFunction[ParentFn] = ExpandedIdx;
412 continue;
413 }
414
415
416
417 GlobalUsesByFunction[ParentFn] = EncounteredUGS[UGSIdx] =
418 UsedGlobalSets.size();
419
420 UsedGlobalSet &NewUGS = CreateGlobalSet();
421 NewUGS.Globals.set(GI);
422 NewUGS.Globals |= UsedGlobalSets[UGSIdx].Globals;
423 }
424 }
425 }
426
427
428
429
431 BitVector AllGlobals(Globals.size());
432 for (const UsedGlobalSet &UGS : UsedGlobalSets) {
433 if (UGS.UsageCount == 0)
434 continue;
435 if (UGS.Globals.count() > 1)
436 AllGlobals |= UGS.Globals;
437 }
438 return doMerge(Globals, AllGlobals, M, isConst, AddrSpace);
439 }
440
441
442
443
444
445
446
448 [](const UsedGlobalSet &UGS1, const UsedGlobalSet &UGS2) {
449 return UGS1.Globals.count() * UGS1.UsageCount <
450 UGS2.Globals.count() * UGS2.UsageCount;
451 });
452
453
454
455
456
457
458
459 BitVector PickedGlobals(Globals.size());
461
462 for (const UsedGlobalSet &UGS : llvm::reverse(UsedGlobalSets)) {
463 if (UGS.UsageCount == 0)
464 continue;
465 if (PickedGlobals.anyCommon(UGS.Globals))
466 continue;
467 PickedGlobals |= UGS.Globals;
468
469
470
471 if (UGS.Globals.count() < 2)
472 continue;
473 Changed |= doMerge(Globals, UGS.Globals, M, isConst, AddrSpace);
474 }
475
477}
478
481 bool isConst, unsigned AddrSpace) const {
483
486 auto &DL = M.getDataLayout();
487
488 LLVM_DEBUG(dbgs() << " Trying to merge set, starts with #"
489 << GlobalSet.find_first() << ", total of " << Globals.size()
490 << "\n");
491
494 while (i != -1) {
495 ssize_t j = 0;
496 uint64_t MergedSize = 0;
497 std::vector<Type*> Tys;
498 std::vector<Constant*> Inits;
499 std::vector StructIdxs;
500
501 bool HasExternal = false;
504 unsigned CurIdx = 0;
505 for (j = i; j != -1; j = GlobalSet.find_next(j)) {
506 Type *Ty = Globals[j]->getValueType();
507
508
509 Align Alignment = DL.getPreferredAlign(Globals[j]);
510 unsigned Padding = alignTo(MergedSize, Alignment) - MergedSize;
512 MergedSize += DL.getTypeAllocSize(Ty);
513 if (MergedSize > Opt.MaxOffset) {
514 break;
515 }
516 if (Padding) {
519 ++CurIdx;
520 }
521 Tys.push_back(Ty);
522 Inits.push_back(Globals[j]->getInitializer());
523 StructIdxs.push_back(CurIdx++);
524
525 MaxAlign = std::max(MaxAlign, Alignment);
526
527 if (Globals[j]->hasExternalLinkage() && !HasExternal) {
528 HasExternal = true;
529 FirstExternalName = Globals[j]->getName();
530 }
531 }
532
533
534 if (Tys.size() < 2) {
535 i = j;
536 continue;
537 }
538
539
540
544
547
548
549
550
551
552
553
554 Twine MergedName =
555 (IsMachO && HasExternal)
556 ? "_MergedGlobals_" + FirstExternalName
557 : "_MergedGlobals";
560 M, MergedTy, isConst, MergedLinkage, MergedInit, MergedName, nullptr,
562
563 MergedGV->setAlignment(MaxAlign);
564 MergedGV->setSection(Globals[i]->getSection());
565
566 LLVM_DEBUG(dbgs() << "MergedGV: " << *MergedGV << "\n");
567
568 const StructLayout *MergedLayout = DL.getStructLayout(MergedTy);
569 for (ssize_t k = i, idx = 0; k != j; k = GlobalSet.find_next(k), ++idx) {
574 Globals[k]->getDLLStorageClass();
575
576
577
578 MergedGV->copyMetadata(Globals[k],
580
582 ConstantInt::get(Int32Ty, 0),
583 ConstantInt::get(Int32Ty, StructIdxs[idx]),
584 };
587 Globals[k]->replaceAllUsesWith(GEP);
588 Globals[k]->eraseFromParent();
589
590
591
592
593
594
595
596
597
598
599
600
606 }
607
608 NumMerged++;
609 }
611 i = j;
612 }
613
615}
616
617void GlobalMergeImpl::collectUsedGlobalVariables(Module &M, StringRef Name) {
618
621
622
624
625 for (unsigned i = 0, e = InitList->getNumOperands(); i != e; ++i)
628 MustKeepGlobalVariables.insert(G);
629}
630
631void GlobalMergeImpl::setMustKeepGlobalVariables(Module &M) {
634
639 if (!Pad->isEHPad() &&
640 !(II && II->getIntrinsicID() == Intrinsic::eh_typeid_for))
641 continue;
642
643
644
645 for (const Use &U : Pad->operands()) {
648 MustKeepGlobalVariables.insert(GV);
650 for (const Use &Elt : CA->operands()) {
653 MustKeepGlobalVariables.insert(GV);
654 }
655 }
656 }
657 }
658 }
659}
660
661
662
663
664
666
667
668 return Section.starts_with("__DATA,__cfstring") ||
669 Section.starts_with("__DATA,__objc_classrefs") ||
670 Section.starts_with("__DATA,__objc_selrefs");
671}
672
673bool GlobalMergeImpl::run(Module &M) {
675 return false;
676
677 IsMachO = M.getTargetTriple().isOSBinFormatMachO();
678
679 auto &DL = M.getDataLayout();
681 Globals, ConstGlobals, BSSGlobals;
683 setMustKeepGlobalVariables(M);
684
686 dbgs() << "Number of GV that must be kept: " <<
687 MustKeepGlobalVariables.size() << "\n";
688 for (const GlobalVariable *KeptGV : MustKeepGlobalVariables)
689 dbgs() << "Kept: " << *KeptGV << "\n";
690 });
691
692 for (auto &GV : M.globals()) {
693
695 continue;
696
697
699 continue;
700
703 continue;
704
706 assert(PT && "Global variable is not a pointer!");
707
708 unsigned AddressSpace = PT->getAddressSpace();
710
711
713 continue;
714
715
718 continue;
719
720
721 if (isMustKeepGlobalVariable(&GV))
722 continue;
723
724
725
726
727
728
730 continue;
731
733 TypeSize AllocSize = DL.getTypeAllocSize(Ty);
736 if (TM &&
741 else
743 }
745 << "\n");
746 }
747
748 for (auto &P : Globals)
749 if (P.second.size() > 1)
750 Changed |= doMerge(P.second, M, false, P.first.first);
751
752 for (auto &P : BSSGlobals)
753 if (P.second.size() > 1)
754 Changed |= doMerge(P.second, M, false, P.first.first);
755
757 for (auto &P : ConstGlobals)
758 if (P.second.size() > 1)
759 Changed |= doMerge(P.second, M, true, P.first.first);
760
762}
763
765 bool OnlyOptimizeForSize,
766 bool MergeExternalByDefault,
767 bool MergeConstantByDefault,
768 bool MergeConstAggressiveByDefault) {
774 : MergeConstAggressiveByDefault;
778 return new GlobalMerge(TM, PreferOffset, OnlyOptimizeForSize, MergeExternal,
779 MergeConstant, MergeConstAggressive);
780}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
This file implements the BitVector class.
This file contains the declarations for the subclasses of Constant, which represent the different fla...
This file defines the DenseMap class.
static bool runOnFunction(Function &F, bool PostInlining)
static cl::opt< bool > GlobalMergeIgnoreSingleUse("global-merge-ignore-single-use", cl::Hidden, cl::desc("Improve global merge pass to ignore globals only used alone"), cl::init(true))
static cl::opt< bool > GlobalMergeGroupByUse("global-merge-group-by-use", cl::Hidden, cl::desc("Improve global merge pass to look at uses"), cl::init(true))
static bool isSpecialMachOSection(StringRef Section)
Definition GlobalMerge.cpp:665
static cl::opt< bool > GlobalMergeAllConst("global-merge-all-const", cl::Hidden, cl::desc("Merge all const globals without looking at uses"), cl::init(false))
static cl::opt< bool > EnableGlobalMergeOnConst("global-merge-on-const", cl::Hidden, cl::desc("Enable global merge pass on constants"), cl::init(false))
static cl::opt< unsigned > GlobalMergeMinDataSize("global-merge-min-data-size", cl::desc("The minimum size in bytes of each global " "that should considered in merging."), cl::init(0), cl::Hidden)
static cl::opt< unsigned > GlobalMergeMaxOffset("global-merge-max-offset", cl::Hidden, cl::desc("Set maximum offset for global merge pass"), cl::init(0))
static cl::opt< bool > EnableGlobalMerge("enable-global-merge", cl::Hidden, cl::desc("Enable the global merge pass"), cl::init(true))
static cl::opt< cl::boolOrDefault > EnableGlobalMergeOnExternal("global-merge-on-external", cl::Hidden, cl::desc("Enable global merge pass on external linkage"))
Module.h This file contains the declarations for the Module class.
This defines the Use class.
Machine Check Debug Module
This file implements a map that provides insertion order iteration.
uint64_t IntrinsicInst * II
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
static StringRef getName(Value *V)
This file implements a set that has insertion order iteration characteristics.
This file defines the SmallVector class.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
LLVM_ABI void setPreservesCFG()
This function should be called by the pass, iff they do not:
static LLVM_ABI ArrayType * get(Type *ElementType, uint64_t NumElements)
This static method is the primary way to construct an ArrayType.
LLVM Basic Block Representation.
InstListType::iterator iterator
Instruction iterators...
int find_first() const
find_first - Returns the index of the first set bit, -1 if none of the bits are set.
int find_next(unsigned Prev) const
find_next - Returns the index of the next set bit following the "Prev" bit.
Represents analyses that only rely on functions' control flow.
static LLVM_ABI ConstantAggregateZero * get(Type *Ty)
ConstantArray - Constant Array Declarations.
A constant value that is initialized with an expression using other constant values.
static Constant * getInBoundsGetElementPtr(Type *Ty, Constant *C, ArrayRef< Constant * > IdxList)
Create an "inbounds" getelementptr.
static LLVM_ABI Constant * get(StructType *T, ArrayRef< Constant * > V)
This is an important base class in LLVM.
FunctionPass class - This class is used to implement most global optimizations.
bool hasMinSize() const
Optimize this function for minimum size (-Oz).
static LLVM_ABI GlobalAlias * create(Type *Ty, unsigned AddressSpace, LinkageTypes Linkage, const Twine &Name, Constant *Aliasee, Module *Parent)
If a parent module is specified, the alias is automatically inserted into the end of the specified mo...
PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM)
Definition GlobalMerge.cpp:247
StringRef getSection() const
Get the custom section of this global if it has one.
bool hasExternalLinkage() const
bool isThreadLocal() const
If the value is "Thread Local", its value isn't shared by the threads.
LLVM_ABI bool isDeclaration() const
Return true if the primary definition of this global value is outside of the current translation unit...
bool hasLocalLinkage() const
void setDLLStorageClass(DLLStorageClassTypes C)
DLLStorageClassTypes
Storage classes of global values for PE targets.
Module * getParent()
Get the module that this global value is contained inside of...
PointerType * getType() const
Global values are always pointers.
VisibilityTypes
An enumeration for the kinds of visibility of global values.
void setVisibility(VisibilityTypes V)
LinkageTypes
An enumeration for the kinds of linkage for global values.
@ PrivateLinkage
Like Internal, but omit from symbol table.
@ InternalLinkage
Rename collisions when linking (static functions).
@ ExternalLinkage
Externally visible function.
Type * getValueType() const
const Constant * getInitializer() const
getInitializer - Return the initializer for this global variable.
bool hasInitializer() const
Definitions have initializers, declarations don't.
bool hasImplicitSection() const
Check if section name is present.
bool isConstant() const
If the value is a global constant, its value is immutable throughout the runtime execution of the pro...
This class implements a map that also provides access to all stored values in a deterministic order.
A Module instance is used to store all the information related to an LLVM module.
static LLVM_ABI PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
Pass interface - Implemented by all 'passes'.
Class to represent pointers.
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
PreservedAnalyses & preserveSet()
Mark an analysis set as preserved.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StringRef - Represent a constant reference to a string, i.e.
bool starts_with(StringRef Prefix) const
Check if this string starts with the given Prefix.
Used to lazily calculate structure layout information for a target machine, based on the DataLayout s...
TypeSize getElementOffset(unsigned Idx) const
Class to represent struct types.
static LLVM_ABI StructType * get(LLVMContext &Context, ArrayRef< Type * > Elements, bool isPacked=false)
This static method is the primary way to create a literal StructType.
static SectionKind getKindForGlobal(const GlobalObject *GO, const TargetMachine &TM)
Classify the specified global variable into a set of target independent categories embodied in Sectio...
Primary interface to the complete machine description for the target machine.
bool shouldAssumeDSOLocal(const GlobalValue *GV) const
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
The instances of the Type class are immutable: once they are created, they are never changed.
static LLVM_ABI IntegerType * getInt32Ty(LLVMContext &C)
static LLVM_ABI IntegerType * getInt8Ty(LLVMContext &C)
A Use represents the edge between a Value definition and its users.
Value * getOperand(unsigned i) const
unsigned getNumOperands() const
LLVM_ABI const Value * stripPointerCasts() const
Strip off pointer casts, all-zero GEPs and address space casts.
iterator_range< use_iterator > uses()
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
@ CE
Windows NT (Windows on ARM)
initializer< Ty > init(const Ty &Val)
PointerTypeMap run(const Module &M)
Compute the PointerTypeMap for the module M.
std::enable_if_t< detail::IsValidPointer< X, Y >::value, X * > extract(Y &&MD)
Extract a Value from Metadata.
Expected< const typename ELFT::Shdr * > getSection(typename ELFT::ShdrRange Sections, uint32_t Index)
This is an optimization pass for GlobalISel generic memory operations.
void stable_sort(R &&Range)
decltype(auto) dyn_cast(const From &Val)
dyn_cast - Return the argument parameter cast to the specified type.
FunctionAddr VTableAddr uintptr_t uintptr_t Int32Ty
LLVM_ABI Pass * createGlobalMergePass(const TargetMachine *TM, unsigned MaximalOffset, bool OnlyOptimizeForSize=false, bool MergeExternalByDefault=false, bool MergeConstantByDefault=false, bool MergeConstAggressiveByDefault=false)
GlobalMerge - This pass merges internal (by default) globals into structs to enable reuse of a base p...
Definition GlobalMerge.cpp:764
LLVM_ABI void initializeGlobalMergePass(PassRegistry &)
auto reverse(ContainerTy &&C)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
bool isa(const From &Val)
isa - Return true if the parameter to the template is an instance of one of the template type argu...
uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
decltype(auto) cast(const From &Val)
cast - Return the argument parameter cast to the specified type.
AnalysisManager< Module > ModuleAnalysisManager
Convenience typedef for the Module analysis manager.
LLVM_ABI GlobalVariable * collectUsedGlobalVariables(const Module &M, SmallVectorImpl< GlobalValue * > &Vec, bool CompilerUsed)
Given "llvm.used" or "llvm.compiler.used" as a global name, collect the initializer elements of that ...
This struct is a compact representation of a valid (non-zero power of two) alignment.
bool MergeConstAggressive
Whether we should merge constant global variables aggressively without looking at use.
bool SizeOnly
Whether we should try to optimize for size only.
bool MergeExternal
Whether we should merge global variables that have external linkage.
bool MergeConstantGlobals
Whether we should merge constant global variables.