From: Alkis Evlogimenos Date: Thu, 10 Feb 2005 18:36:30 +0000 (+0000) Subject: Localize globals if they are only used in main(). This replaces the X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=f64ea9d1221f52c47fed2ea86a74946c05f224ad;p=oota-llvm.git Localize globals if they are only used in main(). This replaces the global with an alloca, which eventually gets promoted into a register. This enables a lot of other optimizations later on. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@20109 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Transforms/IPO/GlobalOpt.cpp b/lib/Transforms/IPO/GlobalOpt.cpp index f2c9647e130..59ea4a6f6f0 100644 --- a/lib/Transforms/IPO/GlobalOpt.cpp +++ b/lib/Transforms/IPO/GlobalOpt.cpp @@ -38,6 +38,7 @@ namespace { Statistic<> NumDeleted ("globalopt", "Number of globals deleted"); Statistic<> NumFnDeleted("globalopt", "Number of functions deleted"); Statistic<> NumGlobUses ("globalopt", "Number of global uses devirtualized"); + Statistic<> NumLocalized("globalopt", "Number of globals localized"); Statistic<> NumShrunkToBool("globalopt", "Number of global vars shrunk to booleans"); @@ -92,12 +93,20 @@ struct GlobalStatus { /// ever stored to this global, keep track of what value it is. Value *StoredOnceValue; + // AccessingFunction/HasMultipleAccessingFunctions - These start out + // null/false. When the first accessing function is noticed, it is recorded. + // When a second different accessing function is noticed, + // HasMultipleAccessingFunctions is set to true. + Function *AccessingFunction; + bool HasMultipleAccessingFunctions; + /// isNotSuitableForSRA - Keep track of whether any SRA preventing users of /// the global exist. Such users include GEP instruction with variable /// indexes, and non-gep/load/store users like constant expr casts. bool isNotSuitableForSRA; GlobalStatus() : isLoaded(false), StoredType(NotStored), StoredOnceValue(0), + AccessingFunction(0), HasMultipleAccessingFunctions(false), isNotSuitableForSRA(false) {} }; @@ -146,6 +155,13 @@ static bool AnalyzeGlobal(Value *V, GlobalStatus &GS, } } else if (Instruction *I = dyn_cast(*UI)) { + if (!GS.HasMultipleAccessingFunctions) { + Function *F = I->getParent()->getParent(); + if (GS.AccessingFunction == 0) + GS.AccessingFunction = F; + else if (GS.AccessingFunction != F) + GS.HasMultipleAccessingFunctions = true; + } if (isa(I)) { GS.isLoaded = true; } else if (StoreInst *SI = dyn_cast(I)) { @@ -898,6 +914,30 @@ bool GlobalOpt::ProcessInternalGlobal(GlobalVariable *GV, } if (!AnalyzeGlobal(GV, GS, PHIUsers)) { + // If this is a first class global and has only one accessing function + // and this function is main (which we know is not recursive we can make + // this global a local variable) we replace the global with a local alloca + // in this function. + // + // NOTE: It doesn't make sense to promote non first class types since we + // are just replacing static memory to stack memory. + if (!GS.HasMultipleAccessingFunctions && + GS.AccessingFunction && + GV->getType()->getElementType()->isFirstClassType() && + GS.AccessingFunction->getName() == "main" && + GS.AccessingFunction->hasExternalLinkage()) { + DEBUG(std::cerr << "LOCALIZING GLOBAL: " << *GV); + Instruction* FirstI = GS.AccessingFunction->getEntryBlock().begin(); + const Type* ElemTy = GV->getType()->getElementType(); + AllocaInst* Alloca = new AllocaInst(ElemTy, NULL, GV->getName(), FirstI); + if (!isa(GV->getInitializer())) + new StoreInst(GV->getInitializer(), Alloca, FirstI); + + GV->replaceAllUsesWith(Alloca); + GV->eraseFromParent(); + ++NumLocalized; + return true; + } // If the global is never loaded (but may be stored to), it is dead. // Delete it now. if (!GS.isLoaded) {