[llvm] 0a5dc7e - [DAGCombiner] Fold fmin/fmax of NaN

Nikita Popov via llvm-commits llvm-commits at lists.llvm.org
Wed Sep 9 14:53:45 PDT 2020


Author: Nikita Popov
Date: 2020-09-09T23:53:32+02:00
New Revision: 0a5dc7effb191eff740e0e7ae7bd8e1f6bdb3ad9

URL: https://github.com/llvm/llvm-project/commit/0a5dc7effb191eff740e0e7ae7bd8e1f6bdb3ad9
DIFF: https://github.com/llvm/llvm-project/commit/0a5dc7effb191eff740e0e7ae7bd8e1f6bdb3ad9.diff

LOG: [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

Added: 
    

Modified: 
    llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
    llvm/test/CodeGen/ARM/fminmax-folds.ll
    llvm/test/CodeGen/X86/fmaxnum.ll
    llvm/test/CodeGen/X86/fminnum.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
index c714358c0157..eaa70444578a 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 807c0a8b8eb4..35fdcd1d0d6f 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 41256ba18dd6..fd5b638a146d 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 373920c185e3..dc1b8ca8eb4d 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
 }


        


More information about the llvm-commits mailing list