spirv-fuzz: Add illustrative tests for new issues (#4347)

Adds (currently disabled) tests related to #4345 and #4346.
diff --git a/test/fuzz/transformation_replace_id_with_synonym_test.cpp b/test/fuzz/transformation_replace_id_with_synonym_test.cpp
index 629a00e..66c7ed0 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 @@
                    .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<FactManager>(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<FactManager>(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