diff options
Diffstat (limited to 'llvm/lib/Transforms/Utils/Evaluator.cpp')
-rw-r--r-- | llvm/lib/Transforms/Utils/Evaluator.cpp | 103 |
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; |