@@ -1454,8 +1454,12 @@ AArch64TargetLowering::AArch64TargetLowering(const TargetMachine &TM,
14541454 setOperationAction(ISD::INSERT_SUBVECTOR, VT, Custom);
14551455 setOperationAction(ISD::UINT_TO_FP, VT, Custom);
14561456 setOperationAction(ISD::SINT_TO_FP, VT, Custom);
1457+ setOperationAction(ISD::STRICT_UINT_TO_FP, VT, Custom);
1458+ setOperationAction(ISD::STRICT_SINT_TO_FP, VT, Custom);
14571459 setOperationAction(ISD::FP_TO_UINT, VT, Custom);
14581460 setOperationAction(ISD::FP_TO_SINT, VT, Custom);
1461+ setOperationAction(ISD::STRICT_FP_TO_UINT, VT, Custom);
1462+ setOperationAction(ISD::STRICT_FP_TO_SINT, VT, Custom);
14591463 setOperationAction(ISD::MLOAD, VT, Custom);
14601464 setOperationAction(ISD::MUL, VT, Custom);
14611465 setOperationAction(ISD::MULHS, VT, Custom);
@@ -2138,6 +2142,8 @@ void AArch64TargetLowering::addTypeForFixedLengthSVE(MVT VT) {
21382142 setOperationAction(ISD::FP_ROUND, VT, Default);
21392143 setOperationAction(ISD::FP_TO_SINT, VT, Default);
21402144 setOperationAction(ISD::FP_TO_UINT, VT, Default);
2145+ setOperationAction(ISD::STRICT_FP_TO_SINT, VT, Default);
2146+ setOperationAction(ISD::STRICT_FP_TO_UINT, VT, Default);
21412147 setOperationAction(ISD::FRINT, VT, Default);
21422148 setOperationAction(ISD::LRINT, VT, Default);
21432149 setOperationAction(ISD::LLRINT, VT, Default);
@@ -2164,6 +2170,7 @@ void AArch64TargetLowering::addTypeForFixedLengthSVE(MVT VT) {
21642170 setOperationAction(ISD::SIGN_EXTEND, VT, Default);
21652171 setOperationAction(ISD::SIGN_EXTEND_INREG, VT, Default);
21662172 setOperationAction(ISD::SINT_TO_FP, VT, Default);
2173+ setOperationAction(ISD::STRICT_SINT_TO_FP, VT, Default);
21672174 setOperationAction(ISD::SMAX, VT, Default);
21682175 setOperationAction(ISD::SMIN, VT, Default);
21692176 setOperationAction(ISD::SPLAT_VECTOR, VT, Default);
@@ -2174,6 +2181,7 @@ void AArch64TargetLowering::addTypeForFixedLengthSVE(MVT VT) {
21742181 setOperationAction(ISD::TRUNCATE, VT, Default);
21752182 setOperationAction(ISD::UDIV, VT, Default);
21762183 setOperationAction(ISD::UINT_TO_FP, VT, Default);
2184+ setOperationAction(ISD::STRICT_UINT_TO_FP, VT, Default);
21772185 setOperationAction(ISD::UMAX, VT, Default);
21782186 setOperationAction(ISD::UMIN, VT, Default);
21792187 setOperationAction(ISD::VECREDUCE_ADD, VT, Default);
@@ -4550,9 +4558,10 @@ SDValue AArch64TargetLowering::LowerVectorFP_TO_INT(SDValue Op,
45504558 EVT VT = Op.getValueType();
45514559
45524560 if (VT.isScalableVector()) {
4553- unsigned Opcode = Op.getOpcode() == ISD::FP_TO_UINT
4554- ? AArch64ISD::FCVTZU_MERGE_PASSTHRU
4555- : AArch64ISD::FCVTZS_MERGE_PASSTHRU;
4561+ unsigned Opc = Op.getOpcode();
4562+ bool IsSigned = Opc == ISD::FP_TO_SINT || Opc == ISD::STRICT_FP_TO_SINT;
4563+ unsigned Opcode = IsSigned ? AArch64ISD::FCVTZS_MERGE_PASSTHRU
4564+ : AArch64ISD::FCVTZU_MERGE_PASSTHRU;
45564565 return LowerToPredicatedOp(Op, DAG, Opcode);
45574566 }
45584567
@@ -4628,6 +4637,51 @@ SDValue AArch64TargetLowering::LowerVectorFP_TO_INT(SDValue Op,
46284637 return Op;
46294638}
46304639
4640+ static bool CanLowerToScalarSVEFPIntConversion(EVT VT) {
4641+ if (!VT.isSimple())
4642+ return false;
4643+ // There are SVE instructions that can convert to/from all pairs of these int
4644+ // and float types. Note: We don't bother with i8 or i16 as those are illegal
4645+ // types for scalars.
4646+ return is_contained({MVT::i32, MVT::i64, MVT::f16, MVT::f32, MVT::f64},
4647+ VT.getSimpleVT().SimpleTy);
4648+ }
4649+
4650+ /// Lowers a scalar FP conversion (to/from) int to SVE.
4651+ static SDValue LowerScalarFPConversionToSVE(SDValue Op, SelectionDAG &DAG) {
4652+ bool IsStrict = Op->isStrictFPOpcode();
4653+ SDValue SrcVal = Op.getOperand(IsStrict ? 1 : 0);
4654+ EVT SrcTy = SrcVal.getValueType();
4655+ EVT DestTy = Op.getValueType();
4656+ EVT SrcVecTy;
4657+ EVT DestVecTy;
4658+ // Use a packed vector for the larger type.
4659+ // Note: For conversions such as FCVTZS_ZPmZ_DtoS, and UCVTF_ZPmZ_StoD that
4660+ // notionally take or return a nxv2i32 type we must instead use a nxv4i32, as
4661+ // (unlike floats) nxv2i32 is an illegal unpacked type.
4662+ if (DestTy.bitsGT(SrcTy)) {
4663+ DestVecTy = getPackedSVEVectorVT(DestTy);
4664+ SrcVecTy = SrcTy == MVT::i32 ? getPackedSVEVectorVT(SrcTy)
4665+ : DestVecTy.changeVectorElementType(SrcTy);
4666+ } else {
4667+ SrcVecTy = getPackedSVEVectorVT(SrcTy);
4668+ DestVecTy = DestTy == MVT::i32 ? getPackedSVEVectorVT(DestTy)
4669+ : SrcVecTy.changeVectorElementType(DestTy);
4670+ }
4671+ SDLoc dl(Op);
4672+ SDValue ZeroIdx = DAG.getVectorIdxConstant(0, dl);
4673+ SDValue Vec = DAG.getNode(ISD::INSERT_VECTOR_ELT, dl, SrcVecTy,
4674+ DAG.getUNDEF(SrcVecTy), SrcVal, ZeroIdx);
4675+ Vec = IsStrict ? DAG.getNode(Op.getOpcode(), dl, {DestVecTy, MVT::Other},
4676+ {Op.getOperand(0), Vec})
4677+ : DAG.getNode(Op.getOpcode(), dl, DestVecTy, Vec);
4678+ SDValue Scalar =
4679+ DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, Op.getValueType(), Vec, ZeroIdx);
4680+ if (IsStrict)
4681+ return DAG.getMergeValues({Scalar, Vec.getValue(1)}, dl);
4682+ return Scalar;
4683+ }
4684+
46314685SDValue AArch64TargetLowering::LowerFP_TO_INT(SDValue Op,
46324686 SelectionDAG &DAG) const {
46334687 bool IsStrict = Op->isStrictFPOpcode();
@@ -4636,6 +4690,12 @@ SDValue AArch64TargetLowering::LowerFP_TO_INT(SDValue Op,
46364690 if (SrcVal.getValueType().isVector())
46374691 return LowerVectorFP_TO_INT(Op, DAG);
46384692
4693+ if (!Subtarget->isNeonAvailable() &&
4694+ Subtarget->isSVEorStreamingSVEAvailable() &&
4695+ CanLowerToScalarSVEFPIntConversion(SrcVal.getValueType()) &&
4696+ CanLowerToScalarSVEFPIntConversion(Op.getValueType()))
4697+ return LowerScalarFPConversionToSVE(Op, DAG);
4698+
46394699 // f16 conversions are promoted to f32 when full fp16 is not supported.
46404700 if ((SrcVal.getValueType() == MVT::f16 && !Subtarget->hasFullFP16()) ||
46414701 SrcVal.getValueType() == MVT::bf16) {
@@ -4939,6 +4999,12 @@ SDValue AArch64TargetLowering::LowerINT_TO_FP(SDValue Op,
49394999 bool IsStrict = Op->isStrictFPOpcode();
49405000 SDValue SrcVal = Op.getOperand(IsStrict ? 1 : 0);
49415001
5002+ if (!Subtarget->isNeonAvailable() &&
5003+ Subtarget->isSVEorStreamingSVEAvailable() &&
5004+ CanLowerToScalarSVEFPIntConversion(SrcVal.getValueType()) &&
5005+ CanLowerToScalarSVEFPIntConversion(Op.getValueType()))
5006+ return LowerScalarFPConversionToSVE(Op, DAG);
5007+
49425008 bool IsSigned = Op->getOpcode() == ISD::STRICT_SINT_TO_FP ||
49435009 Op->getOpcode() == ISD::SINT_TO_FP;
49445010
@@ -28293,7 +28359,21 @@ SDValue AArch64TargetLowering::LowerToPredicatedOp(SDValue Op,
2829328359 unsigned NewOp) const {
2829428360 EVT VT = Op.getValueType();
2829528361 SDLoc DL(Op);
28296- auto Pg = getPredicateForVector(DAG, DL, VT);
28362+ SDValue Pg;
28363+
28364+ // FCVTZS_ZPmZ_DtoS and FCVTZU_ZPmZ_DtoS are special cases. These operations
28365+ // return nxv4i32 rather than the correct nxv2i32, as nxv2i32 is an illegal
28366+ // unpacked type. So, in this case, we take the predicate size from the
28367+ // operand.
28368+ SDValue LastOp{};
28369+ if ((NewOp == AArch64ISD::FCVTZU_MERGE_PASSTHRU ||
28370+ NewOp == AArch64ISD::FCVTZS_MERGE_PASSTHRU) &&
28371+ VT == MVT::nxv4i32 &&
28372+ (LastOp = Op->ops().back().get()).getValueType() == MVT::nxv2f64) {
28373+ Pg = getPredicateForVector(DAG, DL, LastOp.getValueType());
28374+ } else {
28375+ Pg = getPredicateForVector(DAG, DL, VT);
28376+ }
2829728377
2829828378 if (VT.isFixedLengthVector()) {
2829928379 assert(isTypeLegal(VT) && "Expected only legal fixed-width types");
@@ -28329,7 +28409,12 @@ SDValue AArch64TargetLowering::LowerToPredicatedOp(SDValue Op,
2832928409 assert(VT.isScalableVector() && "Only expect to lower scalable vector op!");
2833028410
2833128411 SmallVector<SDValue, 4> Operands = {Pg};
28412+ SDValue Chain{};
2833228413 for (const SDValue &V : Op->op_values()) {
28414+ if (!isa<CondCodeSDNode>(V) && V.getValueType() == MVT::Other) {
28415+ Chain = V;
28416+ continue;
28417+ }
2833328418 assert((!V.getValueType().isVector() ||
2833428419 V.getValueType().isScalableVector()) &&
2833528420 "Only scalable vectors are supported!");
@@ -28339,7 +28424,10 @@ SDValue AArch64TargetLowering::LowerToPredicatedOp(SDValue Op,
2833928424 if (isMergePassthruOpcode(NewOp))
2834028425 Operands.push_back(DAG.getUNDEF(VT));
2834128426
28342- return DAG.getNode(NewOp, DL, VT, Operands, Op->getFlags());
28427+ auto NewNode = DAG.getNode(NewOp, DL, VT, Operands, Op->getFlags());
28428+ if (Chain)
28429+ return DAG.getMergeValues({NewNode, Chain}, DL);
28430+ return NewNode;
2834328431}
2834428432
2834528433// If a fixed length vector operation has no side effects when applied to
0 commit comments