[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