-
Notifications
You must be signed in to change notification settings - Fork 15.2k
simplifyBinaryIntrinsic: Return nan if snan is passed maxnum/minnum #158470
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
@llvm/pr-subscribers-backend-amdgpu @llvm/pr-subscribers-llvm-ir Author: YunQiang Su (wzssyqa) ChangesFixes: #138303 Full diff: https://github.com/llvm/llvm-project/pull/158470.diff 3 Files Affected:
diff --git a/llvm/include/llvm/IR/PatternMatch.h b/llvm/include/llvm/IR/PatternMatch.h
index 2cb78904dd799..10cf451091198 100644
--- a/llvm/include/llvm/IR/PatternMatch.h
+++ b/llvm/include/llvm/IR/PatternMatch.h
@@ -707,9 +707,13 @@ 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(); }
+};
/// 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>(); }
+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 7bff13d59528c..cff8f6dfe8117 100644
--- a/llvm/lib/Analysis/InstructionSimplify.cpp
+++ b/llvm/lib/Analysis/InstructionSimplify.cpp
@@ -6735,12 +6735,17 @@ Value *llvm::simplifyBinaryIntrinsic(Intrinsic::ID IID, Type *ReturnType,
bool PropagateNaN = IID == Intrinsic::minimum || IID == Intrinsic::maximum;
bool IsMin = IID == Intrinsic::minimum || IID == Intrinsic::minnum;
- // minnum(X, nan) -> X
- // maxnum(X, nan) -> X
+ // minnum(X, qnan) -> X
+ // maxnum(X, qnan) -> X
+ // minnum(X, snan) -> nan
+ // maxnum(X, snan) -> nan
// minimum(X, nan) -> nan
// maximum(X, nan) -> nan
- if (match(Op1, m_NaN()))
- return PropagateNaN ? propagateNaN(cast<Constant>(Op1)) : Op0;
+ if (match(Op1, m_NaN())) {
+ if (PropagateNaN || 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.
diff --git a/llvm/test/Transforms/EarlyCSE/commute.ll b/llvm/test/Transforms/EarlyCSE/commute.ll
index edafeccd3c8cc..3e1f9abb8bd99 100644
--- a/llvm/test/Transforms/EarlyCSE/commute.ll
+++ b/llvm/test/Transforms/EarlyCSE/commute.ll
@@ -830,6 +830,39 @@ define float @maxnum(float %a, float %b) {
ret float %r
}
+define float @maxnum_const_snan(float %x) {
+; CHECK-LABEL: @maxnum_const_snan(
+; CHECK-NEXT: ret float 0x7FFC000000000000
+;
+ %r = call float @llvm.minnum.f32(float %x, float 0x7FF4000000000000)
+ ret float %r
+}
+
+define double @minnum_const_snan(double %x) {
+; CHECK-LABEL: @minnum_const_snan(
+; CHECK-NEXT: ret double 0x7FFC000000000000
+;
+ %r = call double @llvm.minnum.f64(double %x, double 0x7FF4000000000000)
+ ret double %r
+}
+
+define float @maxnum_const_qnan(float %x) {
+; CHECK-LABEL: @maxnum_const_qnan(
+; CHECK-NEXT: ret float [[X:%.*]]
+;
+ %r = call float @llvm.minnum.f32(float %x, float 0x7FF8000000000000)
+ ret float %r
+}
+
+define double @minnum_const_qnan(double %x) {
+; CHECK-LABEL: @minnum_const_qnan(
+; CHECK-NEXT: ret double [[X:%.*]]
+;
+ %r = call double @llvm.minnum.f64(double %x, double 0x7FF8000000000000)
+ ret double %r
+}
+
+
define <2 x float> @minnum(<2 x float> %a, <2 x float> %b) {
; CHECK-LABEL: @minnum(
; CHECK-NEXT: [[X:%.*]] = call fast <2 x float> @llvm.minnum.v2f32(<2 x float> [[A:%.*]], <2 x float> [[B:%.*]])
|
@llvm/pr-subscribers-llvm-transforms Author: YunQiang Su (wzssyqa) ChangesFixes: #138303 Full diff: https://github.com/llvm/llvm-project/pull/158470.diff 3 Files Affected:
diff --git a/llvm/include/llvm/IR/PatternMatch.h b/llvm/include/llvm/IR/PatternMatch.h
index 2cb78904dd799..10cf451091198 100644
--- a/llvm/include/llvm/IR/PatternMatch.h
+++ b/llvm/include/llvm/IR/PatternMatch.h
@@ -707,9 +707,13 @@ 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(); }
+};
/// 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>(); }
+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 7bff13d59528c..cff8f6dfe8117 100644
--- a/llvm/lib/Analysis/InstructionSimplify.cpp
+++ b/llvm/lib/Analysis/InstructionSimplify.cpp
@@ -6735,12 +6735,17 @@ Value *llvm::simplifyBinaryIntrinsic(Intrinsic::ID IID, Type *ReturnType,
bool PropagateNaN = IID == Intrinsic::minimum || IID == Intrinsic::maximum;
bool IsMin = IID == Intrinsic::minimum || IID == Intrinsic::minnum;
- // minnum(X, nan) -> X
- // maxnum(X, nan) -> X
+ // minnum(X, qnan) -> X
+ // maxnum(X, qnan) -> X
+ // minnum(X, snan) -> nan
+ // maxnum(X, snan) -> nan
// minimum(X, nan) -> nan
// maximum(X, nan) -> nan
- if (match(Op1, m_NaN()))
- return PropagateNaN ? propagateNaN(cast<Constant>(Op1)) : Op0;
+ if (match(Op1, m_NaN())) {
+ if (PropagateNaN || 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.
diff --git a/llvm/test/Transforms/EarlyCSE/commute.ll b/llvm/test/Transforms/EarlyCSE/commute.ll
index edafeccd3c8cc..3e1f9abb8bd99 100644
--- a/llvm/test/Transforms/EarlyCSE/commute.ll
+++ b/llvm/test/Transforms/EarlyCSE/commute.ll
@@ -830,6 +830,39 @@ define float @maxnum(float %a, float %b) {
ret float %r
}
+define float @maxnum_const_snan(float %x) {
+; CHECK-LABEL: @maxnum_const_snan(
+; CHECK-NEXT: ret float 0x7FFC000000000000
+;
+ %r = call float @llvm.minnum.f32(float %x, float 0x7FF4000000000000)
+ ret float %r
+}
+
+define double @minnum_const_snan(double %x) {
+; CHECK-LABEL: @minnum_const_snan(
+; CHECK-NEXT: ret double 0x7FFC000000000000
+;
+ %r = call double @llvm.minnum.f64(double %x, double 0x7FF4000000000000)
+ ret double %r
+}
+
+define float @maxnum_const_qnan(float %x) {
+; CHECK-LABEL: @maxnum_const_qnan(
+; CHECK-NEXT: ret float [[X:%.*]]
+;
+ %r = call float @llvm.minnum.f32(float %x, float 0x7FF8000000000000)
+ ret float %r
+}
+
+define double @minnum_const_qnan(double %x) {
+; CHECK-LABEL: @minnum_const_qnan(
+; CHECK-NEXT: ret double [[X:%.*]]
+;
+ %r = call double @llvm.minnum.f64(double %x, double 0x7FF8000000000000)
+ ret double %r
+}
+
+
define <2 x float> @minnum(<2 x float> %a, <2 x float> %b) {
; CHECK-LABEL: @minnum(
; CHECK-NEXT: [[X:%.*]] = call fast <2 x float> @llvm.minnum.v2f32(<2 x float> [[A:%.*]], <2 x float> [[B:%.*]])
|
@llvm/pr-subscribers-llvm-analysis Author: YunQiang Su (wzssyqa) ChangesFixes: #138303 Full diff: https://github.com/llvm/llvm-project/pull/158470.diff 3 Files Affected:
diff --git a/llvm/include/llvm/IR/PatternMatch.h b/llvm/include/llvm/IR/PatternMatch.h
index 2cb78904dd799..10cf451091198 100644
--- a/llvm/include/llvm/IR/PatternMatch.h
+++ b/llvm/include/llvm/IR/PatternMatch.h
@@ -707,9 +707,13 @@ 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(); }
+};
/// 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>(); }
+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 7bff13d59528c..cff8f6dfe8117 100644
--- a/llvm/lib/Analysis/InstructionSimplify.cpp
+++ b/llvm/lib/Analysis/InstructionSimplify.cpp
@@ -6735,12 +6735,17 @@ Value *llvm::simplifyBinaryIntrinsic(Intrinsic::ID IID, Type *ReturnType,
bool PropagateNaN = IID == Intrinsic::minimum || IID == Intrinsic::maximum;
bool IsMin = IID == Intrinsic::minimum || IID == Intrinsic::minnum;
- // minnum(X, nan) -> X
- // maxnum(X, nan) -> X
+ // minnum(X, qnan) -> X
+ // maxnum(X, qnan) -> X
+ // minnum(X, snan) -> nan
+ // maxnum(X, snan) -> nan
// minimum(X, nan) -> nan
// maximum(X, nan) -> nan
- if (match(Op1, m_NaN()))
- return PropagateNaN ? propagateNaN(cast<Constant>(Op1)) : Op0;
+ if (match(Op1, m_NaN())) {
+ if (PropagateNaN || 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.
diff --git a/llvm/test/Transforms/EarlyCSE/commute.ll b/llvm/test/Transforms/EarlyCSE/commute.ll
index edafeccd3c8cc..3e1f9abb8bd99 100644
--- a/llvm/test/Transforms/EarlyCSE/commute.ll
+++ b/llvm/test/Transforms/EarlyCSE/commute.ll
@@ -830,6 +830,39 @@ define float @maxnum(float %a, float %b) {
ret float %r
}
+define float @maxnum_const_snan(float %x) {
+; CHECK-LABEL: @maxnum_const_snan(
+; CHECK-NEXT: ret float 0x7FFC000000000000
+;
+ %r = call float @llvm.minnum.f32(float %x, float 0x7FF4000000000000)
+ ret float %r
+}
+
+define double @minnum_const_snan(double %x) {
+; CHECK-LABEL: @minnum_const_snan(
+; CHECK-NEXT: ret double 0x7FFC000000000000
+;
+ %r = call double @llvm.minnum.f64(double %x, double 0x7FF4000000000000)
+ ret double %r
+}
+
+define float @maxnum_const_qnan(float %x) {
+; CHECK-LABEL: @maxnum_const_qnan(
+; CHECK-NEXT: ret float [[X:%.*]]
+;
+ %r = call float @llvm.minnum.f32(float %x, float 0x7FF8000000000000)
+ ret float %r
+}
+
+define double @minnum_const_qnan(double %x) {
+; CHECK-LABEL: @minnum_const_qnan(
+; CHECK-NEXT: ret double [[X:%.*]]
+;
+ %r = call double @llvm.minnum.f64(double %x, double 0x7FF8000000000000)
+ ret double %r
+}
+
+
define <2 x float> @minnum(<2 x float> %a, <2 x float> %b) {
; CHECK-LABEL: @minnum(
; CHECK-NEXT: [[X:%.*]] = call fast <2 x float> @llvm.minnum.v2f32(<2 x float> [[A:%.*]], <2 x float> [[B:%.*]])
|
@arsenm ping. |
Fixes: #138303