[llvm] [X86] Fix NaN handling in minimumnum/maximumnum zero fixup (PR #217420)
via llvm-commits
llvm-commits at lists.llvm.org
Wed Aug 19 11:21:00 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-backend-x86
Author: Oscar Priego (Opriego)
<details>
<summary>Changes</summary>
Fix the X86 lowering of `minimumnum`/`maximumnum` when the first operand is
NaN and signed-zero handling is required.
`PSEUDO_FMIN`/`PSEUDO_FMAX` already select the numeric second operand when
the first operand is NaN. However, the subsequent signed-zero fixup can
modify that numeric result using the sign bit of the first operand.
For example, `minimumnum(-qNaN, +1.0)` can therefore turn the correctly
selected `+1.0` into `-1.0`.
Restore the second operand when the first operand is NaN after the
signed-zero fixup. The additional check is restricted to numeric min/max
operations where NaNs cannot be ignored and the first operand is not
already known to be non-NaN.
The existing handling for a NaN second operand remains unchanged.
This also fixes the symmetric `maximumnum(+qNaN, -1.0)` case and applies
to signaling NaNs as well.
Fast paths for `nnan`, `nsz`, known non-NaN operands, and native AVX10.2
`VMINMAX*` lowering remain unchanged.
Tests were updated for scalar and vector lowering across the existing X86
feature configurations.
Tested with:
- `llvm/test/CodeGen/X86/fminimumnum-fmaximumnum.ll`
- `llvm/test/CodeGen/X86/fminimum-fmaximum.ll`
- `llvm/test/CodeGen/X86/fminimum-fmaximum-i686.ll`
- `llvm/test/CodeGen/X86/avx512fp16-fminimum-fmaximum.ll`
- relevant vector-reduction min/max tests
Runtime exact-bit reproductions were also verified for f32/f64,
qNaN/sNaN, both operand orders, signed zeros, and representative vector
cases.
Fixes #<!-- -->217376
AI-assisted development tools were used during this contribution.
All generated output was reviewed and modified by the author. The final
patch, tests, and validation steps were determined and verified by the author.
---
Patch is 82.92 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/217420.diff
2 Files Affected:
- (modified) llvm/lib/Target/X86/X86ISelLowering.cpp (+8)
- (modified) llvm/test/CodeGen/X86/fminimumnum-fmaximumnum.ll (+759-185)
``````````diff
diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp
index 922657ca9e17c..f078c1df06fe2 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.cpp
+++ b/llvm/lib/Target/X86/X86ISelLowering.cpp
@@ -30212,6 +30212,14 @@ 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 1f4736c7c9b8b..8eed254a014c3 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, ...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/217420
More information about the llvm-commits
mailing list