From 8cc8b6562be9de063a22ddf7f75d11c641779e36 Mon Sep 17 00:00:00 2001 From: Alastair Donaldson Date: Thu, 24 Jun 2021 17:24:46 +0100 Subject: [PATCH] spirv-fuzz: Add illustrative tests for new issues (#4347) Adds (currently disabled) tests related to #4345 and #4346. --- ...formation_replace_id_with_synonym_test.cpp | 235 ++++++++++++++++++ 1 file changed, 235 insertions(+) diff --git a/test/fuzz/transformation_replace_id_with_synonym_test.cpp b/test/fuzz/transformation_replace_id_with_synonym_test.cpp index 629a00eec..66c7ed095 100644 --- a/test/fuzz/transformation_replace_id_with_synonym_test.cpp +++ b/test/fuzz/transformation_replace_id_with_synonym_test.cpp @@ -1796,6 +1796,241 @@ TEST(TransformationReplaceIdWithSynonymTest, IncompatibleTypes) { .IsApplicable(context.get(), transformation_context)); } +// TODO(https://github.com/KhronosGroup/SPIRV-Tools/issues/4346): This test +// should be updated to cover more atomic operations, and once the issue is +// fixed the test should be enabled. +TEST(TransformationReplaceIdWithSynonymTest, + DISABLED_AtomicScopeAndMemorySemanticsMustBeConstant) { + // The following SPIR-V came from this GLSL, edited to add some synonyms: + // + // #version 320 es + // + // #extension GL_KHR_memory_scope_semantics : enable + // + // layout(set = 0, binding = 0) buffer Buf { + // int x; + // }; + // + // void main() { + // int tmp = atomicLoad(x, + // gl_ScopeWorkgroup, + // gl_StorageSemanticsBuffer, + // gl_SemanticsRelaxed); + // } + const std::string shader = R"( + OpCapability Shader + %1 = OpExtInstImport "GLSL.std.450" + OpMemoryModel Logical GLSL450 + OpEntryPoint GLCompute %4 "main" + OpExecutionMode %4 LocalSize 1 1 1 + OpSource ESSL 320 + OpSourceExtension "GL_KHR_memory_scope_semantics" + OpMemberDecorate %9 0 Offset 0 + OpDecorate %9 Block + OpDecorate %11 DescriptorSet 0 + OpDecorate %11 Binding 0 + %2 = OpTypeVoid + %3 = OpTypeFunction %2 + %6 = OpTypeInt 32 1 + %7 = OpTypePointer Function %6 + %9 = OpTypeStruct %6 + %10 = OpTypePointer StorageBuffer %9 + %11 = OpVariable %10 StorageBuffer + %12 = OpConstant %6 0 + %13 = OpTypePointer StorageBuffer %6 + %15 = OpConstant %6 2 + %16 = OpConstant %6 64 + %17 = OpTypeInt 32 0 + %18 = OpConstant %17 1 + %19 = OpConstant %17 0 + %20 = OpConstant %17 64 + %4 = OpFunction %2 None %3 + %5 = OpLabel + %8 = OpVariable %7 Function + %100 = OpCopyObject %6 %15 ; A non-constant version of %15 + %101 = OpCopyObject %17 %20 ; A non-constant version of %20 + %14 = OpAccessChain %13 %11 %12 + %21 = OpAtomicLoad %6 %14 %15 %20 + OpStore %8 %21 + OpReturn + OpFunctionEnd + )"; + + const auto env = SPV_ENV_UNIVERSAL_1_3; + const auto consumer = nullptr; + const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption); + spvtools::ValidatorOptions validator_options; + ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options, + kConsoleMessageConsumer)); + TransformationContext transformation_context( + MakeUnique(context.get()), validator_options); + + // Tell the fact manager that %100 and %15 are synonymous + transformation_context.GetFactManager()->AddFactDataSynonym( + MakeDataDescriptor(100, {}), MakeDataDescriptor(15, {})); + + // Tell the fact manager that %101 and %20 are synonymous + transformation_context.GetFactManager()->AddFactDataSynonym( + MakeDataDescriptor(101, {}), MakeDataDescriptor(20, {})); + + const auto& scope_operand = MakeIdUseDescriptorFromUse( + context.get(), context->get_def_use_mgr()->GetDef(21), 1); + ASSERT_FALSE(TransformationReplaceIdWithSynonym(scope_operand, 100) + .IsApplicable(context.get(), transformation_context)); + + const auto& semantics_operand = MakeIdUseDescriptorFromUse( + context.get(), context->get_def_use_mgr()->GetDef(21), 2); + ASSERT_FALSE(TransformationReplaceIdWithSynonym(semantics_operand, 101) + .IsApplicable(context.get(), transformation_context)); +} + +// TODO(https://github.com/KhronosGroup/SPIRV-Tools/issues/4345): Improve this +// test so that it covers more atomic operations, and enable the test once the +// issue is fixed. +TEST(TransformationReplaceIdWithSynonymTest, + DISABLED_SignOfAtomicScopeAndMemorySemanticsDoesNotMatter) { + // TODO(https://github.com/KhronosGroup/SPIRV-Tools/issues/4345): both the + // GLSL comment and the corresponding SPIR-V should be updated to cover a + // larger number of atomic operations. + // The following SPIR-V came from this GLSL, edited to add some synonyms: + // + // #version 320 es + // + // #extension GL_KHR_memory_scope_semantics : enable + // + // layout(set = 0, binding = 0) buffer Buf { + // int x; + // }; + // + // void main() { + // int tmp = atomicLoad(x, + // gl_ScopeWorkgroup, + // gl_StorageSemanticsBuffer, + // gl_SemanticsRelaxed); + // } + const std::string shader = R"( + OpCapability Shader + %1 = OpExtInstImport "GLSL.std.450" + OpMemoryModel Logical GLSL450 + OpEntryPoint GLCompute %4 "main" + OpExecutionMode %4 LocalSize 1 1 1 + OpSource ESSL 320 + OpSourceExtension "GL_KHR_memory_scope_semantics" + OpMemberDecorate %9 0 Offset 0 + OpDecorate %9 Block + OpDecorate %11 DescriptorSet 0 + OpDecorate %11 Binding 0 + %2 = OpTypeVoid + %3 = OpTypeFunction %2 + %6 = OpTypeInt 32 1 + %7 = OpTypePointer Function %6 + %9 = OpTypeStruct %6 + %10 = OpTypePointer StorageBuffer %9 + %11 = OpVariable %10 StorageBuffer + %12 = OpConstant %6 0 + %13 = OpTypePointer StorageBuffer %6 + %15 = OpConstant %6 2 + %16 = OpConstant %6 64 + %17 = OpTypeInt 32 0 + %100 = OpConstant %17 2 ; The same as %15, but with unsigned int type + %18 = OpConstant %17 1 + %19 = OpConstant %17 0 + %20 = OpConstant %17 64 + %101 = OpConstant %6 64 ; The same as %20, but with signed int type + %4 = OpFunction %2 None %3 + %5 = OpLabel + %8 = OpVariable %7 Function + %14 = OpAccessChain %13 %11 %12 + %21 = OpAtomicLoad %6 %14 %15 %20 + OpStore %8 %21 + OpReturn + OpFunctionEnd + )"; + + const auto env = SPV_ENV_UNIVERSAL_1_3; + const auto consumer = nullptr; + const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption); + spvtools::ValidatorOptions validator_options; + ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options, + kConsoleMessageConsumer)); + TransformationContext transformation_context( + MakeUnique(context.get()), validator_options); + + // Tell the fact manager that %100 and %15 are synonymous + transformation_context.GetFactManager()->AddFactDataSynonym( + MakeDataDescriptor(100, {}), MakeDataDescriptor(15, {})); + + // Tell the fact manager that %101 and %20 are synonymous + transformation_context.GetFactManager()->AddFactDataSynonym( + MakeDataDescriptor(101, {}), MakeDataDescriptor(20, {})); + + { + const auto& scope_operand = MakeIdUseDescriptorFromUse( + context.get(), context->get_def_use_mgr()->GetDef(21), 1); + TransformationReplaceIdWithSynonym replace_scope(scope_operand, 100); + ASSERT_TRUE( + replace_scope.IsApplicable(context.get(), transformation_context)); + ApplyAndCheckFreshIds(replace_scope, context.get(), + &transformation_context); + ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed( + context.get(), validator_options, kConsoleMessageConsumer)); + } + + { + const auto& semantics_operand = MakeIdUseDescriptorFromUse( + context.get(), context->get_def_use_mgr()->GetDef(21), 2); + TransformationReplaceIdWithSynonym replace_semantics(semantics_operand, + 101); + ASSERT_TRUE( + replace_semantics.IsApplicable(context.get(), transformation_context)); + ApplyAndCheckFreshIds(replace_semantics, context.get(), + &transformation_context); + ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed( + context.get(), validator_options, kConsoleMessageConsumer)); + } + + const std::string after_transformation = R"( + OpCapability Shader + %1 = OpExtInstImport "GLSL.std.450" + OpMemoryModel Logical GLSL450 + OpEntryPoint GLCompute %4 "main" + OpExecutionMode %4 LocalSize 1 1 1 + OpSource ESSL 320 + OpSourceExtension "GL_KHR_memory_scope_semantics" + OpMemberDecorate %9 0 Offset 0 + OpDecorate %9 Block + OpDecorate %11 DescriptorSet 0 + OpDecorate %11 Binding 0 + %2 = OpTypeVoid + %3 = OpTypeFunction %2 + %6 = OpTypeInt 32 1 + %7 = OpTypePointer Function %6 + %9 = OpTypeStruct %6 + %10 = OpTypePointer StorageBuffer %9 + %11 = OpVariable %10 StorageBuffer + %12 = OpConstant %6 0 + %13 = OpTypePointer StorageBuffer %6 + %15 = OpConstant %6 2 + %16 = OpConstant %6 64 + %17 = OpTypeInt 32 0 + %100 = OpConstant %17 2 + %18 = OpConstant %17 1 + %19 = OpConstant %17 0 + %20 = OpConstant %17 64 + %101 = OpConstant %6 64 + %4 = OpFunction %2 None %3 + %5 = OpLabel + %8 = OpVariable %7 Function + %14 = OpAccessChain %13 %11 %12 + %21 = OpAtomicLoad %6 %14 %100 %101 + OpStore %8 %21 + OpReturn + OpFunctionEnd + )"; + + ASSERT_TRUE(IsEqual(env, after_transformation, context.get())); +} + } // namespace } // namespace fuzz } // namespace spvtools