[llvm] [AArch64] NFCI: Simplify LowerVectorFP_TO_INT_SAT (part 1) (PR #207198)
Sander de Smalen via llvm-commits
llvm-commits at lists.llvm.org
Mon Jul 13 05:38:10 PDT 2026
https://github.com/sdesmalen-arm updated https://github.com/llvm/llvm-project/pull/207198
>From 0cf83908914f1a2d46b0d04b503febd112559711 Mon Sep 17 00:00:00 2001
From: Sander de Smalen <sander.desmalen at arm.com>
Date: Mon, 22 Jun 2026 14:06:28 +0000
Subject: [PATCH 1/2] [AArch64] Simplify LowerVectorFP_TO_INT_SAT (part 1)
The lowering code tries to implement splitting by keeping two
source values SrcVal and SrcVal2 for the Lo/Hi part respectively.
This is a bit awkward, because SrcVal2 may not be set. It makes
more sense to generating new DAG nodes that will be lowered separately
by the lowering mechanism, which revisits the newly added (split sourceval)
nodes for lowering.
---
.../Target/AArch64/AArch64ISelLowering.cpp | 42 ++++++++-----------
1 file changed, 17 insertions(+), 25 deletions(-)
diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
index fd71b3a2d10d0..373708c8f52e1 100644
--- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
+++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
@@ -5212,7 +5212,6 @@ AArch64TargetLowering::LowerVectorFP_TO_INT_SAT(SDValue Op,
// In the absence of FP16 support, promote f16 to f32 and saturate the result.
SDLoc DL(Op);
- SDValue SrcVal2;
if ((SrcElementVT == MVT::f16 &&
(!Subtarget->hasFullFP16() || DstElementWidth > 16)) ||
SrcElementVT == MVT::bf16) {
@@ -5221,8 +5220,17 @@ AArch64TargetLowering::LowerVectorFP_TO_INT_SAT(SDValue Op,
// 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);
- F32VT = F32VT.getHalfNumVectorElementsVT();
+ 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;
@@ -5241,16 +5249,9 @@ AArch64TargetLowering::LowerVectorFP_TO_INT_SAT(SDValue Op,
SrcElementWidth = 64;
}
// Cases that we can emit directly.
- if (SrcElementWidth == DstElementWidth && SrcElementWidth == SatWidth) {
- SDValue Res = DAG.getNode(Op.getOpcode(), DL, DstVT, SrcVal,
- DAG.getValueType(DstVT.getScalarType()));
- if (SrcVal2) {
- SDValue Res2 = DAG.getNode(Op.getOpcode(), DL, DstVT, SrcVal2,
- DAG.getValueType(DstVT.getScalarType()));
- return DAG.getNode(ISD::CONCAT_VECTORS, DL, DstVT, Res, Res2);
- }
- return Res;
- }
+ if (SrcElementWidth == DstElementWidth && SrcElementWidth == SatWidth)
+ return DAG.getNode(Op.getOpcode(), DL, DstVT, SrcVal,
+ DAG.getValueType(DstVT.getScalarType()));
// Otherwise we emit a cvt that saturates to a higher BW, and saturate the
// result. This is only valid if the legal cvt is larger than the saturate
@@ -5259,35 +5260,26 @@ AArch64TargetLowering::LowerVectorFP_TO_INT_SAT(SDValue Op,
if (SrcElementWidth < SatWidth || SrcElementVT == MVT::f64)
return SDValue();
+ assert((SrcElementWidth > DstElementWidth) ||
+ (SrcElementWidth == DstElementWidth && SatWidth < DstElementWidth));
+
EVT IntVT = SrcVT.changeVectorElementTypeToInteger();
SDValue NativeCvt = DAG.getNode(Op.getOpcode(), DL, IntVT, SrcVal,
DAG.getValueType(IntVT.getScalarType()));
- SDValue NativeCvt2 =
- SrcVal2 ? DAG.getNode(Op.getOpcode(), DL, IntVT, SrcVal2,
- DAG.getValueType(IntVT.getScalarType()))
- : SDValue();
- SDValue Sat, Sat2;
+ SDValue Sat;
if (Op.getOpcode() == ISD::FP_TO_SINT_SAT) {
SDValue MinC = DAG.getConstant(
APInt::getSignedMaxValue(SatWidth).sext(SrcElementWidth), DL, IntVT);
SDValue Min = DAG.getNode(ISD::SMIN, DL, IntVT, NativeCvt, MinC);
- SDValue Min2 = SrcVal2 ? DAG.getNode(ISD::SMIN, DL, IntVT, NativeCvt2, MinC) : SDValue();
SDValue MaxC = DAG.getConstant(
APInt::getSignedMinValue(SatWidth).sext(SrcElementWidth), DL, IntVT);
Sat = DAG.getNode(ISD::SMAX, DL, IntVT, Min, MaxC);
- Sat2 = SrcVal2 ? DAG.getNode(ISD::SMAX, DL, IntVT, Min2, MaxC) : SDValue();
} else {
SDValue MinC = DAG.getConstant(
APInt::getAllOnes(SatWidth).zext(SrcElementWidth), DL, IntVT);
Sat = DAG.getNode(ISD::UMIN, DL, IntVT, NativeCvt, MinC);
- Sat2 = SrcVal2 ? DAG.getNode(ISD::UMIN, DL, IntVT, NativeCvt2, MinC) : SDValue();
}
- if (SrcVal2)
- Sat = DAG.getNode(ISD::CONCAT_VECTORS, DL,
- IntVT.getDoubleNumVectorElementsVT(*DAG.getContext()),
- Sat, Sat2);
-
return DAG.getNode(ISD::TRUNCATE, DL, DstVT, Sat);
}
>From 421db690dda1102856d8c2b49a12543330c6efca Mon Sep 17 00:00:00 2001
From: Sander de Smalen <sander.desmalen at arm.com>
Date: Thu, 9 Jul 2026 07:54:51 +0000
Subject: [PATCH 2/2] Address comments
---
.../Target/AArch64/AArch64ISelLowering.cpp | 27 +++++++++----------
1 file changed, 12 insertions(+), 15 deletions(-)
diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
index 373708c8f52e1..51cd636742614 100644
--- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
+++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
@@ -5211,7 +5211,9 @@ AArch64TargetLowering::LowerVectorFP_TO_INT_SAT(SDValue Op,
EVT SrcElementVT = SrcVT.getVectorElementType();
// In the absence of FP16 support, promote f16 to f32 and saturate the result.
+ // Note that SatWidth stays unchanged.
SDLoc DL(Op);
+ unsigned Opc = Op.getOpcode();
if ((SrcElementVT == MVT::f16 &&
(!Subtarget->hasFullFP16() || DstElementWidth > 16)) ||
SrcElementVT == MVT::bf16) {
@@ -5219,17 +5221,12 @@ AArch64TargetLowering::LowerVectorFP_TO_INT_SAT(SDValue Op,
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);
+ if (F32VT == MVT::v8f32) {
+ auto [SrcValLo, SrcValHi] = DAG.SplitVector(SrcVal, DL);
+ SDValue Lo = DAG.getNode(Opc, DL, MVT::v4i32, SrcValLo, Op.getOperand(1));
+ SDValue Hi = DAG.getNode(Opc, DL, MVT::v4i32, SrcValHi, Op.getOperand(1));
+ Lo = DAG.getNode(ISD::TRUNCATE, DL, MVT::v4i16, Lo);
+ Hi = DAG.getNode(ISD::TRUNCATE, DL, MVT::v4i16, Hi);
return DAG.getNode(ISD::CONCAT_VECTORS, DL, DstVT, Lo, Hi);
}
SrcVT = F32VT;
@@ -5240,7 +5237,7 @@ AArch64TargetLowering::LowerVectorFP_TO_INT_SAT(SDValue Op,
return SDValue();
// Expand to f64 if we are saturating to i64, to help keep the lanes the same
- // width and produce a fcvtzu.
+ // width and produce a fcvtzu. Note that SatWidth stays unchanged.
if (SatWidth == 64 && SrcElementWidth < 64) {
MVT F64VT = MVT::getVectorVT(MVT::f64, SrcVT.getVectorNumElements());
SrcVal = DAG.getNode(ISD::FP_EXTEND, DL, F64VT, SrcVal);
@@ -5250,7 +5247,7 @@ AArch64TargetLowering::LowerVectorFP_TO_INT_SAT(SDValue Op,
}
// Cases that we can emit directly.
if (SrcElementWidth == DstElementWidth && SrcElementWidth == SatWidth)
- return DAG.getNode(Op.getOpcode(), DL, DstVT, SrcVal,
+ return DAG.getNode(Opc, DL, DstVT, SrcVal,
DAG.getValueType(DstVT.getScalarType()));
// Otherwise we emit a cvt that saturates to a higher BW, and saturate the
@@ -5264,10 +5261,10 @@ AArch64TargetLowering::LowerVectorFP_TO_INT_SAT(SDValue Op,
(SrcElementWidth == DstElementWidth && SatWidth < DstElementWidth));
EVT IntVT = SrcVT.changeVectorElementTypeToInteger();
- SDValue NativeCvt = DAG.getNode(Op.getOpcode(), DL, IntVT, SrcVal,
+ SDValue NativeCvt = DAG.getNode(Opc, DL, IntVT, SrcVal,
DAG.getValueType(IntVT.getScalarType()));
SDValue Sat;
- if (Op.getOpcode() == ISD::FP_TO_SINT_SAT) {
+ if (Opc == ISD::FP_TO_SINT_SAT) {
SDValue MinC = DAG.getConstant(
APInt::getSignedMaxValue(SatWidth).sext(SrcElementWidth), DL, IntVT);
SDValue Min = DAG.getNode(ISD::SMIN, DL, IntVT, NativeCvt, MinC);
More information about the llvm-commits
mailing list