diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.h b/llvm/lib/Target/AArch64/AArch64ISelLowering.h --- a/llvm/lib/Target/AArch64/AArch64ISelLowering.h +++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.h @@ -970,6 +970,7 @@ SDValue LowerFP_EXTEND(SDValue Op, SelectionDAG &DAG) const; SDValue LowerFP_ROUND(SDValue Op, SelectionDAG &DAG) const; SDValue LowerVectorFP_TO_INT(SDValue Op, SelectionDAG &DAG) const; + SDValue LowerVectorFP_TO_INT_SAT(SDValue Op, SelectionDAG &DAG) const; SDValue LowerFP_TO_INT(SDValue Op, SelectionDAG &DAG) const; SDValue LowerFP_TO_INT_SAT(SDValue Op, SelectionDAG &DAG) const; SDValue LowerINT_TO_FP(SDValue Op, SelectionDAG &DAG) const; diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp --- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp +++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp @@ -998,6 +998,9 @@ setOperationAction(ISD::UINT_TO_FP, MVT::v1i64, Expand); setOperationAction(ISD::FP_ROUND, MVT::v1f64, Expand); + setOperationAction(ISD::FP_TO_SINT_SAT, MVT::v1i64, Expand); + setOperationAction(ISD::FP_TO_UINT_SAT, MVT::v1i64, Expand); + setOperationAction(ISD::MUL, MVT::v1i64, Expand); // AArch64 doesn't have a direct vector ->f32 conversion instructions for @@ -1461,6 +1464,8 @@ setOperationAction(ISD::FP_TO_SINT, VT, Custom); setOperationAction(ISD::FP_TO_UINT, VT, Custom); + setOperationAction(ISD::FP_TO_SINT_SAT, VT, Custom); + setOperationAction(ISD::FP_TO_UINT_SAT, VT, Custom); if (!VT.isFloatingPoint()) setOperationAction(ISD::ABS, VT, Legal); @@ -3382,31 +3387,77 @@ return SDValue(); } +SDValue +AArch64TargetLowering::LowerVectorFP_TO_INT_SAT(SDValue Op, + SelectionDAG &DAG) const { + // AArch64 FP-to-int conversions saturate to the destination element size, so + // we can lower common saturating conversions to simple instructions. + SDValue SrcVal = Op.getOperand(0); + EVT SrcVT = SrcVal.getValueType(); + EVT DstVT = Op.getValueType(); + EVT SatVT = cast(Op.getOperand(1))->getVT(); + + uint64_t SrcElementWidth = SrcVT.getScalarSizeInBits(); + uint64_t DstElementWidth = DstVT.getScalarSizeInBits(); + uint64_t SatWidth = SatVT.getScalarSizeInBits(); + assert(SatWidth <= DstElementWidth && + "Saturation width cannot exceed result width"); + + // TODO: Consider lowering to SVE operations, as in LowerVectorFP_TO_INT. + // Currently, the `llvm.fpto[su]i.sat.*` instrinsics don't accept scalable + // types, so this is hard to reach. + if (DstVT.isScalableVector()) + return SDValue(); + + // TODO: Saturate to SatWidth explicitly. + if (SatWidth != DstElementWidth) + return SDValue(); + + EVT SrcElementVT = SrcVT.getVectorElementType(); + + // In the absence of FP16 support, promote f16 to f32, like + // LowerVectorFP_TO_INT(). + if (SrcElementVT == MVT::f16 && !Subtarget->hasFullFP16()) { + MVT F32VT = MVT::getVectorVT(MVT::f32, SrcVT.getVectorNumElements()); + return DAG.getNode(Op.getOpcode(), SDLoc(Op), DstVT, + DAG.getNode(ISD::FP_EXTEND, SDLoc(Op), F32VT, SrcVal), + Op.getOperand(1)); + } + + // Cases that we can emit directly. + if ((SrcElementWidth == DstElementWidth) && + (SrcElementVT == MVT::f64 || SrcElementVT == MVT::f32 || + (SrcElementVT == MVT::f16 && Subtarget->hasFullFP16()))) { + return Op; + } + + // For all other cases, fall back on the expanded form. + return SDValue(); +} + SDValue AArch64TargetLowering::LowerFP_TO_INT_SAT(SDValue Op, SelectionDAG &DAG) const { // AArch64 FP-to-int conversions saturate to the destination register size, so // we can lower common saturating conversions to simple instructions. SDValue SrcVal = Op.getOperand(0); - EVT SrcVT = SrcVal.getValueType(); - EVT DstVT = Op.getValueType(); + if (SrcVT.isVector()) + return LowerVectorFP_TO_INT_SAT(Op, DAG); + + EVT DstVT = Op.getValueType(); EVT SatVT = cast(Op.getOperand(1))->getVT(); uint64_t SatWidth = SatVT.getScalarSizeInBits(); uint64_t DstWidth = DstVT.getScalarSizeInBits(); assert(SatWidth <= DstWidth && "Saturation width cannot exceed result width"); - // TODO: Support lowering of NEON and SVE conversions. - if (SrcVT.isVector()) - return SDValue(); - // TODO: Saturate to SatWidth explicitly. if (SatWidth != DstWidth) return SDValue(); - // In the absence of FP16 support, promote f32 to f16, like LowerFP_TO_INT(). + // In the absence of FP16 support, promote f16 to f32, like LowerFP_TO_INT(). if (SrcVT == MVT::f16 && !Subtarget->hasFullFP16()) - return DAG.getNode(Op.getOpcode(), SDLoc(Op), Op.getValueType(), + return DAG.getNode(Op.getOpcode(), SDLoc(Op), DstVT, DAG.getNode(ISD::FP_EXTEND, SDLoc(Op), MVT::f32, SrcVal), Op.getOperand(1)); diff --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.td b/llvm/lib/Target/AArch64/AArch64InstrInfo.td --- a/llvm/lib/Target/AArch64/AArch64InstrInfo.td +++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.td @@ -4148,6 +4148,22 @@ defm FCVTZS : SIMDTwoVectorFPToInt<0, 1, 0b11011, "fcvtzs", fp_to_sint>; defm FCVTZU : SIMDTwoVectorFPToInt<1, 1, 0b11011, "fcvtzu", fp_to_uint>; +// AArch64's FCVT instructions saturate when out of range. +multiclass SIMDTwoVectorFPToIntSatPats { + def : Pat<(v4i16 (to_int_sat v4f16:$Rn, i16)), + (!cast(INST # v4f16) v4f16:$Rn)>; + def : Pat<(v8i16 (to_int_sat v8f16:$Rn, i16)), + (!cast(INST # v8f16) v8f16:$Rn)>; + def : Pat<(v2i32 (to_int_sat v2f32:$Rn, i32)), + (!cast(INST # v2f32) v2f32:$Rn)>; + def : Pat<(v4i32 (to_int_sat v4f32:$Rn, i32)), + (!cast(INST # v4f32) v4f32:$Rn)>; + def : Pat<(v2i64 (to_int_sat v2f64:$Rn, i64)), + (!cast(INST # v2f64) v2f64:$Rn)>; +} +defm : SIMDTwoVectorFPToIntSatPats; +defm : SIMDTwoVectorFPToIntSatPats; + def : Pat<(v4i16 (int_aarch64_neon_fcvtzs v4f16:$Rn)), (FCVTZSv4f16 $Rn)>; def : Pat<(v8i16 (int_aarch64_neon_fcvtzs v8f16:$Rn)), (FCVTZSv8f16 $Rn)>; def : Pat<(v2i32 (int_aarch64_neon_fcvtzs v2f32:$Rn)), (FCVTZSv2f32 $Rn)>; diff --git a/llvm/test/CodeGen/AArch64/fptosi-sat-vector.ll b/llvm/test/CodeGen/AArch64/fptosi-sat-vector.ll --- a/llvm/test/CodeGen/AArch64/fptosi-sat-vector.ll +++ b/llvm/test/CodeGen/AArch64/fptosi-sat-vector.ll @@ -1,5 +1,6 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc -mtriple=aarch64 < %s | FileCheck %s +; RUN: llc < %s -mtriple=aarch64 | FileCheck %s --check-prefixes=CHECK,CHECK-CVT +; RUN: llc < %s -mtriple=aarch64 -mattr=+fullfp16 | FileCheck %s --check-prefixes=CHECK,CHECK-FP16 ; ; Float to signed 32-bit -- Vector size variation @@ -17,13 +18,7 @@ define <1 x i32> @test_signed_v1f32_v1i32(<1 x float> %f) { ; CHECK-LABEL: test_signed_v1f32_v1i32: ; CHECK: // %bb.0: -; CHECK-NEXT: // kill: def $d0 killed $d0 def $q0 -; CHECK-NEXT: fcvtzs w8, s0 -; CHECK-NEXT: mov s1, v0.s[1] -; CHECK-NEXT: fmov s0, w8 -; CHECK-NEXT: fcvtzs w8, s1 -; CHECK-NEXT: mov v0.s[1], w8 -; CHECK-NEXT: // kill: def $d0 killed $d0 killed $q0 +; CHECK-NEXT: fcvtzs v0.2s, v0.2s ; CHECK-NEXT: ret %x = call <1 x i32> @llvm.fptosi.sat.v1f32.v1i32(<1 x float> %f) ret <1 x i32> %x @@ -32,13 +27,7 @@ define <2 x i32> @test_signed_v2f32_v2i32(<2 x float> %f) { ; CHECK-LABEL: test_signed_v2f32_v2i32: ; CHECK: // %bb.0: -; CHECK-NEXT: // kill: def $d0 killed $d0 def $q0 -; CHECK-NEXT: fcvtzs w8, s0 -; CHECK-NEXT: mov s1, v0.s[1] -; CHECK-NEXT: fmov s0, w8 -; CHECK-NEXT: fcvtzs w8, s1 -; CHECK-NEXT: mov v0.s[1], w8 -; CHECK-NEXT: // kill: def $d0 killed $d0 killed $q0 +; CHECK-NEXT: fcvtzs v0.2s, v0.2s ; CHECK-NEXT: ret %x = call <2 x i32> @llvm.fptosi.sat.v2f32.v2i32(<2 x float> %f) ret <2 x i32> %x @@ -47,17 +36,7 @@ define <3 x i32> @test_signed_v3f32_v3i32(<3 x float> %f) { ; CHECK-LABEL: test_signed_v3f32_v3i32: ; CHECK: // %bb.0: -; CHECK-NEXT: fcvtzs w8, s0 -; CHECK-NEXT: mov s1, v0.s[1] -; CHECK-NEXT: mov s2, v0.s[2] -; CHECK-NEXT: mov s3, v0.s[3] -; CHECK-NEXT: fmov s0, w8 -; CHECK-NEXT: fcvtzs w8, s1 -; CHECK-NEXT: fcvtzs w9, s2 -; CHECK-NEXT: mov v0.s[1], w8 -; CHECK-NEXT: mov v0.s[2], w9 -; CHECK-NEXT: fcvtzs w8, s3 -; CHECK-NEXT: mov v0.s[3], w8 +; CHECK-NEXT: fcvtzs v0.4s, v0.4s ; CHECK-NEXT: ret %x = call <3 x i32> @llvm.fptosi.sat.v3f32.v3i32(<3 x float> %f) ret <3 x i32> %x @@ -66,17 +45,7 @@ define <4 x i32> @test_signed_v4f32_v4i32(<4 x float> %f) { ; CHECK-LABEL: test_signed_v4f32_v4i32: ; CHECK: // %bb.0: -; CHECK-NEXT: fcvtzs w8, s0 -; CHECK-NEXT: mov s1, v0.s[1] -; CHECK-NEXT: mov s2, v0.s[2] -; CHECK-NEXT: mov s3, v0.s[3] -; CHECK-NEXT: fmov s0, w8 -; CHECK-NEXT: fcvtzs w8, s1 -; CHECK-NEXT: fcvtzs w9, s2 -; CHECK-NEXT: mov v0.s[1], w8 -; CHECK-NEXT: mov v0.s[2], w9 -; CHECK-NEXT: fcvtzs w8, s3 -; CHECK-NEXT: mov v0.s[3], w8 +; CHECK-NEXT: fcvtzs v0.4s, v0.4s ; CHECK-NEXT: ret %x = call <4 x i32> @llvm.fptosi.sat.v4f32.v4i32(<4 x float> %f) ret <4 x i32> %x @@ -85,11 +54,21 @@ define <5 x i32> @test_signed_v5f32_v5i32(<5 x float> %f) { ; CHECK-LABEL: test_signed_v5f32_v5i32: ; CHECK: // %bb.0: -; CHECK-NEXT: fcvtzs w0, s0 -; CHECK-NEXT: fcvtzs w1, s1 -; CHECK-NEXT: fcvtzs w2, s2 -; CHECK-NEXT: fcvtzs w3, s3 -; CHECK-NEXT: fcvtzs w4, s4 +; CHECK-NEXT: // kill: def $s0 killed $s0 def $q0 +; CHECK-NEXT: // kill: def $s1 killed $s1 def $q1 +; CHECK-NEXT: // kill: def $s2 killed $s2 def $q2 +; CHECK-NEXT: // kill: def $s4 killed $s4 def $q4 +; CHECK-NEXT: // kill: def $s3 killed $s3 def $q3 +; CHECK-NEXT: mov v0.s[1], v1.s[0] +; CHECK-NEXT: mov v0.s[2], v2.s[0] +; CHECK-NEXT: mov v0.s[3], v3.s[0] +; CHECK-NEXT: fcvtzs v4.4s, v4.4s +; CHECK-NEXT: fcvtzs v0.4s, v0.4s +; CHECK-NEXT: mov w1, v0.s[1] +; CHECK-NEXT: mov w2, v0.s[2] +; CHECK-NEXT: mov w3, v0.s[3] +; CHECK-NEXT: fmov w0, s0 +; CHECK-NEXT: fmov w4, s4 ; CHECK-NEXT: ret %x = call <5 x i32> @llvm.fptosi.sat.v5f32.v5i32(<5 x float> %f) ret <5 x i32> %x @@ -98,15 +77,24 @@ define <6 x i32> @test_signed_v6f32_v6i32(<6 x float> %f) { ; CHECK-LABEL: test_signed_v6f32_v6i32: ; CHECK: // %bb.0: -; CHECK-NEXT: fcvtzs w8, s4 -; CHECK-NEXT: fcvtzs w5, s5 -; CHECK-NEXT: fcvtzs w0, s0 -; CHECK-NEXT: fmov s0, w8 -; CHECK-NEXT: mov v0.s[1], w5 -; CHECK-NEXT: fcvtzs w1, s1 -; CHECK-NEXT: fcvtzs w2, s2 -; CHECK-NEXT: fcvtzs w3, s3 -; CHECK-NEXT: fmov w4, s0 +; CHECK-NEXT: // kill: def $s0 killed $s0 def $q0 +; CHECK-NEXT: // kill: def $s1 killed $s1 def $q1 +; CHECK-NEXT: // kill: def $s4 killed $s4 def $q4 +; CHECK-NEXT: // kill: def $s2 killed $s2 def $q2 +; CHECK-NEXT: // kill: def $s5 killed $s5 def $q5 +; CHECK-NEXT: // kill: def $s3 killed $s3 def $q3 +; CHECK-NEXT: mov v0.s[1], v1.s[0] +; CHECK-NEXT: mov v0.s[2], v2.s[0] +; CHECK-NEXT: mov v4.s[1], v5.s[0] +; CHECK-NEXT: mov v0.s[3], v3.s[0] +; CHECK-NEXT: fcvtzs v1.4s, v4.4s +; CHECK-NEXT: fcvtzs v0.4s, v0.4s +; CHECK-NEXT: mov w5, v1.s[1] +; CHECK-NEXT: mov w1, v0.s[1] +; CHECK-NEXT: mov w2, v0.s[2] +; CHECK-NEXT: mov w3, v0.s[3] +; CHECK-NEXT: fmov w4, s1 +; CHECK-NEXT: fmov w0, s0 ; CHECK-NEXT: ret %x = call <6 x i32> @llvm.fptosi.sat.v6f32.v6i32(<6 x float> %f) ret <6 x i32> %x @@ -115,18 +103,27 @@ define <7 x i32> @test_signed_v7f32_v7i32(<7 x float> %f) { ; CHECK-LABEL: test_signed_v7f32_v7i32: ; CHECK: // %bb.0: -; CHECK-NEXT: fcvtzs w8, s4 -; CHECK-NEXT: fcvtzs w9, s5 -; CHECK-NEXT: fcvtzs w0, s0 -; CHECK-NEXT: fmov s0, w8 -; CHECK-NEXT: fcvtzs w6, s6 -; CHECK-NEXT: mov v0.s[1], w9 -; CHECK-NEXT: mov v0.s[2], w6 -; CHECK-NEXT: fcvtzs w1, s1 -; CHECK-NEXT: fcvtzs w2, s2 -; CHECK-NEXT: fcvtzs w3, s3 -; CHECK-NEXT: mov w5, v0.s[1] -; CHECK-NEXT: fmov w4, s0 +; CHECK-NEXT: // kill: def $s0 killed $s0 def $q0 +; CHECK-NEXT: // kill: def $s4 killed $s4 def $q4 +; CHECK-NEXT: // kill: def $s1 killed $s1 def $q1 +; CHECK-NEXT: // kill: def $s5 killed $s5 def $q5 +; CHECK-NEXT: // kill: def $s2 killed $s2 def $q2 +; CHECK-NEXT: // kill: def $s6 killed $s6 def $q6 +; CHECK-NEXT: // kill: def $s3 killed $s3 def $q3 +; CHECK-NEXT: mov v0.s[1], v1.s[0] +; CHECK-NEXT: mov v4.s[1], v5.s[0] +; CHECK-NEXT: mov v0.s[2], v2.s[0] +; CHECK-NEXT: mov v4.s[2], v6.s[0] +; CHECK-NEXT: mov v0.s[3], v3.s[0] +; CHECK-NEXT: fcvtzs v1.4s, v4.4s +; CHECK-NEXT: fcvtzs v0.4s, v0.4s +; CHECK-NEXT: mov w5, v1.s[1] +; CHECK-NEXT: mov w6, v1.s[2] +; CHECK-NEXT: mov w1, v0.s[1] +; CHECK-NEXT: mov w2, v0.s[2] +; CHECK-NEXT: mov w3, v0.s[3] +; CHECK-NEXT: fmov w4, s1 +; CHECK-NEXT: fmov w0, s0 ; CHECK-NEXT: ret %x = call <7 x i32> @llvm.fptosi.sat.v7f32.v7i32(<7 x float> %f) ret <7 x i32> %x @@ -135,30 +132,8 @@ define <8 x i32> @test_signed_v8f32_v8i32(<8 x float> %f) { ; CHECK-LABEL: test_signed_v8f32_v8i32: ; CHECK: // %bb.0: -; CHECK-NEXT: mov s2, v0.s[1] -; CHECK-NEXT: mov s3, v0.s[2] -; CHECK-NEXT: fcvtzs w8, s0 -; CHECK-NEXT: fcvtzs w9, s1 -; CHECK-NEXT: fcvtzs w10, s2 -; CHECK-NEXT: mov s2, v1.s[1] -; CHECK-NEXT: fcvtzs w11, s3 -; CHECK-NEXT: mov s3, v1.s[2] -; CHECK-NEXT: fcvtzs w12, s2 -; CHECK-NEXT: fmov s2, w8 -; CHECK-NEXT: fcvtzs w8, s3 -; CHECK-NEXT: fmov s3, w9 -; CHECK-NEXT: mov v2.s[1], w10 -; CHECK-NEXT: mov v3.s[1], w12 -; CHECK-NEXT: mov s0, v0.s[3] -; CHECK-NEXT: mov v2.s[2], w11 -; CHECK-NEXT: mov s1, v1.s[3] -; CHECK-NEXT: mov v3.s[2], w8 -; CHECK-NEXT: fcvtzs w8, s0 -; CHECK-NEXT: mov v2.s[3], w8 -; CHECK-NEXT: fcvtzs w8, s1 -; CHECK-NEXT: mov v3.s[3], w8 -; CHECK-NEXT: mov v0.16b, v2.16b -; CHECK-NEXT: mov v1.16b, v3.16b +; CHECK-NEXT: fcvtzs v0.4s, v0.4s +; CHECK-NEXT: fcvtzs v1.4s, v1.4s ; CHECK-NEXT: ret %x = call <8 x i32> @llvm.fptosi.sat.v8f32.v8i32(<8 x float> %f) ret <8 x i32> %x @@ -590,202 +565,239 @@ declare <8 x i32> @llvm.fptosi.sat.v8f16.v8i32 (<8 x half>) define <1 x i32> @test_signed_v1f16_v1i32(<1 x half> %f) { -; CHECK-LABEL: test_signed_v1f16_v1i32: -; CHECK: // %bb.0: -; CHECK-NEXT: fcvt s0, h0 -; CHECK-NEXT: fcvtzs w8, s0 -; CHECK-NEXT: fmov s0, w8 -; CHECK-NEXT: ret +; CHECK-CVT-LABEL: test_signed_v1f16_v1i32: +; CHECK-CVT: // %bb.0: +; CHECK-CVT-NEXT: fcvt s0, h0 +; CHECK-CVT-NEXT: fcvtzs w8, s0 +; CHECK-CVT-NEXT: fmov s0, w8 +; CHECK-CVT-NEXT: ret +; +; CHECK-FP16-LABEL: test_signed_v1f16_v1i32: +; CHECK-FP16: // %bb.0: +; CHECK-FP16-NEXT: fcvtzs w8, h0 +; CHECK-FP16-NEXT: fmov s0, w8 +; CHECK-FP16-NEXT: ret %x = call <1 x i32> @llvm.fptosi.sat.v1f16.v1i32(<1 x half> %f) ret <1 x i32> %x } define <2 x i32> @test_signed_v2f16_v2i32(<2 x half> %f) { -; CHECK-LABEL: test_signed_v2f16_v2i32: -; CHECK: // %bb.0: -; CHECK-NEXT: // kill: def $d0 killed $d0 def $q0 -; CHECK-NEXT: fcvt s1, h0 -; CHECK-NEXT: mov h0, v0.h[1] -; CHECK-NEXT: fcvtzs w8, s1 -; CHECK-NEXT: fcvt s1, h0 -; CHECK-NEXT: fmov s0, w8 -; CHECK-NEXT: fcvtzs w8, s1 -; CHECK-NEXT: mov v0.s[1], w8 -; CHECK-NEXT: // kill: def $d0 killed $d0 killed $q0 -; CHECK-NEXT: ret +; CHECK-CVT-LABEL: test_signed_v2f16_v2i32: +; CHECK-CVT: // %bb.0: +; CHECK-CVT-NEXT: fcvtl v0.4s, v0.4h +; CHECK-CVT-NEXT: fcvtzs v0.4s, v0.4s +; CHECK-CVT-NEXT: // kill: def $d0 killed $d0 killed $q0 +; CHECK-CVT-NEXT: ret +; +; CHECK-FP16-LABEL: test_signed_v2f16_v2i32: +; CHECK-FP16: // %bb.0: +; CHECK-FP16-NEXT: // kill: def $d0 killed $d0 def $q0 +; CHECK-FP16-NEXT: fcvtzs w8, h0 +; CHECK-FP16-NEXT: mov h1, v0.h[1] +; CHECK-FP16-NEXT: fmov s0, w8 +; CHECK-FP16-NEXT: fcvtzs w8, h1 +; CHECK-FP16-NEXT: mov v0.s[1], w8 +; CHECK-FP16-NEXT: // kill: def $d0 killed $d0 killed $q0 +; CHECK-FP16-NEXT: ret %x = call <2 x i32> @llvm.fptosi.sat.v2f16.v2i32(<2 x half> %f) ret <2 x i32> %x } define <3 x i32> @test_signed_v3f16_v3i32(<3 x half> %f) { -; CHECK-LABEL: test_signed_v3f16_v3i32: -; CHECK: // %bb.0: -; CHECK-NEXT: // kill: def $d0 killed $d0 def $q0 -; CHECK-NEXT: fcvt s1, h0 -; CHECK-NEXT: mov h2, v0.h[1] -; CHECK-NEXT: fcvtzs w8, s1 -; CHECK-NEXT: fcvt s2, h2 -; CHECK-NEXT: fmov s1, w8 -; CHECK-NEXT: fcvtzs w8, s2 -; CHECK-NEXT: mov h2, v0.h[2] -; CHECK-NEXT: mov h0, v0.h[3] -; CHECK-NEXT: fcvt s2, h2 -; CHECK-NEXT: fcvt s0, h0 -; CHECK-NEXT: mov v1.s[1], w8 -; CHECK-NEXT: fcvtzs w8, s2 -; CHECK-NEXT: mov v1.s[2], w8 -; CHECK-NEXT: fcvtzs w8, s0 -; CHECK-NEXT: mov v1.s[3], w8 -; CHECK-NEXT: mov v0.16b, v1.16b -; CHECK-NEXT: ret +; CHECK-CVT-LABEL: test_signed_v3f16_v3i32: +; CHECK-CVT: // %bb.0: +; CHECK-CVT-NEXT: fcvtl v0.4s, v0.4h +; CHECK-CVT-NEXT: fcvtzs v0.4s, v0.4s +; CHECK-CVT-NEXT: ret +; +; CHECK-FP16-LABEL: test_signed_v3f16_v3i32: +; CHECK-FP16: // %bb.0: +; CHECK-FP16-NEXT: // kill: def $d0 killed $d0 def $q0 +; CHECK-FP16-NEXT: fcvtzs w8, h0 +; CHECK-FP16-NEXT: mov h1, v0.h[1] +; CHECK-FP16-NEXT: mov h2, v0.h[2] +; CHECK-FP16-NEXT: mov h3, v0.h[3] +; CHECK-FP16-NEXT: fmov s0, w8 +; CHECK-FP16-NEXT: fcvtzs w8, h1 +; CHECK-FP16-NEXT: fcvtzs w9, h2 +; CHECK-FP16-NEXT: mov v0.s[1], w8 +; CHECK-FP16-NEXT: mov v0.s[2], w9 +; CHECK-FP16-NEXT: fcvtzs w8, h3 +; CHECK-FP16-NEXT: mov v0.s[3], w8 +; CHECK-FP16-NEXT: ret %x = call <3 x i32> @llvm.fptosi.sat.v3f16.v3i32(<3 x half> %f) ret <3 x i32> %x } define <4 x i32> @test_signed_v4f16_v4i32(<4 x half> %f) { -; CHECK-LABEL: test_signed_v4f16_v4i32: -; CHECK: // %bb.0: -; CHECK-NEXT: // kill: def $d0 killed $d0 def $q0 -; CHECK-NEXT: fcvt s1, h0 -; CHECK-NEXT: mov h2, v0.h[1] -; CHECK-NEXT: fcvtzs w8, s1 -; CHECK-NEXT: fcvt s2, h2 -; CHECK-NEXT: fmov s1, w8 -; CHECK-NEXT: fcvtzs w8, s2 -; CHECK-NEXT: mov h2, v0.h[2] -; CHECK-NEXT: mov h0, v0.h[3] -; CHECK-NEXT: fcvt s2, h2 -; CHECK-NEXT: fcvt s0, h0 -; CHECK-NEXT: mov v1.s[1], w8 -; CHECK-NEXT: fcvtzs w8, s2 -; CHECK-NEXT: mov v1.s[2], w8 -; CHECK-NEXT: fcvtzs w8, s0 -; CHECK-NEXT: mov v1.s[3], w8 -; CHECK-NEXT: mov v0.16b, v1.16b -; CHECK-NEXT: ret +; CHECK-CVT-LABEL: test_signed_v4f16_v4i32: +; CHECK-CVT: // %bb.0: +; CHECK-CVT-NEXT: fcvtl v0.4s, v0.4h +; CHECK-CVT-NEXT: fcvtzs v0.4s, v0.4s +; CHECK-CVT-NEXT: ret +; +; CHECK-FP16-LABEL: test_signed_v4f16_v4i32: +; CHECK-FP16: // %bb.0: +; CHECK-FP16-NEXT: // kill: def $d0 killed $d0 def $q0 +; CHECK-FP16-NEXT: fcvtzs w8, h0 +; CHECK-FP16-NEXT: mov h1, v0.h[1] +; CHECK-FP16-NEXT: mov h2, v0.h[2] +; CHECK-FP16-NEXT: mov h3, v0.h[3] +; CHECK-FP16-NEXT: fmov s0, w8 +; CHECK-FP16-NEXT: fcvtzs w8, h1 +; CHECK-FP16-NEXT: fcvtzs w9, h2 +; CHECK-FP16-NEXT: mov v0.s[1], w8 +; CHECK-FP16-NEXT: mov v0.s[2], w9 +; CHECK-FP16-NEXT: fcvtzs w8, h3 +; CHECK-FP16-NEXT: mov v0.s[3], w8 +; CHECK-FP16-NEXT: ret %x = call <4 x i32> @llvm.fptosi.sat.v4f16.v4i32(<4 x half> %f) ret <4 x i32> %x } define <5 x i32> @test_signed_v5f16_v5i32(<5 x half> %f) { -; CHECK-LABEL: test_signed_v5f16_v5i32: -; CHECK: // %bb.0: -; CHECK-NEXT: fcvt s1, h0 -; CHECK-NEXT: fcvtzs w0, s1 -; CHECK-NEXT: ext v1.16b, v0.16b, v0.16b, #8 -; CHECK-NEXT: fcvt s1, h1 -; CHECK-NEXT: fcvtzs w4, s1 -; CHECK-NEXT: mov h1, v0.h[1] -; CHECK-NEXT: fcvt s1, h1 -; CHECK-NEXT: fcvtzs w1, s1 -; CHECK-NEXT: mov h1, v0.h[2] -; CHECK-NEXT: mov h0, v0.h[3] -; CHECK-NEXT: fcvt s1, h1 -; CHECK-NEXT: fcvt s0, h0 -; CHECK-NEXT: fcvtzs w2, s1 -; CHECK-NEXT: fcvtzs w3, s0 -; CHECK-NEXT: ret +; CHECK-CVT-LABEL: test_signed_v5f16_v5i32: +; CHECK-CVT: // %bb.0: +; CHECK-CVT-NEXT: fcvtl v1.4s, v0.4h +; CHECK-CVT-NEXT: fcvtl2 v0.4s, v0.8h +; CHECK-CVT-NEXT: fcvtzs v1.4s, v1.4s +; CHECK-CVT-NEXT: fcvtzs v0.4s, v0.4s +; CHECK-CVT-NEXT: mov w1, v1.s[1] +; CHECK-CVT-NEXT: mov w2, v1.s[2] +; CHECK-CVT-NEXT: mov w3, v1.s[3] +; CHECK-CVT-NEXT: fmov w4, s0 +; CHECK-CVT-NEXT: fmov w0, s1 +; CHECK-CVT-NEXT: ret +; +; CHECK-FP16-LABEL: test_signed_v5f16_v5i32: +; CHECK-FP16: // %bb.0: +; CHECK-FP16-NEXT: ext v1.16b, v0.16b, v0.16b, #8 +; CHECK-FP16-NEXT: fcvtzs w0, h0 +; CHECK-FP16-NEXT: mov h2, v0.h[1] +; CHECK-FP16-NEXT: mov h3, v0.h[2] +; CHECK-FP16-NEXT: mov h0, v0.h[3] +; CHECK-FP16-NEXT: fcvtzs w4, h1 +; CHECK-FP16-NEXT: fcvtzs w1, h2 +; CHECK-FP16-NEXT: fcvtzs w2, h3 +; CHECK-FP16-NEXT: fcvtzs w3, h0 +; CHECK-FP16-NEXT: ret %x = call <5 x i32> @llvm.fptosi.sat.v5f16.v5i32(<5 x half> %f) ret <5 x i32> %x } define <6 x i32> @test_signed_v6f16_v6i32(<6 x half> %f) { -; CHECK-LABEL: test_signed_v6f16_v6i32: -; CHECK: // %bb.0: -; CHECK-NEXT: ext v1.16b, v0.16b, v0.16b, #8 -; CHECK-NEXT: fcvt s2, h0 -; CHECK-NEXT: fcvtzs w0, s2 -; CHECK-NEXT: fcvt s2, h1 -; CHECK-NEXT: fcvtzs w8, s2 -; CHECK-NEXT: mov h2, v0.h[1] -; CHECK-NEXT: fcvt s2, h2 -; CHECK-NEXT: fcvtzs w1, s2 -; CHECK-NEXT: mov h2, v0.h[2] -; CHECK-NEXT: mov h1, v1.h[1] -; CHECK-NEXT: fcvt s2, h2 -; CHECK-NEXT: fcvt s1, h1 -; CHECK-NEXT: mov h0, v0.h[3] -; CHECK-NEXT: fcvtzs w2, s2 -; CHECK-NEXT: fmov s2, w8 -; CHECK-NEXT: fcvtzs w5, s1 -; CHECK-NEXT: fcvt s0, h0 -; CHECK-NEXT: mov v2.s[1], w5 -; CHECK-NEXT: fcvtzs w3, s0 -; CHECK-NEXT: fmov w4, s2 -; CHECK-NEXT: ret +; CHECK-CVT-LABEL: test_signed_v6f16_v6i32: +; CHECK-CVT: // %bb.0: +; CHECK-CVT-NEXT: fcvtl v1.4s, v0.4h +; CHECK-CVT-NEXT: fcvtl2 v0.4s, v0.8h +; CHECK-CVT-NEXT: fcvtzs v1.4s, v1.4s +; CHECK-CVT-NEXT: fcvtzs v0.4s, v0.4s +; CHECK-CVT-NEXT: mov w5, v0.s[1] +; CHECK-CVT-NEXT: mov w1, v1.s[1] +; CHECK-CVT-NEXT: mov w2, v1.s[2] +; CHECK-CVT-NEXT: mov w3, v1.s[3] +; CHECK-CVT-NEXT: fmov w4, s0 +; CHECK-CVT-NEXT: fmov w0, s1 +; CHECK-CVT-NEXT: ret +; +; CHECK-FP16-LABEL: test_signed_v6f16_v6i32: +; CHECK-FP16: // %bb.0: +; CHECK-FP16-NEXT: ext v1.16b, v0.16b, v0.16b, #8 +; CHECK-FP16-NEXT: mov h2, v0.h[1] +; CHECK-FP16-NEXT: fcvtzs w1, h2 +; CHECK-FP16-NEXT: mov h2, v0.h[2] +; CHECK-FP16-NEXT: fcvtzs w8, h1 +; CHECK-FP16-NEXT: mov h1, v1.h[1] +; CHECK-FP16-NEXT: fcvtzs w2, h2 +; CHECK-FP16-NEXT: fmov s2, w8 +; CHECK-FP16-NEXT: fcvtzs w5, h1 +; CHECK-FP16-NEXT: fcvtzs w0, h0 +; CHECK-FP16-NEXT: mov h0, v0.h[3] +; CHECK-FP16-NEXT: mov v2.s[1], w5 +; CHECK-FP16-NEXT: fcvtzs w3, h0 +; CHECK-FP16-NEXT: fmov w4, s2 +; CHECK-FP16-NEXT: ret %x = call <6 x i32> @llvm.fptosi.sat.v6f16.v6i32(<6 x half> %f) ret <6 x i32> %x } define <7 x i32> @test_signed_v7f16_v7i32(<7 x half> %f) { -; CHECK-LABEL: test_signed_v7f16_v7i32: -; CHECK: // %bb.0: -; CHECK-NEXT: ext v1.16b, v0.16b, v0.16b, #8 -; CHECK-NEXT: fcvt s2, h0 -; CHECK-NEXT: mov h3, v0.h[1] -; CHECK-NEXT: fcvtzs w0, s2 -; CHECK-NEXT: fcvt s2, h1 -; CHECK-NEXT: fcvt s3, h3 -; CHECK-NEXT: fcvtzs w8, s2 -; CHECK-NEXT: mov h2, v0.h[2] -; CHECK-NEXT: fcvtzs w1, s3 -; CHECK-NEXT: mov h3, v1.h[1] -; CHECK-NEXT: mov h1, v1.h[2] -; CHECK-NEXT: fcvt s2, h2 -; CHECK-NEXT: fcvt s3, h3 -; CHECK-NEXT: fcvt s1, h1 -; CHECK-NEXT: fcvtzs w2, s2 -; CHECK-NEXT: fmov s2, w8 -; CHECK-NEXT: fcvtzs w8, s3 -; CHECK-NEXT: mov h0, v0.h[3] -; CHECK-NEXT: fcvtzs w6, s1 -; CHECK-NEXT: mov v2.s[1], w8 -; CHECK-NEXT: fcvt s0, h0 -; CHECK-NEXT: mov v2.s[2], w6 -; CHECK-NEXT: fcvtzs w3, s0 -; CHECK-NEXT: mov w5, v2.s[1] -; CHECK-NEXT: fmov w4, s2 -; CHECK-NEXT: ret +; CHECK-CVT-LABEL: test_signed_v7f16_v7i32: +; CHECK-CVT: // %bb.0: +; CHECK-CVT-NEXT: fcvtl v1.4s, v0.4h +; CHECK-CVT-NEXT: fcvtl2 v0.4s, v0.8h +; CHECK-CVT-NEXT: fcvtzs v1.4s, v1.4s +; CHECK-CVT-NEXT: fcvtzs v0.4s, v0.4s +; CHECK-CVT-NEXT: mov w5, v0.s[1] +; CHECK-CVT-NEXT: mov w6, v0.s[2] +; CHECK-CVT-NEXT: mov w1, v1.s[1] +; CHECK-CVT-NEXT: mov w2, v1.s[2] +; CHECK-CVT-NEXT: mov w3, v1.s[3] +; CHECK-CVT-NEXT: fmov w4, s0 +; CHECK-CVT-NEXT: fmov w0, s1 +; CHECK-CVT-NEXT: ret +; +; CHECK-FP16-LABEL: test_signed_v7f16_v7i32: +; CHECK-FP16: // %bb.0: +; CHECK-FP16-NEXT: ext v1.16b, v0.16b, v0.16b, #8 +; CHECK-FP16-NEXT: mov h2, v0.h[1] +; CHECK-FP16-NEXT: mov h3, v0.h[2] +; CHECK-FP16-NEXT: fcvtzs w8, h1 +; CHECK-FP16-NEXT: fcvtzs w1, h2 +; CHECK-FP16-NEXT: mov h2, v1.h[1] +; CHECK-FP16-NEXT: mov h1, v1.h[2] +; CHECK-FP16-NEXT: fcvtzs w2, h3 +; CHECK-FP16-NEXT: fmov s3, w8 +; CHECK-FP16-NEXT: fcvtzs w8, h2 +; CHECK-FP16-NEXT: fcvtzs w6, h1 +; CHECK-FP16-NEXT: mov v3.s[1], w8 +; CHECK-FP16-NEXT: fcvtzs w0, h0 +; CHECK-FP16-NEXT: mov h0, v0.h[3] +; CHECK-FP16-NEXT: mov v3.s[2], w6 +; CHECK-FP16-NEXT: fcvtzs w3, h0 +; CHECK-FP16-NEXT: mov w5, v3.s[1] +; CHECK-FP16-NEXT: fmov w4, s3 +; CHECK-FP16-NEXT: ret %x = call <7 x i32> @llvm.fptosi.sat.v7f16.v7i32(<7 x half> %f) ret <7 x i32> %x } define <8 x i32> @test_signed_v8f16_v8i32(<8 x half> %f) { -; CHECK-LABEL: test_signed_v8f16_v8i32: -; CHECK: // %bb.0: -; CHECK-NEXT: ext v3.16b, v0.16b, v0.16b, #8 -; CHECK-NEXT: fcvt s1, h0 -; CHECK-NEXT: fcvtzs w8, s1 -; CHECK-NEXT: fcvt s1, h3 -; CHECK-NEXT: mov h2, v0.h[1] -; CHECK-NEXT: fcvtzs w9, s1 -; CHECK-NEXT: mov h1, v0.h[2] -; CHECK-NEXT: fcvt s2, h2 -; CHECK-NEXT: fcvt s1, h1 -; CHECK-NEXT: fcvtzs w10, s2 -; CHECK-NEXT: mov h2, v3.h[1] -; CHECK-NEXT: fcvtzs w11, s1 -; CHECK-NEXT: mov h1, v3.h[2] -; CHECK-NEXT: fcvt s2, h2 -; CHECK-NEXT: fcvt s1, h1 -; CHECK-NEXT: fcvtzs w12, s2 -; CHECK-NEXT: fmov s2, w8 -; CHECK-NEXT: fcvtzs w8, s1 -; CHECK-NEXT: fmov s1, w9 -; CHECK-NEXT: mov h3, v3.h[3] -; CHECK-NEXT: mov v1.s[1], w12 -; CHECK-NEXT: mov h0, v0.h[3] -; CHECK-NEXT: fcvt s3, h3 -; CHECK-NEXT: mov v2.s[1], w10 -; CHECK-NEXT: fcvt s0, h0 -; CHECK-NEXT: mov v1.s[2], w8 -; CHECK-NEXT: fcvtzs w8, s3 -; CHECK-NEXT: mov v2.s[2], w11 -; CHECK-NEXT: mov v1.s[3], w8 -; CHECK-NEXT: fcvtzs w8, s0 -; CHECK-NEXT: mov v2.s[3], w8 -; CHECK-NEXT: mov v0.16b, v2.16b -; CHECK-NEXT: ret +; CHECK-CVT-LABEL: test_signed_v8f16_v8i32: +; CHECK-CVT: // %bb.0: +; CHECK-CVT-NEXT: fcvtl2 v1.4s, v0.8h +; CHECK-CVT-NEXT: fcvtl v0.4s, v0.4h +; CHECK-CVT-NEXT: fcvtzs v1.4s, v1.4s +; CHECK-CVT-NEXT: fcvtzs v0.4s, v0.4s +; CHECK-CVT-NEXT: ret +; +; CHECK-FP16-LABEL: test_signed_v8f16_v8i32: +; CHECK-FP16: // %bb.0: +; CHECK-FP16-NEXT: ext v3.16b, v0.16b, v0.16b, #8 +; CHECK-FP16-NEXT: mov h1, v0.h[1] +; CHECK-FP16-NEXT: fcvtzs w9, h3 +; CHECK-FP16-NEXT: fcvtzs w10, h1 +; CHECK-FP16-NEXT: mov h1, v3.h[1] +; CHECK-FP16-NEXT: fcvtzs w8, h0 +; CHECK-FP16-NEXT: mov h2, v0.h[2] +; CHECK-FP16-NEXT: mov h4, v3.h[2] +; CHECK-FP16-NEXT: fcvtzs w12, h1 +; CHECK-FP16-NEXT: fmov s1, w9 +; CHECK-FP16-NEXT: fcvtzs w11, h2 +; CHECK-FP16-NEXT: fmov s2, w8 +; CHECK-FP16-NEXT: fcvtzs w8, h4 +; CHECK-FP16-NEXT: mov v1.s[1], w12 +; CHECK-FP16-NEXT: mov h3, v3.h[3] +; CHECK-FP16-NEXT: mov v2.s[1], w10 +; CHECK-FP16-NEXT: mov h0, v0.h[3] +; CHECK-FP16-NEXT: mov v1.s[2], w8 +; CHECK-FP16-NEXT: fcvtzs w8, h3 +; CHECK-FP16-NEXT: mov v2.s[2], w11 +; CHECK-FP16-NEXT: mov v1.s[3], w8 +; CHECK-FP16-NEXT: fcvtzs w8, h0 +; CHECK-FP16-NEXT: mov v2.s[3], w8 +; CHECK-FP16-NEXT: mov v0.16b, v2.16b +; CHECK-FP16-NEXT: ret %x = call <8 x i32> @llvm.fptosi.sat.v8f16.v8i32(<8 x half> %f) ret <8 x i32> %x } @@ -943,13 +955,7 @@ define <2 x i32> @test_signed_v2f32_v2i32_duplicate(<2 x float> %f) { ; CHECK-LABEL: test_signed_v2f32_v2i32_duplicate: ; CHECK: // %bb.0: -; CHECK-NEXT: // kill: def $d0 killed $d0 def $q0 -; CHECK-NEXT: fcvtzs w8, s0 -; CHECK-NEXT: mov s1, v0.s[1] -; CHECK-NEXT: fmov s0, w8 -; CHECK-NEXT: fcvtzs w8, s1 -; CHECK-NEXT: mov v0.s[1], w8 -; CHECK-NEXT: // kill: def $d0 killed $d0 killed $q0 +; CHECK-NEXT: fcvtzs v0.2s, v0.2s ; CHECK-NEXT: ret %x = call <2 x i32> @llvm.fptosi.sat.v2f32.v2i32(<2 x float> %f) ret <2 x i32> %x @@ -1324,11 +1330,7 @@ define <2 x i64> @test_signed_v2f64_v2i64(<2 x double> %f) { ; CHECK-LABEL: test_signed_v2f64_v2i64: ; CHECK: // %bb.0: -; CHECK-NEXT: fcvtzs x8, d0 -; CHECK-NEXT: mov d1, v0.d[1] -; CHECK-NEXT: fmov d0, x8 -; CHECK-NEXT: fcvtzs x8, d1 -; CHECK-NEXT: mov v0.d[1], x8 +; CHECK-NEXT: fcvtzs v0.2d, v0.2d ; CHECK-NEXT: ret %x = call <2 x i64> @llvm.fptosi.sat.v2f64.v2i64(<2 x double> %f) ret <2 x i64> %x @@ -1615,47 +1617,48 @@ } define <4 x i16> @test_signed_v4f16_v4i16(<4 x half> %f) { -; CHECK-LABEL: test_signed_v4f16_v4i16: -; CHECK: // %bb.0: -; CHECK-NEXT: mov w8, #-956301312 -; CHECK-NEXT: mov w9, #65024 -; CHECK-NEXT: // kill: def $d0 killed $d0 def $q0 -; CHECK-NEXT: movk w9, #18175, lsl #16 -; CHECK-NEXT: fcvt s2, h0 -; CHECK-NEXT: fmov s3, w8 -; CHECK-NEXT: fmov s4, w9 -; CHECK-NEXT: fmaxnm s5, s2, s3 -; CHECK-NEXT: mov h1, v0.h[1] -; CHECK-NEXT: fminnm s5, s5, s4 -; CHECK-NEXT: fcvtzs w8, s5 -; CHECK-NEXT: mov h5, v0.h[2] -; CHECK-NEXT: mov h0, v0.h[3] -; CHECK-NEXT: fcvt s1, h1 -; CHECK-NEXT: fcvt s6, h0 -; CHECK-NEXT: fmaxnm s0, s1, s3 -; CHECK-NEXT: fminnm s0, s0, s4 -; CHECK-NEXT: fcvt s5, h5 -; CHECK-NEXT: fcmp s1, s1 -; CHECK-NEXT: fcvtzs w9, s0 -; CHECK-NEXT: fmaxnm s0, s5, s3 -; CHECK-NEXT: csel w9, wzr, w9, vs -; CHECK-NEXT: fcmp s2, s2 -; CHECK-NEXT: fmaxnm s1, s6, s3 -; CHECK-NEXT: fminnm s3, s0, s4 -; CHECK-NEXT: csel w8, wzr, w8, vs -; CHECK-NEXT: fminnm s1, s1, s4 -; CHECK-NEXT: fmov s0, w8 -; CHECK-NEXT: fcvtzs w8, s3 -; CHECK-NEXT: fcmp s5, s5 -; CHECK-NEXT: mov v0.h[1], w9 -; CHECK-NEXT: fcvtzs w9, s1 -; CHECK-NEXT: csel w8, wzr, w8, vs -; CHECK-NEXT: fcmp s6, s6 -; CHECK-NEXT: mov v0.h[2], w8 -; CHECK-NEXT: csel w8, wzr, w9, vs -; CHECK-NEXT: mov v0.h[3], w8 -; CHECK-NEXT: // kill: def $d0 killed $d0 killed $q0 -; CHECK-NEXT: ret +; CHECK-CVT-LABEL: test_signed_v4f16_v4i16: +; CHECK-CVT: // %bb.0: +; CHECK-CVT-NEXT: fcvtl v0.4s, v0.4h +; CHECK-CVT-NEXT: mov w8, #-956301312 +; CHECK-CVT-NEXT: mov w9, #65024 +; CHECK-CVT-NEXT: movk w9, #18175, lsl #16 +; CHECK-CVT-NEXT: mov s1, v0.s[1] +; CHECK-CVT-NEXT: fmov s2, w8 +; CHECK-CVT-NEXT: fmov s3, w9 +; CHECK-CVT-NEXT: fcmp s1, s1 +; CHECK-CVT-NEXT: fmaxnm s1, s1, s2 +; CHECK-CVT-NEXT: fmaxnm s4, s0, s2 +; CHECK-CVT-NEXT: fminnm s1, s1, s3 +; CHECK-CVT-NEXT: mov s5, v0.s[2] +; CHECK-CVT-NEXT: fminnm s4, s4, s3 +; CHECK-CVT-NEXT: fcvtzs w9, s1 +; CHECK-CVT-NEXT: fcvtzs w8, s4 +; CHECK-CVT-NEXT: mov s4, v0.s[3] +; CHECK-CVT-NEXT: fmaxnm s1, s5, s2 +; CHECK-CVT-NEXT: csel w9, wzr, w9, vs +; CHECK-CVT-NEXT: fcmp s0, s0 +; CHECK-CVT-NEXT: fmaxnm s2, s4, s2 +; CHECK-CVT-NEXT: fminnm s1, s1, s3 +; CHECK-CVT-NEXT: csel w8, wzr, w8, vs +; CHECK-CVT-NEXT: fminnm s2, s2, s3 +; CHECK-CVT-NEXT: fmov s0, w8 +; CHECK-CVT-NEXT: fcvtzs w8, s1 +; CHECK-CVT-NEXT: fcmp s5, s5 +; CHECK-CVT-NEXT: mov v0.h[1], w9 +; CHECK-CVT-NEXT: fcvtzs w9, s2 +; CHECK-CVT-NEXT: csel w8, wzr, w8, vs +; CHECK-CVT-NEXT: fcmp s4, s4 +; CHECK-CVT-NEXT: mov v0.h[2], w8 +; CHECK-CVT-NEXT: csel w8, wzr, w9, vs +; CHECK-CVT-NEXT: mov v0.h[3], w8 +; CHECK-CVT-NEXT: // kill: def $d0 killed $d0 killed $q0 +; CHECK-CVT-NEXT: ret +; +; CHECK-FP16-LABEL: test_signed_v4f16_v4i16: +; CHECK-FP16: // %bb.0: +; CHECK-FP16-NEXT: fcvtzs v0.4h, v0.4h +; CHECK-FP16-NEXT: ret %x = call <4 x i16> @llvm.fptosi.sat.v4f16.v4i16(<4 x half> %f) ret <4 x i16> %x } @@ -1706,26 +1709,27 @@ } define <4 x i32> @test_signed_v4f16_v4i32_duplicate(<4 x half> %f) { -; CHECK-LABEL: test_signed_v4f16_v4i32_duplicate: -; CHECK: // %bb.0: -; CHECK-NEXT: // kill: def $d0 killed $d0 def $q0 -; CHECK-NEXT: fcvt s1, h0 -; CHECK-NEXT: mov h2, v0.h[1] -; CHECK-NEXT: fcvtzs w8, s1 -; CHECK-NEXT: fcvt s2, h2 -; CHECK-NEXT: fmov s1, w8 -; CHECK-NEXT: fcvtzs w8, s2 -; CHECK-NEXT: mov h2, v0.h[2] -; CHECK-NEXT: mov h0, v0.h[3] -; CHECK-NEXT: fcvt s2, h2 -; CHECK-NEXT: fcvt s0, h0 -; CHECK-NEXT: mov v1.s[1], w8 -; CHECK-NEXT: fcvtzs w8, s2 -; CHECK-NEXT: mov v1.s[2], w8 -; CHECK-NEXT: fcvtzs w8, s0 -; CHECK-NEXT: mov v1.s[3], w8 -; CHECK-NEXT: mov v0.16b, v1.16b -; CHECK-NEXT: ret +; CHECK-CVT-LABEL: test_signed_v4f16_v4i32_duplicate: +; CHECK-CVT: // %bb.0: +; CHECK-CVT-NEXT: fcvtl v0.4s, v0.4h +; CHECK-CVT-NEXT: fcvtzs v0.4s, v0.4s +; CHECK-CVT-NEXT: ret +; +; CHECK-FP16-LABEL: test_signed_v4f16_v4i32_duplicate: +; CHECK-FP16: // %bb.0: +; CHECK-FP16-NEXT: // kill: def $d0 killed $d0 def $q0 +; CHECK-FP16-NEXT: fcvtzs w8, h0 +; CHECK-FP16-NEXT: mov h1, v0.h[1] +; CHECK-FP16-NEXT: mov h2, v0.h[2] +; CHECK-FP16-NEXT: mov h3, v0.h[3] +; CHECK-FP16-NEXT: fmov s0, w8 +; CHECK-FP16-NEXT: fcvtzs w8, h1 +; CHECK-FP16-NEXT: fcvtzs w9, h2 +; CHECK-FP16-NEXT: mov v0.s[1], w8 +; CHECK-FP16-NEXT: mov v0.s[2], w9 +; CHECK-FP16-NEXT: fcvtzs w8, h3 +; CHECK-FP16-NEXT: mov v0.s[3], w8 +; CHECK-FP16-NEXT: ret %x = call <4 x i32> @llvm.fptosi.sat.v4f16.v4i32(<4 x half> %f) ret <4 x i32> %x } @@ -1781,26 +1785,42 @@ } define <4 x i64> @test_signed_v4f16_v4i64(<4 x half> %f) { -; CHECK-LABEL: test_signed_v4f16_v4i64: -; CHECK: // %bb.0: -; CHECK-NEXT: // kill: def $d0 killed $d0 def $q0 -; CHECK-NEXT: fcvt s1, h0 -; CHECK-NEXT: mov h2, v0.h[1] -; CHECK-NEXT: fcvtzs x8, s1 -; CHECK-NEXT: fcvt s1, h2 -; CHECK-NEXT: fmov d2, x8 -; CHECK-NEXT: fcvtzs x8, s1 -; CHECK-NEXT: mov h1, v0.h[2] -; CHECK-NEXT: mov h0, v0.h[3] -; CHECK-NEXT: fcvt s1, h1 -; CHECK-NEXT: mov v2.d[1], x8 -; CHECK-NEXT: fcvtzs x8, s1 -; CHECK-NEXT: fcvt s0, h0 -; CHECK-NEXT: fmov d1, x8 -; CHECK-NEXT: fcvtzs x8, s0 -; CHECK-NEXT: mov v1.d[1], x8 -; CHECK-NEXT: mov v0.16b, v2.16b -; CHECK-NEXT: ret +; CHECK-CVT-LABEL: test_signed_v4f16_v4i64: +; CHECK-CVT: // %bb.0: +; CHECK-CVT-NEXT: // kill: def $d0 killed $d0 def $q0 +; CHECK-CVT-NEXT: fcvt s1, h0 +; CHECK-CVT-NEXT: mov h2, v0.h[1] +; CHECK-CVT-NEXT: fcvtzs x8, s1 +; CHECK-CVT-NEXT: fcvt s1, h2 +; CHECK-CVT-NEXT: fmov d2, x8 +; CHECK-CVT-NEXT: fcvtzs x8, s1 +; CHECK-CVT-NEXT: mov h1, v0.h[2] +; CHECK-CVT-NEXT: mov h0, v0.h[3] +; CHECK-CVT-NEXT: fcvt s1, h1 +; CHECK-CVT-NEXT: mov v2.d[1], x8 +; CHECK-CVT-NEXT: fcvtzs x8, s1 +; CHECK-CVT-NEXT: fcvt s0, h0 +; CHECK-CVT-NEXT: fmov d1, x8 +; CHECK-CVT-NEXT: fcvtzs x8, s0 +; CHECK-CVT-NEXT: mov v1.d[1], x8 +; CHECK-CVT-NEXT: mov v0.16b, v2.16b +; CHECK-CVT-NEXT: ret +; +; CHECK-FP16-LABEL: test_signed_v4f16_v4i64: +; CHECK-FP16: // %bb.0: +; CHECK-FP16-NEXT: // kill: def $d0 killed $d0 def $q0 +; CHECK-FP16-NEXT: fcvtzs x8, h0 +; CHECK-FP16-NEXT: mov h1, v0.h[1] +; CHECK-FP16-NEXT: mov h2, v0.h[2] +; CHECK-FP16-NEXT: mov h3, v0.h[3] +; CHECK-FP16-NEXT: fmov d0, x8 +; CHECK-FP16-NEXT: fcvtzs x8, h1 +; CHECK-FP16-NEXT: fcvtzs x9, h2 +; CHECK-FP16-NEXT: mov v0.d[1], x8 +; CHECK-FP16-NEXT: fmov d1, x9 +; CHECK-FP16-NEXT: fcvtzs x8, h3 +; CHECK-FP16-NEXT: mov v1.d[1], x8 +; CHECK-FP16-NEXT: ret %x = call <4 x i64> @llvm.fptosi.sat.v4f16.v4i64(<4 x half> %f) ret <4 x i64> %x } diff --git a/llvm/test/CodeGen/AArch64/fptoui-sat-vector.ll b/llvm/test/CodeGen/AArch64/fptoui-sat-vector.ll --- a/llvm/test/CodeGen/AArch64/fptoui-sat-vector.ll +++ b/llvm/test/CodeGen/AArch64/fptoui-sat-vector.ll @@ -1,5 +1,6 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc -mtriple=aarch64 < %s | FileCheck %s +; RUN: llc < %s -mtriple=aarch64 | FileCheck %s --check-prefixes=CHECK,CHECK-CVT +; RUN: llc < %s -mtriple=aarch64 -mattr=+fullfp16 | FileCheck %s --check-prefixes=CHECK,CHECK-FP16 ; ; Float to unsigned 32-bit -- Vector size variation @@ -17,13 +18,7 @@ define <1 x i32> @test_unsigned_v1f32_v1i32(<1 x float> %f) { ; CHECK-LABEL: test_unsigned_v1f32_v1i32: ; CHECK: // %bb.0: -; CHECK-NEXT: // kill: def $d0 killed $d0 def $q0 -; CHECK-NEXT: fcvtzu w8, s0 -; CHECK-NEXT: mov s1, v0.s[1] -; CHECK-NEXT: fmov s0, w8 -; CHECK-NEXT: fcvtzu w8, s1 -; CHECK-NEXT: mov v0.s[1], w8 -; CHECK-NEXT: // kill: def $d0 killed $d0 killed $q0 +; CHECK-NEXT: fcvtzu v0.2s, v0.2s ; CHECK-NEXT: ret %x = call <1 x i32> @llvm.fptoui.sat.v1f32.v1i32(<1 x float> %f) ret <1 x i32> %x @@ -32,13 +27,7 @@ define <2 x i32> @test_unsigned_v2f32_v2i32(<2 x float> %f) { ; CHECK-LABEL: test_unsigned_v2f32_v2i32: ; CHECK: // %bb.0: -; CHECK-NEXT: // kill: def $d0 killed $d0 def $q0 -; CHECK-NEXT: fcvtzu w8, s0 -; CHECK-NEXT: mov s1, v0.s[1] -; CHECK-NEXT: fmov s0, w8 -; CHECK-NEXT: fcvtzu w8, s1 -; CHECK-NEXT: mov v0.s[1], w8 -; CHECK-NEXT: // kill: def $d0 killed $d0 killed $q0 +; CHECK-NEXT: fcvtzu v0.2s, v0.2s ; CHECK-NEXT: ret %x = call <2 x i32> @llvm.fptoui.sat.v2f32.v2i32(<2 x float> %f) ret <2 x i32> %x @@ -47,17 +36,7 @@ define <3 x i32> @test_unsigned_v3f32_v3i32(<3 x float> %f) { ; CHECK-LABEL: test_unsigned_v3f32_v3i32: ; CHECK: // %bb.0: -; CHECK-NEXT: fcvtzu w8, s0 -; CHECK-NEXT: mov s1, v0.s[1] -; CHECK-NEXT: mov s2, v0.s[2] -; CHECK-NEXT: mov s3, v0.s[3] -; CHECK-NEXT: fmov s0, w8 -; CHECK-NEXT: fcvtzu w8, s1 -; CHECK-NEXT: fcvtzu w9, s2 -; CHECK-NEXT: mov v0.s[1], w8 -; CHECK-NEXT: mov v0.s[2], w9 -; CHECK-NEXT: fcvtzu w8, s3 -; CHECK-NEXT: mov v0.s[3], w8 +; CHECK-NEXT: fcvtzu v0.4s, v0.4s ; CHECK-NEXT: ret %x = call <3 x i32> @llvm.fptoui.sat.v3f32.v3i32(<3 x float> %f) ret <3 x i32> %x @@ -66,17 +45,7 @@ define <4 x i32> @test_unsigned_v4f32_v4i32(<4 x float> %f) { ; CHECK-LABEL: test_unsigned_v4f32_v4i32: ; CHECK: // %bb.0: -; CHECK-NEXT: fcvtzu w8, s0 -; CHECK-NEXT: mov s1, v0.s[1] -; CHECK-NEXT: mov s2, v0.s[2] -; CHECK-NEXT: mov s3, v0.s[3] -; CHECK-NEXT: fmov s0, w8 -; CHECK-NEXT: fcvtzu w8, s1 -; CHECK-NEXT: fcvtzu w9, s2 -; CHECK-NEXT: mov v0.s[1], w8 -; CHECK-NEXT: mov v0.s[2], w9 -; CHECK-NEXT: fcvtzu w8, s3 -; CHECK-NEXT: mov v0.s[3], w8 +; CHECK-NEXT: fcvtzu v0.4s, v0.4s ; CHECK-NEXT: ret %x = call <4 x i32> @llvm.fptoui.sat.v4f32.v4i32(<4 x float> %f) ret <4 x i32> %x @@ -85,11 +54,21 @@ define <5 x i32> @test_unsigned_v5f32_v5i32(<5 x float> %f) { ; CHECK-LABEL: test_unsigned_v5f32_v5i32: ; CHECK: // %bb.0: -; CHECK-NEXT: fcvtzu w0, s0 -; CHECK-NEXT: fcvtzu w1, s1 -; CHECK-NEXT: fcvtzu w2, s2 -; CHECK-NEXT: fcvtzu w3, s3 -; CHECK-NEXT: fcvtzu w4, s4 +; CHECK-NEXT: // kill: def $s0 killed $s0 def $q0 +; CHECK-NEXT: // kill: def $s1 killed $s1 def $q1 +; CHECK-NEXT: // kill: def $s2 killed $s2 def $q2 +; CHECK-NEXT: // kill: def $s4 killed $s4 def $q4 +; CHECK-NEXT: // kill: def $s3 killed $s3 def $q3 +; CHECK-NEXT: mov v0.s[1], v1.s[0] +; CHECK-NEXT: mov v0.s[2], v2.s[0] +; CHECK-NEXT: mov v0.s[3], v3.s[0] +; CHECK-NEXT: fcvtzu v4.4s, v4.4s +; CHECK-NEXT: fcvtzu v0.4s, v0.4s +; CHECK-NEXT: mov w1, v0.s[1] +; CHECK-NEXT: mov w2, v0.s[2] +; CHECK-NEXT: mov w3, v0.s[3] +; CHECK-NEXT: fmov w0, s0 +; CHECK-NEXT: fmov w4, s4 ; CHECK-NEXT: ret %x = call <5 x i32> @llvm.fptoui.sat.v5f32.v5i32(<5 x float> %f) ret <5 x i32> %x @@ -98,15 +77,24 @@ define <6 x i32> @test_unsigned_v6f32_v6i32(<6 x float> %f) { ; CHECK-LABEL: test_unsigned_v6f32_v6i32: ; CHECK: // %bb.0: -; CHECK-NEXT: fcvtzu w8, s4 -; CHECK-NEXT: fcvtzu w5, s5 -; CHECK-NEXT: fcvtzu w0, s0 -; CHECK-NEXT: fmov s0, w8 -; CHECK-NEXT: mov v0.s[1], w5 -; CHECK-NEXT: fcvtzu w1, s1 -; CHECK-NEXT: fcvtzu w2, s2 -; CHECK-NEXT: fcvtzu w3, s3 -; CHECK-NEXT: fmov w4, s0 +; CHECK-NEXT: // kill: def $s0 killed $s0 def $q0 +; CHECK-NEXT: // kill: def $s1 killed $s1 def $q1 +; CHECK-NEXT: // kill: def $s4 killed $s4 def $q4 +; CHECK-NEXT: // kill: def $s2 killed $s2 def $q2 +; CHECK-NEXT: // kill: def $s5 killed $s5 def $q5 +; CHECK-NEXT: // kill: def $s3 killed $s3 def $q3 +; CHECK-NEXT: mov v0.s[1], v1.s[0] +; CHECK-NEXT: mov v0.s[2], v2.s[0] +; CHECK-NEXT: mov v4.s[1], v5.s[0] +; CHECK-NEXT: mov v0.s[3], v3.s[0] +; CHECK-NEXT: fcvtzu v1.4s, v4.4s +; CHECK-NEXT: fcvtzu v0.4s, v0.4s +; CHECK-NEXT: mov w5, v1.s[1] +; CHECK-NEXT: mov w1, v0.s[1] +; CHECK-NEXT: mov w2, v0.s[2] +; CHECK-NEXT: mov w3, v0.s[3] +; CHECK-NEXT: fmov w4, s1 +; CHECK-NEXT: fmov w0, s0 ; CHECK-NEXT: ret %x = call <6 x i32> @llvm.fptoui.sat.v6f32.v6i32(<6 x float> %f) ret <6 x i32> %x @@ -115,18 +103,27 @@ define <7 x i32> @test_unsigned_v7f32_v7i32(<7 x float> %f) { ; CHECK-LABEL: test_unsigned_v7f32_v7i32: ; CHECK: // %bb.0: -; CHECK-NEXT: fcvtzu w8, s4 -; CHECK-NEXT: fcvtzu w9, s5 -; CHECK-NEXT: fcvtzu w0, s0 -; CHECK-NEXT: fmov s0, w8 -; CHECK-NEXT: fcvtzu w6, s6 -; CHECK-NEXT: mov v0.s[1], w9 -; CHECK-NEXT: mov v0.s[2], w6 -; CHECK-NEXT: fcvtzu w1, s1 -; CHECK-NEXT: fcvtzu w2, s2 -; CHECK-NEXT: fcvtzu w3, s3 -; CHECK-NEXT: mov w5, v0.s[1] -; CHECK-NEXT: fmov w4, s0 +; CHECK-NEXT: // kill: def $s0 killed $s0 def $q0 +; CHECK-NEXT: // kill: def $s4 killed $s4 def $q4 +; CHECK-NEXT: // kill: def $s1 killed $s1 def $q1 +; CHECK-NEXT: // kill: def $s5 killed $s5 def $q5 +; CHECK-NEXT: // kill: def $s2 killed $s2 def $q2 +; CHECK-NEXT: // kill: def $s6 killed $s6 def $q6 +; CHECK-NEXT: // kill: def $s3 killed $s3 def $q3 +; CHECK-NEXT: mov v0.s[1], v1.s[0] +; CHECK-NEXT: mov v4.s[1], v5.s[0] +; CHECK-NEXT: mov v0.s[2], v2.s[0] +; CHECK-NEXT: mov v4.s[2], v6.s[0] +; CHECK-NEXT: mov v0.s[3], v3.s[0] +; CHECK-NEXT: fcvtzu v1.4s, v4.4s +; CHECK-NEXT: fcvtzu v0.4s, v0.4s +; CHECK-NEXT: mov w5, v1.s[1] +; CHECK-NEXT: mov w6, v1.s[2] +; CHECK-NEXT: mov w1, v0.s[1] +; CHECK-NEXT: mov w2, v0.s[2] +; CHECK-NEXT: mov w3, v0.s[3] +; CHECK-NEXT: fmov w4, s1 +; CHECK-NEXT: fmov w0, s0 ; CHECK-NEXT: ret %x = call <7 x i32> @llvm.fptoui.sat.v7f32.v7i32(<7 x float> %f) ret <7 x i32> %x @@ -135,30 +132,8 @@ define <8 x i32> @test_unsigned_v8f32_v8i32(<8 x float> %f) { ; CHECK-LABEL: test_unsigned_v8f32_v8i32: ; CHECK: // %bb.0: -; CHECK-NEXT: mov s2, v0.s[1] -; CHECK-NEXT: mov s3, v0.s[2] -; CHECK-NEXT: fcvtzu w8, s0 -; CHECK-NEXT: fcvtzu w9, s1 -; CHECK-NEXT: fcvtzu w10, s2 -; CHECK-NEXT: mov s2, v1.s[1] -; CHECK-NEXT: fcvtzu w11, s3 -; CHECK-NEXT: mov s3, v1.s[2] -; CHECK-NEXT: fcvtzu w12, s2 -; CHECK-NEXT: fmov s2, w8 -; CHECK-NEXT: fcvtzu w8, s3 -; CHECK-NEXT: fmov s3, w9 -; CHECK-NEXT: mov v2.s[1], w10 -; CHECK-NEXT: mov v3.s[1], w12 -; CHECK-NEXT: mov s0, v0.s[3] -; CHECK-NEXT: mov v2.s[2], w11 -; CHECK-NEXT: mov s1, v1.s[3] -; CHECK-NEXT: mov v3.s[2], w8 -; CHECK-NEXT: fcvtzu w8, s0 -; CHECK-NEXT: mov v2.s[3], w8 -; CHECK-NEXT: fcvtzu w8, s1 -; CHECK-NEXT: mov v3.s[3], w8 -; CHECK-NEXT: mov v0.16b, v2.16b -; CHECK-NEXT: mov v1.16b, v3.16b +; CHECK-NEXT: fcvtzu v0.4s, v0.4s +; CHECK-NEXT: fcvtzu v1.4s, v1.4s ; CHECK-NEXT: ret %x = call <8 x i32> @llvm.fptoui.sat.v8f32.v8i32(<8 x float> %f) ret <8 x i32> %x @@ -519,202 +494,239 @@ declare <8 x i32> @llvm.fptoui.sat.v8f16.v8i32 (<8 x half>) define <1 x i32> @test_unsigned_v1f16_v1i32(<1 x half> %f) { -; CHECK-LABEL: test_unsigned_v1f16_v1i32: -; CHECK: // %bb.0: -; CHECK-NEXT: fcvt s0, h0 -; CHECK-NEXT: fcvtzu w8, s0 -; CHECK-NEXT: fmov s0, w8 -; CHECK-NEXT: ret +; CHECK-CVT-LABEL: test_unsigned_v1f16_v1i32: +; CHECK-CVT: // %bb.0: +; CHECK-CVT-NEXT: fcvt s0, h0 +; CHECK-CVT-NEXT: fcvtzu w8, s0 +; CHECK-CVT-NEXT: fmov s0, w8 +; CHECK-CVT-NEXT: ret +; +; CHECK-FP16-LABEL: test_unsigned_v1f16_v1i32: +; CHECK-FP16: // %bb.0: +; CHECK-FP16-NEXT: fcvtzu w8, h0 +; CHECK-FP16-NEXT: fmov s0, w8 +; CHECK-FP16-NEXT: ret %x = call <1 x i32> @llvm.fptoui.sat.v1f16.v1i32(<1 x half> %f) ret <1 x i32> %x } define <2 x i32> @test_unsigned_v2f16_v2i32(<2 x half> %f) { -; CHECK-LABEL: test_unsigned_v2f16_v2i32: -; CHECK: // %bb.0: -; CHECK-NEXT: // kill: def $d0 killed $d0 def $q0 -; CHECK-NEXT: fcvt s1, h0 -; CHECK-NEXT: mov h0, v0.h[1] -; CHECK-NEXT: fcvtzu w8, s1 -; CHECK-NEXT: fcvt s1, h0 -; CHECK-NEXT: fmov s0, w8 -; CHECK-NEXT: fcvtzu w8, s1 -; CHECK-NEXT: mov v0.s[1], w8 -; CHECK-NEXT: // kill: def $d0 killed $d0 killed $q0 -; CHECK-NEXT: ret +; CHECK-CVT-LABEL: test_unsigned_v2f16_v2i32: +; CHECK-CVT: // %bb.0: +; CHECK-CVT-NEXT: fcvtl v0.4s, v0.4h +; CHECK-CVT-NEXT: fcvtzu v0.4s, v0.4s +; CHECK-CVT-NEXT: // kill: def $d0 killed $d0 killed $q0 +; CHECK-CVT-NEXT: ret +; +; CHECK-FP16-LABEL: test_unsigned_v2f16_v2i32: +; CHECK-FP16: // %bb.0: +; CHECK-FP16-NEXT: // kill: def $d0 killed $d0 def $q0 +; CHECK-FP16-NEXT: fcvtzu w8, h0 +; CHECK-FP16-NEXT: mov h1, v0.h[1] +; CHECK-FP16-NEXT: fmov s0, w8 +; CHECK-FP16-NEXT: fcvtzu w8, h1 +; CHECK-FP16-NEXT: mov v0.s[1], w8 +; CHECK-FP16-NEXT: // kill: def $d0 killed $d0 killed $q0 +; CHECK-FP16-NEXT: ret %x = call <2 x i32> @llvm.fptoui.sat.v2f16.v2i32(<2 x half> %f) ret <2 x i32> %x } define <3 x i32> @test_unsigned_v3f16_v3i32(<3 x half> %f) { -; CHECK-LABEL: test_unsigned_v3f16_v3i32: -; CHECK: // %bb.0: -; CHECK-NEXT: // kill: def $d0 killed $d0 def $q0 -; CHECK-NEXT: fcvt s1, h0 -; CHECK-NEXT: mov h2, v0.h[1] -; CHECK-NEXT: fcvtzu w8, s1 -; CHECK-NEXT: fcvt s2, h2 -; CHECK-NEXT: fmov s1, w8 -; CHECK-NEXT: fcvtzu w8, s2 -; CHECK-NEXT: mov h2, v0.h[2] -; CHECK-NEXT: mov h0, v0.h[3] -; CHECK-NEXT: fcvt s2, h2 -; CHECK-NEXT: fcvt s0, h0 -; CHECK-NEXT: mov v1.s[1], w8 -; CHECK-NEXT: fcvtzu w8, s2 -; CHECK-NEXT: mov v1.s[2], w8 -; CHECK-NEXT: fcvtzu w8, s0 -; CHECK-NEXT: mov v1.s[3], w8 -; CHECK-NEXT: mov v0.16b, v1.16b -; CHECK-NEXT: ret +; CHECK-CVT-LABEL: test_unsigned_v3f16_v3i32: +; CHECK-CVT: // %bb.0: +; CHECK-CVT-NEXT: fcvtl v0.4s, v0.4h +; CHECK-CVT-NEXT: fcvtzu v0.4s, v0.4s +; CHECK-CVT-NEXT: ret +; +; CHECK-FP16-LABEL: test_unsigned_v3f16_v3i32: +; CHECK-FP16: // %bb.0: +; CHECK-FP16-NEXT: // kill: def $d0 killed $d0 def $q0 +; CHECK-FP16-NEXT: fcvtzu w8, h0 +; CHECK-FP16-NEXT: mov h1, v0.h[1] +; CHECK-FP16-NEXT: mov h2, v0.h[2] +; CHECK-FP16-NEXT: mov h3, v0.h[3] +; CHECK-FP16-NEXT: fmov s0, w8 +; CHECK-FP16-NEXT: fcvtzu w8, h1 +; CHECK-FP16-NEXT: fcvtzu w9, h2 +; CHECK-FP16-NEXT: mov v0.s[1], w8 +; CHECK-FP16-NEXT: mov v0.s[2], w9 +; CHECK-FP16-NEXT: fcvtzu w8, h3 +; CHECK-FP16-NEXT: mov v0.s[3], w8 +; CHECK-FP16-NEXT: ret %x = call <3 x i32> @llvm.fptoui.sat.v3f16.v3i32(<3 x half> %f) ret <3 x i32> %x } define <4 x i32> @test_unsigned_v4f16_v4i32(<4 x half> %f) { -; CHECK-LABEL: test_unsigned_v4f16_v4i32: -; CHECK: // %bb.0: -; CHECK-NEXT: // kill: def $d0 killed $d0 def $q0 -; CHECK-NEXT: fcvt s1, h0 -; CHECK-NEXT: mov h2, v0.h[1] -; CHECK-NEXT: fcvtzu w8, s1 -; CHECK-NEXT: fcvt s2, h2 -; CHECK-NEXT: fmov s1, w8 -; CHECK-NEXT: fcvtzu w8, s2 -; CHECK-NEXT: mov h2, v0.h[2] -; CHECK-NEXT: mov h0, v0.h[3] -; CHECK-NEXT: fcvt s2, h2 -; CHECK-NEXT: fcvt s0, h0 -; CHECK-NEXT: mov v1.s[1], w8 -; CHECK-NEXT: fcvtzu w8, s2 -; CHECK-NEXT: mov v1.s[2], w8 -; CHECK-NEXT: fcvtzu w8, s0 -; CHECK-NEXT: mov v1.s[3], w8 -; CHECK-NEXT: mov v0.16b, v1.16b -; CHECK-NEXT: ret +; CHECK-CVT-LABEL: test_unsigned_v4f16_v4i32: +; CHECK-CVT: // %bb.0: +; CHECK-CVT-NEXT: fcvtl v0.4s, v0.4h +; CHECK-CVT-NEXT: fcvtzu v0.4s, v0.4s +; CHECK-CVT-NEXT: ret +; +; CHECK-FP16-LABEL: test_unsigned_v4f16_v4i32: +; CHECK-FP16: // %bb.0: +; CHECK-FP16-NEXT: // kill: def $d0 killed $d0 def $q0 +; CHECK-FP16-NEXT: fcvtzu w8, h0 +; CHECK-FP16-NEXT: mov h1, v0.h[1] +; CHECK-FP16-NEXT: mov h2, v0.h[2] +; CHECK-FP16-NEXT: mov h3, v0.h[3] +; CHECK-FP16-NEXT: fmov s0, w8 +; CHECK-FP16-NEXT: fcvtzu w8, h1 +; CHECK-FP16-NEXT: fcvtzu w9, h2 +; CHECK-FP16-NEXT: mov v0.s[1], w8 +; CHECK-FP16-NEXT: mov v0.s[2], w9 +; CHECK-FP16-NEXT: fcvtzu w8, h3 +; CHECK-FP16-NEXT: mov v0.s[3], w8 +; CHECK-FP16-NEXT: ret %x = call <4 x i32> @llvm.fptoui.sat.v4f16.v4i32(<4 x half> %f) ret <4 x i32> %x } define <5 x i32> @test_unsigned_v5f16_v5i32(<5 x half> %f) { -; CHECK-LABEL: test_unsigned_v5f16_v5i32: -; CHECK: // %bb.0: -; CHECK-NEXT: fcvt s1, h0 -; CHECK-NEXT: fcvtzu w0, s1 -; CHECK-NEXT: ext v1.16b, v0.16b, v0.16b, #8 -; CHECK-NEXT: fcvt s1, h1 -; CHECK-NEXT: fcvtzu w4, s1 -; CHECK-NEXT: mov h1, v0.h[1] -; CHECK-NEXT: fcvt s1, h1 -; CHECK-NEXT: fcvtzu w1, s1 -; CHECK-NEXT: mov h1, v0.h[2] -; CHECK-NEXT: mov h0, v0.h[3] -; CHECK-NEXT: fcvt s1, h1 -; CHECK-NEXT: fcvt s0, h0 -; CHECK-NEXT: fcvtzu w2, s1 -; CHECK-NEXT: fcvtzu w3, s0 -; CHECK-NEXT: ret +; CHECK-CVT-LABEL: test_unsigned_v5f16_v5i32: +; CHECK-CVT: // %bb.0: +; CHECK-CVT-NEXT: fcvtl v1.4s, v0.4h +; CHECK-CVT-NEXT: fcvtl2 v0.4s, v0.8h +; CHECK-CVT-NEXT: fcvtzu v1.4s, v1.4s +; CHECK-CVT-NEXT: fcvtzu v0.4s, v0.4s +; CHECK-CVT-NEXT: mov w1, v1.s[1] +; CHECK-CVT-NEXT: mov w2, v1.s[2] +; CHECK-CVT-NEXT: mov w3, v1.s[3] +; CHECK-CVT-NEXT: fmov w4, s0 +; CHECK-CVT-NEXT: fmov w0, s1 +; CHECK-CVT-NEXT: ret +; +; CHECK-FP16-LABEL: test_unsigned_v5f16_v5i32: +; CHECK-FP16: // %bb.0: +; CHECK-FP16-NEXT: ext v1.16b, v0.16b, v0.16b, #8 +; CHECK-FP16-NEXT: fcvtzu w0, h0 +; CHECK-FP16-NEXT: mov h2, v0.h[1] +; CHECK-FP16-NEXT: mov h3, v0.h[2] +; CHECK-FP16-NEXT: mov h0, v0.h[3] +; CHECK-FP16-NEXT: fcvtzu w4, h1 +; CHECK-FP16-NEXT: fcvtzu w1, h2 +; CHECK-FP16-NEXT: fcvtzu w2, h3 +; CHECK-FP16-NEXT: fcvtzu w3, h0 +; CHECK-FP16-NEXT: ret %x = call <5 x i32> @llvm.fptoui.sat.v5f16.v5i32(<5 x half> %f) ret <5 x i32> %x } define <6 x i32> @test_unsigned_v6f16_v6i32(<6 x half> %f) { -; CHECK-LABEL: test_unsigned_v6f16_v6i32: -; CHECK: // %bb.0: -; CHECK-NEXT: ext v1.16b, v0.16b, v0.16b, #8 -; CHECK-NEXT: fcvt s2, h0 -; CHECK-NEXT: fcvtzu w0, s2 -; CHECK-NEXT: fcvt s2, h1 -; CHECK-NEXT: fcvtzu w8, s2 -; CHECK-NEXT: mov h2, v0.h[1] -; CHECK-NEXT: fcvt s2, h2 -; CHECK-NEXT: fcvtzu w1, s2 -; CHECK-NEXT: mov h2, v0.h[2] -; CHECK-NEXT: mov h1, v1.h[1] -; CHECK-NEXT: fcvt s2, h2 -; CHECK-NEXT: fcvt s1, h1 -; CHECK-NEXT: mov h0, v0.h[3] -; CHECK-NEXT: fcvtzu w2, s2 -; CHECK-NEXT: fmov s2, w8 -; CHECK-NEXT: fcvtzu w5, s1 -; CHECK-NEXT: fcvt s0, h0 -; CHECK-NEXT: mov v2.s[1], w5 -; CHECK-NEXT: fcvtzu w3, s0 -; CHECK-NEXT: fmov w4, s2 -; CHECK-NEXT: ret +; CHECK-CVT-LABEL: test_unsigned_v6f16_v6i32: +; CHECK-CVT: // %bb.0: +; CHECK-CVT-NEXT: fcvtl v1.4s, v0.4h +; CHECK-CVT-NEXT: fcvtl2 v0.4s, v0.8h +; CHECK-CVT-NEXT: fcvtzu v1.4s, v1.4s +; CHECK-CVT-NEXT: fcvtzu v0.4s, v0.4s +; CHECK-CVT-NEXT: mov w5, v0.s[1] +; CHECK-CVT-NEXT: mov w1, v1.s[1] +; CHECK-CVT-NEXT: mov w2, v1.s[2] +; CHECK-CVT-NEXT: mov w3, v1.s[3] +; CHECK-CVT-NEXT: fmov w4, s0 +; CHECK-CVT-NEXT: fmov w0, s1 +; CHECK-CVT-NEXT: ret +; +; CHECK-FP16-LABEL: test_unsigned_v6f16_v6i32: +; CHECK-FP16: // %bb.0: +; CHECK-FP16-NEXT: ext v1.16b, v0.16b, v0.16b, #8 +; CHECK-FP16-NEXT: mov h2, v0.h[1] +; CHECK-FP16-NEXT: fcvtzu w1, h2 +; CHECK-FP16-NEXT: mov h2, v0.h[2] +; CHECK-FP16-NEXT: fcvtzu w8, h1 +; CHECK-FP16-NEXT: mov h1, v1.h[1] +; CHECK-FP16-NEXT: fcvtzu w2, h2 +; CHECK-FP16-NEXT: fmov s2, w8 +; CHECK-FP16-NEXT: fcvtzu w5, h1 +; CHECK-FP16-NEXT: fcvtzu w0, h0 +; CHECK-FP16-NEXT: mov h0, v0.h[3] +; CHECK-FP16-NEXT: mov v2.s[1], w5 +; CHECK-FP16-NEXT: fcvtzu w3, h0 +; CHECK-FP16-NEXT: fmov w4, s2 +; CHECK-FP16-NEXT: ret %x = call <6 x i32> @llvm.fptoui.sat.v6f16.v6i32(<6 x half> %f) ret <6 x i32> %x } define <7 x i32> @test_unsigned_v7f16_v7i32(<7 x half> %f) { -; CHECK-LABEL: test_unsigned_v7f16_v7i32: -; CHECK: // %bb.0: -; CHECK-NEXT: ext v1.16b, v0.16b, v0.16b, #8 -; CHECK-NEXT: fcvt s2, h0 -; CHECK-NEXT: mov h3, v0.h[1] -; CHECK-NEXT: fcvtzu w0, s2 -; CHECK-NEXT: fcvt s2, h1 -; CHECK-NEXT: fcvt s3, h3 -; CHECK-NEXT: fcvtzu w8, s2 -; CHECK-NEXT: mov h2, v0.h[2] -; CHECK-NEXT: fcvtzu w1, s3 -; CHECK-NEXT: mov h3, v1.h[1] -; CHECK-NEXT: mov h1, v1.h[2] -; CHECK-NEXT: fcvt s2, h2 -; CHECK-NEXT: fcvt s3, h3 -; CHECK-NEXT: fcvt s1, h1 -; CHECK-NEXT: fcvtzu w2, s2 -; CHECK-NEXT: fmov s2, w8 -; CHECK-NEXT: fcvtzu w8, s3 -; CHECK-NEXT: mov h0, v0.h[3] -; CHECK-NEXT: fcvtzu w6, s1 -; CHECK-NEXT: mov v2.s[1], w8 -; CHECK-NEXT: fcvt s0, h0 -; CHECK-NEXT: mov v2.s[2], w6 -; CHECK-NEXT: fcvtzu w3, s0 -; CHECK-NEXT: mov w5, v2.s[1] -; CHECK-NEXT: fmov w4, s2 -; CHECK-NEXT: ret +; CHECK-CVT-LABEL: test_unsigned_v7f16_v7i32: +; CHECK-CVT: // %bb.0: +; CHECK-CVT-NEXT: fcvtl v1.4s, v0.4h +; CHECK-CVT-NEXT: fcvtl2 v0.4s, v0.8h +; CHECK-CVT-NEXT: fcvtzu v1.4s, v1.4s +; CHECK-CVT-NEXT: fcvtzu v0.4s, v0.4s +; CHECK-CVT-NEXT: mov w5, v0.s[1] +; CHECK-CVT-NEXT: mov w6, v0.s[2] +; CHECK-CVT-NEXT: mov w1, v1.s[1] +; CHECK-CVT-NEXT: mov w2, v1.s[2] +; CHECK-CVT-NEXT: mov w3, v1.s[3] +; CHECK-CVT-NEXT: fmov w4, s0 +; CHECK-CVT-NEXT: fmov w0, s1 +; CHECK-CVT-NEXT: ret +; +; CHECK-FP16-LABEL: test_unsigned_v7f16_v7i32: +; CHECK-FP16: // %bb.0: +; CHECK-FP16-NEXT: ext v1.16b, v0.16b, v0.16b, #8 +; CHECK-FP16-NEXT: mov h2, v0.h[1] +; CHECK-FP16-NEXT: mov h3, v0.h[2] +; CHECK-FP16-NEXT: fcvtzu w8, h1 +; CHECK-FP16-NEXT: fcvtzu w1, h2 +; CHECK-FP16-NEXT: mov h2, v1.h[1] +; CHECK-FP16-NEXT: mov h1, v1.h[2] +; CHECK-FP16-NEXT: fcvtzu w2, h3 +; CHECK-FP16-NEXT: fmov s3, w8 +; CHECK-FP16-NEXT: fcvtzu w8, h2 +; CHECK-FP16-NEXT: fcvtzu w6, h1 +; CHECK-FP16-NEXT: mov v3.s[1], w8 +; CHECK-FP16-NEXT: fcvtzu w0, h0 +; CHECK-FP16-NEXT: mov h0, v0.h[3] +; CHECK-FP16-NEXT: mov v3.s[2], w6 +; CHECK-FP16-NEXT: fcvtzu w3, h0 +; CHECK-FP16-NEXT: mov w5, v3.s[1] +; CHECK-FP16-NEXT: fmov w4, s3 +; CHECK-FP16-NEXT: ret %x = call <7 x i32> @llvm.fptoui.sat.v7f16.v7i32(<7 x half> %f) ret <7 x i32> %x } define <8 x i32> @test_unsigned_v8f16_v8i32(<8 x half> %f) { -; CHECK-LABEL: test_unsigned_v8f16_v8i32: -; CHECK: // %bb.0: -; CHECK-NEXT: ext v3.16b, v0.16b, v0.16b, #8 -; CHECK-NEXT: fcvt s1, h0 -; CHECK-NEXT: fcvtzu w8, s1 -; CHECK-NEXT: fcvt s1, h3 -; CHECK-NEXT: mov h2, v0.h[1] -; CHECK-NEXT: fcvtzu w9, s1 -; CHECK-NEXT: mov h1, v0.h[2] -; CHECK-NEXT: fcvt s2, h2 -; CHECK-NEXT: fcvt s1, h1 -; CHECK-NEXT: fcvtzu w10, s2 -; CHECK-NEXT: mov h2, v3.h[1] -; CHECK-NEXT: fcvtzu w11, s1 -; CHECK-NEXT: mov h1, v3.h[2] -; CHECK-NEXT: fcvt s2, h2 -; CHECK-NEXT: fcvt s1, h1 -; CHECK-NEXT: fcvtzu w12, s2 -; CHECK-NEXT: fmov s2, w8 -; CHECK-NEXT: fcvtzu w8, s1 -; CHECK-NEXT: fmov s1, w9 -; CHECK-NEXT: mov h3, v3.h[3] -; CHECK-NEXT: mov v1.s[1], w12 -; CHECK-NEXT: mov h0, v0.h[3] -; CHECK-NEXT: fcvt s3, h3 -; CHECK-NEXT: mov v2.s[1], w10 -; CHECK-NEXT: fcvt s0, h0 -; CHECK-NEXT: mov v1.s[2], w8 -; CHECK-NEXT: fcvtzu w8, s3 -; CHECK-NEXT: mov v2.s[2], w11 -; CHECK-NEXT: mov v1.s[3], w8 -; CHECK-NEXT: fcvtzu w8, s0 -; CHECK-NEXT: mov v2.s[3], w8 -; CHECK-NEXT: mov v0.16b, v2.16b -; CHECK-NEXT: ret +; CHECK-CVT-LABEL: test_unsigned_v8f16_v8i32: +; CHECK-CVT: // %bb.0: +; CHECK-CVT-NEXT: fcvtl2 v1.4s, v0.8h +; CHECK-CVT-NEXT: fcvtl v0.4s, v0.4h +; CHECK-CVT-NEXT: fcvtzu v1.4s, v1.4s +; CHECK-CVT-NEXT: fcvtzu v0.4s, v0.4s +; CHECK-CVT-NEXT: ret +; +; CHECK-FP16-LABEL: test_unsigned_v8f16_v8i32: +; CHECK-FP16: // %bb.0: +; CHECK-FP16-NEXT: ext v3.16b, v0.16b, v0.16b, #8 +; CHECK-FP16-NEXT: mov h1, v0.h[1] +; CHECK-FP16-NEXT: fcvtzu w9, h3 +; CHECK-FP16-NEXT: fcvtzu w10, h1 +; CHECK-FP16-NEXT: mov h1, v3.h[1] +; CHECK-FP16-NEXT: fcvtzu w8, h0 +; CHECK-FP16-NEXT: mov h2, v0.h[2] +; CHECK-FP16-NEXT: mov h4, v3.h[2] +; CHECK-FP16-NEXT: fcvtzu w12, h1 +; CHECK-FP16-NEXT: fmov s1, w9 +; CHECK-FP16-NEXT: fcvtzu w11, h2 +; CHECK-FP16-NEXT: fmov s2, w8 +; CHECK-FP16-NEXT: fcvtzu w8, h4 +; CHECK-FP16-NEXT: mov v1.s[1], w12 +; CHECK-FP16-NEXT: mov h3, v3.h[3] +; CHECK-FP16-NEXT: mov v2.s[1], w10 +; CHECK-FP16-NEXT: mov h0, v0.h[3] +; CHECK-FP16-NEXT: mov v1.s[2], w8 +; CHECK-FP16-NEXT: fcvtzu w8, h3 +; CHECK-FP16-NEXT: mov v2.s[2], w11 +; CHECK-FP16-NEXT: mov v1.s[3], w8 +; CHECK-FP16-NEXT: fcvtzu w8, h0 +; CHECK-FP16-NEXT: mov v2.s[3], w8 +; CHECK-FP16-NEXT: mov v0.16b, v2.16b +; CHECK-FP16-NEXT: ret %x = call <8 x i32> @llvm.fptoui.sat.v8f16.v8i32(<8 x half> %f) ret <8 x i32> %x } @@ -848,13 +860,7 @@ define <2 x i32> @test_unsigned_v2f32_v2i32_duplicate(<2 x float> %f) { ; CHECK-LABEL: test_unsigned_v2f32_v2i32_duplicate: ; CHECK: // %bb.0: -; CHECK-NEXT: // kill: def $d0 killed $d0 def $q0 -; CHECK-NEXT: fcvtzu w8, s0 -; CHECK-NEXT: mov s1, v0.s[1] -; CHECK-NEXT: fmov s0, w8 -; CHECK-NEXT: fcvtzu w8, s1 -; CHECK-NEXT: mov v0.s[1], w8 -; CHECK-NEXT: // kill: def $d0 killed $d0 killed $q0 +; CHECK-NEXT: fcvtzu v0.2s, v0.2s ; CHECK-NEXT: ret %x = call <2 x i32> @llvm.fptoui.sat.v2f32.v2i32(<2 x float> %f) ret <2 x i32> %x @@ -1161,11 +1167,7 @@ define <2 x i64> @test_unsigned_v2f64_v2i64(<2 x double> %f) { ; CHECK-LABEL: test_unsigned_v2f64_v2i64: ; CHECK: // %bb.0: -; CHECK-NEXT: fcvtzu x8, d0 -; CHECK-NEXT: mov d1, v0.d[1] -; CHECK-NEXT: fmov d0, x8 -; CHECK-NEXT: fcvtzu x8, d1 -; CHECK-NEXT: mov v0.d[1], x8 +; CHECK-NEXT: fcvtzu v0.2d, v0.2d ; CHECK-NEXT: ret %x = call <2 x i64> @llvm.fptoui.sat.v2f64.v2i64(<2 x double> %f) ret <2 x i64> %x @@ -1394,38 +1396,39 @@ } define <4 x i16> @test_unsigned_v4f16_v4i16(<4 x half> %f) { -; CHECK-LABEL: test_unsigned_v4f16_v4i16: -; CHECK: // %bb.0: -; CHECK-NEXT: // kill: def $d0 killed $d0 def $q0 -; CHECK-NEXT: fcvt s1, h0 -; CHECK-NEXT: mov w8, #65280 -; CHECK-NEXT: mov h3, v0.h[1] -; CHECK-NEXT: mov h4, v0.h[2] -; CHECK-NEXT: mov h0, v0.h[3] -; CHECK-NEXT: movi d2, #0000000000000000 -; CHECK-NEXT: movk w8, #18303, lsl #16 -; CHECK-NEXT: fcvt s3, h3 -; CHECK-NEXT: fcvt s4, h4 -; CHECK-NEXT: fcvt s0, h0 -; CHECK-NEXT: fmaxnm s1, s1, s2 -; CHECK-NEXT: fmaxnm s3, s3, s2 -; CHECK-NEXT: fmaxnm s4, s4, s2 -; CHECK-NEXT: fmaxnm s0, s0, s2 -; CHECK-NEXT: fmov s2, w8 -; CHECK-NEXT: fminnm s1, s1, s2 -; CHECK-NEXT: fcvtzu w8, s1 -; CHECK-NEXT: fminnm s1, s3, s2 -; CHECK-NEXT: fminnm s3, s4, s2 -; CHECK-NEXT: fminnm s2, s0, s2 -; CHECK-NEXT: fmov s0, w8 -; CHECK-NEXT: fcvtzu w8, s1 -; CHECK-NEXT: mov v0.h[1], w8 -; CHECK-NEXT: fcvtzu w8, s3 -; CHECK-NEXT: mov v0.h[2], w8 -; CHECK-NEXT: fcvtzu w8, s2 -; CHECK-NEXT: mov v0.h[3], w8 -; CHECK-NEXT: // kill: def $d0 killed $d0 killed $q0 -; CHECK-NEXT: ret +; CHECK-CVT-LABEL: test_unsigned_v4f16_v4i16: +; CHECK-CVT: // %bb.0: +; CHECK-CVT-NEXT: fcvtl v0.4s, v0.4h +; CHECK-CVT-NEXT: movi d1, #0000000000000000 +; CHECK-CVT-NEXT: mov w8, #65280 +; CHECK-CVT-NEXT: movk w8, #18303, lsl #16 +; CHECK-CVT-NEXT: fmaxnm s2, s0, s1 +; CHECK-CVT-NEXT: mov s3, v0.s[1] +; CHECK-CVT-NEXT: mov s4, v0.s[2] +; CHECK-CVT-NEXT: mov s0, v0.s[3] +; CHECK-CVT-NEXT: fmaxnm s3, s3, s1 +; CHECK-CVT-NEXT: fmaxnm s4, s4, s1 +; CHECK-CVT-NEXT: fmaxnm s0, s0, s1 +; CHECK-CVT-NEXT: fmov s1, w8 +; CHECK-CVT-NEXT: fminnm s2, s2, s1 +; CHECK-CVT-NEXT: fcvtzu w8, s2 +; CHECK-CVT-NEXT: fminnm s2, s3, s1 +; CHECK-CVT-NEXT: fminnm s3, s4, s1 +; CHECK-CVT-NEXT: fminnm s1, s0, s1 +; CHECK-CVT-NEXT: fmov s0, w8 +; CHECK-CVT-NEXT: fcvtzu w8, s2 +; CHECK-CVT-NEXT: mov v0.h[1], w8 +; CHECK-CVT-NEXT: fcvtzu w8, s3 +; CHECK-CVT-NEXT: mov v0.h[2], w8 +; CHECK-CVT-NEXT: fcvtzu w8, s1 +; CHECK-CVT-NEXT: mov v0.h[3], w8 +; CHECK-CVT-NEXT: // kill: def $d0 killed $d0 killed $q0 +; CHECK-CVT-NEXT: ret +; +; CHECK-FP16-LABEL: test_unsigned_v4f16_v4i16: +; CHECK-FP16: // %bb.0: +; CHECK-FP16-NEXT: fcvtzu v0.4h, v0.4h +; CHECK-FP16-NEXT: ret %x = call <4 x i16> @llvm.fptoui.sat.v4f16.v4i16(<4 x half> %f) ret <4 x i16> %x } @@ -1467,26 +1470,27 @@ } define <4 x i32> @test_unsigned_v4f16_v4i32_duplicate(<4 x half> %f) { -; CHECK-LABEL: test_unsigned_v4f16_v4i32_duplicate: -; CHECK: // %bb.0: -; CHECK-NEXT: // kill: def $d0 killed $d0 def $q0 -; CHECK-NEXT: fcvt s1, h0 -; CHECK-NEXT: mov h2, v0.h[1] -; CHECK-NEXT: fcvtzu w8, s1 -; CHECK-NEXT: fcvt s2, h2 -; CHECK-NEXT: fmov s1, w8 -; CHECK-NEXT: fcvtzu w8, s2 -; CHECK-NEXT: mov h2, v0.h[2] -; CHECK-NEXT: mov h0, v0.h[3] -; CHECK-NEXT: fcvt s2, h2 -; CHECK-NEXT: fcvt s0, h0 -; CHECK-NEXT: mov v1.s[1], w8 -; CHECK-NEXT: fcvtzu w8, s2 -; CHECK-NEXT: mov v1.s[2], w8 -; CHECK-NEXT: fcvtzu w8, s0 -; CHECK-NEXT: mov v1.s[3], w8 -; CHECK-NEXT: mov v0.16b, v1.16b -; CHECK-NEXT: ret +; CHECK-CVT-LABEL: test_unsigned_v4f16_v4i32_duplicate: +; CHECK-CVT: // %bb.0: +; CHECK-CVT-NEXT: fcvtl v0.4s, v0.4h +; CHECK-CVT-NEXT: fcvtzu v0.4s, v0.4s +; CHECK-CVT-NEXT: ret +; +; CHECK-FP16-LABEL: test_unsigned_v4f16_v4i32_duplicate: +; CHECK-FP16: // %bb.0: +; CHECK-FP16-NEXT: // kill: def $d0 killed $d0 def $q0 +; CHECK-FP16-NEXT: fcvtzu w8, h0 +; CHECK-FP16-NEXT: mov h1, v0.h[1] +; CHECK-FP16-NEXT: mov h2, v0.h[2] +; CHECK-FP16-NEXT: mov h3, v0.h[3] +; CHECK-FP16-NEXT: fmov s0, w8 +; CHECK-FP16-NEXT: fcvtzu w8, h1 +; CHECK-FP16-NEXT: fcvtzu w9, h2 +; CHECK-FP16-NEXT: mov v0.s[1], w8 +; CHECK-FP16-NEXT: mov v0.s[2], w9 +; CHECK-FP16-NEXT: fcvtzu w8, h3 +; CHECK-FP16-NEXT: mov v0.s[3], w8 +; CHECK-FP16-NEXT: ret %x = call <4 x i32> @llvm.fptoui.sat.v4f16.v4i32(<4 x half> %f) ret <4 x i32> %x } @@ -1531,26 +1535,42 @@ } define <4 x i64> @test_unsigned_v4f16_v4i64(<4 x half> %f) { -; CHECK-LABEL: test_unsigned_v4f16_v4i64: -; CHECK: // %bb.0: -; CHECK-NEXT: // kill: def $d0 killed $d0 def $q0 -; CHECK-NEXT: fcvt s1, h0 -; CHECK-NEXT: mov h2, v0.h[1] -; CHECK-NEXT: fcvtzu x8, s1 -; CHECK-NEXT: fcvt s1, h2 -; CHECK-NEXT: fmov d2, x8 -; CHECK-NEXT: fcvtzu x8, s1 -; CHECK-NEXT: mov h1, v0.h[2] -; CHECK-NEXT: mov h0, v0.h[3] -; CHECK-NEXT: fcvt s1, h1 -; CHECK-NEXT: mov v2.d[1], x8 -; CHECK-NEXT: fcvtzu x8, s1 -; CHECK-NEXT: fcvt s0, h0 -; CHECK-NEXT: fmov d1, x8 -; CHECK-NEXT: fcvtzu x8, s0 -; CHECK-NEXT: mov v1.d[1], x8 -; CHECK-NEXT: mov v0.16b, v2.16b -; CHECK-NEXT: ret +; CHECK-CVT-LABEL: test_unsigned_v4f16_v4i64: +; CHECK-CVT: // %bb.0: +; CHECK-CVT-NEXT: // kill: def $d0 killed $d0 def $q0 +; CHECK-CVT-NEXT: fcvt s1, h0 +; CHECK-CVT-NEXT: mov h2, v0.h[1] +; CHECK-CVT-NEXT: fcvtzu x8, s1 +; CHECK-CVT-NEXT: fcvt s1, h2 +; CHECK-CVT-NEXT: fmov d2, x8 +; CHECK-CVT-NEXT: fcvtzu x8, s1 +; CHECK-CVT-NEXT: mov h1, v0.h[2] +; CHECK-CVT-NEXT: mov h0, v0.h[3] +; CHECK-CVT-NEXT: fcvt s1, h1 +; CHECK-CVT-NEXT: mov v2.d[1], x8 +; CHECK-CVT-NEXT: fcvtzu x8, s1 +; CHECK-CVT-NEXT: fcvt s0, h0 +; CHECK-CVT-NEXT: fmov d1, x8 +; CHECK-CVT-NEXT: fcvtzu x8, s0 +; CHECK-CVT-NEXT: mov v1.d[1], x8 +; CHECK-CVT-NEXT: mov v0.16b, v2.16b +; CHECK-CVT-NEXT: ret +; +; CHECK-FP16-LABEL: test_unsigned_v4f16_v4i64: +; CHECK-FP16: // %bb.0: +; CHECK-FP16-NEXT: // kill: def $d0 killed $d0 def $q0 +; CHECK-FP16-NEXT: fcvtzu x8, h0 +; CHECK-FP16-NEXT: mov h1, v0.h[1] +; CHECK-FP16-NEXT: mov h2, v0.h[2] +; CHECK-FP16-NEXT: mov h3, v0.h[3] +; CHECK-FP16-NEXT: fmov d0, x8 +; CHECK-FP16-NEXT: fcvtzu x8, h1 +; CHECK-FP16-NEXT: fcvtzu x9, h2 +; CHECK-FP16-NEXT: mov v0.d[1], x8 +; CHECK-FP16-NEXT: fmov d1, x9 +; CHECK-FP16-NEXT: fcvtzu x8, h3 +; CHECK-FP16-NEXT: mov v1.d[1], x8 +; CHECK-FP16-NEXT: ret %x = call <4 x i64> @llvm.fptoui.sat.v4f16.v4i64(<4 x half> %f) ret <4 x i64> %x }