Skip to content

Commit

Permalink
New decorations for VCFloatControl (#684)
Browse files Browse the repository at this point in the history
Added following decorations for function VCFloatControl attributes:

DecorateFunctionRoundingModeINTEL DecorateFunctionDenormModeINTEL
DecorateFunctionFloatingPointModeINTEL

Specification can be found in intel/llvm#1611
  • Loading branch information
DmitryBushev authored Aug 26, 2020
1 parent 37ec668 commit 9891e0d
Show file tree
Hide file tree
Showing 14 changed files with 317 additions and 81 deletions.
8 changes: 4 additions & 4 deletions lib/SPIRV/PreprocessMetadata.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -270,17 +270,17 @@ void PreprocessMetadata::preprocessVectorComputeMetadata(Module *M,
.getValueAsString()
.getAsInteger(0, Mode);
spv::ExecutionMode ExecRoundMode =
VCRoundModeExecModeMap::map(getVCRoundMode(Mode));
FPRoundingModeExecModeMap::map(getFPRoundingMode(Mode));
spv::ExecutionMode ExecFloatMode =
VCFloatModeExecModeMap::map(getVCFloatMode(Mode));
FPOperationModeExecModeMap::map(getFPOperationMode(Mode));
VCFloatTypeSizeMap::foreach (
[&](VCFloatType FloatType, unsigned TargetWidth) {
EM.addOp().add(&F).add(ExecRoundMode).add(TargetWidth).done();
EM.addOp().add(&F).add(ExecFloatMode).add(TargetWidth).done();
EM.addOp()
.add(&F)
.add(VCDenormModeExecModeMap::map(
getVCDenormPreserve(Mode, FloatType)))
.add(FPDenormModeExecModeMap::map(
getFPDenormMode(Mode, FloatType)))
.add(TargetWidth)
.done();
});
Expand Down
98 changes: 83 additions & 15 deletions lib/SPIRV/SPIRVReader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3750,27 +3750,95 @@ bool SPIRVToLLVM::transVectorComputeMetadata(SPIRVFunction *BF) {
unsigned FloatControl = 0;
// RoundMode and FloatMode are always same for all types in Cm
// While Denorm could be different for double, float and half
VCRoundModeExecModeMap::foreach ([&](VCRoundMode VCRM, ExecutionMode EM) {
if (BF->getExecutionMode(EM)) {
if (isKernel(BF)) {
FPRoundingModeExecModeMap::foreach (
[&](FPRoundingMode VCRM, ExecutionMode EM) {
if (BF->getExecutionMode(EM)) {
IsVCFloatControl = true;
FloatControl |= getVCFloatControl(VCRM);
}
});
FPOperationModeExecModeMap::foreach (
[&](FPOperationMode VCFM, ExecutionMode EM) {
if (BF->getExecutionMode(EM)) {
IsVCFloatControl = true;
FloatControl |= getVCFloatControl(VCFM);
}
});
FPDenormModeExecModeMap::foreach ([&](FPDenormMode VCDM, ExecutionMode EM) {
auto ExecModes = BF->getExecutionModeRange(EM);
for (auto It = ExecModes.first; It != ExecModes.second; It++) {
IsVCFloatControl = true;
unsigned TargetWidth = (*It).second->getLiterals()[0];
VCFloatType FloatType = VCFloatTypeSizeMap::rmap(TargetWidth);
FloatControl |= getVCFloatControl(VCDM, FloatType);
}
});
} else {
if (BF->hasDecorate(DecorationFunctionRoundingModeINTEL)) {
std::vector<SPIRVDecorate const *> RoundModes =
BF->getDecorations(DecorationFunctionRoundingModeINTEL);

assert(RoundModes.size() == 3 && "Function must have precisely 3 "
"FunctionRoundingModeINTEL decoration");

auto *DecRound =
static_cast<SPIRVDecorateFunctionRoundingModeINTEL const *>(
RoundModes.at(0));
auto RoundingMode = DecRound->getRoundingMode();
#ifndef NDEBUG
for (auto *DecPreCast : RoundModes) {
auto *Dec = static_cast<SPIRVDecorateFunctionRoundingModeINTEL const *>(
DecPreCast);
assert(Dec->getRoundingMode() == RoundingMode &&
"Rounding Mode must be equal within all targets");
}
#endif
IsVCFloatControl = true;
FloatControl |= getVCFloatControl(VCRM);
FloatControl |= getVCFloatControl(RoundingMode);
}
});
VCFloatModeExecModeMap::foreach ([&](VCFloatMode VCFM, ExecutionMode EM) {
if (BF->getExecutionMode(EM)) {

if (BF->hasDecorate(DecorationFunctionDenormModeINTEL)) {
std::vector<SPIRVDecorate const *> DenormModes =
BF->getDecorations(DecorationFunctionDenormModeINTEL);
IsVCFloatControl = true;
FloatControl |= getVCFloatControl(VCFM);

for (auto DecPtr : DenormModes) {
auto DecDenorm =
static_cast<SPIRVDecorateFunctionDenormModeINTEL const *>(DecPtr);
VCFloatType FType =
VCFloatTypeSizeMap::rmap(DecDenorm->getTargetWidth());
FloatControl |= getVCFloatControl(DecDenorm->getDenormMode(), FType);
}
}
});
VCDenormModeExecModeMap::foreach ([&](VCDenormMode VCDM, ExecutionMode EM) {
auto ExecModes = BF->getExecutionModeRange(EM);
for (auto It = ExecModes.first; It != ExecModes.second; It++) {

if (BF->hasDecorate(DecorationFunctionFloatingPointModeINTEL)) {
std::vector<SPIRVDecorate const *> FloatModes =
BF->getDecorations(DecorationFunctionFloatingPointModeINTEL);

assert(FloatModes.size() == 3 &&
"Function must have precisely 3 FunctionFloatingPointModeINTEL "
"decoration");

auto *DecFlt =
static_cast<SPIRVDecorateFunctionFloatingPointModeINTEL const *>(
FloatModes.at(0));
auto FloatingMode = DecFlt->getOperationMode();
#ifndef NDEBUG
for (auto *DecPreCast : FloatModes) {
auto *Dec =
static_cast<SPIRVDecorateFunctionFloatingPointModeINTEL const *>(
DecPreCast);
assert(Dec->getOperationMode() == FloatingMode &&
"Rounding Mode must be equal within all targets");
}
#endif

IsVCFloatControl = true;
unsigned TargetWidth = (*It).second->getLiterals()[0];
VCFloatType FloatType = VCFloatTypeSizeMap::rmap(TargetWidth);
FloatControl |= getVCFloatControl(VCDM, FloatType);
FloatControl |= getVCFloatControl(FloatingMode);
}
});
}

if (IsVCFloatControl) {
Attribute Attr = Attribute::get(*Context, kVCMetadata::VCFloatControl,
std::to_string(FloatControl));
Expand Down
22 changes: 22 additions & 0 deletions lib/SPIRV/SPIRVWriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -584,6 +584,7 @@ SPIRVFunction *LLVMToSPIRV::transFunctionDecl(Function *F) {
}

void LLVMToSPIRV::transVectorComputeMetadata(Function *F) {
using namespace VectorComputeUtil;
if (!BM->isAllowedToUseExtension(ExtensionID::SPV_INTEL_vector_compute))
return;
auto BF = static_cast<SPIRVFunction *>(getTranslatedValue(F));
Expand Down Expand Up @@ -617,6 +618,27 @@ void LLVMToSPIRV::transVectorComputeMetadata(Function *F) {
BA->addDecorate(DecorationFuncParamIOKind, Kind);
}
}
if (!isKernel(F) &&
BM->isAllowedToUseExtension(ExtensionID::SPV_INTEL_float_controls2) &&
Attrs.hasFnAttribute(kVCMetadata::VCFloatControl)) {

SPIRVWord Mode = 0;
Attrs
.getAttribute(AttributeList::FunctionIndex, kVCMetadata::VCFloatControl)
.getValueAsString()
.getAsInteger(0, Mode);
VCFloatTypeSizeMap::foreach (
[&](VCFloatType FloatType, unsigned TargetWidth) {
BF->addDecorate(new SPIRVDecorateFunctionDenormModeINTEL(
BF, TargetWidth, getFPDenormMode(Mode, FloatType)));

BF->addDecorate(new SPIRVDecorateFunctionRoundingModeINTEL(
BF, TargetWidth, getFPRoundingMode(Mode)));

BF->addDecorate(new SPIRVDecorateFunctionFloatingPointModeINTEL(
BF, TargetWidth, getFPOperationMode(Mode)));
});
}
}

SPIRVValue *LLVMToSPIRV::transConstant(Value *V) {
Expand Down
48 changes: 25 additions & 23 deletions lib/SPIRV/VectorComputeUtil.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,18 +62,18 @@ enum VCFloatControlMask {
VC_FLOAT_MASK = (VC_FLOAT_MODE_IEEE | VC_FLOAT_MODE_ALT)
};

typedef SPIRVMap<VCRoundMode, VCFloatControl> VCRoundModeControlBitMap;
typedef SPIRVMap<VCFloatMode, VCFloatControl> VCFloatModeControlBitMap;
typedef SPIRVMap<FPRoundingMode, VCFloatControl> FPRoundingModeControlBitMap;
typedef SPIRVMap<FPOperationMode, VCFloatControl> FPOperationModeControlBitMap;
typedef SPIRVMap<VCFloatType, VCFloatControl> VCFloatTypeDenormMaskMap;
template <> inline void SPIRVMap<VCRoundMode, VCFloatControl>::init() {
add(RTE, VC_RTE);
add(RTP, VC_RTP);
add(RTN, VC_RTN);
add(RTZ, VC_RTZ);
template <> inline void SPIRVMap<FPRoundingMode, VCFloatControl>::init() {
add(spv::FPRoundingModeRTE, VC_RTE);
add(spv::FPRoundingModeRTP, VC_RTP);
add(spv::FPRoundingModeRTN, VC_RTN);
add(spv::FPRoundingModeRTZ, VC_RTZ);
}
template <> inline void SPIRVMap<VCFloatMode, VCFloatControl>::init() {
add(IEEE, VC_FLOAT_MODE_IEEE);
add(ALT, VC_FLOAT_MODE_ALT);
template <> inline void SPIRVMap<FPOperationMode, VCFloatControl>::init() {
add(spv::FPOperationModeIEEE, VC_FLOAT_MODE_IEEE);
add(spv::FPOperationModeALT, VC_FLOAT_MODE_ALT);
}
template <> inline void SPIRVMap<VCFloatType, VCFloatControl>::init() {
add(Double, VC_DENORM_D_ALLOW);
Expand All @@ -83,32 +83,34 @@ template <> inline void SPIRVMap<VCFloatType, VCFloatControl>::init() {

namespace VectorComputeUtil {

VCRoundMode getVCRoundMode(unsigned FloatControl) noexcept {
return VCRoundModeControlBitMap::rmap(
FPRoundingMode getFPRoundingMode(unsigned FloatControl) noexcept {
return FPRoundingModeControlBitMap::rmap(
VCFloatControl(VC_ROUND_MASK & FloatControl));
}

VCDenormMode getVCDenormPreserve(unsigned FloatControl,
VCFloatType FloatType) noexcept {
FPDenormMode getFPDenormMode(unsigned FloatControl,
VCFloatType FloatType) noexcept {
VCFloatControl DenormMask =
VCFloatTypeDenormMaskMap::map(FloatType); // 1 Bit mask
return (DenormMask == (DenormMask & FloatControl)) ? Preserve : FlushToZero;
return (DenormMask == (DenormMask & FloatControl))
? spv::FPDenormModePreserve
: spv::FPDenormModeFlushToZero;
}

VCFloatMode getVCFloatMode(unsigned FloatControl) noexcept {
return VCFloatModeControlBitMap::rmap(
FPOperationMode getFPOperationMode(unsigned FloatControl) noexcept {
return FPOperationModeControlBitMap::rmap(
VCFloatControl(VC_FLOAT_MASK & FloatControl));
}

unsigned getVCFloatControl(VCRoundMode RoundMode) noexcept {
return VCRoundModeControlBitMap::map(RoundMode);
unsigned getVCFloatControl(FPRoundingMode RoundMode) noexcept {
return FPRoundingModeControlBitMap::map(RoundMode);
}
unsigned getVCFloatControl(VCFloatMode FloatMode) noexcept {
return VCFloatModeControlBitMap::map(FloatMode);
unsigned getVCFloatControl(FPOperationMode FloatMode) noexcept {
return FPOperationModeControlBitMap::map(FloatMode);
}
unsigned getVCFloatControl(VCDenormMode DenormMode,
unsigned getVCFloatControl(FPDenormMode DenormMode,
VCFloatType FloatType) noexcept {
if (DenormMode == Preserve)
if (DenormMode == spv::FPDenormModePreserve)
return VCFloatTypeDenormMaskMap::map(FloatType);
return VC_DENORM_FTZ;
}
Expand Down
63 changes: 24 additions & 39 deletions lib/SPIRV/VectorComputeUtil.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,40 +52,28 @@ namespace VectorComputeUtil {
//
///////////////////////////////////////////////////////////////////////////////

enum VCRoundMode {
RTE, // Round to nearest or even
RTP, // Round towards +ve inf
RTN, // Round towards -ve inf
RTZ, // Round towards zero
};
enum VCDenormMode {
FlushToZero,
Preserve,
};
enum VCFloatMode {
IEEE, // Single precision float IEEE mode
ALT, // Single precision float ALT mode
};
enum VCFloatType {
Double,
Float,
Half,
};

VCRoundMode getVCRoundMode(unsigned FloatControl) noexcept;
VCDenormMode getVCDenormPreserve(unsigned FloatControl,
VCFloatType FloatType) noexcept;
VCFloatMode getVCFloatMode(unsigned FloatControl) noexcept;
FPRoundingMode getFPRoundingMode(unsigned FloatControl) noexcept;
FPDenormMode getFPDenormMode(unsigned FloatControl,
VCFloatType FloatType) noexcept;
FPOperationMode getFPOperationMode(unsigned FloatControl) noexcept;

unsigned getVCFloatControl(VCRoundMode RoundMode) noexcept;
unsigned getVCFloatControl(VCFloatMode FloatMode) noexcept;
unsigned getVCFloatControl(VCDenormMode DenormMode,
unsigned getVCFloatControl(FPRoundingMode RoundMode) noexcept;
unsigned getVCFloatControl(FPOperationMode FloatMode) noexcept;
unsigned getVCFloatControl(FPDenormMode DenormMode,
VCFloatType FloatType) noexcept;

typedef SPIRV::SPIRVMap<VCRoundMode, spv::ExecutionMode> VCRoundModeExecModeMap;
typedef SPIRV::SPIRVMap<VCFloatMode, spv::ExecutionMode> VCFloatModeExecModeMap;
typedef SPIRV::SPIRVMap<VCDenormMode, spv::ExecutionMode>
VCDenormModeExecModeMap;
typedef SPIRV::SPIRVMap<FPRoundingMode, spv::ExecutionMode>
FPRoundingModeExecModeMap;
typedef SPIRV::SPIRVMap<FPOperationMode, spv::ExecutionMode>
FPOperationModeExecModeMap;
typedef SPIRV::SPIRVMap<FPDenormMode, spv::ExecutionMode>
FPDenormModeExecModeMap;
typedef SPIRV::SPIRVMap<VCFloatType, unsigned> VCFloatTypeSizeMap;

///////////////////////////////////////////////////////////////////////////////
Expand Down Expand Up @@ -127,24 +115,21 @@ const static char VCSIMTCall[] = "VCSIMTCall";

namespace SPIRV {
template <>
inline void
SPIRVMap<VectorComputeUtil::VCRoundMode, spv::ExecutionMode>::init() {
add(VectorComputeUtil::RTE, spv::ExecutionModeRoundingModeRTE);
add(VectorComputeUtil::RTZ, spv::ExecutionModeRoundingModeRTZ);
add(VectorComputeUtil::RTP, spv::ExecutionModeRoundingModeRTPINTEL);
add(VectorComputeUtil::RTN, spv::ExecutionModeRoundingModeRTNINTEL);
inline void SPIRVMap<spv::FPRoundingMode, spv::ExecutionMode>::init() {
add(spv::FPRoundingModeRTE, spv::ExecutionModeRoundingModeRTE);
add(spv::FPRoundingModeRTZ, spv::ExecutionModeRoundingModeRTZ);
add(spv::FPRoundingModeRTP, spv::ExecutionModeRoundingModeRTPINTEL);
add(spv::FPRoundingModeRTN, spv::ExecutionModeRoundingModeRTNINTEL);
}
template <>
inline void
SPIRVMap<VectorComputeUtil::VCDenormMode, spv::ExecutionMode>::init() {
add(VectorComputeUtil::FlushToZero, spv::ExecutionModeDenormFlushToZero);
add(VectorComputeUtil::Preserve, spv::ExecutionModeDenormPreserve);
inline void SPIRVMap<spv::FPDenormMode, spv::ExecutionMode>::init() {
add(spv::FPDenormModeFlushToZero, spv::ExecutionModeDenormFlushToZero);
add(spv::FPDenormModePreserve, spv::ExecutionModeDenormPreserve);
}
template <>
inline void
SPIRVMap<VectorComputeUtil::VCFloatMode, spv::ExecutionMode>::init() {
add(VectorComputeUtil::IEEE, spv::ExecutionModeFloatingPointModeIEEEINTEL);
add(VectorComputeUtil::ALT, spv::ExecutionModeFloatingPointModeALTINTEL);
inline void SPIRVMap<spv::FPOperationMode, spv::ExecutionMode>::init() {
add(spv::FPOperationModeIEEE, spv::ExecutionModeFloatingPointModeIEEEINTEL);
add(spv::FPOperationModeALT, spv::ExecutionModeFloatingPointModeALTINTEL);
}
template <>
inline void SPIRVMap<VectorComputeUtil::VCFloatType, unsigned>::init() {
Expand Down
9 changes: 9 additions & 0 deletions lib/SPIRV/libSPIRV/SPIRVDecorate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,15 @@ SPIRVDecorateGeneric::SPIRVDecorateGeneric(Op OC, SPIRVWord WC,
updateModuleVersion();
}

SPIRVDecorateGeneric::SPIRVDecorateGeneric(Op OC, SPIRVWord WC,
Decoration TheDec,
SPIRVEntry *TheTarget, SPIRVWord V1,
SPIRVWord V2)
: SPIRVDecorateGeneric(OC, WC, TheDec, TheTarget, V1) {
Literals.push_back(V2);
validate();
updateModuleVersion();
}
SPIRVDecorateGeneric::SPIRVDecorateGeneric(Op OC)
: SPIRVAnnotationGeneric(OC), Dec(DecorationRelaxedPrecision),
Owner(nullptr) {}
Expand Down
Loading

0 comments on commit 9891e0d

Please sign in to comment.