Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 13 additions & 9 deletions docs/OCPTypesRepresentationInLLVM.rst
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,8 @@ SPIR-V conversion instructions
Most conversions will be represented by standard SPIR-V conversion instructions (*OpFConvert*, *OpConvertSToF*, *OpConvertFToS*,
*OpConvertUToF*, *OpConvertFToU*, *OpSConvert*), which don't carry information about floating-point value's width and encoding.
This document adds a new set of external function calls, each of which has a name that is formed from encoding a specific conversion
that it performs. This name has a *__builtin_spirv_* prefix and a postfix indicating the extension (e.g., *EXT* from SPV_EXT_float8,
*INTEL* from SPV_INTEL_int4/SPV_INTEL_float4/SPV_INTEL_fp_conversions). These calls will be translated to SPIR-V conversion
that it performs. This name has a *__builtin_spirv_* prefix and a postfix indicating the extension (e.g., *EXT* from SPV_EXT_float8
and SPV_EXT_ocp_microscaling_types, *INTEL* from SPV_INTEL_int4, SPV_INTEL_float4 and SPV_INTEL_fp_conversions). These calls will be translated to SPIR-V conversion
instructions operating over the appropriate types. These functions are expected to be mangled following Itanium C++ ABI. SPIR-V consumer
will apply Itanium mangling during translation to LLVM IR as well.

Expand Down Expand Up @@ -82,16 +82,19 @@ SPV_INTEL_int4 Conversions

__builtin_spirv_ConvertInt4ToInt8INTEL

SPV_INTEL_float4 Conversions
-----------------------------
SPV_EXT_ocp_microscaling_types Conversions
-------------------------------------------

**Translated to OpFConvert:**

.. code-block:: C

__builtin_spirv_ConvertE2M1ToE4M3INTEL, __builtin_spirv_ConvertE2M1ToE5M2INTEL,
__builtin_spirv_ConvertE2M1ToFP16INTEL, __builtin_spirv_ConvertE2M1ToBF16INTEL,
__builtin_spirv_ConvertFP16ToE2M1INTEL, __builtin_spirv_ConvertBF16ToE2M1INTEL
__builtin_spirv_ConvertE2M1ToE4M3EXT, __builtin_spirv_ConvertE2M1ToE5M2EXT,
__builtin_spirv_ConvertE2M1ToFP16EXT, __builtin_spirv_ConvertE2M1ToBF16EXT,
__builtin_spirv_ConvertFP16ToE2M1EXT, __builtin_spirv_ConvertBF16ToE2M1EXT

For backward compatibility, the equivalent INTEL-postfix builtins (e.g. *__builtin_spirv_ConvertE2M1ToFP16INTEL*)
are also accepted and map to SPV_INTEL_float4; new producers should use the EXT form above.

SPV_INTEL_fp_conversions
-------------------------
Expand All @@ -107,8 +110,9 @@ This extension provides conversions with specialized rounding modes for improved

The result is decorated with *SaturatedToLargestFloat8NormalConversionEXT* (SPV_EXT_float8).

ClampConvert*ToE2M1INTEL builtins are not provided: fp4 (E2M1) saturation is unconditional,
so they collapse into the plain *Convert\*ToE2M1INTEL* form listed under SPV_INTEL_float4.
ClampConvert*ToE2M1 builtins are not provided: fp4 (E2M1) saturation is unconditional,
so they collapse into the plain *Convert\*ToE2M1EXT* / *Convert\*ToE2M1INTEL* form listed under
SPV_EXT_ocp_microscaling_types / SPV_INTEL_float4.

**Translated to OpClampConvertFToSINTEL (clamp rounding to signed integer):**

Expand Down
1 change: 1 addition & 0 deletions include/LLVMSPIRVExtensions.inc
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ EXT(SPV_EXT_float8)
EXT(SPV_INTEL_predicated_io)
EXT(SPV_INTEL_sigmoid)
EXT(SPV_INTEL_float4)
EXT(SPV_EXT_ocp_microscaling_types)
EXT(SPV_INTEL_fp_conversions)
EXT(SPV_KHR_float_controls2)
EXT(SPV_INTEL_rounded_divide_sqrt)
Expand Down
27 changes: 20 additions & 7 deletions lib/SPIRV/SPIRVInternal.h
Original file line number Diff line number Diff line change
Expand Up @@ -1035,7 +1035,8 @@ enum FPEncodingWrap {
BF16 = FPEncoding::FPEncodingBFloat16KHR,
E4M3 = FPEncoding::FPEncodingFloat8E4M3EXT,
E5M2 = FPEncoding::FPEncodingFloat8E5M2EXT,
E2M1 = internal::FPEncodingFloat4E2M1INTEL,
E2M1 = FPEncoding::FPEncodingFloat4E2M1EXT,
E2M1INTEL = internal::FPEncodingFloat4E2M1INTEL,
};

// Structure describing non-trivial conversions (FP8, FP4 and int4)
Expand Down Expand Up @@ -1072,14 +1073,22 @@ typedef SPIRVMap<llvm::StringRef, FPConversionDesc> FPConvertToEncodingMap;
// clang-format off
template <> inline void FPConvertToEncodingMap::init() {
// 4-bit conversions
add("ConvertE2M1ToE4M3INTEL",
add("ConvertE2M1ToE4M3EXT",
{FPEncodingWrap::E2M1, FPEncodingWrap::E4M3, OpFConvert});
add("ConvertE2M1ToE5M2INTEL",
add("ConvertE2M1ToE5M2EXT",
{FPEncodingWrap::E2M1, FPEncodingWrap::E5M2, OpFConvert});
add("ConvertE2M1ToFP16INTEL",
add("ConvertE2M1ToFP16EXT",
{FPEncodingWrap::E2M1, FPEncodingWrap::IEEE754, OpFConvert});
add("ConvertE2M1ToBF16INTEL",
add("ConvertE2M1ToBF16EXT",
{FPEncodingWrap::E2M1, FPEncodingWrap::BF16, OpFConvert});
add("ConvertE2M1ToE4M3INTEL",
{FPEncodingWrap::E2M1INTEL, FPEncodingWrap::E4M3, OpFConvert});
add("ConvertE2M1ToE5M2INTEL",
{FPEncodingWrap::E2M1INTEL, FPEncodingWrap::E5M2, OpFConvert});
add("ConvertE2M1ToFP16INTEL",
{FPEncodingWrap::E2M1INTEL, FPEncodingWrap::IEEE754, OpFConvert});
add("ConvertE2M1ToBF16INTEL",
{FPEncodingWrap::E2M1INTEL, FPEncodingWrap::BF16, OpFConvert});

add("ConvertInt4ToE4M3INTEL",
{FPEncodingWrap::Integer, FPEncodingWrap::E4M3, OpConvertSToF});
Expand All @@ -1092,10 +1101,14 @@ template <> inline void FPConvertToEncodingMap::init() {
add("ConvertInt4ToInt8INTEL",
{FPEncodingWrap::Integer, FPEncodingWrap::Integer, OpSConvert});

add("ConvertFP16ToE2M1INTEL",
add("ConvertFP16ToE2M1EXT",
{FPEncodingWrap::IEEE754, FPEncodingWrap::E2M1, OpFConvert});
add("ConvertBF16ToE2M1INTEL",
add("ConvertBF16ToE2M1EXT",
{FPEncodingWrap::BF16, FPEncodingWrap::E2M1, OpFConvert});
add("ConvertFP16ToE2M1INTEL",
{FPEncodingWrap::IEEE754, FPEncodingWrap::E2M1INTEL, OpFConvert});
add("ConvertBF16ToE2M1INTEL",
{FPEncodingWrap::BF16, FPEncodingWrap::E2M1INTEL, OpFConvert});
add("ConvertFP16ToInt4INTEL",
{FPEncodingWrap::IEEE754, FPEncodingWrap::Integer, OpConvertFToS});
add("ConvertBF16ToInt4INTEL",
Expand Down
6 changes: 5 additions & 1 deletion lib/SPIRV/SPIRVReader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1042,7 +1042,9 @@ Value *SPIRVToLLVM::transConvertInst(SPIRVValue *BV, Function *F,

auto IsFP4OrFP8Encoding = [](FPEncodingWrap Encoding) -> bool {
return Encoding == FPEncodingWrap::E4M3 ||
Encoding == FPEncodingWrap::E5M2 || Encoding == FPEncodingWrap::E2M1;
Encoding == FPEncodingWrap::E5M2 ||
Encoding == FPEncodingWrap::E2M1 ||
Encoding == FPEncodingWrap::E2M1INTEL;
};

switch (static_cast<unsigned>(BC->getOpCode())) {
Expand Down Expand Up @@ -3145,6 +3147,8 @@ Value *SPIRVToLLVM::transValueWithoutDecoration(SPIRVValue *BV, Function *F,
OutMatrixElementTy->isTypeFloat(8, FPEncodingFloat8E5M2EXT) ||
InMatrixElementTy->isTypeFloat(8, FPEncodingFloat8E4M3EXT) ||
InMatrixElementTy->isTypeFloat(8, FPEncodingFloat8E5M2EXT) ||
OutMatrixElementTy->isTypeFloat(4, FPEncodingFloat4E2M1EXT) ||
Comment thread
YuriPlyakhin marked this conversation as resolved.
InMatrixElementTy->isTypeFloat(4, FPEncodingFloat4E2M1EXT) ||
OutMatrixElementTy->isTypeFloat(
4, internal::FPEncodingFloat4E2M1INTEL) ||
InMatrixElementTy->isTypeFloat(4,
Expand Down
18 changes: 11 additions & 7 deletions lib/SPIRV/SPIRVWriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -923,11 +923,14 @@ SPIRVFunction *LLVMToSPIRVBase::transFunctionDecl(Function *F) {
// generation.
if (!BM->isAllowedToUseExtension(ExtensionID::SPV_EXT_float8) &&
!BM->isAllowedToUseExtension(ExtensionID::SPV_INTEL_int4) &&
!BM->isAllowedToUseExtension(ExtensionID::SPV_INTEL_float4)) {
std::string ErrorStr = "One of the following extensions: "
"SPV_EXT_float8, SPV_INTEL_float4, "
"SPV_INTEL_int4 should be enabled to process "
"conversion builtins";
!BM->isAllowedToUseExtension(ExtensionID::SPV_INTEL_float4) &&
!BM->isAllowedToUseExtension(
ExtensionID::SPV_EXT_ocp_microscaling_types)) {
std::string ErrorStr =
"One of the following extensions: "
"SPV_EXT_float8, SPV_EXT_ocp_microscaling_types, "
"SPV_INTEL_float4, SPV_INTEL_int4 should be enabled to process "
"conversion builtins";
getErrorLog().checkError(false, SPIRVEC_RequiresExtension, F, ErrorStr);
}
return nullptr;
Expand Down Expand Up @@ -5717,8 +5720,9 @@ processMiniFPOrInt4Type(Type *LLVMTy, FPEncodingWrap Encoding,
unsigned TyWidth = cast<IntegerType>(ScalarTy)->getBitWidth();
unsigned VecSize = 0;

bool IsPacked =
Encoding == FPEncodingWrap::E2M1 || Encoding == FPEncodingWrap::Integer;
bool IsPacked = Encoding == FPEncodingWrap::E2M1 ||
Encoding == FPEncodingWrap::E2M1INTEL ||
Encoding == FPEncodingWrap::Integer;
if (IsPacked &&
(TyWidth == 8 || TyWidth == 16 || TyWidth == 32 || TyWidth == 64)) {
// Int4 or FP4 packed in an integer: each N-bit integer holds N/4 values.
Expand Down
1 change: 1 addition & 0 deletions lib/SPIRV/libSPIRV/SPIRVNameMapEnum.h
Original file line number Diff line number Diff line change
Expand Up @@ -705,6 +705,7 @@ template <> inline void SPIRVMap<Capability, std::string>::init() {
add(internal::CapabilityFloat4E2M1INTEL, "Float4E2M1INTEL");
add(internal::CapabilityFloat4E2M1CooperativeMatrixINTEL,
"Float4E2M1CooperativeMatrixINTEL");
add(CapabilityFloat4EXT, "Float4EXT");
add(internal::CapabilityFloatConversionsFtoFINTEL,
"FloatConversionsFtoFINTEL");
add(internal::CapabilityFloatConversionsFtoSINTEL,
Expand Down
25 changes: 16 additions & 9 deletions lib/SPIRV/libSPIRV/SPIRVType.h
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,8 @@ class SPIRVTypeFloat : public SPIRVType {
if (isTypeFloat(8, FPEncodingFloat8E4M3EXT) ||
isTypeFloat(8, FPEncodingFloat8E5M2EXT))
return ExtensionID::SPV_EXT_float8;
if (isTypeFloat(4, FPEncodingFloat4E2M1EXT))
return ExtensionID::SPV_EXT_ocp_microscaling_types;
if (isTypeFloat(4, internal::FPEncodingFloat4E2M1INTEL))
return ExtensionID::SPV_INTEL_float4;
return {};
Expand All @@ -270,6 +272,8 @@ class SPIRVTypeFloat : public SPIRVType {
} else if (isTypeFloat(8, FPEncodingFloat8E4M3EXT) ||
isTypeFloat(8, FPEncodingFloat8E5M2EXT)) {
CV.push_back(CapabilityFloat8EXT);
} else if (isTypeFloat(4, FPEncodingFloat4E2M1EXT)) {
CV.push_back(CapabilityFloat4EXT);
} else if (isTypeFloat(4, internal::FPEncodingFloat4E2M1INTEL)) {
CV.push_back(internal::CapabilityFloat4E2M1INTEL);
}
Expand Down Expand Up @@ -298,14 +302,16 @@ class SPIRVTypeFloat : public SPIRVType {
assert((BitWidth == 4 || BitWidth == 8 || BitWidth == 16 ||
BitWidth == 32 || BitWidth == 64) &&
"Invalid bit width");
assert(
(FloatingPointEncoding == FPEncodingMax ||
(BitWidth == 16 && FloatingPointEncoding == FPEncodingBFloat16KHR) ||
(BitWidth == 8 && FloatingPointEncoding == FPEncodingFloat8E4M3EXT) ||
(BitWidth == 8 && FloatingPointEncoding == FPEncodingFloat8E5M2EXT) ||
(BitWidth == 4 &&
FloatingPointEncoding == internal::FPEncodingFloat4E2M1INTEL)) &&
"Invalid floating point encoding");
bool ValidEncoding =
FloatingPointEncoding == FPEncodingMax ||
(BitWidth == 16 && FloatingPointEncoding == FPEncodingBFloat16KHR) ||
(BitWidth == 8 && FloatingPointEncoding == FPEncodingFloat8E4M3EXT) ||
(BitWidth == 8 && FloatingPointEncoding == FPEncodingFloat8E5M2EXT) ||
(BitWidth == 4 && FloatingPointEncoding == FPEncodingFloat4E2M1EXT) ||
(BitWidth == 4 &&
FloatingPointEncoding == internal::FPEncodingFloat4E2M1INTEL);
assert(ValidEncoding && "Invalid floating point encoding");
(void)ValidEncoding;
}

private:
Expand Down Expand Up @@ -1224,7 +1230,8 @@ class SPIRVTypeCooperativeMatrixKHR : public SPIRVType {
else if (CompType->isTypeFloat(8, FPEncodingFloat8E4M3EXT) ||
CompType->isTypeFloat(8, FPEncodingFloat8E5M2EXT))
CV.push_back(CapabilityFloat8CooperativeMatrixEXT);
else if (CompType->isTypeFloat(4, internal::FPEncodingFloat4E2M1INTEL))
else if (CompType->isTypeFloat(4, FPEncodingFloat4E2M1EXT) ||
CompType->isTypeFloat(4, internal::FPEncodingFloat4E2M1INTEL))
CV.push_back(internal::CapabilityFloat4E2M1CooperativeMatrixINTEL);
return CV;
}
Expand Down
2 changes: 1 addition & 1 deletion spirv-headers-tag.conf
Original file line number Diff line number Diff line change
@@ -1 +1 @@
5c50cbd25a40f8b60e44a2ccc2f1ba3c9e0d0299
575b6512579ebde466ed3dfc04e413439d14d95d
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
; Checks that both the EXT builtins (SPV_EXT_ocp_microscaling_types,
; Float4E2M1EXT encoding 4225) and the INTEL builtins (SPV_INTEL_float4,
; Float4E2M1INTEL encoding 6214) can coexist in one module with both
; extensions enabled, and that each conversion round-trips back to its own
; builtin.

; RUN: llvm-spirv %s -o %t.spv --spirv-ext=+SPV_INTEL_float4,+SPV_EXT_ocp_microscaling_types,+SPV_INTEL_int4
; RUN: llvm-spirv %t.spv -o %t.spt --to-text
; RUN: FileCheck < %t.spt %s --check-prefix=CHECK-SPIRV
; RUN: llvm-spirv %t.spv -o %t.rev.bc -r --spirv-target-env=SPV-IR
; RUN: llvm-dis %t.rev.bc -o %t.rev.ll
; RUN: FileCheck < %t.rev.ll %s --check-prefix=CHECK-LLVM

; CHECK-SPIRV-DAG: Capability Float4EXT
; CHECK-SPIRV-DAG: Capability Float4E2M1INTEL
; CHECK-SPIRV-DAG: Extension "SPV_EXT_ocp_microscaling_types"
; CHECK-SPIRV-DAG: Extension "SPV_INTEL_float4"

; CHECK-SPIRV-DAG: Name [[#ext_conv:]] "ext_conv"
; CHECK-SPIRV-DAG: Name [[#intel_conv:]] "intel_conv"

; CHECK-SPIRV-DAG: TypeFloat [[#E2M1ExtTy:]] 4 4225
; CHECK-SPIRV-DAG: TypeFloat [[#E2M1IntelTy:]] 4 6214

target datalayout = "e-p:32:32-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024"
target triple = "spir-unknown-unknown"

; CHECK-SPIRV: Function [[#]] [[#ext_conv]] [[#]]
; CHECK-SPIRV: Bitcast [[#E2M1ExtTy]] [[#ExtCast:]] [[#]]
; CHECK-SPIRV: FConvert [[#]] [[#]] [[#ExtCast]]

; CHECK-LLVM-LABEL: ext_conv
; CHECK-LLVM: call spir_func half @_Z36__builtin_spirv_ConvertE2M1ToFP16EXTi(i4 1)

define spir_func half @ext_conv() {
entry:
%r = call spir_func half @_Z36__builtin_spirv_ConvertE2M1ToFP16EXTi(i4 1)
ret half %r
}

declare dso_local spir_func half @_Z36__builtin_spirv_ConvertE2M1ToFP16EXTi(i4)

; CHECK-SPIRV: Function [[#]] [[#intel_conv]] [[#]]
; CHECK-SPIRV: Bitcast [[#E2M1IntelTy]] [[#IntelCast:]] [[#]]
; CHECK-SPIRV: FConvert [[#]] [[#]] [[#IntelCast]]

; CHECK-LLVM-LABEL: intel_conv
; CHECK-LLVM: call spir_func half @_Z38__builtin_spirv_ConvertE2M1ToFP16INTELi(i4 1)

define spir_func half @intel_conv() {
entry:
%r = call spir_func half @_Z38__builtin_spirv_ConvertE2M1ToFP16INTELi(i4 1)
ret half %r
}

declare dso_local spir_func half @_Z38__builtin_spirv_ConvertE2M1ToFP16INTELi(i4)
Loading
Loading