================
@@ -5205,55 +5205,75 @@ AArch64TargetLowering::LowerVectorFP_TO_INT_SAT(SDValue
Op,
return SDValue();
EVT SrcElementVT = SrcVT.getVectorElementType();
+ if (SrcElementVT != MVT::f64 && SrcElementVT != MVT::f32 &&
+ SrcElementVT != MVT::f16 && SrcElementVT != MVT::bf16)
+ return SDValue();
+
+ // Returns true if the operation can be matched by an isel pattern directly.
+ auto CanHandleNatively = [&DstVT, &SatWidth](EVT SrcVT) -> bool {
+ return SrcVT.getScalarSizeInBits() == DstVT.getScalarSizeInBits() &&
+ SrcVT.getScalarSizeInBits() == SatWidth;
+ };
+
+ // Returns true if the operation is best expanded.
+ auto Expand = [&DstVT, &SatWidth, &CanHandleNatively](EVT SrcVT) -> bool {
+ return !CanHandleNatively(SrcVT) &&
+ (SrcVT.getScalarSizeInBits() < SatWidth ||
+ // NEON has no vector MIN/MAX for i64, so it's simpler to scalarize
+ // (at least until sqxtn is selected).
+ SrcVT.getVectorElementType() == MVT::f64);
+ };
+
+ // Try to promote the operation to a wider type if SrcVT < DstVT,
+ // or if type is bf16 or if the target has no +fullfp16.
+ EVT PromVT = SrcVT;
+ switch (SrcVT.getVectorElementType().getSimpleVT().SimpleTy) {
+ case MVT::f16:
+ case MVT::bf16:
+ if (DstVT.getScalarSizeInBits() == 32 || !Subtarget->hasFullFP16()) {
+ PromVT = MVT::getVectorVT(MVT::f32, SrcVT.getVectorElementCount());
+ break;
+ }
+ [[fallthrough]];
+ case MVT::f32:
+ // Promote to f64
+ if (DstVT.getScalarSizeInBits() == 64) {
+ PromVT = MVT::getVectorVT(MVT::f64, SrcVT.getVectorElementCount());
+ break;
+ }
+ [[fallthrough]];
+ default:
+ break;
+ }
- // In the absence of FP16 support, promote f16 to f32 and saturate the
result.
SDLoc DL(Op);
- if ((SrcElementVT == MVT::f16 &&
- (!Subtarget->hasFullFP16() || DstElementWidth > 16)) ||
- SrcElementVT == MVT::bf16) {
- MVT F32VT = MVT::getVectorVT(MVT::f32, SrcVT.getVectorNumElements());
- SrcVal = DAG.getNode(ISD::FP_EXTEND, DL, F32VT, SrcVal);
- // If we are extending to a v8f32, split into two v4f32 to produce legal
- // types.
- if (F32VT.getSizeInBits() > 128) {
- SDValue SrcVal2;
- std::tie(SrcVal, SrcVal2) = DAG.SplitVector(SrcVal, DL);
- EVT IntVT = SrcVal.getValueType().changeVectorElementTypeToInteger();
- SDValue Lo =
- DAG.getNode(Op.getOpcode(), DL, IntVT, SrcVal, Op.getOperand(1));
- SDValue Hi =
- DAG.getNode(Op.getOpcode(), DL, IntVT, SrcVal2, Op.getOperand(1));
- EVT HalfDstVT = DstVT.getHalfNumVectorElementsVT(*DAG.getContext());
- Lo = DAG.getNode(ISD::TRUNCATE, DL, HalfDstVT, Lo);
- Hi = DAG.getNode(ISD::TRUNCATE, DL, HalfDstVT, Hi);
- return DAG.getNode(ISD::CONCAT_VECTORS, DL, DstVT, Lo, Hi);
- }
- SrcVT = F32VT;
- SrcElementVT = MVT::f32;
- SrcElementWidth = 32;
- } else if (SrcElementVT != MVT::f64 && SrcElementVT != MVT::f32 &&
- SrcElementVT != MVT::f16 && SrcElementVT != MVT::bf16)
- return SDValue();
-
- // Expand to f64 if we are saturating to i64, to help keep the lanes the same
- // width and produce a fcvtzu.
- if (SatWidth == 64 && SrcElementWidth < 64) {
- MVT F64VT = MVT::getVectorVT(MVT::f64, SrcVT.getVectorNumElements());
- SrcVal = DAG.getNode(ISD::FP_EXTEND, DL, F64VT, SrcVal);
- SrcVT = F64VT;
- SrcElementVT = MVT::f64;
- SrcElementWidth = 64;
+ if (PromVT != SrcVT && !Expand(PromVT)) {
----------------
gbossu wrote:
Nit: We are using `SrcVT` as a sentinel value to say "no promotion needed".
Maybe have `std::optional<EVT> PromVT` instead?
I think `if (PromVT && !Expand(*PromVT))` reads a bit nicer.
https://github.com/llvm/llvm-project/pull/207199
_______________________________________________
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits