[llvm] [InstSimplify] Optimize maximumnum and minimumnum (PR #139581)
via llvm-commits
llvm-commits at lists.llvm.org
Mon May 12 10:03:02 PDT 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-llvm-ir
Author: Lewis Crawford (LewisCrawford)
<details>
<summary>Changes</summary>
Add support for the new maximumnum and minimumnum intrinsics in various optimizations in InstSimplify.
Also, change the behavior of optimizing maxnum(sNaN, x) to simplify to qNaN instead of x to better match the LLVM IR spec, and add more tests for sNaN behavior for all 3 max/min intrinsic types.
---
Patch is 49.41 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/139581.diff
4 Files Affected:
- (modified) llvm/include/llvm/IR/PatternMatch.h (+15)
- (modified) llvm/lib/Analysis/InstructionSimplify.cpp (+35-14)
- (modified) llvm/lib/Analysis/ValueTracking.cpp (+2)
- (modified) llvm/test/Transforms/InstSimplify/fminmax-folds.ll (+873-132)
``````````diff
diff --git a/llvm/include/llvm/IR/PatternMatch.h b/llvm/include/llvm/IR/PatternMatch.h
index 6242a686e7bc0..c4d1bd095847d 100644
--- a/llvm/include/llvm/IR/PatternMatch.h
+++ b/llvm/include/llvm/IR/PatternMatch.h
@@ -707,10 +707,25 @@ m_SpecificInt_ICMP(ICmpInst::Predicate Predicate, const APInt &Threshold) {
struct is_nan {
bool isValue(const APFloat &C) const { return C.isNaN(); }
};
+
+struct is_snan {
+ bool isValue(const APFloat &C) const { return C.isSignaling(); }
+};
+
+struct is_qnan {
+ bool isValue(const APFloat &C) const { return C.isNaN() && !C.isSignaling(); }
+};
+
/// Match an arbitrary NaN constant. This includes quiet and signalling nans.
/// For vectors, this includes constants with undefined elements.
inline cstfp_pred_ty<is_nan> m_NaN() { return cstfp_pred_ty<is_nan>(); }
+/// Match quiet NaN constants, including vectors with undefined elements.
+inline cstfp_pred_ty<is_qnan> m_qNaN() { return cstfp_pred_ty<is_qnan>(); }
+
+/// Match signalling NaN constants, including vectors with undefined elements.
+inline cstfp_pred_ty<is_snan> m_sNaN() { return cstfp_pred_ty<is_snan>(); }
+
struct is_nonnan {
bool isValue(const APFloat &C) const { return !C.isNaN(); }
};
diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp
index 85e3be9cc45c3..49774bcb45585 100644
--- a/llvm/lib/Analysis/InstructionSimplify.cpp
+++ b/llvm/lib/Analysis/InstructionSimplify.cpp
@@ -6415,7 +6415,8 @@ static Value *foldMinMaxSharedOp(Intrinsic::ID IID, Value *Op0, Value *Op1) {
static Value *foldMinimumMaximumSharedOp(Intrinsic::ID IID, Value *Op0,
Value *Op1) {
assert((IID == Intrinsic::maxnum || IID == Intrinsic::minnum ||
- IID == Intrinsic::maximum || IID == Intrinsic::minimum) &&
+ IID == Intrinsic::maximum || IID == Intrinsic::minimum ||
+ IID == Intrinsic::maximumnum || IID == Intrinsic::minimumnum) &&
"Unsupported intrinsic");
auto *M0 = dyn_cast<IntrinsicInst>(Op0);
@@ -6711,7 +6712,16 @@ Value *llvm::simplifyBinaryIntrinsic(Intrinsic::ID IID, Type *ReturnType,
case Intrinsic::maxnum:
case Intrinsic::minnum:
case Intrinsic::maximum:
- case Intrinsic::minimum: {
+ case Intrinsic::minimum:
+ case Intrinsic::maximumnum:
+ case Intrinsic::minimumnum: {
+ // In several cases here, we deviate from exact IEEE 754 semantics
+ // to enable optimizations (as allowed by the LLVM IR spec).
+ //
+ // For instance, we often return one of the arguments unmodified instead of
+ // inserting an llvm.canonicalize to transform input sNaNs into qNaNs or to
+ // respect any FTZ semantics, and sometimes assume all NaN inputs are qNaNs.
+
// If the arguments are the same, this is a no-op.
if (Op0 == Op1)
return Op0;
@@ -6725,32 +6735,43 @@ Value *llvm::simplifyBinaryIntrinsic(Intrinsic::ID IID, Type *ReturnType,
return Op0;
bool PropagateNaN = IID == Intrinsic::minimum || IID == Intrinsic::maximum;
- bool IsMin = IID == Intrinsic::minimum || IID == Intrinsic::minnum;
-
- // minnum(X, nan) -> X
- // maxnum(X, nan) -> X
- // minimum(X, nan) -> nan
- // maximum(X, nan) -> nan
- if (match(Op1, m_NaN()))
- return PropagateNaN ? propagateNaN(cast<Constant>(Op1)) : Op0;
+ bool PropagateSNaN = IID == Intrinsic::minnum || IID == Intrinsic::maxnum;
+ bool IsMin = IID == Intrinsic::minimum || IID == Intrinsic::minnum ||
+ IID == Intrinsic::minimumnum;
+
+ // minnum(x, qnan) -> x
+ // maxnum(x, qnan) -> x
+ // minnum(x, snan) -> qnan
+ // maxnum(x, snan) -> qnan
+ // minimum(X, nan) -> qnan
+ // maximum(X, nan) -> qnan
+ if (match(Op1, m_NaN())) {
+ if (PropagateNaN || (PropagateSNaN && match(Op1, m_sNaN())))
+ return propagateNaN(cast<Constant>(Op1));
+ return Op0;
+ }
// In the following folds, inf can be replaced with the largest finite
// float, if the ninf flag is set.
const APFloat *C;
if (match(Op1, m_APFloat(C)) &&
(C->isInfinity() || (Call && Call->hasNoInfs() && C->isLargest()))) {
- // minnum(X, -inf) -> -inf
- // maxnum(X, +inf) -> +inf
+ // minnum(X, -inf) -> -inf (ignoring sNaN -> qNaN propagation)
+ // maxnum(X, +inf) -> +inf (ignoring sNaN -> qNaN propagation)
// minimum(X, -inf) -> -inf if nnan
// maximum(X, +inf) -> +inf if nnan
+ // minimumnum(X, -inf) -> -inf
+ // maximumnum(X, +inf) -> +inf
if (C->isNegative() == IsMin &&
(!PropagateNaN || (Call && Call->hasNoNaNs())))
return ConstantFP::get(ReturnType, *C);
// minnum(X, +inf) -> X if nnan
// maxnum(X, -inf) -> X if nnan
- // minimum(X, +inf) -> X
- // maximum(X, -inf) -> X
+ // minimum(X, +inf) -> X (ignoring quieting of sNaNs)
+ // maximum(X, -inf) -> X (ignoring quieting of sNaNs)
+ // maximumnum(X, -inf) -> X if nnan
+ // minimumnum(X, +inf) -> X if nnan
if (C->isNegative() != IsMin &&
(PropagateNaN || (Call && Call->hasNoNaNs())))
return Op0;
diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index 3d403531cea2f..c01ebbce15804 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -9310,6 +9310,8 @@ Intrinsic::ID llvm::getInverseMinMaxIntrinsic(Intrinsic::ID MinMaxID) {
case Intrinsic::minimum: return Intrinsic::maximum;
case Intrinsic::maxnum: return Intrinsic::minnum;
case Intrinsic::minnum: return Intrinsic::maxnum;
+ case Intrinsic::maximumnum: return Intrinsic::minimumnum;
+ case Intrinsic::minimumnum: return Intrinsic::maximumnum;
default: llvm_unreachable("Unexpected intrinsic");
}
}
diff --git a/llvm/test/Transforms/InstSimplify/fminmax-folds.ll b/llvm/test/Transforms/InstSimplify/fminmax-folds.ll
index fff6cfd8a3b4b..0510a713dba0b 100644
--- a/llvm/test/Transforms/InstSimplify/fminmax-folds.ll
+++ b/llvm/test/Transforms/InstSimplify/fminmax-folds.ll
@@ -54,6 +54,70 @@ define float @test_minimum_const_nan(float %x) {
ret float %r
}
+define float @test_maximumnum_const_nan(float %x) {
+; CHECK-LABEL: @test_maximumnum_const_nan(
+; CHECK-NEXT: ret float [[R:%.*]]
+;
+ %r = call float @llvm.maximumnum.f32(float %x, float 0x7fff000000000000)
+ ret float %r
+}
+
+define float @test_minimumnum_const_nan(float %x) {
+; CHECK-LABEL: @test_minimumnum_const_nan(
+; CHECK-NEXT: ret float [[R:%.*]]
+;
+ %r = call float @llvm.minimumnum.f32(float %x, float 0x7fff000000000000)
+ ret float %r
+}
+
+define float @test_minnum_const_snan(float %x) {
+; CHECK-LABEL: @test_minnum_const_snan(
+; CHECK-NEXT: ret float 0x7FFC000000000000
+;
+ %r = call float @llvm.minnum.f32(float %x, float 0x7ff4000000000000)
+ ret float %r
+}
+
+define float @test_maxnum_const_snan(float %x) {
+; CHECK-LABEL: @test_maxnum_const_snan(
+; CHECK-NEXT: ret float 0x7FFC000000000000
+;
+ %r = call float @llvm.maxnum.f32(float %x, float 0x7ff4000000000000)
+ ret float %r
+}
+
+define float @test_maximum_const_snan(float %x) {
+; CHECK-LABEL: @test_maximum_const_snan(
+; CHECK-NEXT: ret float 0x7FFC000000000000
+;
+ %r = call float @llvm.maximum.f32(float %x, float 0x7ff4000000000000)
+ ret float %r
+}
+
+define float @test_minimum_const_snan(float %x) {
+; CHECK-LABEL: @test_minimum_const_snan(
+; CHECK-NEXT: ret float 0x7FFC000000000000
+;
+ %r = call float @llvm.minimum.f32(float %x, float 0x7ff4000000000000)
+ ret float %r
+}
+
+define float @test_maximumnum_const_snan(float %x) {
+; CHECK-LABEL: @test_maximumnum_const_snan(
+; CHECK-NEXT: ret float [[X:%.*]]
+;
+ %r = call float @llvm.maximumnum.f32(float %x, float 0x7ff4000000000000)
+ ret float %r
+}
+
+define float @test_minimumnum_const_snan(float %x) {
+; CHECK-LABEL: @test_minimumnum_const_snan(
+; CHECK-NEXT: ret float [[X:%.*]]
+;
+ %r = call float @llvm.minimumnum.f32(float %x, float 0x7ff4000000000000)
+ ret float %r
+}
+
define float @test_minnum_const_inf(float %x) {
; CHECK-LABEL: @test_minnum_const_inf(
; CHECK-NEXT: [[R:%.*]] = call float @llvm.minnum.f32(float [[X:%.*]], float 0x7FF0000000000000)
@@ -88,6 +152,23 @@ define float @test_minimum_const_inf(float %x) {
ret float %r
}
+define float @test_maximumnum_const_inf(float %x) {
+; CHECK-LABEL: @test_maximumnum_const_inf(
+; CHECK-NEXT: ret float 0x7FF0000000000000
+;
+ %r = call float @llvm.maximumnum.f32(float %x, float 0x7ff0000000000000)
+ ret float %r
+}
+
+define float @test_minimumnum_const_inf(float %x) {
+; CHECK-LABEL: @test_minimumnum_const_inf(
+; CHECK-NEXT: [[R:%.*]] = call float @llvm.minimumnum.f32(float [[X:%.*]], float 0x7FF0000000000000)
+; CHECK-NEXT: ret float [[R]]
+;
+ %r = call float @llvm.minimumnum.f32(float %x, float 0x7ff0000000000000)
+ ret float %r
+}
+
define float @test_minnum_const_neg_inf(float %x) {
; CHECK-LABEL: @test_minnum_const_neg_inf(
; CHECK-NEXT: ret float 0xFFF0000000000000
@@ -122,6 +203,23 @@ define float @test_minimum_const_neg_inf(float %x) {
ret float %r
}
+define float @test_maximumnum_const_neg_inf(float %x) {
+; CHECK-LABEL: @test_maximumnum_const_neg_inf(
+; CHECK-NEXT: [[X:%.*]] = call float @llvm.maximumnum.f32(float [[X1:%.*]], float 0xFFF0000000000000)
+; CHECK-NEXT: ret float [[X]]
+;
+ %r = call float @llvm.maximumnum.f32(float %x, float 0xfff0000000000000)
+ ret float %r
+}
+
+define float @test_minimumnum_const_neg_inf(float %x) {
+; CHECK-LABEL: @test_minimumnum_const_neg_inf(
+; CHECK-NEXT: ret float 0xFFF0000000000000
+;
+ %r = call float @llvm.minimumnum.f32(float %x, float 0xfff0000000000000)
+ ret float %r
+}
+
define float @test_minnum_const_inf_nnan(float %x) {
; CHECK-LABEL: @test_minnum_const_inf_nnan(
; CHECK-NEXT: ret float [[X:%.*]]
@@ -154,6 +252,22 @@ define float @test_minimum_const_inf_nnan(float %x) {
ret float %r
}
+define float @test_maximumnum_const_inf_nnan(float %x) {
+; CHECK-LABEL: @test_maximumnum_const_inf_nnan(
+; CHECK-NEXT: ret float 0x7FF0000000000000
+;
+ %r = call nnan float @llvm.maximumnum.f32(float %x, float 0x7ff0000000000000)
+ ret float %r
+}
+
+define float @test_minimumnum_const_inf_nnan(float %x) {
+; CHECK-LABEL: @test_minimumnum_const_inf_nnan(
+; CHECK-NEXT: ret float [[X:%.*]]
+;
+ %r = call nnan float @llvm.minimumnum.f32(float %x, float 0x7ff0000000000000)
+ ret float %r
+}
+
define float @test_minnum_const_inf_nnan_comm(float %x) {
; CHECK-LABEL: @test_minnum_const_inf_nnan_comm(
; CHECK-NEXT: ret float [[X:%.*]]
@@ -186,6 +300,22 @@ define float @test_minimum_const_inf_nnan_comm(float %x) {
ret float %r
}
+define float @test_maximumnum_const_inf_nnan_comm(float %x) {
+; CHECK-LABEL: @test_maximumnum_const_inf_nnan_comm(
+; CHECK-NEXT: ret float 0x7FF0000000000000
+;
+ %r = call nnan float @llvm.maximumnum.f32(float 0x7ff0000000000000, float %x)
+ ret float %r
+}
+
+define float @test_minimumnum_const_inf_nnan_comm(float %x) {
+; CHECK-LABEL: @test_minimumnum_const_inf_nnan_comm(
+; CHECK-NEXT: ret float [[X:%.*]]
+;
+ %r = call nnan float @llvm.minimumnum.f32(float 0x7ff0000000000000, float %x)
+ ret float %r
+}
+
define <2 x float> @test_minnum_const_inf_nnan_comm_vec(<2 x float> %x) {
; CHECK-LABEL: @test_minnum_const_inf_nnan_comm_vec(
; CHECK-NEXT: ret <2 x float> [[X:%.*]]
@@ -218,6 +348,22 @@ define <2 x float> @test_minimum_const_inf_nnan_comm_vec(<2 x float> %x) {
ret <2 x float> %r
}
+define <2 x float> @test_maximumnum_const_inf_nnan_comm_vec(<2 x float> %x) {
+; CHECK-LABEL: @test_maximumnum_const_inf_nnan_comm_vec(
+; CHECK-NEXT: ret <2 x float> splat (float 0x7FF0000000000000)
+;
+ %r = call nnan <2 x float> @llvm.maximumnum.v2f32(<2 x float> <float 0x7ff0000000000000, float 0x7ff0000000000000>, <2 x float> %x)
+ ret <2 x float> %r
+}
+
+define <2 x float> @test_minimumnum_const_inf_nnan_comm_vec(<2 x float> %x) {
+; CHECK-LABEL: @test_minimumnum_const_inf_nnan_comm_vec(
+; CHECK-NEXT: ret <2 x float> [[X:%.*]]
+;
+ %r = call nnan <2 x float> @llvm.minimumnum.v2f32(<2 x float> <float 0x7ff0000000000000, float 0x7ff0000000000000>, <2 x float> %x)
+ ret <2 x float> %r
+}
+
define float @test_minnum_const_neg_inf_nnan(float %x) {
; CHECK-LABEL: @test_minnum_const_neg_inf_nnan(
; CHECK-NEXT: ret float 0xFFF0000000000000
@@ -250,6 +396,22 @@ define float @test_minimum_const_neg_inf_nnan(float %x) {
ret float %r
}
+define float @test_maximumnum_const_neg_inf_nnan(float %x) {
+; CHECK-LABEL: @test_maximumnum_const_neg_inf_nnan(
+; CHECK-NEXT: ret float [[X:%.*]]
+;
+ %r = call nnan float @llvm.maximumnum.f32(float %x, float 0xfff0000000000000)
+ ret float %r
+}
+
+define float @test_minimumnum_const_neg_inf_nnan(float %x) {
+; CHECK-LABEL: @test_minimumnum_const_neg_inf_nnan(
+; CHECK-NEXT: ret float 0xFFF0000000000000
+;
+ %r = call nnan float @llvm.minimumnum.f32(float %x, float 0xfff0000000000000)
+ ret float %r
+}
+
define float @test_minnum_const_max(float %x) {
; CHECK-LABEL: @test_minnum_const_max(
; CHECK-NEXT: [[R:%.*]] = call float @llvm.minnum.f32(float [[X:%.*]], float 0x47EFFFFFE0000000)
@@ -286,6 +448,24 @@ define float @test_minimum_const_max(float %x) {
ret float %r
}
+define float @test_maximumnum_const_max(float %x) {
+; CHECK-LABEL: @test_maximumnum_const_max(
+; CHECK-NEXT: [[R:%.*]] = call float @llvm.maximumnum.f32(float [[X:%.*]], float 0x47EFFFFFE0000000)
+; CHECK-NEXT: ret float [[R]]
+;
+ %r = call float @llvm.maximumnum.f32(float %x, float 0x47efffffe0000000)
+ ret float %r
+}
+
+define float @test_minimumnum_const_max(float %x) {
+; CHECK-LABEL: @test_minimumnum_const_max(
+; CHECK-NEXT: [[R:%.*]] = call float @llvm.minimumnum.f32(float [[X:%.*]], float 0x47EFFFFFE0000000)
+; CHECK-NEXT: ret float [[R]]
+;
+ %r = call float @llvm.minimumnum.f32(float %x, float 0x47efffffe0000000)
+ ret float %r
+}
+
define float @test_minnum_const_neg_max(float %x) {
; CHECK-LABEL: @test_minnum_const_neg_max(
; CHECK-NEXT: [[R:%.*]] = call float @llvm.minnum.f32(float [[X:%.*]], float 0xC7EFFFFFE0000000)
@@ -322,6 +502,24 @@ define float @test_minimum_const_neg_max(float %x) {
ret float %r
}
+define float @test_maximumnum_const_neg_max(float %x) {
+; CHECK-LABEL: @test_maximumnum_const_neg_max(
+; CHECK-NEXT: [[R:%.*]] = call float @llvm.maximumnum.f32(float [[X:%.*]], float 0xC7EFFFFFE0000000)
+; CHECK-NEXT: ret float [[R]]
+;
+ %r = call float @llvm.maximumnum.f32(float %x, float 0xc7efffffe0000000)
+ ret float %r
+}
+
+define float @test_minimumnum_const_neg_max(float %x) {
+; CHECK-LABEL: @test_minimumnum_const_neg_max(
+; CHECK-NEXT: [[R:%.*]] = call float @llvm.minimumnum.f32(float [[X:%.*]], float 0xC7EFFFFFE0000000)
+; CHECK-NEXT: ret float [[R]]
+;
+ %r = call float @llvm.minimumnum.f32(float %x, float 0xc7efffffe0000000)
+ ret float %r
+}
+
define float @test_minnum_const_max_ninf(float %x) {
; CHECK-LABEL: @test_minnum_const_max_ninf(
; CHECK-NEXT: [[R:%.*]] = call ninf float @llvm.minnum.f32(float [[X:%.*]], float 0x47EFFFFFE0000000)
@@ -356,6 +554,23 @@ define float @test_minimum_const_max_ninf(float %x) {
ret float %r
}
+define float @test_maximumnum_const_max_ninf(float %x) {
+; CHECK-LABEL: @test_maximumnum_const_max_ninf(
+; CHECK-NEXT: ret float 0x47EFFFFFE0000000
+;
+ %r = call ninf float @llvm.maximumnum.f32(float %x, float 0x47efffffe0000000)
+ ret float %r
+}
+
+define float @test_minimumnum_const_max_ninf(float %x) {
+; CHECK-LABEL: @test_minimumnum_const_max_ninf(
+; CHECK-NEXT: [[R:%.*]] = call ninf float @llvm.minimumnum.f32(float [[X:%.*]], float 0x47EFFFFFE0000000)
+; CHECK-NEXT: ret float [[R]]
+;
+ %r = call ninf float @llvm.minimumnum.f32(float %x, float 0x47efffffe0000000)
+ ret float %r
+}
+
define float @test_minnum_const_neg_max_ninf(float %x) {
; CHECK-LABEL: @test_minnum_const_neg_max_ninf(
; CHECK-NEXT: ret float 0xC7EFFFFFE0000000
@@ -390,6 +605,23 @@ define float @test_minimum_const_neg_max_ninf(float %x) {
ret float %r
}
+define float @test_maximumnum_const_neg_max_ninf(float %x) {
+; CHECK-LABEL: @test_maximumnum_const_neg_max_ninf(
+; CHECK-NEXT: [[X:%.*]] = call ninf float @llvm.maximumnum.f32(float [[X1:%.*]], float 0xC7EFFFFFE0000000)
+; CHECK-NEXT: ret float [[X]]
+;
+ %r = call ninf float @llvm.maximumnum.f32(float %x, float 0xc7efffffe0000000)
+ ret float %r
+}
+
+define float @test_minimumnum_const_neg_max_ninf(float %x) {
+; CHECK-LABEL: @test_minimumnum_const_neg_max_ninf(
+; CHECK-NEXT: ret float 0xC7EFFFFFE0000000
+;
+ %r = call ninf float @llvm.minimumnum.f32(float %x, float 0xc7efffffe0000000)
+ ret float %r
+}
+
define float @test_minnum_const_max_nnan_ninf(float %x) {
; CHECK-LABEL: @test_minnum_const_max_nnan_ninf(
; CHECK-NEXT: ret float [[X:%.*]]
@@ -422,6 +654,22 @@ define float @test_minimum_const_max_nnan_ninf(float %x) {
ret float %r
}
+define float @test_maximumnum_const_max_nnan_ninf(float %x) {
+; CHECK-LABEL: @test_maximumnum_const_max_nnan_ninf(
+; CHECK-NEXT: ret float 0x47EFFFFFE0000000
+;
+ %r = call nnan ninf float @llvm.maximumnum.f32(float %x, float 0x47efffffe0000000)
+ ret float %r
+}
+
+define float @test_minimumnum_const_max_nnan_ninf(float %x) {
+; CHECK-LABEL: @test_minimumnum_const_max_nnan_ninf(
+; CHECK-NEXT: ret float [[X:%.*]]
+;
+ %r = call nnan ninf float @llvm.minimumnum.f32(float %x, float 0x47efffffe0000000)
+ ret float %r
+}
+
define float @test_minnum_const_neg_max_nnan_ninf(float %x) {
; CHECK-LABEL: @test_minnum_const_neg_max_nnan_ninf(
; CHECK-NEXT: ret float 0xC7EFFFFFE0000000
@@ -454,8 +702,24 @@ define float @test_minimum_const_neg_max_nnan_ninf(float %x) {
ret float %r
}
+define float @test_maximumnum_const_neg_max_nnan_ninf(float %x) {
+; CHECK-LABEL: @test_maximumnum_const_neg_max_nnan_ninf(
+; CHECK-NEXT: ret float [[X:%.*]]
+;
+ %r = call nnan ninf float @llvm.maximumnum.f32(float %x, float 0xc7efffffe0000000)
+ ret float %r
+}
+
+define float @test_minimumnum_const_neg_max_nnan_ninf(float %x) {
+; CHECK-LABEL: @test_minimumnum_const_neg_max_nnan_ninf(
+; CHECK-NEXT: ret float 0xC7EFFFFFE0000000
+;
+ %r = call nnan ninf float @llvm.minimumnum.f32(float %x, float 0xc7efffffe0000000)
+ ret float %r
+}
+
; From the LangRef for minnum/maxnum:
-; "If either operand is a NaN, returns the other non-NaN operand."
+; "If either operand is a qNaN, returns the other non-NaN operand. Returns NaN only if both operands are NaN or if either operand is sNaN."
define double @maxnum_nan_op0(double %x) {
; CHECK-LABEL: @maxnum_nan_op0(
@@ -521,115 +785,99 @@ define <2 x double> @minnum_nan_op1_vec(<2 x double> %x) {
ret <2 x double> %r
}
-define float @maxnum_undef_op1(float %x) {
-; CHECK-LABEL: @maxnum_undef_op1(
-; CHECK-NEXT: ret float [[X:%.*]]
-;
- %val = call float @llvm.maxnum.f32(float %x, float undef)
- ret float %val
-}
-
-define float @maxnum_poison_op1(float %x) {
-; CHECK-LABEL: @maxnum_poison_op1(
-; CHECK-NEXT: ret float [[X:%.*]]
-;
- %val = call float @llvm.maxnum.f32(float %x, float poison)
- ret float %val
-}
-
-define float @maxnum_undef_op0(float %x) {
-; CHECK-LABEL: @maxnum_undef_op0(
-; CHECK-NEXT: ret float [[X:%.*]]
+define double @maxnum_snan_op0(double %x) {
+; CHECK-LABEL: @maxnum_snan_op0(
+; CHECK-NEXT: ret double 0x7FFC000000000000
;
- %val = call float @llvm.maxnum.f32(float undef, float %x)
- ret float %val
+ %r = call double @llvm.maxnum.f64(double 0x7ff4000000000000, double %x)
+ ret double %r
}
-define float @maxnum_poison_op0(float %x) {
-; CHECK-LABEL: @maxnum_poison_op0(
-; CHECK-NEXT: ret float [[X:%.*]]
+define double @maxnum_snan_op1(double %x) {
+; CHECK-LABEL: @maxnum_snan_op1(
+; CHECK-NEXT: ret double 0x7FFC00000000DEAD
;
- %val = call float @llvm.maxnum.f32(float poison, float %x)
- ret float %val
+ %r = call double @llvm.maxnum.f64(double %x, double 0x7ff400000000dead)
+ ret double %r
}
-define float @minnum_undef_op1(float %x) {
-; CHECK-LABEL: @minnum_undef_op1(
-; CHECK-NEXT: ret float [[X:%.*]]
+define double @minnum_snan_op0(double %x) {
+; CHECK-LABEL: @minnum_snan_op0(
+; CHECK-NEXT: ret double 0x7FFC000DEAD00000
;
- %val = call float @llvm.minnum.f32(float %x, float undef)
- ret float %val
+ %r = call double @llvm.minnum.f64(double 0x7ff4000dead00000, d...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/139581
More information about the llvm-commits
mailing list