[llvm-commits] CVS: llvm/lib/Transforms/IPO/GlobalOpt.cpp
Chris Lattner
lattner at cs.uiuc.edu
Sun Sep 25 21:44:46 PDT 2005
Changes in directory llvm/lib/Transforms/IPO:
GlobalOpt.cpp updated: 1.44 -> 1.45
---
Log message:
Add a simple interpreter to this code, allowing us to statically evaluate
global ctors that are simple enough. This implements ctor-list-opt.ll:CTOR2.
---
Diffs of the changes: (+110 -4)
GlobalOpt.cpp | 114 +++++++++++++++++++++++++++++++++++++++++++++++++++++++---
1 files changed, 110 insertions(+), 4 deletions(-)
Index: llvm/lib/Transforms/IPO/GlobalOpt.cpp
diff -u llvm/lib/Transforms/IPO/GlobalOpt.cpp:1.44 llvm/lib/Transforms/IPO/GlobalOpt.cpp:1.45
--- llvm/lib/Transforms/IPO/GlobalOpt.cpp:1.44 Sun Sep 25 21:31:18 2005
+++ llvm/lib/Transforms/IPO/GlobalOpt.cpp Sun Sep 25 23:44:35 2005
@@ -46,6 +46,7 @@
Statistic<> NumFastCallFns("globalopt",
"Number of functions converted to fastcc");
Statistic<> NumEmptyCtor ("globalopt", "Number of empty ctors removed");
+ Statistic<> NumCtorsEvaluated("globalopt","Number of static ctors evaluated");
struct GlobalOpt : public ModulePass {
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
@@ -1189,9 +1190,9 @@
// Create the new init list.
std::vector<Constant*> CAList;
for (unsigned i = 0, e = Ctors.size(); i != e; ++i) {
- if (Ctors[i])
+ if (Ctors[i]) {
CSVals[1] = Ctors[i];
- else {
+ } else {
const Type *FTy = FunctionType::get(Type::VoidTy,
std::vector<const Type*>(), false);
const PointerType *PFTy = PointerType::get(FTy);
@@ -1234,7 +1235,99 @@
else
return 0;
}
-
+
+
+static Constant *getVal(std::map<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;
+}
+
+/// isSimpleEnoughPointerToCommit - Return true if this constant is simple
+/// enough for us to understand. In particular, if it is a cast of something,
+/// we punt. We basically just support direct accesses to globals and GEP's of
+/// globals. This should be kept up to date with CommitValueTo.
+static bool isSimpleEnoughPointerToCommit(Constant *C) {
+ if (GlobalVariable *GV = dyn_cast<GlobalVariable>(C))
+ return !GV->isExternal(); // reject external globals.
+ return false;
+}
+
+/// CommitValueTo - We have decided that Addr (which satisfies the predicate
+/// isSimpleEnoughPointerToCommit) should get Val as its value. Make it happen.
+static void CommitValueTo(Constant *Val, Constant *Addr) {
+ GlobalVariable *GV = cast<GlobalVariable>(Addr);
+ assert(GV->hasInitializer());
+ GV->setInitializer(Val);
+}
+
+/// EvaluateStaticConstructor - Evaluate static constructors in the function, if
+/// we can. Return true if we can, false otherwise.
+static bool EvaluateStaticConstructor(Function *F) {
+ /// Values - As we compute SSA register values, we store their contents here.
+ std::map<Value*, Constant*> Values;
+
+ /// 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.
+ std::map<Constant*, Constant*> MutatedMemory;
+
+ // CurInst - The current instruction we're evaluating.
+ BasicBlock::iterator CurInst = F->begin()->begin();
+
+ // This is the main evaluation loop.
+ while (1) {
+ Constant *InstResult = 0;
+
+ if (StoreInst *SI = dyn_cast<StoreInst>(CurInst)) {
+ Constant *Ptr = getVal(Values, SI->getOperand(1));
+ if (!isSimpleEnoughPointerToCommit(Ptr))
+ // If this is too complex for us to commit, reject it.
+ return false;
+ Constant *Val = getVal(Values, SI->getOperand(0));
+ 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)));
+ } else if (ShiftInst *SI = dyn_cast<ShiftInst>(CurInst)) {
+ InstResult = ConstantExpr::get(SI->getOpcode(),
+ getVal(Values, SI->getOperand(0)),
+ getVal(Values, SI->getOperand(1)));
+ } else if (CastInst *CI = dyn_cast<CastInst>(CurInst)) {
+ InstResult = ConstantExpr::getCast(getVal(Values, 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)));
+ } else if (ReturnInst *RI = dyn_cast<ReturnInst>(CurInst)) {
+ assert(RI->getNumOperands() == 0);
+ break; // We succeeded at evaluating this ctor!
+ } else {
+ // TODO: use ConstantFoldCall for function calls.
+
+ // Did not know how to evaluate this!
+ return false;
+ }
+
+ if (!CurInst->use_empty())
+ Values[CurInst] = InstResult;
+
+ // Advance program counter.
+ ++CurInst;
+ }
+
+ // If we get here, we know that we succeeded at evaluation: commit the result.
+ //
+ for (std::map<Constant*, Constant*>::iterator I = MutatedMemory.begin(),
+ E = MutatedMemory.end(); I != E; ++I)
+ CommitValueTo(I->second, I->first);
+ return true;
+}
+
/// OptimizeGlobalCtorsList - Simplify and evaluation global ctors if possible.
/// Return true if anything changed.
@@ -1256,13 +1349,26 @@
break;
}
+ // We cannot simplify external ctor functions.
+ if (F->empty()) continue;
+
+ // If we can evaluate the ctor at compile time, do.
+ if (EvaluateStaticConstructor(F)) {
+ Ctors.erase(Ctors.begin()+i);
+ MadeChange = true;
+ --i;
+ ++NumCtorsEvaluated;
+ continue;
+ }
+
// If the function is empty, just remove it from the ctor list.
- if (!F->empty() && isa<ReturnInst>(F->begin()->getTerminator()) &&
+ if (isa<ReturnInst>(F->begin()->getTerminator()) &&
&F->begin()->front() == F->begin()->getTerminator()) {
Ctors.erase(Ctors.begin()+i);
MadeChange = true;
--i;
++NumEmptyCtor;
+ continue;
}
}
More information about the llvm-commits
mailing list