[llvm] Fix #51923: x86 sse fp to int sat lowering (PR #199416)
via llvm-commits
llvm-commits at lists.llvm.org
Sun May 24 05:51:25 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-backend-x86
Author: Panadulek
<details>
<summary>Changes</summary>
# Task
[X86][SSE] Improve ISD::FP_TO_*INT_SAT vector lowering
# Problem
As noted in the issue description, we currently fall back to scalarizing FP_TO_INT_SAT conversions for 32-bit
vector types. We were failing to take advantage of native SSE behavior for out-of-range integer results,
leading
to severely unoptimized and bloated machine code.
# Solution
Implemented fully vectorized custom lowering paths for v4i32 FP_TO_SINT_SAT and FP_TO_UINT_SAT on SSE2.
For signed conversions, the implementation makes direct use of the cvttps2dq hardware behavior (which
naturally clamps out-of-range lower bounds to INT_MIN via the indefinite integer output) and efficiently
patches positive overflow and NaN cases with bitwise masks. For unsigned conversions, it uses maxps with
0.0 to cleanly drop negatives and NaN before natively expanding to FP_TO_UINT , managing the upper bound
saturation with a simple mask.
# Tests
Added a comprehensive suite of edge-case tests in fp-to-int-sat-vector-sse2.ll ensuring correct vectorized
behavior
for NaN , +/- Inf , 0.0 , and exact precision limits. Updated existing Golden Masters using
update_llc_test_checks.py . Fully verified by passing the entire ninja check-llvm-codegen-x86 test suite with
0
regressions.
---
Patch is 53.19 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/199416.diff
5 Files Affected:
- (modified) llvm/lib/Target/X86/X86ISelLowering.cpp (+70-1)
- (added) llvm/test/CodeGen/X86/fp-to-int-sat-vector-sse2.ll (+113)
- (modified) llvm/test/CodeGen/X86/fpclamptosat_vec.ll (+226-404)
- (modified) llvm/test/CodeGen/X86/fptosi-sat-vector-128.ll (+21-108)
- (modified) llvm/test/CodeGen/X86/fptoui-sat-vector-128.ll (+32-93)
``````````diff
diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp
index 1af8eea0c23c6..ef7a076804eeb 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.cpp
+++ b/llvm/lib/Target/X86/X86ISelLowering.cpp
@@ -319,6 +319,8 @@ X86TargetLowering::X86TargetLowering(const X86TargetMachine &TM,
setOperationAction(ISD::FP_TO_UINT_SAT, MVT::i64, Custom);
setOperationAction(ISD::FP_TO_SINT_SAT, MVT::i64, Custom);
}
+ setOperationAction(ISD::FP_TO_UINT_SAT, MVT::v4i32, Custom);
+ setOperationAction(ISD::FP_TO_SINT_SAT, MVT::v4i32, Custom);
}
if (Subtarget.hasAVX10_2()) {
for (MVT VT : {MVT::v8i8, MVT::v16i8, MVT::v32i8}) {
@@ -22820,8 +22822,75 @@ X86TargetLowering::LowerFP_TO_INT_SAT(SDValue Op, SelectionDAG &DAG) const {
SDValue Res = DAG.getNode(IsSigned ? X86ISD::CVTTP2IBS : X86ISD::CVTTP2IUBS,
dl, VecI16VT, Src);
return DAG.getNode(ISD::TRUNCATE, dl, DstVT, Res);
- }
+ } else if (DstVT == MVT::v4i32 && Subtarget.hasSSE2()) {
+ unsigned SatWidth = SatVT.getScalarSizeInBits();
+ assert(SatWidth <= 32 && "Expected saturation width no wider than result element");
+
+ if (SatWidth == 32) {
+ if (IsSigned) {
+ SDValue Cvt = DAG.getNode(ISD::FP_TO_SINT, dl, DstVT, Src);
+ APFloat PosOvfBoundFlt(SrcVT.getScalarType().getFltSemantics());
+ PosOvfBoundFlt.convertFromAPInt(APInt::getSignedMinValue(32), /*IsSigned=*/true, APFloat::rmTowardZero);
+ PosOvfBoundFlt.changeSign();
+ SDValue PosOvfBound = DAG.getConstantFP(PosOvfBoundFlt, dl, SrcVT);
+ SDValue PosOvf = DAG.getSetCC(dl, DstVT, Src, PosOvfBound, ISD::SETOGE);
+ SDValue IntMax = DAG.getConstant(APInt::getSignedMaxValue(32), dl, DstVT);
+ SDValue Fixed = DAG.getSelect(dl, DstVT, PosOvf, IntMax, Cvt);
+ SDValue IsNaN = DAG.getSetCC(dl, DstVT, Src, Src, ISD::SETUO);
+ SDValue Zero = DAG.getConstant(0, dl, DstVT);
+ return DAG.getSelect(dl, DstVT, IsNaN, Zero, Fixed);
+ } else {
+ SDValue ZeroFP = DAG.getConstantFP(0.0, dl, SrcVT);
+ SDValue Clamped = DAG.getNode(X86ISD::FMAX, dl, SrcVT, Src, ZeroFP);
+ APFloat OvfBoundFlt(SrcVT.getScalarType().getFltSemantics());
+ OvfBoundFlt.convertFromAPInt(APInt::getOneBitSet(33, 32), /*IsSigned=*/false, APFloat::rmTowardZero);
+ SDValue OvfBound = DAG.getConstantFP(OvfBoundFlt, dl, SrcVT);
+ SDValue IsOvf = DAG.getSetCC(dl, DstVT, Clamped, OvfBound, ISD::SETOGE);
+ SDValue Cvt = DAG.getNode(ISD::FP_TO_UINT, dl, DstVT, Clamped);
+ SDValue UintMax = DAG.getConstant(APInt::getMaxValue(32), dl, DstVT);
+ return DAG.getSelect(dl, DstVT, IsOvf, UintMax, Cvt);
+ }
+ }
+
+ APInt MinInt = IsSigned ? APInt::getSignedMinValue(SatWidth)
+ : APInt::getMinValue(SatWidth);
+ APInt MaxInt = IsSigned ? APInt::getSignedMaxValue(SatWidth)
+ : APInt::getMaxValue(SatWidth);
+
+ const fltSemantics &Sem = SrcVT.getFltSemantics();
+ APFloat MinFloat(Sem);
+ APFloat MaxFloat(Sem);
+ // Only use the FMAX/FMIN clamp path when both bounds are exactly
+ // representable in the source float type. If either is inexact, fall back
+ // to generic lowering.
+ bool AreExactFloatBounds =
+ !(MinFloat.convertFromAPInt(MinInt, IsSigned, APFloat::rmTowardZero) &
+ APFloat::opInexact) &&
+ !(MaxFloat.convertFromAPInt(MaxInt, IsSigned, APFloat::rmTowardZero) &
+ APFloat::opInexact);
+ if (!AreExactFloatBounds)
+ return SDValue();
+
+ SDValue MaxC = DAG.getConstantFP(MaxFloat, dl, SrcVT);
+ SDValue MinC = DAG.getConstantFP(MinFloat, dl, SrcVT);
+
+ // Clamp from below. X86ISD::FMAX returns the second operand when either
+ // input is NaN, so NaN maps to MinC here.
+ SDValue ClampedBottom = DAG.getNode(X86ISD::FMAX, dl, SrcVT, Src, MinC);
+ // Clamp from above. NaN (now MinC) is already in range and passes through.
+ SDValue ClampedTop = DAG.getNode(X86ISD::FMIN, dl, SrcVT, ClampedBottom, MaxC);
+ SDValue Result = DAG.getNode(FpToIntOpcode, dl, DstVT, ClampedTop);
+ // For signed saturation, NaN was mapped to MinC, so FP_TO_SINT produces
+ // INT_MIN. ISD::FP_TO_SINT_SAT requires NaN -> 0; fix with a zero-select.
+ // For unsigned saturation, MinC == 0.0, so NaN -> 0.0 -> 0: already correct.
+ if (IsSigned) {
+ SDValue Zero = DAG.getConstant(0, dl, DstVT);
+ SDValue IsNaN = DAG.getSetCC(dl, DstVT, Src, Src, ISD::SETUO);
+ return DAG.getSelect(dl, DstVT, IsNaN, Zero, Result);
+ }
+ return Result;
+ }
// This code is only for floats and doubles. Fall back to generic code for
// anything else.
if (!isScalarFPTypeInSSEReg(SrcVT) || isBF16orSoftF16(SrcVT, Subtarget))
diff --git a/llvm/test/CodeGen/X86/fp-to-int-sat-vector-sse2.ll b/llvm/test/CodeGen/X86/fp-to-int-sat-vector-sse2.ll
new file mode 100644
index 0000000000000..b9ae1157f991f
--- /dev/null
+++ b/llvm/test/CodeGen/X86/fp-to-int-sat-vector-sse2.ll
@@ -0,0 +1,113 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc < %s -mtriple=x86_64 -mattr=+sse2,-avx | FileCheck %s --check-prefix=SSE2
+
+declare <4 x i32> @llvm.fptosi.sat.v4i32.v4f32(<4 x float>)
+declare <4 x i32> @llvm.fptoui.sat.v4i32.v4f32(<4 x float>)
+
+; 1. Base case variables
+define <4 x i32> @test_signed_var(<4 x float> %f) {
+; SSE2-LABEL: test_signed_var:
+; SSE2: # %bb.0:
+; SSE2-NEXT: movaps {{.*#+}} xmm1 = [2.14748365E+9,2.14748365E+9,2.14748365E+9,2.14748365E+9]
+; SSE2-NEXT: cmpleps %xmm0, %xmm1
+; SSE2-NEXT: cvttps2dq %xmm0, %xmm2
+; SSE2-NEXT: movaps %xmm1, %xmm3
+; SSE2-NEXT: andnps %xmm2, %xmm3
+; SSE2-NEXT: andps {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm1
+; SSE2-NEXT: orps %xmm3, %xmm1
+; SSE2-NEXT: cmpunordps %xmm0, %xmm0
+; SSE2-NEXT: andnps %xmm1, %xmm0
+; SSE2-NEXT: retq
+ %x = call <4 x i32> @llvm.fptosi.sat.v4i32.v4f32(<4 x float> %f)
+ ret <4 x i32> %x
+}
+
+define <4 x i32> @test_unsigned_var(<4 x float> %f) {
+; SSE2-LABEL: test_unsigned_var:
+; SSE2: # %bb.0:
+; SSE2-NEXT: xorps %xmm1, %xmm1
+; SSE2-NEXT: maxps %xmm1, %xmm0
+; SSE2-NEXT: cvttps2dq %xmm0, %xmm2
+; SSE2-NEXT: movaps {{.*#+}} xmm1 = [4.2949673E+9,4.2949673E+9,4.2949673E+9,4.2949673E+9]
+; SSE2-NEXT: cmpleps %xmm0, %xmm1
+; SSE2-NEXT: orps %xmm2, %xmm1
+; SSE2-NEXT: psrad $31, %xmm2
+; SSE2-NEXT: subps {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0
+; SSE2-NEXT: cvttps2dq %xmm0, %xmm0
+; SSE2-NEXT: pand %xmm2, %xmm0
+; SSE2-NEXT: orps %xmm0, %xmm1
+; SSE2-NEXT: movaps %xmm1, %xmm0
+; SSE2-NEXT: retq
+ %x = call <4 x i32> @llvm.fptoui.sat.v4i32.v4f32(<4 x float> %f)
+ ret <4 x i32> %x
+}
+
+; 2. Signed edge cases
+define <4 x i32> @test_signed_edge1() {
+ ; NaN, +Inf, -Inf, 0.0
+; SSE2-LABEL: test_signed_edge1:
+; SSE2: # %bb.0:
+; SSE2-NEXT: cvttps2dq {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm1
+; SSE2-NEXT: movaps {{.*#+}} xmm0 = [u,u,NaN,u]
+; SSE2-NEXT: shufps {{.*#+}} xmm0 = xmm0[0,2],xmm1[2,3]
+; SSE2-NEXT: andps {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0
+; SSE2-NEXT: retq
+ %x = call <4 x i32> @llvm.fptosi.sat.v4i32.v4f32(<4 x float> <float 0x7FF8000000000000, float 0x7FF0000000000000, float 0xFFF0000000000000, float 0.0>)
+ ret <4 x i32> %x
+}
+
+define <4 x i32> @test_signed_edge2() {
+ ; exact limits and slight overflow
+ ; 2^31, < -2^31, max f32 < 2^31, -2^31
+; SSE2-LABEL: test_signed_edge2:
+; SSE2: # %bb.0:
+; SSE2-NEXT: movaps {{.*#+}} xmm1 = [2147483647,2147483647,2147483647,2147483647]
+; SSE2-NEXT: cvttps2dq {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0
+; SSE2-NEXT: movss {{.*#+}} xmm0 = xmm1[0],xmm0[1,2,3]
+; SSE2-NEXT: retq
+ %x = call <4 x i32> @llvm.fptosi.sat.v4i32.v4f32(<4 x float> <float 2147483648.0, float -2147483904.0, float 2147483520.0, float -2147483648.0>)
+ ret <4 x i32> %x
+}
+
+; 3. Unsigned edge cases
+define <4 x i32> @test_unsigned_edge1() {
+ ; NaN, -1.0, +Inf, 0.0
+; SSE2-LABEL: test_unsigned_edge1:
+; SSE2: # %bb.0:
+; SSE2-NEXT: xorps %xmm0, %xmm0
+; SSE2-NEXT: movaps {{.*#+}} xmm1 = [NaN,-1.0E+0,+Inf,0.0E+0]
+; SSE2-NEXT: maxps %xmm0, %xmm1
+; SSE2-NEXT: cvttps2dq %xmm1, %xmm2
+; SSE2-NEXT: movaps {{.*#+}} xmm0 = [4.2949673E+9,4.2949673E+9,4.2949673E+9,4.2949673E+9]
+; SSE2-NEXT: cmpleps %xmm1, %xmm0
+; SSE2-NEXT: orps %xmm2, %xmm0
+; SSE2-NEXT: psrad $31, %xmm2
+; SSE2-NEXT: subps {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm1
+; SSE2-NEXT: cvttps2dq %xmm1, %xmm1
+; SSE2-NEXT: pand %xmm2, %xmm1
+; SSE2-NEXT: orps %xmm1, %xmm0
+; SSE2-NEXT: retq
+ %x = call <4 x i32> @llvm.fptoui.sat.v4i32.v4f32(<4 x float> <float 0x7FF8000000000000, float -1.0, float 0x7FF0000000000000, float 0.0>)
+ ret <4 x i32> %x
+}
+
+define <4 x i32> @test_unsigned_edge2() {
+ ; slight below zero, > 2^32, max f32 < 2^32, 2^32 exact
+; SSE2-LABEL: test_unsigned_edge2:
+; SSE2: # %bb.0:
+; SSE2-NEXT: xorps %xmm0, %xmm0
+; SSE2-NEXT: movaps {{.*#+}} xmm1 = [-5.0E-1,4.2949673E+9,4.29496704E+9,4.2949673E+9]
+; SSE2-NEXT: maxps %xmm0, %xmm1
+; SSE2-NEXT: cvttps2dq %xmm1, %xmm2
+; SSE2-NEXT: movaps {{.*#+}} xmm0 = [4.2949673E+9,4.2949673E+9,4.2949673E+9,4.2949673E+9]
+; SSE2-NEXT: cmpleps %xmm1, %xmm0
+; SSE2-NEXT: orps %xmm2, %xmm0
+; SSE2-NEXT: psrad $31, %xmm2
+; SSE2-NEXT: subps {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm1
+; SSE2-NEXT: cvttps2dq %xmm1, %xmm1
+; SSE2-NEXT: pand %xmm2, %xmm1
+; SSE2-NEXT: orps %xmm1, %xmm0
+; SSE2-NEXT: retq
+ %x = call <4 x i32> @llvm.fptoui.sat.v4i32.v4f32(<4 x float> <float -0.5, float 4294967296.0, float 4294967040.0, float 4294967296.0>)
+ ret <4 x i32> %x
+}
diff --git a/llvm/test/CodeGen/X86/fpclamptosat_vec.ll b/llvm/test/CodeGen/X86/fpclamptosat_vec.ll
index 991ce33e58b4c..f8d7eece7c70c 100644
--- a/llvm/test/CodeGen/X86/fpclamptosat_vec.ll
+++ b/llvm/test/CodeGen/X86/fpclamptosat_vec.ll
@@ -227,106 +227,26 @@ entry:
define <4 x i32> @stest_f32i32(<4 x float> %x) nounwind {
; SSE-LABEL: stest_f32i32:
; SSE: # %bb.0: # %entry
-; SSE-NEXT: movaps %xmm0, %xmm1
-; SSE-NEXT: shufps {{.*#+}} xmm1 = xmm1[3,3],xmm0[3,3]
-; SSE-NEXT: cvttss2si %xmm1, %rax
-; SSE-NEXT: movq %rax, %xmm1
-; SSE-NEXT: movaps %xmm0, %xmm2
-; SSE-NEXT: unpckhpd {{.*#+}} xmm2 = xmm2[1],xmm0[1]
-; SSE-NEXT: cvttss2si %xmm2, %rax
-; SSE-NEXT: movq %rax, %xmm2
-; SSE-NEXT: punpcklqdq {{.*#+}} xmm2 = xmm2[0],xmm1[0]
-; SSE-NEXT: cvttss2si %xmm0, %rax
-; SSE-NEXT: movq %rax, %xmm4
-; SSE-NEXT: shufps {{.*#+}} xmm0 = xmm0[1,1,1,1]
-; SSE-NEXT: cvttss2si %xmm0, %rax
-; SSE-NEXT: movq %rax, %xmm0
-; SSE-NEXT: punpcklqdq {{.*#+}} xmm4 = xmm4[0],xmm0[0]
-; SSE-NEXT: movdqa {{.*#+}} xmm3 = [2147483647,2147483647]
-; SSE-NEXT: movdqa {{.*#+}} xmm0 = [2147483648,2147483648]
-; SSE-NEXT: movdqa %xmm4, %xmm1
-; SSE-NEXT: pxor %xmm0, %xmm1
-; SSE-NEXT: pshufd {{.*#+}} xmm5 = xmm1[1,1,3,3]
-; SSE-NEXT: pxor %xmm6, %xmm6
-; SSE-NEXT: pcmpeqd %xmm6, %xmm5
-; SSE-NEXT: movdqa {{.*#+}} xmm7 = [4294967295,4294967295]
-; SSE-NEXT: movdqa %xmm7, %xmm8
-; SSE-NEXT: pcmpgtd %xmm1, %xmm8
-; SSE-NEXT: pshufd {{.*#+}} xmm9 = xmm8[0,0,2,2]
-; SSE-NEXT: pand %xmm5, %xmm9
-; SSE-NEXT: pshufd {{.*#+}} xmm1 = xmm8[1,1,3,3]
-; SSE-NEXT: por %xmm9, %xmm1
-; SSE-NEXT: pand %xmm1, %xmm4
-; SSE-NEXT: pandn %xmm3, %xmm1
-; SSE-NEXT: por %xmm4, %xmm1
-; SSE-NEXT: movdqa %xmm2, %xmm4
-; SSE-NEXT: pxor %xmm0, %xmm4
-; SSE-NEXT: pshufd {{.*#+}} xmm5 = xmm4[1,1,3,3]
-; SSE-NEXT: pcmpeqd %xmm6, %xmm5
-; SSE-NEXT: pcmpgtd %xmm4, %xmm7
-; SSE-NEXT: pshufd {{.*#+}} xmm4 = xmm7[0,0,2,2]
-; SSE-NEXT: pand %xmm5, %xmm4
-; SSE-NEXT: pshufd {{.*#+}} xmm5 = xmm7[1,1,3,3]
-; SSE-NEXT: por %xmm4, %xmm5
-; SSE-NEXT: pand %xmm5, %xmm2
-; SSE-NEXT: pandn %xmm3, %xmm5
-; SSE-NEXT: por %xmm2, %xmm5
-; SSE-NEXT: movdqa {{.*#+}} xmm2 = [18446744071562067968,18446744071562067968]
-; SSE-NEXT: movdqa %xmm5, %xmm3
-; SSE-NEXT: pxor %xmm0, %xmm3
-; SSE-NEXT: pshufd {{.*#+}} xmm4 = xmm3[1,1,3,3]
-; SSE-NEXT: pcmpeqd %xmm6, %xmm6
-; SSE-NEXT: pcmpeqd %xmm6, %xmm4
-; SSE-NEXT: movdqa {{.*#+}} xmm7 = [18446744069414584320,18446744069414584320]
-; SSE-NEXT: pcmpgtd %xmm7, %xmm3
-; SSE-NEXT: pshufd {{.*#+}} xmm8 = xmm3[0,0,2,2]
-; SSE-NEXT: pand %xmm4, %xmm8
-; SSE-NEXT: pshufd {{.*#+}} xmm3 = xmm3[1,1,3,3]
-; SSE-NEXT: por %xmm8, %xmm3
-; SSE-NEXT: pand %xmm3, %xmm5
-; SSE-NEXT: pandn %xmm2, %xmm3
-; SSE-NEXT: por %xmm5, %xmm3
-; SSE-NEXT: pxor %xmm1, %xmm0
-; SSE-NEXT: pshufd {{.*#+}} xmm4 = xmm0[1,1,3,3]
-; SSE-NEXT: pcmpeqd %xmm6, %xmm4
-; SSE-NEXT: pcmpgtd %xmm7, %xmm0
-; SSE-NEXT: pshufd {{.*#+}} xmm5 = xmm0[0,0,2,2]
-; SSE-NEXT: pand %xmm4, %xmm5
-; SSE-NEXT: pshufd {{.*#+}} xmm0 = xmm0[1,1,3,3]
-; SSE-NEXT: por %xmm5, %xmm0
-; SSE-NEXT: pand %xmm0, %xmm1
-; SSE-NEXT: pandn %xmm2, %xmm0
-; SSE-NEXT: por %xmm1, %xmm0
-; SSE-NEXT: shufps {{.*#+}} xmm0 = xmm0[0,2],xmm3[0,2]
+; SSE-NEXT: movaps {{.*#+}} xmm1 = [2.14748365E+9,2.14748365E+9,2.14748365E+9,2.14748365E+9]
+; SSE-NEXT: cmpleps %xmm0, %xmm1
+; SSE-NEXT: cvttps2dq %xmm0, %xmm2
+; SSE-NEXT: movaps %xmm1, %xmm3
+; SSE-NEXT: andnps %xmm2, %xmm3
+; SSE-NEXT: andps {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm1
+; SSE-NEXT: orps %xmm3, %xmm1
+; SSE-NEXT: cmpunordps %xmm0, %xmm0
+; SSE-NEXT: andnps %xmm1, %xmm0
; SSE-NEXT: retq
;
; AVX2-LABEL: stest_f32i32:
; AVX2: # %bb.0: # %entry
-; AVX2-NEXT: vshufps {{.*#+}} xmm1 = xmm0[3,3,3,3]
-; AVX2-NEXT: vcvttss2si %xmm1, %rax
-; AVX2-NEXT: vmovq %rax, %xmm1
-; AVX2-NEXT: vshufpd {{.*#+}} xmm2 = xmm0[1,0]
-; AVX2-NEXT: vcvttss2si %xmm2, %rax
-; AVX2-NEXT: vmovq %rax, %xmm2
-; AVX2-NEXT: vpunpcklqdq {{.*#+}} xmm1 = xmm2[0],xmm1[0]
-; AVX2-NEXT: vcvttss2si %xmm0, %rax
-; AVX2-NEXT: vmovq %rax, %xmm2
-; AVX2-NEXT: vmovshdup {{.*#+}} xmm0 = xmm0[1,1,3,3]
-; AVX2-NEXT: vcvttss2si %xmm0, %rax
-; AVX2-NEXT: vmovq %rax, %xmm0
-; AVX2-NEXT: vpunpcklqdq {{.*#+}} xmm0 = xmm2[0],xmm0[0]
-; AVX2-NEXT: vinserti128 $1, %xmm1, %ymm0, %ymm0
-; AVX2-NEXT: vpbroadcastq {{.*#+}} ymm1 = [2147483647,2147483647,2147483647,2147483647]
-; AVX2-NEXT: vpcmpgtq %ymm0, %ymm1, %ymm2
-; AVX2-NEXT: vblendvpd %ymm2, %ymm0, %ymm1, %ymm0
-; AVX2-NEXT: vpbroadcastq {{.*#+}} ymm1 = [18446744071562067968,18446744071562067968,18446744071562067968,18446744071562067968]
-; AVX2-NEXT: vpcmpgtq %ymm1, %ymm0, %ymm2
-; AVX2-NEXT: vblendvpd %ymm2, %ymm0, %ymm1, %ymm0
-; AVX2-NEXT: vbroadcastf128 {{.*#+}} ymm1 = [0,2,4,6,0,2,4,6]
-; AVX2-NEXT: # ymm1 = mem[0,1,0,1]
-; AVX2-NEXT: vpermps %ymm0, %ymm1, %ymm0
-; AVX2-NEXT: # kill: def $xmm0 killed $xmm0 killed $ymm0
-; AVX2-NEXT: vzeroupper
+; AVX2-NEXT: vbroadcastss {{.*#+}} xmm1 = [2.14748365E+9,2.14748365E+9,2.14748365E+9,2.14748365E+9]
+; AVX2-NEXT: vcmpleps %xmm0, %xmm1, %xmm1
+; AVX2-NEXT: vcvttps2dq %xmm0, %xmm2
+; AVX2-NEXT: vbroadcastss {{.*#+}} xmm3 = [2147483647,2147483647,2147483647,2147483647]
+; AVX2-NEXT: vblendvps %xmm1, %xmm3, %xmm2, %xmm1
+; AVX2-NEXT: vcmpunordps %xmm0, %xmm0, %xmm0
+; AVX2-NEXT: vandnps %xmm1, %xmm0, %xmm0
; AVX2-NEXT: retq
;
; AVX512-LABEL: stest_f32i32:
@@ -604,130 +524,121 @@ entry:
define <4 x i32> @stest_f16i32(<4 x half> %x) nounwind {
; SSE-LABEL: stest_f16i32:
; SSE: # %bb.0: # %entry
-; SSE-NEXT: subq $72, %rsp
-; SSE-NEXT: movdqa %xmm0, (%rsp) # 16-byte Spill
+; SSE-NEXT: pushq %rbp
+; SSE-NEXT: pushq %r14
+; SSE-NEXT: pushq %rbx
+; SSE-NEXT: subq $64, %rsp
+; SSE-NEXT: movdqa %xmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill
; SSE-NEXT: movdqa %xmm0, %xmm1
; SSE-NEXT: psrld $16, %xmm1
; SSE-NEXT: movdqa %xmm1, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill
; SSE-NEXT: movdqa %xmm0, %xmm1
; SSE-NEXT: shufps {{.*#+}} xmm1 = xmm1[1,1],xmm0[1,1]
-; SSE-NEXT: movaps %xmm1, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill
+; SSE-NEXT: movaps %xmm1, (%rsp) # 16-byte Spill
; SSE-NEXT: psrlq $48, %xmm0
; SSE-NEXT: callq __extendhfsf2 at PLT
-; SSE-NEXT: cvttss2si %xmm0, %rax
-; SSE-NEXT: movq %rax, %xmm0
-; SSE-NEXT: movdqa %xmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill
-; SSE-NEXT: movaps {{[-0-9]+}}(%r{{[sb]}}p), %xmm0 # 16-byte Reload
-; SSE-NEXT: callq __extendhfsf2 at PLT
-; SSE-NEXT: cvttss2si %xmm0, %rax
-; SSE-NEXT: movq %rax, %xmm0
-; SSE-NEXT: punpcklqdq {{[-0-9]+}}(%r{{[sb]}}p), %xmm0 # 16-byte Folded Reload
-; SSE-NEXT: # xmm0 = xmm0[0],mem[0]
+; SSE-NEXT: cvttss2si %xmm0, %eax
+; SSE-NEXT: ucomiss {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0
+; SSE-NEXT: movl $-2147483648, %ebx # imm = 0x80000000
+; SSE-NEXT: cmovbl %ebx, %eax
+; SSE-NEXT: ucomiss {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0
+; SSE-NEXT: movl $2147483647, %ebp # imm = 0x7FFFFFFF
+; SSE-NEXT: cmoval %ebp, %eax
+; SSE-NEXT: xorl %r14d, %r14d
+; SSE-NEXT: ucomiss %xmm0, %xmm0
+; SSE-NEXT: cmovpl %r14d, %eax
+; SSE-NEXT: movd %eax, %xmm0
; SSE-NEXT: movdqa %xmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill
; SSE-NEXT: movaps (%rsp), %xmm0 # 16-byte Reload
; SSE-NEXT: callq __extendhfsf2 at PLT
-; SSE-NEXT: cvttss2si %xmm0, %rax
-; SSE-NEXT: movq %rax, %xmm0
+; SSE-NEXT: cvttss2si %xmm0, %eax
+; SSE-NEXT: ucomiss {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0
+; SSE-NEXT: cmovbl %ebx, %eax
+; SSE-NEXT: ucomiss {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0
+; SSE-NEXT: cmoval %ebp, %eax
+; SSE-NEXT: ucomiss %xmm0, %xmm0
+; SSE-NEXT: cmovpl %r14d, %eax
+; SSE-NEXT: movd %eax, %xmm0
+; SSE-NEXT: punpckldq {{[-0-9]+}}(%r{{[sb]}}p), %xmm0 # 16-byte Folded Reload
+; SSE-NEXT: # xmm0 = xmm0[0],mem[0],xmm0[1],mem[1]
; SSE-NEXT: movdqa %xmm0, (%rsp) # 16-byte Spill
; SSE-NEXT: movaps {{[-0-9]+}}(%r{{[sb]}}p), %xmm0 # 16-byte Reload
; SSE-NEXT: callq __extendhfsf2 at PLT
-; SSE-NEXT: cvttss2si %xmm0, %rax
-; SSE-NEXT: movq %rax, %xmm0
-; SSE-NEXT: movdqa (%rsp), %xmm3 # 16-byte Reload
-; SSE-NEXT: punpcklqdq {{.*#+}} xmm3 = xmm3[0],xmm0[0]
-; SSE-NEXT: movdqa {{.*#+}} xmm2 = [2147483647,2147483647]
-; SSE-NEXT: movdqa {{.*#+}} xmm0 = [2147483648,2147483648]
-; SSE-NEXT: movdqa %xmm3, %xmm1
-; SSE-NEXT: movdqa %xmm3, %xmm8
-; SSE-NEXT: pxor %xmm0, %xmm1
-; SSE-NEXT: pshufd {{.*#+}} xmm3 = xmm1[1,1,3,3]
-; SSE-NEXT: pxor %xmm4, %xmm4
-; SSE-NEXT: pcmpeqd %xmm4, %xmm3
-; SSE-NEXT: movdqa {{.*#+}} xmm5 = [4294967295,4294967295]
-; SSE-NEXT: movdqa %xmm5, %xmm6
-; SSE-NEXT: pcmpgtd %xmm1, %xmm6
-; SSE-NEXT: pshufd {{.*#+}} xmm7 = xmm6[0,0,2,2]
-; SSE-NEXT: pand %xmm3, %xmm7
-; SSE-NEXT: pshufd {{.*#+}} xmm1 = xmm6[1,1,3,3]
-; SSE-NEXT: por %xmm7, %xmm1
-; SSE-NEXT: pand %xmm1, %xmm8
-; SSE-NEXT: pandn %xmm2, %xmm1
-; SSE-NEXT: por %xmm8, %xmm1
-; SSE-NEXT: movdqa {{[-0-9]+}}(%r{{[sb]}}p), %xmm7 # 16-byte Reload
-; SSE-NEXT: movdqa %xmm7, %xmm3
-; SSE-NEXT: pxor %xmm0, %xmm3
-; SSE-NEXT: pshufd {{.*#+}} xmm6 = xmm3[1,1,3,3]
-; SSE-NEXT: pcmpeqd %xmm4, %xmm6
-; SSE-NEXT: pcmpgtd %xmm3, %xmm5
-; SSE-NEXT: pshufd {{.*#+}} xmm3 = xmm5[0,0,2,2]
-; SSE-NEXT: pand %xmm6, %xmm3
-; SSE-NEXT: pshufd {{.*#+}} xmm4 = xmm5[1,1,3,3]
-; SSE-NEXT: por %xmm3, %xmm4
-; SSE-NEXT: movdqa %xmm7, %xmm3
-; SSE-NEXT: pand %xmm4, %xmm3
-; SSE-NEXT: pandn %xmm2, %xmm4
-; SSE-NEXT: por %xmm3, %xmm4
-; SSE-NEXT: movdqa {{.*#+}} xmm2 = [18446744071562067968,18446744071562067968]
-; SSE-NEXT: movdqa %xmm4, %xmm3
-; SSE-NEXT: pxor %xmm0, %xmm3
-; SSE-NEXT: pshufd {{.*#+}} xmm5 = xmm3[1,1,3,3]
-; SSE-NEXT: pcmpeqd %xmm6, %xmm6
-; SSE-NEXT: pcmpeqd %xmm6, %xmm5
-; SSE-NEXT: movdqa {{.*#+}} xmm7 = [18446744069414584320,18446744069414584320]
-; SSE-NEXT: pcmpgtd %xmm7, %xmm3
-; SSE-NEXT: pshufd {{.*#+}} xmm8 = xmm3[0,0,2,2]
-; SSE-NEXT: pand %xmm5, %xmm8
-; SSE-NEXT: pshufd {{.*#+}} xmm3 = xmm3[1,1,3,3]
-; SSE-NEXT: por %xmm8, %xmm3
-; SSE-NEXT: pand %xmm3, %xmm4
-; SSE-NEXT: pandn %xmm2, %xmm3
-; SSE-NEXT: por %xmm4, %xmm3
-; SSE-NEXT: pxor %xmm1, %xmm0
-; SSE-NEXT: pshufd {{.*#+}} xmm4 = xmm0[1,1,3,3]
-; SSE-NEXT: pcmpeqd %xmm6, %xmm4
-; SS...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/199416
More information about the llvm-commits
mailing list