@@ -1454,8 +1454,12 @@ AArch64TargetLowering::AArch64TargetLowering(const TargetMachine &TM,
1454
1454
setOperationAction(ISD::INSERT_SUBVECTOR, VT, Custom);
1455
1455
setOperationAction(ISD::UINT_TO_FP, VT, Custom);
1456
1456
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);
1457
1459
setOperationAction(ISD::FP_TO_UINT, VT, Custom);
1458
1460
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);
1459
1463
setOperationAction(ISD::MLOAD, VT, Custom);
1460
1464
setOperationAction(ISD::MUL, VT, Custom);
1461
1465
setOperationAction(ISD::MULHS, VT, Custom);
@@ -2138,6 +2142,8 @@ void AArch64TargetLowering::addTypeForFixedLengthSVE(MVT VT) {
2138
2142
setOperationAction(ISD::FP_ROUND, VT, Default);
2139
2143
setOperationAction(ISD::FP_TO_SINT, VT, Default);
2140
2144
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);
2141
2147
setOperationAction(ISD::FRINT, VT, Default);
2142
2148
setOperationAction(ISD::LRINT, VT, Default);
2143
2149
setOperationAction(ISD::LLRINT, VT, Default);
@@ -2164,6 +2170,7 @@ void AArch64TargetLowering::addTypeForFixedLengthSVE(MVT VT) {
2164
2170
setOperationAction(ISD::SIGN_EXTEND, VT, Default);
2165
2171
setOperationAction(ISD::SIGN_EXTEND_INREG, VT, Default);
2166
2172
setOperationAction(ISD::SINT_TO_FP, VT, Default);
2173
+ setOperationAction(ISD::STRICT_SINT_TO_FP, VT, Default);
2167
2174
setOperationAction(ISD::SMAX, VT, Default);
2168
2175
setOperationAction(ISD::SMIN, VT, Default);
2169
2176
setOperationAction(ISD::SPLAT_VECTOR, VT, Default);
@@ -2174,6 +2181,7 @@ void AArch64TargetLowering::addTypeForFixedLengthSVE(MVT VT) {
2174
2181
setOperationAction(ISD::TRUNCATE, VT, Default);
2175
2182
setOperationAction(ISD::UDIV, VT, Default);
2176
2183
setOperationAction(ISD::UINT_TO_FP, VT, Default);
2184
+ setOperationAction(ISD::STRICT_UINT_TO_FP, VT, Default);
2177
2185
setOperationAction(ISD::UMAX, VT, Default);
2178
2186
setOperationAction(ISD::UMIN, VT, Default);
2179
2187
setOperationAction(ISD::VECREDUCE_ADD, VT, Default);
@@ -4550,9 +4558,10 @@ SDValue AArch64TargetLowering::LowerVectorFP_TO_INT(SDValue Op,
4550
4558
EVT VT = Op.getValueType();
4551
4559
4552
4560
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;
4556
4565
return LowerToPredicatedOp(Op, DAG, Opcode);
4557
4566
}
4558
4567
@@ -4628,6 +4637,51 @@ SDValue AArch64TargetLowering::LowerVectorFP_TO_INT(SDValue Op,
4628
4637
return Op;
4629
4638
}
4630
4639
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
+
4631
4685
SDValue AArch64TargetLowering::LowerFP_TO_INT(SDValue Op,
4632
4686
SelectionDAG &DAG) const {
4633
4687
bool IsStrict = Op->isStrictFPOpcode();
@@ -4636,6 +4690,12 @@ SDValue AArch64TargetLowering::LowerFP_TO_INT(SDValue Op,
4636
4690
if (SrcVal.getValueType().isVector())
4637
4691
return LowerVectorFP_TO_INT(Op, DAG);
4638
4692
4693
+ if (!Subtarget->isNeonAvailable() &&
4694
+ Subtarget->isSVEorStreamingSVEAvailable() &&
4695
+ CanLowerToScalarSVEFPIntConversion(SrcVal.getValueType()) &&
4696
+ CanLowerToScalarSVEFPIntConversion(Op.getValueType()))
4697
+ return LowerScalarFPConversionToSVE(Op, DAG);
4698
+
4639
4699
// f16 conversions are promoted to f32 when full fp16 is not supported.
4640
4700
if ((SrcVal.getValueType() == MVT::f16 && !Subtarget->hasFullFP16()) ||
4641
4701
SrcVal.getValueType() == MVT::bf16) {
@@ -4939,6 +4999,12 @@ SDValue AArch64TargetLowering::LowerINT_TO_FP(SDValue Op,
4939
4999
bool IsStrict = Op->isStrictFPOpcode();
4940
5000
SDValue SrcVal = Op.getOperand(IsStrict ? 1 : 0);
4941
5001
5002
+ if (!Subtarget->isNeonAvailable() &&
5003
+ Subtarget->isSVEorStreamingSVEAvailable() &&
5004
+ CanLowerToScalarSVEFPIntConversion(SrcVal.getValueType()) &&
5005
+ CanLowerToScalarSVEFPIntConversion(Op.getValueType()))
5006
+ return LowerScalarFPConversionToSVE(Op, DAG);
5007
+
4942
5008
bool IsSigned = Op->getOpcode() == ISD::STRICT_SINT_TO_FP ||
4943
5009
Op->getOpcode() == ISD::SINT_TO_FP;
4944
5010
@@ -28293,7 +28359,21 @@ SDValue AArch64TargetLowering::LowerToPredicatedOp(SDValue Op,
28293
28359
unsigned NewOp) const {
28294
28360
EVT VT = Op.getValueType();
28295
28361
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
+ }
28297
28377
28298
28378
if (VT.isFixedLengthVector()) {
28299
28379
assert(isTypeLegal(VT) && "Expected only legal fixed-width types");
@@ -28329,7 +28409,12 @@ SDValue AArch64TargetLowering::LowerToPredicatedOp(SDValue Op,
28329
28409
assert(VT.isScalableVector() && "Only expect to lower scalable vector op!");
28330
28410
28331
28411
SmallVector<SDValue, 4> Operands = {Pg};
28412
+ SDValue Chain{};
28332
28413
for (const SDValue &V : Op->op_values()) {
28414
+ if (!isa<CondCodeSDNode>(V) && V.getValueType() == MVT::Other) {
28415
+ Chain = V;
28416
+ continue;
28417
+ }
28333
28418
assert((!V.getValueType().isVector() ||
28334
28419
V.getValueType().isScalableVector()) &&
28335
28420
"Only scalable vectors are supported!");
@@ -28339,7 +28424,10 @@ SDValue AArch64TargetLowering::LowerToPredicatedOp(SDValue Op,
28339
28424
if (isMergePassthruOpcode(NewOp))
28340
28425
Operands.push_back(DAG.getUNDEF(VT));
28341
28426
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;
28343
28431
}
28344
28432
28345
28433
// If a fixed length vector operation has no side effects when applied to
0 commit comments