[llvm] [AMDGPU] Add custom lowering of llvm.convert.from.arbitrary.fp for FP8 (PR #194144)
Dmitry Sidorov via llvm-commits
llvm-commits at lists.llvm.org
Thu Apr 30 16:04:36 PDT 2026
================
@@ -10569,6 +10584,123 @@ SDValue SITargetLowering::lowerWorkitemID(SelectionDAG &DAG, SDValue Op,
DAG.getValueType(SmallVT));
}
+// Pack vector inputs as hw instruction is packed.
+// FIXME: note, packing loses lane-wise poison. Should we do something about
+// it?
+SDValue SITargetLowering::packBytesToI32(SelectionDAG &DAG, const SDLoc &SL,
+ SDValue Src, unsigned NumBytes,
+ unsigned FirstLane) {
+ EVT SrcEltVT = Src.getValueType().getVectorElementType();
+ SDValue PackedI32;
+ for (unsigned I = 0; I != NumBytes; ++I) {
+ SDValue Elt = DAG.getExtractVectorElt(SL, SrcEltVT, Src, FirstLane + I);
+ SDValue Byte = DAG.getZExtOrTrunc(Elt, SL, MVT::i32);
+ Byte = DAG.getNode(ISD::AND, SL, MVT::i32, Byte,
+ DAG.getConstant(0xFF, SL, MVT::i32));
+ if (I != 0)
+ Byte = DAG.getNode(ISD::SHL, SL, MVT::i32, Byte,
+ DAG.getConstant(I * 8, SL, MVT::i32));
+ PackedI32 =
+ I == 0 ? Byte : DAG.getNode(ISD::OR, SL, MVT::i32, PackedI32, Byte);
+ }
+ return PackedI32;
+}
+
+SDValue SITargetLowering::lowerFromFP8ToF32(SDValue Op, bool IsBF8,
+ SelectionDAG &DAG) const {
+ EVT DstVT = Op.getValueType();
+ SDLoc SL(Op);
+ SDValue Src = Op.getOperand(0);
+
+ if (DstVT == MVT::f32) {
+ unsigned IntrID =
+ IsBF8 ? Intrinsic::amdgcn_cvt_f32_bf8 : Intrinsic::amdgcn_cvt_f32_fp8;
+ SDValue SrcI32 = DAG.getAnyExtOrTrunc(Src, SL, MVT::i32);
+ return DAG.getNode(ISD::INTRINSIC_WO_CHAIN, SL, MVT::f32,
+ DAG.getTargetConstant(IntrID, SL, MVT::i32), SrcI32,
+ DAG.getTargetConstant(0, SL, MVT::i32));
+ }
+
+ auto EmitPk = [&](SDValue PackedI32, unsigned WordSel) {
+ unsigned IntrID = IsBF8 ? Intrinsic::amdgcn_cvt_pk_f32_bf8
+ : Intrinsic::amdgcn_cvt_pk_f32_fp8;
+ return DAG.getNode(ISD::INTRINSIC_WO_CHAIN, SL, MVT::v2f32,
+ DAG.getTargetConstant(IntrID, SL, MVT::i32), PackedI32,
+ DAG.getTargetConstant(WordSel, SL, MVT::i1));
+ };
+
+ if (DstVT == MVT::v2f32)
+ return EmitPk(packBytesToI32(DAG, SL, Src, 2, 0), 0);
+
+ SDValue PackedI32 = packBytesToI32(DAG, SL, Src, 4, 0);
+ SDValue Lo = EmitPk(PackedI32, 0);
+ SDValue Hi = EmitPk(PackedI32, 1);
+ return DAG.getNode(ISD::CONCAT_VECTORS, SL, MVT::v4f32, Lo, Hi);
+}
+
+SDValue SITargetLowering::lowerFromFP8ToF16(SDValue Op, bool IsBF8,
+ SelectionDAG &DAG) const {
+ assert(Subtarget->hasGFX1250Insts() &&
+ "unscaled fp8/bf8 -> f16 requires gfx1250+");
+ EVT DstVT = Op.getValueType();
+ SDLoc SL(Op);
+ SDValue Src = Op.getOperand(0);
+
+ // amdgcn_cvt_f16_{fp8,bf8}(i32 src, byte_sel) -> f16.
+ // amdgcn_cvt_pk_f16_{fp8,bf8}(i16 src) -> v2f16.
+ if (!DstVT.isVector()) {
+ unsigned IntrID =
+ IsBF8 ? Intrinsic::amdgcn_cvt_f16_bf8 : Intrinsic::amdgcn_cvt_f16_fp8;
+ SDValue SrcI32 = DAG.getAnyExtOrTrunc(Src, SL, MVT::i32);
+ return DAG.getNode(ISD::INTRINSIC_WO_CHAIN, SL, MVT::f16,
----------------
MrSidims wrote:
Moved to .td for scalars
https://github.com/llvm/llvm-project/pull/194144
More information about the llvm-commits
mailing list