From: Nikita Popov Date: Wed, 9 Sep 2020 20:35:02 +0000 (+0200) Subject: [DAGCombiner] Fold fmin/fmax of NaN X-Git-Tag: llvmorg-13-init~12520 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=0a5dc7effb191eff740e0e7ae7bd8e1f6bdb3ad9;p=platform%2Fupstream%2Fllvm.git [DAGCombiner] Fold fmin/fmax of NaN fminnum(X, NaN) is X, fminimum(X, NaN) is NaN. This mirrors the behavior of existing InstSimplify folds. This is expected to improve the reduction lowerings in D87391, which use NaN as a neutral element. Differential Revision: https://reviews.llvm.org/D87415 --- diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp index c714358..eaa7044 100644 --- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -14040,7 +14040,8 @@ SDValue DAGCombiner::visitFNEG(SDNode *N) { } 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 @@ static SDValue visitFMinMax(SelectionDAG &DAG, SDNode *N, !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 index 807c0a8..35fdcd1 100644 --- a/llvm/test/CodeGen/ARM/fminmax-folds.ll +++ b/llvm/test/CodeGen/ARM/fminmax-folds.ll @@ -9,15 +9,7 @@ declare float @llvm.maximum.f32(float, float) 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_minnum_const_nan(float %x) { 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_maxnum_const_nan(float %x) { 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_maximum_const_nan(float %x) { 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 index 41256ba..fd5b638 100644 --- a/llvm/test/CodeGen/X86/fmaxnum.ll +++ b/llvm/test/CodeGen/X86/fmaxnum.ll @@ -610,35 +610,9 @@ define float @test_maxnum_const_op2(float %x) { } 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 index 373920c1..dc1b8ca 100644 --- a/llvm/test/CodeGen/X86/fminnum.ll +++ b/llvm/test/CodeGen/X86/fminnum.ll @@ -610,35 +610,9 @@ define float @test_minnum_const_op2(float %x) { } 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 }