[llvm] 294ad08 - Revert "Revert "InstSimplify: Use correct interested FP classes when simplifying fcmp""

Philip Reames via llvm-commits llvm-commits at lists.llvm.org
Fri Sep 1 12:17:54 PDT 2023


Author: Philip Reames
Date: 2023-09-01T12:17:36-07:00
New Revision: 294ad08ecc0085e3ae93bbd16d488f284fe0d8fb

URL: https://github.com/llvm/llvm-project/commit/294ad08ecc0085e3ae93bbd16d488f284fe0d8fb
DIFF: https://github.com/llvm/llvm-project/commit/294ad08ecc0085e3ae93bbd16d488f284fe0d8fb.diff

LOG: Revert "Revert "InstSimplify: Use correct interested FP classes when simplifying fcmp""

This reverts commit 89f0314ee14a4d7f5a92fd63574ba545863df016.  Change does not build.

Added: 
    

Modified: 
    llvm/include/llvm/Analysis/ValueTracking.h
    llvm/lib/Analysis/InstructionSimplify.cpp
    llvm/lib/Analysis/ValueTracking.cpp
    llvm/test/Transforms/Attributor/nofpclass.ll
    llvm/test/Transforms/InstCombine/fcmp.ll
    llvm/test/Transforms/InstCombine/is_fpclass.ll
    llvm/test/Transforms/InstSimplify/floating-point-compare.ll
    llvm/test/Transforms/InstSimplify/known-never-infinity.ll

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/Analysis/ValueTracking.h b/llvm/include/llvm/Analysis/ValueTracking.h
index 3521fa8be3b691d..695f2fecae885b7 100644
--- a/llvm/include/llvm/Analysis/ValueTracking.h
+++ b/llvm/include/llvm/Analysis/ValueTracking.h
@@ -18,6 +18,7 @@
 #include "llvm/ADT/SmallSet.h"
 #include "llvm/IR/Constants.h"
 #include "llvm/IR/DataLayout.h"
+#include "llvm/IR/FMF.h"
 #include "llvm/IR/InstrTypes.h"
 #include "llvm/IR/Intrinsics.h"
 #include <cassert>
@@ -229,6 +230,10 @@ std::pair<Value *, FPClassTest> fcmpToClassTest(CmpInst::Predicate Pred,
                                                 const Function &F, Value *LHS,
                                                 Value *RHS,
                                                 bool LookThroughSrc = true);
+std::pair<Value *, FPClassTest> fcmpToClassTest(CmpInst::Predicate Pred,
+                                                const Function &F, Value *LHS,
+                                                const APFloat *ConstRHS,
+                                                bool LookThroughSrc = true);
 
 struct KnownFPClass {
   /// Floating-point classes the value could be one of.
@@ -471,6 +476,28 @@ KnownFPClass computeKnownFPClass(
     const Instruction *CxtI = nullptr, const DominatorTree *DT = nullptr,
     bool UseInstrInfo = true);
 
+/// Wrapper to account for known fast math flags at the use instruction.
+inline KnownFPClass computeKnownFPClass(
+    const Value *V, FastMathFlags FMF, const DataLayout &DL,
+    FPClassTest InterestedClasses = fcAllFlags, unsigned Depth = 0,
+    const TargetLibraryInfo *TLI = nullptr, AssumptionCache *AC = nullptr,
+    const Instruction *CxtI = nullptr, const DominatorTree *DT = nullptr,
+    bool UseInstrInfo = true) {
+  if (FMF.noNaNs())
+    InterestedClasses &= ~fcNan;
+  if (FMF.noInfs())
+    InterestedClasses &= ~fcInf;
+
+  KnownFPClass Result = computeKnownFPClass(V, DL, InterestedClasses, Depth,
+                                            TLI, AC, CxtI, DT, UseInstrInfo);
+
+  if (FMF.noNaNs())
+    Result.KnownFPClasses &= ~fcNan;
+  if (FMF.noInfs())
+    Result.KnownFPClasses &= ~fcInf;
+  return Result;
+}
+
 /// Return true if we can prove that the specified FP value is never equal to
 /// -0.0. Users should use caution when considering PreserveSign
 /// denormal-fp-math.

diff  --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp
index 600418a5b7debf8..040c2e55d87ceda 100644
--- a/llvm/lib/Analysis/InstructionSimplify.cpp
+++ b/llvm/lib/Analysis/InstructionSimplify.cpp
@@ -4060,19 +4060,6 @@ static Value *simplifyFCmpInst(unsigned Predicate, Value *LHS, Value *RHS,
   if (Pred == FCmpInst::FCMP_TRUE)
     return getTrue(RetTy);
 
-  // Fold (un)ordered comparison if we can determine there are no NaNs.
-  if (Pred == FCmpInst::FCMP_UNO || Pred == FCmpInst::FCMP_ORD)
-    if (FMF.noNaNs() ||
-        (isKnownNeverNaN(LHS, Q.DL, Q.TLI, 0, Q.AC, Q.CxtI, Q.DT) &&
-         isKnownNeverNaN(RHS, Q.DL, Q.TLI, 0, Q.AC, Q.CxtI, Q.DT)))
-      return ConstantInt::get(RetTy, Pred == FCmpInst::FCMP_ORD);
-
-  // NaN is unordered; NaN is not ordered.
-  assert((FCmpInst::isOrdered(Pred) || FCmpInst::isUnordered(Pred)) &&
-         "Comparison must be either ordered or unordered");
-  if (match(RHS, m_NaN()))
-    return ConstantInt::get(RetTy, CmpInst::isUnordered(Pred));
-
   // fcmp pred x, poison and  fcmp pred poison, x
   // fold to poison
   if (isa<PoisonValue>(LHS) || isa<PoisonValue>(RHS))
@@ -4094,80 +4081,86 @@ static Value *simplifyFCmpInst(unsigned Predicate, Value *LHS, Value *RHS,
       return getFalse(RetTy);
   }
 
-  // Handle fcmp with constant RHS.
-  // TODO: Use match with a specific FP value, so these work with vectors with
-  // undef lanes.
-  const APFloat *C;
-  if (match(RHS, m_APFloat(C))) {
-    // Check whether the constant is an infinity.
-    if (C->isInfinity()) {
-      if (C->isNegative()) {
-        switch (Pred) {
-        case FCmpInst::FCMP_OLT:
-          // No value is ordered and less than negative infinity.
-          return getFalse(RetTy);
-        case FCmpInst::FCMP_UGE:
-          // All values are unordered with or at least negative infinity.
-          return getTrue(RetTy);
-        default:
-          break;
-        }
-      } else {
-        switch (Pred) {
-        case FCmpInst::FCMP_OGT:
-          // No value is ordered and greater than infinity.
-          return getFalse(RetTy);
-        case FCmpInst::FCMP_ULE:
-          // All values are unordered with and at most infinity.
-          return getTrue(RetTy);
-        default:
-          break;
-        }
-      }
+  // Fold (un)ordered comparison if we can determine there are no NaNs.
+  //
+  // This catches the 2 variable input case, constants are handled below as a
+  // class-like compare.
+  if (Pred == FCmpInst::FCMP_ORD || Pred == FCmpInst::FCMP_UNO) {
+    if (FMF.noNaNs() ||
+        (isKnownNeverNaN(RHS, Q.DL, Q.TLI, 0, Q.AC, Q.CxtI, Q.DT) &&
+         isKnownNeverNaN(LHS, Q.DL, Q.TLI, 0, Q.AC, Q.CxtI, Q.DT)))
+      return ConstantInt::get(RetTy, Pred == FCmpInst::FCMP_ORD);
+  }
 
-      // LHS == Inf
-      if (Pred == FCmpInst::FCMP_OEQ &&
-          isKnownNeverInfinity(LHS, Q.DL, Q.TLI, 0, Q.AC, Q.CxtI, Q.DT))
-        return getFalse(RetTy);
-      // LHS != Inf
-      if (Pred == FCmpInst::FCMP_UNE &&
-          isKnownNeverInfinity(LHS, Q.DL, Q.TLI, 0, Q.AC, Q.CxtI, Q.DT))
-        return getTrue(RetTy);
-      // LHS == Inf || LHS == NaN
-      if (Pred == FCmpInst::FCMP_UEQ &&
-          isKnownNeverInfOrNaN(LHS, Q.DL, Q.TLI, 0, Q.AC, Q.CxtI, Q.DT))
+  const APFloat *C = nullptr;
+  match(RHS, m_APFloatAllowUndef(C));
+  std::optional<KnownFPClass> FullKnownClassLHS;
+
+  // Lazily compute the possible classes for LHS. Avoid computing it twice if
+  // RHS is a 0.
+  auto computeLHSClass = [=, &FullKnownClassLHS](FPClassTest InterestedFlags =
+                                                     fcAllFlags) {
+    if (FullKnownClassLHS)
+      return *FullKnownClassLHS;
+    return computeKnownFPClass(LHS, FMF, Q.DL, InterestedFlags, 0, Q.TLI, Q.AC,
+                               Q.CxtI, Q.DT, Q.IIQ.UseInstrInfo);
+  };
+
+  if (C && Q.CxtI) {
+    // Fold out compares that express a class test.
+    //
+    // FIXME: Should be able to perform folds without context
+    // instruction. Always pass in the context function?
+
+    const Function *ParentF = Q.CxtI->getFunction();
+    auto [ClassVal, ClassTest] = fcmpToClassTest(Pred, *ParentF, LHS, C);
+    if (ClassVal) {
+      FullKnownClassLHS = computeLHSClass();
+      if ((FullKnownClassLHS->KnownFPClasses & ClassTest) == fcNone)
         return getFalse(RetTy);
-      // LHS != Inf && LHS != NaN
-      if (Pred == FCmpInst::FCMP_ONE &&
-          isKnownNeverInfOrNaN(LHS, Q.DL, Q.TLI, 0, Q.AC, Q.CxtI, Q.DT))
+      if ((FullKnownClassLHS->KnownFPClasses & ~ClassTest) == fcNone)
         return getTrue(RetTy);
     }
+  }
+
+  // Handle fcmp with constant RHS.
+  if (C) {
+    // TODO: Need version fcmpToClassTest which returns implied class when the
+    // compare isn't a complete class test. e.g. > 1.0 implies fcPositive, but
+    // isn't implementable as a class call.
     if (C->isNegative() && !C->isNegZero()) {
+      FPClassTest Interested = KnownFPClass::OrderedLessThanZeroMask;
+
+      // FIXME: This assert won't always hold if we depend on the context
+      // instruction above
       assert(!C->isNaN() && "Unexpected NaN constant!");
       // TODO: We can catch more cases by using a range check rather than
       //       relying on CannotBeOrderedLessThanZero.
       switch (Pred) {
       case FCmpInst::FCMP_UGE:
       case FCmpInst::FCMP_UGT:
-      case FCmpInst::FCMP_UNE:
+      case FCmpInst::FCMP_UNE: {
+        KnownFPClass KnownClass = computeLHSClass(Interested);
+
         // (X >= 0) implies (X > C) when (C < 0)
-        if (cannotBeOrderedLessThanZero(LHS, Q.DL, Q.TLI, 0,
-                                        Q.AC, Q.CxtI, Q.DT))
+        if (KnownClass.cannotBeOrderedLessThanZero())
           return getTrue(RetTy);
         break;
+      }
       case FCmpInst::FCMP_OEQ:
       case FCmpInst::FCMP_OLE:
-      case FCmpInst::FCMP_OLT:
+      case FCmpInst::FCMP_OLT: {
+        KnownFPClass KnownClass = computeLHSClass(Interested);
+
         // (X >= 0) implies !(X < C) when (C < 0)
-        if (cannotBeOrderedLessThanZero(LHS, Q.DL, Q.TLI, 0, Q.AC, Q.CxtI,
-                                        Q.DT))
+        if (KnownClass.cannotBeOrderedLessThanZero())
           return getFalse(RetTy);
         break;
+      }
       default:
         break;
       }
     }
-
     // Check comparison of [minnum/maxnum with constant] with other constant.
     const APFloat *C2;
     if ((match(LHS, m_Intrinsic<Intrinsic::minnum>(m_Value(), m_APFloat(C2))) &&
@@ -4214,13 +4207,17 @@ static Value *simplifyFCmpInst(unsigned Predicate, Value *LHS, Value *RHS,
     }
   }
 
+  // TODO: Could fold this with above if there were a matcher which returned all
+  // classes in a non-splat vector.
   if (match(RHS, m_AnyZeroFP())) {
     switch (Pred) {
     case FCmpInst::FCMP_OGE:
     case FCmpInst::FCMP_ULT: {
-      FPClassTest Interested = FMF.noNaNs() ? fcNegative : fcNegative | fcNan;
-      KnownFPClass Known = computeKnownFPClass(LHS, Q.DL, Interested, 0,
-                                               Q.TLI, Q.AC, Q.CxtI, Q.DT);
+      FPClassTest Interested = KnownFPClass::OrderedLessThanZeroMask;
+      if (!FMF.noNaNs())
+        Interested |= fcNan;
+
+      KnownFPClass Known = computeLHSClass(Interested);
 
       // Positive or zero X >= 0.0 --> true
       // Positive or zero X <  0.0 --> false
@@ -4230,12 +4227,16 @@ static Value *simplifyFCmpInst(unsigned Predicate, Value *LHS, Value *RHS,
       break;
     }
     case FCmpInst::FCMP_UGE:
-    case FCmpInst::FCMP_OLT:
+    case FCmpInst::FCMP_OLT: {
+      FPClassTest Interested = KnownFPClass::OrderedLessThanZeroMask;
+      KnownFPClass Known = computeLHSClass(Interested);
+
       // Positive or zero or nan X >= 0.0 --> true
       // Positive or zero or nan X <  0.0 --> false
-      if (cannotBeOrderedLessThanZero(LHS, Q.DL, Q.TLI, 0, Q.AC, Q.CxtI, Q.DT))
+      if (Known.cannotBeOrderedLessThanZero())
         return Pred == FCmpInst::FCMP_UGE ? getTrue(RetTy) : getFalse(RetTy);
       break;
+    }
     default:
       break;
     }
@@ -6816,6 +6817,9 @@ static Value *simplifyInstructionWithOperands(Instruction *I,
                                               const SimplifyQuery &SQ,
                                               unsigned MaxRecurse) {
   assert(I->getFunction() && "instruction should be inserted in a function");
+  assert((!SQ.CxtI || SQ.CxtI->getFunction() == I->getFunction()) &&
+         "context instruction should be in the same function");
+
   const SimplifyQuery Q = SQ.CxtI ? SQ : SQ.getWithInstruction(I);
 
   switch (I->getOpcode()) {

diff  --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index 0c31dc22b871ef2..801814e0c18a837 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -4007,9 +4007,15 @@ std::pair<Value *, FPClassTest> llvm::fcmpToClassTest(FCmpInst::Predicate Pred,
                                                       Value *LHS, Value *RHS,
                                                       bool LookThroughSrc) {
   const APFloat *ConstRHS;
-  if (!match(RHS, m_APFloat(ConstRHS)))
+  if (!match(RHS, m_APFloatAllowUndef(ConstRHS)))
     return {nullptr, fcNone};
 
+  return fcmpToClassTest(Pred, F, LHS, ConstRHS, LookThroughSrc);
+}
+
+std::pair<Value *, FPClassTest>
+llvm::fcmpToClassTest(FCmpInst::Predicate Pred, const Function &F, Value *LHS,
+                      const APFloat *ConstRHS, bool LookThroughSrc) {
   // fcmp ord x, zero|normal|subnormal|inf -> ~fcNan
   if (Pred == FCmpInst::FCMP_ORD && !ConstRHS->isNaN())
     return {LHS, ~fcNan};

diff  --git a/llvm/test/Transforms/Attributor/nofpclass.ll b/llvm/test/Transforms/Attributor/nofpclass.ll
index 2690bba123a3454..051ae8b8fe3d5ac 100644
--- a/llvm/test/Transforms/Attributor/nofpclass.ll
+++ b/llvm/test/Transforms/Attributor/nofpclass.ll
@@ -600,8 +600,7 @@ define half @assume_fcmp_fabs_with_other_fabs_assume_fallback(half %arg) {
 ; CHECK-NEXT:    call void @llvm.assume(i1 noundef true) #[[ATTR16]]
 ; CHECK-NEXT:    [[UNRELATED_FABS:%.*]] = fcmp oeq half [[FABS]], 0xH0000
 ; CHECK-NEXT:    call void @llvm.assume(i1 noundef [[UNRELATED_FABS]]) #[[ATTR16]]
-; CHECK-NEXT:    [[IS_SUBNORMAL:%.*]] = fcmp olt half [[FABS]], 0xH0400
-; CHECK-NEXT:    call void @llvm.assume(i1 noundef [[IS_SUBNORMAL]]) #[[ATTR16]]
+; CHECK-NEXT:    call void @llvm.assume(i1 noundef true) #[[ATTR16]]
 ; CHECK-NEXT:    call void @extern.use.f16(half nofpclass(nan inf norm) [[ARG]])
 ; CHECK-NEXT:    call void @extern.use.f16(half nofpclass(nan inf nzero sub norm) [[FABS]])
 ; CHECK-NEXT:    ret half [[ARG]]

diff  --git a/llvm/test/Transforms/InstCombine/fcmp.ll b/llvm/test/Transforms/InstCombine/fcmp.ll
index 5c4380b14397dcb..159c84d0dd8aa91 100644
--- a/llvm/test/Transforms/InstCombine/fcmp.ll
+++ b/llvm/test/Transforms/InstCombine/fcmp.ll
@@ -718,9 +718,7 @@ define i1 @is_signbit_clear_nonzero(double %x) {
 
 define i1 @is_signbit_set_simplify_zero(double %x) {
 ; CHECK-LABEL: @is_signbit_set_simplify_zero(
-; CHECK-NEXT:    [[S:%.*]] = call double @llvm.copysign.f64(double 0.000000e+00, double [[X:%.*]])
-; CHECK-NEXT:    [[R:%.*]] = fcmp ogt double [[S]], 0.000000e+00
-; CHECK-NEXT:    ret i1 [[R]]
+; CHECK-NEXT:    ret i1 false
 ;
   %s = call double @llvm.copysign.f64(double 0.0, double %x)
   %r = fcmp ogt double %s, 0.0
@@ -731,9 +729,7 @@ define i1 @is_signbit_set_simplify_zero(double %x) {
 
 define i1 @is_signbit_set_simplify_nan(double %x) {
 ; CHECK-LABEL: @is_signbit_set_simplify_nan(
-; CHECK-NEXT:    [[S:%.*]] = call double @llvm.copysign.f64(double 0xFFFFFFFFFFFFFFFF, double [[X:%.*]])
-; CHECK-NEXT:    [[R:%.*]] = fcmp ogt double [[S]], 0.000000e+00
-; CHECK-NEXT:    ret i1 [[R]]
+; CHECK-NEXT:    ret i1 false
 ;
   %s = call double @llvm.copysign.f64(double 0xffffffffffffffff, double %x)
   %r = fcmp ogt double %s, 0.0

diff  --git a/llvm/test/Transforms/InstCombine/is_fpclass.ll b/llvm/test/Transforms/InstCombine/is_fpclass.ll
index 2f399e7e23a6376..ad0bcd1b0c437cb 100644
--- a/llvm/test/Transforms/InstCombine/is_fpclass.ll
+++ b/llvm/test/Transforms/InstCombine/is_fpclass.ll
@@ -2444,8 +2444,7 @@ define <2 x i1> @test_class_fneg_fabs_posinf_negnormal_possubnormal_negzero_nan_
 
 define i1 @test_class_is_zero_nozero_src(float nofpclass(zero) %arg) {
 ; CHECK-LABEL: @test_class_is_zero_nozero_src(
-; CHECK-NEXT:    [[CLASS:%.*]] = fcmp oeq float [[ARG:%.*]], 0.000000e+00
-; CHECK-NEXT:    ret i1 [[CLASS]]
+; CHECK-NEXT:    ret i1 false
 ;
   %class = call i1 @llvm.is.fpclass.f32(float %arg, i32 96)
   ret i1 %class
@@ -2578,8 +2577,7 @@ define i1 @test_class_is_neginf_or_nopinf_src(float nofpclass(pinf) %arg) {
 
 define i1 @test_class_is_neginf_noninf_src(float nofpclass(ninf) %arg) {
 ; CHECK-LABEL: @test_class_is_neginf_noninf_src(
-; CHECK-NEXT:    [[CLASS:%.*]] = fcmp oeq float [[ARG:%.*]], 0xFFF0000000000000
-; CHECK-NEXT:    ret i1 [[CLASS]]
+; CHECK-NEXT:    ret i1 false
 ;
   %class = call i1 @llvm.is.fpclass.f32(float %arg, i32 4)
   ret i1 %class
@@ -2604,8 +2602,7 @@ define i1 @test_class_is_posinf_noninf_src(float nofpclass(ninf) %arg) {
 
 define i1 @test_class_is_posinf_nopinf_src(float nofpclass(pinf) %arg) {
 ; CHECK-LABEL: @test_class_is_posinf_nopinf_src(
-; CHECK-NEXT:    [[CLASS:%.*]] = fcmp oeq float [[ARG:%.*]], 0x7FF0000000000000
-; CHECK-NEXT:    ret i1 [[CLASS]]
+; CHECK-NEXT:    ret i1 false
 ;
   %class = call i1 @llvm.is.fpclass.f32(float %arg, i32 512)
   ret i1 %class
@@ -2733,8 +2730,7 @@ define i1 @test_class_is_nan_assume_uno(float %x) {
 ; CHECK-LABEL: @test_class_is_nan_assume_uno(
 ; CHECK-NEXT:    [[ORD:%.*]] = fcmp uno float [[X:%.*]], 0.000000e+00
 ; CHECK-NEXT:    call void @llvm.assume(i1 [[ORD]])
-; CHECK-NEXT:    [[CLASS:%.*]] = fcmp uno float [[X]], 0.000000e+00
-; CHECK-NEXT:    ret i1 [[CLASS]]
+; CHECK-NEXT:    ret i1 true
 ;
   %ord = fcmp uno float %x, 0.0
   call void @llvm.assume(i1 %ord)

diff  --git a/llvm/test/Transforms/InstSimplify/floating-point-compare.ll b/llvm/test/Transforms/InstSimplify/floating-point-compare.ll
index a88057e4d4d93ed..62dd37d9b74e62c 100644
--- a/llvm/test/Transforms/InstSimplify/floating-point-compare.ll
+++ b/llvm/test/Transforms/InstSimplify/floating-point-compare.ll
@@ -656,8 +656,7 @@ define i1 @assume_nan_ord(float %x) {
 ; CHECK-LABEL: @assume_nan_ord(
 ; CHECK-NEXT:    [[UNO:%.*]] = fcmp uno float [[X:%.*]], 0.000000e+00
 ; CHECK-NEXT:    call void @llvm.assume(i1 [[UNO]])
-; CHECK-NEXT:    [[CMP:%.*]] = fcmp ord float [[X]], 1.000000e+00
-; CHECK-NEXT:    ret i1 [[CMP]]
+; CHECK-NEXT:    ret i1 false
 ;
   %uno = fcmp uno float %x, 0.0
   call void @llvm.assume(i1 %uno)
@@ -681,8 +680,7 @@ define i1 @assume_nan_uno(float %x) {
 ; CHECK-LABEL: @assume_nan_uno(
 ; CHECK-NEXT:    [[UNO:%.*]] = fcmp uno float [[X:%.*]], 0.000000e+00
 ; CHECK-NEXT:    call void @llvm.assume(i1 [[UNO]])
-; CHECK-NEXT:    [[CMP:%.*]] = fcmp uno float [[X]], 1.000000e+00
-; CHECK-NEXT:    ret i1 [[CMP]]
+; CHECK-NEXT:    ret i1 true
 ;
   %uno = fcmp uno float %x, 0.0
   call void @llvm.assume(i1 %uno)
@@ -1525,10 +1523,7 @@ define i1 @fcmp_olt_0_assumed_oge_zero(float %x) {
 define i1 @ogt_zero_fabs_select_negone_or_pinf(i1 %cond) {
 ; CHECK-LABEL: @ogt_zero_fabs_select_negone_or_pinf(
 ; CHECK-NEXT:  entry:
-; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[COND:%.*]], float -1.000000e+00, float 0x7FF0000000000000
-; CHECK-NEXT:    [[FABS:%.*]] = call float @llvm.fabs.f32(float [[SELECT]])
-; CHECK-NEXT:    [[ONE:%.*]] = fcmp ogt float [[FABS]], 0.000000e+00
-; CHECK-NEXT:    ret i1 [[ONE]]
+; CHECK-NEXT:    ret i1 true
 ;
 entry:
   %select = select i1 %cond, float -1.0, float 0x7FF0000000000000
@@ -1540,10 +1535,7 @@ entry:
 define i1 @ogt_zero_fabs_select_one_or_ninf(i1 %cond) {
 ; CHECK-LABEL: @ogt_zero_fabs_select_one_or_ninf(
 ; CHECK-NEXT:  entry:
-; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[COND:%.*]], float 1.000000e+00, float 0xFFF0000000000000
-; CHECK-NEXT:    [[FABS:%.*]] = call float @llvm.fabs.f32(float [[SELECT]])
-; CHECK-NEXT:    [[ONE:%.*]] = fcmp ogt float [[FABS]], 0.000000e+00
-; CHECK-NEXT:    ret i1 [[ONE]]
+; CHECK-NEXT:    ret i1 true
 ;
 entry:
   %select = select i1 %cond, float 1.0, float 0xFFF0000000000000
@@ -1552,6 +1544,114 @@ entry:
   ret i1 %one
 }
 
+; Make sure we recognize fcmp < 0 is recognized as impossible here when simplifying the fcmp
+define float @fast_square_must_be_positive_ieee(float %arg, float %arg1) {
+; CHECK-LABEL: @fast_square_must_be_positive_ieee(
+; CHECK-NEXT:  bb:
+; CHECK-NEXT:    [[I:%.*]] = fmul float [[ARG:%.*]], [[ARG]]
+; CHECK-NEXT:    [[I2:%.*]] = fmul float [[ARG1:%.*]], [[ARG1]]
+; CHECK-NEXT:    [[I3:%.*]] = fadd float [[I2]], [[I]]
+; CHECK-NEXT:    ret float [[I3]]
+;
+bb:
+  %i = fmul float %arg, %arg
+  %i2 = fmul float %arg1, %arg1
+  %i3 = fadd float %i2, %i
+  %i4 = fcmp olt float %i3, 0.000000e+00
+  %i5 = select i1 %i4, float 0.000000e+00, float %i3
+  ret float %i5
+}
+
+; Make sure we recognize fcmp < 0 is recognized as impossible here when simplifying the fcmp
+define float @fast_square_must_be_positive_ieee_nnan(float %arg, float %arg1) {
+; CHECK-LABEL: @fast_square_must_be_positive_ieee_nnan(
+; CHECK-NEXT:  bb:
+; CHECK-NEXT:    [[I:%.*]] = fmul float [[ARG:%.*]], [[ARG]]
+; CHECK-NEXT:    [[I2:%.*]] = fmul float [[ARG1:%.*]], [[ARG1]]
+; CHECK-NEXT:    [[I3:%.*]] = fadd float [[I2]], [[I]]
+; CHECK-NEXT:    ret float [[I3]]
+;
+bb:
+  %i = fmul float %arg, %arg
+  %i2 = fmul float %arg1, %arg1
+  %i3 = fadd float %i2, %i
+  %i4 = fcmp nnan olt float %i3, 0.000000e+00
+  %i5 = select i1 %i4, float 0.000000e+00, float %i3
+  ret float %i5
+}
+
+; Make sure we recognize fcmp < 0 is recognized as impossible here when simplifying the fcmp
+define float @fast_square_must_be_positive_daz(float %arg, float %arg1) #0 {
+; CHECK-LABEL: @fast_square_must_be_positive_daz(
+; CHECK-NEXT:  bb:
+; CHECK-NEXT:    [[I:%.*]] = fmul float [[ARG:%.*]], [[ARG]]
+; CHECK-NEXT:    [[I2:%.*]] = fmul float [[ARG1:%.*]], [[ARG1]]
+; CHECK-NEXT:    [[I3:%.*]] = fadd float [[I2]], [[I]]
+; CHECK-NEXT:    ret float [[I3]]
+;
+bb:
+  %i = fmul float %arg, %arg
+  %i2 = fmul float %arg1, %arg1
+  %i3 = fadd float %i2, %i
+  %i4 = fcmp olt float %i3, 0.000000e+00
+  %i5 = select i1 %i4, float 0.000000e+00, float %i3
+  ret float %i5
+}
+
+; Make sure we recognize fcmp < 0 is recognized as impossible here when simplifying the fcmp
+define float @fast_square_must_be_positive_daz_nnan(float %arg, float %arg1) #0 {
+; CHECK-LABEL: @fast_square_must_be_positive_daz_nnan(
+; CHECK-NEXT:  bb:
+; CHECK-NEXT:    [[I:%.*]] = fmul float [[ARG:%.*]], [[ARG]]
+; CHECK-NEXT:    [[I2:%.*]] = fmul float [[ARG1:%.*]], [[ARG1]]
+; CHECK-NEXT:    [[I3:%.*]] = fadd float [[I2]], [[I]]
+; CHECK-NEXT:    ret float [[I3]]
+;
+bb:
+  %i = fmul float %arg, %arg
+  %i2 = fmul float %arg1, %arg1
+  %i3 = fadd float %i2, %i
+  %i4 = fcmp nnan olt float %i3, 0.000000e+00
+  %i5 = select i1 %i4, float 0.000000e+00, float %i3
+  ret float %i5
+}
+
+; Make the compare to negative constant is folded out
+define float @must_be_olt_negative_constant_daz(float %arg, float %arg1) #0 {
+; CHECK-LABEL: @must_be_olt_negative_constant_daz(
+; CHECK-NEXT:  bb:
+; CHECK-NEXT:    [[I:%.*]] = fmul float [[ARG:%.*]], [[ARG]]
+; CHECK-NEXT:    [[I2:%.*]] = fmul float [[ARG1:%.*]], [[ARG1]]
+; CHECK-NEXT:    [[I3:%.*]] = fadd float [[I2]], [[I]]
+; CHECK-NEXT:    ret float [[I3]]
+;
+bb:
+  %i = fmul float %arg, %arg
+  %i2 = fmul float %arg1, %arg1
+  %i3 = fadd float %i2, %i
+  %i4 = fcmp olt float %i3, -1.0
+  %i5 = select i1 %i4, float 0.000000e+00, float %i3
+  ret float %i5
+}
+
+; Make the compare to negative constant is folded out
+define float @must_be_olt_negative_constant_daz_nnan(float %arg, float %arg1) #0 {
+; CHECK-LABEL: @must_be_olt_negative_constant_daz_nnan(
+; CHECK-NEXT:  bb:
+; CHECK-NEXT:    [[I:%.*]] = fmul float [[ARG:%.*]], [[ARG]]
+; CHECK-NEXT:    [[I2:%.*]] = fmul float [[ARG1:%.*]], [[ARG1]]
+; CHECK-NEXT:    [[I3:%.*]] = fadd float [[I2]], [[I]]
+; CHECK-NEXT:    ret float [[I3]]
+;
+bb:
+  %i = fmul float %arg, %arg
+  %i2 = fmul float %arg1, %arg1
+  %i3 = fadd float %i2, %i
+  %i4 = fcmp nnan olt float %i3, -1.0
+  %i5 = select i1 %i4, float 0.000000e+00, float %i3
+  ret float %i5
+}
+
 declare <2 x double> @llvm.fabs.v2f64(<2 x double>)
 declare <2 x float> @llvm.fabs.v2f32(<2 x float>)
 declare <2 x float> @llvm.maxnum.v2f32(<2 x float>, <2 x float>)
@@ -1571,3 +1671,5 @@ declare double @llvm.sqrt.f64(double)
 declare double @llvm.copysign.f64(double, double)
 declare half @llvm.fabs.f16(half)
 declare void @llvm.assume(i1 noundef)
+
+attributes #0 = { "denormal-fp-math"="preserve-sign,preserve-sign" }

diff  --git a/llvm/test/Transforms/InstSimplify/known-never-infinity.ll b/llvm/test/Transforms/InstSimplify/known-never-infinity.ll
index a7b7e0b4b1fa6c9..efa19aa0999a7a3 100644
--- a/llvm/test/Transforms/InstSimplify/known-never-infinity.ll
+++ b/llvm/test/Transforms/InstSimplify/known-never-infinity.ll
@@ -753,11 +753,7 @@ define i1 @isKnownNeverInfinity_cos(double %x) {
 define i1 @isKnownNeverInfinity_log(double %x) {
 ; CHECK-LABEL: define i1 @isKnownNeverInfinity_log
 ; CHECK-SAME: (double [[X:%.*]]) {
-; CHECK-NEXT:    [[X_CLAMP_ZERO:%.*]] = call double @llvm.maxnum.f64(double [[X]], double 0.000000e+00)
-; CHECK-NEXT:    [[A:%.*]] = fadd ninf double [[X_CLAMP_ZERO]], 1.000000e+00
-; CHECK-NEXT:    [[E:%.*]] = call double @llvm.log.f64(double [[A]])
-; CHECK-NEXT:    [[R:%.*]] = fcmp une double [[E]], 0x7FF0000000000000
-; CHECK-NEXT:    ret i1 [[R]]
+; CHECK-NEXT:    ret i1 true
 ;
   %x.clamp.zero = call double @llvm.maxnum.f64(double %x, double 0.0)
   %a = fadd ninf double %x.clamp.zero, 1.0
@@ -769,10 +765,7 @@ define i1 @isKnownNeverInfinity_log(double %x) {
 define i1 @isNotKnownNeverInfinity_log_maybe_negative(double %x) {
 ; CHECK-LABEL: define i1 @isNotKnownNeverInfinity_log_maybe_negative
 ; CHECK-SAME: (double [[X:%.*]]) {
-; CHECK-NEXT:    [[X_NOT_INF:%.*]] = fadd ninf double [[X]], 1.000000e+00
-; CHECK-NEXT:    [[E:%.*]] = call double @llvm.log.f64(double [[X_NOT_INF]])
-; CHECK-NEXT:    [[R:%.*]] = fcmp une double [[E]], 0x7FF0000000000000
-; CHECK-NEXT:    ret i1 [[R]]
+; CHECK-NEXT:    ret i1 true
 ;
 
   %x.not.inf = fadd ninf double %x, 1.0
@@ -812,11 +805,7 @@ define i1 @isKnownNeverNegInfinity_log_maybe_0(double %x) {
 define i1 @isKnownNeverInfinity_log10(double %x) {
 ; CHECK-LABEL: define i1 @isKnownNeverInfinity_log10
 ; CHECK-SAME: (double [[X:%.*]]) {
-; CHECK-NEXT:    [[X_CLAMP_ZERO:%.*]] = call double @llvm.maxnum.f64(double [[X]], double 0.000000e+00)
-; CHECK-NEXT:    [[A:%.*]] = fadd ninf double [[X_CLAMP_ZERO]], 1.000000e+00
-; CHECK-NEXT:    [[E:%.*]] = call double @llvm.log10.f64(double [[A]])
-; CHECK-NEXT:    [[R:%.*]] = fcmp une double [[E]], 0x7FF0000000000000
-; CHECK-NEXT:    ret i1 [[R]]
+; CHECK-NEXT:    ret i1 true
 ;
   %x.clamp.zero = call double @llvm.maxnum.f64(double %x, double 0.0)
   %a = fadd ninf double %x.clamp.zero, 1.0
@@ -828,10 +817,7 @@ define i1 @isKnownNeverInfinity_log10(double %x) {
 define i1 @isNotKnownNeverInfinity_log10_maybe_negative(double %x) {
 ; CHECK-LABEL: define i1 @isNotKnownNeverInfinity_log10_maybe_negative
 ; CHECK-SAME: (double [[X:%.*]]) {
-; CHECK-NEXT:    [[X_NOT_INF:%.*]] = fadd ninf double [[X]], 1.000000e+00
-; CHECK-NEXT:    [[E:%.*]] = call double @llvm.log10.f64(double [[X_NOT_INF]])
-; CHECK-NEXT:    [[R:%.*]] = fcmp une double [[E]], 0x7FF0000000000000
-; CHECK-NEXT:    ret i1 [[R]]
+; CHECK-NEXT:    ret i1 true
 ;
 
   %x.not.inf = fadd ninf double %x, 1.0
@@ -871,11 +857,7 @@ define i1 @isKnownNeverNegInfinity_log10_maybe_0(double %x) {
 define i1 @isKnownNeverInfinity_log2(double %x) {
 ; CHECK-LABEL: define i1 @isKnownNeverInfinity_log2
 ; CHECK-SAME: (double [[X:%.*]]) {
-; CHECK-NEXT:    [[X_CLAMP_ZERO:%.*]] = call double @llvm.maxnum.f64(double [[X]], double 0.000000e+00)
-; CHECK-NEXT:    [[A:%.*]] = fadd ninf double [[X_CLAMP_ZERO]], 1.000000e+00
-; CHECK-NEXT:    [[E:%.*]] = call double @llvm.log2.f64(double [[A]])
-; CHECK-NEXT:    [[R:%.*]] = fcmp une double [[E]], 0x7FF0000000000000
-; CHECK-NEXT:    ret i1 [[R]]
+; CHECK-NEXT:    ret i1 true
 ;
   %x.clamp.zero = call double @llvm.maxnum.f64(double %x, double 0.0)
   %a = fadd ninf double %x.clamp.zero, 1.0
@@ -887,10 +869,7 @@ define i1 @isKnownNeverInfinity_log2(double %x) {
 define i1 @isNotKnownNeverInfinity_log2_maybe_negative(double %x) {
 ; CHECK-LABEL: define i1 @isNotKnownNeverInfinity_log2_maybe_negative
 ; CHECK-SAME: (double [[X:%.*]]) {
-; CHECK-NEXT:    [[X_NOT_INF:%.*]] = fadd ninf double [[X]], 1.000000e+00
-; CHECK-NEXT:    [[E:%.*]] = call double @llvm.log2.f64(double [[X_NOT_INF]])
-; CHECK-NEXT:    [[R:%.*]] = fcmp une double [[E]], 0x7FF0000000000000
-; CHECK-NEXT:    ret i1 [[R]]
+; CHECK-NEXT:    ret i1 true
 ;
 
   %x.not.inf = fadd ninf double %x, 1.0
@@ -1057,10 +1036,7 @@ define i1 @not_ninf_fabs_select_nzero_or_pinf(i1 %cond) {
 ; CHECK-LABEL: define i1 @not_ninf_fabs_select_nzero_or_pinf
 ; CHECK-SAME: (i1 [[COND:%.*]]) {
 ; CHECK-NEXT:  entry:
-; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[COND]], float -0.000000e+00, float 0x7FF0000000000000
-; CHECK-NEXT:    [[FABS:%.*]] = call float @llvm.fabs.f32(float [[SELECT]])
-; CHECK-NEXT:    [[ONE:%.*]] = fcmp one float [[FABS]], 0xFFF0000000000000
-; CHECK-NEXT:    ret i1 [[ONE]]
+; CHECK-NEXT:    ret i1 true
 ;
 entry:
   %select = select i1 %cond, float -0.000000e+00, float 0x7FF0000000000000


        


More information about the llvm-commits mailing list