Skip to content

Commit b3d6ad9

Browse files
authored
update validator for SPV_INTEL_rounded_divide_sqrt (KhronosGroup#6717)
The SPV_INTEL_rounded_divide_sqrt extension allows an FPRoundingMode decoration on divide and square root instructions. This PR updates the validator so SPIR-V modules using this extension are not considered invalid. --------- Signed-off-by: Ben Ashbaugh <ben.ashbaugh@intel.com>
1 parent 5b52551 commit b3d6ad9

2 files changed

Lines changed: 123 additions & 4 deletions

File tree

source/val/validate_decorations.cpp

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include <vector>
2323

2424
#include "source/diagnostic.h"
25+
#include "source/latest_version_opencl_std_header.h"
2526
#include "source/opcode.h"
2627
#include "source/spirv_constant.h"
2728
#include "source/spirv_target_env.h"
@@ -1823,11 +1824,23 @@ spv_result_t CheckFPRoundingModeForShaders(ValidationState_t& vstate,
18231824

18241825
spv_result_t CheckFPRoundingModeForKernels(ValidationState_t& vstate,
18251826
const Instruction& inst) {
1826-
// Validates conversion instruction to or from a floating-point type
18271827
const auto opcode = inst.opcode();
1828-
if (opcode != spv::Op::OpConvertFToU && opcode != spv::Op::OpConvertFToS &&
1829-
opcode != spv::Op::OpConvertSToF && opcode != spv::Op::OpConvertUToF &&
1830-
opcode != spv::Op::OpFConvert) {
1828+
const bool isSqrtExtendedInstruction =
1829+
spvIsExtendedInstruction(inst.opcode()) &&
1830+
inst.ext_inst_type() == SPV_EXT_INST_TYPE_OPENCL_STD &&
1831+
inst.word(4) == OpenCLLIB::Sqrt;
1832+
if (opcode == spv::Op::OpFDiv || isSqrtExtendedInstruction) {
1833+
if (!vstate.HasCapability(spv::Capability::RoundedDivideSqrtINTEL)) {
1834+
return vstate.diag(SPV_ERROR_INVALID_ID, &inst)
1835+
<< "FPRoundingMode decoration can be applied to OpFDiv and "
1836+
"sqrt extended instructions only if the RoundedDivideSqrtINTEL "
1837+
"capability is enabled.";
1838+
}
1839+
} else if (opcode != spv::Op::OpConvertFToU &&
1840+
opcode != spv::Op::OpConvertFToS &&
1841+
opcode != spv::Op::OpConvertSToF &&
1842+
opcode != spv::Op::OpConvertUToF &&
1843+
opcode != spv::Op::OpFConvert) {
18311844
return vstate.diag(SPV_ERROR_INVALID_ID, &inst)
18321845
<< "FPRoundingMode decoration can be applied only to a conversion "
18331846
"instruction to or from a floating-point type.";

test/val/val_decoration_test.cpp

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5369,6 +5369,112 @@ TEST_F(ValidateDecorations, KernelFPRoundingModeBadMode) {
53695369
"instruction to or from a floating-point type."));
53705370
}
53715371

5372+
TEST_F(ValidateDecorations, KernelFPRoundingModeDivideBad) {
5373+
std::string spirv = R"(
5374+
OpCapability Addresses
5375+
OpCapability Kernel
5376+
OpMemoryModel Physical64 OpenCL
5377+
OpEntryPoint Kernel %kernel "test"
5378+
OpDecorate %out_float FPRoundingMode RTE
5379+
%void = OpTypeVoid
5380+
%float = OpTypeFloat 32
5381+
%functype = OpTypeFunction %void %float
5382+
%kernel = OpFunction %void None %functype
5383+
%in_float = OpFunctionParameter %float
5384+
%entry = OpLabel
5385+
%out_float = OpFDiv %float %in_float %in_float
5386+
OpReturn
5387+
OpFunctionEnd
5388+
)";
5389+
5390+
CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_0);
5391+
EXPECT_EQ(SPV_ERROR_INVALID_ID,
5392+
ValidateAndRetrieveValidationState(SPV_ENV_UNIVERSAL_1_0));
5393+
EXPECT_THAT(getDiagnosticString(),
5394+
HasSubstr("FPRoundingMode decoration can be applied to OpFDiv "
5395+
"and sqrt extended instructions only if the "
5396+
"RoundedDivideSqrtINTEL capability is enabled."));
5397+
}
5398+
5399+
TEST_F(ValidateDecorations, KernelFPRoundingModeDivideGood) {
5400+
std::string spirv = R"(
5401+
OpCapability Addresses
5402+
OpCapability Kernel
5403+
OpCapability RoundedDivideSqrtINTEL
5404+
OpExtension "SPV_INTEL_rounded_divide_sqrt"
5405+
OpMemoryModel Physical64 OpenCL
5406+
OpEntryPoint Kernel %kernel "test"
5407+
OpDecorate %out_float FPRoundingMode RTE
5408+
%void = OpTypeVoid
5409+
%float = OpTypeFloat 32
5410+
%functype = OpTypeFunction %void %float
5411+
%kernel = OpFunction %void None %functype
5412+
%in_float = OpFunctionParameter %float
5413+
%entry = OpLabel
5414+
%out_float = OpFDiv %float %in_float %in_float
5415+
OpReturn
5416+
OpFunctionEnd
5417+
)";
5418+
5419+
CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_0);
5420+
EXPECT_EQ(SPV_SUCCESS,
5421+
ValidateAndRetrieveValidationState(SPV_ENV_UNIVERSAL_1_0));
5422+
}
5423+
5424+
TEST_F(ValidateDecorations, KernelFPRoundingModeSqrtBad) {
5425+
std::string spirv = R"(
5426+
OpCapability Addresses
5427+
OpCapability Kernel
5428+
%opencl = OpExtInstImport "OpenCL.std"
5429+
OpMemoryModel Physical64 OpenCL
5430+
OpEntryPoint Kernel %kernel "test"
5431+
OpDecorate %out_float FPRoundingMode RTE
5432+
%void = OpTypeVoid
5433+
%float = OpTypeFloat 32
5434+
%functype = OpTypeFunction %void %float
5435+
%kernel = OpFunction %void None %functype
5436+
%in_float = OpFunctionParameter %float
5437+
%entry = OpLabel
5438+
%out_float = OpExtInst %float %opencl sqrt %in_float
5439+
OpReturn
5440+
OpFunctionEnd
5441+
)";
5442+
5443+
CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_0);
5444+
EXPECT_EQ(SPV_ERROR_INVALID_ID,
5445+
ValidateAndRetrieveValidationState(SPV_ENV_UNIVERSAL_1_0));
5446+
EXPECT_THAT(getDiagnosticString(),
5447+
HasSubstr("FPRoundingMode decoration can be applied to OpFDiv "
5448+
"and sqrt extended instructions only if the "
5449+
"RoundedDivideSqrtINTEL capability is enabled."));
5450+
}
5451+
5452+
TEST_F(ValidateDecorations, KernelFPRoundingModeSqrtGood) {
5453+
std::string spirv = R"(
5454+
OpCapability Addresses
5455+
OpCapability Kernel
5456+
OpCapability RoundedDivideSqrtINTEL
5457+
OpExtension "SPV_INTEL_rounded_divide_sqrt"
5458+
%opencl = OpExtInstImport "OpenCL.std"
5459+
OpMemoryModel Physical64 OpenCL
5460+
OpEntryPoint Kernel %kernel "test"
5461+
OpDecorate %out_float FPRoundingMode RTE
5462+
%void = OpTypeVoid
5463+
%float = OpTypeFloat 32
5464+
%functype = OpTypeFunction %void %float
5465+
%kernel = OpFunction %void None %functype
5466+
%in_float = OpFunctionParameter %float
5467+
%entry = OpLabel
5468+
%out_float = OpExtInst %float %opencl sqrt %in_float
5469+
OpReturn
5470+
OpFunctionEnd
5471+
)";
5472+
5473+
CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_0);
5474+
EXPECT_EQ(SPV_SUCCESS,
5475+
ValidateAndRetrieveValidationState(SPV_ENV_UNIVERSAL_1_0));
5476+
}
5477+
53725478
TEST_F(ValidateDecorations, GroupDecorateTargetsDecorationGroup) {
53735479
std::string spirv = R"(
53745480
OpCapability Shader

0 commit comments

Comments
 (0)