summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Analysis/ValueTracking.cpp
diff options
context:
space:
mode:
authorBenjamin Kramer <benny.kra@googlemail.com>2019-11-19 19:12:45 +0100
committerBenjamin Kramer <benny.kra@googlemail.com>2019-11-19 22:24:46 +0100
commitcd4811360e2a1d23578073c6c99b2ef8ba276289 (patch)
tree5a1f909781e239bf17b9d09f0d2e872be28941d0 /llvm/lib/Analysis/ValueTracking.cpp
parent8c48405069085a2c8b6b80816eda99e5dad31fc1 (diff)
downloadbcm5719-llvm-cd4811360e2a1d23578073c6c99b2ef8ba276289.tar.gz
bcm5719-llvm-cd4811360e2a1d23578073c6c99b2ef8ba276289.zip
[ValueTracking] Add a basic version of isKnownNonInfinity and use it to detect more NoNaNs
Diffstat (limited to 'llvm/lib/Analysis/ValueTracking.cpp')
-rw-r--r--llvm/lib/Analysis/ValueTracking.cpp73
1 files changed, 69 insertions, 4 deletions
diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index f03a4a6eee4..51d92cca214 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -3095,6 +3095,58 @@ bool llvm::SignBitMustBeZero(const Value *V, const TargetLibraryInfo *TLI) {
return cannotBeOrderedLessThanZeroImpl(V, TLI, true, 0);
}
+bool llvm::isKnownNeverInfinity(const Value *V, const TargetLibraryInfo *TLI,
+ unsigned Depth) {
+ assert(V->getType()->isFPOrFPVectorTy() && "Querying for Inf on non-FP type");
+
+ // If we're told that infinities won't happen, assume they won't.
+ if (auto *FPMathOp = dyn_cast<FPMathOperator>(V))
+ if (FPMathOp->hasNoInfs())
+ return true;
+
+ // Handle scalar constants.
+ if (auto *CFP = dyn_cast<ConstantFP>(V))
+ return !CFP->isInfinity();
+
+ if (Depth == MaxDepth)
+ return false;
+
+ if (auto *Inst = dyn_cast<Instruction>(V)) {
+ switch (Inst->getOpcode()) {
+ case Instruction::Select: {
+ return isKnownNeverInfinity(Inst->getOperand(1), TLI, Depth + 1) &&
+ isKnownNeverInfinity(Inst->getOperand(2), TLI, Depth + 1);
+ }
+ case Instruction::UIToFP:
+ // If the input type fits into the floating type the result is finite.
+ return ilogb(APFloat::getLargest(
+ Inst->getType()->getScalarType()->getFltSemantics())) >=
+ (int)Inst->getOperand(0)->getType()->getScalarSizeInBits();
+ default:
+ break;
+ }
+ }
+
+ // Bail out for constant expressions, but try to handle vector constants.
+ if (!V->getType()->isVectorTy() || !isa<Constant>(V))
+ return false;
+
+ // For vectors, verify that each element is not infinity.
+ unsigned NumElts = V->getType()->getVectorNumElements();
+ for (unsigned i = 0; i != NumElts; ++i) {
+ Constant *Elt = cast<Constant>(V)->getAggregateElement(i);
+ if (!Elt)
+ return false;
+ if (isa<UndefValue>(Elt))
+ continue;
+ auto *CElt = dyn_cast<ConstantFP>(Elt);
+ if (!CElt || CElt->isInfinity())
+ return false;
+ }
+ // All elements were confirmed non-infinity or undefined.
+ return true;
+}
+
bool llvm::isKnownNeverNaN(const Value *V, const TargetLibraryInfo *TLI,
unsigned Depth) {
assert(V->getType()->isFPOrFPVectorTy() && "Querying for NaN on non-FP type");
@@ -3114,13 +3166,26 @@ bool llvm::isKnownNeverNaN(const Value *V, const TargetLibraryInfo *TLI,
if (auto *Inst = dyn_cast<Instruction>(V)) {
switch (Inst->getOpcode()) {
case Instruction::FAdd:
- case Instruction::FMul:
case Instruction::FSub:
+ // Adding positive and negative infinity produces NaN.
+ return isKnownNeverNaN(Inst->getOperand(0), TLI, Depth + 1) &&
+ isKnownNeverNaN(Inst->getOperand(1), TLI, Depth + 1) &&
+ (isKnownNeverInfinity(Inst->getOperand(0), TLI, Depth + 1) ||
+ isKnownNeverInfinity(Inst->getOperand(1), TLI, Depth + 1));
+
+ case Instruction::FMul:
+ // Zero multiplied with infinity produces NaN.
+ // FIXME: If neither side can be zero fmul never produces NaN.
+ return isKnownNeverNaN(Inst->getOperand(0), TLI, Depth + 1) &&
+ isKnownNeverInfinity(Inst->getOperand(0), TLI, Depth + 1) &&
+ isKnownNeverNaN(Inst->getOperand(1), TLI, Depth + 1) &&
+ isKnownNeverInfinity(Inst->getOperand(1), TLI, Depth + 1);
+
case Instruction::FDiv:
- case Instruction::FRem: {
- // TODO: Need isKnownNeverInfinity
+ case Instruction::FRem:
+ // FIXME: Only 0/0, Inf/Inf, Inf REM x and x REM 0 produce NaN.
return false;
- }
+
case Instruction::Select: {
return isKnownNeverNaN(Inst->getOperand(1), TLI, Depth + 1) &&
isKnownNeverNaN(Inst->getOperand(2), TLI, Depth + 1);
OpenPOWER on IntegriCloud