Move EvaluateFunction and EvaluateBlock into a class, and make the class store

the information that they pass around between them. No functionality change!


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@150939 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Nick Lewycky 2012-02-19 23:26:27 +00:00
parent 7db76e7ca3
commit 23ec5d7759

View File

@ -2059,13 +2059,6 @@ 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,
@ -2260,15 +2253,105 @@ static void CommitValueTo(Constant *Val, Constant *Addr) {
GV->setInitializer(EvaluateStoreInto(GV->getInitializer(), Val, CE, 2));
}
/// Evaluate - 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 Evaluate {
public:
Evaluate(const TargetData *TD, const TargetLibraryInfo *TLI)
: TD(TD), TLI(TLI) {
ValueStack.push_back(new DenseMap<Value*, Constant*>);
}
~Evaluate() {
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;
};
/// 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 *Evaluate::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)) {
@ -2289,40 +2372,22 @@ static Constant *ComputeLoadResult(Constant *P,
return 0; // don't know how to evaluate.
}
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,
SmallPtrSet<GlobalVariable*, 8> &Invariants,
const TargetData *TD,
const TargetLibraryInfo *TLI);
/// 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.
static bool EvaluateBlock(BasicBlock::iterator CurInst, BasicBlock *&NextBB,
std::vector<Function*> &CallStack,
DenseMap<Value*, Constant*> &Values,
DenseMap<Constant*, Constant*> &MutatedMemory,
std::vector<GlobalVariable*> &AllocaTmps,
SmallPtrSet<Constant*, 8> &SimpleConstants,
SmallPtrSet<GlobalVariable*, 8> &Invariants,
const TargetData *TD,
const TargetLibraryInfo *TLI) {
bool Evaluate::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 (!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.
@ -2369,33 +2434,32 @@ static bool EvaluateBlock(BasicBlock::iterator CurInst, BasicBlock *&NextBB,
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);
InstResult = ComputeLoadResult(getVal(LI->getOperand(0)));
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.
@ -2420,10 +2484,9 @@ static bool EvaluateBlock(BasicBlock::iterator CurInst, BasicBlock *&NextBB,
if (IntrinsicInst *II = dyn_cast<IntrinsicInst>(CS.getInstruction())) {
if (MemSetInst *MSI = dyn_cast<MemSetInst>(II)) {
if (MSI->isVolatile()) return false;
Constant *Ptr = getVal(Values, MSI->getDest());
Constant *Val = getVal(Values, MSI->getValue());
Constant *DestVal = ComputeLoadResult(getVal(Values, Ptr),
MutatedMemory);
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;
@ -2444,7 +2507,7 @@ static bool EvaluateBlock(BasicBlock::iterator CurInst, BasicBlock *&NextBB,
return false;
ConstantInt *Size = cast<ConstantInt>(II->getArgOperand(0));
if (Size->isAllOnesValue()) {
Value *PtrArg = getVal(Values, II->getArgOperand(1));
Value *PtrArg = getVal(II->getArgOperand(1));
Value *Ptr = PtrArg->stripPointerCasts();
if (GlobalVariable *GV = dyn_cast<GlobalVariable>(Ptr))
Invariants.insert(GV);
@ -2457,14 +2520,13 @@ static bool EvaluateBlock(BasicBlock::iterator CurInst, BasicBlock *&NextBB,
}
// Resolve function pointers.
Function *Callee = dyn_cast<Function>(getVal(Values,
CS.getCalledValue()));
Function *Callee = dyn_cast<Function>(getVal(CS.getCalledValue()));
if (!Callee || Callee->mayBeOverridden())
return false; // Cannot resolve.
SmallVector<Constant*, 8> Formals;
for (User::op_iterator i = CS.arg_begin(), e = CS.arg_end(); i != e; ++i)
Formals.push_back(getVal(Values, *i));
Formals.push_back(getVal(*i));
if (Callee->isDeclaration()) {
// If this is a function we can constant fold, do it.
@ -2479,10 +2541,10 @@ static bool EvaluateBlock(BasicBlock::iterator CurInst, BasicBlock *&NextBB,
Constant *RetVal;
// Execute the call, if successful, use the return value.
if (!EvaluateFunction(Callee, RetVal, Formals, CallStack,
MutatedMemory, AllocaTmps, SimpleConstants,
Invariants, TD, TLI))
ValueStack.push_back(new DenseMap<Value*, Constant*>);
if (!EvaluateFunction(Callee, RetVal, Formals))
return false;
ValueStack.pop_back();
InstResult = RetVal;
if (InvokeInst *II = dyn_cast<InvokeInst>(CurInst)) {
@ -2496,19 +2558,19 @@ static bool EvaluateBlock(BasicBlock::iterator CurInst, BasicBlock *&NextBB,
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.
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.
unsigned ValTISucc = SI->resolveSuccessorIndex(SI->findCaseValue(Val));
NextBB = SI->getSuccessor(ValTISucc);
} 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))
NextBB = BA->getBasicBlock();
else
@ -2531,7 +2593,7 @@ static bool EvaluateBlock(BasicBlock::iterator CurInst, BasicBlock *&NextBB,
if (ConstantExpr *CE = dyn_cast<ConstantExpr>(InstResult))
InstResult = ConstantFoldConstantExpression(CE, TD, TLI);
Values[CurInst] = InstResult;
setVal(CurInst, InstResult);
}
// Advance program counter.
@ -2542,15 +2604,8 @@ static bool EvaluateBlock(BasicBlock::iterator CurInst, BasicBlock *&NextBB,
/// 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,
SmallPtrSet<GlobalVariable*, 8> &Invariants,
const TargetData *TD,
const TargetLibraryInfo *TLI) {
bool Evaluate::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())
@ -2558,14 +2613,11 @@ static bool EvaluateFunction(Function *F, Constant *&RetVal,
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];
setVal(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
@ -2579,8 +2631,7 @@ static bool EvaluateFunction(Function *F, Constant *&RetVal,
while (1) {
BasicBlock *NextBB;
if (!EvaluateBlock(CurInst, NextBB, CallStack, Values, MutatedMemory,
AllocaTmps, SimpleConstants, Invariants, TD, TLI))
if (!EvaluateBlock(CurInst, NextBB))
return false;
if (NextBB == 0) {
@ -2588,7 +2639,7 @@ static bool EvaluateFunction(Function *F, Constant *&RetVal,
// the return. Fill it the return value and pop the call stack.
ReturnInst *RI = cast<ReturnInst>(CurBB->getTerminator());
if (RI->getNumOperands())
RetVal = getVal(Values, RI->getOperand(0));
RetVal = getVal(RI->getOperand(0));
CallStack.pop_back();
return true;
}
@ -2605,7 +2656,7 @@ static bool EvaluateFunction(Function *F, Constant *&RetVal,
PHINode *PN = 0;
for (CurInst = NextBB->begin();
(PN = dyn_cast<PHINode>(CurInst)); ++CurInst)
Values[PN] = getVal(Values, PN->getIncomingValueForBlock(CurBB));
setVal(PN, getVal(PN->getIncomingValueForBlock(CurBB)));
// Advance to the next block.
CurBB = NextBB;
@ -2616,63 +2667,27 @@ static bool EvaluateFunction(Function *F, Constant *&RetVal,
/// we can. Return true if we can, false otherwise.
static bool EvaluateStaticConstructor(Function *F, const TargetData *TD,
const TargetLibraryInfo *TLI) {
// 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.
std::vector<GlobalVariable*> AllocaTmps;
// 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;
// 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;
// Invariants - These global variables have been marked invariant by the
// static constructor.
SmallPtrSet<GlobalVariable*, 8> Invariants;
// Call the function.
Evaluate Eval(TD, TLI);
Constant *RetValDummy;
bool EvalSuccess = EvaluateFunction(F, RetValDummy,
SmallVector<Constant*, 0>(), CallStack,
MutatedMemory, AllocaTmps,
SimpleConstants, Invariants, TD, TLI);
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);
for (SmallPtrSet<GlobalVariable*, 8>::iterator I = Invariants.begin(),
E = Invariants.end(); I != E; ++I)
for (SmallPtrSet<GlobalVariable*, 8>::const_iterator I =
Eval.getInvariants().begin(), E = Eval.getInvariants().end();
I != E; ++I)
(*I)->setConstant(true);
}
// 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;
}
return EvalSuccess;
}