diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp --- a/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp @@ -3197,6 +3197,18 @@ Results.push_back(Expanded); break; } + case ISD::FMINIMUM: + case ISD::FMAXIMUM: { + EVT VT = Node->getValueType(0); + ISD::NodeType NT = + Node->getOpcode() == ISD::FMINIMUM ? ISD::FMINNUM : ISD::FMAXNUM; + Tmp1 = Node->getOperand(0); + Tmp2 = Node->getOperand(1); + Tmp3 = DAG.getNode(NT, dl, VT, {Tmp1, Tmp2}); + Tmp4 = DAG.getConstantFP(std::numeric_limits::quiet_NaN(), dl, VT); + Results.push_back(DAG.getSelectCC(dl, Tmp1, Tmp2, Tmp4, Tmp3, ISD::SETUO)); + break; + } case ISD::FSIN: case ISD::FCOS: { EVT VT = Node->getValueType(0); 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 @@ -77,13 +77,19 @@ ; CHECK: @ %bb.0: ; CHECK-NEXT: vldr s0, .LCPI6_0 ; CHECK-NEXT: vmov s2, r0 -; CHECK-NEXT: vmax.f32 d0, d1, d0 +; CHECK-NEXT: vldr s4, .LCPI6_1 +; CHECK-NEXT: vcmp.f32 s2, s0 +; CHECK-NEXT: vmaxnm.f32 s6, s2, s0 +; CHECK-NEXT: vmrs APSR_nzcv, fpscr +; CHECK-NEXT: vselvs.f32 s0, s4, s6 ; CHECK-NEXT: vmov r0, s0 ; CHECK-NEXT: bx lr ; CHECK-NEXT: .p2align 2 ; CHECK-NEXT: @ %bb.1: ; CHECK-NEXT: .LCPI6_0: ; CHECK-NEXT: .long 0x7f800000 @ float +Inf +; CHECK-NEXT: .LCPI6_1: +; CHECK-NEXT: .long 0x7fc00000 @ float NaN %r = call float @llvm.maximum.f32(float %x, float 0x7ff0000000000000) ret float %r } @@ -135,13 +141,19 @@ ; CHECK: @ %bb.0: ; CHECK-NEXT: vldr s0, .LCPI11_0 ; CHECK-NEXT: vmov s2, r0 -; CHECK-NEXT: vmin.f32 d0, d1, d0 +; CHECK-NEXT: vldr s4, .LCPI11_1 +; CHECK-NEXT: vcmp.f32 s2, s0 +; CHECK-NEXT: vminnm.f32 s6, s2, s0 +; CHECK-NEXT: vmrs APSR_nzcv, fpscr +; CHECK-NEXT: vselvs.f32 s0, s4, s6 ; CHECK-NEXT: vmov r0, s0 ; CHECK-NEXT: bx lr ; CHECK-NEXT: .p2align 2 ; CHECK-NEXT: @ %bb.1: ; CHECK-NEXT: .LCPI11_0: ; CHECK-NEXT: .long 0xff800000 @ float -Inf +; CHECK-NEXT: .LCPI11_1: +; CHECK-NEXT: .long 0x7fc00000 @ float NaN %r = call float @llvm.minimum.f32(float %x, float 0xfff0000000000000) ret float %r } @@ -337,13 +349,19 @@ ; CHECK: @ %bb.0: ; CHECK-NEXT: vldr s0, .LCPI30_0 ; CHECK-NEXT: vmov s2, r0 -; CHECK-NEXT: vmax.f32 d0, d1, d0 +; CHECK-NEXT: vldr s4, .LCPI30_1 +; CHECK-NEXT: vcmp.f32 s2, s0 +; CHECK-NEXT: vmaxnm.f32 s6, s2, s0 +; CHECK-NEXT: vmrs APSR_nzcv, fpscr +; CHECK-NEXT: vselvs.f32 s0, s4, s6 ; CHECK-NEXT: vmov r0, s0 ; CHECK-NEXT: bx lr ; CHECK-NEXT: .p2align 2 ; CHECK-NEXT: @ %bb.1: ; CHECK-NEXT: .LCPI30_0: ; CHECK-NEXT: .long 0x7f7fffff @ float 3.40282347E+38 +; CHECK-NEXT: .LCPI30_1: +; CHECK-NEXT: .long 0x7fc00000 @ float NaN %r = call float @llvm.maximum.f32(float %x, float 0x47efffffe0000000) ret float %r } @@ -353,13 +371,19 @@ ; CHECK: @ %bb.0: ; CHECK-NEXT: vldr s0, .LCPI31_0 ; CHECK-NEXT: vmov s2, r0 -; CHECK-NEXT: vmin.f32 d0, d1, d0 +; CHECK-NEXT: vldr s4, .LCPI31_1 +; CHECK-NEXT: vcmp.f32 s2, s0 +; CHECK-NEXT: vminnm.f32 s6, s2, s0 +; CHECK-NEXT: vmrs APSR_nzcv, fpscr +; CHECK-NEXT: vselvs.f32 s0, s4, s6 ; CHECK-NEXT: vmov r0, s0 ; CHECK-NEXT: bx lr ; CHECK-NEXT: .p2align 2 ; CHECK-NEXT: @ %bb.1: ; CHECK-NEXT: .LCPI31_0: ; CHECK-NEXT: .long 0x7f7fffff @ float 3.40282347E+38 +; CHECK-NEXT: .LCPI31_1: +; CHECK-NEXT: .long 0x7fc00000 @ float NaN %r = call float @llvm.minimum.f32(float %x, float 0x47efffffe0000000) ret float %r } @@ -401,13 +425,19 @@ ; CHECK: @ %bb.0: ; CHECK-NEXT: vldr s0, .LCPI34_0 ; CHECK-NEXT: vmov s2, r0 -; CHECK-NEXT: vmax.f32 d0, d1, d0 +; CHECK-NEXT: vldr s4, .LCPI34_1 +; CHECK-NEXT: vcmp.f32 s2, s0 +; CHECK-NEXT: vmaxnm.f32 s6, s2, s0 +; CHECK-NEXT: vmrs APSR_nzcv, fpscr +; CHECK-NEXT: vselvs.f32 s0, s4, s6 ; CHECK-NEXT: vmov r0, s0 ; CHECK-NEXT: bx lr ; CHECK-NEXT: .p2align 2 ; CHECK-NEXT: @ %bb.1: ; CHECK-NEXT: .LCPI34_0: ; CHECK-NEXT: .long 0xff7fffff @ float -3.40282347E+38 +; CHECK-NEXT: .LCPI34_1: +; CHECK-NEXT: .long 0x7fc00000 @ float NaN %r = call float @llvm.maximum.f32(float %x, float 0xc7efffffe0000000) ret float %r } @@ -417,13 +447,19 @@ ; CHECK: @ %bb.0: ; CHECK-NEXT: vldr s0, .LCPI35_0 ; CHECK-NEXT: vmov s2, r0 -; CHECK-NEXT: vmin.f32 d0, d1, d0 +; CHECK-NEXT: vldr s4, .LCPI35_1 +; CHECK-NEXT: vcmp.f32 s2, s0 +; CHECK-NEXT: vminnm.f32 s6, s2, s0 +; CHECK-NEXT: vmrs APSR_nzcv, fpscr +; CHECK-NEXT: vselvs.f32 s0, s4, s6 ; CHECK-NEXT: vmov r0, s0 ; CHECK-NEXT: bx lr ; CHECK-NEXT: .p2align 2 ; CHECK-NEXT: @ %bb.1: ; CHECK-NEXT: .LCPI35_0: ; CHECK-NEXT: .long 0xff7fffff @ float -3.40282347E+38 +; CHECK-NEXT: .LCPI35_1: +; CHECK-NEXT: .long 0x7fc00000 @ float NaN %r = call float @llvm.minimum.f32(float %x, float 0xc7efffffe0000000) ret float %r } @@ -459,13 +495,19 @@ ; CHECK: @ %bb.0: ; CHECK-NEXT: vldr s0, .LCPI38_0 ; CHECK-NEXT: vmov s2, r0 -; CHECK-NEXT: vmax.f32 d0, d1, d0 +; CHECK-NEXT: vldr s4, .LCPI38_1 +; CHECK-NEXT: vcmp.f32 s2, s0 +; CHECK-NEXT: vmaxnm.f32 s6, s2, s0 +; CHECK-NEXT: vmrs APSR_nzcv, fpscr +; CHECK-NEXT: vselvs.f32 s0, s4, s6 ; CHECK-NEXT: vmov r0, s0 ; CHECK-NEXT: bx lr ; CHECK-NEXT: .p2align 2 ; CHECK-NEXT: @ %bb.1: ; CHECK-NEXT: .LCPI38_0: ; CHECK-NEXT: .long 0x7f7fffff @ float 3.40282347E+38 +; CHECK-NEXT: .LCPI38_1: +; CHECK-NEXT: .long 0x7fc00000 @ float NaN %r = call ninf float @llvm.maximum.f32(float %x, float 0x47efffffe0000000) ret float %r } @@ -516,13 +558,19 @@ ; CHECK: @ %bb.0: ; CHECK-NEXT: vldr s0, .LCPI43_0 ; CHECK-NEXT: vmov s2, r0 -; CHECK-NEXT: vmin.f32 d0, d1, d0 +; CHECK-NEXT: vldr s4, .LCPI43_1 +; CHECK-NEXT: vcmp.f32 s2, s0 +; CHECK-NEXT: vminnm.f32 s6, s2, s0 +; CHECK-NEXT: vmrs APSR_nzcv, fpscr +; CHECK-NEXT: vselvs.f32 s0, s4, s6 ; CHECK-NEXT: vmov r0, s0 ; CHECK-NEXT: bx lr ; CHECK-NEXT: .p2align 2 ; CHECK-NEXT: @ %bb.1: ; CHECK-NEXT: .LCPI43_0: ; CHECK-NEXT: .long 0xff7fffff @ float -3.40282347E+38 +; CHECK-NEXT: .LCPI43_1: +; CHECK-NEXT: .long 0x7fc00000 @ float NaN %r = call ninf float @llvm.minimum.f32(float %x, float 0xc7efffffe0000000) ret float %r } diff --git a/llvm/test/CodeGen/NVPTX/fminimum-fmaximum.ll b/llvm/test/CodeGen/NVPTX/fminimum-fmaximum.ll --- a/llvm/test/CodeGen/NVPTX/fminimum-fmaximum.ll +++ b/llvm/test/CodeGen/NVPTX/fminimum-fmaximum.ll @@ -5,6 +5,10 @@ ; ---- minimum ---- +declare half @llvm.minimum.f16(half %a, half %b) +declare float @llvm.minimum.f32(float %a, float %b) +declare double @llvm.minimum.f64(double %a, double %b) + ; CHECK-LABEL: minimum_half define half @minimum_half(half %a) #0 { ; CHECK-NONAN: setp @@ -15,6 +19,16 @@ ret half %x } +; CHECK-LABEL: minimum_intr_half +define half @minimum_intr_half(half %a, half %b) #0 { + ; CHECK-NONAN-DAG: min.f32 + ; CHECK-NONAN-DAG: setp.nan.f32 + ; CHECK-NONAN-DAG: selp.b16 + ; CHECK-NAN: min.NaN.f16 + %x = call half @llvm.minimum.f16(half %a, half %b) + ret half %x +} + ; CHECK-LABEL: minimum_float define float @minimum_float(float %a) #0 { ; CHECK-NONAN: setp @@ -25,6 +39,16 @@ ret float %x } +; CHECK-LABEL: minimum_intr_float +define float @minimum_intr_float(float %a, float %b) #0 { + ; CHECK-NONAN-DAG: min.f32 + ; CHECK-NONAN-DAG: setp.nan.f32 + ; CHECK-NONAN-DAG: selp.f32 + ; CHECK-NAN: min.NaN.f32 + %x = call float @llvm.minimum.f32(float %a, float %b) + ret float %x +} + ; CHECK-LABEL: minimum_double define double @minimum_double(double %a) #0 { ; CHECK: setp @@ -34,6 +58,15 @@ ret double %x } +; CHECK-LABEL: minimum_intr_double +define double @minimum_intr_double(double %a, double %b) #0 { + ; CHECK-DAG: min.f64 + ; CHECK-DAG: setp.nan.f64 + ; CHECK-DAG: selp.f64 + %x = call double @llvm.minimum.f64(double %a, double %b) + ret double %x +} + ; CHECK-LABEL: minimum_v2half define <2 x half> @minimum_v2half(<2 x half> %a) #0 { ; CHECK-NONAN-DAG: setp @@ -48,6 +81,10 @@ ; ---- maximum ---- +declare half @llvm.maximum.f16(half %a, half %b) +declare float @llvm.maximum.f32(float %a, float %b) +declare double @llvm.maximum.f64(double %a, double %b) + ; CHECK-LABEL: maximum_half define half @maximum_half(half %a) #0 { ; CHECK-NONAN: setp @@ -58,6 +95,16 @@ ret half %x } +; CHECK-LABEL: maximum_intr_half +define half @maximum_intr_half(half %a, half %b) #0 { + ; CHECK-NONAN-DAG: max.f32 + ; CHECK-NONAN-DAG: setp.nan.f32 + ; CHECK-NONAN-DAG: selp.b16 + ; CHECK-NAN: max.NaN.f16 + %x = call half @llvm.maximum.f16(half %a, half %b) + ret half %x +} + ; CHECK-LABEL: maximum_float define float @maximum_float(float %a) #0 { ; CHECK-NONAN: setp @@ -68,6 +115,16 @@ ret float %x } +; CHECK-LABEL: maximum_intr_float +define float @maximum_intr_float(float %a, float %b) #0 { + ; CHECK-NONAN-DAG: max.f32 + ; CHECK-NONAN-DAG: setp.nan.f32 + ; CHECK-NONAN-DAG: selp.f32 + ; CHECK-NAN: max.NaN.f32 + %x = call float @llvm.maximum.f32(float %a, float %b) + ret float %x +} + ; CHECK-LABEL: maximum_double define double @maximum_double(double %a) #0 { ; CHECK: setp @@ -77,6 +134,15 @@ ret double %x } +; CHECK-LABEL: maximum_intr_double +define double @maximum_intr_double(double %a, double %b) #0 { + ; CHECK-DAG: max.f64 + ; CHECK-DAG: setp.nan.f64 + ; CHECK-DAG: selp.f64 + %x = call double @llvm.maximum.f64(double %a, double %b) + ret double %x +} + ; CHECK-LABEL: maximum_v2half define <2 x half> @maximum_v2half(<2 x half> %a) #0 { ; CHECK-NONAN-DAG: setp