ValueTracking: Start enhancing isKnownNeverNaN
llvm-svn: 339399
diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp
index 9d317b4..a64409b 100644
--- a/llvm/lib/Analysis/InstructionSimplify.cpp
+++ b/llvm/lib/Analysis/InstructionSimplify.cpp
@@ -1694,7 +1694,8 @@
return nullptr;
}
-static Value *simplifyAndOrOfFCmps(FCmpInst *LHS, FCmpInst *RHS, bool IsAnd) {
+static Value *simplifyAndOrOfFCmps(const TargetLibraryInfo *TLI,
+ FCmpInst *LHS, FCmpInst *RHS, bool IsAnd) {
Value *LHS0 = LHS->getOperand(0), *LHS1 = LHS->getOperand(1);
Value *RHS0 = RHS->getOperand(0), *RHS1 = RHS->getOperand(1);
if (LHS0->getType() != RHS0->getType())
@@ -1711,8 +1712,8 @@
// (fcmp uno NNAN, X) | (fcmp uno Y, X) --> fcmp uno Y, X
// (fcmp uno X, NNAN) | (fcmp uno X, Y) --> fcmp uno X, Y
// (fcmp uno X, NNAN) | (fcmp uno Y, X) --> fcmp uno Y, X
- if ((isKnownNeverNaN(LHS0) && (LHS1 == RHS0 || LHS1 == RHS1)) ||
- (isKnownNeverNaN(LHS1) && (LHS0 == RHS0 || LHS0 == RHS1)))
+ if ((isKnownNeverNaN(LHS0, TLI) && (LHS1 == RHS0 || LHS1 == RHS1)) ||
+ (isKnownNeverNaN(LHS1, TLI) && (LHS0 == RHS0 || LHS0 == RHS1)))
return RHS;
// (fcmp ord X, Y) & (fcmp ord NNAN, X) --> fcmp ord X, Y
@@ -1723,15 +1724,16 @@
// (fcmp uno Y, X) | (fcmp uno NNAN, X) --> fcmp uno Y, X
// (fcmp uno X, Y) | (fcmp uno X, NNAN) --> fcmp uno X, Y
// (fcmp uno Y, X) | (fcmp uno X, NNAN) --> fcmp uno Y, X
- if ((isKnownNeverNaN(RHS0) && (RHS1 == LHS0 || RHS1 == LHS1)) ||
- (isKnownNeverNaN(RHS1) && (RHS0 == LHS0 || RHS0 == LHS1)))
+ if ((isKnownNeverNaN(RHS0, TLI) && (RHS1 == LHS0 || RHS1 == LHS1)) ||
+ (isKnownNeverNaN(RHS1, TLI) && (RHS0 == LHS0 || RHS0 == LHS1)))
return LHS;
}
return nullptr;
}
-static Value *simplifyAndOrOfCmps(Value *Op0, Value *Op1, bool IsAnd) {
+static Value *simplifyAndOrOfCmps(const TargetLibraryInfo *TLI,
+ Value *Op0, Value *Op1, bool IsAnd) {
// Look through casts of the 'and' operands to find compares.
auto *Cast0 = dyn_cast<CastInst>(Op0);
auto *Cast1 = dyn_cast<CastInst>(Op1);
@@ -1751,7 +1753,7 @@
auto *FCmp0 = dyn_cast<FCmpInst>(Op0);
auto *FCmp1 = dyn_cast<FCmpInst>(Op1);
if (FCmp0 && FCmp1)
- V = simplifyAndOrOfFCmps(FCmp0, FCmp1, IsAnd);
+ V = simplifyAndOrOfFCmps(TLI, FCmp0, FCmp1, IsAnd);
if (!V)
return nullptr;
@@ -1831,7 +1833,7 @@
return Op1;
}
- if (Value *V = simplifyAndOrOfCmps(Op0, Op1, true))
+ if (Value *V = simplifyAndOrOfCmps(Q.TLI, Op0, Op1, true))
return V;
// Try some generic simplifications for associative operations.
@@ -1981,7 +1983,7 @@
match(Op0, m_c_Xor(m_Not(m_Specific(A)), m_Specific(B)))))
return Op0;
- if (Value *V = simplifyAndOrOfCmps(Op0, Op1, false))
+ if (Value *V = simplifyAndOrOfCmps(Q.TLI, Op0, Op1, false))
return V;
// Try some generic simplifications for associative operations.
diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index 2aac19a..2484cec 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -2841,10 +2841,10 @@
default:
break;
case Intrinsic::maxnum:
- return (isKnownNeverNaN(I->getOperand(0)) &&
+ return (isKnownNeverNaN(I->getOperand(0), TLI) &&
cannotBeOrderedLessThanZeroImpl(I->getOperand(0), TLI,
SignBitOnly, Depth + 1)) ||
- (isKnownNeverNaN(I->getOperand(1)) &&
+ (isKnownNeverNaN(I->getOperand(1), TLI) &&
cannotBeOrderedLessThanZeroImpl(I->getOperand(1), TLI,
SignBitOnly, Depth + 1));
@@ -2909,7 +2909,8 @@
return cannotBeOrderedLessThanZeroImpl(V, TLI, true, 0);
}
-bool llvm::isKnownNeverNaN(const Value *V) {
+bool llvm::isKnownNeverNaN(const Value *V, const TargetLibraryInfo *TLI,
+ unsigned Depth) {
assert(V->getType()->isFPOrFPVectorTy() && "Querying for NaN on non-FP type");
// If we're told that NaNs won't happen, assume they won't.
@@ -2924,6 +2925,23 @@
if (auto *CFP = dyn_cast<ConstantFP>(V))
return !CFP->isNaN();
+ if (Depth == MaxDepth)
+ return false;
+
+ if (const auto *II = dyn_cast<IntrinsicInst>(V)) {
+ switch (II->getIntrinsicID()) {
+ case Intrinsic::canonicalize:
+ case Intrinsic::fabs:
+ case Intrinsic::copysign:
+ return isKnownNeverNaN(II->getArgOperand(0), TLI, Depth + 1);
+ case Intrinsic::sqrt:
+ return isKnownNeverNaN(II->getArgOperand(0), TLI, Depth + 1) &&
+ CannotBeOrderedLessThanZero(II->getArgOperand(0), TLI);
+ default:
+ return false;
+ }
+ }
+
// Bail out for constant expressions, but try to handle vector constants.
if (!V->getType()->isVectorTy() || !isa<Constant>(V))
return false;