diff options
author | Chris Lattner <sabre@nondot.org> | 2004-12-12 05:53:50 +0000 |
---|---|---|
committer | Chris Lattner <sabre@nondot.org> | 2004-12-12 05:53:50 +0000 |
commit | 96a86b2993c03be1de934b2c4e10ed08dbacfe0a (patch) | |
tree | 47e62fa96344175212b18d7e20ccae8cbbfcffc6 /lib | |
parent | ef07cc5e489def0561d45d850d4eeccee723d5db (diff) | |
download | external_llvm-96a86b2993c03be1de934b2c4e10ed08dbacfe0a.zip external_llvm-96a86b2993c03be1de934b2c4e10ed08dbacfe0a.tar.gz external_llvm-96a86b2993c03be1de934b2c4e10ed08dbacfe0a.tar.bz2 |
If a variable can only hold two values, and is not already a bool, shrink it
down to actually BE a bool. This allows simple value range propagation
stuff work harder, deleting comparisons in bzip2 in some hot loops.
This implements GlobalOpt/integer-bool.ll, which is the essence of the
loop condition distilled into a testcase.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@18817 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Transforms/IPO/GlobalOpt.cpp | 100 |
1 files changed, 78 insertions, 22 deletions
diff --git a/lib/Transforms/IPO/GlobalOpt.cpp b/lib/Transforms/IPO/GlobalOpt.cpp index 0fde1d9..6309c3b 100644 --- a/lib/Transforms/IPO/GlobalOpt.cpp +++ b/lib/Transforms/IPO/GlobalOpt.cpp @@ -38,6 +38,8 @@ namespace { Statistic<> NumDeleted ("globalopt", "Number of globals deleted"); Statistic<> NumFnDeleted("globalopt", "Number of functions deleted"); Statistic<> NumGlobUses ("globalopt", "Number of global uses devirtualized"); + Statistic<> NumShrunkToBool("globalopt", + "Number of global vars shrunk to booleans"); struct GlobalOpt : public ModulePass { virtual void getAnalysisUsage(AnalysisUsage &AU) const { @@ -817,6 +819,50 @@ static bool OptimizeOnceStoredGlobal(GlobalVariable *GV, Value *StoredOnceVal, return false; } +/// ShrinkGlobalToBoolean - At this point, we have learned that the only two +/// values ever stored into GV are its initializer and OtherVal. +static void ShrinkGlobalToBoolean(GlobalVariable *GV, Constant *OtherVal) { + // Create the new global, initializing it to false. + GlobalVariable *NewGV = new GlobalVariable(Type::BoolTy, false, + GlobalValue::InternalLinkage, ConstantBool::False, GV->getName()+".b"); + GV->getParent()->getGlobalList().insert(GV, NewGV); + + Constant *InitVal = GV->getInitializer(); + assert(InitVal->getType() != Type::BoolTy && "No reason to shrink to bool!"); + + // If initialized to zero and storing one into the global, we can use a cast + // instead of a select to synthesize the desired value. + bool IsOneZero = false; + if (ConstantInt *CI = dyn_cast<ConstantInt>(OtherVal)) + IsOneZero = InitVal->isNullValue() && CI->equalsInt(1); + + while (!GV->use_empty()) { + Instruction *UI = cast<Instruction>(GV->use_back()); + if (StoreInst *SI = dyn_cast<StoreInst>(UI)) { + // Change the store into a boolean store. + bool StoringOther = SI->getOperand(0) == OtherVal; + // Only do this if we weren't storing a loaded value. + if (StoringOther || SI->getOperand(0) == InitVal) + new StoreInst(ConstantBool::get(StoringOther), NewGV, SI); + } else { + // Change the load into a load of bool then a select. + LoadInst *LI = cast<LoadInst>(UI); + std::string Name = LI->getName(); LI->setName(""); + LoadInst *NLI = new LoadInst(NewGV, Name+".b", LI); + Value *NSI; + if (IsOneZero) + NSI = new CastInst(NLI, LI->getType(), Name, LI); + else + NSI = new SelectInst(NLI, OtherVal, InitVal, Name, LI); + LI->replaceAllUsesWith(NSI); + } + UI->eraseFromParent(); + } + + GV->eraseFromParent(); +} + + /// ProcessInternalGlobal - Analyze the specified global variable and optimize /// it if possible. If we make a change, return true. bool GlobalOpt::ProcessInternalGlobal(GlobalVariable *GV, @@ -875,35 +921,45 @@ bool GlobalOpt::ProcessInternalGlobal(GlobalVariable *GV, return true; } } else if (GS.StoredType == GlobalStatus::isStoredOnce) { - // If the initial value for the global was an undef value, and if only one - // other value was stored into it, we can just change the initializer to - // be an undef value, then delete all stores to the global. This allows - // us to mark it constant. - if (isa<UndefValue>(GV->getInitializer()) && - isa<Constant>(GS.StoredOnceValue)) { - // Change the initial value here. - GV->setInitializer(cast<Constant>(GS.StoredOnceValue)); - - // Clean up any obviously simplifiable users now. - CleanupConstantGlobalUsers(GV, GV->getInitializer()); - - if (GV->use_empty()) { - DEBUG(std::cerr << " *** Substituting initializer allowed us to " - "simplify all users and delete global!\n"); - GV->eraseFromParent(); - ++NumDeleted; - } else { - GVI = GV; + // If the initial value for the global was an undef value, and if only + // one other value was stored into it, we can just change the + // initializer to be an undef value, then delete all stores to the + // global. This allows us to mark it constant. + if (Constant *SOVConstant = dyn_cast<Constant>(GS.StoredOnceValue)) + if (isa<UndefValue>(GV->getInitializer())) { + // Change the initial value here. + GV->setInitializer(SOVConstant); + + // Clean up any obviously simplifiable users now. + CleanupConstantGlobalUsers(GV, GV->getInitializer()); + + if (GV->use_empty()) { + DEBUG(std::cerr << " *** Substituting initializer allowed us to " + "simplify all users and delete global!\n"); + GV->eraseFromParent(); + ++NumDeleted; + } else { + GVI = GV; + } + ++NumSubstitute; + return true; } - ++NumSubstitute; - return true; - } // 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, getAnalysis<TargetData>())) return true; + + // Otherwise, if the global was not a boolean, we can shrink it to be a + // boolean. + if (Constant *SOVConstant = dyn_cast<Constant>(GS.StoredOnceValue)) + if (GV->getType()->getElementType() != Type::BoolTy) { + DEBUG(std::cerr << " *** SHRINKING TO BOOL: " << *GV); + ShrinkGlobalToBoolean(GV, SOVConstant); + ++NumShrunkToBool; + return true; + } } } return false; |