diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp --- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -14040,7 +14040,8 @@ } static SDValue visitFMinMax(SelectionDAG &DAG, SDNode *N, - APFloat (*Op)(const APFloat &, const APFloat &)) { + APFloat (*Op)(const APFloat &, const APFloat &), + bool PropagatesNaN) { SDValue N0 = N->getOperand(0); SDValue N1 = N->getOperand(1); EVT VT = N->getValueType(0); @@ -14058,23 +14059,30 @@ !isConstantFPBuildVectorOrConstantFP(N1)) return DAG.getNode(N->getOpcode(), SDLoc(N), VT, N1, N0); + // minnum(X, nan) -> X + // maxnum(X, nan) -> X + // minimum(X, nan) -> nan + // maximum(X, nan) -> nan + if (N1CFP && N1CFP->isNaN()) + return PropagatesNaN ? N->getOperand(1) : N->getOperand(0); + return SDValue(); } SDValue DAGCombiner::visitFMINNUM(SDNode *N) { - return visitFMinMax(DAG, N, minnum); + return visitFMinMax(DAG, N, minnum, /* PropagatesNaN */ false); } SDValue DAGCombiner::visitFMAXNUM(SDNode *N) { - return visitFMinMax(DAG, N, maxnum); + return visitFMinMax(DAG, N, maxnum, /* PropagatesNaN */ false); } SDValue DAGCombiner::visitFMINIMUM(SDNode *N) { - return visitFMinMax(DAG, N, minimum); + return visitFMinMax(DAG, N, minimum, /* PropagatesNaN */ true); } SDValue DAGCombiner::visitFMAXIMUM(SDNode *N) { - return visitFMinMax(DAG, N, maximum); + return visitFMinMax(DAG, N, maximum, /* PropagatesNaN */ true); } SDValue DAGCombiner::visitFABS(SDNode *N) { diff --git a/llvm/test/CodeGen/ARM/fminmax-folds.ll b/llvm/test/CodeGen/ARM/fminmax-folds.ll --- a/llvm/test/CodeGen/ARM/fminmax-folds.ll +++ b/llvm/test/CodeGen/ARM/fminmax-folds.ll @@ -9,15 +9,7 @@ define float @test_minnum_const_nan(float %x) { ; CHECK-LABEL: test_minnum_const_nan: ; CHECK: @ %bb.0: -; CHECK-NEXT: vldr s0, .LCPI0_0 -; CHECK-NEXT: vmov s2, r0 -; CHECK-NEXT: vminnm.f32 s0, s2, s0 -; CHECK-NEXT: vmov r0, s0 ; CHECK-NEXT: bx lr -; CHECK-NEXT: .p2align 2 -; CHECK-NEXT: @ %bb.1: -; CHECK-NEXT: .LCPI0_0: -; CHECK-NEXT: .long 0x7ff80000 @ float NaN %r = call float @llvm.minnum.f32(float %x, float 0x7fff000000000000) ret float %r } @@ -25,15 +17,7 @@ define float @test_maxnum_const_nan(float %x) { ; CHECK-LABEL: test_maxnum_const_nan: ; CHECK: @ %bb.0: -; CHECK-NEXT: vldr s0, .LCPI1_0 -; CHECK-NEXT: vmov s2, r0 -; CHECK-NEXT: vmaxnm.f32 s0, s2, s0 -; CHECK-NEXT: vmov r0, s0 ; CHECK-NEXT: bx lr -; CHECK-NEXT: .p2align 2 -; CHECK-NEXT: @ %bb.1: -; CHECK-NEXT: .LCPI1_0: -; CHECK-NEXT: .long 0x7ff80000 @ float NaN %r = call float @llvm.maxnum.f32(float %x, float 0x7fff000000000000) ret float %r } @@ -41,15 +25,9 @@ define float @test_maximum_const_nan(float %x) { ; CHECK-LABEL: test_maximum_const_nan: ; CHECK: @ %bb.0: -; CHECK-NEXT: vldr s0, .LCPI2_0 -; CHECK-NEXT: vmov s2, r0 -; CHECK-NEXT: vmax.f32 d0, d1, d0 -; CHECK-NEXT: vmov r0, s0 +; CHECK-NEXT: movw r0, #0 +; CHECK-NEXT: movt r0, #32760 ; CHECK-NEXT: bx lr -; CHECK-NEXT: .p2align 2 -; CHECK-NEXT: @ %bb.1: -; CHECK-NEXT: .LCPI2_0: -; CHECK-NEXT: .long 0x7ff80000 @ float NaN %r = call float @llvm.maximum.f32(float %x, float 0x7fff000000000000) ret float %r } @@ -57,15 +35,9 @@ define float @test_minimum_const_nan(float %x) { ; CHECK-LABEL: test_minimum_const_nan: ; CHECK: @ %bb.0: -; CHECK-NEXT: vldr s0, .LCPI3_0 -; CHECK-NEXT: vmov s2, r0 -; CHECK-NEXT: vmin.f32 d0, d1, d0 -; CHECK-NEXT: vmov r0, s0 +; CHECK-NEXT: movw r0, #0 +; CHECK-NEXT: movt r0, #32760 ; CHECK-NEXT: bx lr -; CHECK-NEXT: .p2align 2 -; CHECK-NEXT: @ %bb.1: -; CHECK-NEXT: .LCPI3_0: -; CHECK-NEXT: .long 0x7ff80000 @ float NaN %r = call float @llvm.minimum.f32(float %x, float 0x7fff000000000000) ret float %r } diff --git a/llvm/test/CodeGen/X86/fmaxnum.ll b/llvm/test/CodeGen/X86/fmaxnum.ll --- a/llvm/test/CodeGen/X86/fmaxnum.ll +++ b/llvm/test/CodeGen/X86/fmaxnum.ll @@ -610,35 +610,9 @@ } define float @test_maxnum_const_nan(float %x) { -; SSE-LABEL: test_maxnum_const_nan: -; SSE: # %bb.0: -; SSE-NEXT: movss {{.*#+}} xmm2 = mem[0],zero,zero,zero -; SSE-NEXT: movaps %xmm0, %xmm1 -; SSE-NEXT: cmpunordss %xmm0, %xmm1 -; SSE-NEXT: movaps %xmm1, %xmm3 -; SSE-NEXT: andps %xmm2, %xmm3 -; SSE-NEXT: maxss %xmm0, %xmm2 -; SSE-NEXT: andnps %xmm2, %xmm1 -; SSE-NEXT: orps %xmm3, %xmm1 -; SSE-NEXT: movaps %xmm1, %xmm0 -; SSE-NEXT: retq -; -; AVX1-LABEL: test_maxnum_const_nan: -; AVX1: # %bb.0: -; AVX1-NEXT: vmovss {{.*#+}} xmm1 = mem[0],zero,zero,zero -; AVX1-NEXT: vmaxss %xmm0, %xmm1, %xmm2 -; AVX1-NEXT: vcmpunordss %xmm0, %xmm0, %xmm0 -; AVX1-NEXT: vblendvps %xmm0, %xmm1, %xmm2, %xmm0 -; AVX1-NEXT: retq -; -; AVX512-LABEL: test_maxnum_const_nan: -; AVX512: # %bb.0: -; AVX512-NEXT: vmovss {{.*#+}} xmm2 = mem[0],zero,zero,zero -; AVX512-NEXT: vmaxss %xmm0, %xmm2, %xmm1 -; AVX512-NEXT: vcmpunordss %xmm0, %xmm0, %k1 -; AVX512-NEXT: vmovss %xmm2, %xmm1, %xmm1 {%k1} -; AVX512-NEXT: vmovaps %xmm1, %xmm0 -; AVX512-NEXT: retq +; CHECK-LABEL: test_maxnum_const_nan: +; CHECK: # %bb.0: +; CHECK-NEXT: retq %r = call float @llvm.maxnum.f32(float %x, float 0x7fff000000000000) ret float %r } diff --git a/llvm/test/CodeGen/X86/fminnum.ll b/llvm/test/CodeGen/X86/fminnum.ll --- a/llvm/test/CodeGen/X86/fminnum.ll +++ b/llvm/test/CodeGen/X86/fminnum.ll @@ -610,35 +610,9 @@ } define float @test_minnum_const_nan(float %x) { -; SSE-LABEL: test_minnum_const_nan: -; SSE: # %bb.0: -; SSE-NEXT: movss {{.*#+}} xmm2 = mem[0],zero,zero,zero -; SSE-NEXT: movaps %xmm0, %xmm1 -; SSE-NEXT: cmpunordss %xmm0, %xmm1 -; SSE-NEXT: movaps %xmm1, %xmm3 -; SSE-NEXT: andps %xmm2, %xmm3 -; SSE-NEXT: minss %xmm0, %xmm2 -; SSE-NEXT: andnps %xmm2, %xmm1 -; SSE-NEXT: orps %xmm3, %xmm1 -; SSE-NEXT: movaps %xmm1, %xmm0 -; SSE-NEXT: retq -; -; AVX1-LABEL: test_minnum_const_nan: -; AVX1: # %bb.0: -; AVX1-NEXT: vmovss {{.*#+}} xmm1 = mem[0],zero,zero,zero -; AVX1-NEXT: vminss %xmm0, %xmm1, %xmm2 -; AVX1-NEXT: vcmpunordss %xmm0, %xmm0, %xmm0 -; AVX1-NEXT: vblendvps %xmm0, %xmm1, %xmm2, %xmm0 -; AVX1-NEXT: retq -; -; AVX512-LABEL: test_minnum_const_nan: -; AVX512: # %bb.0: -; AVX512-NEXT: vmovss {{.*#+}} xmm2 = mem[0],zero,zero,zero -; AVX512-NEXT: vminss %xmm0, %xmm2, %xmm1 -; AVX512-NEXT: vcmpunordss %xmm0, %xmm0, %k1 -; AVX512-NEXT: vmovss %xmm2, %xmm1, %xmm1 {%k1} -; AVX512-NEXT: vmovaps %xmm1, %xmm0 -; AVX512-NEXT: retq +; CHECK-LABEL: test_minnum_const_nan: +; CHECK: # %bb.0: +; CHECK-NEXT: retq %r = call float @llvm.minnum.f32(float %x, float 0x7fff000000000000) ret float %r }