Index: lib/Transforms/InstCombine/InstCombineCalls.cpp =================================================================== --- lib/Transforms/InstCombine/InstCombineCalls.cpp +++ lib/Transforms/InstCombine/InstCombineCalls.cpp @@ -1004,8 +1004,26 @@ return Arg0; } - // TODO: fmin(nnan x, inf) -> x - // TODO: fmin(nnan ninf x, flt_max) -> x + // fmin(nnan x, inf) -> x + if (II.hasNoNaNs() && C1 && C1->isInfinity()) + return Arg0; + + if (Instruction *I = dyn_cast(Arg0)) { + if (I->hasNoNaNs() && C1 && C1->isInfinity()) + return Arg0; + } + + // fmin(nnan ninf x, flt_max) -> x + if (II.hasNoNaNs() && II.hasNoInfs() && C1 && + C1->getValueAPF().isLargest() && !C1->getValueAPF().isNegative()) + return Arg0; + + if (Instruction *I = dyn_cast(Arg0)) { + if (I->hasNoNaNs() && I->hasNoInfs() && C1 && + C1->getValueAPF().isLargest() && !C1->getValueAPF().isNegative()) + return Arg0; + } + if (C1 && C1->isInfinity()) { // fmin(x, -inf) -> -inf if (C1->isNegative()) @@ -1027,8 +1045,26 @@ return Arg0; } - // TODO: fmax(nnan x, -inf) -> x - // TODO: fmax(nnan ninf x, -flt_max) -> x + // fmax(nnan x, -inf) -> x + if (II.hasNoNaNs() && C1 && C1->isInfinity() && C1->isNegative()) + return Arg0; + + if (Instruction *I = dyn_cast(Arg0)) { + if (I->hasNoNaNs() && C1 && C1->isInfinity() && C1->isNegative()) + return Arg0; + } + + // fmax(nnan ninf x, -flt_max) -> x + if (II.hasNoNaNs() && II.hasNoInfs() && C1 && + C1->getValueAPF().isLargest() && C1->getValueAPF().isNegative()) + return Arg0; + + if (Instruction *I = dyn_cast(Arg0)) { + if (I->hasNoNaNs() && I->hasNoInfs() && C1 && + C1->getValueAPF().isLargest() && C1->getValueAPF().isNegative()) + return Arg0; + } + if (C1 && C1->isInfinity()) { // fmax(x, inf) -> inf if (!C1->isNegative()) Index: test/Transforms/InstCombine/maxnum.ll =================================================================== --- test/Transforms/InstCombine/maxnum.ll +++ test/Transforms/InstCombine/maxnum.ll @@ -219,4 +219,38 @@ ret float %val } +; CHECK-LABEL: @fold_maxnum_nnan_fadd_neginf_val +; CHECK-NEXT: %ret = fadd nnan float %y, %z +; CHECK-NEXT: ret float %ret +define float @fold_maxnum_nnan_fadd_neginf_val(float %x,float %y,float %z) nounwind { + %ret = fadd nnan float %y, %z + %val = call float @llvm.maxnum.f32(float %ret,float 0xFFF0000000000000) #0 + ret float %val +} + +; CHECK-LABEL: @fold_maxnum_nnan_x_neginf_val +; CHECK-NEXT: ret float %x +define float @fold_maxnum_nnan_x_neginf_val(float %x) nounwind { + %val = call nnan float @llvm.maxnum.f32(float 0xFFF0000000000000,float %x) #0 + ret float %val +} + +; CHECK-LABEL: @fold_maxnum_nnan_ninf_x_min_val +; CHECK-NEXT: ret float %x +define float @fold_maxnum_nnan_ninf_x_min_val(float %x) nounwind { + %val = call nnan ninf float @llvm.maxnum.f32(float 0xC7EFFFFFE0000000,float %x) #0 + ret float %val +} + + +; CHECK-LABEL: @fold_maxnum_nnan_ninf_fadd_min_val +; CHECK-NEXT: %ret = fadd nnan ninf float %y, %z +; CHECK-NEXT: float %ret +define float @fold_maxnum_nnan_ninf_fadd_min_val(float %x,float %y,float %z) nounwind { + %ret = fadd nnan ninf float %y, %z + %val = call float @llvm.maxnum.f32(float 0xC7EFFFFFE0000000,float %ret) #0 + ret float %val +} + + attributes #0 = { nounwind readnone } Index: test/Transforms/InstCombine/minnum.ll =================================================================== --- test/Transforms/InstCombine/minnum.ll +++ test/Transforms/InstCombine/minnum.ll @@ -241,4 +241,36 @@ ret float %val } +; CHECK-LABEL: @fold_minnum_nnan_fadd_inf_val +; CHECK-NEXT: %ret = fadd nnan float %y, %z +; CHECK-NEXT: ret float %ret +define float @fold_minnum_nnan_fadd_inf_val(float %x,float %y,float %z) nounwind { + %ret = fadd nnan float %y, %z + %val = call float @llvm.minnum.f32(float %ret,float 0x7FF0000000000000) #0 + ret float %val +} + +; CHECK-LABEL: @fold_minnum_nnan_x_inf_val +; CHECK-NEXT: ret float %x +define float @fold_minnum_nnan_x_inf_val(float %x) nounwind { + %val = call nnan float @llvm.minnum.f32(float 0x7FF0000000000000,float %x) #0 + ret float %val +} + +; CHECK-LABEL: @fold_minnum_nnan_ninf_x_max_val +; CHECK-NEXT: ret float %x +define float @fold_minnum_nnan_ninf_x_max_val(float %x) nounwind { + %val = call nnan ninf float @llvm.minnum.f32(float 0x47EFFFFFE0000000,float %x) #0 + ret float %val +} + + +; CHECK-LABEL: @fold_minnum_nnan_ninf_fadd_max_val +; CHECK-NEXT: %ret = fadd nnan ninf float %y, %z +; CHECK-NEXT: float %ret +define float @fold_minnum_nnan_ninf_fadd_max_val(float %x,float %y,float %z) nounwind { + %ret = fadd nnan ninf float %y, %z + %val = call float @llvm.minnum.f32(float 0x47EFFFFFE0000000,float %ret) #0 + ret float %val +} attributes #0 = { nounwind readnone }