[llvm] [Valuetracking] Use all FPClasses ordering information for min/max (PR #199651)

Niklas Ulvinge via llvm-commits llvm-commits at lists.llvm.org
Mon Jun 1 05:22:01 PDT 2026


https://github.com/nulvinge updated https://github.com/llvm/llvm-project/pull/199651

>From 230961b77a82a3c1186092f05ca2fb666c7c7e3b Mon Sep 17 00:00:00 2001
From: Niklas Ulvinge <niklas.ulvinge at arm.com>
Date: Tue, 19 May 2026 13:54:40 +0200
Subject: [PATCH] [Valuetracking] Use all FPClasses ordering information for
 min/max

Min/Max functions can exclude more FPClasses than
OrderedLessThanZeroMask/OrderedGreaterThanZeroMask.
Now it excludes all analyzable FPClasses, of which
+/-Inf are the most useful.
---
 llvm/include/llvm/ADT/FloatingPointMode.h     | 20 ++++++
 llvm/lib/Support/FloatingPointMode.cpp        | 38 +++++++++++
 llvm/lib/Support/KnownFPClass.cpp             | 35 ++++------
 .../Attributor/nofpclass-minimum-maximum.ll   | 32 ++++-----
 .../nofpclass-minimumnum-maximumnum.ll        | 16 ++---
 .../Attributor/nofpclass-minnum-maxnum.ll     | 16 ++---
 .../InstSimplify/known-never-infinity.ll      | 66 +++++++++++++++----
 7 files changed, 157 insertions(+), 66 deletions(-)

diff --git a/llvm/include/llvm/ADT/FloatingPointMode.h b/llvm/include/llvm/ADT/FloatingPointMode.h
index da1fd22d85e0b..fc4cf2c9e3d6d 100644
--- a/llvm/include/llvm/ADT/FloatingPointMode.h
+++ b/llvm/include/llvm/ADT/FloatingPointMode.h
@@ -412,6 +412,26 @@ LLVM_ABI bool cannotOrderStrictlyLess(FPClassTest LHS, FPClassTest RHS,
 LLVM_ABI bool cannotOrderStrictlyLessEq(FPClassTest LHS, FPClassTest RHS,
                                         bool OrderedZeroSign = false);
 
+/// Returns all FPClasses which are less than all values in \p Mask
+/// That is, return all classes for which the comparison
+/// `fcmp ole LHS, RHS` will always return false.
+/// Ignores nan and treats the sign of the zeroes as ordered.
+///
+/// If \p OrderedZeroSign is true, -0 will be treated as ordered less than +0,
+/// unlike fcmp.
+LLVM_ABI FPClassTest orderedStrictlyLess(FPClassTest Mask,
+                                         bool OrderedZeroSign = false);
+
+/// Returns all FPClasses which are greater than all values in \p Mask
+/// That is, return all classes for which the comparison
+/// `fcmp ole LHS, RHS` will always return false.
+/// Ignores nan and treats the sign of the zeroes as ordered.
+///
+/// If \p OrderedZeroSign is true, -0 will be treated as ordered less than +0,
+/// unlike fcmp.
+LLVM_ABI FPClassTest orderedStrictlyGreater(FPClassTest Mask,
+                                            bool OrderedZeroSign = false);
+
 } // namespace llvm
 
 #endif // LLVM_ADT_FLOATINGPOINTMODE_H
diff --git a/llvm/lib/Support/FloatingPointMode.cpp b/llvm/lib/Support/FloatingPointMode.cpp
index a81a2644a3713..d6aadc42bd21e 100644
--- a/llvm/lib/Support/FloatingPointMode.cpp
+++ b/llvm/lib/Support/FloatingPointMode.cpp
@@ -173,3 +173,41 @@ bool llvm::cannotOrderStrictlyLessEq(FPClassTest LHS, FPClassTest RHS,
                                      bool OrderedZeroSign) {
   return cannotOrderStrictlyGreaterImpl(RHS, LHS, true, OrderedZeroSign);
 }
+
+FPClassTest llvm::orderedStrictlyLess(FPClassTest Mask, bool OrderedZeroSign) {
+  // Ignores NaN
+  Mask &= ~fcNan;
+  // Since the classes are ordered bits, we can get all classes which are
+  // smaller than all classes in Known by setting all trailing 0 bits to 1,
+  // and setting the other bits to 0.
+  // This is done by counting the number of trailing 0 bits and creating a
+  // mask based on that.
+  // For example: 0b1111000000 = fcPositive
+  //           -> 0b0000111111 = fcNegative | fcNan
+  FPClassTest NewMask = static_cast<FPClassTest>(
+      maskTrailingOnes<unsigned>(countr_zero<unsigned>(Mask)));
+  // Remove NaNs
+  NewMask &= ~fcNan;
+  // We cannot conclude that only one zero is smaller
+  // if the zeroes are not ordered
+  if (!OrderedZeroSign && ((NewMask & fcZero) != fcZero))
+    NewMask &= ~fcZero;
+  return NewMask;
+}
+
+FPClassTest llvm::orderedStrictlyGreater(FPClassTest Mask,
+                                         bool OrderedZeroSign) {
+  // Counting the number of leading 0 bits and create a mask based on that,
+  // removing the leading 1s that are outside the bitfield:
+  // For example: 0b0000111100 = fcNegative
+  //           -> 0b1111000000 = fcPositive
+  FPClassTest NewMask = static_cast<FPClassTest>(
+      maskLeadingOnes<unsigned>(countl_zero<unsigned>(Mask)) & fcAllFlags);
+  // Remove NaNs
+  NewMask &= ~fcNan;
+  // We cannot conclude that only one zero is greater
+  // if the zeroes are not ordered
+  if (!OrderedZeroSign && ((NewMask & fcZero) != fcZero))
+    NewMask &= ~fcZero;
+  return NewMask;
+}
diff --git a/llvm/lib/Support/KnownFPClass.cpp b/llvm/lib/Support/KnownFPClass.cpp
index 3e2f6a1704b01..dab72cd37c841 100644
--- a/llvm/lib/Support/KnownFPClass.cpp
+++ b/llvm/lib/Support/KnownFPClass.cpp
@@ -108,32 +108,21 @@ KnownFPClass KnownFPClass::minMaxLike(const KnownFPClass &LHS_,
     Known.knownNot(fcNan);
 
   if (Kind == MinMaxKind::maxnum || Kind == MinMaxKind::maximumnum) {
-    // If at least one operand is known to be positive, the result must be
-    // positive.
-    if ((KnownLHS.cannotBeOrderedLessThanZero() &&
-         KnownLHS.isKnownNeverNaN()) ||
-        (KnownRHS.cannotBeOrderedLessThanZero() && KnownRHS.isKnownNeverNaN()))
-      Known.knownNot(KnownFPClass::OrderedLessThanZeroMask);
+    if (KnownLHS.isKnownNeverNaN())
+      Known.knownNot(orderedStrictlyLess(KnownLHS.KnownFPClasses));
+    if (KnownRHS.isKnownNeverNaN())
+      Known.knownNot(orderedStrictlyLess(KnownRHS.KnownFPClasses));
   } else if (Kind == MinMaxKind::maximum) {
-    // If at least one operand is known to be positive, the result must be
-    // positive.
-    if (KnownLHS.cannotBeOrderedLessThanZero() ||
-        KnownRHS.cannotBeOrderedLessThanZero())
-      Known.knownNot(KnownFPClass::OrderedLessThanZeroMask);
+    Known.knownNot(orderedStrictlyLess(KnownLHS.KnownFPClasses) |
+                   orderedStrictlyLess(KnownRHS.KnownFPClasses));
   } else if (Kind == MinMaxKind::minnum || Kind == MinMaxKind::minimumnum) {
-    // If at least one operand is known to be negative, the result must be
-    // negative.
-    if ((KnownLHS.cannotBeOrderedGreaterThanZero() &&
-         KnownLHS.isKnownNeverNaN()) ||
-        (KnownRHS.cannotBeOrderedGreaterThanZero() &&
-         KnownRHS.isKnownNeverNaN()))
-      Known.knownNot(KnownFPClass::OrderedGreaterThanZeroMask);
+    if (KnownLHS.isKnownNeverNaN())
+      Known.knownNot(orderedStrictlyGreater(KnownLHS.KnownFPClasses));
+    if (KnownRHS.isKnownNeverNaN())
+      Known.knownNot(orderedStrictlyGreater(KnownRHS.KnownFPClasses));
   } else if (Kind == MinMaxKind::minimum) {
-    // If at least one operand is known to be negative, the result must be
-    // negative.
-    if (KnownLHS.cannotBeOrderedGreaterThanZero() ||
-        KnownRHS.cannotBeOrderedGreaterThanZero())
-      Known.knownNot(KnownFPClass::OrderedGreaterThanZeroMask);
+    Known.knownNot(orderedStrictlyGreater(KnownLHS.KnownFPClasses) |
+                   orderedStrictlyGreater(KnownRHS.KnownFPClasses));
   } else
     llvm_unreachable("unhandled intrinsic");
 
diff --git a/llvm/test/Transforms/Attributor/nofpclass-minimum-maximum.ll b/llvm/test/Transforms/Attributor/nofpclass-minimum-maximum.ll
index 7059620febe74..093cbbe19e2ce 100644
--- a/llvm/test/Transforms/Attributor/nofpclass-minimum-maximum.ll
+++ b/llvm/test/Transforms/Attributor/nofpclass-minimum-maximum.ll
@@ -26,9 +26,9 @@ define float @ret_minimum_noinf__noinf(float nofpclass(inf) %arg0, float nofpcla
 }
 
 define float @ret_minimum_noinf__nonan(float nofpclass(inf) %arg0, float nofpclass(nan) %arg1) #0 {
-; CHECK-LABEL: define float @ret_minimum_noinf__nonan
+; CHECK-LABEL: define nofpclass(pinf) float @ret_minimum_noinf__nonan
 ; CHECK-SAME: (float nofpclass(inf) [[ARG0:%.*]], float nofpclass(nan) [[ARG1:%.*]]) #[[ATTR1]] {
-; CHECK-NEXT:    [[CALL:%.*]] = call float @llvm.minimum.f32(float nofpclass(inf) [[ARG0]], float nofpclass(nan) [[ARG1]]) #[[ATTR9]]
+; CHECK-NEXT:    [[CALL:%.*]] = call nofpclass(pinf) float @llvm.minimum.f32(float nofpclass(inf) [[ARG0]], float nofpclass(nan) [[ARG1]]) #[[ATTR9]]
 ; CHECK-NEXT:    ret float [[CALL]]
 ;
   %call = call float @llvm.minimum.f32(float %arg0, float %arg1)
@@ -36,9 +36,9 @@ define float @ret_minimum_noinf__nonan(float nofpclass(inf) %arg0, float nofpcla
 }
 
 define float @ret_minimum_nonan__noinf(float nofpclass(nan) %arg0, float nofpclass(inf) %arg1) #0 {
-; CHECK-LABEL: define float @ret_minimum_nonan__noinf
+; CHECK-LABEL: define nofpclass(pinf) float @ret_minimum_nonan__noinf
 ; CHECK-SAME: (float nofpclass(nan) [[ARG0:%.*]], float nofpclass(inf) [[ARG1:%.*]]) #[[ATTR1]] {
-; CHECK-NEXT:    [[CALL:%.*]] = call float @llvm.minimum.f32(float nofpclass(nan) [[ARG0]], float nofpclass(inf) [[ARG1]]) #[[ATTR9]]
+; CHECK-NEXT:    [[CALL:%.*]] = call nofpclass(pinf) float @llvm.minimum.f32(float nofpclass(nan) [[ARG0]], float nofpclass(inf) [[ARG1]]) #[[ATTR9]]
 ; CHECK-NEXT:    ret float [[CALL]]
 ;
   %call = call float @llvm.minimum.f32(float %arg0, float %arg1)
@@ -46,9 +46,9 @@ define float @ret_minimum_nonan__noinf(float nofpclass(nan) %arg0, float nofpcla
 }
 
 define float @ret_minimum_noinf_nonan__nonan(float nofpclass(inf nan) %arg0, float nofpclass(nan) %arg1) #0 {
-; CHECK-LABEL: define nofpclass(nan) float @ret_minimum_noinf_nonan__nonan
+; CHECK-LABEL: define nofpclass(nan pinf) float @ret_minimum_noinf_nonan__nonan
 ; CHECK-SAME: (float nofpclass(nan inf) [[ARG0:%.*]], float nofpclass(nan) [[ARG1:%.*]]) #[[ATTR1]] {
-; CHECK-NEXT:    [[CALL:%.*]] = call nofpclass(nan) float @llvm.minimum.f32(float nofpclass(nan inf) [[ARG0]], float nofpclass(nan) [[ARG1]]) #[[ATTR9]]
+; CHECK-NEXT:    [[CALL:%.*]] = call nofpclass(nan pinf) float @llvm.minimum.f32(float nofpclass(nan inf) [[ARG0]], float nofpclass(nan) [[ARG1]]) #[[ATTR9]]
 ; CHECK-NEXT:    ret float [[CALL]]
 ;
   %call = call float @llvm.minimum.f32(float %arg0, float %arg1)
@@ -56,9 +56,9 @@ define float @ret_minimum_noinf_nonan__nonan(float nofpclass(inf nan) %arg0, flo
 }
 
 define float @ret_minimum_nonan__noinf_nonan(float nofpclass(nan) %arg0, float nofpclass(inf nan) %arg1) #0 {
-; CHECK-LABEL: define nofpclass(nan) float @ret_minimum_nonan__noinf_nonan
+; CHECK-LABEL: define nofpclass(nan pinf) float @ret_minimum_nonan__noinf_nonan
 ; CHECK-SAME: (float nofpclass(nan) [[ARG0:%.*]], float nofpclass(nan inf) [[ARG1:%.*]]) #[[ATTR1]] {
-; CHECK-NEXT:    [[CALL:%.*]] = call nofpclass(nan) float @llvm.minimum.f32(float nofpclass(nan) [[ARG0]], float nofpclass(nan inf) [[ARG1]]) #[[ATTR9]]
+; CHECK-NEXT:    [[CALL:%.*]] = call nofpclass(nan pinf) float @llvm.minimum.f32(float nofpclass(nan) [[ARG0]], float nofpclass(nan inf) [[ARG1]]) #[[ATTR9]]
 ; CHECK-NEXT:    ret float [[CALL]]
 ;
   %call = call float @llvm.minimum.f32(float %arg0, float %arg1)
@@ -96,9 +96,9 @@ define float @ret_maximum_noinf__noinf(float nofpclass(inf) %arg0, float nofpcla
 }
 
 define float @ret_maximum_noinf__nonan(float nofpclass(inf) %arg0, float nofpclass(nan) %arg1) #0 {
-; CHECK-LABEL: define float @ret_maximum_noinf__nonan
+; CHECK-LABEL: define nofpclass(ninf) float @ret_maximum_noinf__nonan
 ; CHECK-SAME: (float nofpclass(inf) [[ARG0:%.*]], float nofpclass(nan) [[ARG1:%.*]]) #[[ATTR1]] {
-; CHECK-NEXT:    [[CALL:%.*]] = call float @llvm.maximum.f32(float nofpclass(inf) [[ARG0]], float nofpclass(nan) [[ARG1]]) #[[ATTR9]]
+; CHECK-NEXT:    [[CALL:%.*]] = call nofpclass(ninf) float @llvm.maximum.f32(float nofpclass(inf) [[ARG0]], float nofpclass(nan) [[ARG1]]) #[[ATTR9]]
 ; CHECK-NEXT:    ret float [[CALL]]
 ;
   %call = call float @llvm.maximum.f32(float %arg0, float %arg1)
@@ -106,9 +106,9 @@ define float @ret_maximum_noinf__nonan(float nofpclass(inf) %arg0, float nofpcla
 }
 
 define float @ret_maximum_nonan__noinf(float nofpclass(nan) %arg0, float nofpclass(inf) %arg1) #0 {
-; CHECK-LABEL: define float @ret_maximum_nonan__noinf
+; CHECK-LABEL: define nofpclass(ninf) float @ret_maximum_nonan__noinf
 ; CHECK-SAME: (float nofpclass(nan) [[ARG0:%.*]], float nofpclass(inf) [[ARG1:%.*]]) #[[ATTR1]] {
-; CHECK-NEXT:    [[CALL:%.*]] = call float @llvm.maximum.f32(float nofpclass(nan) [[ARG0]], float nofpclass(inf) [[ARG1]]) #[[ATTR9]]
+; CHECK-NEXT:    [[CALL:%.*]] = call nofpclass(ninf) float @llvm.maximum.f32(float nofpclass(nan) [[ARG0]], float nofpclass(inf) [[ARG1]]) #[[ATTR9]]
 ; CHECK-NEXT:    ret float [[CALL]]
 ;
   %call = call float @llvm.maximum.f32(float %arg0, float %arg1)
@@ -116,9 +116,9 @@ define float @ret_maximum_nonan__noinf(float nofpclass(nan) %arg0, float nofpcla
 }
 
 define float @ret_maximum_noinf_nonan__nonan(float nofpclass(inf nan) %arg0, float nofpclass(nan) %arg1) #0 {
-; CHECK-LABEL: define nofpclass(nan) float @ret_maximum_noinf_nonan__nonan
+; CHECK-LABEL: define nofpclass(nan ninf) float @ret_maximum_noinf_nonan__nonan
 ; CHECK-SAME: (float nofpclass(nan inf) [[ARG0:%.*]], float nofpclass(nan) [[ARG1:%.*]]) #[[ATTR1]] {
-; CHECK-NEXT:    [[CALL:%.*]] = call nofpclass(nan) float @llvm.maximum.f32(float nofpclass(nan inf) [[ARG0]], float nofpclass(nan) [[ARG1]]) #[[ATTR9]]
+; CHECK-NEXT:    [[CALL:%.*]] = call nofpclass(nan ninf) float @llvm.maximum.f32(float nofpclass(nan inf) [[ARG0]], float nofpclass(nan) [[ARG1]]) #[[ATTR9]]
 ; CHECK-NEXT:    ret float [[CALL]]
 ;
   %call = call float @llvm.maximum.f32(float %arg0, float %arg1)
@@ -126,9 +126,9 @@ define float @ret_maximum_noinf_nonan__nonan(float nofpclass(inf nan) %arg0, flo
 }
 
 define float @ret_maximum_nonan__noinf_nonan(float nofpclass(nan) %arg0, float nofpclass(inf nan) %arg1) #0 {
-; CHECK-LABEL: define nofpclass(nan) float @ret_maximum_nonan__noinf_nonan
+; CHECK-LABEL: define nofpclass(nan ninf) float @ret_maximum_nonan__noinf_nonan
 ; CHECK-SAME: (float nofpclass(nan) [[ARG0:%.*]], float nofpclass(nan inf) [[ARG1:%.*]]) #[[ATTR1]] {
-; CHECK-NEXT:    [[CALL:%.*]] = call nofpclass(nan) float @llvm.maximum.f32(float nofpclass(nan) [[ARG0]], float nofpclass(nan inf) [[ARG1]]) #[[ATTR9]]
+; CHECK-NEXT:    [[CALL:%.*]] = call nofpclass(nan ninf) float @llvm.maximum.f32(float nofpclass(nan) [[ARG0]], float nofpclass(nan inf) [[ARG1]]) #[[ATTR9]]
 ; CHECK-NEXT:    ret float [[CALL]]
 ;
   %call = call float @llvm.maximum.f32(float %arg0, float %arg1)
diff --git a/llvm/test/Transforms/Attributor/nofpclass-minimumnum-maximumnum.ll b/llvm/test/Transforms/Attributor/nofpclass-minimumnum-maximumnum.ll
index d5a289b51c107..1b971f2874f74 100644
--- a/llvm/test/Transforms/Attributor/nofpclass-minimumnum-maximumnum.ll
+++ b/llvm/test/Transforms/Attributor/nofpclass-minimumnum-maximumnum.ll
@@ -46,9 +46,9 @@ define float @ret_minimumnum_nonan__noinf(float nofpclass(nan) %arg0, float nofp
 }
 
 define float @ret_minimumnum_noinf_nonan__nonan(float nofpclass(inf nan) %arg0, float nofpclass(nan) %arg1) #0 {
-; CHECK-LABEL: define nofpclass(nan) float @ret_minimumnum_noinf_nonan__nonan
+; CHECK-LABEL: define nofpclass(nan pinf) float @ret_minimumnum_noinf_nonan__nonan
 ; CHECK-SAME: (float nofpclass(nan inf) [[ARG0:%.*]], float nofpclass(nan) [[ARG1:%.*]]) #[[ATTR1]] {
-; CHECK-NEXT:    [[CALL:%.*]] = call nofpclass(nan) float @llvm.minimumnum.f32(float nofpclass(nan inf) [[ARG0]], float nofpclass(nan) [[ARG1]]) #[[ATTR9]]
+; CHECK-NEXT:    [[CALL:%.*]] = call nofpclass(nan pinf) float @llvm.minimumnum.f32(float nofpclass(nan inf) [[ARG0]], float nofpclass(nan) [[ARG1]]) #[[ATTR9]]
 ; CHECK-NEXT:    ret float [[CALL]]
 ;
   %call = call float @llvm.minimumnum.f32(float %arg0, float %arg1)
@@ -56,9 +56,9 @@ define float @ret_minimumnum_noinf_nonan__nonan(float nofpclass(inf nan) %arg0,
 }
 
 define float @ret_minimumnum_nonan__noinf_nonan(float nofpclass(nan) %arg0, float nofpclass(inf nan) %arg1) #0 {
-; CHECK-LABEL: define nofpclass(nan) float @ret_minimumnum_nonan__noinf_nonan
+; CHECK-LABEL: define nofpclass(nan pinf) float @ret_minimumnum_nonan__noinf_nonan
 ; CHECK-SAME: (float nofpclass(nan) [[ARG0:%.*]], float nofpclass(nan inf) [[ARG1:%.*]]) #[[ATTR1]] {
-; CHECK-NEXT:    [[CALL:%.*]] = call nofpclass(nan) float @llvm.minimumnum.f32(float nofpclass(nan) [[ARG0]], float nofpclass(nan inf) [[ARG1]]) #[[ATTR9]]
+; CHECK-NEXT:    [[CALL:%.*]] = call nofpclass(nan pinf) float @llvm.minimumnum.f32(float nofpclass(nan) [[ARG0]], float nofpclass(nan inf) [[ARG1]]) #[[ATTR9]]
 ; CHECK-NEXT:    ret float [[CALL]]
 ;
   %call = call float @llvm.minimumnum.f32(float %arg0, float %arg1)
@@ -116,9 +116,9 @@ define float @ret_maximumnum_nonan__noinf(float nofpclass(nan) %arg0, float nofp
 }
 
 define float @ret_maximumnum_noinf_nonan__nonan(float nofpclass(inf nan) %arg0, float nofpclass(nan) %arg1) #0 {
-; CHECK-LABEL: define nofpclass(nan) float @ret_maximumnum_noinf_nonan__nonan
+; CHECK-LABEL: define nofpclass(nan ninf) float @ret_maximumnum_noinf_nonan__nonan
 ; CHECK-SAME: (float nofpclass(nan inf) [[ARG0:%.*]], float nofpclass(nan) [[ARG1:%.*]]) #[[ATTR1]] {
-; CHECK-NEXT:    [[CALL:%.*]] = call nofpclass(nan) float @llvm.maximumnum.f32(float nofpclass(nan inf) [[ARG0]], float nofpclass(nan) [[ARG1]]) #[[ATTR9]]
+; CHECK-NEXT:    [[CALL:%.*]] = call nofpclass(nan ninf) float @llvm.maximumnum.f32(float nofpclass(nan inf) [[ARG0]], float nofpclass(nan) [[ARG1]]) #[[ATTR9]]
 ; CHECK-NEXT:    ret float [[CALL]]
 ;
   %call = call float @llvm.maximumnum.f32(float %arg0, float %arg1)
@@ -126,9 +126,9 @@ define float @ret_maximumnum_noinf_nonan__nonan(float nofpclass(inf nan) %arg0,
 }
 
 define float @ret_maximumnum_nonan__noinf_nonan(float nofpclass(nan) %arg0, float nofpclass(inf nan) %arg1) #0 {
-; CHECK-LABEL: define nofpclass(nan) float @ret_maximumnum_nonan__noinf_nonan
+; CHECK-LABEL: define nofpclass(nan ninf) float @ret_maximumnum_nonan__noinf_nonan
 ; CHECK-SAME: (float nofpclass(nan) [[ARG0:%.*]], float nofpclass(nan inf) [[ARG1:%.*]]) #[[ATTR1]] {
-; CHECK-NEXT:    [[CALL:%.*]] = call nofpclass(nan) float @llvm.maximumnum.f32(float nofpclass(nan) [[ARG0]], float nofpclass(nan inf) [[ARG1]]) #[[ATTR9]]
+; CHECK-NEXT:    [[CALL:%.*]] = call nofpclass(nan ninf) float @llvm.maximumnum.f32(float nofpclass(nan) [[ARG0]], float nofpclass(nan inf) [[ARG1]]) #[[ATTR9]]
 ; CHECK-NEXT:    ret float [[CALL]]
 ;
   %call = call float @llvm.maximumnum.f32(float %arg0, float %arg1)
diff --git a/llvm/test/Transforms/Attributor/nofpclass-minnum-maxnum.ll b/llvm/test/Transforms/Attributor/nofpclass-minnum-maxnum.ll
index 308f58b7dd2fc..8963a7a362c98 100644
--- a/llvm/test/Transforms/Attributor/nofpclass-minnum-maxnum.ll
+++ b/llvm/test/Transforms/Attributor/nofpclass-minnum-maxnum.ll
@@ -46,9 +46,9 @@ define float @ret_minnum_nonan__noinf(float nofpclass(nan) %arg0, float nofpclas
 }
 
 define float @ret_minnum_noinf_nonan__nonan(float nofpclass(inf nan) %arg0, float nofpclass(nan) %arg1) #0 {
-; CHECK-LABEL: define nofpclass(nan) float @ret_minnum_noinf_nonan__nonan
+; CHECK-LABEL: define nofpclass(nan pinf) float @ret_minnum_noinf_nonan__nonan
 ; CHECK-SAME: (float nofpclass(nan inf) [[ARG0:%.*]], float nofpclass(nan) [[ARG1:%.*]]) #[[ATTR1]] {
-; CHECK-NEXT:    [[CALL:%.*]] = call nofpclass(nan) float @llvm.minnum.f32(float nofpclass(nan inf) [[ARG0]], float nofpclass(nan) [[ARG1]]) #[[ATTR9]]
+; CHECK-NEXT:    [[CALL:%.*]] = call nofpclass(nan pinf) float @llvm.minnum.f32(float nofpclass(nan inf) [[ARG0]], float nofpclass(nan) [[ARG1]]) #[[ATTR9]]
 ; CHECK-NEXT:    ret float [[CALL]]
 ;
   %call = call float @llvm.minnum.f32(float %arg0, float %arg1)
@@ -56,9 +56,9 @@ define float @ret_minnum_noinf_nonan__nonan(float nofpclass(inf nan) %arg0, floa
 }
 
 define float @ret_minnum_nonan__noinf_nonan(float nofpclass(nan) %arg0, float nofpclass(inf nan) %arg1) #0 {
-; CHECK-LABEL: define nofpclass(nan) float @ret_minnum_nonan__noinf_nonan
+; CHECK-LABEL: define nofpclass(nan pinf) float @ret_minnum_nonan__noinf_nonan
 ; CHECK-SAME: (float nofpclass(nan) [[ARG0:%.*]], float nofpclass(nan inf) [[ARG1:%.*]]) #[[ATTR1]] {
-; CHECK-NEXT:    [[CALL:%.*]] = call nofpclass(nan) float @llvm.minnum.f32(float nofpclass(nan) [[ARG0]], float nofpclass(nan inf) [[ARG1]]) #[[ATTR9]]
+; CHECK-NEXT:    [[CALL:%.*]] = call nofpclass(nan pinf) float @llvm.minnum.f32(float nofpclass(nan) [[ARG0]], float nofpclass(nan inf) [[ARG1]]) #[[ATTR9]]
 ; CHECK-NEXT:    ret float [[CALL]]
 ;
   %call = call float @llvm.minnum.f32(float %arg0, float %arg1)
@@ -116,9 +116,9 @@ define float @ret_maxnum_nonan__noinf(float nofpclass(nan) %arg0, float nofpclas
 }
 
 define float @ret_maxnum_noinf_nonan__nonan(float nofpclass(inf nan) %arg0, float nofpclass(nan) %arg1) #0 {
-; CHECK-LABEL: define nofpclass(nan) float @ret_maxnum_noinf_nonan__nonan
+; CHECK-LABEL: define nofpclass(nan ninf) float @ret_maxnum_noinf_nonan__nonan
 ; CHECK-SAME: (float nofpclass(nan inf) [[ARG0:%.*]], float nofpclass(nan) [[ARG1:%.*]]) #[[ATTR1]] {
-; CHECK-NEXT:    [[CALL:%.*]] = call nofpclass(nan) float @llvm.maxnum.f32(float nofpclass(nan inf) [[ARG0]], float nofpclass(nan) [[ARG1]]) #[[ATTR9]]
+; CHECK-NEXT:    [[CALL:%.*]] = call nofpclass(nan ninf) float @llvm.maxnum.f32(float nofpclass(nan inf) [[ARG0]], float nofpclass(nan) [[ARG1]]) #[[ATTR9]]
 ; CHECK-NEXT:    ret float [[CALL]]
 ;
   %call = call float @llvm.maxnum.f32(float %arg0, float %arg1)
@@ -126,9 +126,9 @@ define float @ret_maxnum_noinf_nonan__nonan(float nofpclass(inf nan) %arg0, floa
 }
 
 define float @ret_maxnum_nonan__noinf_nonan(float nofpclass(nan) %arg0, float nofpclass(inf nan) %arg1) #0 {
-; CHECK-LABEL: define nofpclass(nan) float @ret_maxnum_nonan__noinf_nonan
+; CHECK-LABEL: define nofpclass(nan ninf) float @ret_maxnum_nonan__noinf_nonan
 ; CHECK-SAME: (float nofpclass(nan) [[ARG0:%.*]], float nofpclass(nan inf) [[ARG1:%.*]]) #[[ATTR1]] {
-; CHECK-NEXT:    [[CALL:%.*]] = call nofpclass(nan) float @llvm.maxnum.f32(float nofpclass(nan) [[ARG0]], float nofpclass(nan inf) [[ARG1]]) #[[ATTR9]]
+; CHECK-NEXT:    [[CALL:%.*]] = call nofpclass(nan ninf) float @llvm.maxnum.f32(float nofpclass(nan) [[ARG0]], float nofpclass(nan inf) [[ARG1]]) #[[ATTR9]]
 ; CHECK-NEXT:    ret float [[CALL]]
 ;
   %call = call float @llvm.maxnum.f32(float %arg0, float %arg1)
diff --git a/llvm/test/Transforms/InstSimplify/known-never-infinity.ll b/llvm/test/Transforms/InstSimplify/known-never-infinity.ll
index d58edb4c91a75..0825cbd79a1e2 100644
--- a/llvm/test/Transforms/InstSimplify/known-never-infinity.ll
+++ b/llvm/test/Transforms/InstSimplify/known-never-infinity.ll
@@ -637,31 +637,53 @@ define i1 @isKnownNeverInfinity_minimum(double %x, double %y) {
   ret i1 %cmp
 }
 
-define i1 @isNotKnownNeverInfinity_minimum_lhs(double %x, double %y) {
-; CHECK-LABEL: define i1 @isNotKnownNeverInfinity_minimum_lhs
+define i1 @isNotKnownNeverPInfinity_minimum_lhs(double %x, double %y) {
+; CHECK-LABEL: define i1 @isNotKnownNeverPInfinity_minimum_lhs
+; CHECK-SAME: (double [[X:%.*]], double [[Y:%.*]]) {
+; CHECK-NEXT:    ret i1 true
+;
+  %ninf.y = fadd ninf double %y, 1.0
+  %op = call double @llvm.minimum.f64(double %x, double %ninf.y)
+  %cmp = fcmp une double %op, 0x7ff0000000000000
+  ret i1 %cmp
+}
+
+define i1 @isNotKnownNeverNInfinity_minimum_lhs(double %x, double %y) {
+; CHECK-LABEL: define i1 @isNotKnownNeverNInfinity_minimum_lhs
 ; CHECK-SAME: (double [[X:%.*]], double [[Y:%.*]]) {
 ; CHECK-NEXT:    [[NINF_Y:%.*]] = fadd ninf double [[Y]], 1.000000e+00
 ; CHECK-NEXT:    [[OP:%.*]] = call double @llvm.minimum.f64(double [[X]], double [[NINF_Y]])
-; CHECK-NEXT:    [[CMP:%.*]] = fcmp une double [[OP]], +inf
+; CHECK-NEXT:    [[CMP:%.*]] = fcmp une double [[OP]], -inf
 ; CHECK-NEXT:    ret i1 [[CMP]]
 ;
   %ninf.y = fadd ninf double %y, 1.0
   %op = call double @llvm.minimum.f64(double %x, double %ninf.y)
+  %cmp = fcmp une double %op, 0xfff0000000000000
+  ret i1 %cmp
+}
+
+define i1 @isNotKnownNeverPInfinity_minimum_rhs(double %x, double %y) {
+; CHECK-LABEL: define i1 @isNotKnownNeverPInfinity_minimum_rhs
+; CHECK-SAME: (double [[X:%.*]], double [[Y:%.*]]) {
+; CHECK-NEXT:    ret i1 true
+;
+  %ninf.x = fadd ninf double %x, 1.0
+  %op = call double @llvm.minimum.f64(double %ninf.x, double %y)
   %cmp = fcmp une double %op, 0x7ff0000000000000
   ret i1 %cmp
 }
 
-define i1 @isNotKnownNeverInfinity_minimum_rhs(double %x, double %y) {
-; CHECK-LABEL: define i1 @isNotKnownNeverInfinity_minimum_rhs
+define i1 @isNotKnownNeverNInfinity_minimum_rhs(double %x, double %y) {
+; CHECK-LABEL: define i1 @isNotKnownNeverNInfinity_minimum_rhs
 ; CHECK-SAME: (double [[X:%.*]], double [[Y:%.*]]) {
 ; CHECK-NEXT:    [[NINF_X:%.*]] = fadd ninf double [[X]], 1.000000e+00
 ; CHECK-NEXT:    [[OP:%.*]] = call double @llvm.minimum.f64(double [[NINF_X]], double [[Y]])
-; CHECK-NEXT:    [[CMP:%.*]] = fcmp une double [[OP]], +inf
+; CHECK-NEXT:    [[CMP:%.*]] = fcmp une double [[OP]], -inf
 ; CHECK-NEXT:    ret i1 [[CMP]]
 ;
   %ninf.x = fadd ninf double %x, 1.0
   %op = call double @llvm.minimum.f64(double %ninf.x, double %y)
-  %cmp = fcmp une double %op, 0x7ff0000000000000
+  %cmp = fcmp une double %op, 0xfff0000000000000
   ret i1 %cmp
 }
 
@@ -677,8 +699,8 @@ define i1 @isKnownNeverInfinity_maximum(double %x, double %y) {
   ret i1 %cmp
 }
 
-define i1 @isNotKnownNeverInfinity_maximum_lhs(double %x, double %y) {
-; CHECK-LABEL: define i1 @isNotKnownNeverInfinity_maximum_lhs
+define i1 @isNotKnownNeverPInfinity_maximum_lhs(double %x, double %y) {
+; CHECK-LABEL: define i1 @isNotKnownNeverPInfinity_maximum_lhs
 ; CHECK-SAME: (double [[X:%.*]], double [[Y:%.*]]) {
 ; CHECK-NEXT:    [[NINF_Y:%.*]] = fadd ninf double [[Y]], 1.000000e+00
 ; CHECK-NEXT:    [[OP:%.*]] = call double @llvm.maximum.f64(double [[X]], double [[NINF_Y]])
@@ -691,8 +713,19 @@ define i1 @isNotKnownNeverInfinity_maximum_lhs(double %x, double %y) {
   ret i1 %cmp
 }
 
-define i1 @isNotKnownNeverInfinity_maximum_rhs(double %x, double %y) {
-; CHECK-LABEL: define i1 @isNotKnownNeverInfinity_maximum_rhs
+define i1 @isNotKnownNeverNInfinity_maximum_lhs(double %x, double %y) {
+; CHECK-LABEL: define i1 @isNotKnownNeverNInfinity_maximum_lhs
+; CHECK-SAME: (double [[X:%.*]], double [[Y:%.*]]) {
+; CHECK-NEXT:    ret i1 true
+;
+  %ninf.y = fadd ninf double %y, 1.0
+  %op = call double @llvm.maximum.f64(double %x, double %ninf.y)
+  %cmp = fcmp une double %op, 0xfff0000000000000
+  ret i1 %cmp
+}
+
+define i1 @isNotKnownNeverPInfinity_maximum_rhs(double %x, double %y) {
+; CHECK-LABEL: define i1 @isNotKnownNeverPInfinity_maximum_rhs
 ; CHECK-SAME: (double [[X:%.*]], double [[Y:%.*]]) {
 ; CHECK-NEXT:    [[NINF_X:%.*]] = fadd ninf double [[X]], 1.000000e+00
 ; CHECK-NEXT:    [[OP:%.*]] = call double @llvm.maximum.f64(double [[NINF_X]], double [[Y]])
@@ -705,6 +738,17 @@ define i1 @isNotKnownNeverInfinity_maximum_rhs(double %x, double %y) {
   ret i1 %cmp
 }
 
+define i1 @isNotKnownNeverNInfinity_maximum_rhs(double %x, double %y) {
+; CHECK-LABEL: define i1 @isNotKnownNeverNInfinity_maximum_rhs
+; CHECK-SAME: (double [[X:%.*]], double [[Y:%.*]]) {
+; CHECK-NEXT:    ret i1 true
+;
+  %ninf.x = fadd ninf double %x, 1.0
+  %op = call double @llvm.maximum.f64(double %ninf.x, double %y)
+  %cmp = fcmp une double %op, 0xfff0000000000000
+  ret i1 %cmp
+}
+
 define i1 @isKnownNeverInfinity_sqrt(double %x) {
 ; CHECK-LABEL: define i1 @isKnownNeverInfinity_sqrt
 ; CHECK-SAME: (double [[X:%.*]]) {



More information about the llvm-commits mailing list