aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Analysis/ValueTracking.cpp
diff options
context:
space:
mode:
authorSanjay Patel <spatel@rotateright.com>2020-07-14 07:42:43 -0400
committerSanjay Patel <spatel@rotateright.com>2020-07-14 08:08:09 -0400
commit34d35d4a42dc747345cea4a8b7066371a70cf7a8 (patch)
tree84e9259a9fbd0af6aa19c244e9741242ac09e5b3 /llvm/lib/Analysis/ValueTracking.cpp
parent9cc669d22d8641e9d359d871ac7761a121c9caf0 (diff)
downloadllvm-34d35d4a42dc747345cea4a8b7066371a70cf7a8.zip
llvm-34d35d4a42dc747345cea4a8b7066371a70cf7a8.tar.gz
llvm-34d35d4a42dc747345cea4a8b7066371a70cf7a8.tar.bz2
[ValueTracking] fix miscompile in maxnum case of cannotBeOrderedLessThanZeroImpl (PR46627)
A miscompile with -0.0 is shown in: http://bugs.llvm.org/PR46627 This is because maxnum(-0.0, +0.0) does not specify a fixed result: http://llvm.org/docs/LangRef.html#llvm-maxnum-intrinsic So we need to tighten the constraints for when it is ok to say the result of maxnum is positive (including +0.0). Differential Revision: https://reviews.llvm.org/D83601
Diffstat (limited to 'llvm/lib/Analysis/ValueTracking.cpp')
-rw-r--r--llvm/lib/Analysis/ValueTracking.cpp29
1 files changed, 22 insertions, 7 deletions
diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index 614c8bb..ffa2037 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -3368,13 +3368,28 @@ static bool cannotBeOrderedLessThanZeroImpl(const Value *V,
switch (IID) {
default:
break;
- case Intrinsic::maxnum:
- return (isKnownNeverNaN(I->getOperand(0), TLI) &&
- cannotBeOrderedLessThanZeroImpl(I->getOperand(0), TLI,
- SignBitOnly, Depth + 1)) ||
- (isKnownNeverNaN(I->getOperand(1), TLI) &&
- cannotBeOrderedLessThanZeroImpl(I->getOperand(1), TLI,
- SignBitOnly, Depth + 1));
+ case Intrinsic::maxnum: {
+ Value *V0 = I->getOperand(0), *V1 = I->getOperand(1);
+ auto isPositiveNum = [&](Value *V) {
+ if (SignBitOnly) {
+ // With SignBitOnly, this is tricky because the result of
+ // maxnum(+0.0, -0.0) is unspecified. Just check if the operand is
+ // a constant strictly greater than 0.0.
+ const APFloat *C;
+ return match(V, m_APFloat(C)) &&
+ *C > APFloat::getZero(C->getSemantics());
+ }
+
+ // -0.0 compares equal to 0.0, so if this operand is at least -0.0,
+ // maxnum can't be ordered-less-than-zero.
+ return isKnownNeverNaN(V, TLI) &&
+ cannotBeOrderedLessThanZeroImpl(V, TLI, false, Depth + 1);
+ };
+
+ // TODO: This could be improved. We could also check that neither operand
+ // has its sign bit set (and at least 1 is not-NAN?).
+ return isPositiveNum(V0) || isPositiveNum(V1);
+ }
case Intrinsic::maximum:
return cannotBeOrderedLessThanZeroImpl(I->getOperand(0), TLI, SignBitOnly,