aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Analysis/ValueTracking.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Analysis/ValueTracking.cpp')
-rw-r--r--llvm/lib/Analysis/ValueTracking.cpp35
1 files changed, 29 insertions, 6 deletions
diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index 278bdd0..5931032 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -4741,14 +4741,30 @@ void computeKnownFPClass(const Value *V, const APInt &DemandedElts,
case Instruction::FAdd:
case Instruction::FSub: {
KnownFPClass KnownLHS, KnownRHS;
- computeKnownFPClass(Op->getOperand(1), DemandedElts, fcNan | fcInf,
+ bool WantNegative =
+ Op->getOpcode() == Instruction::FAdd &&
+ (InterestedClasses & KnownFPClass::OrderedLessThanZeroMask) != fcNone;
+ bool WantNaN = (InterestedClasses & fcNan) != fcNone;
+ bool WantNegZero = (InterestedClasses & fcNegZero) != fcNone;
+
+ if (!WantNaN && !WantNegative && !WantNegZero)
+ break;
+
+ FPClassTest InterestedSrcs = InterestedClasses;
+ if (WantNegative)
+ InterestedSrcs |= KnownFPClass::OrderedLessThanZeroMask;
+ if (InterestedClasses & fcNan)
+ InterestedSrcs |= fcInf;
+ computeKnownFPClass(Op->getOperand(1), DemandedElts, InterestedSrcs,
KnownRHS, Depth + 1, Q);
- if (KnownRHS.isKnownNeverNaN() || KnownRHS.isKnownNeverNegZero() ||
- (Opc == Instruction::FSub && KnownRHS.isKnownNeverPosZero())) {
+ if ((WantNaN && KnownRHS.isKnownNeverNaN()) ||
+ (WantNegative && KnownRHS.cannotBeOrderedLessThanZero()) ||
+ WantNegZero || Opc == Instruction::FSub) {
+
// RHS is canonically cheaper to compute. Skip inspecting the LHS if
// there's no point.
- computeKnownFPClass(Op->getOperand(0), DemandedElts, fcNan | fcInf,
+ computeKnownFPClass(Op->getOperand(0), DemandedElts, InterestedSrcs,
KnownLHS, Depth + 1, Q);
// Adding positive and negative infinity produces NaN.
// TODO: Check sign of infinities.
@@ -4758,10 +4774,14 @@ void computeKnownFPClass(const Value *V, const APInt &DemandedElts,
// FIXME: Context function should always be passed in separately
const Function *F = cast<Instruction>(Op)->getFunction();
- if (!F)
- break;
if (Op->getOpcode() == Instruction::FAdd) {
+ if (KnownLHS.cannotBeOrderedLessThanZero() &&
+ KnownRHS.cannotBeOrderedLessThanZero())
+ Known.knownNot(KnownFPClass::OrderedLessThanZeroMask);
+ if (!F)
+ break;
+
// (fadd x, 0.0) is guaranteed to return +0.0, not -0.0.
if ((KnownLHS.isKnownNeverLogicalNegZero(*F, Op->getType()) ||
KnownRHS.isKnownNeverLogicalNegZero(*F, Op->getType())) &&
@@ -4769,6 +4789,9 @@ void computeKnownFPClass(const Value *V, const APInt &DemandedElts,
outputDenormalIsIEEEOrPosZero(*F, Op->getType()))
Known.knownNot(fcNegZero);
} else {
+ if (!F)
+ break;
+
// Only fsub -0, +0 can return -0
if ((KnownLHS.isKnownNeverLogicalNegZero(*F, Op->getType()) ||
KnownRHS.isKnownNeverLogicalPosZero(*F, Op->getType())) &&