[llvm] 6ed48eb - ValueTracking: Recognize fpclass clamping select patterns
Matt Arsenault via llvm-commits
llvm-commits at lists.llvm.org
Wed Jul 12 10:14:14 PDT 2023
Author: Matt Arsenault
Date: 2023-07-12T13:14:05-04:00
New Revision: 6ed48ebf2e80c3ada88b95c0122ead24c4cd4f29
URL: https://github.com/llvm/llvm-project/commit/6ed48ebf2e80c3ada88b95c0122ead24c4cd4f29
DIFF: https://github.com/llvm/llvm-project/commit/6ed48ebf2e80c3ada88b95c0122ead24c4cd4f29.diff
LOG: ValueTracking: Recognize fpclass clamping select patterns
Improve computeKnownFPClass select handling to cover the case where
the condition performs a class test. This allows us to recognize
no-nans in cases like:
%not.nan = fcmp ord float %x, 0.0
%select = select i1 %not.nan, float %x, float 0.0
Math library code has similar edge case filtering on the inputs and
final results.
https://reviews.llvm.org/D153089
Added:
Modified:
llvm/lib/Analysis/ValueTracking.cpp
llvm/test/Transforms/Attributor/nofpclass-select.ll
llvm/test/Transforms/InstCombine/minmax-fp.ll
Removed:
################################################################################
diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index 57d3d8b98287c3..37c93462ce8ad9 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -4306,11 +4306,51 @@ void computeKnownFPClass(const Value *V, const APInt &DemandedElts,
break;
}
case Instruction::Select: {
+ Value *Cond = Op->getOperand(0);
+ Value *LHS = Op->getOperand(1);
+ Value *RHS = Op->getOperand(2);
+
+ FPClassTest FilterLHS = fcAllFlags;
+ FPClassTest FilterRHS = fcAllFlags;
+
+ Value *TestedValue = nullptr;
+ FPClassTest TestedMask = fcNone;
+ uint64_t ClassVal = 0;
+ const Function *F = cast<Instruction>(Op)->getFunction();
+ CmpInst::Predicate Pred;
+ Value *CmpLHS, *CmpRHS;
+ if (F && match(Cond, m_FCmp(Pred, m_Value(CmpLHS), m_Value(CmpRHS)))) {
+ // If the select filters out a value based on the class, it no longer
+ // participates in the class of the result
+
+ // TODO: In some degenerate cases we can infer something if we try again
+ // without looking through sign operations.
+ bool LookThroughFAbsFNeg = CmpLHS != LHS && CmpLHS != RHS;
+ std::tie(TestedValue, TestedMask) =
+ fcmpToClassTest(Pred, *F, CmpLHS, CmpRHS, LookThroughFAbsFNeg);
+ } else if (match(Cond,
+ m_Intrinsic<Intrinsic::is_fpclass>(
+ m_Value(TestedValue), m_ConstantInt(ClassVal)))) {
+ TestedMask = static_cast<FPClassTest>(ClassVal);
+ }
+
+ if (TestedValue == LHS) {
+ // match !isnan(x) ? x : y
+ FilterLHS = TestedMask;
+ } else if (TestedValue == RHS) {
+ // match !isnan(x) ? y : x
+ FilterRHS = ~TestedMask;
+ }
+
KnownFPClass Known2;
- computeKnownFPClass(Op->getOperand(1), DemandedElts, InterestedClasses,
- Known, Depth + 1, Q);
- computeKnownFPClass(Op->getOperand(2), DemandedElts, InterestedClasses,
+ computeKnownFPClass(LHS, DemandedElts, InterestedClasses & FilterLHS, Known,
+ Depth + 1, Q);
+ Known.KnownFPClasses &= FilterLHS;
+
+ computeKnownFPClass(RHS, DemandedElts, InterestedClasses & FilterRHS,
Known2, Depth + 1, Q);
+ Known2.KnownFPClasses &= FilterRHS;
+
Known |= Known2;
break;
}
diff --git a/llvm/test/Transforms/Attributor/nofpclass-select.ll b/llvm/test/Transforms/Attributor/nofpclass-select.ll
index c74353971dddc3..86be5ac7145fa4 100644
--- a/llvm/test/Transforms/Attributor/nofpclass-select.ll
+++ b/llvm/test/Transforms/Attributor/nofpclass-select.ll
@@ -69,11 +69,11 @@ define float @ret_select_nonan__noinf_nonan(i1 %cond, float nofpclass(nan) %arg0
; Clamp nan to 0 pattern
define float @ret_select_clamp_nan_to_zero_uno(float %arg) {
-; CHECK-LABEL: define float @ret_select_clamp_nan_to_zero_uno
+; CHECK-LABEL: define nofpclass(nan) float @ret_select_clamp_nan_to_zero_uno
; CHECK-SAME: (float [[ARG:%.*]]) #[[ATTR1]] {
; CHECK-NEXT: [[IS_NAN:%.*]] = fcmp uno float [[ARG]], 0.000000e+00
; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[IS_NAN]], float 0.000000e+00, float [[ARG]]
-; CHECK-NEXT: [[FENCE:%.*]] = call float @llvm.arithmetic.fence.f32(float [[SELECT]]) #[[ATTR2]]
+; CHECK-NEXT: [[FENCE:%.*]] = call nofpclass(nan) float @llvm.arithmetic.fence.f32(float [[SELECT]]) #[[ATTR2]]
; CHECK-NEXT: ret float [[FENCE]]
;
%is.nan = fcmp uno float %arg, 0.0
@@ -83,11 +83,11 @@ define float @ret_select_clamp_nan_to_zero_uno(float %arg) {
}
define float @ret_select_clamp_nan_to_zero_ord(float %arg) {
-; CHECK-LABEL: define float @ret_select_clamp_nan_to_zero_ord
+; CHECK-LABEL: define nofpclass(nan) float @ret_select_clamp_nan_to_zero_ord
; CHECK-SAME: (float [[ARG:%.*]]) #[[ATTR1]] {
; CHECK-NEXT: [[NOT_NAN:%.*]] = fcmp ord float [[ARG]], 0.000000e+00
; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[NOT_NAN]], float [[ARG]], float 0.000000e+00
-; CHECK-NEXT: [[FENCE:%.*]] = call float @llvm.arithmetic.fence.f32(float [[SELECT]]) #[[ATTR2]]
+; CHECK-NEXT: [[FENCE:%.*]] = call nofpclass(nan) float @llvm.arithmetic.fence.f32(float [[SELECT]]) #[[ATTR2]]
; CHECK-NEXT: ret float [[FENCE]]
;
%not.nan = fcmp ord float %arg, 0.0
@@ -97,11 +97,11 @@ define float @ret_select_clamp_nan_to_zero_ord(float %arg) {
}
define float @ret_select_clamp_onlynans(float %arg) {
-; CHECK-LABEL: define float @ret_select_clamp_onlynans
+; CHECK-LABEL: define nofpclass(inf zero sub norm) float @ret_select_clamp_onlynans
; CHECK-SAME: (float [[ARG:%.*]]) #[[ATTR1]] {
; CHECK-NEXT: [[NOT_NAN:%.*]] = fcmp ord float [[ARG]], 0.000000e+00
; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[NOT_NAN]], float 0x7FF8000000000000, float [[ARG]]
-; CHECK-NEXT: [[FENCE:%.*]] = call float @llvm.arithmetic.fence.f32(float [[SELECT]]) #[[ATTR2]]
+; CHECK-NEXT: [[FENCE:%.*]] = call nofpclass(inf zero sub norm) float @llvm.arithmetic.fence.f32(float [[SELECT]]) #[[ATTR2]]
; CHECK-NEXT: ret float [[FENCE]]
;
%not.nan = fcmp ord float %arg, 0.0
@@ -111,12 +111,12 @@ define float @ret_select_clamp_onlynans(float %arg) {
}
define float @clamp_nonfinite_to_normal_olt(float %arg) {
-; CHECK-LABEL: define float @clamp_nonfinite_to_normal_olt
+; CHECK-LABEL: define nofpclass(nan inf) float @clamp_nonfinite_to_normal_olt
; CHECK-SAME: (float [[ARG:%.*]]) #[[ATTR1]] {
; CHECK-NEXT: [[FABS:%.*]] = call float @llvm.fabs.f32(float [[ARG]]) #[[ATTR2]]
; CHECK-NEXT: [[IS_FINITE:%.*]] = fcmp olt float [[FABS]], 0x7FF0000000000000
; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[IS_FINITE]], float [[ARG]], float 1.024000e+03
-; CHECK-NEXT: [[FENCE:%.*]] = call float @llvm.arithmetic.fence.f32(float [[SELECT]]) #[[ATTR2]]
+; CHECK-NEXT: [[FENCE:%.*]] = call nofpclass(nan inf) float @llvm.arithmetic.fence.f32(float [[SELECT]]) #[[ATTR2]]
; CHECK-NEXT: ret float [[FENCE]]
;
%fabs = call float @llvm.fabs.f32(float %arg)
@@ -127,12 +127,12 @@ define float @clamp_nonfinite_to_normal_olt(float %arg) {
}
define float @clamp_eq_inf_to_pnormal(float %arg) {
-; CHECK-LABEL: define float @clamp_eq_inf_to_pnormal
+; CHECK-LABEL: define nofpclass(inf) float @clamp_eq_inf_to_pnormal
; CHECK-SAME: (float [[ARG:%.*]]) #[[ATTR1]] {
; CHECK-NEXT: [[FABS:%.*]] = call float @llvm.fabs.f32(float [[ARG]]) #[[ATTR2]]
; CHECK-NEXT: [[IS_INF:%.*]] = fcmp oeq float [[FABS]], 0x7FF0000000000000
; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[IS_INF]], float 1.024000e+03, float [[ARG]]
-; CHECK-NEXT: [[FENCE:%.*]] = call float @llvm.arithmetic.fence.f32(float [[SELECT]]) #[[ATTR2]]
+; CHECK-NEXT: [[FENCE:%.*]] = call nofpclass(inf) float @llvm.arithmetic.fence.f32(float [[SELECT]]) #[[ATTR2]]
; CHECK-NEXT: ret float [[FENCE]]
;
%fabs = call float @llvm.fabs.f32(float %arg)
@@ -143,11 +143,11 @@ define float @clamp_eq_inf_to_pnormal(float %arg) {
}
define float @clamp_eq_pinf_to_pnormal(float %arg) {
-; CHECK-LABEL: define float @clamp_eq_pinf_to_pnormal
+; CHECK-LABEL: define nofpclass(pinf) float @clamp_eq_pinf_to_pnormal
; CHECK-SAME: (float [[ARG:%.*]]) #[[ATTR1]] {
; CHECK-NEXT: [[IS_INF:%.*]] = fcmp oeq float [[ARG]], 0x7FF0000000000000
; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[IS_INF]], float 1.024000e+03, float [[ARG]]
-; CHECK-NEXT: [[FENCE:%.*]] = call float @llvm.arithmetic.fence.f32(float [[SELECT]]) #[[ATTR2]]
+; CHECK-NEXT: [[FENCE:%.*]] = call nofpclass(pinf) float @llvm.arithmetic.fence.f32(float [[SELECT]]) #[[ATTR2]]
; CHECK-NEXT: ret float [[FENCE]]
;
%is.inf = fcmp oeq float %arg, 0x7FF0000000000000
@@ -157,11 +157,11 @@ define float @clamp_eq_pinf_to_pnormal(float %arg) {
}
define float @clamp_eq_ninf_to_negnormal(float %arg) {
-; CHECK-LABEL: define float @clamp_eq_ninf_to_negnormal
+; CHECK-LABEL: define nofpclass(ninf) float @clamp_eq_ninf_to_negnormal
; CHECK-SAME: (float [[ARG:%.*]]) #[[ATTR1]] {
; CHECK-NEXT: [[IS_INF:%.*]] = fcmp oeq float [[ARG]], 0xFFF0000000000000
; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[IS_INF]], float -1.024000e+03, float [[ARG]]
-; CHECK-NEXT: [[FENCE:%.*]] = call float @llvm.arithmetic.fence.f32(float [[SELECT]]) #[[ATTR2]]
+; CHECK-NEXT: [[FENCE:%.*]] = call nofpclass(ninf) float @llvm.arithmetic.fence.f32(float [[SELECT]]) #[[ATTR2]]
; CHECK-NEXT: ret float [[FENCE]]
;
%is.inf = fcmp oeq float %arg, 0xFFF0000000000000
@@ -171,12 +171,12 @@ define float @clamp_eq_ninf_to_negnormal(float %arg) {
}
define float @clamp_eq_inf_to_nan(float %arg) {
-; CHECK-LABEL: define float @clamp_eq_inf_to_nan
+; CHECK-LABEL: define nofpclass(inf) float @clamp_eq_inf_to_nan
; CHECK-SAME: (float [[ARG:%.*]]) #[[ATTR1]] {
; CHECK-NEXT: [[FABS:%.*]] = call float @llvm.fabs.f32(float [[ARG]]) #[[ATTR2]]
; CHECK-NEXT: [[IS_INF:%.*]] = fcmp oeq float [[FABS]], 0x7FF0000000000000
; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[IS_INF]], float 0x7FF8000000000000, float [[ARG]]
-; CHECK-NEXT: [[FENCE:%.*]] = call float @llvm.arithmetic.fence.f32(float [[SELECT]]) #[[ATTR2]]
+; CHECK-NEXT: [[FENCE:%.*]] = call nofpclass(inf) float @llvm.arithmetic.fence.f32(float [[SELECT]]) #[[ATTR2]]
; CHECK-NEXT: ret float [[FENCE]]
;
%fabs = call float @llvm.fabs.f32(float %arg)
@@ -201,12 +201,12 @@ define float @ret_select_clamp_nan_to_zero_uno_returned_
diff erent_arg(float %arg
}
define float @isfinite_select_fabs_val_0(float %arg) {
-; CHECK-LABEL: define nofpclass(ninf nzero nsub nnorm) float @isfinite_select_fabs_val_0
+; CHECK-LABEL: define nofpclass(nan inf nzero nsub nnorm) float @isfinite_select_fabs_val_0
; CHECK-SAME: (float [[ARG:%.*]]) #[[ATTR1]] {
; CHECK-NEXT: [[FABS:%.*]] = call float @llvm.fabs.f32(float [[ARG]]) #[[ATTR2]]
; CHECK-NEXT: [[IS_FINITE:%.*]] = fcmp olt float [[FABS]], 0x7FF0000000000000
; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[IS_FINITE]], float [[FABS]], float 1.024000e+03
-; CHECK-NEXT: [[FENCE:%.*]] = call nofpclass(ninf nzero nsub nnorm) float @llvm.arithmetic.fence.f32(float [[SELECT]]) #[[ATTR2]]
+; CHECK-NEXT: [[FENCE:%.*]] = call nofpclass(nan inf nzero nsub nnorm) float @llvm.arithmetic.fence.f32(float [[SELECT]]) #[[ATTR2]]
; CHECK-NEXT: ret float [[FENCE]]
;
%fabs = call float @llvm.fabs.f32(float %arg)
@@ -217,12 +217,12 @@ define float @isfinite_select_fabs_val_0(float %arg) {
}
define float @isfinite_select_fabs_val_1(float %arg) {
-; CHECK-LABEL: define nofpclass(ninf nzero nsub nnorm) float @isfinite_select_fabs_val_1
+; CHECK-LABEL: define nofpclass(nan inf nzero nsub nnorm) float @isfinite_select_fabs_val_1
; CHECK-SAME: (float [[ARG:%.*]]) #[[ATTR1]] {
; CHECK-NEXT: [[FABS:%.*]] = call float @llvm.fabs.f32(float [[ARG]]) #[[ATTR2]]
; CHECK-NEXT: [[NOT_IS_FINITE:%.*]] = fcmp uge float [[FABS]], 0x3810000000000000
; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[NOT_IS_FINITE]], float 1.024000e+03, float [[FABS]]
-; CHECK-NEXT: [[FENCE:%.*]] = call nofpclass(ninf nzero nsub nnorm) float @llvm.arithmetic.fence.f32(float [[SELECT]]) #[[ATTR2]]
+; CHECK-NEXT: [[FENCE:%.*]] = call nofpclass(nan inf nzero nsub nnorm) float @llvm.arithmetic.fence.f32(float [[SELECT]]) #[[ATTR2]]
; CHECK-NEXT: ret float [[FENCE]]
;
%fabs = call float @llvm.fabs.f32(float %arg)
@@ -233,12 +233,12 @@ define float @isfinite_select_fabs_val_1(float %arg) {
}
define float @clamp_denormal_to_poszero(float %arg) {
-; CHECK-LABEL: define float @clamp_denormal_to_poszero
+; CHECK-LABEL: define nofpclass(nzero sub) float @clamp_denormal_to_poszero
; CHECK-SAME: (float [[ARG:%.*]]) #[[ATTR1]] {
; CHECK-NEXT: [[FABS:%.*]] = call float @llvm.fabs.f32(float [[ARG]]) #[[ATTR2]]
; CHECK-NEXT: [[IS_DENORM_OR_ZERO:%.*]] = fcmp olt float [[FABS]], 0x3810000000000000
; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[IS_DENORM_OR_ZERO]], float 0.000000e+00, float [[ARG]]
-; CHECK-NEXT: [[FENCE:%.*]] = call float @llvm.arithmetic.fence.f32(float [[SELECT]]) #[[ATTR2]]
+; CHECK-NEXT: [[FENCE:%.*]] = call nofpclass(nzero sub) float @llvm.arithmetic.fence.f32(float [[SELECT]]) #[[ATTR2]]
; CHECK-NEXT: ret float [[FENCE]]
;
%fabs = call float @llvm.fabs.f32(float %arg)
@@ -249,12 +249,12 @@ define float @clamp_denormal_to_poszero(float %arg) {
}
define float @clamp_denormal_to_negzero(float %arg) {
-; CHECK-LABEL: define float @clamp_denormal_to_negzero
+; CHECK-LABEL: define nofpclass(pzero sub) float @clamp_denormal_to_negzero
; CHECK-SAME: (float [[ARG:%.*]]) #[[ATTR1]] {
; CHECK-NEXT: [[FABS:%.*]] = call float @llvm.fabs.f32(float [[ARG]]) #[[ATTR2]]
; CHECK-NEXT: [[IS_DENORM_OR_ZERO:%.*]] = fcmp olt float [[FABS]], 0x3810000000000000
; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[IS_DENORM_OR_ZERO]], float -0.000000e+00, float [[ARG]]
-; CHECK-NEXT: [[FENCE:%.*]] = call float @llvm.arithmetic.fence.f32(float [[SELECT]]) #[[ATTR2]]
+; CHECK-NEXT: [[FENCE:%.*]] = call nofpclass(pzero sub) float @llvm.arithmetic.fence.f32(float [[SELECT]]) #[[ATTR2]]
; CHECK-NEXT: ret float [[FENCE]]
;
%fabs = call float @llvm.fabs.f32(float %arg)
@@ -265,13 +265,13 @@ define float @clamp_denormal_to_negzero(float %arg) {
}
define float @clamp_denormal_to_zero_copysign(float %arg) {
-; CHECK-LABEL: define float @clamp_denormal_to_zero_copysign
+; CHECK-LABEL: define nofpclass(sub) float @clamp_denormal_to_zero_copysign
; CHECK-SAME: (float [[ARG:%.*]]) #[[ATTR1]] {
; CHECK-NEXT: [[FABS:%.*]] = call float @llvm.fabs.f32(float [[ARG]]) #[[ATTR2]]
; CHECK-NEXT: [[IS_DENORM_OR_ZERO:%.*]] = fcmp olt float [[FABS]], 0x3810000000000000
; CHECK-NEXT: [[ZERO:%.*]] = call float @llvm.copysign.f32(float noundef 0.000000e+00, float [[ARG]]) #[[ATTR2]]
; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[IS_DENORM_OR_ZERO]], float [[ZERO]], float [[ARG]]
-; CHECK-NEXT: [[FENCE:%.*]] = call float @llvm.arithmetic.fence.f32(float [[SELECT]]) #[[ATTR2]]
+; CHECK-NEXT: [[FENCE:%.*]] = call nofpclass(sub) float @llvm.arithmetic.fence.f32(float [[SELECT]]) #[[ATTR2]]
; CHECK-NEXT: ret float [[FENCE]]
;
%fabs = call float @llvm.fabs.f32(float %arg)
@@ -283,12 +283,12 @@ define float @clamp_denormal_to_zero_copysign(float %arg) {
}
define float @clamp_only_denormal_or_zero(float %arg) {
-; CHECK-LABEL: define float @clamp_only_denormal_or_zero
+; CHECK-LABEL: define nofpclass(nan inf norm) float @clamp_only_denormal_or_zero
; CHECK-SAME: (float [[ARG:%.*]]) #[[ATTR1]] {
; CHECK-NEXT: [[FABS:%.*]] = call float @llvm.fabs.f32(float [[ARG]]) #[[ATTR2]]
; CHECK-NEXT: [[IS_DENORM_OR_ZERO:%.*]] = fcmp olt float [[FABS]], 0x3810000000000000
; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[IS_DENORM_OR_ZERO]], float [[ARG]], float 0.000000e+00
-; CHECK-NEXT: [[FENCE:%.*]] = call float @llvm.arithmetic.fence.f32(float [[SELECT]]) #[[ATTR2]]
+; CHECK-NEXT: [[FENCE:%.*]] = call nofpclass(nan inf norm) float @llvm.arithmetic.fence.f32(float [[SELECT]]) #[[ATTR2]]
; CHECK-NEXT: ret float [[FENCE]]
;
%fabs = call float @llvm.fabs.f32(float %arg)
@@ -331,11 +331,11 @@ define float @not_clamp_inf_to_fabs(float %arg) {
}
define float @clamp_zero_to_inf(float %arg) {
-; CHECK-LABEL: define float @clamp_zero_to_inf
+; CHECK-LABEL: define nofpclass(zero) float @clamp_zero_to_inf
; CHECK-SAME: (float [[ARG:%.*]]) #[[ATTR1]] {
; CHECK-NEXT: [[IS_ZERO:%.*]] = fcmp oeq float [[ARG]], 0.000000e+00
; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[IS_ZERO]], float 0x7FF0000000000000, float [[ARG]]
-; CHECK-NEXT: [[FENCE:%.*]] = call float @llvm.arithmetic.fence.f32(float [[SELECT]]) #[[ATTR2]]
+; CHECK-NEXT: [[FENCE:%.*]] = call nofpclass(zero) float @llvm.arithmetic.fence.f32(float [[SELECT]]) #[[ATTR2]]
; CHECK-NEXT: ret float [[FENCE]]
;
%is.zero = fcmp oeq float %arg, 0.0
@@ -345,11 +345,11 @@ define float @clamp_zero_to_inf(float %arg) {
}
define float @clamp_zero_to_only_inf(float %arg) {
-; CHECK-LABEL: define float @clamp_zero_to_only_inf
+; CHECK-LABEL: define nofpclass(nan ninf sub norm) float @clamp_zero_to_only_inf
; CHECK-SAME: (float [[ARG:%.*]]) #[[ATTR1]] {
; CHECK-NEXT: [[IS_ZERO:%.*]] = fcmp oeq float [[ARG]], 0.000000e+00
; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[IS_ZERO]], float [[ARG]], float 0x7FF0000000000000
-; CHECK-NEXT: [[FENCE:%.*]] = call float @llvm.arithmetic.fence.f32(float [[SELECT]]) #[[ATTR2]]
+; CHECK-NEXT: [[FENCE:%.*]] = call nofpclass(nan ninf sub norm) float @llvm.arithmetic.fence.f32(float [[SELECT]]) #[[ATTR2]]
; CHECK-NEXT: ret float [[FENCE]]
;
%is.zero = fcmp oeq float %arg, 0.0
@@ -359,11 +359,11 @@ define float @clamp_zero_to_only_inf(float %arg) {
}
define float @clamp_is_class_subnormal_or_inf_to_nan(float %arg) {
-; CHECK-LABEL: define float @clamp_is_class_subnormal_or_inf_to_nan
+; CHECK-LABEL: define nofpclass(inf sub) float @clamp_is_class_subnormal_or_inf_to_nan
; CHECK-SAME: (float [[ARG:%.*]]) #[[ATTR1]] {
; CHECK-NEXT: [[IS_SUBNORMAL_OR_INF:%.*]] = call i1 @llvm.is.fpclass.f32(float [[ARG]], i32 noundef 660) #[[ATTR2]]
; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[IS_SUBNORMAL_OR_INF]], float 0x7FF8000000000000, float [[ARG]]
-; CHECK-NEXT: [[FENCE:%.*]] = call float @llvm.arithmetic.fence.f32(float [[SELECT]]) #[[ATTR2]]
+; CHECK-NEXT: [[FENCE:%.*]] = call nofpclass(inf sub) float @llvm.arithmetic.fence.f32(float [[SELECT]]) #[[ATTR2]]
; CHECK-NEXT: ret float [[FENCE]]
;
%is.subnormal.or.inf = call i1 @llvm.is.fpclass.f32(float %arg, i32 660)
@@ -373,11 +373,11 @@ define float @clamp_is_class_subnormal_or_inf_to_nan(float %arg) {
}
define float @clamp_is_class_subnormal_or_inf_to_nan_swap(float %arg) {
-; CHECK-LABEL: define float @clamp_is_class_subnormal_or_inf_to_nan_swap
+; CHECK-LABEL: define nofpclass(inf sub) float @clamp_is_class_subnormal_or_inf_to_nan_swap
; CHECK-SAME: (float [[ARG:%.*]]) #[[ATTR1]] {
; CHECK-NEXT: [[NOT_IS_SUBNORMAL_OR_INF:%.*]] = call i1 @llvm.is.fpclass.f32(float [[ARG]], i32 noundef 363) #[[ATTR2]]
; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[NOT_IS_SUBNORMAL_OR_INF]], float [[ARG]], float 0x7FF8000000000000
-; CHECK-NEXT: [[FENCE:%.*]] = call float @llvm.arithmetic.fence.f32(float [[SELECT]]) #[[ATTR2]]
+; CHECK-NEXT: [[FENCE:%.*]] = call nofpclass(inf sub) float @llvm.arithmetic.fence.f32(float [[SELECT]]) #[[ATTR2]]
; CHECK-NEXT: ret float [[FENCE]]
;
%not.is.subnormal.or.inf = call i1 @llvm.is.fpclass.f32(float %arg, i32 363)
@@ -387,11 +387,11 @@ define float @clamp_is_class_subnormal_or_inf_to_nan_swap(float %arg) {
}
define float @ret_select_clamp_nan_to_zero_fpclass(float %arg) {
-; CHECK-LABEL: define float @ret_select_clamp_nan_to_zero_fpclass
+; CHECK-LABEL: define nofpclass(nan) float @ret_select_clamp_nan_to_zero_fpclass
; CHECK-SAME: (float [[ARG:%.*]]) #[[ATTR1]] {
; CHECK-NEXT: [[IS_NAN:%.*]] = call i1 @llvm.is.fpclass.f32(float [[ARG]], i32 noundef 3) #[[ATTR2]]
; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[IS_NAN]], float 0.000000e+00, float [[ARG]]
-; CHECK-NEXT: [[FENCE:%.*]] = call float @llvm.arithmetic.fence.f32(float [[SELECT]]) #[[ATTR2]]
+; CHECK-NEXT: [[FENCE:%.*]] = call nofpclass(nan) float @llvm.arithmetic.fence.f32(float [[SELECT]]) #[[ATTR2]]
; CHECK-NEXT: ret float [[FENCE]]
;
%is.nan = call i1 @llvm.is.fpclass.f32(float %arg, i32 3)
@@ -401,11 +401,11 @@ define float @ret_select_clamp_nan_to_zero_fpclass(float %arg) {
}
define float @ret_select_clamp_snan_to_zero_fpclass(float %arg) {
-; CHECK-LABEL: define float @ret_select_clamp_snan_to_zero_fpclass
+; CHECK-LABEL: define nofpclass(snan) float @ret_select_clamp_snan_to_zero_fpclass
; CHECK-SAME: (float [[ARG:%.*]]) #[[ATTR1]] {
; CHECK-NEXT: [[IS_NAN:%.*]] = call i1 @llvm.is.fpclass.f32(float [[ARG]], i32 noundef 1) #[[ATTR2]]
; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[IS_NAN]], float 0.000000e+00, float [[ARG]]
-; CHECK-NEXT: [[FENCE:%.*]] = call float @llvm.arithmetic.fence.f32(float [[SELECT]]) #[[ATTR2]]
+; CHECK-NEXT: [[FENCE:%.*]] = call nofpclass(snan) float @llvm.arithmetic.fence.f32(float [[SELECT]]) #[[ATTR2]]
; CHECK-NEXT: ret float [[FENCE]]
;
%is.nan = call i1 @llvm.is.fpclass.f32(float %arg, i32 1)
@@ -415,11 +415,11 @@ define float @ret_select_clamp_snan_to_zero_fpclass(float %arg) {
}
define float @ret_select_clamp_qnan_to_zero_fpclass(float %arg) {
-; CHECK-LABEL: define float @ret_select_clamp_qnan_to_zero_fpclass
+; CHECK-LABEL: define nofpclass(qnan) float @ret_select_clamp_qnan_to_zero_fpclass
; CHECK-SAME: (float [[ARG:%.*]]) #[[ATTR1]] {
; CHECK-NEXT: [[IS_NAN:%.*]] = call i1 @llvm.is.fpclass.f32(float [[ARG]], i32 noundef 2) #[[ATTR2]]
; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[IS_NAN]], float 0.000000e+00, float [[ARG]]
-; CHECK-NEXT: [[FENCE:%.*]] = call float @llvm.arithmetic.fence.f32(float [[SELECT]]) #[[ATTR2]]
+; CHECK-NEXT: [[FENCE:%.*]] = call nofpclass(qnan) float @llvm.arithmetic.fence.f32(float [[SELECT]]) #[[ATTR2]]
; CHECK-NEXT: ret float [[FENCE]]
;
%is.nan = call i1 @llvm.is.fpclass.f32(float %arg, i32 2)
diff --git a/llvm/test/Transforms/InstCombine/minmax-fp.ll b/llvm/test/Transforms/InstCombine/minmax-fp.ll
index d3c506d0dc2ad2..7ab9193ac0b22b 100644
--- a/llvm/test/Transforms/InstCombine/minmax-fp.ll
+++ b/llvm/test/Transforms/InstCombine/minmax-fp.ll
@@ -117,16 +117,12 @@ define float @fmin_fmin_zero_mismatch(float %x) {
ret float %min2
}
-; TODO: We do not recognize these as max ops because of the mismatched zeros.
; max(max(x, -0.0), -0.0) --> max(x, -0.0)
-
define float @fmax_fmax_zero_mismatch(float %x) {
; CHECK-LABEL: @fmax_fmax_zero_mismatch(
; CHECK-NEXT: [[CMP1:%.*]] = fcmp ogt float [[X:%.*]], 0.000000e+00
; CHECK-NEXT: [[MAX1:%.*]] = select i1 [[CMP1]], float [[X]], float -0.000000e+00
-; CHECK-NEXT: [[CMP2:%.*]] = fcmp olt float [[MAX1]], 0.000000e+00
-; CHECK-NEXT: [[MAX2:%.*]] = select i1 [[CMP2]], float -0.000000e+00, float [[MAX1]]
-; CHECK-NEXT: ret float [[MAX2]]
+; CHECK-NEXT: ret float [[MAX1]]
;
%cmp1 = fcmp ogt float %x, 0.0
%max1 = select i1 %cmp1, float %x, float -0.0
More information about the llvm-commits
mailing list