[llvm-branch-commits] [llvm] release/23.x: [X86] Fix NaN handling in minimumnum/maximumnum zero fixup (#217420) (PR #218645)
via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Tue Aug 25 02:28:28 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-backend-x86
Author: Nikita Popov (nikic)
<details>
<summary>Changes</summary>
(cherry picked from commit 4a1c14678024d9b424cbca33774afdccdb14019e)
---
Patch is 97.15 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/218645.diff
2 Files Affected:
- (modified) llvm/lib/Target/X86/X86ISelLowering.cpp (+7)
- (modified) llvm/test/CodeGen/X86/fminimumnum-fmaximumnum.ll (+819-245)
``````````diff
diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp
index 9452d18018db6..1183ad64f1554 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.cpp
+++ b/llvm/lib/Target/X86/X86ISelLowering.cpp
@@ -30194,6 +30194,13 @@ static SDValue LowerFMINIMUM_FMAXIMUM(SDValue Op, const X86Subtarget &Subtarget,
DAG.getVectorIdxConstant(0, DL));
else
MinMax = Result;
+
+ // The signed-zero fixup may corrupt the numeric NewY result with the sign
+ // bit of a NaN NewX. Restore NewY in that case.
+ if (IsNum && !IgnoreNaN && !IsXNeverNaN) {
+ SDValue IsXNaN = DAG.getSetCC(DL, SetCCType, NewX, NewX, ISD::SETUO);
+ MinMax = DAG.getSelect(DL, VT, IsXNaN, NewY, MinMax);
+ }
}
if (IgnoreNaN || DAG.isKnownNeverNaN(IsNum ? NewY : NewX))
diff --git a/llvm/test/CodeGen/X86/fminimumnum-fmaximumnum.ll b/llvm/test/CodeGen/X86/fminimumnum-fmaximumnum.ll
index 8abd68701676c..19d7832ea6991 100644
--- a/llvm/test/CodeGen/X86/fminimumnum-fmaximumnum.ll
+++ b/llvm/test/CodeGen/X86/fminimumnum-fmaximumnum.ll
@@ -27,16 +27,21 @@ declare <4 x bfloat> @llvm.maximumnum.v4bf16(<4 x bfloat>, <4 x bfloat>)
define float @test_fmaximumnum(float %x, float %y) nounwind {
; SSE2-LABEL: test_fmaximumnum:
; SSE2: # %bb.0:
-; SSE2-NEXT: movaps %xmm0, %xmm3
-; SSE2-NEXT: maxss %xmm1, %xmm3
+; SSE2-NEXT: movaps %xmm0, %xmm2
+; SSE2-NEXT: cmpunordss %xmm0, %xmm2
+; SSE2-NEXT: movaps %xmm2, %xmm3
+; SSE2-NEXT: andps %xmm1, %xmm3
+; SSE2-NEXT: movaps %xmm0, %xmm4
+; SSE2-NEXT: maxss %xmm1, %xmm4
+; SSE2-NEXT: movaps {{.*#+}} xmm5 = [NaN,NaN,NaN,NaN]
+; SSE2-NEXT: orps %xmm0, %xmm5
+; SSE2-NEXT: andps %xmm4, %xmm5
+; SSE2-NEXT: andnps %xmm5, %xmm2
+; SSE2-NEXT: orps %xmm3, %xmm2
; SSE2-NEXT: cmpunordss %xmm1, %xmm1
-; SSE2-NEXT: movaps %xmm1, %xmm2
-; SSE2-NEXT: andps %xmm0, %xmm2
-; SSE2-NEXT: orps {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0
-; SSE2-NEXT: andps %xmm3, %xmm0
-; SSE2-NEXT: andnps %xmm0, %xmm1
-; SSE2-NEXT: orps %xmm1, %xmm2
-; SSE2-NEXT: movaps %xmm2, %xmm0
+; SSE2-NEXT: andps %xmm1, %xmm0
+; SSE2-NEXT: andnps %xmm2, %xmm1
+; SSE2-NEXT: orps %xmm1, %xmm0
; SSE2-NEXT: retq
;
; AVX1-LABEL: test_fmaximumnum:
@@ -44,6 +49,8 @@ define float @test_fmaximumnum(float %x, float %y) nounwind {
; AVX1-NEXT: vmaxss %xmm1, %xmm0, %xmm2
; AVX1-NEXT: vorps {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm3
; AVX1-NEXT: vandps %xmm2, %xmm3, %xmm2
+; AVX1-NEXT: vcmpunordss %xmm0, %xmm0, %xmm3
+; AVX1-NEXT: vblendvps %xmm3, %xmm1, %xmm2, %xmm2
; AVX1-NEXT: vcmpunordss %xmm1, %xmm1, %xmm1
; AVX1-NEXT: vblendvps %xmm1, %xmm0, %xmm2, %xmm0
; AVX1-NEXT: retq
@@ -54,6 +61,8 @@ define float @test_fmaximumnum(float %x, float %y) nounwind {
; AVX512F-NEXT: vorps %xmm2, %xmm0, %xmm2
; AVX512F-NEXT: vmaxss %xmm1, %xmm0, %xmm3
; AVX512F-NEXT: vandps %xmm3, %xmm2, %xmm2
+; AVX512F-NEXT: vcmpunordss %xmm0, %xmm0, %k1
+; AVX512F-NEXT: vmovss %xmm1, %xmm2, %xmm2 {%k1}
; AVX512F-NEXT: vcmpunordss %xmm1, %xmm1, %k1
; AVX512F-NEXT: vmovss %xmm0, %xmm2, %xmm2 {%k1}
; AVX512F-NEXT: vmovaps %xmm2, %xmm0
@@ -65,6 +74,8 @@ define float @test_fmaximumnum(float %x, float %y) nounwind {
; AVX512DQ-NEXT: vorps %xmm2, %xmm0, %xmm2
; AVX512DQ-NEXT: vmaxss %xmm1, %xmm0, %xmm3
; AVX512DQ-NEXT: vandps %xmm3, %xmm2, %xmm2
+; AVX512DQ-NEXT: vcmpunordss %xmm0, %xmm0, %k1
+; AVX512DQ-NEXT: vmovss %xmm1, %xmm2, %xmm2 {%k1}
; AVX512DQ-NEXT: vcmpunordss %xmm1, %xmm1, %k1
; AVX512DQ-NEXT: vmovss %xmm0, %xmm2, %xmm2 {%k1}
; AVX512DQ-NEXT: vmovaps %xmm2, %xmm0
@@ -74,6 +85,8 @@ define float @test_fmaximumnum(float %x, float %y) nounwind {
; AVX512BF16: # %bb.0:
; AVX512BF16-NEXT: vmaxss %xmm1, %xmm0, %xmm2
; AVX512BF16-NEXT: vpternlogd {{.*#+}} xmm2 = xmm2 & (xmm0 | m32bcst)
+; AVX512BF16-NEXT: vcmpunordss %xmm0, %xmm0, %k1
+; AVX512BF16-NEXT: vmovss %xmm1, %xmm2, %xmm2 {%k1}
; AVX512BF16-NEXT: vcmpunordss %xmm1, %xmm1, %k1
; AVX512BF16-NEXT: vmovss %xmm0, %xmm2, %xmm2 {%k1}
; AVX512BF16-NEXT: vmovaps %xmm2, %xmm0
@@ -92,6 +105,8 @@ define float @test_fmaximumnum(float %x, float %y) nounwind {
; X86-NEXT: vmaxss %xmm0, %xmm1, %xmm2
; X86-NEXT: vorps {{\.?LCPI[0-9]+_[0-9]+}}, %xmm1, %xmm3
; X86-NEXT: vandps %xmm2, %xmm3, %xmm2
+; X86-NEXT: vcmpunordss %xmm1, %xmm1, %xmm3
+; X86-NEXT: vblendvps %xmm3, %xmm0, %xmm2, %xmm2
; X86-NEXT: vcmpunordss %xmm0, %xmm0, %xmm0
; X86-NEXT: vblendvps %xmm0, %xmm1, %xmm2, %xmm0
; X86-NEXT: vmovss %xmm0, (%esp)
@@ -102,6 +117,103 @@ define float @test_fmaximumnum(float %x, float %y) nounwind {
ret float %1
}
+; Keep both operands unknown so lowering must handle a NaN in the first operand
+; after the signed-zero fixup.
+define double @test_fmaximumnum_f64(double %x, double %y) nounwind {
+; SSE2-LABEL: test_fmaximumnum_f64:
+; SSE2: # %bb.0:
+; SSE2-NEXT: movapd %xmm0, %xmm2
+; SSE2-NEXT: cmpunordsd %xmm0, %xmm2
+; SSE2-NEXT: movapd %xmm2, %xmm3
+; SSE2-NEXT: andpd %xmm1, %xmm3
+; SSE2-NEXT: movapd %xmm0, %xmm4
+; SSE2-NEXT: maxsd %xmm1, %xmm4
+; SSE2-NEXT: movapd {{.*#+}} xmm5 = [NaN,NaN]
+; SSE2-NEXT: orpd %xmm0, %xmm5
+; SSE2-NEXT: andpd %xmm4, %xmm5
+; SSE2-NEXT: andnpd %xmm5, %xmm2
+; SSE2-NEXT: orpd %xmm3, %xmm2
+; SSE2-NEXT: cmpunordsd %xmm1, %xmm1
+; SSE2-NEXT: andpd %xmm1, %xmm0
+; SSE2-NEXT: andnpd %xmm2, %xmm1
+; SSE2-NEXT: orpd %xmm1, %xmm0
+; SSE2-NEXT: retq
+;
+; AVX1-LABEL: test_fmaximumnum_f64:
+; AVX1: # %bb.0:
+; AVX1-NEXT: vmaxsd %xmm1, %xmm0, %xmm2
+; AVX1-NEXT: vorpd {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm3
+; AVX1-NEXT: vandpd %xmm2, %xmm3, %xmm2
+; AVX1-NEXT: vcmpunordsd %xmm0, %xmm0, %xmm3
+; AVX1-NEXT: vblendvpd %xmm3, %xmm1, %xmm2, %xmm2
+; AVX1-NEXT: vcmpunordsd %xmm1, %xmm1, %xmm1
+; AVX1-NEXT: vblendvpd %xmm1, %xmm0, %xmm2, %xmm0
+; AVX1-NEXT: retq
+;
+; AVX512F-LABEL: test_fmaximumnum_f64:
+; AVX512F: # %bb.0:
+; AVX512F-NEXT: vmaxsd %xmm1, %xmm0, %xmm2
+; AVX512F-NEXT: vorpd {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm3
+; AVX512F-NEXT: vandpd %xmm2, %xmm3, %xmm2
+; AVX512F-NEXT: vcmpunordsd %xmm0, %xmm0, %k1
+; AVX512F-NEXT: vmovsd %xmm1, %xmm2, %xmm2 {%k1}
+; AVX512F-NEXT: vcmpunordsd %xmm1, %xmm1, %k1
+; AVX512F-NEXT: vmovsd %xmm0, %xmm2, %xmm2 {%k1}
+; AVX512F-NEXT: vmovapd %xmm2, %xmm0
+; AVX512F-NEXT: retq
+;
+; AVX512DQ-LABEL: test_fmaximumnum_f64:
+; AVX512DQ: # %bb.0:
+; AVX512DQ-NEXT: vmaxsd %xmm1, %xmm0, %xmm2
+; AVX512DQ-NEXT: vorpd {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm3
+; AVX512DQ-NEXT: vandpd %xmm2, %xmm3, %xmm2
+; AVX512DQ-NEXT: vcmpunordsd %xmm0, %xmm0, %k1
+; AVX512DQ-NEXT: vmovsd %xmm1, %xmm2, %xmm2 {%k1}
+; AVX512DQ-NEXT: vcmpunordsd %xmm1, %xmm1, %k1
+; AVX512DQ-NEXT: vmovsd %xmm0, %xmm2, %xmm2 {%k1}
+; AVX512DQ-NEXT: vmovapd %xmm2, %xmm0
+; AVX512DQ-NEXT: retq
+;
+; AVX512BF16-LABEL: test_fmaximumnum_f64:
+; AVX512BF16: # %bb.0:
+; AVX512BF16-NEXT: vmaxsd %xmm1, %xmm0, %xmm2
+; AVX512BF16-NEXT: vpternlogq {{.*#+}} xmm2 = xmm2 & (xmm0 | m64bcst)
+; AVX512BF16-NEXT: vcmpunordsd %xmm0, %xmm0, %k1
+; AVX512BF16-NEXT: vmovsd %xmm1, %xmm2, %xmm2 {%k1}
+; AVX512BF16-NEXT: vcmpunordsd %xmm1, %xmm1, %k1
+; AVX512BF16-NEXT: vmovsd %xmm0, %xmm2, %xmm2 {%k1}
+; AVX512BF16-NEXT: vmovapd %xmm2, %xmm0
+; AVX512BF16-NEXT: retq
+;
+; AVX10_2-LABEL: test_fmaximumnum_f64:
+; AVX10_2: # %bb.0:
+; AVX10_2-NEXT: vminmaxsd $21, %xmm1, %xmm0
+; AVX10_2-NEXT: retq
+;
+; X86-LABEL: test_fmaximumnum_f64:
+; X86: # %bb.0:
+; X86-NEXT: pushl %ebp
+; X86-NEXT: movl %esp, %ebp
+; X86-NEXT: andl $-8, %esp
+; X86-NEXT: subl $8, %esp
+; X86-NEXT: vmovsd {{.*#+}} xmm0 = mem[0],zero
+; X86-NEXT: vmovsd {{.*#+}} xmm1 = mem[0],zero
+; X86-NEXT: vmaxsd %xmm0, %xmm1, %xmm2
+; X86-NEXT: vorpd {{\.?LCPI[0-9]+_[0-9]+}}, %xmm1, %xmm3
+; X86-NEXT: vandpd %xmm2, %xmm3, %xmm2
+; X86-NEXT: vcmpunordsd %xmm1, %xmm1, %xmm3
+; X86-NEXT: vblendvpd %xmm3, %xmm0, %xmm2, %xmm2
+; X86-NEXT: vcmpunordsd %xmm0, %xmm0, %xmm0
+; X86-NEXT: vblendvpd %xmm0, %xmm1, %xmm2, %xmm0
+; X86-NEXT: vmovlpd %xmm0, (%esp)
+; X86-NEXT: fldl (%esp)
+; X86-NEXT: movl %ebp, %esp
+; X86-NEXT: popl %ebp
+; X86-NEXT: retl
+ %r = call double @llvm.maximumnum.f64(double %x, double %y)
+ ret double %r
+}
+
define <4 x float> @test_fmaximumnum_scalarize(<4 x float> %x, <4 x float> %y) {
; SSE2-LABEL: test_fmaximumnum_scalarize:
; SSE2: # %bb.0:
@@ -403,26 +515,38 @@ define float @test_fmaximumnum_combine_cmps(float %x, float %y) nounwind {
; SSE2: # %bb.0:
; SSE2-NEXT: divss %xmm0, %xmm1
; SSE2-NEXT: movaps %xmm0, %xmm2
-; SSE2-NEXT: maxss %xmm1, %xmm2
+; SSE2-NEXT: cmpunordss %xmm0, %xmm2
+; SSE2-NEXT: movaps %xmm2, %xmm3
+; SSE2-NEXT: andps %xmm1, %xmm3
+; SSE2-NEXT: movaps %xmm0, %xmm4
+; SSE2-NEXT: maxss %xmm1, %xmm4
; SSE2-NEXT: orps {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0
-; SSE2-NEXT: andps %xmm2, %xmm0
+; SSE2-NEXT: andps %xmm4, %xmm0
+; SSE2-NEXT: andnps %xmm0, %xmm2
+; SSE2-NEXT: orps %xmm3, %xmm2
+; SSE2-NEXT: movaps %xmm2, %xmm0
; SSE2-NEXT: retq
;
; AVX1-LABEL: test_fmaximumnum_combine_cmps:
; AVX1: # %bb.0:
; AVX1-NEXT: vdivss %xmm0, %xmm1, %xmm1
-; AVX1-NEXT: vmaxss %xmm1, %xmm0, %xmm1
-; AVX1-NEXT: vorps {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm0
-; AVX1-NEXT: vandps %xmm1, %xmm0, %xmm0
+; AVX1-NEXT: vmaxss %xmm1, %xmm0, %xmm2
+; AVX1-NEXT: vorps {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm3
+; AVX1-NEXT: vandps %xmm2, %xmm3, %xmm2
+; AVX1-NEXT: vcmpunordss %xmm0, %xmm0, %xmm0
+; AVX1-NEXT: vblendvps %xmm0, %xmm1, %xmm2, %xmm0
; AVX1-NEXT: retq
;
; AVX512F-LABEL: test_fmaximumnum_combine_cmps:
; AVX512F: # %bb.0:
-; AVX512F-NEXT: vdivss %xmm0, %xmm1, %xmm1
-; AVX512F-NEXT: vbroadcastss {{.*#+}} xmm2 = [NaN,NaN,NaN,NaN]
-; AVX512F-NEXT: vorps %xmm2, %xmm0, %xmm2
-; AVX512F-NEXT: vmaxss %xmm1, %xmm0, %xmm0
-; AVX512F-NEXT: vandps %xmm0, %xmm2, %xmm0
+; AVX512F-NEXT: vdivss %xmm0, %xmm1, %xmm2
+; AVX512F-NEXT: vbroadcastss {{.*#+}} xmm1 = [NaN,NaN,NaN,NaN]
+; AVX512F-NEXT: vorps %xmm1, %xmm0, %xmm1
+; AVX512F-NEXT: vmaxss %xmm2, %xmm0, %xmm3
+; AVX512F-NEXT: vandps %xmm3, %xmm1, %xmm1
+; AVX512F-NEXT: vcmpunordss %xmm0, %xmm0, %k1
+; AVX512F-NEXT: vmovss %xmm2, %xmm1, %xmm1 {%k1}
+; AVX512F-NEXT: vmovaps %xmm1, %xmm0
; AVX512F-NEXT: retq
;
; AVX512DQ-LABEL: test_fmaximumnum_combine_cmps:
@@ -438,9 +562,12 @@ define float @test_fmaximumnum_combine_cmps(float %x, float %y) nounwind {
;
; AVX512BF16-LABEL: test_fmaximumnum_combine_cmps:
; AVX512BF16: # %bb.0:
-; AVX512BF16-NEXT: vdivss %xmm0, %xmm1, %xmm1
-; AVX512BF16-NEXT: vmaxss %xmm1, %xmm0, %xmm1
-; AVX512BF16-NEXT: vpternlogd {{.*#+}} xmm0 = xmm1 & (xmm0 | m32bcst)
+; AVX512BF16-NEXT: vdivss %xmm0, %xmm1, %xmm2
+; AVX512BF16-NEXT: vmaxss %xmm2, %xmm0, %xmm1
+; AVX512BF16-NEXT: vpternlogd {{.*#+}} xmm1 = xmm1 & (xmm0 | m32bcst)
+; AVX512BF16-NEXT: vcmpunordss %xmm0, %xmm0, %k1
+; AVX512BF16-NEXT: vmovss %xmm2, %xmm1, %xmm1 {%k1}
+; AVX512BF16-NEXT: vmovaps %xmm1, %xmm0
; AVX512BF16-NEXT: retq
;
; AVX10_2-LABEL: test_fmaximumnum_combine_cmps:
@@ -455,9 +582,11 @@ define float @test_fmaximumnum_combine_cmps(float %x, float %y) nounwind {
; X86-NEXT: vmovss {{.*#+}} xmm0 = mem[0],zero,zero,zero
; X86-NEXT: vmovss {{.*#+}} xmm1 = mem[0],zero,zero,zero
; X86-NEXT: vdivss %xmm0, %xmm1, %xmm1
-; X86-NEXT: vmaxss %xmm1, %xmm0, %xmm1
-; X86-NEXT: vorps {{\.?LCPI[0-9]+_[0-9]+}}, %xmm0, %xmm0
-; X86-NEXT: vandps %xmm1, %xmm0, %xmm0
+; X86-NEXT: vmaxss %xmm1, %xmm0, %xmm2
+; X86-NEXT: vorps {{\.?LCPI[0-9]+_[0-9]+}}, %xmm0, %xmm3
+; X86-NEXT: vandps %xmm2, %xmm3, %xmm2
+; X86-NEXT: vcmpunordss %xmm0, %xmm0, %xmm0
+; X86-NEXT: vblendvps %xmm0, %xmm1, %xmm2, %xmm0
; X86-NEXT: vmovss %xmm0, (%esp)
; X86-NEXT: flds (%esp)
; X86-NEXT: popl %eax
@@ -474,16 +603,21 @@ define float @test_fmaximumnum_combine_cmps(float %x, float %y) nounwind {
define float @test_fminimumnum(float %x, float %y) nounwind {
; SSE2-LABEL: test_fminimumnum:
; SSE2: # %bb.0:
-; SSE2-NEXT: movaps %xmm0, %xmm3
-; SSE2-NEXT: minss %xmm1, %xmm3
+; SSE2-NEXT: movaps %xmm0, %xmm2
+; SSE2-NEXT: cmpunordss %xmm0, %xmm2
+; SSE2-NEXT: movaps %xmm2, %xmm3
+; SSE2-NEXT: andps %xmm1, %xmm3
+; SSE2-NEXT: movaps %xmm0, %xmm4
+; SSE2-NEXT: minss %xmm1, %xmm4
+; SSE2-NEXT: movaps {{.*#+}} xmm5 = [-0.0E+0,-0.0E+0,-0.0E+0,-0.0E+0]
+; SSE2-NEXT: andps %xmm0, %xmm5
+; SSE2-NEXT: orps %xmm4, %xmm5
+; SSE2-NEXT: andnps %xmm5, %xmm2
+; SSE2-NEXT: orps %xmm3, %xmm2
; SSE2-NEXT: cmpunordss %xmm1, %xmm1
-; SSE2-NEXT: movaps %xmm1, %xmm2
-; SSE2-NEXT: andps %xmm0, %xmm2
-; SSE2-NEXT: andps {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0
-; SSE2-NEXT: orps %xmm3, %xmm0
-; SSE2-NEXT: andnps %xmm0, %xmm1
-; SSE2-NEXT: orps %xmm1, %xmm2
-; SSE2-NEXT: movaps %xmm2, %xmm0
+; SSE2-NEXT: andps %xmm1, %xmm0
+; SSE2-NEXT: andnps %xmm2, %xmm1
+; SSE2-NEXT: orps %xmm1, %xmm0
; SSE2-NEXT: retq
;
; AVX1-LABEL: test_fminimumnum:
@@ -491,6 +625,8 @@ define float @test_fminimumnum(float %x, float %y) nounwind {
; AVX1-NEXT: vminss %xmm1, %xmm0, %xmm2
; AVX1-NEXT: vandps {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm3
; AVX1-NEXT: vorps %xmm2, %xmm3, %xmm2
+; AVX1-NEXT: vcmpunordss %xmm0, %xmm0, %xmm3
+; AVX1-NEXT: vblendvps %xmm3, %xmm1, %xmm2, %xmm2
; AVX1-NEXT: vcmpunordss %xmm1, %xmm1, %xmm1
; AVX1-NEXT: vblendvps %xmm1, %xmm0, %xmm2, %xmm0
; AVX1-NEXT: retq
@@ -501,6 +637,8 @@ define float @test_fminimumnum(float %x, float %y) nounwind {
; AVX512F-NEXT: vandps %xmm2, %xmm0, %xmm2
; AVX512F-NEXT: vminss %xmm1, %xmm0, %xmm3
; AVX512F-NEXT: vorps %xmm3, %xmm2, %xmm2
+; AVX512F-NEXT: vcmpunordss %xmm0, %xmm0, %k1
+; AVX512F-NEXT: vmovss %xmm1, %xmm2, %xmm2 {%k1}
; AVX512F-NEXT: vcmpunordss %xmm1, %xmm1, %k1
; AVX512F-NEXT: vmovss %xmm0, %xmm2, %xmm2 {%k1}
; AVX512F-NEXT: vmovaps %xmm2, %xmm0
@@ -512,6 +650,8 @@ define float @test_fminimumnum(float %x, float %y) nounwind {
; AVX512DQ-NEXT: vandps %xmm2, %xmm0, %xmm2
; AVX512DQ-NEXT: vminss %xmm1, %xmm0, %xmm3
; AVX512DQ-NEXT: vorps %xmm3, %xmm2, %xmm2
+; AVX512DQ-NEXT: vcmpunordss %xmm0, %xmm0, %k1
+; AVX512DQ-NEXT: vmovss %xmm1, %xmm2, %xmm2 {%k1}
; AVX512DQ-NEXT: vcmpunordss %xmm1, %xmm1, %k1
; AVX512DQ-NEXT: vmovss %xmm0, %xmm2, %xmm2 {%k1}
; AVX512DQ-NEXT: vmovaps %xmm2, %xmm0
@@ -521,6 +661,8 @@ define float @test_fminimumnum(float %x, float %y) nounwind {
; AVX512BF16: # %bb.0:
; AVX512BF16-NEXT: vminss %xmm1, %xmm0, %xmm2
; AVX512BF16-NEXT: vpternlogd {{.*#+}} xmm2 = xmm2 | (xmm0 & m32bcst)
+; AVX512BF16-NEXT: vcmpunordss %xmm0, %xmm0, %k1
+; AVX512BF16-NEXT: vmovss %xmm1, %xmm2, %xmm2 {%k1}
; AVX512BF16-NEXT: vcmpunordss %xmm1, %xmm1, %k1
; AVX512BF16-NEXT: vmovss %xmm0, %xmm2, %xmm2 {%k1}
; AVX512BF16-NEXT: vmovaps %xmm2, %xmm0
@@ -539,6 +681,8 @@ define float @test_fminimumnum(float %x, float %y) nounwind {
; X86-NEXT: vminss %xmm0, %xmm1, %xmm2
; X86-NEXT: vandps {{\.?LCPI[0-9]+_[0-9]+}}, %xmm1, %xmm3
; X86-NEXT: vorps %xmm2, %xmm3, %xmm2
+; X86-NEXT: vcmpunordss %xmm1, %xmm1, %xmm3
+; X86-NEXT: vblendvps %xmm3, %xmm0, %xmm2, %xmm2
; X86-NEXT: vcmpunordss %xmm0, %xmm0, %xmm0
; X86-NEXT: vblendvps %xmm0, %xmm1, %xmm2, %xmm0
; X86-NEXT: vmovss %xmm0, (%esp)
@@ -549,6 +693,103 @@ define float @test_fminimumnum(float %x, float %y) nounwind {
ret float %1
}
+; Keep both operands unknown so lowering must handle a NaN in the first operand
+; after the signed-zero fixup.
+define double @test_fminimumnum_f64(double %x, double %y) nounwind {
+; SSE2-LABEL: test_fminimumnum_f64:
+; SSE2: # %bb.0:
+; SSE2-NEXT: movapd %xmm0, %xmm2
+; SSE2-NEXT: cmpunordsd %xmm0, %xmm2
+; SSE2-NEXT: movapd %xmm2, %xmm3
+; SSE2-NEXT: andpd %xmm1, %xmm3
+; SSE2-NEXT: movapd %xmm0, %xmm4
+; SSE2-NEXT: minsd %xmm1, %xmm4
+; SSE2-NEXT: movapd {{.*#+}} xmm5 = [-0.0E+0,-0.0E+0]
+; SSE2-NEXT: andpd %xmm0, %xmm5
+; SSE2-NEXT: orpd %xmm4, %xmm5
+; SSE2-NEXT: andnpd %xmm5, %xmm2
+; SSE2-NEXT: orpd %xmm3, %xmm2
+; SSE2-NEXT: cmpunordsd %xmm1, %xmm1
+; SSE2-NEXT: andpd %xmm1, %xmm0
+; SSE2-NEXT: andnpd %xmm2, %xmm1
+; SSE2-NEXT: orpd %xmm1, %xmm0
+; SSE2-NEXT: retq
+;
+; AVX1-LABEL: test_fminimumnum_f64:
+; AVX1: # %bb.0:
+; AVX1-NEXT: vminsd %xmm1, %xmm0, %xmm2
+; AVX1-NEXT: vandpd {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm3
+; AVX1-NEXT: vorpd %xmm2, %xmm3, %xmm2
+; AVX1-NEXT: vcmpunordsd %xmm0, %xmm0, %xmm3
+; AVX1-NEXT: vblendvpd %xmm3, %xmm1, %xmm2, %xmm2
+; AVX1-NEXT: vcmpunordsd %xmm1, %xmm1, %xmm1
+; AVX1-NEXT: vblendvpd %xmm1, %xmm0, %xmm2, %xmm0
+; AVX1-NEXT: retq
+;
+; AVX512F-LABEL: test_fminimumnum_f64:
+; AVX512F: # %bb.0:
+; AVX512F-NEXT: vminsd %xmm1, %xmm0, %xmm2
+; AVX512F-NEXT: vandpd {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm3
+; AVX512F-NEXT: vorpd %xmm2, %xmm3, %xmm2
+; AVX512F-NEXT: vcmpunordsd %xmm0, %xmm0, %k1
+; AVX512F-NEXT: vmovsd %xmm1, %xmm2, %xmm2 {%k1}
+; AVX512F-NEXT: vcmpunordsd %xmm1, %xmm1, %k1
+; AVX512F-NEXT: vmovsd %xmm0, %xmm2, %xmm2 {%k1}
+; AVX512F-NEXT: vmovapd %xmm2, %xmm0
+; AVX512F-NEXT: retq
+;
+; AVX512DQ-LABEL: test_fminimumnum_f64:
+; AVX512DQ: # %bb.0:
+; AVX512DQ-NEXT: vminsd %xmm1, %xmm0, %xmm2
+; AVX512DQ-NEXT: vandpd {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm3
+; AVX512DQ-NEXT: vorpd %xmm2, %xmm3, %xmm2
+; AVX512DQ-NEXT: vcmpunordsd %xmm0, %xmm0, %k1
+; AVX512DQ-NEXT: vmovsd %xmm1, %xmm2, %xmm2 {%k1}
+; AVX512DQ-NEXT: vcmpunordsd %xmm1, %xmm1, %k1
+; AVX512DQ-NEXT: vmovsd %xmm0, %xmm2, %xmm2 {%k1}
+; AVX512DQ-NEXT: vmovapd %xmm2, %xmm0
+; AVX512DQ-NEXT: retq
+;
+; AVX512BF16-LABEL: test_fminimumnum_f64:
+; AVX512BF16: # %bb.0:
+; AVX512BF16-NEXT: vminsd %xmm1, %xmm0, %xmm2
+; AVX512BF16-NEXT: vpternlogq {{.*#+}} xmm2 = xmm2 | (xmm0 & m64bcst)
+; AVX512BF16-NEXT: vcmpunordsd %xmm0, %xmm0, %k1
+; AVX512BF16-NEXT: vmovsd %xmm1, %xmm2, %xmm2 {%k1}
+; AVX512BF16-NEXT: vcmpunordsd %xmm1, %xmm1, %k1
+; AVX512BF16-NEXT: vmovsd %xmm0, %xmm2, %xmm2 {%k1}
+; AVX512BF16-NEXT: vmovapd %xmm2, %xmm0
+; AVX512BF16-NEXT: retq
+;
+; AVX10_2-LABEL: test_fminimumnum_f64:
+; AVX10_2: # %bb.0:
+; AVX10_2-NEXT: vminmaxsd $20, %xmm1, %xmm0
+; AVX10_2-NEXT: retq
+;
+; X86-LABEL: test_fminimumnum_f64:
+; X86: # %bb.0:
+; X86-NEXT: pushl %ebp
+; X86-NEXT: movl %esp, %ebp
+; X86-NEXT: andl $-8, %esp
+; X86-NEXT: subl $8, %esp
+; X86-NEXT: vmovsd {{.*#+}} xmm0 = mem[0],zero
+; X86-NEXT: vmovsd {{.*#+}} xmm1 = mem[0],zero
+; X86-NEXT: vminsd %xmm0, %xmm1, %xmm2
+; X86-NEXT: vandpd {{\.?LCPI[0-9]+_[0-9]+}}, %xmm1, %xmm3
+; X86-NEXT: vorpd %xmm2, %xmm3, %xmm2
+; X86-NEXT: vcmpunordsd %xmm1, %xmm1, %xmm3
+; X86-NEXT: vblendvpd %xmm3, %xmm0, %xmm2, %xmm2
+; X86-NEXT: vcmpunordsd %xmm0, %xmm0, %xmm0
+; X86-NEXT: vblendvpd %xmm0, %xmm1, %xmm2, %xmm0
+; X86-NEXT: vmovlpd %xmm0, (%esp)
+; X86-NEXT: fldl (%esp)
+; X86-NEXT: movl %ebp, %esp
+; X86-NEXT: popl %ebp
+; X86-NEXT: retl
+ %r = call double @llvm.minimumnum.f64(double %x, double %y)
+ ret double %r
+}
+
define <2 x double> @test_fminimumnum_scalarize(<2 x double> %x, <2 x double> %y) {
; SSE2-LABEL: test_fminimumnum_scalarize:
; SSE2: # %bb.0:
@@ -827,26 +1068,38 @@ define float @test_fminimumnum_combine_cmps(float %x, float %y) nounwind {
; SSE2: # %bb.0:
; SSE2-NEXT: divss %xmm0, %xmm1
; SSE2-NEXT: movaps %xmm0, %xmm2
-; SSE2-NEXT: minss %xmm1, %xmm2
+; SSE2-NEXT: cmpunordss %xmm0, %xmm2
+; SSE2-NEXT: movaps %xmm2, %xmm3
+; SSE2-NEXT: andps %xmm1, %xmm3
+; SSE2-NEXT: movaps %xmm0, %xmm4
+; SSE2-NEXT: minss %xmm1, %xmm4
; SSE2-NEXT: andps {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0
-; SSE2-NEXT: orps %xmm2, %xmm0
+; SSE2-NEXT: orps %xmm4, %xmm0
+; SS...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/218645
More information about the llvm-branch-commits
mailing list