[llvm-commits] CVS: llvm/lib/Transforms/IPO/GlobalOpt.cpp
Chris Lattner
lattner at cs.uiuc.edu
Sat Dec 11 21:54:05 PST 2004
Changes in directory llvm/lib/Transforms/IPO:
GlobalOpt.cpp updated: 1.29 -> 1.30
---
Log message:
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.
---
Diffs of the changes: (+78 -22)
Index: llvm/lib/Transforms/IPO/GlobalOpt.cpp
diff -u llvm/lib/Transforms/IPO/GlobalOpt.cpp:1.29 llvm/lib/Transforms/IPO/GlobalOpt.cpp:1.30
--- llvm/lib/Transforms/IPO/GlobalOpt.cpp:1.29 Thu Dec 2 01:11:07 2004
+++ llvm/lib/Transforms/IPO/GlobalOpt.cpp Sat Dec 11 23:53:50 2004
@@ -38,6 +38,8 @@
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 @@
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 @@
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;
More information about the llvm-commits
mailing list