diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp index 9933360a3a1a33..88cfe5a1fa8556 100644 --- a/llvm/lib/Analysis/InstructionSimplify.cpp +++ b/llvm/lib/Analysis/InstructionSimplify.cpp @@ -5455,23 +5455,30 @@ static Value *simplifyBinaryIntrinsic(Function *F, Value *Op0, Value *Op1, if (Q.isUndefValue(Op1)) return Op0; - // If an argument is NaN, return other or NaN appropriately. bool PropagateNaN = IID == Intrinsic::minimum || IID == Intrinsic::maximum; + bool IsMin = IID == Intrinsic::minimum || IID == Intrinsic::minnum; + + // minnum(X, nan) -> X + // maxnum(X, nan) -> X + // minimum(X, nan) -> nan + // maximum(X, nan) -> nan if (match(Op1, m_NaN())) return PropagateNaN ? Op1 : Op0; - // min(X, -Inf) --> -Inf - // max(X, +Inf) --> +Inf - bool UseNegInf = IID == Intrinsic::minnum || IID == Intrinsic::minimum; + // In the following folds, inf can be replaced with the largest finite + // float, if the ninf flag is set. const APFloat *C; - if (match(Op1, m_APFloat(C)) && C->isInfinity() && - C->isNegative() == UseNegInf && !PropagateNaN) - return ConstantFP::getInfinity(ReturnType, UseNegInf); - - // TODO: minimum(nnan x, inf) -> x - // TODO: minnum(nnan ninf x, flt_max) -> x - // TODO: maximum(nnan x, -inf) -> x - // TODO: maxnum(nnan ninf x, -flt_max) -> x + if (match(Op1, m_APFloat(C)) && + (C->isInfinity() || (Q.CxtI->hasNoInfs() && C->isLargest()))) { + // min(X, -Inf) --> -Inf + // max(X, +Inf) --> +Inf + if (C->isNegative() == IsMin && !PropagateNaN) + return ConstantFP::get(ReturnType, *C); + // TODO: minimum(nnan x, inf) -> x + // TODO: minnum(nnan ninf x, flt_max) -> x + // TODO: maximum(nnan x, -inf) -> x + // TODO: maxnum(nnan ninf x, -flt_max) -> x + } // Min/max of the same operation with common operand: // m(m(X, Y)), X --> m(X, Y) (4 commuted variants) diff --git a/llvm/test/Transforms/InstSimplify/fminmax-folds.ll b/llvm/test/Transforms/InstSimplify/fminmax-folds.ll index 5d502d22cccab6..3811ae81e8d399 100644 --- a/llvm/test/Transforms/InstSimplify/fminmax-folds.ll +++ b/llvm/test/Transforms/InstSimplify/fminmax-folds.ll @@ -344,8 +344,7 @@ define float @test_minnum_const_max_ninf(float %x) { define float @test_maxnum_const_max_ninf(float %x) { ; CHECK-LABEL: @test_maxnum_const_max_ninf( -; CHECK-NEXT: [[R:%.*]] = call ninf float @llvm.maxnum.f32(float [[X:%.*]], float 0x47EFFFFFE0000000) -; CHECK-NEXT: ret float [[R]] +; CHECK-NEXT: ret float 0x47EFFFFFE0000000 ; %r = call ninf float @llvm.maxnum.f32(float %x, float 0x47efffffe0000000) ret float %r @@ -371,8 +370,7 @@ define float @test_minimum_const_max_ninf(float %x) { define float @test_minnum_const_neg_max_ninf(float %x) { ; CHECK-LABEL: @test_minnum_const_neg_max_ninf( -; CHECK-NEXT: [[R:%.*]] = call ninf float @llvm.minnum.f32(float [[X:%.*]], float 0xC7EFFFFFE0000000) -; CHECK-NEXT: ret float [[R]] +; CHECK-NEXT: ret float 0xC7EFFFFFE0000000 ; %r = call ninf float @llvm.minnum.f32(float %x, float 0xc7efffffe0000000) ret float %r @@ -416,8 +414,7 @@ define float @test_minnum_const_max_nnan_ninf(float %x) { define float @test_maxnum_const_max_nnan_ninf(float %x) { ; CHECK-LABEL: @test_maxnum_const_max_nnan_ninf( -; CHECK-NEXT: [[R:%.*]] = call nnan ninf float @llvm.maxnum.f32(float [[X:%.*]], float 0x47EFFFFFE0000000) -; CHECK-NEXT: ret float [[R]] +; CHECK-NEXT: ret float 0x47EFFFFFE0000000 ; %r = call nnan ninf float @llvm.maxnum.f32(float %x, float 0x47efffffe0000000) ret float %r @@ -443,8 +440,7 @@ define float @test_minimum_const_max_nnan_ninf(float %x) { define float @test_minnum_const_neg_max_nnan_ninf(float %x) { ; CHECK-LABEL: @test_minnum_const_neg_max_nnan_ninf( -; CHECK-NEXT: [[R:%.*]] = call nnan ninf float @llvm.minnum.f32(float [[X:%.*]], float 0xC7EFFFFFE0000000) -; CHECK-NEXT: ret float [[R]] +; CHECK-NEXT: ret float 0xC7EFFFFFE0000000 ; %r = call nnan ninf float @llvm.minnum.f32(float %x, float 0xc7efffffe0000000) ret float %r