diff options
author | Juneyoung Lee <aqjune@gmail.com> | 2020-04-14 10:28:45 +0900 |
---|---|---|
committer | Juneyoung Lee <aqjune@gmail.com> | 2020-04-15 05:58:06 +0900 |
commit | 994543abc9bf7bbb94a2deea31323031fb9ff58d (patch) | |
tree | 8257d7164aab35c8e1c7cb99b59918e0f2fab7d6 /llvm/lib/Analysis/ValueTracking.cpp | |
parent | 6474d1b20ea74982f9446a11b367a5936b6bbbdd (diff) | |
download | llvm-994543abc9bf7bbb94a2deea31323031fb9ff58d.zip llvm-994543abc9bf7bbb94a2deea31323031fb9ff58d.tar.gz llvm-994543abc9bf7bbb94a2deea31323031fb9ff58d.tar.bz2 |
[ValueTracking] Implement canCreatePoison
Summary:
This PR adds `canCreatePoison(Instruction *I)` which returns true if `I` can generate poison from non-poison
operands.
Reviewers: spatel, nikic, lebedev.ri
Reviewed By: spatel
Subscribers: hiraditya, llvm-commits, regehr, nlopes
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D77890
Diffstat (limited to 'llvm/lib/Analysis/ValueTracking.cpp')
-rw-r--r-- | llvm/lib/Analysis/ValueTracking.cpp | 85 |
1 files changed, 85 insertions, 0 deletions
diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp index 58b15f4..f80ec73 100644 --- a/llvm/lib/Analysis/ValueTracking.cpp +++ b/llvm/lib/Analysis/ValueTracking.cpp @@ -4592,6 +4592,91 @@ bool llvm::isOverflowIntrinsicNoWrap(const WithOverflowInst *WO, return llvm::any_of(GuardingBranches, AllUsesGuardedByBranch); } +bool llvm::canCreatePoison(const Instruction *I) { + // See whether I has flags that may create poison + if (isa<OverflowingBinaryOperator>(I) && + (I->hasNoSignedWrap() || I->hasNoUnsignedWrap())) + return true; + if (isa<PossiblyExactOperator>(I) && I->isExact()) + return true; + if (auto *FP = dyn_cast<FPMathOperator>(I)) { + auto FMF = FP->getFastMathFlags(); + if (FMF.noNaNs() || FMF.noInfs()) + return true; + } + if (auto *GEP = dyn_cast<GetElementPtrInst>(I)) + if (GEP->isInBounds()) + return true; + + unsigned Opcode = I->getOpcode(); + + // Check whether opcode is a poison-generating operation + switch (Opcode) { + case Instruction::Shl: + case Instruction::AShr: + case Instruction::LShr: { + // Shifts return poison if shiftwidth is larger than the bitwidth. + if (auto *C = dyn_cast<Constant>(I->getOperand(1))) { + SmallVector<Constant *, 4> ShiftAmounts; + if (C->getType()->isVectorTy()) { + unsigned NumElts = cast<VectorType>(C->getType())->getNumElements(); + for (unsigned i = 0; i < NumElts; ++i) + ShiftAmounts.push_back(C->getAggregateElement(i)); + } else + ShiftAmounts.push_back(C); + + bool Safe = llvm::all_of(ShiftAmounts, [](Constant *C) { + auto *CI = dyn_cast<ConstantInt>(C); + return CI && CI->getZExtValue() < C->getType()->getIntegerBitWidth(); + }); + return !Safe; + } + return true; + } + case Instruction::FPToSI: + case Instruction::FPToUI: + // fptosi/ui yields poison if the resulting value does not fit in the + // destination type. + return true; + case Instruction::Call: + case Instruction::CallBr: + case Instruction::Invoke: + // Function calls can return a poison value even if args are non-poison + // values. CallBr returns poison when jumping to indirect labels. + return true; + case Instruction::InsertElement: + case Instruction::ExtractElement: { + // If index exceeds the length of the vector, it returns poison + auto *VTy = cast<VectorType>(I->getOperand(0)->getType()); + unsigned IdxOp = I->getOpcode() == Instruction::InsertElement ? 2 : 1; + auto *Idx = dyn_cast<ConstantInt>(I->getOperand(IdxOp)); + if (!Idx || Idx->getZExtValue() >= VTy->getElementCount().Min) + return true; + return false; + } + case Instruction::FNeg: + case Instruction::PHI: + case Instruction::Select: + case Instruction::URem: + case Instruction::SRem: + case Instruction::ShuffleVector: + case Instruction::ExtractValue: + case Instruction::InsertValue: + case Instruction::Freeze: + case Instruction::ICmp: + case Instruction::FCmp: + case Instruction::GetElementPtr: + return false; + default: + if (isa<CastInst>(I)) + return false; + else if (isa<BinaryOperator>(I)) + return false; + // Be conservative and return true. + return true; + } +} + bool llvm::isGuaranteedNotToBeUndefOrPoison(const Value *V, const Instruction *CtxI, const DominatorTree *DT) { |