diff options
author | Sanjay Patel <spatel@rotateright.com> | 2020-07-14 07:42:43 -0400 |
---|---|---|
committer | Sanjay Patel <spatel@rotateright.com> | 2020-07-14 08:08:09 -0400 |
commit | 34d35d4a42dc747345cea4a8b7066371a70cf7a8 (patch) | |
tree | 84e9259a9fbd0af6aa19c244e9741242ac09e5b3 /llvm/lib/Analysis/ValueTracking.cpp | |
parent | 9cc669d22d8641e9d359d871ac7761a121c9caf0 (diff) | |
download | llvm-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.cpp | 29 |
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, |