summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Transforms/Utils/Evaluator.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Transforms/Utils/Evaluator.cpp')
-rw-r--r--llvm/lib/Transforms/Utils/Evaluator.cpp103
1 files changed, 65 insertions, 38 deletions
diff --git a/llvm/lib/Transforms/Utils/Evaluator.cpp b/llvm/lib/Transforms/Utils/Evaluator.cpp
index fb8cb3ddea6..0e203f4e075 100644
--- a/llvm/lib/Transforms/Utils/Evaluator.cpp
+++ b/llvm/lib/Transforms/Utils/Evaluator.cpp
@@ -174,6 +174,34 @@ static bool isSimpleEnoughPointerToCommit(Constant *C) {
return false;
}
+/// Apply 'Func' to Ptr. If this returns nullptr, introspect the pointer's
+/// type and walk down through the initial elements to obtain additional
+/// pointers to try. Returns the first non-null return value from Func, or
+/// nullptr if the type can't be introspected further.
+static Constant *
+evaluateBitcastFromPtr(Constant *Ptr, const DataLayout &DL,
+ const TargetLibraryInfo *TLI,
+ std::function<Constant *(Constant *)> Func) {
+ Constant *Val;
+ while (!(Val = Func(Ptr))) {
+ // If Ty is a struct, we can convert the pointer to the struct
+ // into a pointer to its first member.
+ // FIXME: This could be extended to support arrays as well.
+ Type *Ty = cast<PointerType>(Ptr->getType())->getElementType();
+ if (!isa<StructType>(Ty))
+ break;
+
+ IntegerType *IdxTy = IntegerType::get(Ty->getContext(), 32);
+ Constant *IdxZero = ConstantInt::get(IdxTy, 0, false);
+ Constant *const IdxList[] = {IdxZero, IdxZero};
+
+ Ptr = ConstantExpr::getGetElementPtr(Ty, Ptr, IdxList);
+ if (auto *FoldedPtr = ConstantFoldConstant(Ptr, DL, TLI))
+ Ptr = FoldedPtr;
+ }
+ return Val;
+}
+
static Constant *getInitializer(Constant *C) {
auto *GV = dyn_cast<GlobalVariable>(C);
return GV && GV->hasDefinitiveInitializer() ? GV->getInitializer() : nullptr;
@@ -184,8 +212,14 @@ static Constant *getInitializer(Constant *C) {
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 = MutatedMemory.find(P);
- if (I != MutatedMemory.end()) return I->second;
+ auto findMemLoc = [this](Constant *Ptr) {
+ DenseMap<Constant *, Constant *>::const_iterator I =
+ MutatedMemory.find(Ptr);
+ return I != MutatedMemory.end() ? I->second : nullptr;
+ };
+
+ if (Constant *Val = findMemLoc(P))
+ return Val;
// Access it.
if (GlobalVariable *GV = dyn_cast<GlobalVariable>(P)) {
@@ -203,13 +237,17 @@ Constant *Evaluator::ComputeLoadResult(Constant *P) {
break;
// Handle a constantexpr bitcast.
case Instruction::BitCast:
- Constant *Val = getVal(CE->getOperand(0));
- auto MM = MutatedMemory.find(Val);
- auto *I = (MM != MutatedMemory.end()) ? MM->second
- : getInitializer(CE->getOperand(0));
- if (I)
+ // We're evaluating a load through a pointer that was bitcast to a
+ // different type. See if the "from" pointer has recently been stored.
+ // If it hasn't, we may still be able to find a stored pointer by
+ // introspecting the type.
+ Constant *Val =
+ evaluateBitcastFromPtr(CE->getOperand(0), DL, TLI, findMemLoc);
+ if (!Val)
+ Val = getInitializer(CE->getOperand(0));
+ if (Val)
return ConstantFoldLoadThroughBitcast(
- I, P->getType()->getPointerElementType(), DL);
+ Val, P->getType()->getPointerElementType(), DL);
break;
}
}
@@ -329,37 +367,26 @@ bool Evaluator::EvaluateBlock(BasicBlock::iterator CurInst,
<< "Attempting to resolve bitcast on constant ptr.\n");
// If we're evaluating a store through a bitcast, then we need
// to pull the bitcast off the pointer type and push it onto the
- // stored value.
- Ptr = CE->getOperand(0);
-
- 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
- // introspecting NewTy to find a legal conversion.
- Constant *NewVal;
- while (!(NewVal = ConstantFoldLoadThroughBitcast(Val, NewTy, DL))) {
- // If NewTy is a struct, we can convert the pointer to the struct
- // into a pointer to its first member.
- // FIXME: This could be extended to support arrays as well.
- if (StructType *STy = dyn_cast<StructType>(NewTy)) {
-
- IntegerType *IdxTy = IntegerType::get(NewTy->getContext(), 32);
- Constant *IdxZero = ConstantInt::get(IdxTy, 0, false);
- Constant * const IdxList[] = {IdxZero, IdxZero};
-
- Ptr = ConstantExpr::getGetElementPtr(NewTy, Ptr, IdxList);
- if (auto *FoldedPtr = ConstantFoldConstant(Ptr, DL, TLI))
- Ptr = FoldedPtr;
- NewTy = STy->getTypeAtIndex(0U);
-
- // If we can't improve the situation by introspecting NewTy,
- // we have to give up.
- } else {
- LLVM_DEBUG(dbgs() << "Failed to bitcast constant ptr, can not "
- "evaluate.\n");
- return false;
+ // stored value. In order to push the bitcast onto the stored value,
+ // a bitcast from the pointer's element type to Val's type must be
+ // legal. If it's not, we can try introspecting the type to find a
+ // legal conversion.
+
+ auto castValTy = [&](Constant *P) -> Constant * {
+ Type *Ty = cast<PointerType>(P->getType())->getElementType();
+ if (Constant *FV = ConstantFoldLoadThroughBitcast(Val, Ty, DL)) {
+ Ptr = P;
+ return FV;
}
+ return nullptr;
+ };
+
+ Constant *NewVal =
+ evaluateBitcastFromPtr(CE->getOperand(0), DL, TLI, castValTy);
+ if (!NewVal) {
+ LLVM_DEBUG(dbgs() << "Failed to bitcast constant ptr, can not "
+ "evaluate.\n");
+ return false;
}
Val = NewVal;
OpenPOWER on IntegriCloud