[llvm] r339399 - ValueTracking: Start enhancing isKnownNeverNaN

Matt Arsenault via llvm-commits llvm-commits at lists.llvm.org
Thu Aug 9 15:40:08 PDT 2018


Author: arsenm
Date: Thu Aug  9 15:40:08 2018
New Revision: 339399

URL: http://llvm.org/viewvc/llvm-project?rev=339399&view=rev
Log:
ValueTracking: Start enhancing isKnownNeverNaN

Added:
    llvm/trunk/test/Transforms/InstCombine/known-never-nan.ll
Modified:
    llvm/trunk/include/llvm/Analysis/ValueTracking.h
    llvm/trunk/lib/Analysis/InstructionSimplify.cpp
    llvm/trunk/lib/Analysis/ValueTracking.cpp
    llvm/trunk/lib/Transforms/InstCombine/InstCombineCompares.cpp

Modified: llvm/trunk/include/llvm/Analysis/ValueTracking.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Analysis/ValueTracking.h?rev=339399&r1=339398&r2=339399&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Analysis/ValueTracking.h (original)
+++ llvm/trunk/include/llvm/Analysis/ValueTracking.h Thu Aug  9 15:40:08 2018
@@ -194,7 +194,8 @@ class Value;
   /// Return true if the floating-point scalar value is not a NaN or if the
   /// floating-point vector value has no NaN elements. Return false if a value
   /// could ever be NaN.
-  bool isKnownNeverNaN(const Value *V);
+  bool isKnownNeverNaN(const Value *V, const TargetLibraryInfo *TLI,
+                       unsigned Depth = 0);
 
   /// Return true if we can prove that the specified FP value's sign bit is 0.
   ///

Modified: llvm/trunk/lib/Analysis/InstructionSimplify.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/InstructionSimplify.cpp?rev=339399&r1=339398&r2=339399&view=diff
==============================================================================
--- llvm/trunk/lib/Analysis/InstructionSimplify.cpp (original)
+++ llvm/trunk/lib/Analysis/InstructionSimplify.cpp Thu Aug  9 15:40:08 2018
@@ -1694,7 +1694,8 @@ static Value *simplifyOrOfICmps(ICmpInst
   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 @@ static Value *simplifyAndOrOfFCmps(FCmpI
     // (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 @@ static Value *simplifyAndOrOfFCmps(FCmpI
     // (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 @@ static Value *simplifyAndOrOfCmps(Value
   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 @@ static Value *SimplifyAndInst(Value *Op0
       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 @@ static Value *SimplifyOrInst(Value *Op0,
        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.

Modified: llvm/trunk/lib/Analysis/ValueTracking.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/ValueTracking.cpp?rev=339399&r1=339398&r2=339399&view=diff
==============================================================================
--- llvm/trunk/lib/Analysis/ValueTracking.cpp (original)
+++ llvm/trunk/lib/Analysis/ValueTracking.cpp Thu Aug  9 15:40:08 2018
@@ -2841,10 +2841,10 @@ static bool cannotBeOrderedLessThanZeroI
     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 @@ bool llvm::SignBitMustBeZero(const Value
   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 @@ bool llvm::isKnownNeverNaN(const Value *
   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;

Modified: llvm/trunk/lib/Transforms/InstCombine/InstCombineCompares.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/InstCombine/InstCombineCompares.cpp?rev=339399&r1=339398&r2=339399&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/InstCombine/InstCombineCompares.cpp (original)
+++ llvm/trunk/lib/Transforms/InstCombine/InstCombineCompares.cpp Thu Aug  9 15:40:08 2018
@@ -5153,11 +5153,11 @@ Instruction *InstCombiner::visitFCmpInst
   // 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_PosZeroFP()) && isKnownNeverNaN(Op0)) {
+    if (!match(Op0, m_PosZeroFP()) && isKnownNeverNaN(Op0, &TLI)) {
       I.setOperand(0, ConstantFP::getNullValue(Op0->getType()));
       return &I;
     }
-    if (!match(Op1, m_PosZeroFP()) && isKnownNeverNaN(Op1)) {
+    if (!match(Op1, m_PosZeroFP()) && isKnownNeverNaN(Op1, &TLI)) {
       I.setOperand(1, ConstantFP::getNullValue(Op0->getType()));
       return &I;
     }

Added: llvm/trunk/test/Transforms/InstCombine/known-never-nan.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/known-never-nan.ll?rev=339399&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/InstCombine/known-never-nan.ll (added)
+++ llvm/trunk/test/Transforms/InstCombine/known-never-nan.ll Thu Aug  9 15:40:08 2018
@@ -0,0 +1,61 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt -S -instcombine %s | FileCheck %s
+
+define i1 @nnan_fabs_src(double %arg) {
+; CHECK-LABEL: @nnan_fabs_src(
+; CHECK-NEXT:    ret i1 true
+;
+  %nnan = fadd nnan double %arg, 1.0
+  %op = call double @llvm.fabs.f64(double %nnan)
+  %tmp = fcmp ord double %op, %op
+  ret i1 %tmp
+}
+
+define i1 @nnan_opicalize_src(double %arg) {
+; CHECK-LABEL: @nnan_opicalize_src(
+; CHECK-NEXT:    ret i1 true
+;
+  %nnan = fadd nnan double %arg, 1.0
+  %op = call double @llvm.canonicalize.f64(double %nnan)
+  %tmp = fcmp ord double %op, %op
+  ret i1 %tmp
+}
+
+define i1 @nnan_copysign_src(double %arg0, double %arg1) {
+; CHECK-LABEL: @nnan_copysign_src(
+; CHECK-NEXT:    ret i1 true
+;
+  %nnan = fadd nnan double %arg0, 1.0
+  %op = call double @llvm.copysign.f64(double %nnan, double %arg1)
+  %tmp = fcmp ord double %op, %op
+  ret i1 %tmp
+}
+
+define i1 @fabs_sqrt_src(double %arg0, double %arg1) {
+; CHECK-LABEL: @fabs_sqrt_src(
+; CHECK-NEXT:    ret i1 true
+;
+  %nnan = fadd nnan double %arg0, 1.0
+  %fabs = call double @llvm.fabs.f64(double %nnan)
+  %op = call double @llvm.sqrt.f64(double %fabs)
+  %tmp = fcmp ord double %op, %op
+  ret i1 %tmp
+}
+
+define i1 @fabs_sqrt_src_maybe_nan(double %arg0, double %arg1) {
+; CHECK-LABEL: @fabs_sqrt_src_maybe_nan(
+; CHECK-NEXT:    [[FABS:%.*]] = call double @llvm.fabs.f64(double [[ARG0:%.*]])
+; CHECK-NEXT:    [[OP:%.*]] = call double @llvm.sqrt.f64(double [[FABS]])
+; CHECK-NEXT:    [[TMP:%.*]] = fcmp ord double [[OP]], 0.000000e+00
+; CHECK-NEXT:    ret i1 [[TMP]]
+;
+  %fabs = call double @llvm.fabs.f64(double %arg0)
+  %op = call double @llvm.sqrt.f64(double %fabs)
+  %tmp = fcmp ord double %op, %op
+  ret i1 %tmp
+}
+
+declare double @llvm.sqrt.f64(double)
+declare double @llvm.fabs.f64(double)
+declare double @llvm.canonicalize.f64(double)
+declare double @llvm.copysign.f64(double, double)




More information about the llvm-commits mailing list