[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
Tue May 5 10:33:52 PDT 2026


================
@@ -10569,6 +10584,126 @@ SDValue SITargetLowering::lowerWorkitemID(SelectionDAG &DAG, SDValue Op,
                      DAG.getValueType(SmallVT));
 }
 
+// Pack a vector of i8 lanes into i32 via bitcast.
+// FIXME: 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 SrcVT = Src.getValueType();
+  assert(SrcVT.isVector() && SrcVT.getVectorElementType() == MVT::i8 &&
+         "packBytesToI32 expects a v*i8 source");
+  unsigned SrcBytes = SrcVT.getVectorNumElements();
+  assert((NumBytes == 2 || NumBytes == 4) && "expected 2 or 4 bytes");
+
+  if (NumBytes == 4) {
+    assert(FirstLane == 0 && "v4i8 -> i32 takes the full vector");
+    return DAG.getNode(ISD::BITCAST, SL, MVT::i32, Src);
+  }
+
+  // Bitcast a vector to the same-width integer, optionally shift down to the
+  // requested slice, truncate to i16, and zext to i32.
+  EVT IntVT = EVT::getIntegerVT(*DAG.getContext(), SrcBytes * 8);
+  SDValue AsInt = DAG.getNode(ISD::BITCAST, SL, IntVT, Src);
+  if (FirstLane != 0)
+    AsInt = DAG.getNode(ISD::SRL, SL, IntVT, AsInt,
+                        DAG.getConstant(FirstLane * 8, SL, IntVT));
+  SDValue I16 = DAG.getNode(ISD::TRUNCATE, SL, MVT::i16, AsInt);
+  return DAG.getNode(ISD::ZERO_EXTEND, SL, MVT::i32, I16);
+}
+
+SDValue SITargetLowering::lowerFromFP8ToF32(SDValue Op, bool IsBF8,
+                                            SelectionDAG &DAG) const {
+  EVT DstVT = Op.getValueType();
+  SDLoc SL(Op);
+  SDValue Src = Op.getOperand(0);
+
+  assert(DstVT.isVector() && "Scalar f32 should be selected by TableGen");
+
+  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,
----------------
MrSidims wrote:

Custom lowering for v2 is still there as H/W instruction is packed. I'm not sure if lowering via table gen would be more handy than manually written C++ code.

https://github.com/llvm/llvm-project/pull/194144


More information about the llvm-commits mailing list