Index: llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp =================================================================== --- llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp +++ llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp @@ -2303,6 +2303,21 @@ } } + // If there are no NaNs, convert minnum/maxnum to fcmp/select for better + // analysis. + if (II->hasNoNaNs() && + (IID == Intrinsic::minnum || IID == Intrinsic::maxnum)) { + // Minnum/maxnum have unspecified behavior comparing (+/-)0.0, so set nsz. + BuilderTy::FastMathFlagGuard Guard(Builder); + FastMathFlags FMF = II->getFastMathFlags(); + FMF.setNoSignedZeros(); + Builder.setFastMathFlags(FMF); + FCmpInst::Predicate Pred = IID == Intrinsic::maxnum ? FCmpInst::FCMP_OGT + : FCmpInst::FCMP_OLT; + Value *Cmp = Builder.CreateFCmp(Pred, Arg0, Arg1); + return SelectInst::Create(Cmp, Arg0, Arg1); + } + break; } case Intrinsic::fmuladd: { Index: llvm/test/Transforms/InstCombine/AMDGPU/amdgcn-intrinsics.ll =================================================================== --- llvm/test/Transforms/InstCombine/AMDGPU/amdgcn-intrinsics.ll +++ llvm/test/Transforms/InstCombine/AMDGPU/amdgcn-intrinsics.ll @@ -1413,7 +1413,8 @@ define float @fmed3_fmf_undef_x_y_f32(float %x, float %y) { ; CHECK-LABEL: @fmed3_fmf_undef_x_y_f32( -; CHECK-NEXT: [[MED3:%.*]] = call nnan float @llvm.minnum.f32(float [[X:%.*]], float [[Y:%.*]]) +; CHECK-NEXT: [[TMP1:%.*]] = fcmp nnan nsz olt float [[X:%.*]], [[Y:%.*]] +; CHECK-NEXT: [[MED3:%.*]] = select i1 [[TMP1]], float [[X]], float [[Y]] ; CHECK-NEXT: ret float [[MED3]] ; %med3 = call nnan float @llvm.amdgcn.fmed3.f32(float undef, float %x, float %y) @@ -2452,4 +2453,3 @@ } ; CHECK: attributes #5 = { convergent } - Index: llvm/test/Transforms/InstCombine/maxnum.ll =================================================================== --- llvm/test/Transforms/InstCombine/maxnum.ll +++ llvm/test/Transforms/InstCombine/maxnum.ll @@ -157,8 +157,9 @@ define float @maxnum_f32_1_maxnum_p0_val_fast(float %x) { ; CHECK-LABEL: @maxnum_f32_1_maxnum_p0_val_fast( -; CHECK-NEXT: [[TMP1:%.*]] = call fast float @llvm.maxnum.f32(float [[X:%.*]], float 1.000000e+00) -; CHECK-NEXT: ret float [[TMP1]] +; CHECK-NEXT: [[TMP1:%.*]] = fcmp fast ogt float [[X:%.*]], 1.000000e+00 +; CHECK-NEXT: [[TMP2:%.*]] = select i1 [[TMP1]], float [[X]], float 1.000000e+00 +; CHECK-NEXT: ret float [[TMP2]] ; %y = call float @llvm.maxnum.f32(float 0.0, float %x) %z = call fast float @llvm.maxnum.f32(float %y, float 1.0) @@ -167,8 +168,9 @@ define float @maxnum_f32_1_maxnum_p0_val_nnan_ninf(float %x) { ; CHECK-LABEL: @maxnum_f32_1_maxnum_p0_val_nnan_ninf( -; CHECK-NEXT: [[TMP1:%.*]] = call nnan ninf float @llvm.maxnum.f32(float [[X:%.*]], float 1.000000e+00) -; CHECK-NEXT: ret float [[TMP1]] +; CHECK-NEXT: [[TMP1:%.*]] = fcmp nnan ninf nsz ogt float [[X:%.*]], 1.000000e+00 +; CHECK-NEXT: [[TMP2:%.*]] = select i1 [[TMP1]], float [[X]], float 1.000000e+00 +; CHECK-NEXT: ret float [[TMP2]] ; %y = call float @llvm.maxnum.f32(float 0.0, float %x) %z = call nnan ninf float @llvm.maxnum.f32(float %y, float 1.0) @@ -236,8 +238,9 @@ define float @neg_neg_vec_fmf(float %x, float %y) { ; CHECK-LABEL: @neg_neg_vec_fmf( -; CHECK-NEXT: [[TMP1:%.*]] = call fast float @llvm.minnum.f32(float [[X:%.*]], float [[Y:%.*]]) -; CHECK-NEXT: [[R:%.*]] = fsub fast float -0.000000e+00, [[TMP1]] +; CHECK-NEXT: [[TMP1:%.*]] = fcmp fast olt float [[X:%.*]], [[Y:%.*]] +; CHECK-NEXT: [[TMP2:%.*]] = select i1 [[TMP1]], float [[X]], float [[Y]] +; CHECK-NEXT: [[R:%.*]] = fsub fast float -0.000000e+00, [[TMP2]] ; CHECK-NEXT: ret float [[R]] ; %negx = fsub arcp float -0.0, %x Index: llvm/test/Transforms/InstCombine/minnum.ll =================================================================== --- llvm/test/Transforms/InstCombine/minnum.ll +++ llvm/test/Transforms/InstCombine/minnum.ll @@ -159,8 +159,9 @@ define float @minnum_f32_1_minnum_p0_val_fast(float %x) { ; CHECK-LABEL: @minnum_f32_1_minnum_p0_val_fast( -; CHECK-NEXT: [[TMP1:%.*]] = call fast float @llvm.minnum.f32(float [[X:%.*]], float 0.000000e+00) -; CHECK-NEXT: ret float [[TMP1]] +; CHECK-NEXT: [[TMP1:%.*]] = fcmp fast olt float [[X:%.*]], 0.000000e+00 +; CHECK-NEXT: [[TMP2:%.*]] = select i1 [[TMP1]], float [[X]], float 0.000000e+00 +; CHECK-NEXT: ret float [[TMP2]] ; %y = call float @llvm.minnum.f32(float 0.0, float %x) %z = call fast float @llvm.minnum.f32(float %y, float 1.0) @@ -169,8 +170,9 @@ define float @minnum_f32_1_minnum_p0_val_nnan_ninf(float %x) { ; CHECK-LABEL: @minnum_f32_1_minnum_p0_val_nnan_ninf( -; CHECK-NEXT: [[TMP1:%.*]] = call nnan ninf float @llvm.minnum.f32(float [[X:%.*]], float 0.000000e+00) -; CHECK-NEXT: ret float [[TMP1]] +; CHECK-NEXT: [[TMP1:%.*]] = fcmp nnan ninf nsz olt float [[X:%.*]], 0.000000e+00 +; CHECK-NEXT: [[TMP2:%.*]] = select i1 [[TMP1]], float [[X]], float 0.000000e+00 +; CHECK-NEXT: ret float [[TMP2]] ; %y = call float @llvm.minnum.f32(float 0.0, float %x) %z = call nnan ninf float @llvm.minnum.f32(float %y, float 1.0) @@ -261,8 +263,9 @@ define <2 x double> @neg_neg_vec_fmf(<2 x double> %x, <2 x double> %y) { ; CHECK-LABEL: @neg_neg_vec_fmf( -; CHECK-NEXT: [[TMP1:%.*]] = call nnan ninf <2 x double> @llvm.maxnum.v2f64(<2 x double> [[X:%.*]], <2 x double> [[Y:%.*]]) -; CHECK-NEXT: [[R:%.*]] = fsub nnan ninf <2 x double> , [[TMP1]] +; CHECK-NEXT: [[TMP1:%.*]] = fcmp nnan ninf nsz ogt <2 x double> [[X:%.*]], [[Y:%.*]] +; CHECK-NEXT: [[TMP2:%.*]] = select <2 x i1> [[TMP1]], <2 x double> [[X]], <2 x double> [[Y]] +; CHECK-NEXT: [[R:%.*]] = fsub nnan ninf <2 x double> , [[TMP2]] ; CHECK-NEXT: ret <2 x double> [[R]] ; %negx = fsub reassoc <2 x double> , %x