summaryrefslogtreecommitdiffstats
path: root/llvm/lib
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib')
-rw-r--r--llvm/lib/Analysis/ValueTracking.cpp35
-rw-r--r--llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp21
-rw-r--r--llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp13
3 files changed, 54 insertions, 15 deletions
diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index a9619746797..f47559b850a 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -2695,6 +2695,41 @@ bool llvm::SignBitMustBeZero(const Value *V, const TargetLibraryInfo *TLI) {
return cannotBeOrderedLessThanZeroImpl(V, TLI, true, 0);
}
+bool llvm::isKnownNeverNaN(const Value *V) {
+ assert(V->getType()->isFPOrFPVectorTy() && "Querying for NaN on non-FP type");
+
+ // If we're told that NaNs won't happen, assume they won't.
+ if (auto *FPMathOp = dyn_cast<FPMathOperator>(V))
+ if (FPMathOp->hasNoNaNs())
+ return true;
+
+ // TODO: Handle instructions and potentially recurse like other 'isKnown'
+ // functions. For example, the result of sitofp is never NaN.
+
+ // Handle scalar constants.
+ if (auto *CFP = dyn_cast<ConstantFP>(V))
+ return !CFP->isNaN();
+
+ // 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 NaN.
+ 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->isNaN())
+ return false;
+ }
+ // All elements were confirmed not-NaN or undefined.
+ return true;
+}
+
/// If the specified value can be set by repeating the same byte in memory,
/// return the i8 value that it is represented with. This is
/// true for all i8 values obviously, but is also true for i32 0, i32 -1,
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
index 006ed418c73..a81f295b91d 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
@@ -938,21 +938,12 @@ Value *InstCombiner::foldLogicOfFCmps(FCmpInst *LHS, FCmpInst *RHS, bool IsAnd)
if (LHS0->getType() != RHS0->getType())
return nullptr;
- auto *LHSC = dyn_cast<ConstantFP>(LHS1);
- auto *RHSC = dyn_cast<ConstantFP>(RHS1);
- if (LHSC && RHSC) {
- assert(!LHSC->getValueAPF().isNaN() && !RHSC->getValueAPF().isNaN() &&
- "Failed to simplify fcmp ord/uno with NAN operand");
- // Ignore the constants because they can't be NANs:
- // (fcmp ord x, c) & (fcmp ord y, c) -> (fcmp ord x, y)
- // (fcmp uno x, c) & (fcmp uno y, c) -> (fcmp uno x, y)
- return Builder.CreateFCmp(PredL, LHS0, RHS0);
- }
-
- // Handle vector zeros. This occurs because the canonical form of
- // "fcmp ord/uno x,x" is "fcmp ord/uno x, 0".
- if (isa<ConstantAggregateZero>(LHS1) &&
- isa<ConstantAggregateZero>(RHS1))
+ // FCmp canonicalization ensures that (fcmp ord/uno X, X) and
+ // (fcmp ord/uno X, C) will be transformed to (fcmp X, 0.0).
+ if (match(LHS1, m_Zero()) && LHS1 == RHS1)
+ // Ignore the constants because they are obviously not NANs:
+ // (fcmp ord x, 0.0) & (fcmp ord y, 0.0) -> (fcmp ord x, y)
+ // (fcmp uno x, 0.0) | (fcmp uno y, 0.0) -> (fcmp uno x, y)
return Builder.CreateFCmp(PredL, LHS0, RHS0);
}
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
index c2de45a3699..240a9c41b5f 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
@@ -4963,6 +4963,19 @@ Instruction *InstCombiner::visitFCmpInst(FCmpInst &I) {
}
}
+ // If we're just checking for a NaN (ORD/UNO) and have a non-NaN operand,
+ // then canonicalize the operand to 0.0.
+ if (Pred == CmpInst::FCMP_ORD || Pred == CmpInst::FCMP_UNO) {
+ if (!match(Op0, m_Zero()) && isKnownNeverNaN(Op0)) {
+ I.setOperand(0, ConstantFP::getNullValue(Op0->getType()));
+ return &I;
+ }
+ if (!match(Op1, m_Zero()) && isKnownNeverNaN(Op1)) {
+ I.setOperand(1, ConstantFP::getNullValue(Op0->getType()));
+ return &I;
+ }
+ }
+
// Test if the FCmpInst instruction is used exclusively by a select as
// part of a minimum or maximum operation. If so, refrain from doing
// any other folding. This helps out other analyses which understand
OpenPOWER on IntegriCloud