[llvm] [AMDGPU] Implement llvm.fptosi.sat and llvm.fptoui.sat (PR #174726)
Jay Foad via llvm-commits
llvm-commits at lists.llvm.org
Fri Jan 30 02:19:42 PST 2026
================
@@ -3762,6 +3775,86 @@ SDValue AMDGPUTargetLowering::LowerFP_TO_INT(const SDValue Op,
return SDValue();
}
+SDValue AMDGPUTargetLowering::LowerFP_TO_INT_SAT(const SDValue Op,
+ SelectionDAG &DAG) const {
+ SDValue Src = Op.getOperand(0);
+ unsigned OpOpcode = Op.getOpcode();
+ EVT SrcVT = Src.getValueType();
+ EVT DstVT = Op.getValueType();
+ SDValue SatVTOp = Op.getNode()->getOperand(1);
+ EVT SatVT = cast<VTSDNode>(SatVTOp)->getVT();
+ SDLoc DL(Op);
+
+ uint64_t DstWidth = DstVT.getScalarSizeInBits();
+ uint64_t SatWidth = SatVT.getScalarSizeInBits();
+ assert(SatWidth <= DstWidth && "Saturation width cannot exceed result width");
+
+ // Will be selected natively
+ if (DstVT == MVT::i32 && SatWidth == DstWidth &&
+ (SrcVT == MVT::f32 || SrcVT == MVT::f64))
+ return Op;
+
+ const SDValue Int32VT = DAG.getValueType(MVT::i32);
+
+ // Perform all saturation at i32 and truncate
+ if (SatWidth < DstWidth) {
+ const uint64_t Int32Width = 32;
+ SDValue FpToInt32 = DAG.getNode(OpOpcode, DL, MVT::i32, Src, Int32VT);
+ SDValue Int32SatVal;
+
+ if (Op.getOpcode() == ISD::FP_TO_SINT_SAT) {
+ SDValue MinConst = DAG.getConstant(
+ APInt::getSignedMaxValue(SatWidth).sext(Int32Width), DL, MVT::i32);
+ SDValue MaxConst = DAG.getConstant(
+ APInt::getSignedMinValue(SatWidth).sext(Int32Width), DL, MVT::i32);
+ SDValue MinVal =
+ DAG.getNode(ISD::SMIN, DL, MVT::i32, FpToInt32, MinConst);
+ Int32SatVal = DAG.getNode(ISD::SMAX, DL, MVT::i32, MinVal, MaxConst);
+ } else {
+ SDValue MinConst = DAG.getConstant(
+ APInt::getMaxValue(SatWidth).zext(Int32Width), DL, MVT::i32);
+ Int32SatVal = DAG.getNode(ISD::UMIN, DL, MVT::i32, FpToInt32, MinConst);
+ }
+
+ if (DstWidth == Int32Width)
+ return Int32SatVal;
+ if (DstWidth < Int32Width)
+ return DAG.getNode(ISD::TRUNCATE, DL, DstVT, Int32SatVal);
+
+ // DstWidth > Int32Width
+ const unsigned Ext =
+ OpOpcode == ISD::FP_TO_SINT_SAT ? ISD::SIGN_EXTEND : ISD::ZERO_EXTEND;
+ return DAG.getNode(Ext, DL, DstVT, FpToInt32);
----------------
jayfoad wrote:
All of this can be done with a single `DAG.getExtOrTrunc`.
https://github.com/llvm/llvm-project/pull/174726
More information about the llvm-commits
mailing list