[llvm] 5df5e8d - [AMDGPU] Add custom lowering of llvm.convert.from.arbitrary.fp for FP8 (#194144)
via llvm-commits
llvm-commits at lists.llvm.org
Fri Jul 31 06:16:36 PDT 2026
Author: Dmitry Sidorov
Date: 2026-07-31T15:16:30+02:00
New Revision: 5df5e8d9fd6386d99c37cb72ea92c99819c801bc
URL: https://github.com/llvm/llvm-project/commit/5df5e8d9fd6386d99c37cb72ea92c99819c801bc
DIFF: https://github.com/llvm/llvm-project/commit/5df5e8d9fd6386d99c37cb72ea92c99819c801bc.diff
LOG: [AMDGPU] Add custom lowering of llvm.convert.from.arbitrary.fp for FP8 (#194144)
Map conversions from FP8 source formats to v_cvt_{,pk_}f32_{fp8,bf8} and v_cvt_{pk_}f16_{fp8,bf8} HW instructions.
Added:
llvm/test/CodeGen/AMDGPU/arbitrary-fp-from-float-fp8-f16-hw.ll
llvm/test/CodeGen/AMDGPU/arbitrary-fp-to-float-fp8-hw.ll
Modified:
llvm/include/llvm/Target/TargetSelectionDAG.td
llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
llvm/lib/Target/AMDGPU/AMDGPU.td
llvm/lib/Target/AMDGPU/SIISelLowering.cpp
llvm/lib/Target/AMDGPU/SIISelLowering.h
llvm/lib/Target/AMDGPU/SIInstrInfo.td
llvm/lib/Target/AMDGPU/VOP1Instructions.td
llvm/test/CodeGen/AMDGPU/llvm.amdgcn.cvt.fp8.dpp.mir
llvm/test/TableGen/GlobalISelEmitter/GlobalISelEmitter.td
Removed:
################################################################################
diff --git a/llvm/include/llvm/Target/TargetSelectionDAG.td b/llvm/include/llvm/Target/TargetSelectionDAG.td
index c0b3b3008bcf7..37b7b8716bcd8 100644
--- a/llvm/include/llvm/Target/TargetSelectionDAG.td
+++ b/llvm/include/llvm/Target/TargetSelectionDAG.td
@@ -175,6 +175,9 @@ def SDIsFPClassOp : SDTypeProfile<1, 2, [ // is_fpclass
def SDTIntToFPOp : SDTypeProfile<1, 1, [ // [su]int_to_fp
SDTCisFP<0>, SDTCisInt<1>, SDTCisSameNumEltsAs<0, 1>
]>;
+def SDTConvertFromArbitraryFPOp : SDTypeProfile<1, 2, [
+ SDTCisFP<0>, SDTCisInt<1>, SDTCisInt<2>, SDTCisSameNumEltsAs<0, 1>
+]>;
def SDTFPToIntOp : SDTypeProfile<1, 1, [ // fp_to_[su]int
SDTCisInt<0>, SDTCisFP<1>, SDTCisSameNumEltsAs<0, 1>
]>;
@@ -646,6 +649,8 @@ def is_fpclass : SDNode<"ISD::IS_FPCLASS" , SDIsFPClassOp>;
def sint_to_fp : SDNode<"ISD::SINT_TO_FP" , SDTIntToFPOp>;
def uint_to_fp : SDNode<"ISD::UINT_TO_FP" , SDTIntToFPOp>;
+def convert_from_arbitrary_fp : SDNode<"ISD::CONVERT_FROM_ARBITRARY_FP",
+ SDTConvertFromArbitraryFPOp>;
def fp_to_sint : SDNode<"ISD::FP_TO_SINT" , SDTFPToIntOp>;
def fp_to_uint : SDNode<"ISD::FP_TO_UINT" , SDTFPToIntOp>;
def fp_to_sint_sat : SDNode<"ISD::FP_TO_SINT_SAT" , SDTFPToIntSatOp>;
@@ -1274,6 +1279,11 @@ class ImmLeaf<ValueType vt, code pred, SDNodeXForm xform = NOOP_SDNodeXForm,
class TImmLeaf<ValueType vt, code pred, SDNodeXForm xform = NOOP_SDNodeXForm,
SDNode ImmNode = timm> : ImmLeaf<vt, pred, xform, ImmNode>;
+// llvm.convert.from.arbitrary.fp format-selector predicates.
+// Only OCP formats are matched here; FNUZ formats use the generic expansion.
+def Float8E4M3FN : TImmLeaf<i32, [{ return Imm == APFloatBase::S_Float8E4M3FN; }]>;
+def Float8E5M2 : TImmLeaf<i32, [{ return Imm == APFloatBase::S_Float8E5M2; }]>;
+
// An ImmLeaf where the `Imm` in the C++ predicate is an `APInt`.
//
// This is useful when you need to zero-extend the immediate instead of
diff --git a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
index b82f42493f57d..6f47bf1b81c57 100644
--- a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
@@ -14277,6 +14277,12 @@ SDValue TargetLowering::expandVectorNaryOpBySplitting(SDNode *Node,
SmallVector<SDValue, 4> LoOps, HiOps;
for (const SDValue &V : Node->op_values()) {
+ if (!V.getValueType().isVector()) {
+ // Scalar operands pass through to both halves unchanged.
+ LoOps.push_back(V);
+ HiOps.push_back(V);
+ continue;
+ }
auto [Lo, Hi] = DAG.SplitVector(V, DL, LoVT, HiVT);
LoOps.push_back(Lo);
HiOps.push_back(Hi);
diff --git a/llvm/lib/Target/AMDGPU/AMDGPU.td b/llvm/lib/Target/AMDGPU/AMDGPU.td
index 01c39232ff479..fb2221e671758 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPU.td
+++ b/llvm/lib/Target/AMDGPU/AMDGPU.td
@@ -881,6 +881,16 @@ defm FP8ConversionInsts : AMDGPUSubtargetFeature<"fp8-conversion-insts",
"Has fp8 and bf8 conversion instructions"
>;
+// OCP fp8 semantics (E4M3FN, E5M2). Distinct from the FNUZ formats used by
+// gfx942.
+defm OCPFP8ConversionInsts : AMDGPUSubtargetFeature<"ocp-fp8-conversion-insts",
+ "Has OCP fp8 (E4M3FN, E5M2) conversion instructions"
+>;
+
+defm FP8F16ConversionInsts : AMDGPUSubtargetFeature<"fp8-f16-conversion-insts",
+ "Has fp8 and bf8 conversion to f16 instructions"
+>;
+
defm FP8E5M3Insts : AMDGPUSubtargetFeature<"fp8e5m3-insts",
"Has fp8 e5m3 format support"
>;
@@ -1953,6 +1963,7 @@ def FeatureISAVersion9_5_Common : FeatureSet<
FeatureFP8Insts,
FeatureFP8ConversionInsts,
FeatureCvtFP8SDWASrcSel,
+ FeatureOCPFP8ConversionInsts,
FeatureGFX950Insts,
FeaturePrngInst,
FeatureBF16ConversionInsts,
@@ -2165,6 +2176,7 @@ def FeatureISAVersion11_7_Common : FeatureSet<
FeatureDPPSrc1SGPR,
FeatureFP8ConversionInsts,
FeatureCvtFP8ByteSel,
+ FeatureOCPFP8ConversionInsts,
FeatureDot11Insts,
FeatureWMMA128bInsts,
FeatureSWMMACGfx1200Insts,
@@ -2207,6 +2219,7 @@ def FeatureISAVersion12 : FeatureSet<
FeatureExtendedImageInsts,
FeatureFP8ConversionInsts,
FeatureCvtFP8ByteSel,
+ FeatureOCPFP8ConversionInsts,
FeatureWMMA128bInsts,
FeatureSWMMACGfx1200Insts,
FeatureIEEEMinimumMaximumInsts,
@@ -2270,6 +2283,8 @@ def FeatureISAVersion12_50_Common : FeatureSet<
FeatureFlatAtomicFaddF32Inst,
FeatureFP8ConversionInsts,
FeatureCvtFP8ByteSel,
+ FeatureOCPFP8ConversionInsts,
+ FeatureFP8F16ConversionInsts,
FeatureFP8E5M3Insts,
FeaturePackedTID,
FeatureVcmpxPermlaneHazard,
@@ -2426,6 +2441,8 @@ def FeatureISAVersion13 : FeatureSet<
FeatureFlatAtomicFaddF32Inst,
FeatureFP8ConversionInsts,
FeatureCvtFP8ByteSel,
+ FeatureOCPFP8ConversionInsts,
+ FeatureFP8F16ConversionInsts,
FeaturePackedTID,
FeatureVcmpxPermlaneHazard,
FeatureSALUFloatInsts,
diff --git a/llvm/lib/Target/AMDGPU/SIISelLowering.cpp b/llvm/lib/Target/AMDGPU/SIISelLowering.cpp
index b5e2a36ad9f19..403f5d7476dfc 100644
--- a/llvm/lib/Target/AMDGPU/SIISelLowering.cpp
+++ b/llvm/lib/Target/AMDGPU/SIISelLowering.cpp
@@ -22,6 +22,7 @@
#include "MCTargetDesc/AMDGPUMCTargetDesc.h"
#include "SIMachineFunctionInfo.h"
#include "SIRegisterInfo.h"
+#include "llvm/ADT/APFloat.h"
#include "llvm/ADT/APInt.h"
#include "llvm/ADT/FloatingPointMode.h"
#include "llvm/ADT/Statistic.h"
@@ -1043,6 +1044,17 @@ SITargetLowering::SITargetLowering(const TargetMachine &TM,
setOperationAction({ISD::FEXP2, ISD::FLOG2, ISD::FSQRT}, MVT::bf16, Legal);
}
+ if (Subtarget->hasOCPFP8ConversionInsts()) {
+ setOperationAction(ISD::CONVERT_FROM_ARBITRARY_FP, {MVT::f32, MVT::v2f32},
+ Custom);
+ setOperationAction(ISD::CONVERT_FROM_ARBITRARY_FP, MVT::v2i8, Custom);
+ }
+
+ if (Subtarget->hasFP8F16ConversionInsts()) {
+ setOperationAction(ISD::CONVERT_FROM_ARBITRARY_FP, {MVT::f16, MVT::v2f16},
+ Custom);
+ }
+
if (Subtarget->hasCvtPkF16F32Inst()) {
setOperationAction(ISD::FP_ROUND,
{MVT::v2f16, MVT::v4f16, MVT::v8f16, MVT::v16f16},
@@ -7634,6 +7646,8 @@ SDValue SITargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) const {
return LowerExternalSymbol(Op, DAG);
case ISD::INTRINSIC_WO_CHAIN:
return LowerINTRINSIC_WO_CHAIN(Op, DAG);
+ case ISD::CONVERT_FROM_ARBITRARY_FP:
+ return LowerCONVERT_FROM_ARBITRARY_FP(Op, DAG);
case ISD::INTRINSIC_W_CHAIN:
return LowerINTRINSIC_W_CHAIN(Op, DAG);
case ISD::INTRINSIC_VOID:
@@ -10944,6 +10958,61 @@ SDValue SITargetLowering::lowerWorkitemID(SelectionDAG &DAG, SDValue Op,
DAG.getValueType(SmallVT));
}
+SDValue SITargetLowering::lowerFromFP8(SDValue Op, bool IsBF8,
+ SelectionDAG &DAG) const {
+ SDLoc SL(Op);
+ SDValue Src = Op.getOperand(0);
+ EVT DstVT = Op.getValueType();
+ bool IsF16 = DstVT.getVectorElementType() == MVT::f16;
+ assert((!IsF16 || Subtarget->hasFP8F16ConversionInsts()) &&
+ "fp8/bf8 -> f16 conversion requires FP8F16ConversionInsts");
+
+ unsigned Opc;
+ if (IsF16)
+ Opc = IsBF8 ? AMDGPUISD::CVT_PK_F16_BF8 : AMDGPUISD::CVT_PK_F16_FP8;
+ else
+ Opc = IsBF8 ? AMDGPUISD::CVT_PK_F32_BF8 : AMDGPUISD::CVT_PK_F32_FP8;
+
+ // Pack the two i8 lanes into the integer type the packed HW node reads. The
+ // f16 form takes i16 and the f32 form takes i32. v2i8 bitcasts to i16
+ // directly and the f32 node reads the low half of an any-extended i32.
+ EVT PackedVT =
+ EVT::getIntegerVT(*DAG.getContext(), DstVT.getScalarSizeInBits());
+ SDValue AsI16 = DAG.getNode(ISD::BITCAST, SL, MVT::i16, Src);
+ SDValue Packed = DAG.getAnyExtOrTrunc(AsI16, SL, PackedVT);
+ return DAG.getNode(Opc, SL, DstVT, Packed);
+}
+
+SDValue
+SITargetLowering::LowerCONVERT_FROM_ARBITRARY_FP(SDValue Op,
+ SelectionDAG &DAG) const {
+ // Only handle OCP FP8 formats (E4M3FN, E5M2). FNUZ formats that are supported
+ // by gfx942 fall through to the generic expansion.
+ APFloatBase::Semantics FPSemantic =
+ static_cast<APFloatBase::Semantics>(Op.getConstantOperandVal(1));
+ if (FPSemantic != APFloatBase::S_Float8E4M3FN &&
+ FPSemantic != APFloatBase::S_Float8E5M2)
+ return SDValue();
+ const bool IsBF8 = FPSemantic == APFloatBase::S_Float8E5M2;
+
+ EVT DstVT = Op.getValueType();
+ if (!DstVT.isVector()) {
+ SDValue Src = Op.getOperand(0);
+ if (Src.getValueType() != MVT::i32) {
+ SDLoc SL(Op);
+ SDValue SrcI32 = DAG.getAnyExtOrTrunc(Src, SL, MVT::i32);
+ return DAG.getNode(ISD::CONVERT_FROM_ARBITRARY_FP, SL, DstVT, SrcI32,
+ Op.getOperand(1));
+ }
+ return Op;
+ }
+
+ EVT EltVT = DstVT.getVectorElementType();
+ if (EltVT == MVT::f16 || EltVT == MVT::f32)
+ return lowerFromFP8(Op, IsBF8, DAG);
+ return SDValue();
+}
+
SDValue SITargetLowering::LowerINTRINSIC_WO_CHAIN(SDValue Op,
SelectionDAG &DAG) const {
MachineFunction &MF = DAG.getMachineFunction();
diff --git a/llvm/lib/Target/AMDGPU/SIISelLowering.h b/llvm/lib/Target/AMDGPU/SIISelLowering.h
index be4bb6d825b46..df34db74d7563 100644
--- a/llvm/lib/Target/AMDGPU/SIISelLowering.h
+++ b/llvm/lib/Target/AMDGPU/SIISelLowering.h
@@ -104,6 +104,8 @@ class SITargetLowering final : public AMDGPUTargetLowering {
SDValue LowerINTRINSIC_WO_CHAIN(SDValue Op, SelectionDAG &DAG) const;
SDValue LowerINTRINSIC_W_CHAIN(SDValue Op, SelectionDAG &DAG) const;
SDValue LowerINTRINSIC_VOID(SDValue Op, SelectionDAG &DAG) const;
+ SDValue LowerCONVERT_FROM_ARBITRARY_FP(SDValue Op, SelectionDAG &DAG) const;
+ SDValue lowerFromFP8(SDValue Op, bool IsBF8, SelectionDAG &DAG) const;
// The raw.tbuffer and struct.tbuffer intrinsics have two offset args: offset
// (the offset that is included in bounds checking and swizzling, to be split
diff --git a/llvm/lib/Target/AMDGPU/SIInstrInfo.td b/llvm/lib/Target/AMDGPU/SIInstrInfo.td
index 31f6043a146ef..77a7713371438 100644
--- a/llvm/lib/Target/AMDGPU/SIInstrInfo.td
+++ b/llvm/lib/Target/AMDGPU/SIInstrInfo.td
@@ -326,6 +326,25 @@ class UnscaledMFMAOptimizationPat<SDPatternOperator intrin> : PatFrag<
def mfma_f32_16x16x128_f8f6f4 : UnscaledMFMAOptimizationPat<int_amdgcn_mfma_scale_f32_16x16x128_f8f6f4>;
def mfma_f32_32x32x64_f8f6f4 : UnscaledMFMAOptimizationPat<int_amdgcn_mfma_scale_f32_32x32x64_f8f6f4>;
+def cvt_from_fp8 : PatFrag<(ops node:$src),
+ (convert_from_arbitrary_fp node:$src, Float8E4M3FN)>;
+def cvt_from_bf8 : PatFrag<(ops node:$src),
+ (convert_from_arbitrary_fp node:$src, Float8E5M2)>;
+
+def AMDGPUcvt_pk_f32_fp8 : SDNode<"AMDGPUISD::CVT_PK_F32_FP8",
+ SDTypeProfile<1, 1, [SDTCisVT<0, v2f32>, SDTCisVT<1, i32>]>>;
+def AMDGPUcvt_pk_f32_bf8 : SDNode<"AMDGPUISD::CVT_PK_F32_BF8",
+ SDTypeProfile<1, 1, [SDTCisVT<0, v2f32>, SDTCisVT<1, i32>]>>;
+def AMDGPUcvt_pk_f16_fp8 : SDNode<"AMDGPUISD::CVT_PK_F16_FP8",
+ SDTypeProfile<1, 1, [SDTCisVT<0, v2f16>, SDTCisVT<1, i16>]>>;
+def AMDGPUcvt_pk_f16_bf8 : SDNode<"AMDGPUISD::CVT_PK_F16_BF8",
+ SDTypeProfile<1, 1, [SDTCisVT<0, v2f16>, SDTCisVT<1, i16>]>>;
+
+def cvt_pk_f16_fp8 : PatFrags<(ops node:$src),
+ [(int_amdgcn_cvt_pk_f16_fp8 node:$src), (AMDGPUcvt_pk_f16_fp8 node:$src)]>;
+def cvt_pk_f16_bf8 : PatFrags<(ops node:$src),
+ [(int_amdgcn_cvt_pk_f16_bf8 node:$src), (AMDGPUcvt_pk_f16_bf8 node:$src)]>;
+
//===----------------------------------------------------------------------===//
// ValueType helpers
//===----------------------------------------------------------------------===//
diff --git a/llvm/lib/Target/AMDGPU/VOP1Instructions.td b/llvm/lib/Target/AMDGPU/VOP1Instructions.td
index feb803fb4a69f..8cb3dc0723612 100644
--- a/llvm/lib/Target/AMDGPU/VOP1Instructions.td
+++ b/llvm/lib/Target/AMDGPU/VOP1Instructions.td
@@ -717,6 +717,12 @@ foreach Index = [1, 2, 3] in {
}
} // End SubtargetPredicate = HasCvtFP8SDWASrcSel
+let SubtargetPredicate = HasCvtFP8SDWASrcSel,
+ OtherPredicates = [HasOCPFP8ConversionInsts] in {
+ def : GCNPat<(f32 (cvt_from_fp8 i32:$src)), (V_CVT_F32_FP8_e32 $src)>;
+ def : GCNPat<(f32 (cvt_from_bf8 i32:$src)), (V_CVT_F32_BF8_e32 $src)>;
+}
+
class Cvt_PK_F32_F8_Pat<SDPatternOperator node, int index,
VOP1_Pseudo inst_e32, VOP1_SDWA_Pseudo inst_sdwa> : GCNPat<
(v2f32 (node i32:$src, index)),
@@ -734,6 +740,16 @@ let SubtargetPredicate = HasCvtFP8SDWASrcSel in {
}
}
+class Cvt_PK_F32_F8_Conv_Pat<SDPatternOperator node, Instruction inst> : GCNPat<
+ (v2f32 (node i32:$src)),
+ (inst $src)
+>;
+
+let SubtargetPredicate = HasCvtFP8SDWASrcSel in {
+ def : Cvt_PK_F32_F8_Conv_Pat<AMDGPUcvt_pk_f32_fp8, V_CVT_PK_F32_FP8_e32>;
+ def : Cvt_PK_F32_F8_Conv_Pat<AMDGPUcvt_pk_f32_bf8, V_CVT_PK_F32_BF8_e32>;
+}
+
let HasClamp = 0, HasOMod = 0, HasExtDPP = 0, HasExtVOP3DPP = 0,
HasOpSel = 1 in {
// Input modifiers are not supported
@@ -765,13 +781,14 @@ def V_CVT_F16_F8_Fake16_Profile : VOP3_Profile_Fake16<V_CVT_F16_F8_Profile>;
}
let SubtargetPredicate = HasCvtFP8ByteSel,
+ OtherPredicates = [HasOCPFP8ConversionInsts],
mayRaiseFPException = 0, SchedRW = [WriteFloatCvt] in {
let SubtargetPredicate = HasCvtFP8ByteSelNotE5M3 in
- defm V_CVT_F32_FP8_OP_SEL : VOP1Inst<"v_cvt_f32_fp8_op_sel", VOPProfile_Base_CVT_F_F8_ByteSel<f32>>;
+ defm V_CVT_F32_FP8_op_sel : VOP1Inst<"v_cvt_f32_fp8_op_sel", VOPProfile_Base_CVT_F_F8_ByteSel<f32>, cvt_from_fp8>;
let SubtargetPredicate = HasCvtFP8ByteSelE5M3 in
- defm V_CVT_F32_FP8_gfx1250 : VOP1Inst<"v_cvt_f32_fp8_gfx1250", VOPProfile_Base_CVT_F_F8_ByteSel<f32, 1>>;
+ defm V_CVT_F32_FP8_gfx1250 : VOP1Inst<"v_cvt_f32_fp8_gfx1250", VOPProfile_Base_CVT_F_F8_ByteSel<f32, 1>, cvt_from_fp8>;
- defm V_CVT_F32_BF8_OP_SEL : VOP1Inst<"v_cvt_f32_bf8_op_sel", VOPProfile_Base_CVT_F_F8_ByteSel<f32>>;
+ defm V_CVT_F32_BF8_op_sel : VOP1Inst<"v_cvt_f32_bf8_op_sel", VOPProfile_Base_CVT_F_F8_ByteSel<f32>, cvt_from_bf8>;
let True16Predicate = UseFakeTrue16Insts in {
defm V_CVT_PK_F32_FP8_fake16 : VOP1Inst<"v_cvt_pk_f32_fp8_fake16", VOPProfile_Base_CVT_PK_F32_F8_fake16>;
@@ -790,7 +807,7 @@ class Cvt_F_F8_Pat_ByteSel<SDPatternOperator node, VOP3_Pseudo inst, bit HasOpSe
>;
let SubtargetPredicate = HasCvtFP8ByteSelNotE5M3 in
- def : Cvt_F_F8_Pat_ByteSel<int_amdgcn_cvt_f32_fp8, V_CVT_F32_FP8_OP_SEL_e64>;
+ def : Cvt_F_F8_Pat_ByteSel<int_amdgcn_cvt_f32_fp8, V_CVT_F32_FP8_op_sel_e64>;
let SubtargetPredicate = HasCvtFP8ByteSelE5M3 in {
def : GCNPat<(int_amdgcn_cvt_f32_fp8 i32:$src0, timm:$byte_sel),
@@ -800,7 +817,7 @@ let SubtargetPredicate = HasCvtFP8ByteSelE5M3 in {
}
let SubtargetPredicate = HasCvtFP8ByteSel in
- def : Cvt_F_F8_Pat_ByteSel<int_amdgcn_cvt_f32_bf8, V_CVT_F32_BF8_OP_SEL_e64>;
+ def : Cvt_F_F8_Pat_ByteSel<int_amdgcn_cvt_f32_bf8, V_CVT_F32_BF8_op_sel_e64>;
class Cvt_PK_F32_F8_Pat_OpSel<SDPatternOperator node, int index,
VOP1_Pseudo inst_e32, VOP3_Pseudo inst_e64> : GCNPat<
@@ -819,6 +836,11 @@ let SubtargetPredicate = HasCvtFP8ByteSel in {
}
}
+let SubtargetPredicate = HasCvtFP8ByteSel in {
+ def : Cvt_PK_F32_F8_Conv_Pat<AMDGPUcvt_pk_f32_fp8, V_CVT_PK_F32_FP8_fake16_e32>;
+ def : Cvt_PK_F32_F8_Conv_Pat<AMDGPUcvt_pk_f32_bf8, V_CVT_PK_F32_BF8_fake16_e32>;
+}
+
// FIXME-TRUE16: True16 versions of these instructions are untested.
let HasExtSDWA = 0, HasOpSel = 1, EmitDstSel = 0, HasOMod = 0, HasModifiers = 1 in {
def VOPProfile_CVT_PK_F16_F8 : VOPProfile<[v2f16, i16, untyped, untyped]>;
@@ -826,18 +848,20 @@ def VOPProfile_CVT_PK_F16_F8_true16 : VOP3_Profile_True16<VOPProfile_CVT_PK_F16_
def VOPProfile_CVT_PK_F16_F8_fake16 : VOP3_Profile_Fake16<VOPProfile_CVT_PK_F16_F8>;
}
-let SubtargetPredicate = isGFX1250Plus in {
+let SubtargetPredicate = HasFP8F16ConversionInsts in {
let mayRaiseFPException = 0, SchedRW = [WriteFloatCvt] in {
defm V_CVT_F16_FP8 : VOP1Inst_t16_with_profiles<"v_cvt_f16_fp8",
- V_CVT_F16_F8_Profile, V_CVT_F16_F8_True16_Profile, V_CVT_F16_F8_Fake16_Profile>;
+ V_CVT_F16_F8_Profile, V_CVT_F16_F8_True16_Profile, V_CVT_F16_F8_Fake16_Profile,
+ cvt_from_fp8>;
defm V_CVT_F16_BF8 : VOP1Inst_t16_with_profiles<"v_cvt_f16_bf8",
- V_CVT_F16_F8_Profile, V_CVT_F16_F8_True16_Profile, V_CVT_F16_F8_Fake16_Profile>;
+ V_CVT_F16_F8_Profile, V_CVT_F16_F8_True16_Profile, V_CVT_F16_F8_Fake16_Profile,
+ cvt_from_bf8>;
defm V_CVT_PK_F16_FP8 : VOP1Inst_t16_with_profiles<"v_cvt_pk_f16_fp8",
VOPProfile_CVT_PK_F16_F8, VOPProfile_CVT_PK_F16_F8_true16, VOPProfile_CVT_PK_F16_F8_fake16,
- int_amdgcn_cvt_pk_f16_fp8>;
+ cvt_pk_f16_fp8>;
defm V_CVT_PK_F16_BF8 : VOP1Inst_t16_with_profiles<"v_cvt_pk_f16_bf8",
VOPProfile_CVT_PK_F16_F8, VOPProfile_CVT_PK_F16_F8_true16, VOPProfile_CVT_PK_F16_F8_fake16,
- int_amdgcn_cvt_pk_f16_bf8>;
+ cvt_pk_f16_bf8>;
}
let True16Predicate = UseRealTrue16Insts in {
@@ -849,6 +873,9 @@ let SubtargetPredicate = isGFX1250Plus in {
def : Cvt_F_F8_Pat_ByteSel<int_amdgcn_cvt_f16_bf8, V_CVT_F16_BF8_fake16_e64, 1>;
}
+} // End SubtargetPredicate = HasFP8F16ConversionInsts
+
+let SubtargetPredicate = isGFX1250Plus in {
defm V_SAT_PK4_I4_I8 : VOP1Inst_t16<"v_sat_pk4_i4_i8", VOP1_I16_I32, int_amdgcn_sat_pk4_i4_i8>;
defm V_SAT_PK4_U4_U8 : VOP1Inst_t16<"v_sat_pk4_u4_u8", VOP1_I16_I32, int_amdgcn_sat_pk4_u4_u8>;
} // End SubtargetPredicate = isGFX1250Plus
@@ -1220,10 +1247,10 @@ multiclass VOP1_Real_OpSelIsDPP_gfx1250_gfx13<bits<9> op> :
VOP1_Real_OpSelIsDPP<GFX1250Gen, op>,
VOP1_Real_OpSelIsDPP<GFX13Gen, op>;
-defm V_CVT_F32_FP8 : VOP1_Real_FULL_with_name_gfx11_gfx12_gfx13_not_gfx1250<0x06c, "V_CVT_F32_FP8_OP_SEL", "v_cvt_f32_fp8">;
+defm V_CVT_F32_FP8 : VOP1_Real_FULL_with_name_gfx11_gfx12_gfx13_not_gfx1250<0x06c, "V_CVT_F32_FP8_op_sel", "v_cvt_f32_fp8">;
defm V_CVT_F32_FP8 : VOP1_Real_FULL_with_name<GFX1250Gen, 0x06c, "V_CVT_F32_FP8_gfx1250", "v_cvt_f32_fp8">;
-defm V_CVT_F32_BF8 : VOP1_Real_FULL_with_name_gfx11_gfx12_gfx13<0x06d, "V_CVT_F32_BF8_OP_SEL", "v_cvt_f32_bf8">;
+defm V_CVT_F32_BF8 : VOP1_Real_FULL_with_name_gfx11_gfx12_gfx13<0x06d, "V_CVT_F32_BF8_op_sel", "v_cvt_f32_bf8">;
defm V_CVT_PK_F32_FP8_fake16 : VOP1_Real_e32_with_name_gfx11_gfx12_gfx13<0x06e, "V_CVT_PK_F32_FP8_fake16", "v_cvt_pk_f32_fp8">;
defm V_CVT_PK_F32_FP8_t16 : VOP1_Real_e32_with_name_gfx11_gfx12_gfx13<0x06e, "V_CVT_PK_F32_FP8_t16", "v_cvt_pk_f32_fp8">;
diff --git a/llvm/test/CodeGen/AMDGPU/arbitrary-fp-from-float-fp8-f16-hw.ll b/llvm/test/CodeGen/AMDGPU/arbitrary-fp-from-float-fp8-f16-hw.ll
new file mode 100644
index 0000000000000..a22454f818a4c
--- /dev/null
+++ b/llvm/test/CodeGen/AMDGPU/arbitrary-fp-from-float-fp8-f16-hw.ll
@@ -0,0 +1,224 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
+; RUN: llc < %s -mtriple=amdgcn-amd-amdhsa -mcpu=gfx1250 -mattr=+real-true16 | FileCheck -check-prefixes=GFX1250,GFX1250-TRUE16 %s
+; RUN: llc < %s -mtriple=amdgcn-amd-amdhsa -mcpu=gfx1250 -mattr=-real-true16 | FileCheck -check-prefixes=GFX1250,GFX1250-FAKE16 %s
+
+; llvm.convert.from.arbitrary.fp from FP8/BF8 producing f16 result types,
+; lowered via the gfx1250+ unscaled v_cvt_{pk_}f16_{fp8,bf8} instructions.
+
+; Scalar Float8E4M3FN
+define half @from_fp8_f16_s(i8 %x) {
+; GFX1250-TRUE16-LABEL: from_fp8_f16_s:
+; GFX1250-TRUE16: ; %bb.0:
+; GFX1250-TRUE16-NEXT: s_wait_loadcnt_dscnt 0x0
+; GFX1250-TRUE16-NEXT: s_wait_kmcnt 0x0
+; GFX1250-TRUE16-NEXT: v_cvt_f16_fp8_e32 v0.l, v0
+; GFX1250-TRUE16-NEXT: s_set_pc_i64 s[30:31]
+;
+; GFX1250-FAKE16-LABEL: from_fp8_f16_s:
+; GFX1250-FAKE16: ; %bb.0:
+; GFX1250-FAKE16-NEXT: s_wait_loadcnt_dscnt 0x0
+; GFX1250-FAKE16-NEXT: s_wait_kmcnt 0x0
+; GFX1250-FAKE16-NEXT: v_cvt_f16_fp8_e32 v0, v0
+; GFX1250-FAKE16-NEXT: s_set_pc_i64 s[30:31]
+ %r = call half @llvm.convert.from.arbitrary.fp.f16.i8(i8 %x, metadata !"Float8E4M3FN")
+ ret half %r
+}
+
+; Scalar Float8E5M2
+define half @from_bf8_f16_s(i8 %x) {
+; GFX1250-TRUE16-LABEL: from_bf8_f16_s:
+; GFX1250-TRUE16: ; %bb.0:
+; GFX1250-TRUE16-NEXT: s_wait_loadcnt_dscnt 0x0
+; GFX1250-TRUE16-NEXT: s_wait_kmcnt 0x0
+; GFX1250-TRUE16-NEXT: v_cvt_f16_bf8_e32 v0.l, v0
+; GFX1250-TRUE16-NEXT: s_set_pc_i64 s[30:31]
+;
+; GFX1250-FAKE16-LABEL: from_bf8_f16_s:
+; GFX1250-FAKE16: ; %bb.0:
+; GFX1250-FAKE16-NEXT: s_wait_loadcnt_dscnt 0x0
+; GFX1250-FAKE16-NEXT: s_wait_kmcnt 0x0
+; GFX1250-FAKE16-NEXT: v_cvt_f16_bf8_e32 v0, v0
+; GFX1250-FAKE16-NEXT: s_set_pc_i64 s[30:31]
+ %r = call half @llvm.convert.from.arbitrary.fp.f16.i8(i8 %x, metadata !"Float8E5M2")
+ ret half %r
+}
+
+; Vector Float8E4M3FN
+define <2 x half> @from_fp8_v2f16(<2 x i8> %x) {
+; GFX1250-TRUE16-LABEL: from_fp8_v2f16:
+; GFX1250-TRUE16: ; %bb.0:
+; GFX1250-TRUE16-NEXT: s_wait_loadcnt_dscnt 0x0
+; GFX1250-TRUE16-NEXT: s_wait_kmcnt 0x0
+; GFX1250-TRUE16-NEXT: v_lshlrev_b16 v1.l, 8, v1.l
+; GFX1250-TRUE16-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(NEXT) | instid1(VALU_DEP_1)
+; GFX1250-TRUE16-NEXT: v_bitop3_b16 v0.l, v0.l, v1.l, 0xff bitop3:0xec
+; GFX1250-TRUE16-NEXT: v_cvt_pk_f16_fp8 v0, v0.l
+; GFX1250-TRUE16-NEXT: s_set_pc_i64 s[30:31]
+;
+; GFX1250-FAKE16-LABEL: from_fp8_v2f16:
+; GFX1250-FAKE16: ; %bb.0:
+; GFX1250-FAKE16-NEXT: s_wait_loadcnt_dscnt 0x0
+; GFX1250-FAKE16-NEXT: s_wait_kmcnt 0x0
+; GFX1250-FAKE16-NEXT: v_lshlrev_b16 v1, 8, v1
+; GFX1250-FAKE16-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(NEXT) | instid1(VALU_DEP_1)
+; GFX1250-FAKE16-NEXT: v_bitop3_b16 v0, v0, v1, 0xff bitop3:0xec
+; GFX1250-FAKE16-NEXT: v_cvt_pk_f16_fp8 v0, v0
+; GFX1250-FAKE16-NEXT: s_set_pc_i64 s[30:31]
+ %r = call <2 x half> @llvm.convert.from.arbitrary.fp.v2f16.v2i8(<2 x i8> %x, metadata !"Float8E4M3FN")
+ ret <2 x half> %r
+}
+
+; Vector Float8E5M2
+define <2 x half> @from_bf8_v2f16(<2 x i8> %x) {
+; GFX1250-TRUE16-LABEL: from_bf8_v2f16:
+; GFX1250-TRUE16: ; %bb.0:
+; GFX1250-TRUE16-NEXT: s_wait_loadcnt_dscnt 0x0
+; GFX1250-TRUE16-NEXT: s_wait_kmcnt 0x0
+; GFX1250-TRUE16-NEXT: v_lshlrev_b16 v1.l, 8, v1.l
+; GFX1250-TRUE16-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(NEXT) | instid1(VALU_DEP_1)
+; GFX1250-TRUE16-NEXT: v_bitop3_b16 v0.l, v0.l, v1.l, 0xff bitop3:0xec
+; GFX1250-TRUE16-NEXT: v_cvt_pk_f16_bf8 v0, v0.l
+; GFX1250-TRUE16-NEXT: s_set_pc_i64 s[30:31]
+;
+; GFX1250-FAKE16-LABEL: from_bf8_v2f16:
+; GFX1250-FAKE16: ; %bb.0:
+; GFX1250-FAKE16-NEXT: s_wait_loadcnt_dscnt 0x0
+; GFX1250-FAKE16-NEXT: s_wait_kmcnt 0x0
+; GFX1250-FAKE16-NEXT: v_lshlrev_b16 v1, 8, v1
+; GFX1250-FAKE16-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(NEXT) | instid1(VALU_DEP_1)
+; GFX1250-FAKE16-NEXT: v_bitop3_b16 v0, v0, v1, 0xff bitop3:0xec
+; GFX1250-FAKE16-NEXT: v_cvt_pk_f16_bf8 v0, v0
+; GFX1250-FAKE16-NEXT: s_set_pc_i64 s[30:31]
+ %r = call <2 x half> @llvm.convert.from.arbitrary.fp.v2f16.v2i8(<2 x i8> %x, metadata !"Float8E5M2")
+ ret <2 x half> %r
+}
+
+; v3f16 Float8E4M3FN
+define <3 x half> @from_fp8_v3f16(<3 x i8> %x) {
+; GFX1250-TRUE16-LABEL: from_fp8_v3f16:
+; GFX1250-TRUE16: ; %bb.0:
+; GFX1250-TRUE16-NEXT: s_wait_loadcnt_dscnt 0x0
+; GFX1250-TRUE16-NEXT: s_wait_kmcnt 0x0
+; GFX1250-TRUE16-NEXT: v_lshlrev_b16 v0.h, 8, v1.l
+; GFX1250-TRUE16-NEXT: v_and_b16 v1.l, 0xff, v2.l
+; GFX1250-TRUE16-NEXT: s_delay_alu instid0(VALU_DEP_2) | instskip(NEXT) | instid1(VALU_DEP_2)
+; GFX1250-TRUE16-NEXT: v_bitop3_b16 v0.l, v0.l, v0.h, 0xff bitop3:0xec
+; GFX1250-TRUE16-NEXT: v_cvt_pk_f16_fp8 v1, v1.l
+; GFX1250-TRUE16-NEXT: s_delay_alu instid0(VALU_DEP_2)
+; GFX1250-TRUE16-NEXT: v_cvt_pk_f16_fp8 v0, v0.l
+; GFX1250-TRUE16-NEXT: s_set_pc_i64 s[30:31]
+;
+; GFX1250-FAKE16-LABEL: from_fp8_v3f16:
+; GFX1250-FAKE16: ; %bb.0:
+; GFX1250-FAKE16-NEXT: s_wait_loadcnt_dscnt 0x0
+; GFX1250-FAKE16-NEXT: s_wait_kmcnt 0x0
+; GFX1250-FAKE16-NEXT: v_lshlrev_b16 v1, 8, v1
+; GFX1250-FAKE16-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(SKIP_1) | instid1(VALU_DEP_2)
+; GFX1250-FAKE16-NEXT: v_bitop3_b16 v0, v0, v1, 0xff bitop3:0xec
+; GFX1250-FAKE16-NEXT: v_and_b32_e32 v1, 0xff, v2
+; GFX1250-FAKE16-NEXT: v_cvt_pk_f16_fp8 v0, v0
+; GFX1250-FAKE16-NEXT: s_delay_alu instid0(VALU_DEP_2)
+; GFX1250-FAKE16-NEXT: v_cvt_pk_f16_fp8 v1, v1
+; GFX1250-FAKE16-NEXT: s_set_pc_i64 s[30:31]
+ %r = call <3 x half> @llvm.convert.from.arbitrary.fp.v3f16.v3i8(<3 x i8> %x, metadata !"Float8E4M3FN")
+ ret <3 x half> %r
+}
+
+; v3f16 Float8E5M2
+define <3 x half> @from_bf8_v3f16(<3 x i8> %x) {
+; GFX1250-TRUE16-LABEL: from_bf8_v3f16:
+; GFX1250-TRUE16: ; %bb.0:
+; GFX1250-TRUE16-NEXT: s_wait_loadcnt_dscnt 0x0
+; GFX1250-TRUE16-NEXT: s_wait_kmcnt 0x0
+; GFX1250-TRUE16-NEXT: v_lshlrev_b16 v0.h, 8, v1.l
+; GFX1250-TRUE16-NEXT: v_and_b16 v1.l, 0xff, v2.l
+; GFX1250-TRUE16-NEXT: s_delay_alu instid0(VALU_DEP_2) | instskip(NEXT) | instid1(VALU_DEP_2)
+; GFX1250-TRUE16-NEXT: v_bitop3_b16 v0.l, v0.l, v0.h, 0xff bitop3:0xec
+; GFX1250-TRUE16-NEXT: v_cvt_pk_f16_bf8 v1, v1.l
+; GFX1250-TRUE16-NEXT: s_delay_alu instid0(VALU_DEP_2)
+; GFX1250-TRUE16-NEXT: v_cvt_pk_f16_bf8 v0, v0.l
+; GFX1250-TRUE16-NEXT: s_set_pc_i64 s[30:31]
+;
+; GFX1250-FAKE16-LABEL: from_bf8_v3f16:
+; GFX1250-FAKE16: ; %bb.0:
+; GFX1250-FAKE16-NEXT: s_wait_loadcnt_dscnt 0x0
+; GFX1250-FAKE16-NEXT: s_wait_kmcnt 0x0
+; GFX1250-FAKE16-NEXT: v_lshlrev_b16 v1, 8, v1
+; GFX1250-FAKE16-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(SKIP_1) | instid1(VALU_DEP_2)
+; GFX1250-FAKE16-NEXT: v_bitop3_b16 v0, v0, v1, 0xff bitop3:0xec
+; GFX1250-FAKE16-NEXT: v_and_b32_e32 v1, 0xff, v2
+; GFX1250-FAKE16-NEXT: v_cvt_pk_f16_bf8 v0, v0
+; GFX1250-FAKE16-NEXT: s_delay_alu instid0(VALU_DEP_2)
+; GFX1250-FAKE16-NEXT: v_cvt_pk_f16_bf8 v1, v1
+; GFX1250-FAKE16-NEXT: s_set_pc_i64 s[30:31]
+ %r = call <3 x half> @llvm.convert.from.arbitrary.fp.v3f16.v3i8(<3 x i8> %x, metadata !"Float8E5M2")
+ ret <3 x half> %r
+}
+
+; v4f16 Float8E4M3FN
+define <4 x half> @from_fp8_v4f16(<4 x i8> %x) {
+; GFX1250-TRUE16-LABEL: from_fp8_v4f16:
+; GFX1250-TRUE16: ; %bb.0:
+; GFX1250-TRUE16-NEXT: s_wait_loadcnt_dscnt 0x0
+; GFX1250-TRUE16-NEXT: s_wait_kmcnt 0x0
+; GFX1250-TRUE16-NEXT: v_lshlrev_b16 v0.h, 8, v1.l
+; GFX1250-TRUE16-NEXT: v_lshlrev_b16 v1.l, 8, v3.l
+; GFX1250-TRUE16-NEXT: s_delay_alu instid0(VALU_DEP_2) | instskip(NEXT) | instid1(VALU_DEP_2)
+; GFX1250-TRUE16-NEXT: v_bitop3_b16 v0.l, v0.l, v0.h, 0xff bitop3:0xec
+; GFX1250-TRUE16-NEXT: v_bitop3_b16 v1.l, v2.l, v1.l, 0xff bitop3:0xec
+; GFX1250-TRUE16-NEXT: s_delay_alu instid0(VALU_DEP_2) | instskip(NEXT) | instid1(VALU_DEP_2)
+; GFX1250-TRUE16-NEXT: v_cvt_pk_f16_fp8 v0, v0.l
+; GFX1250-TRUE16-NEXT: v_cvt_pk_f16_fp8 v1, v1.l
+; GFX1250-TRUE16-NEXT: s_set_pc_i64 s[30:31]
+;
+; GFX1250-FAKE16-LABEL: from_fp8_v4f16:
+; GFX1250-FAKE16: ; %bb.0:
+; GFX1250-FAKE16-NEXT: s_wait_loadcnt_dscnt 0x0
+; GFX1250-FAKE16-NEXT: s_wait_kmcnt 0x0
+; GFX1250-FAKE16-NEXT: v_lshlrev_b16 v1, 8, v1
+; GFX1250-FAKE16-NEXT: v_lshlrev_b16 v3, 8, v3
+; GFX1250-FAKE16-NEXT: s_delay_alu instid0(VALU_DEP_2) | instskip(NEXT) | instid1(VALU_DEP_2)
+; GFX1250-FAKE16-NEXT: v_bitop3_b16 v0, v0, v1, 0xff bitop3:0xec
+; GFX1250-FAKE16-NEXT: v_bitop3_b16 v1, v2, v3, 0xff bitop3:0xec
+; GFX1250-FAKE16-NEXT: s_delay_alu instid0(VALU_DEP_2) | instskip(NEXT) | instid1(VALU_DEP_2)
+; GFX1250-FAKE16-NEXT: v_cvt_pk_f16_fp8 v0, v0
+; GFX1250-FAKE16-NEXT: v_cvt_pk_f16_fp8 v1, v1
+; GFX1250-FAKE16-NEXT: s_set_pc_i64 s[30:31]
+ %r = call <4 x half> @llvm.convert.from.arbitrary.fp.v4f16.v4i8(<4 x i8> %x, metadata !"Float8E4M3FN")
+ ret <4 x half> %r
+}
+
+; v4f16 Float8E5M2
+define <4 x half> @from_bf8_v4f16(<4 x i8> %x) {
+; GFX1250-TRUE16-LABEL: from_bf8_v4f16:
+; GFX1250-TRUE16: ; %bb.0:
+; GFX1250-TRUE16-NEXT: s_wait_loadcnt_dscnt 0x0
+; GFX1250-TRUE16-NEXT: s_wait_kmcnt 0x0
+; GFX1250-TRUE16-NEXT: v_lshlrev_b16 v0.h, 8, v1.l
+; GFX1250-TRUE16-NEXT: v_lshlrev_b16 v1.l, 8, v3.l
+; GFX1250-TRUE16-NEXT: s_delay_alu instid0(VALU_DEP_2) | instskip(NEXT) | instid1(VALU_DEP_2)
+; GFX1250-TRUE16-NEXT: v_bitop3_b16 v0.l, v0.l, v0.h, 0xff bitop3:0xec
+; GFX1250-TRUE16-NEXT: v_bitop3_b16 v1.l, v2.l, v1.l, 0xff bitop3:0xec
+; GFX1250-TRUE16-NEXT: s_delay_alu instid0(VALU_DEP_2) | instskip(NEXT) | instid1(VALU_DEP_2)
+; GFX1250-TRUE16-NEXT: v_cvt_pk_f16_bf8 v0, v0.l
+; GFX1250-TRUE16-NEXT: v_cvt_pk_f16_bf8 v1, v1.l
+; GFX1250-TRUE16-NEXT: s_set_pc_i64 s[30:31]
+;
+; GFX1250-FAKE16-LABEL: from_bf8_v4f16:
+; GFX1250-FAKE16: ; %bb.0:
+; GFX1250-FAKE16-NEXT: s_wait_loadcnt_dscnt 0x0
+; GFX1250-FAKE16-NEXT: s_wait_kmcnt 0x0
+; GFX1250-FAKE16-NEXT: v_lshlrev_b16 v1, 8, v1
+; GFX1250-FAKE16-NEXT: v_lshlrev_b16 v3, 8, v3
+; GFX1250-FAKE16-NEXT: s_delay_alu instid0(VALU_DEP_2) | instskip(NEXT) | instid1(VALU_DEP_2)
+; GFX1250-FAKE16-NEXT: v_bitop3_b16 v0, v0, v1, 0xff bitop3:0xec
+; GFX1250-FAKE16-NEXT: v_bitop3_b16 v1, v2, v3, 0xff bitop3:0xec
+; GFX1250-FAKE16-NEXT: s_delay_alu instid0(VALU_DEP_2) | instskip(NEXT) | instid1(VALU_DEP_2)
+; GFX1250-FAKE16-NEXT: v_cvt_pk_f16_bf8 v0, v0
+; GFX1250-FAKE16-NEXT: v_cvt_pk_f16_bf8 v1, v1
+; GFX1250-FAKE16-NEXT: s_set_pc_i64 s[30:31]
+ %r = call <4 x half> @llvm.convert.from.arbitrary.fp.v4f16.v4i8(<4 x i8> %x, metadata !"Float8E5M2")
+ ret <4 x half> %r
+}
+;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line:
+; GFX1250: {{.*}}
diff --git a/llvm/test/CodeGen/AMDGPU/arbitrary-fp-to-float-fp8-hw.ll b/llvm/test/CodeGen/AMDGPU/arbitrary-fp-to-float-fp8-hw.ll
new file mode 100644
index 0000000000000..86a9e663cfc0c
--- /dev/null
+++ b/llvm/test/CodeGen/AMDGPU/arbitrary-fp-to-float-fp8-hw.ll
@@ -0,0 +1,256 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
+; RUN: llc < %s -mtriple=amdgcn-amd-amdhsa -mcpu=gfx950 | FileCheck -check-prefix=GFX950 %s
+; RUN: llc < %s -mtriple=amdgcn-amd-amdhsa -mcpu=gfx1170 | FileCheck -check-prefix=GFX1170 %s
+; RUN: llc < %s -mtriple=amdgcn-amd-amdhsa -mcpu=gfx1250 | FileCheck -check-prefix=GFX1250 %s
+
+; llvm.convert.from.arbitrary.fp on FP8ConversionInsts targets with OCP FP8.
+
+; Scalar Float8E5M2
+define float @from_bf8_dynamic(i8 %x) {
+; GFX950-LABEL: from_bf8_dynamic:
+; GFX950: ; %bb.0:
+; GFX950-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX950-NEXT: v_cvt_f32_bf8_e32 v0, v0
+; GFX950-NEXT: s_setpc_b64 s[30:31]
+;
+; GFX1170-LABEL: from_bf8_dynamic:
+; GFX1170: ; %bb.0:
+; GFX1170-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX1170-NEXT: v_cvt_f32_bf8_e32 v0, v0
+; GFX1170-NEXT: s_setpc_b64 s[30:31]
+;
+; GFX1250-LABEL: from_bf8_dynamic:
+; GFX1250: ; %bb.0:
+; GFX1250-NEXT: s_wait_loadcnt_dscnt 0x0
+; GFX1250-NEXT: s_wait_kmcnt 0x0
+; GFX1250-NEXT: v_cvt_f32_bf8_e32 v0, v0
+; GFX1250-NEXT: s_set_pc_i64 s[30:31]
+ %r = call float @llvm.convert.from.arbitrary.fp.f32.i8(i8 %x, metadata !"Float8E5M2")
+ ret float %r
+}
+
+; Scalar Float8E4M3FN
+define float @from_fp8_dynamic(i8 %x) {
+; GFX950-LABEL: from_fp8_dynamic:
+; GFX950: ; %bb.0:
+; GFX950-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX950-NEXT: v_cvt_f32_fp8_e32 v0, v0
+; GFX950-NEXT: s_setpc_b64 s[30:31]
+;
+; GFX1170-LABEL: from_fp8_dynamic:
+; GFX1170: ; %bb.0:
+; GFX1170-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX1170-NEXT: v_cvt_f32_fp8_e32 v0, v0
+; GFX1170-NEXT: s_setpc_b64 s[30:31]
+;
+; GFX1250-LABEL: from_fp8_dynamic:
+; GFX1250: ; %bb.0:
+; GFX1250-NEXT: s_wait_loadcnt_dscnt 0x0
+; GFX1250-NEXT: s_wait_kmcnt 0x0
+; GFX1250-NEXT: v_cvt_f32_fp8_e32 v0, v0
+; GFX1250-NEXT: s_set_pc_i64 s[30:31]
+ %r = call float @llvm.convert.from.arbitrary.fp.f32.i8(i8 %x, metadata !"Float8E4M3FN")
+ ret float %r
+}
+
+; v2f32
+define <2 x float> @v2_from_bf8(<2 x i8> %x) {
+; GFX950-LABEL: v2_from_bf8:
+; GFX950: ; %bb.0:
+; GFX950-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX950-NEXT: s_mov_b32 s0, 0xc0c0004
+; GFX950-NEXT: v_perm_b32 v0, v0, v1, s0
+; GFX950-NEXT: v_cvt_pk_f32_bf8_e32 v[0:1], v0
+; GFX950-NEXT: s_setpc_b64 s[30:31]
+;
+; GFX1170-LABEL: v2_from_bf8:
+; GFX1170: ; %bb.0:
+; GFX1170-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX1170-NEXT: v_perm_b32 v0, v0, v1, 0xc0c0004
+; GFX1170-NEXT: s_delay_alu instid0(VALU_DEP_1)
+; GFX1170-NEXT: v_cvt_pk_f32_bf8_e32 v[0:1], v0
+; GFX1170-NEXT: s_setpc_b64 s[30:31]
+;
+; GFX1250-LABEL: v2_from_bf8:
+; GFX1250: ; %bb.0:
+; GFX1250-NEXT: s_wait_loadcnt_dscnt 0x0
+; GFX1250-NEXT: s_wait_kmcnt 0x0
+; GFX1250-NEXT: v_perm_b32 v0, v0, v1, 0xc0c0004
+; GFX1250-NEXT: s_delay_alu instid0(VALU_DEP_1)
+; GFX1250-NEXT: v_cvt_pk_f32_bf8_e32 v[0:1], v0
+; GFX1250-NEXT: s_set_pc_i64 s[30:31]
+ %r = call <2 x float> @llvm.convert.from.arbitrary.fp.v2f32.v2i8(<2 x i8> %x, metadata !"Float8E5M2")
+ ret <2 x float> %r
+}
+
+define <2 x float> @v2_from_fp8(<2 x i8> %x) {
+; GFX950-LABEL: v2_from_fp8:
+; GFX950: ; %bb.0:
+; GFX950-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX950-NEXT: s_mov_b32 s0, 0xc0c0004
+; GFX950-NEXT: v_perm_b32 v0, v0, v1, s0
+; GFX950-NEXT: v_cvt_pk_f32_fp8_e32 v[0:1], v0
+; GFX950-NEXT: s_setpc_b64 s[30:31]
+;
+; GFX1170-LABEL: v2_from_fp8:
+; GFX1170: ; %bb.0:
+; GFX1170-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX1170-NEXT: v_perm_b32 v0, v0, v1, 0xc0c0004
+; GFX1170-NEXT: s_delay_alu instid0(VALU_DEP_1)
+; GFX1170-NEXT: v_cvt_pk_f32_fp8_e32 v[0:1], v0
+; GFX1170-NEXT: s_setpc_b64 s[30:31]
+;
+; GFX1250-LABEL: v2_from_fp8:
+; GFX1250: ; %bb.0:
+; GFX1250-NEXT: s_wait_loadcnt_dscnt 0x0
+; GFX1250-NEXT: s_wait_kmcnt 0x0
+; GFX1250-NEXT: v_perm_b32 v0, v0, v1, 0xc0c0004
+; GFX1250-NEXT: s_delay_alu instid0(VALU_DEP_1)
+; GFX1250-NEXT: v_cvt_pk_f32_fp8_e32 v[0:1], v0
+; GFX1250-NEXT: s_set_pc_i64 s[30:31]
+ %r = call <2 x float> @llvm.convert.from.arbitrary.fp.v2f32.v2i8(<2 x i8> %x, metadata !"Float8E4M3FN")
+ ret <2 x float> %r
+}
+
+; v4f32
+define <4 x float> @v4_from_bf8(<4 x i8> %x) {
+; GFX950-LABEL: v4_from_bf8:
+; GFX950: ; %bb.0:
+; GFX950-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX950-NEXT: s_mov_b32 s0, 0xc0c0004
+; GFX950-NEXT: v_perm_b32 v0, v0, v1, s0
+; GFX950-NEXT: v_perm_b32 v2, v2, v3, s0
+; GFX950-NEXT: v_cvt_pk_f32_bf8_e32 v[0:1], v0
+; GFX950-NEXT: v_cvt_pk_f32_bf8_e32 v[2:3], v2
+; GFX950-NEXT: s_setpc_b64 s[30:31]
+;
+; GFX1170-LABEL: v4_from_bf8:
+; GFX1170: ; %bb.0:
+; GFX1170-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX1170-NEXT: v_perm_b32 v0, v0, v1, 0xc0c0004
+; GFX1170-NEXT: v_perm_b32 v2, v2, v3, 0xc0c0004
+; GFX1170-NEXT: s_delay_alu instid0(VALU_DEP_2) | instskip(NEXT) | instid1(VALU_DEP_2)
+; GFX1170-NEXT: v_cvt_pk_f32_bf8_e32 v[0:1], v0
+; GFX1170-NEXT: v_cvt_pk_f32_bf8_e32 v[2:3], v2
+; GFX1170-NEXT: s_setpc_b64 s[30:31]
+;
+; GFX1250-LABEL: v4_from_bf8:
+; GFX1250: ; %bb.0:
+; GFX1250-NEXT: s_wait_loadcnt_dscnt 0x0
+; GFX1250-NEXT: s_wait_kmcnt 0x0
+; GFX1250-NEXT: v_perm_b32 v0, v0, v1, 0xc0c0004
+; GFX1250-NEXT: v_perm_b32 v2, v2, v3, 0xc0c0004
+; GFX1250-NEXT: s_delay_alu instid0(VALU_DEP_2) | instskip(NEXT) | instid1(VALU_DEP_2)
+; GFX1250-NEXT: v_cvt_pk_f32_bf8_e32 v[0:1], v0
+; GFX1250-NEXT: v_cvt_pk_f32_bf8_e32 v[2:3], v2
+; GFX1250-NEXT: s_set_pc_i64 s[30:31]
+ %r = call <4 x float> @llvm.convert.from.arbitrary.fp.v4f32.v4i8(<4 x i8> %x, metadata !"Float8E5M2")
+ ret <4 x float> %r
+}
+
+define <4 x float> @v4_from_fp8(<4 x i8> %x) {
+; GFX950-LABEL: v4_from_fp8:
+; GFX950: ; %bb.0:
+; GFX950-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX950-NEXT: s_mov_b32 s0, 0xc0c0004
+; GFX950-NEXT: v_perm_b32 v0, v0, v1, s0
+; GFX950-NEXT: v_perm_b32 v2, v2, v3, s0
+; GFX950-NEXT: v_cvt_pk_f32_fp8_e32 v[0:1], v0
+; GFX950-NEXT: v_cvt_pk_f32_fp8_e32 v[2:3], v2
+; GFX950-NEXT: s_setpc_b64 s[30:31]
+;
+; GFX1170-LABEL: v4_from_fp8:
+; GFX1170: ; %bb.0:
+; GFX1170-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX1170-NEXT: v_perm_b32 v0, v0, v1, 0xc0c0004
+; GFX1170-NEXT: v_perm_b32 v2, v2, v3, 0xc0c0004
+; GFX1170-NEXT: s_delay_alu instid0(VALU_DEP_2) | instskip(NEXT) | instid1(VALU_DEP_2)
+; GFX1170-NEXT: v_cvt_pk_f32_fp8_e32 v[0:1], v0
+; GFX1170-NEXT: v_cvt_pk_f32_fp8_e32 v[2:3], v2
+; GFX1170-NEXT: s_setpc_b64 s[30:31]
+;
+; GFX1250-LABEL: v4_from_fp8:
+; GFX1250: ; %bb.0:
+; GFX1250-NEXT: s_wait_loadcnt_dscnt 0x0
+; GFX1250-NEXT: s_wait_kmcnt 0x0
+; GFX1250-NEXT: v_perm_b32 v0, v0, v1, 0xc0c0004
+; GFX1250-NEXT: v_perm_b32 v2, v2, v3, 0xc0c0004
+; GFX1250-NEXT: s_delay_alu instid0(VALU_DEP_2) | instskip(NEXT) | instid1(VALU_DEP_2)
+; GFX1250-NEXT: v_cvt_pk_f32_fp8_e32 v[0:1], v0
+; GFX1250-NEXT: v_cvt_pk_f32_fp8_e32 v[2:3], v2
+; GFX1250-NEXT: s_set_pc_i64 s[30:31]
+ %r = call <4 x float> @llvm.convert.from.arbitrary.fp.v4f32.v4i8(<4 x i8> %x, metadata !"Float8E4M3FN")
+ ret <4 x float> %r
+}
+
+; v3f32
+define <3 x float> @v3_from_bf8(<3 x i8> %x) {
+; GFX950-LABEL: v3_from_bf8:
+; GFX950: ; %bb.0:
+; GFX950-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX950-NEXT: s_mov_b32 s0, 0xc0c0004
+; GFX950-NEXT: v_perm_b32 v0, v0, v1, s0
+; GFX950-NEXT: v_and_b32_e32 v2, 0xff, v2
+; GFX950-NEXT: v_cvt_pk_f32_bf8_e32 v[0:1], v0
+; GFX950-NEXT: v_cvt_pk_f32_bf8_e32 v[2:3], v2
+; GFX950-NEXT: s_setpc_b64 s[30:31]
+;
+; GFX1170-LABEL: v3_from_bf8:
+; GFX1170: ; %bb.0:
+; GFX1170-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX1170-NEXT: v_perm_b32 v0, v0, v1, 0xc0c0004
+; GFX1170-NEXT: v_and_b16 v2.l, 0xff, v2.l
+; GFX1170-NEXT: s_delay_alu instid0(VALU_DEP_2) | instskip(NEXT) | instid1(VALU_DEP_2)
+; GFX1170-NEXT: v_cvt_pk_f32_bf8_e32 v[0:1], v0
+; GFX1170-NEXT: v_cvt_pk_f32_bf8_e32 v[2:3], v2
+; GFX1170-NEXT: s_setpc_b64 s[30:31]
+;
+; GFX1250-LABEL: v3_from_bf8:
+; GFX1250: ; %bb.0:
+; GFX1250-NEXT: s_wait_loadcnt_dscnt 0x0
+; GFX1250-NEXT: s_wait_kmcnt 0x0
+; GFX1250-NEXT: v_perm_b32 v0, v0, v1, 0xc0c0004
+; GFX1250-NEXT: v_and_b16 v2.l, 0xff, v2.l
+; GFX1250-NEXT: s_delay_alu instid0(VALU_DEP_2) | instskip(NEXT) | instid1(VALU_DEP_2)
+; GFX1250-NEXT: v_cvt_pk_f32_bf8_e32 v[0:1], v0
+; GFX1250-NEXT: v_cvt_pk_f32_bf8_e32 v[2:3], v2
+; GFX1250-NEXT: s_set_pc_i64 s[30:31]
+ %r = call <3 x float> @llvm.convert.from.arbitrary.fp.v3f32.v3i8(<3 x i8> %x, metadata !"Float8E5M2")
+ ret <3 x float> %r
+}
+
+define <3 x float> @v3_from_fp8(<3 x i8> %x) {
+; GFX950-LABEL: v3_from_fp8:
+; GFX950: ; %bb.0:
+; GFX950-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX950-NEXT: s_mov_b32 s0, 0xc0c0004
+; GFX950-NEXT: v_perm_b32 v0, v0, v1, s0
+; GFX950-NEXT: v_and_b32_e32 v2, 0xff, v2
+; GFX950-NEXT: v_cvt_pk_f32_fp8_e32 v[0:1], v0
+; GFX950-NEXT: v_cvt_pk_f32_fp8_e32 v[2:3], v2
+; GFX950-NEXT: s_setpc_b64 s[30:31]
+;
+; GFX1170-LABEL: v3_from_fp8:
+; GFX1170: ; %bb.0:
+; GFX1170-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX1170-NEXT: v_perm_b32 v0, v0, v1, 0xc0c0004
+; GFX1170-NEXT: v_and_b16 v2.l, 0xff, v2.l
+; GFX1170-NEXT: s_delay_alu instid0(VALU_DEP_2) | instskip(NEXT) | instid1(VALU_DEP_2)
+; GFX1170-NEXT: v_cvt_pk_f32_fp8_e32 v[0:1], v0
+; GFX1170-NEXT: v_cvt_pk_f32_fp8_e32 v[2:3], v2
+; GFX1170-NEXT: s_setpc_b64 s[30:31]
+;
+; GFX1250-LABEL: v3_from_fp8:
+; GFX1250: ; %bb.0:
+; GFX1250-NEXT: s_wait_loadcnt_dscnt 0x0
+; GFX1250-NEXT: s_wait_kmcnt 0x0
+; GFX1250-NEXT: v_perm_b32 v0, v0, v1, 0xc0c0004
+; GFX1250-NEXT: v_and_b16 v2.l, 0xff, v2.l
+; GFX1250-NEXT: s_delay_alu instid0(VALU_DEP_2) | instskip(NEXT) | instid1(VALU_DEP_2)
+; GFX1250-NEXT: v_cvt_pk_f32_fp8_e32 v[0:1], v0
+; GFX1250-NEXT: v_cvt_pk_f32_fp8_e32 v[2:3], v2
+; GFX1250-NEXT: s_set_pc_i64 s[30:31]
+ %r = call <3 x float> @llvm.convert.from.arbitrary.fp.v3f32.v3i8(<3 x i8> %x, metadata !"Float8E4M3FN")
+ ret <3 x float> %r
+}
+
diff --git a/llvm/test/CodeGen/AMDGPU/llvm.amdgcn.cvt.fp8.dpp.mir b/llvm/test/CodeGen/AMDGPU/llvm.amdgcn.cvt.fp8.dpp.mir
index cfa2d5ec3d959..69bfb847eb5df 100644
--- a/llvm/test/CodeGen/AMDGPU/llvm.amdgcn.cvt.fp8.dpp.mir
+++ b/llvm/test/CodeGen/AMDGPU/llvm.amdgcn.cvt.fp8.dpp.mir
@@ -16,12 +16,12 @@ body: |
; GFX1170PLUS-NEXT: {{ $}}
; GFX1170PLUS-NEXT: [[COPY:%[0-9]+]]:vgpr_32 = COPY $vgpr0
; GFX1170PLUS-NEXT: [[DEF:%[0-9]+]]:vgpr_32 = IMPLICIT_DEF
- ; GFX1170PLUS-NEXT: [[V_CVT_F32_BF8_OP_SEL_dpp:%[0-9]+]]:vgpr_32 = V_CVT_F32_BF8_OP_SEL_dpp [[DEF]], [[COPY]], 228, 15, 15, 1, implicit $mode, implicit $exec
- ; GFX1170PLUS-NEXT: $vgpr0 = COPY [[V_CVT_F32_BF8_OP_SEL_dpp]]
+ ; GFX1170PLUS-NEXT: [[V_CVT_F32_BF8_op_sel_dpp:%[0-9]+]]:vgpr_32 = V_CVT_F32_BF8_op_sel_dpp [[DEF]], [[COPY]], 228, 15, 15, 1, implicit $mode, implicit $exec
+ ; GFX1170PLUS-NEXT: $vgpr0 = COPY [[V_CVT_F32_BF8_op_sel_dpp]]
; GFX1170PLUS-NEXT: SI_RETURN_TO_EPILOG $vgpr0
%0:vgpr_32 = COPY $vgpr0
%1:vgpr_32 = V_MOV_B32_dpp %0, %0, 228, 15, 15, -1, implicit $exec
- %2:vgpr_32 = V_CVT_F32_BF8_OP_SEL_e32 killed %1, implicit $mode, implicit $exec
+ %2:vgpr_32 = V_CVT_F32_BF8_op_sel_e32 killed %1, implicit $mode, implicit $exec
$vgpr0 = COPY %2
SI_RETURN_TO_EPILOG $vgpr0
@@ -38,12 +38,12 @@ body: |
; GFX1170PLUS-NEXT: {{ $}}
; GFX1170PLUS-NEXT: [[COPY:%[0-9]+]]:vgpr_32 = COPY $vgpr0
; GFX1170PLUS-NEXT: [[DEF:%[0-9]+]]:vgpr_32 = IMPLICIT_DEF
- ; GFX1170PLUS-NEXT: [[V_CVT_F32_BF8_OP_SEL_e64_dpp:%[0-9]+]]:vgpr_32 = V_CVT_F32_BF8_OP_SEL_e64_dpp [[DEF]], [[COPY]], 2, 228, 15, 15, 1, implicit $mode, implicit $exec
- ; GFX1170PLUS-NEXT: $vgpr0 = COPY [[V_CVT_F32_BF8_OP_SEL_e64_dpp]]
+ ; GFX1170PLUS-NEXT: [[V_CVT_F32_BF8_op_sel_e64_dpp:%[0-9]+]]:vgpr_32 = V_CVT_F32_BF8_op_sel_e64_dpp [[DEF]], [[COPY]], 2, 228, 15, 15, 1, implicit $mode, implicit $exec
+ ; GFX1170PLUS-NEXT: $vgpr0 = COPY [[V_CVT_F32_BF8_op_sel_e64_dpp]]
; GFX1170PLUS-NEXT: SI_RETURN_TO_EPILOG $vgpr0
%0:vgpr_32 = COPY $vgpr0
%1:vgpr_32 = V_MOV_B32_dpp %0, %0, 228, 15, 15, -1, implicit $exec
- %2:vgpr_32 = V_CVT_F32_BF8_OP_SEL_e64 killed %1, 2, implicit $mode, implicit $exec
+ %2:vgpr_32 = V_CVT_F32_BF8_op_sel_e64 killed %1, 2, implicit $mode, implicit $exec
$vgpr0 = COPY %2
SI_RETURN_TO_EPILOG $vgpr0
@@ -60,12 +60,12 @@ body: |
; GFX1170PLUS-NEXT: {{ $}}
; GFX1170PLUS-NEXT: [[COPY:%[0-9]+]]:vgpr_32 = COPY $vgpr0
; GFX1170PLUS-NEXT: [[DEF:%[0-9]+]]:vgpr_32 = IMPLICIT_DEF
- ; GFX1170PLUS-NEXT: [[V_CVT_F32_FP8_OP_SEL_e64_dpp:%[0-9]+]]:vgpr_32 = V_CVT_F32_FP8_OP_SEL_e64_dpp [[DEF]], [[COPY]], 3, 228, 15, 15, 1, implicit $mode, implicit $exec
- ; GFX1170PLUS-NEXT: $vgpr0 = COPY [[V_CVT_F32_FP8_OP_SEL_e64_dpp]]
+ ; GFX1170PLUS-NEXT: [[V_CVT_F32_FP8_op_sel_e64_dpp:%[0-9]+]]:vgpr_32 = V_CVT_F32_FP8_op_sel_e64_dpp [[DEF]], [[COPY]], 3, 228, 15, 15, 1, implicit $mode, implicit $exec
+ ; GFX1170PLUS-NEXT: $vgpr0 = COPY [[V_CVT_F32_FP8_op_sel_e64_dpp]]
; GFX1170PLUS-NEXT: SI_RETURN_TO_EPILOG $vgpr0
%0:vgpr_32 = COPY $vgpr0
%1:vgpr_32 = V_MOV_B32_dpp %0, %0, 228, 15, 15, -1, implicit $exec
- %2:vgpr_32 = V_CVT_F32_FP8_OP_SEL_e64 killed %1, 3, implicit $mode, implicit $exec
+ %2:vgpr_32 = V_CVT_F32_FP8_op_sel_e64 killed %1, 3, implicit $mode, implicit $exec
$vgpr0 = COPY %2
SI_RETURN_TO_EPILOG $vgpr0
diff --git a/llvm/test/TableGen/GlobalISelEmitter/GlobalISelEmitter.td b/llvm/test/TableGen/GlobalISelEmitter/GlobalISelEmitter.td
index fa02ca90b0a16..79d8bd57ef560 100644
--- a/llvm/test/TableGen/GlobalISelEmitter/GlobalISelEmitter.td
+++ b/llvm/test/TableGen/GlobalISelEmitter/GlobalISelEmitter.td
@@ -201,12 +201,20 @@ def HasC : Predicate<"Subtarget->hasC()"> { let RecomputePerFunction = 1; }
// CHECK-LABEL: // PatFrag predicates.
// CHECK-NEXT: enum {
-// CHECK-NEXT: GICXXPred_I64_Predicate_cimm8 = GICXXPred_Invalid + 1,
+// CHECK-NEXT: GICXXPred_I64_Predicate_Float8E4M3FN = GICXXPred_Invalid + 1,
+// CHECK-NEXT: GICXXPred_I64_Predicate_Float8E5M2,
+// CHECK-NEXT: GICXXPred_I64_Predicate_cimm8,
// CHECK-NEXT: GICXXPred_I64_Predicate_simm8,
// CHECK-NEXT: };
// CHECK-NEXT: bool MyTargetInstructionSelector::testImmPredicate_I64(unsigned PredicateID, int64_t Imm) const {
// CHECK-NEXT: switch (PredicateID) {
+// CHECK-NEXT: case GICXXPred_I64_Predicate_Float8E4M3FN: {
+// CHECK-NEXT: return Imm == APFloatBase::S_Float8E4M3FN;
+// CHECK-NEXT: }
+// CHECK-NEXT: case GICXXPred_I64_Predicate_Float8E5M2: {
+// CHECK-NEXT: return Imm == APFloatBase::S_Float8E5M2;
+// CHECK-NEXT: }
// CHECK-NEXT: case GICXXPred_I64_Predicate_cimm8: {
// CHECK-NEXT: return isInt<8>(Imm);
// CHECK-NEXT: }
More information about the llvm-commits
mailing list