[X86] Add custom lowering for v2i64->v2f32 strict_sint_to_fp/strict_uint_to_fp for...
authorCraig Topper <craig.topper@gmail.com>
Thu, 26 Dec 2019 08:04:37 +0000 (00:04 -0800)
committerCraig Topper <craig.topper@gmail.com>
Thu, 26 Dec 2019 16:58:34 +0000 (08:58 -0800)
With avx512dq+avx512vl we have instruction that implements this and
places zeroes in the upper 64-bits of the destination xmm register.

llvm/lib/Target/X86/X86ISelLowering.cpp
llvm/test/CodeGen/X86/vec-strict-inttofp-128.ll

index 66a1174..31fb67b 100644 (file)
@@ -1000,6 +1000,7 @@ X86TargetLowering::X86TargetLowering(const X86TargetMachine &TM,
     setOperationAction(ISD::STRICT_UINT_TO_FP,  MVT::v2i32, Custom);
 
     // Fast v2f32 UINT_TO_FP( v2i32 ) custom conversion.
+    // FIXME: Does this apply to STRICT_UINT_TO_FP?
     setOperationAction(ISD::UINT_TO_FP,         MVT::v2f32, Custom);
 
     setOperationAction(ISD::FP_EXTEND,          MVT::v2f32, Custom);
@@ -1843,9 +1844,11 @@ X86TargetLowering::X86TargetLowering(const X86TargetMachine &TM,
     if (Subtarget.hasDQI()) {
       // Fast v2f32 SINT_TO_FP( v2i64 ) custom conversion.
       // v2f32 UINT_TO_FP is already custom under SSE2.
-      setOperationAction(ISD::SINT_TO_FP,    MVT::v2f32, Custom);
+      setOperationAction(ISD::SINT_TO_FP,        MVT::v2f32, Custom);
+      setOperationAction(ISD::STRICT_SINT_TO_FP, MVT::v2f32, Custom);
       assert(isOperationCustom(ISD::UINT_TO_FP, MVT::v2f32) &&
              "Unexpected operation action!");
+      setOperationAction(ISD::STRICT_UINT_TO_FP,  MVT::v2f32, Custom);
       // v2i64 FP_TO_S/UINT(v2f32) custom conversion.
       setOperationAction(ISD::FP_TO_SINT,        MVT::v2f32, Custom);
       setOperationAction(ISD::FP_TO_UINT,        MVT::v2f32, Custom);
@@ -28778,26 +28781,47 @@ void X86TargetLowering::ReplaceNodeResults(SDNode *N,
     }
     return;
   }
-  case ISD::SINT_TO_FP: {
+  case ISD::SINT_TO_FP:
+  case ISD::STRICT_SINT_TO_FP: {
     assert(Subtarget.hasDQI() && Subtarget.hasVLX() && "Requires AVX512DQVL!");
-    SDValue Src = N->getOperand(0);
+    bool IsStrict = N->isStrictFPOpcode();
+    SDValue Src = N->getOperand(IsStrict ? 1 : 0);
     if (N->getValueType(0) != MVT::v2f32 || Src.getValueType() != MVT::v2i64)
       return;
-    Results.push_back(DAG.getNode(X86ISD::CVTSI2P, dl, MVT::v4f32, Src));
+    if (IsStrict) {
+      SDValue Res =
+          DAG.getNode(X86ISD::STRICT_CVTSI2P, dl, {MVT::v4f32, MVT::Other},
+                      {N->getOperand(0), Src});
+      Results.push_back(Res);
+      Results.push_back(Res.getValue(1));
+    } else {
+      Results.push_back(DAG.getNode(X86ISD::CVTSI2P, dl, MVT::v4f32, Src));
+    }
     return;
   }
-  case ISD::UINT_TO_FP: {
+  case ISD::UINT_TO_FP:
+  case ISD::STRICT_UINT_TO_FP: {
     assert(Subtarget.hasSSE2() && "Requires at least SSE2!");
+    bool IsStrict = N->isStrictFPOpcode();
     EVT VT = N->getValueType(0);
     if (VT != MVT::v2f32)
       return;
-    SDValue Src = N->getOperand(0);
+    SDValue Src = N->getOperand(IsStrict ? 1 : 0);
     EVT SrcVT = Src.getValueType();
     if (Subtarget.hasDQI() && Subtarget.hasVLX() && SrcVT == MVT::v2i64) {
-      Results.push_back(DAG.getNode(X86ISD::CVTUI2P, dl, MVT::v4f32, Src));
+      if (IsStrict) {
+        SDValue Res =
+            DAG.getNode(X86ISD::STRICT_CVTUI2P, dl, {MVT::v4f32, MVT::Other},
+                        {N->getOperand(0), Src});
+        Results.push_back(Res);
+        Results.push_back(Res.getValue(1));
+      } else {
+        Results.push_back(DAG.getNode(X86ISD::CVTUI2P, dl, MVT::v4f32, Src));
+      }
       return;
     }
-    if (SrcVT != MVT::v2i32)
+    // FIXME: Is this safe for strict fp?
+    if (SrcVT != MVT::v2i32 || IsStrict)
       return;
     SDValue ZExtIn = DAG.getNode(ISD::ZERO_EXTEND, dl, MVT::v2i64, Src);
     SDValue VBias =
index 4b44152..c68c612 100644 (file)
@@ -121,24 +121,10 @@ define <2 x float> @sitofp_v2i64_v2f32(<2 x i64> %x) #0 {
 ; AVX512DQ-64-NEXT:    vinsertps {{.*#+}} xmm0 = xmm0[0],xmm1[0],xmm0[2,3]
 ; AVX512DQ-64-NEXT:    retq
 ;
-; AVX512DQVL-32-LABEL: sitofp_v2i64_v2f32:
-; AVX512DQVL-32:       # %bb.0:
-; AVX512DQVL-32-NEXT:    # kill: def $xmm0 killed $xmm0 def $ymm0
-; AVX512DQVL-32-NEXT:    vcvtqq2ps %ymm0, %xmm1
-; AVX512DQVL-32-NEXT:    vpermilps {{.*#+}} xmm0 = xmm0[2,3,0,1]
-; AVX512DQVL-32-NEXT:    vcvtqq2ps %ymm0, %xmm0
-; AVX512DQVL-32-NEXT:    vinsertps {{.*#+}} xmm0 = xmm1[0],xmm0[0],zero,zero
-; AVX512DQVL-32-NEXT:    vzeroupper
-; AVX512DQVL-32-NEXT:    retl
-;
-; AVX512DQVL-64-LABEL: sitofp_v2i64_v2f32:
-; AVX512DQVL-64:       # %bb.0:
-; AVX512DQVL-64-NEXT:    vpextrq $1, %xmm0, %rax
-; AVX512DQVL-64-NEXT:    vcvtsi2ss %rax, %xmm1, %xmm1
-; AVX512DQVL-64-NEXT:    vmovq %xmm0, %rax
-; AVX512DQVL-64-NEXT:    vcvtsi2ss %rax, %xmm2, %xmm0
-; AVX512DQVL-64-NEXT:    vinsertps {{.*#+}} xmm0 = xmm0[0],xmm1[0],xmm0[2,3]
-; AVX512DQVL-64-NEXT:    retq
+; AVX512DQVL-LABEL: sitofp_v2i64_v2f32:
+; AVX512DQVL:       # %bb.0:
+; AVX512DQVL-NEXT:    vcvtqq2ps %xmm0, %xmm0
+; AVX512DQVL-NEXT:    ret{{[l|q]}}
  %result = call <2 x float> @llvm.experimental.constrained.sitofp.v2f32.v2i64(<2 x i64> %x,
                                                               metadata !"round.dynamic",
                                                               metadata !"fpexcept.strict") #0
@@ -318,24 +304,10 @@ define <2 x float> @uitofp_v2i64_v2f32(<2 x i64> %x) #0 {
 ; AVX512DQ-64-NEXT:    vinsertps {{.*#+}} xmm0 = xmm0[0],xmm1[0],xmm0[2,3]
 ; AVX512DQ-64-NEXT:    retq
 ;
-; AVX512DQVL-32-LABEL: uitofp_v2i64_v2f32:
-; AVX512DQVL-32:       # %bb.0:
-; AVX512DQVL-32-NEXT:    # kill: def $xmm0 killed $xmm0 def $ymm0
-; AVX512DQVL-32-NEXT:    vcvtuqq2ps %ymm0, %xmm1
-; AVX512DQVL-32-NEXT:    vpermilps {{.*#+}} xmm0 = xmm0[2,3,0,1]
-; AVX512DQVL-32-NEXT:    vcvtuqq2ps %ymm0, %xmm0
-; AVX512DQVL-32-NEXT:    vinsertps {{.*#+}} xmm0 = xmm1[0],xmm0[0],zero,zero
-; AVX512DQVL-32-NEXT:    vzeroupper
-; AVX512DQVL-32-NEXT:    retl
-;
-; AVX512DQVL-64-LABEL: uitofp_v2i64_v2f32:
-; AVX512DQVL-64:       # %bb.0:
-; AVX512DQVL-64-NEXT:    vpextrq $1, %xmm0, %rax
-; AVX512DQVL-64-NEXT:    vcvtusi2ss %rax, %xmm1, %xmm1
-; AVX512DQVL-64-NEXT:    vmovq %xmm0, %rax
-; AVX512DQVL-64-NEXT:    vcvtusi2ss %rax, %xmm2, %xmm0
-; AVX512DQVL-64-NEXT:    vinsertps {{.*#+}} xmm0 = xmm0[0],xmm1[0],xmm0[2,3]
-; AVX512DQVL-64-NEXT:    retq
+; AVX512DQVL-LABEL: uitofp_v2i64_v2f32:
+; AVX512DQVL:       # %bb.0:
+; AVX512DQVL-NEXT:    vcvtuqq2ps %xmm0, %xmm0
+; AVX512DQVL-NEXT:    ret{{[l|q]}}
  %result = call <2 x float> @llvm.experimental.constrained.uitofp.v2f32.v2i64(<2 x i64> %x,
                                                               metadata !"round.dynamic",
                                                               metadata !"fpexcept.strict") #0