diff options
Diffstat (limited to 'lib/Transforms/IPO/GlobalOpt.cpp')
-rw-r--r-- | lib/Transforms/IPO/GlobalOpt.cpp | 715 |
1 files changed, 415 insertions, 300 deletions
diff --git a/lib/Transforms/IPO/GlobalOpt.cpp b/lib/Transforms/IPO/GlobalOpt.cpp index 3552d03..1522aa4 100644 --- a/lib/Transforms/IPO/GlobalOpt.cpp +++ b/lib/Transforms/IPO/GlobalOpt.cpp @@ -26,6 +26,7 @@ #include "llvm/Analysis/ConstantFolding.h" #include "llvm/Analysis/MemoryBuiltins.h" #include "llvm/Target/TargetData.h" +#include "llvm/Target/TargetLibraryInfo.h" #include "llvm/Support/CallSite.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" @@ -61,6 +62,7 @@ namespace { struct GlobalStatus; struct GlobalOpt : public ModulePass { virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.addRequired<TargetLibraryInfo>(); } static char ID; // Pass identification, replacement for typeid GlobalOpt() : ModulePass(ID) { @@ -80,11 +82,17 @@ namespace { const SmallPtrSet<const PHINode*, 16> &PHIUsers, const GlobalStatus &GS); bool OptimizeEmptyGlobalCXXDtors(Function *CXAAtExitFn); + + TargetData *TD; + TargetLibraryInfo *TLI; }; } char GlobalOpt::ID = 0; -INITIALIZE_PASS(GlobalOpt, "globalopt", +INITIALIZE_PASS_BEGIN(GlobalOpt, "globalopt", + "Global Variable Optimizer", false, false) +INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfo) +INITIALIZE_PASS_END(GlobalOpt, "globalopt", "Global Variable Optimizer", false, false) ModulePass *llvm::createGlobalOptimizerPass() { return new GlobalOpt(); } @@ -143,18 +151,31 @@ struct GlobalStatus { /// HasPHIUser - Set to true if this global has a user that is a PHI node. bool HasPHIUser; + /// AtomicOrdering - Set to the strongest atomic ordering requirement. + AtomicOrdering Ordering; + GlobalStatus() : isCompared(false), isLoaded(false), StoredType(NotStored), StoredOnceValue(0), AccessingFunction(0), - HasMultipleAccessingFunctions(false), HasNonInstructionUser(false), - HasPHIUser(false) {} + HasMultipleAccessingFunctions(false), + HasNonInstructionUser(false), HasPHIUser(false), + Ordering(NotAtomic) {} }; } -// SafeToDestroyConstant - It is safe to destroy a constant iff it is only used -// by constants itself. Note that constants cannot be cyclic, so this test is -// pretty easy to implement recursively. -// +/// StrongerOrdering - Return the stronger of the two ordering. If the two +/// orderings are acquire and release, then return AcquireRelease. +/// +static AtomicOrdering StrongerOrdering(AtomicOrdering X, AtomicOrdering Y) { + if (X == Acquire && Y == Release) return AcquireRelease; + if (Y == Acquire && X == Release) return AcquireRelease; + return (AtomicOrdering)std::max(X, Y); +} + +/// SafeToDestroyConstant - It is safe to destroy a constant iff it is only used +/// by constants itself. Note that constants cannot be cyclic, so this test is +/// pretty easy to implement recursively. +/// static bool SafeToDestroyConstant(const Constant *C) { if (isa<GlobalValue>(C)) return false; @@ -195,14 +216,16 @@ static bool AnalyzeGlobal(const Value *V, GlobalStatus &GS, } if (const LoadInst *LI = dyn_cast<LoadInst>(I)) { GS.isLoaded = true; - // Don't hack on volatile/atomic loads. - if (!LI->isSimple()) return true; + // Don't hack on volatile loads. + if (LI->isVolatile()) return true; + GS.Ordering = StrongerOrdering(GS.Ordering, LI->getOrdering()); } else if (const StoreInst *SI = dyn_cast<StoreInst>(I)) { // Don't allow a store OF the address, only stores TO the address. if (SI->getOperand(0) == V) return true; - // Don't hack on volatile/atomic stores. - if (!SI->isSimple()) return true; + // Don't hack on volatile stores. + if (SI->isVolatile()) return true; + GS.Ordering = StrongerOrdering(GS.Ordering, SI->getOrdering()); // If this is a direct store to the global (i.e., the global is a scalar // value, not an aggregate), keep more specific information about @@ -271,43 +294,12 @@ static bool AnalyzeGlobal(const Value *V, GlobalStatus &GS, return false; } -static Constant *getAggregateConstantElement(Constant *Agg, Constant *Idx) { - ConstantInt *CI = dyn_cast<ConstantInt>(Idx); - if (!CI) return 0; - unsigned IdxV = CI->getZExtValue(); - - if (ConstantStruct *CS = dyn_cast<ConstantStruct>(Agg)) { - if (IdxV < CS->getNumOperands()) return CS->getOperand(IdxV); - } else if (ConstantArray *CA = dyn_cast<ConstantArray>(Agg)) { - if (IdxV < CA->getNumOperands()) return CA->getOperand(IdxV); - } else if (ConstantVector *CP = dyn_cast<ConstantVector>(Agg)) { - if (IdxV < CP->getNumOperands()) return CP->getOperand(IdxV); - } else if (isa<ConstantAggregateZero>(Agg)) { - if (StructType *STy = dyn_cast<StructType>(Agg->getType())) { - if (IdxV < STy->getNumElements()) - return Constant::getNullValue(STy->getElementType(IdxV)); - } else if (SequentialType *STy = - dyn_cast<SequentialType>(Agg->getType())) { - return Constant::getNullValue(STy->getElementType()); - } - } else if (isa<UndefValue>(Agg)) { - if (StructType *STy = dyn_cast<StructType>(Agg->getType())) { - if (IdxV < STy->getNumElements()) - return UndefValue::get(STy->getElementType(IdxV)); - } else if (SequentialType *STy = - dyn_cast<SequentialType>(Agg->getType())) { - return UndefValue::get(STy->getElementType()); - } - } - return 0; -} - - /// CleanupConstantGlobalUsers - We just marked GV constant. Loop over all /// users of the global, cleaning up the obvious ones. This is largely just a /// quick scan over the use list to clean up the easy and obvious cruft. This /// returns true if it made a change. -static bool CleanupConstantGlobalUsers(Value *V, Constant *Init) { +static bool CleanupConstantGlobalUsers(Value *V, Constant *Init, + TargetData *TD, TargetLibraryInfo *TLI) { bool Changed = false; for (Value::use_iterator UI = V->use_begin(), E = V->use_end(); UI != E;) { User *U = *UI++; @@ -328,11 +320,11 @@ static bool CleanupConstantGlobalUsers(Value *V, Constant *Init) { Constant *SubInit = 0; if (Init) SubInit = ConstantFoldLoadThroughGEPConstantExpr(Init, CE); - Changed |= CleanupConstantGlobalUsers(CE, SubInit); + Changed |= CleanupConstantGlobalUsers(CE, SubInit, TD, TLI); } else if (CE->getOpcode() == Instruction::BitCast && CE->getType()->isPointerTy()) { // Pointer cast, delete any stores and memsets to the global. - Changed |= CleanupConstantGlobalUsers(CE, 0); + Changed |= CleanupConstantGlobalUsers(CE, 0, TD, TLI); } if (CE->use_empty()) { @@ -346,11 +338,17 @@ static bool CleanupConstantGlobalUsers(Value *V, Constant *Init) { Constant *SubInit = 0; if (!isa<ConstantExpr>(GEP->getOperand(0))) { ConstantExpr *CE = - dyn_cast_or_null<ConstantExpr>(ConstantFoldInstruction(GEP)); + dyn_cast_or_null<ConstantExpr>(ConstantFoldInstruction(GEP, TD, TLI)); if (Init && CE && CE->getOpcode() == Instruction::GetElementPtr) SubInit = ConstantFoldLoadThroughGEPConstantExpr(Init, CE); + + // If the initializer is an all-null value and we have an inbounds GEP, + // we already know what the result of any load from that GEP is. + // TODO: Handle splats. + if (Init && isa<ConstantAggregateZero>(Init) && GEP->isInBounds()) + SubInit = Constant::getNullValue(GEP->getType()->getElementType()); } - Changed |= CleanupConstantGlobalUsers(GEP, SubInit); + Changed |= CleanupConstantGlobalUsers(GEP, SubInit, TD, TLI); if (GEP->use_empty()) { GEP->eraseFromParent(); @@ -368,7 +366,7 @@ static bool CleanupConstantGlobalUsers(Value *V, Constant *Init) { if (SafeToDestroyConstant(C)) { C->destroyConstant(); // This could have invalidated UI, start over from scratch. - CleanupConstantGlobalUsers(V, Init); + CleanupConstantGlobalUsers(V, Init, TD, TLI); return true; } } @@ -514,8 +512,7 @@ static GlobalVariable *SRAGlobal(GlobalVariable *GV, const TargetData &TD) { NewGlobals.reserve(STy->getNumElements()); const StructLayout &Layout = *TD.getStructLayout(STy); for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i) { - Constant *In = getAggregateConstantElement(Init, - ConstantInt::get(Type::getInt32Ty(STy->getContext()), i)); + Constant *In = Init->getAggregateElement(i); assert(In && "Couldn't get element of initializer?"); GlobalVariable *NGV = new GlobalVariable(STy->getElementType(i), false, GlobalVariable::InternalLinkage, @@ -547,8 +544,7 @@ static GlobalVariable *SRAGlobal(GlobalVariable *GV, const TargetData &TD) { uint64_t EltSize = TD.getTypeAllocSize(STy->getElementType()); unsigned EltAlign = TD.getABITypeAlignment(STy->getElementType()); for (unsigned i = 0, e = NumElements; i != e; ++i) { - Constant *In = getAggregateConstantElement(Init, - ConstantInt::get(Type::getInt32Ty(Init->getContext()), i)); + Constant *In = Init->getAggregateElement(i); assert(In && "Couldn't get element of initializer?"); GlobalVariable *NGV = new GlobalVariable(STy->getElementType(), false, @@ -770,7 +766,9 @@ static bool OptimizeAwayTrappingUsesOfValue(Value *V, Constant *NewV) { /// value stored into it. If there are uses of the loaded value that would trap /// if the loaded value is dynamically null, then we know that they cannot be /// reachable with a null optimize away the load. -static bool OptimizeAwayTrappingUsesOfLoads(GlobalVariable *GV, Constant *LV) { +static bool OptimizeAwayTrappingUsesOfLoads(GlobalVariable *GV, Constant *LV, + TargetData *TD, + TargetLibraryInfo *TLI) { bool Changed = false; // Keep track of whether we are able to remove all the uses of the global @@ -813,7 +811,7 @@ static bool OptimizeAwayTrappingUsesOfLoads(GlobalVariable *GV, Constant *LV) { // nor is the global. if (AllNonStoreUsesGone) { DEBUG(dbgs() << " *** GLOBAL NOW DEAD!\n"); - CleanupConstantGlobalUsers(GV, 0); + CleanupConstantGlobalUsers(GV, 0, TD, TLI); if (GV->use_empty()) { GV->eraseFromParent(); ++NumDeleted; @@ -825,10 +823,11 @@ static bool OptimizeAwayTrappingUsesOfLoads(GlobalVariable *GV, Constant *LV) { /// ConstantPropUsersOf - Walk the use list of V, constant folding all of the /// instructions that are foldable. -static void ConstantPropUsersOf(Value *V) { +static void ConstantPropUsersOf(Value *V, + TargetData *TD, TargetLibraryInfo *TLI) { for (Value::use_iterator UI = V->use_begin(), E = V->use_end(); UI != E; ) if (Instruction *I = dyn_cast<Instruction>(*UI++)) - if (Constant *NewC = ConstantFoldInstruction(I)) { + if (Constant *NewC = ConstantFoldInstruction(I, TD, TLI)) { I->replaceAllUsesWith(NewC); // Advance UI to the next non-I use to avoid invalidating it! @@ -848,7 +847,8 @@ static GlobalVariable *OptimizeGlobalAddressOfMalloc(GlobalVariable *GV, CallInst *CI, Type *AllocTy, ConstantInt *NElements, - TargetData* TD) { + TargetData *TD, + TargetLibraryInfo *TLI) { DEBUG(errs() << "PROMOTING GLOBAL: " << *GV << " CALL = " << *CI << '\n'); Type *GlobalType; @@ -906,7 +906,8 @@ static GlobalVariable *OptimizeGlobalAddressOfMalloc(GlobalVariable *GV, while (!GV->use_empty()) { if (StoreInst *SI = dyn_cast<StoreInst>(GV->use_back())) { // The global is initialized when the store to it occurs. - new StoreInst(ConstantInt::getTrue(GV->getContext()), InitBool, SI); + new StoreInst(ConstantInt::getTrue(GV->getContext()), InitBool, false, 0, + SI->getOrdering(), SI->getSynchScope(), SI); SI->eraseFromParent(); continue; } @@ -921,7 +922,10 @@ static GlobalVariable *OptimizeGlobalAddressOfMalloc(GlobalVariable *GV, ICmpInst *ICI = cast<ICmpInst>(LoadUse.getUser()); // Replace the cmp X, 0 with a use of the bool value. - Value *LV = new LoadInst(InitBool, InitBool->getName()+".val", ICI); + // Sink the load to where the compare was, if atomic rules allow us to. + Value *LV = new LoadInst(InitBool, InitBool->getName()+".val", false, 0, + LI->getOrdering(), LI->getSynchScope(), + LI->isUnordered() ? (Instruction*)ICI : LI); InitBoolUsed = true; switch (ICI->getPredicate()) { default: llvm_unreachable("Unknown ICmp Predicate!"); @@ -962,9 +966,9 @@ static GlobalVariable *OptimizeGlobalAddressOfMalloc(GlobalVariable *GV, // To further other optimizations, loop over all users of NewGV and try to // constant prop them. This will promote GEP instructions with constant // indices into GEP constant-exprs, which will allow global-opt to hack on it. - ConstantPropUsersOf(NewGV); + ConstantPropUsersOf(NewGV, TD, TLI); if (RepValue != NewGV) - ConstantPropUsersOf(RepValue); + ConstantPropUsersOf(RepValue, TD, TLI); return NewGV; } @@ -1203,7 +1207,6 @@ static Value *GetHeapSROAValue(Value *V, unsigned FieldNo, PHIsToRewrite.push_back(std::make_pair(PN, FieldNo)); } else { llvm_unreachable("Unknown usable value"); - Result = 0; } return FieldVals[FieldNo] = Result; @@ -1293,9 +1296,9 @@ static void RewriteUsesOfLoadForHeapSRoA(LoadInst *Load, /// PerformHeapAllocSRoA - CI is an allocation of an array of structures. Break /// it up into multiple allocations of arrays of the fields. static GlobalVariable *PerformHeapAllocSRoA(GlobalVariable *GV, CallInst *CI, - Value* NElems, TargetData *TD) { + Value *NElems, TargetData *TD) { DEBUG(dbgs() << "SROA HEAP ALLOC: " << *GV << " MALLOC = " << *CI << '\n'); - Type* MAT = getMallocAllocatedType(CI); + Type *MAT = getMallocAllocatedType(CI); StructType *STy = cast<StructType>(MAT); // There is guaranteed to be at least one use of the malloc (storing @@ -1482,8 +1485,10 @@ static GlobalVariable *PerformHeapAllocSRoA(GlobalVariable *GV, CallInst *CI, static bool TryToOptimizeStoreOfMallocToGlobal(GlobalVariable *GV, CallInst *CI, Type *AllocTy, + AtomicOrdering Ordering, Module::global_iterator &GVI, - TargetData *TD) { + TargetData *TD, + TargetLibraryInfo *TLI) { if (!TD) return false; @@ -1502,7 +1507,7 @@ static bool TryToOptimizeStoreOfMallocToGlobal(GlobalVariable *GV, // We can't optimize this if the malloc itself is used in a complex way, // for example, being stored into multiple globals. This allows the - // malloc to be stored into the specified global, loaded setcc'd, and + // malloc to be stored into the specified global, loaded icmp'd, and // GEP'd. These are all things we could transform to using the global // for. SmallPtrSet<const PHINode*, 8> PHIs; @@ -1523,7 +1528,7 @@ static bool TryToOptimizeStoreOfMallocToGlobal(GlobalVariable *GV, // (2048 bytes currently), as we don't want to introduce a 16M global or // something. if (NElements->getZExtValue() * TD->getTypeAllocSize(AllocTy) < 2048) { - GVI = OptimizeGlobalAddressOfMalloc(GV, CI, AllocTy, NElements, TD); + GVI = OptimizeGlobalAddressOfMalloc(GV, CI, AllocTy, NElements, TD, TLI); return true; } @@ -1531,6 +1536,9 @@ static bool TryToOptimizeStoreOfMallocToGlobal(GlobalVariable *GV, // into multiple malloc'd arrays, one for each field. This is basically // SRoA for malloc'd memory. + if (Ordering != NotAtomic) + return false; + // If this is an allocation of a fixed size array of structs, analyze as a // variable size array. malloc [100 x struct],1 -> malloc struct, 100 if (NElems == ConstantInt::get(CI->getArgOperand(0)->getType(), 1)) @@ -1563,7 +1571,7 @@ static bool TryToOptimizeStoreOfMallocToGlobal(GlobalVariable *GV, extractMallocCallFromBitCast(Malloc) : cast<CallInst>(Malloc); } - GVI = PerformHeapAllocSRoA(GV, CI, getMallocArraySize(CI, TD, true),TD); + GVI = PerformHeapAllocSRoA(GV, CI, getMallocArraySize(CI, TD, true), TD); return true; } @@ -1573,8 +1581,9 @@ static bool TryToOptimizeStoreOfMallocToGlobal(GlobalVariable *GV, // OptimizeOnceStoredGlobal - Try to optimize globals based on the knowledge // that only one value (besides its initializer) is ever stored to the global. static bool OptimizeOnceStoredGlobal(GlobalVariable *GV, Value *StoredOnceVal, + AtomicOrdering Ordering, Module::global_iterator &GVI, - TargetData *TD) { + TargetData *TD, TargetLibraryInfo *TLI) { // Ignore no-op GEPs and bitcasts. StoredOnceVal = StoredOnceVal->stripPointerCasts(); @@ -1589,12 +1598,13 @@ static bool OptimizeOnceStoredGlobal(GlobalVariable *GV, Value *StoredOnceVal, SOVC = ConstantExpr::getBitCast(SOVC, GV->getInitializer()->getType()); // Optimize away any trapping uses of the loaded value. - if (OptimizeAwayTrappingUsesOfLoads(GV, SOVC)) + if (OptimizeAwayTrappingUsesOfLoads(GV, SOVC, TD, TLI)) return true; } else if (CallInst *CI = extractMallocCall(StoredOnceVal)) { - Type* MallocType = getMallocAllocatedType(CI); - if (MallocType && TryToOptimizeStoreOfMallocToGlobal(GV, CI, MallocType, - GVI, TD)) + Type *MallocType = getMallocAllocatedType(CI); + if (MallocType && + TryToOptimizeStoreOfMallocToGlobal(GV, CI, MallocType, Ordering, GVI, + TD, TLI)) return true; } } @@ -1670,7 +1680,8 @@ static bool TryToShrinkGlobalToBoolean(GlobalVariable *GV, Constant *OtherVal) { if (LoadInst *LI = dyn_cast<LoadInst>(StoredVal)) { assert(LI->getOperand(0) == GV && "Not a copy!"); // Insert a new load, to preserve the saved value. - StoreVal = new LoadInst(NewGV, LI->getName()+".b", LI); + StoreVal = new LoadInst(NewGV, LI->getName()+".b", false, 0, + LI->getOrdering(), LI->getSynchScope(), LI); } else { assert((isa<CastInst>(StoredVal) || isa<SelectInst>(StoredVal)) && "This is not a form that we understand!"); @@ -1678,11 +1689,13 @@ static bool TryToShrinkGlobalToBoolean(GlobalVariable *GV, Constant *OtherVal) { assert(isa<LoadInst>(StoreVal) && "Not a load of NewGV!"); } } - new StoreInst(StoreVal, NewGV, SI); + new StoreInst(StoreVal, NewGV, false, 0, + SI->getOrdering(), SI->getSynchScope(), SI); } else { // Change the load into a load of bool then a select. LoadInst *LI = cast<LoadInst>(UI); - LoadInst *NLI = new LoadInst(NewGV, LI->getName()+".b", LI); + LoadInst *NLI = new LoadInst(NewGV, LI->getName()+".b", false, 0, + LI->getOrdering(), LI->getSynchScope(), LI); Value *NSI; if (IsOneZero) NSI = new ZExtInst(NLI, LI->getType(), "", LI); @@ -1699,8 +1712,8 @@ static bool TryToShrinkGlobalToBoolean(GlobalVariable *GV, Constant *OtherVal) { } -/// ProcessInternalGlobal - Analyze the specified global variable and optimize -/// it if possible. If we make a change, return true. +/// ProcessGlobal - Analyze the specified global variable and optimize it if +/// possible. If we make a change, return true. bool GlobalOpt::ProcessGlobal(GlobalVariable *GV, Module::global_iterator &GVI) { if (!GV->hasLocalLinkage()) @@ -1737,7 +1750,7 @@ bool GlobalOpt::ProcessGlobal(GlobalVariable *GV, /// it if possible. If we make a change, return true. bool GlobalOpt::ProcessInternalGlobal(GlobalVariable *GV, Module::global_iterator &GVI, - const SmallPtrSet<const PHINode*, 16> &PHIUsers, + const SmallPtrSet<const PHINode*, 16> &PHIUsers, const GlobalStatus &GS) { // 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 @@ -1755,11 +1768,11 @@ bool GlobalOpt::ProcessInternalGlobal(GlobalVariable *GV, GS.AccessingFunction->hasExternalLinkage() && GV->getType()->getAddressSpace() == 0) { DEBUG(dbgs() << "LOCALIZING GLOBAL: " << *GV); - Instruction& FirstI = const_cast<Instruction&>(*GS.AccessingFunction + Instruction &FirstI = const_cast<Instruction&>(*GS.AccessingFunction ->getEntryBlock().begin()); - Type* ElemTy = GV->getType()->getElementType(); + Type *ElemTy = GV->getType()->getElementType(); // FIXME: Pass Global's alignment when globals have alignment - AllocaInst* Alloca = new AllocaInst(ElemTy, NULL, GV->getName(), &FirstI); + AllocaInst *Alloca = new AllocaInst(ElemTy, NULL, GV->getName(), &FirstI); if (!isa<UndefValue>(GV->getInitializer())) new StoreInst(GV->getInitializer(), Alloca, &FirstI); @@ -1776,7 +1789,8 @@ bool GlobalOpt::ProcessInternalGlobal(GlobalVariable *GV, // Delete any stores we can find to the global. We may not be able to // make it completely dead though. - bool Changed = CleanupConstantGlobalUsers(GV, GV->getInitializer()); + bool Changed = CleanupConstantGlobalUsers(GV, GV->getInitializer(), + TD, TLI); // If the global is dead now, delete it. if (GV->use_empty()) { @@ -1791,7 +1805,7 @@ bool GlobalOpt::ProcessInternalGlobal(GlobalVariable *GV, GV->setConstant(true); // Clean up any obviously simplifiable users now. - CleanupConstantGlobalUsers(GV, GV->getInitializer()); + CleanupConstantGlobalUsers(GV, GV->getInitializer(), TD, TLI); // If the global is dead now, just nuke it. if (GV->use_empty()) { @@ -1820,7 +1834,7 @@ bool GlobalOpt::ProcessInternalGlobal(GlobalVariable *GV, GV->setInitializer(SOVConstant); // Clean up any obviously simplifiable users now. - CleanupConstantGlobalUsers(GV, GV->getInitializer()); + CleanupConstantGlobalUsers(GV, GV->getInitializer(), TD, TLI); if (GV->use_empty()) { DEBUG(dbgs() << " *** Substituting initializer allowed us to " @@ -1836,8 +1850,8 @@ bool GlobalOpt::ProcessInternalGlobal(GlobalVariable *GV, // Try to optimize globals based on the knowledge that only one value // (besides its initializer) is ever stored to the global. - if (OptimizeOnceStoredGlobal(GV, GS.StoredOnceValue, GVI, - getAnalysisIfAvailable<TargetData>())) + if (OptimizeOnceStoredGlobal(GV, GS.StoredOnceValue, GS.Ordering, GVI, + TD, TLI)) return true; // Otherwise, if the global was not a boolean, we can shrink it to be a @@ -1890,7 +1904,7 @@ bool GlobalOpt::OptimizeFunctions(Module &M) { if (!F->hasName() && !F->isDeclaration()) F->setLinkage(GlobalValue::InternalLinkage); F->removeDeadConstantUsers(); - if (F->use_empty() && (F->hasLocalLinkage() || F->hasLinkOnceLinkage())) { + if (F->isDefTriviallyDead()) { F->eraseFromParent(); Changed = true; ++NumFnDeleted; @@ -1930,8 +1944,7 @@ bool GlobalOpt::OptimizeGlobalVars(Module &M) { // Simplify the initializer. if (GV->hasInitializer()) if (ConstantExpr *CE = dyn_cast<ConstantExpr>(GV->getInitializer())) { - TargetData *TD = getAnalysisIfAvailable<TargetData>(); - Constant *New = ConstantFoldConstantExpression(CE, TD); + Constant *New = ConstantFoldConstantExpression(CE, TD, TLI); if (New && New != CE) GV->setInitializer(New); } @@ -2052,16 +2065,10 @@ static GlobalVariable *InstallGlobalCtors(GlobalVariable *GCL, } -static Constant *getVal(DenseMap<Value*, Constant*> &ComputedValues, Value *V) { - if (Constant *CV = dyn_cast<Constant>(V)) return CV; - Constant *R = ComputedValues[V]; - assert(R && "Reference to an uncomputed value!"); - return R; -} - static inline bool isSimpleEnoughValueToCommit(Constant *C, - SmallPtrSet<Constant*, 8> &SimpleConstants); + SmallPtrSet<Constant*, 8> &SimpleConstants, + const TargetData *TD); /// isSimpleEnoughValueToCommit - Return true if the specified constant can be @@ -2073,7 +2080,8 @@ isSimpleEnoughValueToCommit(Constant *C, /// in SimpleConstants to avoid having to rescan the same constants all the /// time. static bool isSimpleEnoughValueToCommitHelper(Constant *C, - SmallPtrSet<Constant*, 8> &SimpleConstants) { + SmallPtrSet<Constant*, 8> &SimpleConstants, + const TargetData *TD) { // Simple integer, undef, constant aggregate zero, global addresses, etc are // all supported. if (C->getNumOperands() == 0 || isa<BlockAddress>(C) || @@ -2085,7 +2093,7 @@ static bool isSimpleEnoughValueToCommitHelper(Constant *C, isa<ConstantVector>(C)) { for (unsigned i = 0, e = C->getNumOperands(); i != e; ++i) { Constant *Op = cast<Constant>(C->getOperand(i)); - if (!isSimpleEnoughValueToCommit(Op, SimpleConstants)) + if (!isSimpleEnoughValueToCommit(Op, SimpleConstants, TD)) return false; } return true; @@ -2097,34 +2105,42 @@ static bool isSimpleEnoughValueToCommitHelper(Constant *C, ConstantExpr *CE = cast<ConstantExpr>(C); switch (CE->getOpcode()) { case Instruction::BitCast: + // Bitcast is fine if the casted value is fine. + return isSimpleEnoughValueToCommit(CE->getOperand(0), SimpleConstants, TD); + case Instruction::IntToPtr: case Instruction::PtrToInt: - // These casts are always fine if the casted value is. - return isSimpleEnoughValueToCommit(CE->getOperand(0), SimpleConstants); + // int <=> ptr is fine if the int type is the same size as the + // pointer type. + if (!TD || TD->getTypeSizeInBits(CE->getType()) != + TD->getTypeSizeInBits(CE->getOperand(0)->getType())) + return false; + return isSimpleEnoughValueToCommit(CE->getOperand(0), SimpleConstants, TD); // GEP is fine if it is simple + constant offset. case Instruction::GetElementPtr: for (unsigned i = 1, e = CE->getNumOperands(); i != e; ++i) if (!isa<ConstantInt>(CE->getOperand(i))) return false; - return isSimpleEnoughValueToCommit(CE->getOperand(0), SimpleConstants); + return isSimpleEnoughValueToCommit(CE->getOperand(0), SimpleConstants, TD); case Instruction::Add: // We allow simple+cst. if (!isa<ConstantInt>(CE->getOperand(1))) return false; - return isSimpleEnoughValueToCommit(CE->getOperand(0), SimpleConstants); + return isSimpleEnoughValueToCommit(CE->getOperand(0), SimpleConstants, TD); } return false; } static inline bool isSimpleEnoughValueToCommit(Constant *C, - SmallPtrSet<Constant*, 8> &SimpleConstants) { + SmallPtrSet<Constant*, 8> &SimpleConstants, + const TargetData *TD) { // If we already checked this constant, we win. if (!SimpleConstants.insert(C)) return true; // Check the constant. - return isSimpleEnoughValueToCommitHelper(C, SimpleConstants); + return isSimpleEnoughValueToCommitHelper(C, SimpleConstants, TD); } @@ -2191,23 +2207,11 @@ static Constant *EvaluateStoreInto(Constant *Init, Constant *Val, return Val; } - std::vector<Constant*> Elts; + SmallVector<Constant*, 32> Elts; if (StructType *STy = dyn_cast<StructType>(Init->getType())) { - // Break up the constant into its elements. - if (ConstantStruct *CS = dyn_cast<ConstantStruct>(Init)) { - for (User::op_iterator i = CS->op_begin(), e = CS->op_end(); i != e; ++i) - Elts.push_back(cast<Constant>(*i)); - } else if (isa<ConstantAggregateZero>(Init)) { - for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i) - Elts.push_back(Constant::getNullValue(STy->getElementType(i))); - } else if (isa<UndefValue>(Init)) { - for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i) - Elts.push_back(UndefValue::get(STy->getElementType(i))); - } else { - llvm_unreachable("This code is out of sync with " - " ConstantFoldLoadThroughGEPConstantExpr"); - } + for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i) + Elts.push_back(Init->getAggregateElement(i)); // Replace the element that we are supposed to. ConstantInt *CU = cast<ConstantInt>(Addr->getOperand(OpNo)); @@ -2226,22 +2230,11 @@ static Constant *EvaluateStoreInto(Constant *Init, Constant *Val, if (ArrayType *ATy = dyn_cast<ArrayType>(InitTy)) NumElts = ATy->getNumElements(); else - NumElts = cast<VectorType>(InitTy)->getNumElements(); + NumElts = InitTy->getVectorNumElements(); // Break up the array into elements. - if (ConstantArray *CA = dyn_cast<ConstantArray>(Init)) { - for (User::op_iterator i = CA->op_begin(), e = CA->op_end(); i != e; ++i) - Elts.push_back(cast<Constant>(*i)); - } else if (ConstantVector *CV = dyn_cast<ConstantVector>(Init)) { - for (User::op_iterator i = CV->op_begin(), e = CV->op_end(); i != e; ++i) - Elts.push_back(cast<Constant>(*i)); - } else if (isa<ConstantAggregateZero>(Init)) { - Elts.assign(NumElts, Constant::getNullValue(InitTy->getElementType())); - } else { - assert(isa<UndefValue>(Init) && "This code is out of sync with " - " ConstantFoldLoadThroughGEPConstantExpr"); - Elts.assign(NumElts, UndefValue::get(InitTy->getElementType())); - } + for (uint64_t i = 0, e = NumElts; i != e; ++i) + Elts.push_back(Init->getAggregateElement(i)); assert(CI->getZExtValue() < NumElts); Elts[CI->getZExtValue()] = @@ -2266,15 +2259,109 @@ static void CommitValueTo(Constant *Val, Constant *Addr) { GV->setInitializer(EvaluateStoreInto(GV->getInitializer(), Val, CE, 2)); } +namespace { + +/// Evaluator - This class evaluates LLVM IR, producing the Constant +/// representing each SSA instruction. Changes to global variables are stored +/// in a mapping that can be iterated over after the evaluation is complete. +/// Once an evaluation call fails, the evaluation object should not be reused. +class Evaluator { +public: + Evaluator(const TargetData *TD, const TargetLibraryInfo *TLI) + : TD(TD), TLI(TLI) { + ValueStack.push_back(new DenseMap<Value*, Constant*>); + } + + ~Evaluator() { + DeleteContainerPointers(ValueStack); + while (!AllocaTmps.empty()) { + GlobalVariable *Tmp = AllocaTmps.back(); + AllocaTmps.pop_back(); + + // If there are still users of the alloca, the program is doing something + // silly, e.g. storing the address of the alloca somewhere and using it + // later. Since this is undefined, we'll just make it be null. + if (!Tmp->use_empty()) + Tmp->replaceAllUsesWith(Constant::getNullValue(Tmp->getType())); + delete Tmp; + } + } + + /// EvaluateFunction - Evaluate a call to function F, returning true if + /// successful, false if we can't evaluate it. ActualArgs contains the formal + /// arguments for the function. + bool EvaluateFunction(Function *F, Constant *&RetVal, + const SmallVectorImpl<Constant*> &ActualArgs); + + /// EvaluateBlock - Evaluate all instructions in block BB, returning true if + /// successful, false if we can't evaluate it. NewBB returns the next BB that + /// control flows into, or null upon return. + bool EvaluateBlock(BasicBlock::iterator CurInst, BasicBlock *&NextBB); + + Constant *getVal(Value *V) { + if (Constant *CV = dyn_cast<Constant>(V)) return CV; + Constant *R = ValueStack.back()->lookup(V); + assert(R && "Reference to an uncomputed value!"); + return R; + } + + void setVal(Value *V, Constant *C) { + ValueStack.back()->operator[](V) = C; + } + + const DenseMap<Constant*, Constant*> &getMutatedMemory() const { + return MutatedMemory; + } + + const SmallPtrSet<GlobalVariable*, 8> &getInvariants() const { + return Invariants; + } + +private: + Constant *ComputeLoadResult(Constant *P); + + /// ValueStack - As we compute SSA register values, we store their contents + /// here. The back of the vector contains the current function and the stack + /// contains the values in the calling frames. + SmallVector<DenseMap<Value*, Constant*>*, 4> ValueStack; + + /// CallStack - This is used to detect recursion. In pathological situations + /// we could hit exponential behavior, but at least there is nothing + /// unbounded. + SmallVector<Function*, 4> CallStack; + + /// MutatedMemory - For each store we execute, we update this map. Loads + /// check this to get the most up-to-date value. If evaluation is successful, + /// this state is committed to the process. + DenseMap<Constant*, Constant*> MutatedMemory; + + /// AllocaTmps - To 'execute' an alloca, we create a temporary global variable + /// to represent its body. This vector is needed so we can delete the + /// temporary globals when we are done. + SmallVector<GlobalVariable*, 32> AllocaTmps; + + /// Invariants - These global variables have been marked invariant by the + /// static constructor. + SmallPtrSet<GlobalVariable*, 8> Invariants; + + /// SimpleConstants - These are constants we have checked and know to be + /// simple enough to live in a static initializer of a global. + SmallPtrSet<Constant*, 8> SimpleConstants; + + const TargetData *TD; + const TargetLibraryInfo *TLI; +}; + +} // anonymous namespace + /// ComputeLoadResult - Return the value that would be computed by a load from /// P after the stores reflected by 'memory' have been performed. If we can't /// decide, return null. -static Constant *ComputeLoadResult(Constant *P, - const DenseMap<Constant*, Constant*> &Memory) { +Constant *Evaluator::ComputeLoadResult(Constant *P) { // If this memory location has been recently stored, use the stored value: it // is the most up-to-date. - DenseMap<Constant*, Constant*>::const_iterator I = Memory.find(P); - if (I != Memory.end()) return I->second; + DenseMap<Constant*, Constant*>::const_iterator I = MutatedMemory.find(P); + if (I != MutatedMemory.end()) return I->second; // Access it. if (GlobalVariable *GV = dyn_cast<GlobalVariable>(P)) { @@ -2295,56 +2382,29 @@ static Constant *ComputeLoadResult(Constant *P, return 0; // don't know how to evaluate. } -/// EvaluateFunction - Evaluate a call to function F, returning true if -/// successful, false if we can't evaluate it. ActualArgs contains the formal -/// arguments for the function. -static bool EvaluateFunction(Function *F, Constant *&RetVal, - const SmallVectorImpl<Constant*> &ActualArgs, - std::vector<Function*> &CallStack, - DenseMap<Constant*, Constant*> &MutatedMemory, - std::vector<GlobalVariable*> &AllocaTmps, - SmallPtrSet<Constant*, 8> &SimpleConstants, - const TargetData *TD) { - // Check to see if this function is already executing (recursion). If so, - // bail out. TODO: we might want to accept limited recursion. - if (std::find(CallStack.begin(), CallStack.end(), F) != CallStack.end()) - return false; - - CallStack.push_back(F); - - /// Values - As we compute SSA register values, we store their contents here. - DenseMap<Value*, Constant*> Values; - - // Initialize arguments to the incoming values specified. - unsigned ArgNo = 0; - for (Function::arg_iterator AI = F->arg_begin(), E = F->arg_end(); AI != E; - ++AI, ++ArgNo) - Values[AI] = ActualArgs[ArgNo]; - - /// ExecutedBlocks - We only handle non-looping, non-recursive code. As such, - /// we can only evaluate any one basic block at most once. This set keeps - /// track of what we have executed so we can detect recursive cases etc. - SmallPtrSet<BasicBlock*, 32> ExecutedBlocks; - - // CurInst - The current instruction we're evaluating. - BasicBlock::iterator CurInst = F->begin()->begin(); - +/// EvaluateBlock - Evaluate all instructions in block BB, returning true if +/// successful, false if we can't evaluate it. NewBB returns the next BB that +/// control flows into, or null upon return. +bool Evaluator::EvaluateBlock(BasicBlock::iterator CurInst, + BasicBlock *&NextBB) { // This is the main evaluation loop. while (1) { Constant *InstResult = 0; if (StoreInst *SI = dyn_cast<StoreInst>(CurInst)) { if (!SI->isSimple()) return false; // no volatile/atomic accesses. - Constant *Ptr = getVal(Values, SI->getOperand(1)); + Constant *Ptr = getVal(SI->getOperand(1)); + if (ConstantExpr *CE = dyn_cast<ConstantExpr>(Ptr)) + Ptr = ConstantFoldConstantExpression(CE, TD, TLI); if (!isSimpleEnoughPointerToCommit(Ptr)) // If this is too complex for us to commit, reject it. return false; - Constant *Val = getVal(Values, SI->getOperand(0)); + Constant *Val = getVal(SI->getOperand(0)); // If this might be too difficult for the backend to handle (e.g. the addr // of one global variable divided by another) then we can't commit it. - if (!isSimpleEnoughValueToCommit(Val, SimpleConstants)) + if (!isSimpleEnoughValueToCommit(Val, SimpleConstants, TD)) return false; if (ConstantExpr *CE = dyn_cast<ConstantExpr>(Ptr)) @@ -2354,7 +2414,7 @@ static bool EvaluateFunction(Function *F, Constant *&RetVal, // stored value. Ptr = CE->getOperand(0); - Type *NewTy=cast<PointerType>(Ptr->getType())->getElementType(); + Type *NewTy = cast<PointerType>(Ptr->getType())->getElementType(); // In order to push the bitcast onto the stored value, a bitcast // from NewTy to Val's type must be legal. If it's not, we can try @@ -2366,16 +2426,18 @@ static bool EvaluateFunction(Function *F, Constant *&RetVal, if (StructType *STy = dyn_cast<StructType>(NewTy)) { NewTy = STy->getTypeAtIndex(0U); - IntegerType *IdxTy =IntegerType::get(NewTy->getContext(), 32); + IntegerType *IdxTy = IntegerType::get(NewTy->getContext(), 32); Constant *IdxZero = ConstantInt::get(IdxTy, 0, false); Constant * const IdxList[] = {IdxZero, IdxZero}; Ptr = ConstantExpr::getGetElementPtr(Ptr, IdxList); - + if (ConstantExpr *CE = dyn_cast<ConstantExpr>(Ptr)) + Ptr = ConstantFoldConstantExpression(CE, TD, TLI); + // If we can't improve the situation by introspecting NewTy, // we have to give up. } else { - return 0; + return false; } } @@ -2387,33 +2449,35 @@ static bool EvaluateFunction(Function *F, Constant *&RetVal, MutatedMemory[Ptr] = Val; } else if (BinaryOperator *BO = dyn_cast<BinaryOperator>(CurInst)) { InstResult = ConstantExpr::get(BO->getOpcode(), - getVal(Values, BO->getOperand(0)), - getVal(Values, BO->getOperand(1))); + getVal(BO->getOperand(0)), + getVal(BO->getOperand(1))); } else if (CmpInst *CI = dyn_cast<CmpInst>(CurInst)) { InstResult = ConstantExpr::getCompare(CI->getPredicate(), - getVal(Values, CI->getOperand(0)), - getVal(Values, CI->getOperand(1))); + getVal(CI->getOperand(0)), + getVal(CI->getOperand(1))); } else if (CastInst *CI = dyn_cast<CastInst>(CurInst)) { InstResult = ConstantExpr::getCast(CI->getOpcode(), - getVal(Values, CI->getOperand(0)), + getVal(CI->getOperand(0)), CI->getType()); } else if (SelectInst *SI = dyn_cast<SelectInst>(CurInst)) { - InstResult = ConstantExpr::getSelect(getVal(Values, SI->getOperand(0)), - getVal(Values, SI->getOperand(1)), - getVal(Values, SI->getOperand(2))); + InstResult = ConstantExpr::getSelect(getVal(SI->getOperand(0)), + getVal(SI->getOperand(1)), + getVal(SI->getOperand(2))); } else if (GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(CurInst)) { - Constant *P = getVal(Values, GEP->getOperand(0)); + Constant *P = getVal(GEP->getOperand(0)); SmallVector<Constant*, 8> GEPOps; for (User::op_iterator i = GEP->op_begin() + 1, e = GEP->op_end(); i != e; ++i) - GEPOps.push_back(getVal(Values, *i)); + GEPOps.push_back(getVal(*i)); InstResult = ConstantExpr::getGetElementPtr(P, GEPOps, cast<GEPOperator>(GEP)->isInBounds()); } else if (LoadInst *LI = dyn_cast<LoadInst>(CurInst)) { if (!LI->isSimple()) return false; // no volatile/atomic accesses. - InstResult = ComputeLoadResult(getVal(Values, LI->getOperand(0)), - MutatedMemory); + Constant *Ptr = getVal(LI->getOperand(0)); + if (ConstantExpr *CE = dyn_cast<ConstantExpr>(Ptr)) + Ptr = ConstantFoldConstantExpression(CE, TD, TLI); + InstResult = ComputeLoadResult(Ptr); if (InstResult == 0) return false; // Could not evaluate load. } else if (AllocaInst *AI = dyn_cast<AllocaInst>(CurInst)) { if (AI->isArrayAllocation()) return false; // Cannot handle array allocs. @@ -2423,25 +2487,53 @@ static bool EvaluateFunction(Function *F, Constant *&RetVal, UndefValue::get(Ty), AI->getName())); InstResult = AllocaTmps.back(); - } else if (CallInst *CI = dyn_cast<CallInst>(CurInst)) { + } else if (isa<CallInst>(CurInst) || isa<InvokeInst>(CurInst)) { + CallSite CS(CurInst); // Debug info can safely be ignored here. - if (isa<DbgInfoIntrinsic>(CI)) { + if (isa<DbgInfoIntrinsic>(CS.getInstruction())) { ++CurInst; continue; } // Cannot handle inline asm. - if (isa<InlineAsm>(CI->getCalledValue())) return false; - - if (MemSetInst *MSI = dyn_cast<MemSetInst>(CI)) { - if (MSI->isVolatile()) return false; - Constant *Ptr = getVal(Values, MSI->getDest()); - Constant *Val = getVal(Values, MSI->getValue()); - Constant *DestVal = ComputeLoadResult(getVal(Values, Ptr), - MutatedMemory); - if (Val->isNullValue() && DestVal && DestVal->isNullValue()) { - // This memset is a no-op. + if (isa<InlineAsm>(CS.getCalledValue())) return false; + + if (IntrinsicInst *II = dyn_cast<IntrinsicInst>(CS.getInstruction())) { + if (MemSetInst *MSI = dyn_cast<MemSetInst>(II)) { + if (MSI->isVolatile()) return false; + Constant *Ptr = getVal(MSI->getDest()); + Constant *Val = getVal(MSI->getValue()); + Constant *DestVal = ComputeLoadResult(getVal(Ptr)); + if (Val->isNullValue() && DestVal && DestVal->isNullValue()) { + // This memset is a no-op. + ++CurInst; + continue; + } + } + + if (II->getIntrinsicID() == Intrinsic::lifetime_start || + II->getIntrinsicID() == Intrinsic::lifetime_end) { + ++CurInst; + continue; + } + + if (II->getIntrinsicID() == Intrinsic::invariant_start) { + // We don't insert an entry into Values, as it doesn't have a + // meaningful return value. + if (!II->use_empty()) + return false; + ConstantInt *Size = cast<ConstantInt>(II->getArgOperand(0)); + Value *PtrArg = getVal(II->getArgOperand(1)); + Value *Ptr = PtrArg->stripPointerCasts(); + if (GlobalVariable *GV = dyn_cast<GlobalVariable>(Ptr)) { + Type *ElemTy = cast<PointerType>(GV->getType())->getElementType(); + if (!Size->isAllOnesValue() && + Size->getValue().getLimitedValue() >= + TD->getTypeStoreSize(ElemTy)) + Invariants.insert(GV); + } + // Continue even if we do nothing. ++CurInst; continue; } @@ -2449,19 +2541,17 @@ static bool EvaluateFunction(Function *F, Constant *&RetVal, } // Resolve function pointers. - Function *Callee = dyn_cast<Function>(getVal(Values, - CI->getCalledValue())); - if (!Callee) return false; // Cannot resolve. + Function *Callee = dyn_cast<Function>(getVal(CS.getCalledValue())); + if (!Callee || Callee->mayBeOverridden()) + return false; // Cannot resolve. SmallVector<Constant*, 8> Formals; - CallSite CS(CI); - for (User::op_iterator i = CS.arg_begin(), e = CS.arg_end(); - i != e; ++i) - Formals.push_back(getVal(Values, *i)); + for (User::op_iterator i = CS.arg_begin(), e = CS.arg_end(); i != e; ++i) + Formals.push_back(getVal(*i)); if (Callee->isDeclaration()) { // If this is a function we can constant fold, do it. - if (Constant *C = ConstantFoldCall(Callee, Formals)) { + if (Constant *C = ConstantFoldCall(Callee, Formals, TLI)) { InstResult = C; } else { return false; @@ -2472,62 +2562,43 @@ static bool EvaluateFunction(Function *F, Constant *&RetVal, Constant *RetVal; // Execute the call, if successful, use the return value. - if (!EvaluateFunction(Callee, RetVal, Formals, CallStack, - MutatedMemory, AllocaTmps, SimpleConstants, TD)) + ValueStack.push_back(new DenseMap<Value*, Constant*>); + if (!EvaluateFunction(Callee, RetVal, Formals)) return false; + delete ValueStack.pop_back_val(); InstResult = RetVal; } } else if (isa<TerminatorInst>(CurInst)) { - BasicBlock *NewBB = 0; if (BranchInst *BI = dyn_cast<BranchInst>(CurInst)) { if (BI->isUnconditional()) { - NewBB = BI->getSuccessor(0); + NextBB = BI->getSuccessor(0); } else { ConstantInt *Cond = - dyn_cast<ConstantInt>(getVal(Values, BI->getCondition())); + dyn_cast<ConstantInt>(getVal(BI->getCondition())); if (!Cond) return false; // Cannot determine. - NewBB = BI->getSuccessor(!Cond->getZExtValue()); + NextBB = BI->getSuccessor(!Cond->getZExtValue()); } } else if (SwitchInst *SI = dyn_cast<SwitchInst>(CurInst)) { ConstantInt *Val = - dyn_cast<ConstantInt>(getVal(Values, SI->getCondition())); + dyn_cast<ConstantInt>(getVal(SI->getCondition())); if (!Val) return false; // Cannot determine. - NewBB = SI->getSuccessor(SI->findCaseValue(Val)); + NextBB = SI->findCaseValue(Val).getCaseSuccessor(); } else if (IndirectBrInst *IBI = dyn_cast<IndirectBrInst>(CurInst)) { - Value *Val = getVal(Values, IBI->getAddress())->stripPointerCasts(); + Value *Val = getVal(IBI->getAddress())->stripPointerCasts(); if (BlockAddress *BA = dyn_cast<BlockAddress>(Val)) - NewBB = BA->getBasicBlock(); + NextBB = BA->getBasicBlock(); else return false; // Cannot determine. - } else if (ReturnInst *RI = dyn_cast<ReturnInst>(CurInst)) { - if (RI->getNumOperands()) - RetVal = getVal(Values, RI->getOperand(0)); - - CallStack.pop_back(); // return from fn. - return true; // We succeeded at evaluating this ctor! + } else if (isa<ReturnInst>(CurInst)) { + NextBB = 0; } else { // invoke, unwind, resume, unreachable. return false; // Cannot handle this terminator. } - // Okay, we succeeded in evaluating this control flow. See if we have - // executed the new block before. If so, we have a looping function, - // which we cannot evaluate in reasonable time. - if (!ExecutedBlocks.insert(NewBB)) - return false; // looped! - - // Okay, we have never been in this block before. Check to see if there - // are any PHI nodes. If so, evaluate them with information about where - // we came from. - BasicBlock *OldBB = CurInst->getParent(); - CurInst = NewBB->begin(); - PHINode *PN; - for (; (PN = dyn_cast<PHINode>(CurInst)); ++CurInst) - Values[PN] = getVal(Values, PN->getIncomingValueForBlock(OldBB)); - - // Do NOT increment CurInst. We know that the terminator had no value. - continue; + // We succeeded at evaluating this block! + return true; } else { // Did not know how to evaluate this! return false; @@ -2535,9 +2606,15 @@ static bool EvaluateFunction(Function *F, Constant *&RetVal, if (!CurInst->use_empty()) { if (ConstantExpr *CE = dyn_cast<ConstantExpr>(InstResult)) - InstResult = ConstantFoldConstantExpression(CE, TD); + InstResult = ConstantFoldConstantExpression(CE, TD, TLI); - Values[CurInst] = InstResult; + setVal(CurInst, InstResult); + } + + // If we just processed an invoke, we finished evaluating the block. + if (InvokeInst *II = dyn_cast<InvokeInst>(CurInst)) { + NextBB = II->getNormalDest(); + return true; } // Advance program counter. @@ -2545,64 +2622,96 @@ static bool EvaluateFunction(Function *F, Constant *&RetVal, } } -/// EvaluateStaticConstructor - Evaluate static constructors in the function, if -/// we can. Return true if we can, false otherwise. -static bool EvaluateStaticConstructor(Function *F, const TargetData *TD) { - /// MutatedMemory - For each store we execute, we update this map. Loads - /// check this to get the most up-to-date value. If evaluation is successful, - /// this state is committed to the process. - DenseMap<Constant*, Constant*> MutatedMemory; +/// EvaluateFunction - Evaluate a call to function F, returning true if +/// successful, false if we can't evaluate it. ActualArgs contains the formal +/// arguments for the function. +bool Evaluator::EvaluateFunction(Function *F, Constant *&RetVal, + const SmallVectorImpl<Constant*> &ActualArgs) { + // Check to see if this function is already executing (recursion). If so, + // bail out. TODO: we might want to accept limited recursion. + if (std::find(CallStack.begin(), CallStack.end(), F) != CallStack.end()) + return false; - /// AllocaTmps - To 'execute' an alloca, we create a temporary global variable - /// to represent its body. This vector is needed so we can delete the - /// temporary globals when we are done. - std::vector<GlobalVariable*> AllocaTmps; + CallStack.push_back(F); - /// CallStack - This is used to detect recursion. In pathological situations - /// we could hit exponential behavior, but at least there is nothing - /// unbounded. - std::vector<Function*> CallStack; + // Initialize arguments to the incoming values specified. + unsigned ArgNo = 0; + for (Function::arg_iterator AI = F->arg_begin(), E = F->arg_end(); AI != E; + ++AI, ++ArgNo) + setVal(AI, ActualArgs[ArgNo]); - /// SimpleConstants - These are constants we have checked and know to be - /// simple enough to live in a static initializer of a global. - SmallPtrSet<Constant*, 8> SimpleConstants; - + // ExecutedBlocks - We only handle non-looping, non-recursive code. As such, + // we can only evaluate any one basic block at most once. This set keeps + // track of what we have executed so we can detect recursive cases etc. + SmallPtrSet<BasicBlock*, 32> ExecutedBlocks; + + // CurBB - The current basic block we're evaluating. + BasicBlock *CurBB = F->begin(); + + BasicBlock::iterator CurInst = CurBB->begin(); + + while (1) { + BasicBlock *NextBB = 0; // Initialized to avoid compiler warnings. + if (!EvaluateBlock(CurInst, NextBB)) + return false; + + if (NextBB == 0) { + // Successfully running until there's no next block means that we found + // the return. Fill it the return value and pop the call stack. + ReturnInst *RI = cast<ReturnInst>(CurBB->getTerminator()); + if (RI->getNumOperands()) + RetVal = getVal(RI->getOperand(0)); + CallStack.pop_back(); + return true; + } + + // Okay, we succeeded in evaluating this control flow. See if we have + // executed the new block before. If so, we have a looping function, + // which we cannot evaluate in reasonable time. + if (!ExecutedBlocks.insert(NextBB)) + return false; // looped! + + // Okay, we have never been in this block before. Check to see if there + // are any PHI nodes. If so, evaluate them with information about where + // we came from. + PHINode *PN = 0; + for (CurInst = NextBB->begin(); + (PN = dyn_cast<PHINode>(CurInst)); ++CurInst) + setVal(PN, getVal(PN->getIncomingValueForBlock(CurBB))); + + // Advance to the next block. + CurBB = NextBB; + } +} + +/// EvaluateStaticConstructor - Evaluate static constructors in the function, if +/// we can. Return true if we can, false otherwise. +static bool EvaluateStaticConstructor(Function *F, const TargetData *TD, + const TargetLibraryInfo *TLI) { // Call the function. + Evaluator Eval(TD, TLI); Constant *RetValDummy; - bool EvalSuccess = EvaluateFunction(F, RetValDummy, - SmallVector<Constant*, 0>(), CallStack, - MutatedMemory, AllocaTmps, - SimpleConstants, TD); + bool EvalSuccess = Eval.EvaluateFunction(F, RetValDummy, + SmallVector<Constant*, 0>()); if (EvalSuccess) { // We succeeded at evaluation: commit the result. DEBUG(dbgs() << "FULLY EVALUATED GLOBAL CTOR FUNCTION '" - << F->getName() << "' to " << MutatedMemory.size() + << F->getName() << "' to " << Eval.getMutatedMemory().size() << " stores.\n"); - for (DenseMap<Constant*, Constant*>::iterator I = MutatedMemory.begin(), - E = MutatedMemory.end(); I != E; ++I) + for (DenseMap<Constant*, Constant*>::const_iterator I = + Eval.getMutatedMemory().begin(), E = Eval.getMutatedMemory().end(); + I != E; ++I) CommitValueTo(I->second, I->first); - } - - // At this point, we are done interpreting. If we created any 'alloca' - // temporaries, release them now. - while (!AllocaTmps.empty()) { - GlobalVariable *Tmp = AllocaTmps.back(); - AllocaTmps.pop_back(); - - // If there are still users of the alloca, the program is doing something - // silly, e.g. storing the address of the alloca somewhere and using it - // later. Since this is undefined, we'll just make it be null. - if (!Tmp->use_empty()) - Tmp->replaceAllUsesWith(Constant::getNullValue(Tmp->getType())); - delete Tmp; + for (SmallPtrSet<GlobalVariable*, 8>::const_iterator I = + Eval.getInvariants().begin(), E = Eval.getInvariants().end(); + I != E; ++I) + (*I)->setConstant(true); } return EvalSuccess; } - - /// OptimizeGlobalCtorsList - Simplify and evaluation global ctors if possible. /// Return true if anything changed. bool GlobalOpt::OptimizeGlobalCtorsList(GlobalVariable *&GCL) { @@ -2610,7 +2719,6 @@ bool GlobalOpt::OptimizeGlobalCtorsList(GlobalVariable *&GCL) { bool MadeChange = false; if (Ctors.empty()) return false; - const TargetData *TD = getAnalysisIfAvailable<TargetData>(); // Loop over global ctors, optimizing them when we can. for (unsigned i = 0; i != Ctors.size(); ++i) { Function *F = Ctors[i]; @@ -2628,7 +2736,7 @@ bool GlobalOpt::OptimizeGlobalCtorsList(GlobalVariable *&GCL) { if (F->empty()) continue; // If we can evaluate the ctor at compile time, do. - if (EvaluateStaticConstructor(F, TD)) { + if (EvaluateStaticConstructor(F, TD, TLI)) { Ctors.erase(Ctors.begin()+i); MadeChange = true; --i; @@ -2700,12 +2808,15 @@ bool GlobalOpt::OptimizeGlobalAliases(Module &M) { return Changed; } -static Function *FindCXAAtExit(Module &M) { - Function *Fn = M.getFunction("__cxa_atexit"); +static Function *FindCXAAtExit(Module &M, TargetLibraryInfo *TLI) { + if (!TLI->has(LibFunc::cxa_atexit)) + return 0; + + Function *Fn = M.getFunction(TLI->getName(LibFunc::cxa_atexit)); if (!Fn) return 0; - + FunctionType *FTy = Fn->getFunctionType(); // Checking that the function has the right return type, the right number of @@ -2724,7 +2835,8 @@ static Function *FindCXAAtExit(Module &M) { /// destructor and can therefore be eliminated. /// Note that we assume that other optimization passes have already simplified /// the code so we only look for a function with a single basic block, where -/// the only allowed instructions are 'ret' or 'call' to empty C++ dtor. +/// the only allowed instructions are 'ret', 'call' to an empty C++ dtor and +/// other side-effect free instructions. static bool cxxDtorIsEmpty(const Function &Fn, SmallPtrSet<const Function *, 8> &CalledFunctions) { // FIXME: We could eliminate C++ destructors if they're readonly/readnone and @@ -2757,9 +2869,9 @@ static bool cxxDtorIsEmpty(const Function &Fn, if (!cxxDtorIsEmpty(*CalledFn, NewCalledFunctions)) return false; } else if (isa<ReturnInst>(*I)) - return true; - else - return false; + return true; // We're done. + else if (I->mayHaveSideEffects()) + return false; // Destructor with side effects, bail. } return false; @@ -2815,10 +2927,13 @@ bool GlobalOpt::OptimizeEmptyGlobalCXXDtors(Function *CXAAtExitFn) { bool GlobalOpt::runOnModule(Module &M) { bool Changed = false; + TD = getAnalysisIfAvailable<TargetData>(); + TLI = &getAnalysis<TargetLibraryInfo>(); + // Try to find the llvm.globalctors list. GlobalVariable *GlobalCtors = FindGlobalCtors(M); - Function *CXAAtExitFn = FindCXAAtExit(M); + Function *CXAAtExitFn = FindCXAAtExit(M, TLI); bool LocalChange = true; while (LocalChange) { |