87 #define DEBUG_TYPE "global-merge"
92 cl::desc(
"Enable the global merge pass"),
101 cl::desc(
"Improve global merge pass to ignore globals only used alone"),
106 cl::desc(
"Enable global merge pass on constants"),
113 cl::desc(
"Enable global merge pass on external linkage"),
116 STATISTIC(NumMerged,
"Number of globals merged");
130 bool OnlyOptimizeForSize;
133 Module &M,
bool isConst,
unsigned AddrSpace)
const;
138 unsigned AddrSpace)
const;
144 return MustKeepGlobalVariables.count(GV);
149 void setMustKeepGlobalVariables(
Module &M);
160 unsigned MaximalOffset = 0,
161 bool OnlyOptimizeForSize =
false)
163 OnlyOptimizeForSize(OnlyOptimizeForSize) {
167 bool doInitialization(
Module &M)
override;
168 bool runOnFunction(
Function &
F)
override;
169 bool doFinalization(
Module &M)
override;
171 const char *getPassName()
const override {
172 return "Merge internal globals";
189 Module &M,
bool isConst,
unsigned AddrSpace)
const {
190 auto &
DL = M.getDataLayout();
193 Globals.begin(), Globals.end(),
195 Type *Ty1 = cast<PointerType>(GV1->
getType())->getElementType();
196 Type *Ty2 = cast<PointerType>(GV2->getType())->getElementType();
198 return (
DL.getTypeAllocSize(Ty1) <
DL.getTypeAllocSize(Ty2));
205 return doMerge(Globals, AllGlobals, M, isConst, AddrSpace);
227 struct UsedGlobalSet {
228 UsedGlobalSet(
size_t Size) : Globals(Size), UsageCount(1) {}
234 std::vector<UsedGlobalSet> UsedGlobalSets;
237 auto CreateGlobalSet = [&]() -> UsedGlobalSet & {
238 UsedGlobalSets.emplace_back(Globals.size());
239 return UsedGlobalSets.back();
243 CreateGlobalSet().UsageCount = 0;
264 std::vector<size_t> EncounteredUGS;
266 for (
size_t GI = 0,
GE = Globals.size(); GI !=
GE; ++GI) {
270 std::fill(EncounteredUGS.begin(), EncounteredUGS.end(), 0);
272 EncounteredUGS.resize(UsedGlobalSets.size());
276 size_t CurGVOnlySetIdx = 0;
279 for (
auto &U : GV->
uses()) {
283 if (
ConstantExpr *CE = dyn_cast<ConstantExpr>(U.getUser())) {
286 UI = &*CE->use_begin();
288 }
else if (isa<Instruction>(U.getUser())) {
297 for (; UI != UE; UI = UI->getNext()) {
305 if (OnlyOptimizeForSize &&
309 size_t UGSIdx = GlobalUsesByFunction[ParentFn];
315 if (!CurGVOnlySetIdx) {
316 CurGVOnlySetIdx = UsedGlobalSets.
size();
317 CreateGlobalSet().Globals.set(GI);
319 ++UsedGlobalSets[CurGVOnlySetIdx].UsageCount;
322 GlobalUsesByFunction[ParentFn] = CurGVOnlySetIdx;
327 if (UsedGlobalSets[UGSIdx].Globals.test(GI)) {
328 ++UsedGlobalSets[UGSIdx].UsageCount;
333 --UsedGlobalSets[UGSIdx].UsageCount;
337 if (
size_t ExpandedIdx = EncounteredUGS[UGSIdx]) {
338 ++UsedGlobalSets[ExpandedIdx].UsageCount;
339 GlobalUsesByFunction[ParentFn] = ExpandedIdx;
345 GlobalUsesByFunction[ParentFn] = EncounteredUGS[UGSIdx] =
346 UsedGlobalSets.size();
348 UsedGlobalSet &NewUGS = CreateGlobalSet();
349 NewUGS.Globals.set(GI);
350 NewUGS.Globals |= UsedGlobalSets[UGSIdx].Globals;
361 std::sort(UsedGlobalSets.begin(), UsedGlobalSets.end(),
362 [](
const UsedGlobalSet &UGS1,
const UsedGlobalSet &UGS2) {
363 return UGS1.Globals.count() * UGS1.UsageCount <
364 UGS2.Globals.count() * UGS2.UsageCount;
372 for (
size_t i = 0, e = UsedGlobalSets.size(); i != e; ++i) {
373 const UsedGlobalSet &UGS = UsedGlobalSets[e - i - 1];
374 if (UGS.UsageCount == 0)
376 if (UGS.Globals.count() > 1)
377 AllGlobals |= UGS.Globals;
379 return doMerge(Globals, AllGlobals, M, isConst, AddrSpace);
389 bool Changed =
false;
391 for (
size_t i = 0, e = UsedGlobalSets.size(); i != e; ++i) {
392 const UsedGlobalSet &UGS = UsedGlobalSets[e - i - 1];
393 if (UGS.UsageCount == 0)
395 if (PickedGlobals.anyCommon(UGS.Globals))
397 PickedGlobals |= UGS.Globals;
401 if (UGS.Globals.count() < 2)
403 Changed |= doMerge(Globals, UGS.Globals, M, isConst, AddrSpace);
411 unsigned AddrSpace)
const {
416 assert(Globals.
size() > 1);
418 DEBUG(
dbgs() <<
" Trying to merge set, starts with #"
424 uint64_t MergedSize = 0;
425 std::vector<Type*> Tys;
426 std::vector<Constant*> Inits;
428 bool HasExternal =
false;
430 for (j = i; j != -1; j = GlobalSet.
find_next(j)) {
431 Type *Ty = Globals[j]->getType()->getElementType();
432 MergedSize += DL.getTypeAllocSize(Ty);
433 if (MergedSize > MaxOffset) {
437 Inits.push_back(Globals[j]->getInitializer());
439 if (Globals[j]->hasExternalLinkage() && !HasExternal) {
441 TheFirstExternal = Globals[j];
458 M, MergedTy, isConst, Linkage, MergedInit,
459 HasExternal ?
"_MergedGlobals_" + TheFirstExternal->
getName()
463 for (ssize_t k = i, idx = 0; k != j; k = GlobalSet.
find_next(k)) {
465 std::string
Name = Globals[k]->getName();
473 Globals[k]->replaceAllUsesWith(GEP);
474 Globals[k]->eraseFromParent();
478 auto *PTy = cast<PointerType>(GEP->
getType());
501 MustKeepGlobalVariables.insert(
G);
504 void GlobalMerge::setMustKeepGlobalVariables(
Module &M) {
510 IBB != IEndBB; ++IBB) {
518 Idx != NumClauses; ++Idx)
520 dyn_cast<GlobalVariable>(LPInst->
getClause(Idx)
522 MustKeepGlobalVariables.insert(GV);
527 bool GlobalMerge::doInitialization(
Module &M) {
534 bool Changed =
false;
535 setMustKeepGlobalVariables(M);
541 if (
I->isDeclaration() ||
I->isThreadLocal() ||
I->hasSection())
545 !
I->hasInternalLinkage())
549 assert(PT &&
"Global variable is not a pointer!");
554 unsigned Alignment = DL.getPreferredAlignment(
I);
555 Type *Ty =
I->getType()->getElementType();
556 if (Alignment > DL.getABITypeAlignment(Ty))
560 if (
I->getName().startswith(
"llvm.") ||
561 I->getName().startswith(
".llvm."))
565 if (isMustKeepGlobalVariable(
I))
568 if (DL.getTypeAllocSize(Ty) < MaxOffset) {
570 BSSGlobals[AddressSpace].push_back(
I);
571 else if (
I->isConstant())
572 ConstGlobals[AddressSpace].push_back(
I);
579 I = Globals.
begin(), E = Globals.
end();
I != E; ++
I)
580 if (
I->second.size() > 1)
581 Changed |= doMerge(
I->second, M,
false,
I->first);
584 I = BSSGlobals.
begin(), E = BSSGlobals.
end();
I != E; ++
I)
585 if (
I->second.size() > 1)
586 Changed |= doMerge(
I->second, M,
false,
I->first);
590 I = ConstGlobals.
begin(), E = ConstGlobals.
end();
I != E; ++
I)
591 if (
I->second.size() > 1)
592 Changed |= doMerge(
I->second, M,
true,
I->first);
597 bool GlobalMerge::runOnFunction(
Function &
F) {
601 bool GlobalMerge::doFinalization(
Module &M) {
602 MustKeepGlobalVariables.clear();
607 bool OnlyOptimizeForSize) {
608 return new GlobalMerge(TM, Offset, OnlyOptimizeForSize);
Pass interface - Implemented by all 'passes'.
void push_back(const T &Elt)
static SectionKind getKindForGlobal(const GlobalValue *GV, const TargetMachine &TM)
Classify the specified global variable into a set of target independent categories embodied in Sectio...
int find_first() const
find_first - Returns the index of the first set bit, -1 if none of the bits are set.
iterator_range< use_iterator > uses()
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
STATISTIC(NumFunctions,"Total number of functions")
A Module instance is used to store all the information related to an LLVM module. ...
Constant * getClause(unsigned Idx) const
Get the value of the clause at index Idx.
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))
unsigned getNumOperands() const
int find_next(unsigned Prev) const
find_next - Returns the index of the next set bit following the "Prev" bit.
virtual void getAnalysisUsage(AnalysisUsage &) const
getAnalysisUsage - This function should be overriden by passes that need analysis information to do t...
INITIALIZE_PASS_BEGIN(GlobalMerge,"global-merge","Merge global variables", false, false) INITIALIZE_PASS_END(GlobalMerge
Externally visible function.
const Function * getParent() const
Return the enclosing method, or null if none.
unsigned getAddressSpace() const
Return the address space of the Pointer type.
const Constant * getInitializer() const
getInitializer - Return the initializer for this global variable.
StringRef getName() const
Return a constant reference to the value's name.
global Merge global variables
StructType - Class to represent struct types.
A Use represents the edge between a Value definition and its users.
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
This file contains the simple types necessary to represent the attributes associated with functions a...
static cl::opt< bool > EnableGlobalMerge("enable-global-merge", cl::Hidden, cl::desc("Enable the global merge pass"), cl::init(true))
global_iterator global_begin()
ConstantExpr - a constant value that is initialized with an expression using other constant values...
unsigned getNumClauses() const
getNumClauses - Get the number of clauses for this landing pad.
PointerType - Class to represent pointers.
initializer< Ty > init(const Ty &Val)
static Constant * getInBoundsGetElementPtr(Type *Ty, Constant *C, ArrayRef< Constant * > IdxList)
Create an "inbounds" getelementptr.
LandingPadInst - The landingpad instruction holds all of the information necessary to generate correc...
Constant * stripPointerCasts()
The instances of the Type class are immutable: once they are created, they are never changed...
static GlobalAlias * create(PointerType *Ty, 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...
This is an important base class in LLVM.
This file contains the declarations for the subclasses of Constant, which represent the different fla...
LandingPadInst * getLandingPadInst()
Return the landingpad instruction associated with the landing pad.
Represent the analysis usage information of a pass.
FunctionPass class - This class is used to implement most global optimizations.
Value * getOperand(unsigned i) const
static Constant * get(StructType *T, ArrayRef< Constant * > V)
global Merge global false
global_iterator global_end()
BasicBlock * getUnwindDest() const
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements...
static StructType * get(LLVMContext &Context, ArrayRef< Type * > Elements, bool isPacked=false)
StructType::get - This static method is the primary way to create a literal StructType.
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small...
Module.h This file contains the declarations for the Module class.
Type * getType() const
All values are typed, get the type of this value.
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))
Value * stripPointerCasts()
Strip off pointer casts, all-zero GEPs, and aliases.
static Constant * get(Type *Ty, uint64_t V, bool isSigned=false)
If Ty is a vector type, return a Constant with a splat of the given value.
void setPreservesCFG()
This function should be called by the pass, iff they do not:
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
ConstantArray - Constant Array Declarations.
bool hasInitializer() const
Definitions have initializers, declarations don't.
LinkageTypes
An enumeration for the kinds of linkage for global values.
LLVM_ATTRIBUTE_UNUSED_RESULT std::enable_if< !is_simple_type< Y >::value, typename cast_retty< X, const Y >::ret_type >::type dyn_cast(const Y &Val)
PointerType * getType() const
Global values are always pointers.
const DataLayout & getDataLayout() const
Get the data layout for the module's target platform.
bool hasFnAttribute(Attribute::AttrKind Kind) const
Return true if the function has the attribute.
static IntegerType * getInt32Ty(LLVMContext &C)
static cl::opt< bool > EnableGlobalMergeOnExternal("global-merge-on-external", cl::Hidden, cl::desc("Enable global merge pass on external linkage"), cl::init(false))
Rename collisions when linking (static functions).
static cl::opt< bool > EnableGlobalMergeOnConst("global-merge-on-const", cl::Hidden, cl::desc("Enable global merge pass on constants"), cl::init(false))
void initializeGlobalMergePass(PassRegistry &)
GlobalVariable * collectUsedGlobalVariables(Module &M, SmallPtrSetImpl< GlobalValue * > &Set, bool CompilerUsed)
Given "llvm.used" or "llvm.compiler.used" as a global name, collect the initializer elements of that ...
InvokeInst - Invoke instruction.
Primary interface to the complete machine description for the target machine.
const BasicBlock * getParent() const
GlobalVariable * getGlobalVariable(StringRef Name) const
Look up the specified global variable in the module symbol table.
Pass * createGlobalMergePass(const TargetMachine *TM, unsigned MaximalOffset, bool OnlyOptimizeForSize=false)
LLVMContext & getContext() const
Get the global data context.
This file describes how to lower LLVM code to machine code.
Function must be optimized for size first.