[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