Index: lib/Transforms/InstCombine/InstCombineCalls.cpp =================================================================== --- lib/Transforms/InstCombine/InstCombineCalls.cpp +++ lib/Transforms/InstCombine/InstCombineCalls.cpp @@ -1004,6 +1004,20 @@ return Arg0; } + // fmin(x, fmax(x, y)) -> x + // fmin(y, fmax(x, y)) -> y + if (match(Arg1, m_FMax(m_Value(X), m_Value(Y)))) { + if (Arg0 == X || Arg0 == Y) + return Arg0; + } + + // fmin(fmax(x, y), x) -> x + // fmin(fmax(x, y), y) -> y + if (match(Arg0, m_FMax(m_Value(X), m_Value(Y)))) { + if (Arg1 == X || Arg1 == Y) + return Arg1; + } + // TODO: fmin(nnan x, inf) -> x // TODO: fmin(nnan ninf x, flt_max) -> x if (C1 && C1->isInfinity()) { @@ -1027,6 +1041,20 @@ return Arg0; } + // fmax(x, fmin(x, y)) -> x + // fmax(y, fmin(x, y)) -> y + if (match(Arg1, m_FMin(m_Value(X), m_Value(Y)))) { + if (Arg0 == X || Arg0 == Y) + return Arg0; + } + + // fmax(fmin(x, y), x) -> x + // fmax(fmin(x, y), y) -> y + if (match(Arg0, m_FMin(m_Value(X), m_Value(Y)))) { + if (Arg1 == X || Arg1 == Y) + return Arg1; + } + // TODO: fmax(nnan x, -inf) -> x // TODO: fmax(nnan ninf x, -flt_max) -> x if (C1 && C1->isInfinity()) { Index: test/Transforms/InstCombine/maxnum.ll =================================================================== --- test/Transforms/InstCombine/maxnum.ll +++ test/Transforms/InstCombine/maxnum.ll @@ -1,6 +1,7 @@ ; RUN: opt -S -instcombine < %s | FileCheck %s declare float @llvm.maxnum.f32(float, float) #0 +declare float @llvm.minnum.f32(float, float) #0 declare float @llvm.maxnum.v2f32(<2 x float>, <2 x float>) #0 declare <4 x float> @llvm.maxnum.v4f32(<4 x float>, <4 x float>) #0 @@ -219,4 +220,20 @@ ret float %val } +; CHECK-LABEL: @maxnum_x_minnum_x_y +; CHECK-NEXT: ret float %x +define float @maxnum_x_minnum_x_y(float %x, float %y) #0 { + %a = call float @llvm.minnum.f32(float %x, float %y) #0 + %b = call float @llvm.maxnum.f32(float %x, float %a) #0 + ret float %b +} + +; CHECK-LABEL: @minnum_x_y_maxnum_y +; CHECK-NEXT: ret float %y +define float @minnum_x_y_maxnum_y(float %x, float %y) #0 { + %a = call float @llvm.minnum.f32(float %x, float %y) #0 + %b = call float @llvm.maxnum.f32(float %a, float %y) #0 + ret float %b +} + attributes #0 = { nounwind readnone } Index: test/Transforms/InstCombine/minnum.ll =================================================================== --- test/Transforms/InstCombine/minnum.ll +++ test/Transforms/InstCombine/minnum.ll @@ -1,13 +1,13 @@ ; RUN: opt -S -instcombine < %s | FileCheck %s declare float @llvm.minnum.f32(float, float) #0 +declare float @llvm.maxnum.f32(float, float) #0 declare float @llvm.minnum.v2f32(<2 x float>, <2 x float>) #0 declare <4 x float> @llvm.minnum.v4f32(<4 x float>, <4 x float>) #0 declare double @llvm.minnum.f64(double, double) #0 declare <2 x double> @llvm.minnum.v2f64(<2 x double>, <2 x double>) #0 -declare float @llvm.maxnum.f32(float, float) #0 ; CHECK-LABEL: @constant_fold_minnum_f32 ; CHECK-NEXT: ret float 1.000000e+00 @@ -206,26 +206,6 @@ ret float %c } -; CHECK-LABEL: @minnum_x_maxnum_x_y -; CHECK-NEXT: call float @llvm.maxnum.f32 -; CHECK-NEXT: call float @llvm.minnum.f32 -; CHECK-NEXT: ret float -define float @minnum_x_maxnum_x_y(float %x, float %y) #0 { - %a = call float @llvm.maxnum.f32(float %x, float %y) #0 - %b = call float @llvm.minnum.f32(float %x, float %a) #0 - ret float %b -} - -; CHECK-LABEL: @maxnum_x_minnum_x_y -; CHECK-NEXT: call float @llvm.minnum.f32 -; CHECK-NEXT: call float @llvm.maxnum.f32 -; CHECK-NEXT: ret float -define float @maxnum_x_minnum_x_y(float %x, float %y) #0 { - %a = call float @llvm.minnum.f32(float %x, float %y) #0 - %b = call float @llvm.maxnum.f32(float %x, float %a) #0 - ret float %b -} - ; CHECK-LABEL: @fold_minnum_f32_inf_val ; CHECK-NEXT: call float @llvm.minnum.f32(float %x, float 0x7FF0000000000000) ; CHECK-NEXT: ret float @@ -241,4 +221,20 @@ ret float %val } +; CHECK-LABEL: @minnum_x_maxnum_x_y +; CHECK-NEXT: ret float %x +define float @minnum_x_maxnum_x_y(float %x, float %y) #0 { + %a = call float @llvm.maxnum.f32(float %x, float %y) #0 + %b = call float @llvm.minnum.f32(float %x, float %a) #0 + ret float %b +} + +; CHECK-LABEL: @maxnum_x_y_minnum_y +; CHECK-NEXT: ret float %y +define float @maxnum_x_y_minnum_y(float %x, float %y) #0 { + %a = call float @llvm.maxnum.f32(float %x, float %y) #0 + %b = call float @llvm.minnum.f32(float %a, float %y) #0 + ret float %b +} + attributes #0 = { nounwind readnone }