| // Copyright (c) 2018 Google LLC | |
| // | |
| // Licensed under the Apache License, Version 2.0 (the "License"); | |
| // you may not use this file except in compliance with the License. | |
| // You may obtain a copy of the License at | |
| // | |
| // http://www.apache.org/licenses/LICENSE-2.0 | |
| // | |
| // Unless required by applicable law or agreed to in writing, software | |
| // distributed under the License is distributed on an "AS IS" BASIS, | |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| // See the License for the specific language governing permissions and | |
| // limitations under the License. | |
| #include "assembly_builder.h" | |
| #include "pass_fixture.h" | |
| #include "pass_utils.h" | |
| namespace { | |
| using namespace spvtools; | |
| using UpgradeMemoryModelTest = opt::PassTest<::testing::Test>; | |
| TEST_F(UpgradeMemoryModelTest, InvalidMemoryModelOpenCL) { | |
| const std::string text = R"( | |
| ; CHECK: OpMemoryModel Logical OpenCL | |
| OpCapability Kernel | |
| OpCapability Linkage | |
| OpMemoryModel Logical OpenCL | |
| )"; | |
| SinglePassRunAndMatch<opt::UpgradeMemoryModel>(text, true); | |
| } | |
| TEST_F(UpgradeMemoryModelTest, InvalidMemoryModelVulkan) { | |
| const std::string text = R"( | |
| ; CHECK: OpMemoryModel Logical Vulkan | |
| OpCapability Shader | |
| OpCapability Linkage | |
| OpCapability VulkanMemoryModel | |
| OpExtension "SPV_KHR_vulkan_memory_model" | |
| OpMemoryModel Logical Vulkan | |
| )"; | |
| SinglePassRunAndMatch<opt::UpgradeMemoryModel>(text, true); | |
| } | |
| TEST_F(UpgradeMemoryModelTest, JustMemoryModel) { | |
| const std::string text = R"( | |
| ; CHECK: OpCapability VulkanMemoryModel | |
| ; CHECK: OpExtension "SPV_KHR_vulkan_memory_model" | |
| ; CHECK: OpMemoryModel Logical Vulkan | |
| OpCapability Shader | |
| OpCapability Linkage | |
| OpMemoryModel Logical GLSL450 | |
| )"; | |
| SinglePassRunAndMatch<opt::UpgradeMemoryModel>(text, true); | |
| } | |
| TEST_F(UpgradeMemoryModelTest, RemoveDecorations) { | |
| const std::string text = R"( | |
| ; CHECK-NOT: OpDecorate | |
| OpCapability Shader | |
| OpCapability Linkage | |
| OpMemoryModel Logical GLSL450 | |
| OpDecorate %var Volatile | |
| OpDecorate %var Coherent | |
| %int = OpTypeInt 32 0 | |
| %ptr_int_Uniform = OpTypePointer Uniform %int | |
| %var = OpVariable %ptr_int_Uniform Uniform | |
| )"; | |
| SinglePassRunAndMatch<opt::UpgradeMemoryModel>(text, true); | |
| } | |
| TEST_F(UpgradeMemoryModelTest, WorkgroupVariable) { | |
| const std::string text = R"( | |
| ; CHECK: [[scope:%\w+]] = OpConstant {{%\w+}} 2 | |
| ; CHECK: OpLoad {{%\w+}} {{%\w+}} MakePointerVisible|NonPrivatePointer [[scope]] | |
| ; CHECK: OpStore {{%\w+}} {{%\w+}} MakePointerAvailable|NonPrivatePointer [[scope]] | |
| OpCapability Shader | |
| OpCapability Linkage | |
| OpMemoryModel Logical GLSL450 | |
| %void = OpTypeVoid | |
| %int = OpTypeInt 32 0 | |
| %ptr_int_Workgroup = OpTypePointer Workgroup %int | |
| %var = OpVariable %ptr_int_Workgroup Workgroup | |
| %func_ty = OpTypeFunction %void | |
| %func = OpFunction %void None %func_ty | |
| %1 = OpLabel | |
| %ld = OpLoad %int %var | |
| OpStore %var %ld | |
| OpReturn | |
| OpFunctionEnd | |
| )"; | |
| SinglePassRunAndMatch<opt::UpgradeMemoryModel>(text, true); | |
| } | |
| TEST_F(UpgradeMemoryModelTest, WorkgroupFunctionParameter) { | |
| const std::string text = R"( | |
| ; CHECK: [[scope:%\w+]] = OpConstant {{%\w+}} 2 | |
| ; CHECK: OpLoad {{%\w+}} {{%\w+}} MakePointerVisible|NonPrivatePointer [[scope]] | |
| ; CHECK: OpStore {{%\w+}} {{%\w+}} MakePointerAvailable|NonPrivatePointer [[scope]] | |
| OpCapability Shader | |
| OpCapability Linkage | |
| OpMemoryModel Logical GLSL450 | |
| %void = OpTypeVoid | |
| %int = OpTypeInt 32 0 | |
| %ptr_int_Workgroup = OpTypePointer Workgroup %int | |
| %func_ty = OpTypeFunction %void %ptr_int_Workgroup | |
| %func = OpFunction %void None %func_ty | |
| %param = OpFunctionParameter %ptr_int_Workgroup | |
| %1 = OpLabel | |
| %ld = OpLoad %int %param | |
| OpStore %param %ld | |
| OpReturn | |
| OpFunctionEnd | |
| )"; | |
| SinglePassRunAndMatch<opt::UpgradeMemoryModel>(text, true); | |
| } | |
| TEST_F(UpgradeMemoryModelTest, SimpleUniformVariable) { | |
| const std::string text = R"( | |
| ; CHECK-NOT: OpDecorate | |
| ; CHECK: [[scope:%\w+]] = OpConstant {{%\w+}} 5 | |
| ; CHECK: OpLoad {{%\w+}} {{%\w+}} Volatile|MakePointerVisible|NonPrivatePointer [[scope]] | |
| ; CHECK: OpStore {{%\w+}} {{%\w+}} Volatile|MakePointerAvailable|NonPrivatePointer [[scope]] | |
| OpCapability Shader | |
| OpCapability Linkage | |
| OpMemoryModel Logical GLSL450 | |
| OpDecorate %var Coherent | |
| OpDecorate %var Volatile | |
| %void = OpTypeVoid | |
| %int = OpTypeInt 32 0 | |
| %ptr_int_Uniform = OpTypePointer Uniform %int | |
| %var = OpVariable %ptr_int_Uniform Uniform | |
| %func_ty = OpTypeFunction %void | |
| %func = OpFunction %void None %func_ty | |
| %1 = OpLabel | |
| %ld = OpLoad %int %var | |
| OpStore %var %ld | |
| OpReturn | |
| OpFunctionEnd | |
| )"; | |
| SinglePassRunAndMatch<opt::UpgradeMemoryModel>(text, true); | |
| } | |
| TEST_F(UpgradeMemoryModelTest, SimpleUniformFunctionParameter) { | |
| const std::string text = R"( | |
| ; CHECK-NOT: OpDecorate | |
| ; CHECK: [[scope:%\w+]] = OpConstant {{%\w+}} 5 | |
| ; CHECK: OpLoad {{%\w+}} {{%\w+}} Volatile|MakePointerVisible|NonPrivatePointer [[scope]] | |
| ; CHECK: OpStore {{%\w+}} {{%\w+}} Volatile|MakePointerAvailable|NonPrivatePointer [[scope]] | |
| OpCapability Shader | |
| OpCapability Linkage | |
| OpMemoryModel Logical GLSL450 | |
| OpDecorate %param Coherent | |
| OpDecorate %param Volatile | |
| %void = OpTypeVoid | |
| %int = OpTypeInt 32 0 | |
| %ptr_int_Uniform = OpTypePointer Uniform %int | |
| %func_ty = OpTypeFunction %void %ptr_int_Uniform | |
| %func = OpFunction %void None %func_ty | |
| %param = OpFunctionParameter %ptr_int_Uniform | |
| %1 = OpLabel | |
| %ld = OpLoad %int %param | |
| OpStore %param %ld | |
| OpReturn | |
| OpFunctionEnd | |
| )"; | |
| SinglePassRunAndMatch<opt::UpgradeMemoryModel>(text, true); | |
| } | |
| TEST_F(UpgradeMemoryModelTest, SimpleUniformVariableOnlyVolatile) { | |
| const std::string text = R"( | |
| ; CHECK-NOT: OpDecorate | |
| ; CHECK-NOT: OpConstant | |
| ; CHECK: OpLoad {{%\w+}} {{%\w+}} Volatile | |
| ; CHECK: OpStore {{%\w+}} {{%\w+}} Volatile | |
| OpCapability Shader | |
| OpCapability Linkage | |
| OpMemoryModel Logical GLSL450 | |
| OpDecorate %var Volatile | |
| %void = OpTypeVoid | |
| %int = OpTypeInt 32 0 | |
| %ptr_int_Uniform = OpTypePointer Uniform %int | |
| %var = OpVariable %ptr_int_Uniform Uniform | |
| %func_ty = OpTypeFunction %void | |
| %func = OpFunction %void None %func_ty | |
| %1 = OpLabel | |
| %ld = OpLoad %int %var | |
| OpStore %var %ld | |
| OpReturn | |
| OpFunctionEnd | |
| )"; | |
| SinglePassRunAndMatch<opt::UpgradeMemoryModel>(text, true); | |
| } | |
| TEST_F(UpgradeMemoryModelTest, SimpleUniformVariableCopied) { | |
| const std::string text = R"( | |
| ; CHECK-NOT: OpDecorate | |
| ; CHECK: [[scope:%\w+]] = OpConstant {{%\w+}} 5 | |
| ; CHECK: OpLoad {{%\w+}} {{%\w+}} Volatile|MakePointerVisible|NonPrivatePointer [[scope]] | |
| ; CHECK: OpStore {{%\w+}} {{%\w+}} Volatile|MakePointerAvailable|NonPrivatePointer [[scope]] | |
| OpCapability Shader | |
| OpCapability Linkage | |
| OpMemoryModel Logical GLSL450 | |
| OpDecorate %var Coherent | |
| OpDecorate %var Volatile | |
| %void = OpTypeVoid | |
| %int = OpTypeInt 32 0 | |
| %ptr_int_Uniform = OpTypePointer Uniform %int | |
| %var = OpVariable %ptr_int_Uniform Uniform | |
| %func_ty = OpTypeFunction %void | |
| %func = OpFunction %void None %func_ty | |
| %1 = OpLabel | |
| %copy = OpCopyObject %ptr_int_Uniform %var | |
| %ld = OpLoad %int %copy | |
| OpStore %copy %ld | |
| OpReturn | |
| OpFunctionEnd | |
| )"; | |
| SinglePassRunAndMatch<opt::UpgradeMemoryModel>(text, true); | |
| } | |
| TEST_F(UpgradeMemoryModelTest, SimpleUniformFunctionParameterCopied) { | |
| const std::string text = R"( | |
| ; CHECK-NOT: OpDecorate | |
| ; CHECK: [[scope:%\w+]] = OpConstant {{%\w+}} 5 | |
| ; CHECK: OpLoad {{%\w+}} {{%\w+}} Volatile|MakePointerVisible|NonPrivatePointer [[scope]] | |
| ; CHECK: OpStore {{%\w+}} {{%\w+}} Volatile|MakePointerAvailable|NonPrivatePointer [[scope]] | |
| OpCapability Shader | |
| OpCapability Linkage | |
| OpMemoryModel Logical GLSL450 | |
| OpDecorate %param Coherent | |
| OpDecorate %param Volatile | |
| %void = OpTypeVoid | |
| %int = OpTypeInt 32 0 | |
| %ptr_int_Uniform = OpTypePointer Uniform %int | |
| %func_ty = OpTypeFunction %void %ptr_int_Uniform | |
| %func = OpFunction %void None %func_ty | |
| %param = OpFunctionParameter %ptr_int_Uniform | |
| %1 = OpLabel | |
| %copy = OpCopyObject %ptr_int_Uniform %param | |
| %ld = OpLoad %int %copy | |
| %copy2 = OpCopyObject %ptr_int_Uniform %param | |
| OpStore %copy2 %ld | |
| OpReturn | |
| OpFunctionEnd | |
| )"; | |
| SinglePassRunAndMatch<opt::UpgradeMemoryModel>(text, true); | |
| } | |
| TEST_F(UpgradeMemoryModelTest, SimpleUniformVariableAccessChain) { | |
| const std::string text = R"( | |
| ; CHECK-NOT: OpDecorate | |
| ; CHECK: [[scope:%\w+]] = OpConstant {{%\w+}} 5 | |
| ; CHECK: OpLoad {{%\w+}} {{%\w+}} Volatile|MakePointerVisible|NonPrivatePointer [[scope]] | |
| ; CHECK: OpStore {{%\w+}} {{%\w+}} Volatile|MakePointerAvailable|NonPrivatePointer [[scope]] | |
| OpCapability Shader | |
| OpCapability Linkage | |
| OpMemoryModel Logical GLSL450 | |
| OpDecorate %var Coherent | |
| OpDecorate %var Volatile | |
| %void = OpTypeVoid | |
| %int = OpTypeInt 32 0 | |
| %int0 = OpConstant %int 0 | |
| %int3 = OpConstant %int 3 | |
| %int_array_3 = OpTypeArray %int %int3 | |
| %ptr_intarray_Uniform = OpTypePointer Uniform %int_array_3 | |
| %ptr_int_Uniform = OpTypePointer Uniform %int | |
| %var = OpVariable %ptr_intarray_Uniform Uniform | |
| %func_ty = OpTypeFunction %void | |
| %func = OpFunction %void None %func_ty | |
| %1 = OpLabel | |
| %gep = OpAccessChain %ptr_int_Uniform %var %int0 | |
| %ld = OpLoad %int %gep | |
| OpStore %gep %ld | |
| OpReturn | |
| OpFunctionEnd | |
| )"; | |
| SinglePassRunAndMatch<opt::UpgradeMemoryModel>(text, true); | |
| } | |
| TEST_F(UpgradeMemoryModelTest, SimpleUniformFunctionParameterAccessChain) { | |
| const std::string text = R"( | |
| ; CHECK-NOT: OpDecorate | |
| ; CHECK: [[scope:%\w+]] = OpConstant {{%\w+}} 5 | |
| ; CHECK: OpLoad {{%\w+}} {{%\w+}} Volatile|MakePointerVisible|NonPrivatePointer [[scope]] | |
| ; CHECK: OpStore {{%\w+}} {{%\w+}} Volatile|MakePointerAvailable|NonPrivatePointer [[scope]] | |
| OpCapability Shader | |
| OpCapability Linkage | |
| OpMemoryModel Logical GLSL450 | |
| OpDecorate %param Coherent | |
| OpDecorate %param Volatile | |
| %void = OpTypeVoid | |
| %int = OpTypeInt 32 0 | |
| %int0 = OpConstant %int 0 | |
| %int3 = OpConstant %int 3 | |
| %int_array_3 = OpTypeArray %int %int3 | |
| %ptr_intarray_Uniform = OpTypePointer Uniform %int_array_3 | |
| %ptr_int_Uniform = OpTypePointer Uniform %int | |
| %func_ty = OpTypeFunction %void %ptr_intarray_Uniform | |
| %func = OpFunction %void None %func_ty | |
| %param = OpFunctionParameter %ptr_intarray_Uniform | |
| %1 = OpLabel | |
| %ld_gep = OpAccessChain %ptr_int_Uniform %param %int0 | |
| %ld = OpLoad %int %ld_gep | |
| %st_gep = OpAccessChain %ptr_int_Uniform %param %int0 | |
| OpStore %st_gep %ld | |
| OpReturn | |
| OpFunctionEnd | |
| )"; | |
| SinglePassRunAndMatch<opt::UpgradeMemoryModel>(text, true); | |
| } | |
| TEST_F(UpgradeMemoryModelTest, VariablePointerSelect) { | |
| const std::string text = R"( | |
| ; CHECK-NOT: OpDecorate | |
| ; CHECK: [[scope:%\w+]] = OpConstant {{%\w+}} 5 | |
| ; CHECK: OpLoad {{%\w+}} {{%\w+}} Volatile|MakePointerVisible|NonPrivatePointer [[scope]] | |
| ; CHECK: OpStore {{%\w+}} {{%\w+}} Volatile|MakePointerAvailable|NonPrivatePointer [[scope]] | |
| OpCapability Shader | |
| OpCapability Linkage | |
| OpCapability VariablePointers | |
| OpExtension "SPV_KHR_variable_pointers" | |
| OpMemoryModel Logical GLSL450 | |
| OpDecorate %var Coherent | |
| OpDecorate %var Volatile | |
| %void = OpTypeVoid | |
| %int = OpTypeInt 32 0 | |
| %bool = OpTypeBool | |
| %true = OpConstantTrue %bool | |
| %ptr_int_StorageBuffer = OpTypePointer StorageBuffer %int | |
| %null = OpConstantNull %ptr_int_StorageBuffer | |
| %var = OpVariable %ptr_int_StorageBuffer StorageBuffer | |
| %func_ty = OpTypeFunction %void | |
| %func = OpFunction %void None %func_ty | |
| %1 = OpLabel | |
| %select = OpSelect %ptr_int_StorageBuffer %true %var %null | |
| %ld = OpLoad %int %select | |
| OpStore %var %ld | |
| OpReturn | |
| OpFunctionEnd | |
| )"; | |
| SinglePassRunAndMatch<opt::UpgradeMemoryModel>(text, true); | |
| } | |
| TEST_F(UpgradeMemoryModelTest, VariablePointerSelectConservative) { | |
| const std::string text = R"( | |
| ; CHECK-NOT: OpDecorate | |
| ; CHECK: [[scope:%\w+]] = OpConstant {{%\w+}} 5 | |
| ; CHECK: OpLoad {{%\w+}} {{%\w+}} Volatile|MakePointerVisible|NonPrivatePointer [[scope]] | |
| ; CHECK: OpStore {{%\w+}} {{%\w+}} Volatile|MakePointerAvailable|NonPrivatePointer [[scope]] | |
| OpCapability Shader | |
| OpCapability Linkage | |
| OpCapability VariablePointers | |
| OpExtension "SPV_KHR_variable_pointers" | |
| OpMemoryModel Logical GLSL450 | |
| OpDecorate %var1 Coherent | |
| OpDecorate %var2 Volatile | |
| %void = OpTypeVoid | |
| %int = OpTypeInt 32 0 | |
| %bool = OpTypeBool | |
| %true = OpConstantTrue %bool | |
| %ptr_int_StorageBuffer = OpTypePointer StorageBuffer %int | |
| %var1 = OpVariable %ptr_int_StorageBuffer StorageBuffer | |
| %var2 = OpVariable %ptr_int_StorageBuffer StorageBuffer | |
| %func_ty = OpTypeFunction %void | |
| %func = OpFunction %void None %func_ty | |
| %1 = OpLabel | |
| %select = OpSelect %ptr_int_StorageBuffer %true %var1 %var2 | |
| %ld = OpLoad %int %select | |
| OpStore %select %ld | |
| OpReturn | |
| OpFunctionEnd | |
| )"; | |
| SinglePassRunAndMatch<opt::UpgradeMemoryModel>(text, true); | |
| } | |
| TEST_F(UpgradeMemoryModelTest, VariablePointerIncrement) { | |
| const std::string text = R"( | |
| ; CHECK-NOT: OpDecorate {{%\w+}} Coherent | |
| ; CHECK: [[scope:%\w+]] = OpConstant {{%\w+}} 5 | |
| ; CHECK: OpLoad {{%\w+}} {{%\w+}} MakePointerVisible|NonPrivatePointer [[scope]] | |
| ; CHECK: OpStore {{%\w+}} {{%\w+}} MakePointerAvailable|NonPrivatePointer [[scope]] | |
| OpCapability Shader | |
| OpCapability Linkage | |
| OpCapability VariablePointers | |
| OpExtension "SPV_KHR_variable_pointers" | |
| OpMemoryModel Logical GLSL450 | |
| OpDecorate %param Coherent | |
| OpDecorate %ptr_int_StorageBuffer ArrayStride 4 | |
| %void = OpTypeVoid | |
| %bool = OpTypeBool | |
| %int = OpTypeInt 32 0 | |
| %int0 = OpConstant %int 0 | |
| %int1 = OpConstant %int 1 | |
| %int10 = OpConstant %int 10 | |
| %ptr_int_StorageBuffer = OpTypePointer StorageBuffer %int | |
| %func_ty = OpTypeFunction %void %ptr_int_StorageBuffer | |
| %func = OpFunction %void None %func_ty | |
| %param = OpFunctionParameter %ptr_int_StorageBuffer | |
| %1 = OpLabel | |
| OpBranch %2 | |
| %2 = OpLabel | |
| %phi = OpPhi %ptr_int_StorageBuffer %param %1 %ptr_next %2 | |
| %iv = OpPhi %int %int0 %1 %inc %2 | |
| %inc = OpIAdd %int %iv %int1 | |
| %ptr_next = OpPtrAccessChain %ptr_int_StorageBuffer %phi %int1 | |
| %cmp = OpIEqual %bool %iv %int10 | |
| OpLoopMerge %3 %2 None | |
| OpBranchConditional %cmp %3 %2 | |
| %3 = OpLabel | |
| %ld = OpLoad %int %phi | |
| OpStore %phi %ld | |
| OpReturn | |
| OpFunctionEnd | |
| )"; | |
| SinglePassRunAndMatch<opt::UpgradeMemoryModel>(text, true); | |
| } | |
| TEST_F(UpgradeMemoryModelTest, CoherentStructElement) { | |
| const std::string text = R"( | |
| ; CHECK-NOT: OpMemberDecorate | |
| ; CHECK: [[scope:%\w+]] = OpConstant {{%\w+}} 5 | |
| ; CHECK: OpLoad {{%\w+}} {{%\w+}} MakePointerVisible|NonPrivatePointer [[scope]] | |
| ; CHECK: OpStore {{%\w+}} {{%\w+}} MakePointerAvailable|NonPrivatePointer [[scope]] | |
| OpCapability Shader | |
| OpCapability Linkage | |
| OpExtension "SPV_KHR_storage_buffer_storage_class" | |
| OpMemoryModel Logical GLSL450 | |
| OpMemberDecorate %struct 0 Coherent | |
| %void = OpTypeVoid | |
| %int = OpTypeInt 32 0 | |
| %int0 = OpConstant %int 0 | |
| %struct = OpTypeStruct %int | |
| %ptr_struct_StorageBuffer = OpTypePointer StorageBuffer %struct | |
| %ptr_int_StorageBuffer = OpTypePointer StorageBuffer %int | |
| %func_ty = OpTypeFunction %void %ptr_struct_StorageBuffer | |
| %func = OpFunction %void None %func_ty | |
| %param = OpFunctionParameter %ptr_struct_StorageBuffer | |
| %1 = OpLabel | |
| %gep = OpAccessChain %ptr_int_StorageBuffer %param %int0 | |
| %ld = OpLoad %int %gep | |
| OpStore %gep %ld | |
| OpReturn | |
| OpFunctionEnd | |
| )"; | |
| SinglePassRunAndMatch<opt::UpgradeMemoryModel>(text, true); | |
| } | |
| TEST_F(UpgradeMemoryModelTest, CoherentElementFullStructAccess) { | |
| const std::string text = R"( | |
| ; CHECK-NOT: OpMemberDecorate | |
| ; CHECK: [[scope:%\w+]] = OpConstant {{%\w+}} 5 | |
| ; CHECK: OpLoad {{%\w+}} {{%\w+}} MakePointerVisible|NonPrivatePointer [[scope]] | |
| ; CHECK: OpStore {{%\w+}} {{%\w+}} MakePointerAvailable|NonPrivatePointer [[scope]] | |
| OpCapability Shader | |
| OpCapability Linkage | |
| OpExtension "SPV_KHR_storage_buffer_storage_class" | |
| OpMemoryModel Logical GLSL450 | |
| OpMemberDecorate %struct 0 Coherent | |
| %void = OpTypeVoid | |
| %int = OpTypeInt 32 0 | |
| %struct = OpTypeStruct %int | |
| %ptr_struct_StorageBuffer = OpTypePointer StorageBuffer %struct | |
| %func_ty = OpTypeFunction %void %ptr_struct_StorageBuffer | |
| %func = OpFunction %void None %func_ty | |
| %param = OpFunctionParameter %ptr_struct_StorageBuffer | |
| %1 = OpLabel | |
| %ld = OpLoad %struct %param | |
| OpStore %param %ld | |
| OpReturn | |
| OpFunctionEnd | |
| )"; | |
| SinglePassRunAndMatch<opt::UpgradeMemoryModel>(text, true); | |
| } | |
| TEST_F(UpgradeMemoryModelTest, CoherentElementNotAccessed) { | |
| const std::string text = R"( | |
| ; CHECK-NOT: OpMemberDecorate | |
| ; CHECK-NOT: MakePointerAvailable | |
| ; CHECK-NOT: NonPrivatePointer | |
| ; CHECK-NOT: MakePointerVisible | |
| OpCapability Shader | |
| OpCapability Linkage | |
| OpExtension "SPV_KHR_storage_buffer_storage_class" | |
| OpMemoryModel Logical GLSL450 | |
| OpMemberDecorate %struct 1 Coherent | |
| %void = OpTypeVoid | |
| %int = OpTypeInt 32 0 | |
| %int0 = OpConstant %int 0 | |
| %struct = OpTypeStruct %int %int | |
| %ptr_struct_StorageBuffer = OpTypePointer StorageBuffer %struct | |
| %ptr_int_StorageBuffer = OpTypePointer StorageBuffer %int | |
| %func_ty = OpTypeFunction %void %ptr_struct_StorageBuffer | |
| %func = OpFunction %void None %func_ty | |
| %param = OpFunctionParameter %ptr_struct_StorageBuffer | |
| %1 = OpLabel | |
| %gep = OpAccessChain %ptr_int_StorageBuffer %param %int0 | |
| %ld = OpLoad %int %gep | |
| OpStore %gep %ld | |
| OpReturn | |
| OpFunctionEnd | |
| )"; | |
| SinglePassRunAndMatch<opt::UpgradeMemoryModel>(text, true); | |
| } | |
| TEST_F(UpgradeMemoryModelTest, MultiIndexAccessCoherent) { | |
| const std::string text = R"( | |
| ; CHECK-NOT: OpMemberDecorate | |
| ; CHECK: [[scope:%\w+]] = OpConstant {{%\w+}} 5 | |
| ; CHECK: OpLoad {{%\w+}} {{%\w+}} MakePointerVisible|NonPrivatePointer [[scope]] | |
| ; CHECK: OpStore {{%\w+}} {{%\w+}} MakePointerAvailable|NonPrivatePointer [[scope]] | |
| OpCapability Shader | |
| OpCapability Linkage | |
| OpExtension "SPV_KHR_storage_buffer_storage_class" | |
| OpMemoryModel Logical GLSL450 | |
| OpMemberDecorate %inner 1 Coherent | |
| %void = OpTypeVoid | |
| %int = OpTypeInt 32 0 | |
| %int0 = OpConstant %int 0 | |
| %int1 = OpConstant %int 1 | |
| %inner = OpTypeStruct %int %int | |
| %middle = OpTypeStruct %inner | |
| %outer = OpTypeStruct %middle %middle | |
| %ptr_outer_StorageBuffer = OpTypePointer StorageBuffer %outer | |
| %ptr_int_StorageBuffer = OpTypePointer StorageBuffer %int | |
| %func_ty = OpTypeFunction %void %ptr_outer_StorageBuffer | |
| %func = OpFunction %void None %func_ty | |
| %param = OpFunctionParameter %ptr_outer_StorageBuffer | |
| %1 = OpLabel | |
| %ld_gep = OpInBoundsAccessChain %ptr_int_StorageBuffer %param %int0 %int0 %int1 | |
| %ld = OpLoad %int %ld_gep | |
| %st_gep = OpInBoundsAccessChain %ptr_int_StorageBuffer %param %int1 %int0 %int1 | |
| OpStore %st_gep %ld | |
| OpReturn | |
| OpFunctionEnd | |
| )"; | |
| SinglePassRunAndMatch<opt::UpgradeMemoryModel>(text, true); | |
| } | |
| TEST_F(UpgradeMemoryModelTest, MultiIndexAccessNonCoherent) { | |
| const std::string text = R"( | |
| ; CHECK-NOT: OpMemberDecorate | |
| ; CHECK-NOT: MakePointerAvailable | |
| ; CHECK-NOT: NonPrivatePointer | |
| ; CHECK-NOT: MakePointerVisible | |
| OpCapability Shader | |
| OpCapability Linkage | |
| OpExtension "SPV_KHR_storage_buffer_storage_class" | |
| OpMemoryModel Logical GLSL450 | |
| OpMemberDecorate %inner 1 Coherent | |
| %void = OpTypeVoid | |
| %int = OpTypeInt 32 0 | |
| %int0 = OpConstant %int 0 | |
| %int1 = OpConstant %int 1 | |
| %inner = OpTypeStruct %int %int | |
| %middle = OpTypeStruct %inner | |
| %outer = OpTypeStruct %middle %middle | |
| %ptr_outer_StorageBuffer = OpTypePointer StorageBuffer %outer | |
| %ptr_int_StorageBuffer = OpTypePointer StorageBuffer %int | |
| %func_ty = OpTypeFunction %void %ptr_outer_StorageBuffer | |
| %func = OpFunction %void None %func_ty | |
| %param = OpFunctionParameter %ptr_outer_StorageBuffer | |
| %1 = OpLabel | |
| %ld_gep = OpInBoundsAccessChain %ptr_int_StorageBuffer %param %int0 %int0 %int0 | |
| %ld = OpLoad %int %ld_gep | |
| %st_gep = OpInBoundsAccessChain %ptr_int_StorageBuffer %param %int1 %int0 %int0 | |
| OpStore %st_gep %ld | |
| OpReturn | |
| OpFunctionEnd | |
| )"; | |
| SinglePassRunAndMatch<opt::UpgradeMemoryModel>(text, true); | |
| } | |
| TEST_F(UpgradeMemoryModelTest, ConsecutiveAccessChainCoherent) { | |
| const std::string text = R"( | |
| ; CHECK-NOT: OpMemberDecorate | |
| ; CHECK: [[scope:%\w+]] = OpConstant {{%\w+}} 5 | |
| ; CHECK: OpLoad {{%\w+}} {{%\w+}} MakePointerVisible|NonPrivatePointer [[scope]] | |
| ; CHECK: OpStore {{%\w+}} {{%\w+}} MakePointerAvailable|NonPrivatePointer [[scope]] | |
| OpCapability Shader | |
| OpCapability Linkage | |
| OpExtension "SPV_KHR_storage_buffer_storage_class" | |
| OpMemoryModel Logical GLSL450 | |
| OpMemberDecorate %inner 1 Coherent | |
| %void = OpTypeVoid | |
| %int = OpTypeInt 32 0 | |
| %int0 = OpConstant %int 0 | |
| %int1 = OpConstant %int 1 | |
| %inner = OpTypeStruct %int %int | |
| %middle = OpTypeStruct %inner | |
| %outer = OpTypeStruct %middle %middle | |
| %ptr_outer_StorageBuffer = OpTypePointer StorageBuffer %outer | |
| %ptr_middle_StorageBuffer = OpTypePointer StorageBuffer %middle | |
| %ptr_inner_StorageBuffer = OpTypePointer StorageBuffer %inner | |
| %ptr_int_StorageBuffer = OpTypePointer StorageBuffer %int | |
| %func_ty = OpTypeFunction %void %ptr_outer_StorageBuffer | |
| %func = OpFunction %void None %func_ty | |
| %param = OpFunctionParameter %ptr_outer_StorageBuffer | |
| %1 = OpLabel | |
| %ld_gep1 = OpInBoundsAccessChain %ptr_middle_StorageBuffer %param %int0 | |
| %ld_gep2 = OpInBoundsAccessChain %ptr_inner_StorageBuffer %ld_gep1 %int0 | |
| %ld_gep3 = OpInBoundsAccessChain %ptr_int_StorageBuffer %ld_gep2 %int1 | |
| %ld = OpLoad %int %ld_gep3 | |
| %st_gep1 = OpInBoundsAccessChain %ptr_middle_StorageBuffer %param %int1 | |
| %st_gep2 = OpInBoundsAccessChain %ptr_inner_StorageBuffer %st_gep1 %int0 | |
| %st_gep3 = OpInBoundsAccessChain %ptr_int_StorageBuffer %st_gep2 %int1 | |
| OpStore %st_gep3 %ld | |
| OpReturn | |
| OpFunctionEnd | |
| )"; | |
| SinglePassRunAndMatch<opt::UpgradeMemoryModel>(text, true); | |
| } | |
| TEST_F(UpgradeMemoryModelTest, ConsecutiveAccessChainNonCoherent) { | |
| const std::string text = R"( | |
| ; CHECK-NOT: OpMemberDecorate | |
| ; CHECK-NOT: MakePointerAvailable | |
| ; CHECK-NOT: NonPrivatePointer | |
| ; CHECK-NOT: MakePointerVisible | |
| OpCapability Shader | |
| OpCapability Linkage | |
| OpExtension "SPV_KHR_storage_buffer_storage_class" | |
| OpMemoryModel Logical GLSL450 | |
| OpMemberDecorate %inner 1 Coherent | |
| %void = OpTypeVoid | |
| %int = OpTypeInt 32 0 | |
| %int0 = OpConstant %int 0 | |
| %int1 = OpConstant %int 1 | |
| %inner = OpTypeStruct %int %int | |
| %middle = OpTypeStruct %inner | |
| %outer = OpTypeStruct %middle %middle | |
| %ptr_outer_StorageBuffer = OpTypePointer StorageBuffer %outer | |
| %ptr_middle_StorageBuffer = OpTypePointer StorageBuffer %middle | |
| %ptr_inner_StorageBuffer = OpTypePointer StorageBuffer %inner | |
| %ptr_int_StorageBuffer = OpTypePointer StorageBuffer %int | |
| %func_ty = OpTypeFunction %void %ptr_outer_StorageBuffer | |
| %func = OpFunction %void None %func_ty | |
| %param = OpFunctionParameter %ptr_outer_StorageBuffer | |
| %1 = OpLabel | |
| %ld_gep1 = OpInBoundsAccessChain %ptr_middle_StorageBuffer %param %int0 | |
| %ld_gep2 = OpInBoundsAccessChain %ptr_inner_StorageBuffer %ld_gep1 %int0 | |
| %ld_gep3 = OpInBoundsAccessChain %ptr_int_StorageBuffer %ld_gep2 %int0 | |
| %ld = OpLoad %int %ld_gep3 | |
| %st_gep1 = OpInBoundsAccessChain %ptr_middle_StorageBuffer %param %int1 | |
| %st_gep2 = OpInBoundsAccessChain %ptr_inner_StorageBuffer %st_gep1 %int0 | |
| %st_gep3 = OpInBoundsAccessChain %ptr_int_StorageBuffer %st_gep2 %int0 | |
| OpStore %st_gep3 %ld | |
| OpReturn | |
| OpFunctionEnd | |
| )"; | |
| SinglePassRunAndMatch<opt::UpgradeMemoryModel>(text, true); | |
| } | |
| TEST_F(UpgradeMemoryModelTest, CoherentStructElementAccess) { | |
| const std::string text = R"( | |
| ; CHECK-NOT: OpMemberDecorate | |
| ; CHECK: [[scope:%\w+]] = OpConstant {{%\w+}} 5 | |
| ; CHECK: OpLoad {{%\w+}} {{%\w+}} MakePointerVisible|NonPrivatePointer [[scope]] | |
| ; CHECK: OpStore {{%\w+}} {{%\w+}} MakePointerAvailable|NonPrivatePointer [[scope]] | |
| OpCapability Shader | |
| OpCapability Linkage | |
| OpExtension "SPV_KHR_storage_buffer_storage_class" | |
| OpMemoryModel Logical GLSL450 | |
| OpMemberDecorate %middle 0 Coherent | |
| %void = OpTypeVoid | |
| %int = OpTypeInt 32 0 | |
| %int0 = OpConstant %int 0 | |
| %int1 = OpConstant %int 1 | |
| %inner = OpTypeStruct %int %int | |
| %middle = OpTypeStruct %inner | |
| %outer = OpTypeStruct %middle %middle | |
| %ptr_outer_StorageBuffer = OpTypePointer StorageBuffer %outer | |
| %ptr_middle_StorageBuffer = OpTypePointer StorageBuffer %middle | |
| %ptr_inner_StorageBuffer = OpTypePointer StorageBuffer %inner | |
| %ptr_int_StorageBuffer = OpTypePointer StorageBuffer %int | |
| %func_ty = OpTypeFunction %void %ptr_outer_StorageBuffer | |
| %func = OpFunction %void None %func_ty | |
| %param = OpFunctionParameter %ptr_outer_StorageBuffer | |
| %1 = OpLabel | |
| %ld_gep1 = OpInBoundsAccessChain %ptr_middle_StorageBuffer %param %int0 | |
| %ld_gep2 = OpInBoundsAccessChain %ptr_inner_StorageBuffer %ld_gep1 %int0 | |
| %ld_gep3 = OpInBoundsAccessChain %ptr_int_StorageBuffer %ld_gep2 %int1 | |
| %ld = OpLoad %int %ld_gep3 | |
| %st_gep1 = OpInBoundsAccessChain %ptr_middle_StorageBuffer %param %int1 | |
| %st_gep2 = OpInBoundsAccessChain %ptr_inner_StorageBuffer %st_gep1 %int0 | |
| %st_gep3 = OpInBoundsAccessChain %ptr_int_StorageBuffer %st_gep2 %int1 | |
| OpStore %st_gep3 %ld | |
| OpReturn | |
| OpFunctionEnd | |
| )"; | |
| SinglePassRunAndMatch<opt::UpgradeMemoryModel>(text, true); | |
| } | |
| TEST_F(UpgradeMemoryModelTest, NonCoherentLoadCoherentStore) { | |
| const std::string text = R"( | |
| ; CHECK-NOT: OpMemberDecorate | |
| ; CHECK: [[scope:%\w+]] = OpConstant {{%\w+}} 5 | |
| ; CHECK-NOT: MakePointerVisible | |
| ; CHECK: OpStore {{%\w+}} {{%\w+}} MakePointerAvailable|NonPrivatePointer [[scope]] | |
| OpCapability Shader | |
| OpCapability Linkage | |
| OpExtension "SPV_KHR_storage_buffer_storage_class" | |
| OpMemoryModel Logical GLSL450 | |
| OpMemberDecorate %outer 1 Coherent | |
| %void = OpTypeVoid | |
| %int = OpTypeInt 32 0 | |
| %int0 = OpConstant %int 0 | |
| %int1 = OpConstant %int 1 | |
| %inner = OpTypeStruct %int %int | |
| %middle = OpTypeStruct %inner | |
| %outer = OpTypeStruct %middle %middle | |
| %ptr_outer_StorageBuffer = OpTypePointer StorageBuffer %outer | |
| %ptr_middle_StorageBuffer = OpTypePointer StorageBuffer %middle | |
| %ptr_inner_StorageBuffer = OpTypePointer StorageBuffer %inner | |
| %ptr_int_StorageBuffer = OpTypePointer StorageBuffer %int | |
| %func_ty = OpTypeFunction %void %ptr_outer_StorageBuffer | |
| %func = OpFunction %void None %func_ty | |
| %param = OpFunctionParameter %ptr_outer_StorageBuffer | |
| %1 = OpLabel | |
| %ld_gep1 = OpInBoundsAccessChain %ptr_middle_StorageBuffer %param %int0 | |
| %ld_gep2 = OpInBoundsAccessChain %ptr_inner_StorageBuffer %ld_gep1 %int0 | |
| %ld_gep3 = OpInBoundsAccessChain %ptr_int_StorageBuffer %ld_gep2 %int1 | |
| %ld = OpLoad %int %ld_gep3 | |
| %st_gep1 = OpInBoundsAccessChain %ptr_middle_StorageBuffer %param %int1 | |
| %st_gep2 = OpInBoundsAccessChain %ptr_inner_StorageBuffer %st_gep1 %int0 | |
| %st_gep3 = OpInBoundsAccessChain %ptr_int_StorageBuffer %st_gep2 %int1 | |
| OpStore %st_gep3 %ld | |
| OpReturn | |
| OpFunctionEnd | |
| )"; | |
| SinglePassRunAndMatch<opt::UpgradeMemoryModel>(text, true); | |
| } | |
| TEST_F(UpgradeMemoryModelTest, CopyMemory) { | |
| const std::string text = R"( | |
| ; CHECK-NOT: OpDecorate | |
| ; CHECK: [[queuefamily:%\w+]] = OpConstant {{%\w+}} 5 | |
| ; CHECK: OpCopyMemory {{%\w+}} {{%\w+}} Volatile|MakePointerVisible|NonPrivatePointer [[queuefamily]] | |
| ; CHECK-NOT: [[queuefamily]] | |
| OpCapability Shader | |
| OpCapability Linkage | |
| OpExtension "SPV_KHR_storage_buffer_storage_class" | |
| OpMemoryModel Logical GLSL450 | |
| OpDecorate %in_var Coherent | |
| OpDecorate %out_var Volatile | |
| %void = OpTypeVoid | |
| %int = OpTypeInt 32 0 | |
| %ptr_int_StorageBuffer = OpTypePointer StorageBuffer %int | |
| %in_var = OpVariable %ptr_int_StorageBuffer StorageBuffer | |
| %out_var = OpVariable %ptr_int_StorageBuffer StorageBuffer | |
| %func_ty = OpTypeFunction %void | |
| %func = OpFunction %void None %func_ty | |
| %1 = OpLabel | |
| OpCopyMemory %out_var %in_var | |
| OpReturn | |
| OpFunctionEnd | |
| )"; | |
| SinglePassRunAndMatch<opt::UpgradeMemoryModel>(text, true); | |
| } | |
| TEST_F(UpgradeMemoryModelTest, CopyMemorySized) { | |
| const std::string text = R"( | |
| ; CHECK-NOT: OpDecorate | |
| ; CHECK: [[queuefamily:%\w+]] = OpConstant {{%\w+}} 5 | |
| ; CHECK: OpCopyMemorySized {{%\w+}} {{%\w+}} {{%\w+}} Volatile|MakePointerAvailable|NonPrivatePointer [[queuefamily]] | |
| ; CHECK-NOT: [[queuefamily]] | |
| OpCapability Shader | |
| OpCapability Linkage | |
| OpCapability Addresses | |
| OpExtension "SPV_KHR_storage_buffer_storage_class" | |
| OpMemoryModel Logical GLSL450 | |
| OpDecorate %out_param Coherent | |
| OpDecorate %in_param Volatile | |
| %void = OpTypeVoid | |
| %int = OpTypeInt 32 0 | |
| %int4 = OpConstant %int 4 | |
| %ptr_int_StorageBuffer = OpTypePointer StorageBuffer %int | |
| %func_ty = OpTypeFunction %void %ptr_int_StorageBuffer %ptr_int_StorageBuffer | |
| %func = OpFunction %void None %func_ty | |
| %in_param = OpFunctionParameter %ptr_int_StorageBuffer | |
| %out_param = OpFunctionParameter %ptr_int_StorageBuffer | |
| %1 = OpLabel | |
| OpCopyMemorySized %out_param %in_param %int4 | |
| OpReturn | |
| OpFunctionEnd | |
| )"; | |
| SinglePassRunAndMatch<opt::UpgradeMemoryModel>(text, true); | |
| } | |
| TEST_F(UpgradeMemoryModelTest, CopyMemoryTwoScopes) { | |
| const std::string text = R"( | |
| ; CHECK-NOT: OpDecorate | |
| ; CHECK-DAG: [[queuefamily:%\w+]] = OpConstant {{%\w+}} 5 | |
| ; CHECK-DAG: [[workgroup:%\w+]] = OpConstant {{%\w+}} 2 | |
| ; CHECK: OpCopyMemory {{%\w+}} {{%\w+}} MakePointerAvailable|MakePointerVisible|NonPrivatePointer [[workgroup]] [[queuefamily]] | |
| OpCapability Shader | |
| OpCapability Linkage | |
| OpExtension "SPV_KHR_storage_buffer_storage_class" | |
| OpMemoryModel Logical GLSL450 | |
| OpDecorate %in_var Coherent | |
| OpDecorate %out_var Coherent | |
| %void = OpTypeVoid | |
| %int = OpTypeInt 32 0 | |
| %ptr_int_Workgroup = OpTypePointer Workgroup %int | |
| %ptr_int_StorageBuffer = OpTypePointer StorageBuffer %int | |
| %in_var = OpVariable %ptr_int_StorageBuffer StorageBuffer | |
| %out_var = OpVariable %ptr_int_Workgroup Workgroup | |
| %func_ty = OpTypeFunction %void | |
| %func = OpFunction %void None %func_ty | |
| %1 = OpLabel | |
| OpCopyMemory %out_var %in_var | |
| OpReturn | |
| OpFunctionEnd | |
| )"; | |
| SinglePassRunAndMatch<opt::UpgradeMemoryModel>(text, true); | |
| } | |
| TEST_F(UpgradeMemoryModelTest, VolatileImageRead) { | |
| const std::string text = R"( | |
| ; CHECK-NOT: OpDecorate | |
| ; CHECK: OpLoad {{%\w+}} {{%\w+}} Volatile | |
| ; CHECK: OpImageRead {{%\w+}} {{%\w+}} {{%\w+}} VolatileTexel | |
| OpCapability Shader | |
| OpCapability Linkage | |
| OpCapability StorageImageReadWithoutFormat | |
| OpExtension "SPV_KHR_storage_buffer_storage_class" | |
| OpMemoryModel Logical GLSL450 | |
| OpDecorate %var Volatile | |
| %void = OpTypeVoid | |
| %int = OpTypeInt 32 0 | |
| %v2int = OpTypeVector %int 2 | |
| %float = OpTypeFloat 32 | |
| %int0 = OpConstant %int 0 | |
| %v2int_0 = OpConstantComposite %v2int %int0 %int0 | |
| %image = OpTypeImage %float 2D 0 0 0 2 Unknown | |
| %ptr_image_StorageBuffer = OpTypePointer StorageBuffer %image | |
| %var = OpVariable %ptr_image_StorageBuffer StorageBuffer | |
| %func_ty = OpTypeFunction %void | |
| %func = OpFunction %void None %func_ty | |
| %1 = OpLabel | |
| %ld = OpLoad %image %var | |
| %rd = OpImageRead %float %ld %v2int_0 | |
| OpReturn | |
| OpFunctionEnd | |
| )"; | |
| SinglePassRunAndMatch<opt::UpgradeMemoryModel>(text, true); | |
| } | |
| TEST_F(UpgradeMemoryModelTest, CoherentImageRead) { | |
| const std::string text = R"( | |
| ; CHECK-NOT: OpDecorate | |
| ; CHECK: [[scope:%\w+]] = OpConstant {{%\w+}} 5 | |
| ; CHECK: OpLoad {{%\w+}} {{%\w+}} MakePointerVisible|NonPrivatePointer [[scope]] | |
| ; CHECK: OpImageRead {{%\w+}} {{%\w+}} {{%\w+}} MakeTexelVisible|NonPrivateTexel [[scope]] | |
| OpCapability Shader | |
| OpCapability Linkage | |
| OpCapability StorageImageReadWithoutFormat | |
| OpExtension "SPV_KHR_storage_buffer_storage_class" | |
| OpMemoryModel Logical GLSL450 | |
| OpDecorate %var Coherent | |
| %void = OpTypeVoid | |
| %int = OpTypeInt 32 0 | |
| %v2int = OpTypeVector %int 2 | |
| %float = OpTypeFloat 32 | |
| %int0 = OpConstant %int 0 | |
| %v2int_0 = OpConstantComposite %v2int %int0 %int0 | |
| %image = OpTypeImage %float 2D 0 0 0 2 Unknown | |
| %ptr_image_StorageBuffer = OpTypePointer StorageBuffer %image | |
| %var = OpVariable %ptr_image_StorageBuffer StorageBuffer | |
| %func_ty = OpTypeFunction %void | |
| %func = OpFunction %void None %func_ty | |
| %1 = OpLabel | |
| %ld = OpLoad %image %var | |
| %rd = OpImageRead %float %ld %v2int_0 | |
| OpReturn | |
| OpFunctionEnd | |
| )"; | |
| SinglePassRunAndMatch<opt::UpgradeMemoryModel>(text, true); | |
| } | |
| TEST_F(UpgradeMemoryModelTest, CoherentImageReadExtractedFromSampledImage) { | |
| const std::string text = R"( | |
| ; CHECK-NOT: OpDecorate | |
| ; CHECK: [[image:%\w+]] = OpTypeImage | |
| ; CHECK: [[scope:%\w+]] = OpConstant {{%\w+}} 5 | |
| ; CHECK: OpLoad [[image]] {{%\w+}} MakePointerVisible|NonPrivatePointer [[scope]] | |
| ; CHECK-NOT: NonPrivatePointer | |
| ; CHECK: OpImageRead {{%\w+}} {{%\w+}} {{%\w+}} MakeTexelVisible|NonPrivateTexel [[scope]] | |
| OpCapability Shader | |
| OpCapability Linkage | |
| OpCapability StorageImageReadWithoutFormat | |
| OpExtension "SPV_KHR_storage_buffer_storage_class" | |
| OpMemoryModel Logical GLSL450 | |
| OpDecorate %var Coherent | |
| %void = OpTypeVoid | |
| %int = OpTypeInt 32 0 | |
| %v2int = OpTypeVector %int 2 | |
| %float = OpTypeFloat 32 | |
| %int0 = OpConstant %int 0 | |
| %v2int_0 = OpConstantComposite %v2int %int0 %int0 | |
| %image = OpTypeImage %float 2D 0 0 0 0 Unknown | |
| %sampled_image = OpTypeSampledImage %image | |
| %sampler = OpTypeSampler | |
| %ptr_image_StorageBuffer = OpTypePointer StorageBuffer %image | |
| %ptr_sampler_StorageBuffer = OpTypePointer StorageBuffer %sampler | |
| %var = OpVariable %ptr_image_StorageBuffer StorageBuffer | |
| %sampler_var = OpVariable %ptr_sampler_StorageBuffer StorageBuffer | |
| %func_ty = OpTypeFunction %void | |
| %func = OpFunction %void None %func_ty | |
| %1 = OpLabel | |
| %ld = OpLoad %image %var | |
| %ld_sampler = OpLoad %sampler %sampler_var | |
| %sample = OpSampledImage %sampled_image %ld %ld_sampler | |
| %extract = OpImage %image %sample | |
| %rd = OpImageRead %float %extract %v2int_0 | |
| OpReturn | |
| OpFunctionEnd | |
| )"; | |
| SinglePassRunAndMatch<opt::UpgradeMemoryModel>(text, true); | |
| } | |
| TEST_F(UpgradeMemoryModelTest, VolatileImageWrite) { | |
| const std::string text = R"( | |
| ; CHECK-NOT: OpDecorate | |
| ; CHECK: OpLoad {{%\w+}} {{%\w+}} Volatile | |
| ; CHECK: OpImageWrite {{%\w+}} {{%\w+}} {{%\w+}} VolatileTexel | |
| OpCapability Shader | |
| OpCapability Linkage | |
| OpCapability StorageImageWriteWithoutFormat | |
| OpExtension "SPV_KHR_storage_buffer_storage_class" | |
| OpMemoryModel Logical GLSL450 | |
| OpDecorate %param Volatile | |
| %void = OpTypeVoid | |
| %int = OpTypeInt 32 0 | |
| %v2int = OpTypeVector %int 2 | |
| %float = OpTypeFloat 32 | |
| %float0 = OpConstant %float 0 | |
| %v2int_null = OpConstantNull %v2int | |
| %image = OpTypeImage %float 2D 0 0 0 0 Unknown | |
| %ptr_image_StorageBuffer = OpTypePointer StorageBuffer %image | |
| %func_ty = OpTypeFunction %void %ptr_image_StorageBuffer | |
| %func = OpFunction %void None %func_ty | |
| %param = OpFunctionParameter %ptr_image_StorageBuffer | |
| %1 = OpLabel | |
| %ld = OpLoad %image %param | |
| OpImageWrite %ld %v2int_null %float0 | |
| OpReturn | |
| OpFunctionEnd | |
| )"; | |
| SinglePassRunAndMatch<opt::UpgradeMemoryModel>(text, true); | |
| } | |
| TEST_F(UpgradeMemoryModelTest, CoherentImageWrite) { | |
| const std::string text = R"( | |
| ; CHECK-NOT: OpDecorate | |
| ; CHECK: [[scope:%\w+]] = OpConstant {{%\w+}} 5 | |
| ; CHECK: OpLoad {{%\w+}} {{%\w+}} MakePointerVisible|NonPrivatePointer | |
| ; CHECK: OpImageWrite {{%\w+}} {{%\w+}} {{%\w+}} MakeTexelAvailable|NonPrivateTexel [[scope]] | |
| OpCapability Shader | |
| OpCapability Linkage | |
| OpCapability StorageImageWriteWithoutFormat | |
| OpExtension "SPV_KHR_storage_buffer_storage_class" | |
| OpMemoryModel Logical GLSL450 | |
| OpDecorate %param Coherent | |
| %void = OpTypeVoid | |
| %int = OpTypeInt 32 0 | |
| %v2int = OpTypeVector %int 2 | |
| %float = OpTypeFloat 32 | |
| %float0 = OpConstant %float 0 | |
| %v2int_null = OpConstantNull %v2int | |
| %image = OpTypeImage %float 2D 0 0 0 0 Unknown | |
| %ptr_image_StorageBuffer = OpTypePointer StorageBuffer %image | |
| %func_ty = OpTypeFunction %void %ptr_image_StorageBuffer | |
| %func = OpFunction %void None %func_ty | |
| %param = OpFunctionParameter %ptr_image_StorageBuffer | |
| %1 = OpLabel | |
| %ld = OpLoad %image %param | |
| OpImageWrite %ld %v2int_null %float0 | |
| OpReturn | |
| OpFunctionEnd | |
| )"; | |
| SinglePassRunAndMatch<opt::UpgradeMemoryModel>(text, true); | |
| } | |
| TEST_F(UpgradeMemoryModelTest, CoherentImageWriteExtractFromSampledImage) { | |
| const std::string text = R"( | |
| ; CHECK-NOT: OpDecorate | |
| ; CHECK: [[scope:%\w+]] = OpConstant {{%\w+}} 5 | |
| ; CHECK: OpLoad {{%\w+}} {{%\w+}} MakePointerVisible|NonPrivatePointer | |
| ; CHECK-NOT: NonPrivatePointer | |
| ; CHECK: OpImageWrite {{%\w+}} {{%\w+}} {{%\w+}} MakeTexelAvailable|NonPrivateTexel [[scope]] | |
| OpCapability Shader | |
| OpCapability Linkage | |
| OpCapability StorageImageWriteWithoutFormat | |
| OpExtension "SPV_KHR_storage_buffer_storage_class" | |
| OpMemoryModel Logical GLSL450 | |
| OpDecorate %param Coherent | |
| %void = OpTypeVoid | |
| %int = OpTypeInt 32 0 | |
| %v2int = OpTypeVector %int 2 | |
| %float = OpTypeFloat 32 | |
| %float0 = OpConstant %float 0 | |
| %v2int_null = OpConstantNull %v2int | |
| %image = OpTypeImage %float 2D 0 0 0 0 Unknown | |
| %sampled_image = OpTypeSampledImage %image | |
| %sampler = OpTypeSampler | |
| %ptr_image_StorageBuffer = OpTypePointer StorageBuffer %image | |
| %ptr_sampler_StorageBuffer = OpTypePointer StorageBuffer %sampler | |
| %func_ty = OpTypeFunction %void %ptr_image_StorageBuffer %ptr_sampler_StorageBuffer | |
| %func = OpFunction %void None %func_ty | |
| %param = OpFunctionParameter %ptr_image_StorageBuffer | |
| %sampler_param = OpFunctionParameter %ptr_sampler_StorageBuffer | |
| %1 = OpLabel | |
| %ld = OpLoad %image %param | |
| %ld_sampler = OpLoad %sampler %sampler_param | |
| %sample = OpSampledImage %sampled_image %ld %ld_sampler | |
| %extract = OpImage %image %sample | |
| OpImageWrite %extract %v2int_null %float0 | |
| OpReturn | |
| OpFunctionEnd | |
| )"; | |
| SinglePassRunAndMatch<opt::UpgradeMemoryModel>(text, true); | |
| } | |
| TEST_F(UpgradeMemoryModelTest, VolatileImageSparseRead) { | |
| const std::string text = R"( | |
| ; CHECK-NOT: OpDecorate | |
| ; CHECK: OpLoad {{%\w+}} {{%\w+}} Volatile | |
| ; CHECK: OpImageSparseRead {{%\w+}} {{%\w+}} {{%\w+}} VolatileTexel | |
| OpCapability Shader | |
| OpCapability Linkage | |
| OpCapability StorageImageReadWithoutFormat | |
| OpCapability SparseResidency | |
| OpExtension "SPV_KHR_storage_buffer_storage_class" | |
| OpMemoryModel Logical GLSL450 | |
| OpDecorate %var Volatile | |
| %void = OpTypeVoid | |
| %int = OpTypeInt 32 0 | |
| %v2int = OpTypeVector %int 2 | |
| %float = OpTypeFloat 32 | |
| %int0 = OpConstant %int 0 | |
| %v2int_0 = OpConstantComposite %v2int %int0 %int0 | |
| %image = OpTypeImage %float 2D 0 0 0 2 Unknown | |
| %struct = OpTypeStruct %int %float | |
| %ptr_image_StorageBuffer = OpTypePointer StorageBuffer %image | |
| %var = OpVariable %ptr_image_StorageBuffer StorageBuffer | |
| %func_ty = OpTypeFunction %void | |
| %func = OpFunction %void None %func_ty | |
| %1 = OpLabel | |
| %ld = OpLoad %image %var | |
| %rd = OpImageSparseRead %struct %ld %v2int_0 | |
| OpReturn | |
| OpFunctionEnd | |
| )"; | |
| SinglePassRunAndMatch<opt::UpgradeMemoryModel>(text, true); | |
| } | |
| TEST_F(UpgradeMemoryModelTest, CoherentImageSparseRead) { | |
| const std::string text = R"( | |
| ; CHECK-NOT: OpDecorate | |
| ; CHECK: [[scope:%\w+]] = OpConstant {{%\w+}} 5 | |
| ; CHECK: OpLoad {{%\w+}} {{%\w+}} MakePointerVisible|NonPrivatePointer [[scope]] | |
| ; CHECK: OpImageSparseRead {{%\w+}} {{%\w+}} {{%\w+}} MakeTexelVisible|NonPrivateTexel [[scope]] | |
| OpCapability Shader | |
| OpCapability Linkage | |
| OpCapability StorageImageReadWithoutFormat | |
| OpCapability SparseResidency | |
| OpExtension "SPV_KHR_storage_buffer_storage_class" | |
| OpMemoryModel Logical GLSL450 | |
| OpDecorate %var Coherent | |
| %void = OpTypeVoid | |
| %int = OpTypeInt 32 0 | |
| %v2int = OpTypeVector %int 2 | |
| %float = OpTypeFloat 32 | |
| %int0 = OpConstant %int 0 | |
| %v2int_0 = OpConstantComposite %v2int %int0 %int0 | |
| %image = OpTypeImage %float 2D 0 0 0 2 Unknown | |
| %struct = OpTypeStruct %int %float | |
| %ptr_image_StorageBuffer = OpTypePointer StorageBuffer %image | |
| %var = OpVariable %ptr_image_StorageBuffer StorageBuffer | |
| %func_ty = OpTypeFunction %void | |
| %func = OpFunction %void None %func_ty | |
| %1 = OpLabel | |
| %ld = OpLoad %image %var | |
| %rd = OpImageSparseRead %struct %ld %v2int_0 | |
| OpReturn | |
| OpFunctionEnd | |
| )"; | |
| SinglePassRunAndMatch<opt::UpgradeMemoryModel>(text, true); | |
| } | |
| TEST_F(UpgradeMemoryModelTest, | |
| CoherentImageSparseReadExtractedFromSampledImage) { | |
| const std::string text = R"( | |
| ; CHECK-NOT: OpDecorate | |
| ; CHECK: [[image:%\w+]] = OpTypeImage | |
| ; CHECK: [[scope:%\w+]] = OpConstant {{%\w+}} 5 | |
| ; CHECK: OpLoad [[image]] {{%\w+}} MakePointerVisible|NonPrivatePointer [[scope]] | |
| ; CHECK-NOT: NonPrivatePointer | |
| ; CHECK: OpImageSparseRead {{%\w+}} {{%\w+}} {{%\w+}} MakeTexelVisible|NonPrivateTexel [[scope]] | |
| OpCapability Shader | |
| OpCapability Linkage | |
| OpCapability StorageImageReadWithoutFormat | |
| OpCapability SparseResidency | |
| OpExtension "SPV_KHR_storage_buffer_storage_class" | |
| OpMemoryModel Logical GLSL450 | |
| OpDecorate %var Coherent | |
| %void = OpTypeVoid | |
| %int = OpTypeInt 32 0 | |
| %v2int = OpTypeVector %int 2 | |
| %float = OpTypeFloat 32 | |
| %int0 = OpConstant %int 0 | |
| %v2int_0 = OpConstantComposite %v2int %int0 %int0 | |
| %image = OpTypeImage %float 2D 0 0 0 0 Unknown | |
| %struct = OpTypeStruct %int %float | |
| %sampled_image = OpTypeSampledImage %image | |
| %sampler = OpTypeSampler | |
| %ptr_image_StorageBuffer = OpTypePointer StorageBuffer %image | |
| %ptr_sampler_StorageBuffer = OpTypePointer StorageBuffer %sampler | |
| %var = OpVariable %ptr_image_StorageBuffer StorageBuffer | |
| %sampler_var = OpVariable %ptr_sampler_StorageBuffer StorageBuffer | |
| %func_ty = OpTypeFunction %void | |
| %func = OpFunction %void None %func_ty | |
| %1 = OpLabel | |
| %ld = OpLoad %image %var | |
| %ld_sampler = OpLoad %sampler %sampler_var | |
| %sample = OpSampledImage %sampled_image %ld %ld_sampler | |
| %extract = OpImage %image %sample | |
| %rd = OpImageSparseRead %struct %extract %v2int_0 | |
| OpReturn | |
| OpFunctionEnd | |
| )"; | |
| SinglePassRunAndMatch<opt::UpgradeMemoryModel>(text, true); | |
| } | |
| TEST_F(UpgradeMemoryModelTest, TessellationControlBarrierNoChange) { | |
| const std::string text = R"( | |
| ; CHECK: [[none:%\w+]] = OpConstant {{%\w+}} 0 | |
| ; CHECK: [[workgroup:%\w+]] = OpConstant {{%\w+}} 2 | |
| ; CHECK: OpControlBarrier [[workgroup]] [[workgroup]] [[none]] | |
| OpCapability Tessellation | |
| OpMemoryModel Logical GLSL450 | |
| OpEntryPoint TessellationControl %func "func" | |
| %void = OpTypeVoid | |
| %int = OpTypeInt 32 0 | |
| %none = OpConstant %int 0 | |
| %workgroup = OpConstant %int 2 | |
| %func_ty = OpTypeFunction %void | |
| %func = OpFunction %void None %func_ty | |
| %1 = OpLabel | |
| OpControlBarrier %workgroup %workgroup %none | |
| OpReturn | |
| OpFunctionEnd | |
| )"; | |
| SinglePassRunAndMatch<opt::UpgradeMemoryModel>(text, true); | |
| } | |
| TEST_F(UpgradeMemoryModelTest, TessellationControlBarrierAddOutput) { | |
| const std::string text = R"( | |
| ; CHECK: [[workgroup:%\w+]] = OpConstant {{%\w+}} 2 | |
| ; CHECK: [[output:%\w+]] = OpConstant {{%\w+}} 4096 | |
| ; CHECK: OpControlBarrier [[workgroup]] [[workgroup]] [[output]] | |
| OpCapability Tessellation | |
| OpMemoryModel Logical GLSL450 | |
| OpEntryPoint TessellationControl %func "func" %var | |
| %void = OpTypeVoid | |
| %int = OpTypeInt 32 0 | |
| %none = OpConstant %int 0 | |
| %workgroup = OpConstant %int 2 | |
| %ptr_int_Output = OpTypePointer Output %int | |
| %var = OpVariable %ptr_int_Output Output | |
| %func_ty = OpTypeFunction %void | |
| %func = OpFunction %void None %func_ty | |
| %1 = OpLabel | |
| %ld = OpLoad %int %var | |
| OpControlBarrier %workgroup %workgroup %none | |
| OpStore %var %ld | |
| OpReturn | |
| OpFunctionEnd | |
| )"; | |
| SinglePassRunAndMatch<opt::UpgradeMemoryModel>(text, true); | |
| } | |
| TEST_F(UpgradeMemoryModelTest, TessellationMemoryBarrierNoChange) { | |
| const std::string text = R"( | |
| ; CHECK: [[none:%\w+]] = OpConstant {{%\w+}} 0 | |
| ; CHECK: [[workgroup:%\w+]] = OpConstant {{%\w+}} 2 | |
| ; CHECK: OpMemoryBarrier [[workgroup]] [[none]] | |
| OpCapability Tessellation | |
| OpMemoryModel Logical GLSL450 | |
| OpEntryPoint TessellationControl %func "func" %var | |
| %void = OpTypeVoid | |
| %int = OpTypeInt 32 0 | |
| %none = OpConstant %int 0 | |
| %workgroup = OpConstant %int 2 | |
| %ptr_int_Output = OpTypePointer Output %int | |
| %var = OpVariable %ptr_int_Output Output | |
| %func_ty = OpTypeFunction %void | |
| %func = OpFunction %void None %func_ty | |
| %1 = OpLabel | |
| %ld = OpLoad %int %var | |
| OpMemoryBarrier %workgroup %none | |
| OpStore %var %ld | |
| OpReturn | |
| OpFunctionEnd | |
| )"; | |
| SinglePassRunAndMatch<opt::UpgradeMemoryModel>(text, true); | |
| } | |
| TEST_F(UpgradeMemoryModelTest, TessellationControlBarrierAddOutputSubFunction) { | |
| const std::string text = R"( | |
| ; CHECK: [[workgroup:%\w+]] = OpConstant {{%\w+}} 2 | |
| ; CHECK: [[output:%\w+]] = OpConstant {{%\w+}} 4096 | |
| ; CHECK: OpControlBarrier [[workgroup]] [[workgroup]] [[output]] | |
| OpCapability Tessellation | |
| OpMemoryModel Logical GLSL450 | |
| OpEntryPoint TessellationControl %func "func" %var | |
| %void = OpTypeVoid | |
| %int = OpTypeInt 32 0 | |
| %none = OpConstant %int 0 | |
| %workgroup = OpConstant %int 2 | |
| %ptr_int_Output = OpTypePointer Output %int | |
| %var = OpVariable %ptr_int_Output Output | |
| %func_ty = OpTypeFunction %void | |
| %func = OpFunction %void None %func_ty | |
| %1 = OpLabel | |
| %call = OpFunctionCall %void %sub_func | |
| OpReturn | |
| OpFunctionEnd | |
| %sub_func = OpFunction %void None %func_ty | |
| %2 = OpLabel | |
| %ld = OpLoad %int %var | |
| OpControlBarrier %workgroup %workgroup %none | |
| OpStore %var %ld | |
| OpReturn | |
| OpFunctionEnd | |
| )"; | |
| SinglePassRunAndMatch<opt::UpgradeMemoryModel>(text, true); | |
| } | |
| TEST_F(UpgradeMemoryModelTest, | |
| TessellationControlBarrierAddOutputDifferentFunctions) { | |
| const std::string text = R"( | |
| ; CHECK: [[workgroup:%\w+]] = OpConstant {{%\w+}} 2 | |
| ; CHECK: [[output:%\w+]] = OpConstant {{%\w+}} 4096 | |
| ; CHECK: OpControlBarrier [[workgroup]] [[workgroup]] [[output]] | |
| OpCapability Tessellation | |
| OpMemoryModel Logical GLSL450 | |
| OpEntryPoint TessellationControl %func "func" %var | |
| %void = OpTypeVoid | |
| %int = OpTypeInt 32 0 | |
| %none = OpConstant %int 0 | |
| %workgroup = OpConstant %int 2 | |
| %ptr_int_Output = OpTypePointer Output %int | |
| %var = OpVariable %ptr_int_Output Output | |
| %func_ty = OpTypeFunction %void | |
| %ld_func_ty = OpTypeFunction %int | |
| %st_func_ty = OpTypeFunction %void %int | |
| %func = OpFunction %void None %func_ty | |
| %1 = OpLabel | |
| %call_ld = OpFunctionCall %int %ld_func | |
| %call_barrier = OpFunctionCall %void %barrier_func | |
| %call_st = OpFunctionCall %void %st_func %call_ld | |
| OpReturn | |
| OpFunctionEnd | |
| %ld_func = OpFunction %int None %ld_func_ty | |
| %2 = OpLabel | |
| %ld = OpLoad %int %var | |
| OpReturnValue %ld | |
| OpFunctionEnd | |
| %barrier_func = OpFunction %void None %func_ty | |
| %3 = OpLabel | |
| OpControlBarrier %workgroup %workgroup %none | |
| OpReturn | |
| OpFunctionEnd | |
| %st_func = OpFunction %void None %st_func_ty | |
| %param = OpFunctionParameter %int | |
| %4 = OpLabel | |
| OpStore %var %param | |
| OpReturn | |
| OpFunctionEnd | |
| )"; | |
| SinglePassRunAndMatch<opt::UpgradeMemoryModel>(text, true); | |
| } | |
| TEST_F(UpgradeMemoryModelTest, ChangeControlBarrierMemoryScope) { | |
| std::string text = R"( | |
| ; CHECK: [[workgroup:%\w+]] = OpConstant {{%\w+}} 2 | |
| ; CHECK: [[queuefamily:%\w+]] = OpConstant {{%\w+}} 5 | |
| ; CHECK: OpControlBarrier [[workgroup]] [[queuefamily]] | |
| OpCapability Shader | |
| OpMemoryModel Logical GLSL450 | |
| OpEntryPoint GLCompute %func "func" | |
| %void = OpTypeVoid | |
| %int = OpTypeInt 32 0 | |
| %none = OpConstant %int 0 | |
| %device = OpConstant %int 1 | |
| %workgroup = OpConstant %int 2 | |
| %func_ty = OpTypeFunction %void | |
| %func = OpFunction %void None %func_ty | |
| %1 = OpLabel | |
| OpControlBarrier %workgroup %device %none | |
| OpReturn | |
| OpFunctionEnd | |
| )"; | |
| SinglePassRunAndMatch<opt::UpgradeMemoryModel>(text, true); | |
| } | |
| TEST_F(UpgradeMemoryModelTest, ChangeMemoryBarrierMemoryScope) { | |
| std::string text = R"( | |
| ; CHECK: [[queuefamily:%\w+]] = OpConstant {{%\w+}} 5 | |
| ; CHECK: OpMemoryBarrier [[queuefamily]] | |
| OpCapability Shader | |
| OpMemoryModel Logical GLSL450 | |
| OpEntryPoint GLCompute %func "func" | |
| %void = OpTypeVoid | |
| %int = OpTypeInt 32 0 | |
| %none = OpConstant %int 0 | |
| %device = OpConstant %int 1 | |
| %func_ty = OpTypeFunction %void | |
| %func = OpFunction %void None %func_ty | |
| %1 = OpLabel | |
| OpMemoryBarrier %device %none | |
| OpReturn | |
| OpFunctionEnd | |
| )"; | |
| SinglePassRunAndMatch<opt::UpgradeMemoryModel>(text, true); | |
| } | |
| TEST_F(UpgradeMemoryModelTest, ChangeAtomicMemoryScope) { | |
| std::string text = R"( | |
| ; CHECK: [[int:%\w+]] = OpTypeInt | |
| ; CHECK: [[var:%\w+]] = OpVariable | |
| ; CHECK: [[qf:%\w+]] = OpConstant [[int]] 5 | |
| ; CHECK: OpAtomicLoad [[int]] [[var]] [[qf]] | |
| ; CHECK: OpAtomicStore [[var]] [[qf]] | |
| ; CHECK: OpAtomicExchange [[int]] [[var]] [[qf]] | |
| ; CHECK: OpAtomicCompareExchange [[int]] [[var]] [[qf]] | |
| ; CHECK: OpAtomicIIncrement [[int]] [[var]] [[qf]] | |
| ; CHECK: OpAtomicIDecrement [[int]] [[var]] [[qf]] | |
| ; CHECK: OpAtomicIAdd [[int]] [[var]] [[qf]] | |
| ; CHECK: OpAtomicISub [[int]] [[var]] [[qf]] | |
| ; CHECK: OpAtomicSMin [[int]] [[var]] [[qf]] | |
| ; CHECK: OpAtomicSMax [[int]] [[var]] [[qf]] | |
| ; CHECK: OpAtomicUMin [[int]] [[var]] [[qf]] | |
| ; CHECK: OpAtomicUMax [[int]] [[var]] [[qf]] | |
| ; CHECK: OpAtomicAnd [[int]] [[var]] [[qf]] | |
| ; CHECK: OpAtomicOr [[int]] [[var]] [[qf]] | |
| ; CHECK: OpAtomicXor [[int]] [[var]] [[qf]] | |
| OpCapability Shader | |
| OpExtension "SPV_KHR_storage_buffer_storage_class" | |
| OpMemoryModel Logical GLSL450 | |
| OpEntryPoint GLCompute %func "func" | |
| %void = OpTypeVoid | |
| %int = OpTypeInt 32 0 | |
| %none = OpConstant %int 0 | |
| %device = OpConstant %int 1 | |
| %func_ty = OpTypeFunction %void | |
| %ptr_int_StorageBuffer = OpTypePointer StorageBuffer %int | |
| %var = OpVariable %ptr_int_StorageBuffer StorageBuffer | |
| %func = OpFunction %void None %func_ty | |
| %1 = OpLabel | |
| %ld = OpAtomicLoad %int %var %device %none | |
| OpAtomicStore %var %device %none %ld | |
| %ex = OpAtomicExchange %int %var %device %none %ld | |
| %cmp_ex = OpAtomicCompareExchange %int %var %device %none %none %ld %ld | |
| %inc = OpAtomicIIncrement %int %var %device %none | |
| %dec = OpAtomicIDecrement %int %var %device %none | |
| %add = OpAtomicIAdd %int %var %device %none %ld | |
| %sub = OpAtomicISub %int %var %device %none %ld | |
| %smin = OpAtomicSMin %int %var %device %none %ld | |
| %smax = OpAtomicSMax %int %var %device %none %ld | |
| %umin = OpAtomicUMin %int %var %device %none %ld | |
| %umax = OpAtomicUMax %int %var %device %none %ld | |
| %and = OpAtomicAnd %int %var %device %none %ld | |
| %or = OpAtomicOr %int %var %device %none %ld | |
| %xor = OpAtomicXor %int %var %device %none %ld | |
| OpReturn | |
| OpFunctionEnd | |
| )"; | |
| SinglePassRunAndMatch<opt::UpgradeMemoryModel>(text, true); | |
| } | |
| TEST_F(UpgradeMemoryModelTest, UpgradeModfNoFlags) { | |
| const std::string text = R"( | |
| ; CHECK: [[float:%\w+]] = OpTypeFloat 32 | |
| ; CHECK: [[float_0:%\w+]] = OpConstant [[float]] 0 | |
| ; CHECK: [[ptr:%\w+]] = OpTypePointer StorageBuffer [[float]] | |
| ; CHECK: [[var:%\w+]] = OpVariable [[ptr]] StorageBuffer | |
| ; CHECK: [[struct:%\w+]] = OpTypeStruct [[float]] [[float]] | |
| ; CHECK: [[modfstruct:%\w+]] = OpExtInst [[struct]] {{%\w+}} ModfStruct [[float_0]] | |
| ; CHECK: [[ex0:%\w+]] = OpCompositeExtract [[float]] [[modfstruct]] 0 | |
| ; CHECK: [[ex1:%\w+]] = OpCompositeExtract [[float]] [[modfstruct]] 1 | |
| ; CHECK: OpStore [[var]] [[ex1]] | |
| ; CHECK-NOT: NonPrivatePointer | |
| ; CHECK: OpFAdd [[float]] [[float_0]] [[ex0]] | |
| OpCapability Shader | |
| OpMemoryModel Logical GLSL450 | |
| %import = OpExtInstImport "GLSL.std.450" | |
| OpEntryPoint GLCompute %func "func" | |
| %void = OpTypeVoid | |
| %float = OpTypeFloat 32 | |
| %float_0 = OpConstant %float 0 | |
| %ptr_ssbo_float = OpTypePointer StorageBuffer %float | |
| %ssbo_var = OpVariable %ptr_ssbo_float StorageBuffer | |
| %func_ty = OpTypeFunction %void | |
| %func = OpFunction %void None %func_ty | |
| %1 = OpLabel | |
| %2 = OpExtInst %float %import Modf %float_0 %ssbo_var | |
| %3 = OpFAdd %float %float_0 %2 | |
| OpReturn | |
| OpFunctionEnd | |
| )"; | |
| SinglePassRunAndMatch<opt::UpgradeMemoryModel>(text, true); | |
| } | |
| TEST_F(UpgradeMemoryModelTest, UpgradeModfWorkgroupCoherent) { | |
| const std::string text = R"( | |
| ; CHECK: [[float:%\w+]] = OpTypeFloat 32 | |
| ; CHECK: [[float_0:%\w+]] = OpConstant [[float]] 0 | |
| ; CHECK: [[ptr:%\w+]] = OpTypePointer Workgroup [[float]] | |
| ; CHECK: [[var:%\w+]] = OpVariable [[ptr]] Workgroup | |
| ; CHECK: [[struct:%\w+]] = OpTypeStruct [[float]] [[float]] | |
| ; CHECK: [[wg_scope:%\w+]] = OpConstant {{%\w+}} 2 | |
| ; CHECK: [[modfstruct:%\w+]] = OpExtInst [[struct]] {{%\w+}} ModfStruct [[float_0]] | |
| ; CHECK: [[ex0:%\w+]] = OpCompositeExtract [[float]] [[modfstruct]] 0 | |
| ; CHECK: [[ex1:%\w+]] = OpCompositeExtract [[float]] [[modfstruct]] 1 | |
| ; CHECK: OpStore [[var]] [[ex1]] MakePointerAvailable|NonPrivatePointer [[wg_scope]] | |
| ; CHECK: OpFAdd [[float]] [[float_0]] [[ex0]] | |
| OpCapability Shader | |
| OpMemoryModel Logical GLSL450 | |
| %import = OpExtInstImport "GLSL.std.450" | |
| OpEntryPoint GLCompute %func "func" | |
| OpDecorate %wg_var Coherent | |
| %void = OpTypeVoid | |
| %float = OpTypeFloat 32 | |
| %float_0 = OpConstant %float 0 | |
| %ptr_wg_float = OpTypePointer Workgroup %float | |
| %wg_var = OpVariable %ptr_wg_float Workgroup | |
| %func_ty = OpTypeFunction %void | |
| %func = OpFunction %void None %func_ty | |
| %1 = OpLabel | |
| %2 = OpExtInst %float %import Modf %float_0 %wg_var | |
| %3 = OpFAdd %float %float_0 %2 | |
| OpReturn | |
| OpFunctionEnd | |
| )"; | |
| SinglePassRunAndMatch<opt::UpgradeMemoryModel>(text, true); | |
| } | |
| TEST_F(UpgradeMemoryModelTest, UpgradeModfSSBOCoherent) { | |
| const std::string text = R"( | |
| ; CHECK: [[float:%\w+]] = OpTypeFloat 32 | |
| ; CHECK: [[float_0:%\w+]] = OpConstant [[float]] 0 | |
| ; CHECK: [[ptr:%\w+]] = OpTypePointer StorageBuffer [[float]] | |
| ; CHECK: [[var:%\w+]] = OpVariable [[ptr]] StorageBuffer | |
| ; CHECK: [[struct:%\w+]] = OpTypeStruct [[float]] [[float]] | |
| ; CHECK: [[qf_scope:%\w+]] = OpConstant {{%\w+}} 5 | |
| ; CHECK: [[modfstruct:%\w+]] = OpExtInst [[struct]] {{%\w+}} ModfStruct [[float_0]] | |
| ; CHECK: [[ex0:%\w+]] = OpCompositeExtract [[float]] [[modfstruct]] 0 | |
| ; CHECK: [[ex1:%\w+]] = OpCompositeExtract [[float]] [[modfstruct]] 1 | |
| ; CHECK: OpStore [[var]] [[ex1]] MakePointerAvailable|NonPrivatePointer [[qf_scope]] | |
| ; CHECK: OpFAdd [[float]] [[float_0]] [[ex0]] | |
| OpCapability Shader | |
| OpMemoryModel Logical GLSL450 | |
| %import = OpExtInstImport "GLSL.std.450" | |
| OpEntryPoint GLCompute %func "func" | |
| OpDecorate %ssbo_var Coherent | |
| %void = OpTypeVoid | |
| %float = OpTypeFloat 32 | |
| %float_0 = OpConstant %float 0 | |
| %ptr_ssbo_float = OpTypePointer StorageBuffer %float | |
| %ssbo_var = OpVariable %ptr_ssbo_float StorageBuffer | |
| %func_ty = OpTypeFunction %void | |
| %func = OpFunction %void None %func_ty | |
| %1 = OpLabel | |
| %2 = OpExtInst %float %import Modf %float_0 %ssbo_var | |
| %3 = OpFAdd %float %float_0 %2 | |
| OpReturn | |
| OpFunctionEnd | |
| )"; | |
| SinglePassRunAndMatch<opt::UpgradeMemoryModel>(text, true); | |
| } | |
| TEST_F(UpgradeMemoryModelTest, UpgradeModfSSBOVolatile) { | |
| const std::string text = R"( | |
| ; CHECK: [[float:%\w+]] = OpTypeFloat 32 | |
| ; CHECK: [[float_0:%\w+]] = OpConstant [[float]] 0 | |
| ; CHECK: [[ptr:%\w+]] = OpTypePointer StorageBuffer [[float]] | |
| ; CHECK: [[var:%\w+]] = OpVariable [[ptr]] StorageBuffer | |
| ; CHECK: [[struct:%\w+]] = OpTypeStruct [[float]] [[float]] | |
| ; CHECK: [[modfstruct:%\w+]] = OpExtInst [[struct]] {{%\w+}} ModfStruct [[float_0]] | |
| ; CHECK: [[ex0:%\w+]] = OpCompositeExtract [[float]] [[modfstruct]] 0 | |
| ; CHECK: [[ex1:%\w+]] = OpCompositeExtract [[float]] [[modfstruct]] 1 | |
| ; CHECK: OpStore [[var]] [[ex1]] Volatile | |
| ; CHECK: OpFAdd [[float]] [[float_0]] [[ex0]] | |
| OpCapability Shader | |
| OpMemoryModel Logical GLSL450 | |
| %import = OpExtInstImport "GLSL.std.450" | |
| OpEntryPoint GLCompute %func "func" | |
| OpDecorate %wg_var Volatile | |
| %void = OpTypeVoid | |
| %float = OpTypeFloat 32 | |
| %float_0 = OpConstant %float 0 | |
| %ptr_ssbo_float = OpTypePointer StorageBuffer %float | |
| %wg_var = OpVariable %ptr_ssbo_float StorageBuffer | |
| %func_ty = OpTypeFunction %void | |
| %func = OpFunction %void None %func_ty | |
| %1 = OpLabel | |
| %2 = OpExtInst %float %import Modf %float_0 %wg_var | |
| %3 = OpFAdd %float %float_0 %2 | |
| OpReturn | |
| OpFunctionEnd | |
| )"; | |
| SinglePassRunAndMatch<opt::UpgradeMemoryModel>(text, true); | |
| } | |
| TEST_F(UpgradeMemoryModelTest, UpgradeFrexpNoFlags) { | |
| const std::string text = R"( | |
| ; CHECK: [[float:%\w+]] = OpTypeFloat 32 | |
| ; CHECK: [[float_0:%\w+]] = OpConstant [[float]] 0 | |
| ; CHECK: [[int:%\w+]] = OpTypeInt 32 0 | |
| ; CHECK: [[ptr:%\w+]] = OpTypePointer StorageBuffer [[int]] | |
| ; CHECK: [[var:%\w+]] = OpVariable [[ptr]] StorageBuffer | |
| ; CHECK: [[struct:%\w+]] = OpTypeStruct [[float]] [[int]] | |
| ; CHECK: [[modfstruct:%\w+]] = OpExtInst [[struct]] {{%\w+}} FrexpStruct [[float_0]] | |
| ; CHECK: [[ex0:%\w+]] = OpCompositeExtract [[float]] [[modfstruct]] 0 | |
| ; CHECK: [[ex1:%\w+]] = OpCompositeExtract [[int]] [[modfstruct]] 1 | |
| ; CHECK: OpStore [[var]] [[ex1]] | |
| ; CHECK-NOT: NonPrivatePointer | |
| ; CHECK: OpFAdd [[float]] [[float_0]] [[ex0]] | |
| OpCapability Shader | |
| OpMemoryModel Logical GLSL450 | |
| %import = OpExtInstImport "GLSL.std.450" | |
| OpEntryPoint GLCompute %func "func" | |
| %void = OpTypeVoid | |
| %float = OpTypeFloat 32 | |
| %float_0 = OpConstant %float 0 | |
| %int = OpTypeInt 32 0 | |
| %ptr_ssbo_int = OpTypePointer StorageBuffer %int | |
| %ssbo_var = OpVariable %ptr_ssbo_int StorageBuffer | |
| %func_ty = OpTypeFunction %void | |
| %func = OpFunction %void None %func_ty | |
| %1 = OpLabel | |
| %2 = OpExtInst %float %import Frexp %float_0 %ssbo_var | |
| %3 = OpFAdd %float %float_0 %2 | |
| OpReturn | |
| OpFunctionEnd | |
| )"; | |
| SinglePassRunAndMatch<opt::UpgradeMemoryModel>(text, true); | |
| } | |
| TEST_F(UpgradeMemoryModelTest, UpgradeFrexpWorkgroupCoherent) { | |
| const std::string text = R"( | |
| ; CHECK: [[float:%\w+]] = OpTypeFloat 32 | |
| ; CHECK: [[float_0:%\w+]] = OpConstant [[float]] 0 | |
| ; CHECK: [[int:%\w+]] = OpTypeInt 32 0 | |
| ; CHECK: [[ptr:%\w+]] = OpTypePointer Workgroup [[int]] | |
| ; CHECK: [[var:%\w+]] = OpVariable [[ptr]] Workgroup | |
| ; CHECK: [[struct:%\w+]] = OpTypeStruct [[float]] [[int]] | |
| ; CHECK: [[wg_scope:%\w+]] = OpConstant {{%\w+}} 2 | |
| ; CHECK: [[modfstruct:%\w+]] = OpExtInst [[struct]] {{%\w+}} FrexpStruct [[float_0]] | |
| ; CHECK: [[ex0:%\w+]] = OpCompositeExtract [[float]] [[modfstruct]] 0 | |
| ; CHECK: [[ex1:%\w+]] = OpCompositeExtract [[int]] [[modfstruct]] 1 | |
| ; CHECK: OpStore [[var]] [[ex1]] MakePointerAvailable|NonPrivatePointer [[wg_scope]] | |
| ; CHECK: OpFAdd [[float]] [[float_0]] [[ex0]] | |
| OpCapability Shader | |
| OpMemoryModel Logical GLSL450 | |
| %import = OpExtInstImport "GLSL.std.450" | |
| OpEntryPoint GLCompute %func "func" | |
| OpDecorate %wg_var Coherent | |
| %void = OpTypeVoid | |
| %float = OpTypeFloat 32 | |
| %float_0 = OpConstant %float 0 | |
| %int = OpTypeInt 32 0 | |
| %ptr_wg_int = OpTypePointer Workgroup %int | |
| %wg_var = OpVariable %ptr_wg_int Workgroup | |
| %func_ty = OpTypeFunction %void | |
| %func = OpFunction %void None %func_ty | |
| %1 = OpLabel | |
| %2 = OpExtInst %float %import Frexp %float_0 %wg_var | |
| %3 = OpFAdd %float %float_0 %2 | |
| OpReturn | |
| OpFunctionEnd | |
| )"; | |
| SinglePassRunAndMatch<opt::UpgradeMemoryModel>(text, true); | |
| } | |
| TEST_F(UpgradeMemoryModelTest, UpgradeFrexpSSBOCoherent) { | |
| const std::string text = R"( | |
| ; CHECK: [[float:%\w+]] = OpTypeFloat 32 | |
| ; CHECK: [[float_0:%\w+]] = OpConstant [[float]] 0 | |
| ; CHECK: [[int:%\w+]] = OpTypeInt 32 0 | |
| ; CHECK: [[ptr:%\w+]] = OpTypePointer StorageBuffer [[int]] | |
| ; CHECK: [[var:%\w+]] = OpVariable [[ptr]] StorageBuffer | |
| ; CHECK: [[struct:%\w+]] = OpTypeStruct [[float]] [[int]] | |
| ; CHECK: [[qf_scope:%\w+]] = OpConstant {{%\w+}} 5 | |
| ; CHECK: [[modfstruct:%\w+]] = OpExtInst [[struct]] {{%\w+}} FrexpStruct [[float_0]] | |
| ; CHECK: [[ex0:%\w+]] = OpCompositeExtract [[float]] [[modfstruct]] 0 | |
| ; CHECK: [[ex1:%\w+]] = OpCompositeExtract [[int]] [[modfstruct]] 1 | |
| ; CHECK: OpStore [[var]] [[ex1]] MakePointerAvailable|NonPrivatePointer [[qf_scope]] | |
| ; CHECK: OpFAdd [[float]] [[float_0]] [[ex0]] | |
| OpCapability Shader | |
| OpMemoryModel Logical GLSL450 | |
| %import = OpExtInstImport "GLSL.std.450" | |
| OpEntryPoint GLCompute %func "func" | |
| OpDecorate %ssbo_var Coherent | |
| %void = OpTypeVoid | |
| %float = OpTypeFloat 32 | |
| %float_0 = OpConstant %float 0 | |
| %int = OpTypeInt 32 0 | |
| %ptr_ssbo_int = OpTypePointer StorageBuffer %int | |
| %ssbo_var = OpVariable %ptr_ssbo_int StorageBuffer | |
| %func_ty = OpTypeFunction %void | |
| %func = OpFunction %void None %func_ty | |
| %1 = OpLabel | |
| %2 = OpExtInst %float %import Frexp %float_0 %ssbo_var | |
| %3 = OpFAdd %float %float_0 %2 | |
| OpReturn | |
| OpFunctionEnd | |
| )"; | |
| SinglePassRunAndMatch<opt::UpgradeMemoryModel>(text, true); | |
| } | |
| TEST_F(UpgradeMemoryModelTest, UpgradeFrexpSSBOVolatile) { | |
| const std::string text = R"( | |
| ; CHECK: [[float:%\w+]] = OpTypeFloat 32 | |
| ; CHECK: [[float_0:%\w+]] = OpConstant [[float]] 0 | |
| ; CHECK: [[int:%\w+]] = OpTypeInt 32 0 | |
| ; CHECK: [[ptr:%\w+]] = OpTypePointer StorageBuffer [[int]] | |
| ; CHECK: [[var:%\w+]] = OpVariable [[ptr]] StorageBuffer | |
| ; CHECK: [[struct:%\w+]] = OpTypeStruct [[float]] [[int]] | |
| ; CHECK: [[modfstruct:%\w+]] = OpExtInst [[struct]] {{%\w+}} FrexpStruct [[float_0]] | |
| ; CHECK: [[ex0:%\w+]] = OpCompositeExtract [[float]] [[modfstruct]] 0 | |
| ; CHECK: [[ex1:%\w+]] = OpCompositeExtract [[int]] [[modfstruct]] 1 | |
| ; CHECK: OpStore [[var]] [[ex1]] Volatile | |
| ; CHECK: OpFAdd [[float]] [[float_0]] [[ex0]] | |
| OpCapability Shader | |
| OpMemoryModel Logical GLSL450 | |
| %import = OpExtInstImport "GLSL.std.450" | |
| OpEntryPoint GLCompute %func "func" | |
| OpDecorate %wg_var Volatile | |
| %void = OpTypeVoid | |
| %float = OpTypeFloat 32 | |
| %float_0 = OpConstant %float 0 | |
| %int = OpTypeInt 32 0 | |
| %ptr_ssbo_int = OpTypePointer StorageBuffer %int | |
| %wg_var = OpVariable %ptr_ssbo_int StorageBuffer | |
| %func_ty = OpTypeFunction %void | |
| %func = OpFunction %void None %func_ty | |
| %1 = OpLabel | |
| %2 = OpExtInst %float %import Frexp %float_0 %wg_var | |
| %3 = OpFAdd %float %float_0 %2 | |
| OpReturn | |
| OpFunctionEnd | |
| )"; | |
| SinglePassRunAndMatch<opt::UpgradeMemoryModel>(text, true); | |
| } | |
| TEST_F(UpgradeMemoryModelTest, SPV14NormalizeCopyMemoryAddOperands) { | |
| const std::string text = R"( | |
| ; CHECK: OpCopyMemory {{%\w+}} {{%\w+}} None None | |
| OpCapability Shader | |
| OpMemoryModel Logical GLSL450 | |
| OpEntryPoint GLCompute %func "func" %src %dst | |
| %void = OpTypeVoid | |
| %int = OpTypeInt 32 0 | |
| %ptr_ssbo_int = OpTypePointer StorageBuffer %int | |
| %src = OpVariable %ptr_ssbo_int StorageBuffer | |
| %dst = OpVariable %ptr_ssbo_int StorageBuffer | |
| %void_fn = OpTypeFunction %void | |
| %func = OpFunction %void None %void_fn | |
| %entry = OpLabel | |
| OpCopyMemory %dst %src | |
| OpReturn | |
| OpFunctionEnd | |
| )"; | |
| SetTargetEnv(SPV_ENV_UNIVERSAL_1_4); | |
| SinglePassRunAndMatch<opt::UpgradeMemoryModel>(text, true); | |
| } | |
| TEST_F(UpgradeMemoryModelTest, SPV14NormalizeCopyMemoryDuplicateOperand) { | |
| const std::string text = R"( | |
| ; CHECK: OpCopyMemory {{%\w+}} {{%\w+}} Nontemporal Nontemporal | |
| OpCapability Shader | |
| OpMemoryModel Logical GLSL450 | |
| OpEntryPoint GLCompute %func "func" %src %dst | |
| %void = OpTypeVoid | |
| %int = OpTypeInt 32 0 | |
| %ptr_ssbo_int = OpTypePointer StorageBuffer %int | |
| %src = OpVariable %ptr_ssbo_int StorageBuffer | |
| %dst = OpVariable %ptr_ssbo_int StorageBuffer | |
| %void_fn = OpTypeFunction %void | |
| %func = OpFunction %void None %void_fn | |
| %entry = OpLabel | |
| OpCopyMemory %dst %src Nontemporal | |
| OpReturn | |
| OpFunctionEnd | |
| )"; | |
| SetTargetEnv(SPV_ENV_UNIVERSAL_1_4); | |
| SinglePassRunAndMatch<opt::UpgradeMemoryModel>(text, true); | |
| } | |
| TEST_F(UpgradeMemoryModelTest, SPV14NormalizeCopyMemoryDuplicateOperands) { | |
| const std::string text = R"( | |
| ; CHECK: OpCopyMemory {{%\w+}} {{%\w+}} Aligned 4 Aligned 4 | |
| OpCapability Shader | |
| OpMemoryModel Logical GLSL450 | |
| OpEntryPoint GLCompute %func "func" %src %dst | |
| %void = OpTypeVoid | |
| %int = OpTypeInt 32 0 | |
| %ptr_ssbo_int = OpTypePointer StorageBuffer %int | |
| %src = OpVariable %ptr_ssbo_int StorageBuffer | |
| %dst = OpVariable %ptr_ssbo_int StorageBuffer | |
| %void_fn = OpTypeFunction %void | |
| %func = OpFunction %void None %void_fn | |
| %entry = OpLabel | |
| OpCopyMemory %dst %src Aligned 4 | |
| OpReturn | |
| OpFunctionEnd | |
| )"; | |
| SetTargetEnv(SPV_ENV_UNIVERSAL_1_4); | |
| SinglePassRunAndMatch<opt::UpgradeMemoryModel>(text, true); | |
| } | |
| TEST_F(UpgradeMemoryModelTest, SPV14CopyMemoryDstCoherent) { | |
| const std::string text = R"( | |
| ; CHECK: [[scope:%\w+]] = OpConstant {{%\w+}} 5 | |
| ; CHECK: OpCopyMemory {{%\w+}} {{%\w+}} MakePointerAvailable|NonPrivatePointer [[scope]] None | |
| OpCapability Shader | |
| OpMemoryModel Logical GLSL450 | |
| OpEntryPoint GLCompute %func "func" %src %dst | |
| OpDecorate %dst Coherent | |
| %void = OpTypeVoid | |
| %int = OpTypeInt 32 0 | |
| %ptr_ssbo_int = OpTypePointer StorageBuffer %int | |
| %src = OpVariable %ptr_ssbo_int StorageBuffer | |
| %dst = OpVariable %ptr_ssbo_int StorageBuffer | |
| %void_fn = OpTypeFunction %void | |
| %func = OpFunction %void None %void_fn | |
| %entry = OpLabel | |
| OpCopyMemory %dst %src | |
| OpReturn | |
| OpFunctionEnd | |
| )"; | |
| SetTargetEnv(SPV_ENV_UNIVERSAL_1_4); | |
| SinglePassRunAndMatch<opt::UpgradeMemoryModel>(text, true); | |
| } | |
| TEST_F(UpgradeMemoryModelTest, SPV14CopyMemoryDstCoherentPreviousArgs) { | |
| const std::string text = R"( | |
| ; CHECK: [[scope:%\w+]] = OpConstant {{%\w+}} 5 | |
| ; CHECK: OpCopyMemory {{%\w+}} {{%\w+}} Aligned|MakePointerAvailable|NonPrivatePointer 4 [[scope]] Aligned 4 | |
| OpCapability Shader | |
| OpMemoryModel Logical GLSL450 | |
| OpEntryPoint GLCompute %func "func" %src %dst | |
| OpDecorate %dst Coherent | |
| %void = OpTypeVoid | |
| %int = OpTypeInt 32 0 | |
| %ptr_ssbo_int = OpTypePointer StorageBuffer %int | |
| %src = OpVariable %ptr_ssbo_int StorageBuffer | |
| %dst = OpVariable %ptr_ssbo_int StorageBuffer | |
| %void_fn = OpTypeFunction %void | |
| %func = OpFunction %void None %void_fn | |
| %entry = OpLabel | |
| OpCopyMemory %dst %src Aligned 4 | |
| OpReturn | |
| OpFunctionEnd | |
| )"; | |
| SetTargetEnv(SPV_ENV_UNIVERSAL_1_4); | |
| SinglePassRunAndMatch<opt::UpgradeMemoryModel>(text, true); | |
| } | |
| TEST_F(UpgradeMemoryModelTest, SPV14CopyMemorySrcCoherent) { | |
| const std::string text = R"( | |
| ; CHECK: [[scope:%\w+]] = OpConstant {{%\w+}} 5 | |
| ; CHECK: OpCopyMemory {{%\w+}} {{%\w+}} None MakePointerVisible|NonPrivatePointer [[scope]] | |
| OpCapability Shader | |
| OpMemoryModel Logical GLSL450 | |
| OpEntryPoint GLCompute %func "func" %src %dst | |
| OpDecorate %src Coherent | |
| %void = OpTypeVoid | |
| %int = OpTypeInt 32 0 | |
| %ptr_ssbo_int = OpTypePointer StorageBuffer %int | |
| %src = OpVariable %ptr_ssbo_int StorageBuffer | |
| %dst = OpVariable %ptr_ssbo_int StorageBuffer | |
| %void_fn = OpTypeFunction %void | |
| %func = OpFunction %void None %void_fn | |
| %entry = OpLabel | |
| OpCopyMemory %dst %src | |
| OpReturn | |
| OpFunctionEnd | |
| )"; | |
| SetTargetEnv(SPV_ENV_UNIVERSAL_1_4); | |
| SinglePassRunAndMatch<opt::UpgradeMemoryModel>(text, true); | |
| } | |
| TEST_F(UpgradeMemoryModelTest, SPV14CopyMemorySrcCoherentPreviousArgs) { | |
| const std::string text = R"( | |
| ; CHECK: [[scope:%\w+]] = OpConstant {{%\w+}} 5 | |
| ; CHECK: OpCopyMemory {{%\w+}} {{%\w+}} Aligned 4 Aligned|MakePointerVisible|NonPrivatePointer 4 [[scope]] | |
| OpCapability Shader | |
| OpMemoryModel Logical GLSL450 | |
| OpEntryPoint GLCompute %func "func" %src %dst | |
| OpDecorate %src Coherent | |
| %void = OpTypeVoid | |
| %int = OpTypeInt 32 0 | |
| %ptr_ssbo_int = OpTypePointer StorageBuffer %int | |
| %src = OpVariable %ptr_ssbo_int StorageBuffer | |
| %dst = OpVariable %ptr_ssbo_int StorageBuffer | |
| %void_fn = OpTypeFunction %void | |
| %func = OpFunction %void None %void_fn | |
| %entry = OpLabel | |
| OpCopyMemory %dst %src Aligned 4 | |
| OpReturn | |
| OpFunctionEnd | |
| )"; | |
| SetTargetEnv(SPV_ENV_UNIVERSAL_1_4); | |
| SinglePassRunAndMatch<opt::UpgradeMemoryModel>(text, true); | |
| } | |
| TEST_F(UpgradeMemoryModelTest, SPV14CopyMemoryBothCoherent) { | |
| const std::string text = R"( | |
| ; CHECK-DAG: [[queue:%\w+]] = OpConstant {{%\w+}} 5 | |
| ; CHECK-DAG: [[wg:%\w+]] = OpConstant {{%\w+}} 2 | |
| ; CHECK: OpCopyMemory {{%\w+}} {{%\w+}} MakePointerAvailable|NonPrivatePointer [[wg]] MakePointerVisible|NonPrivatePointer [[queue]] | |
| OpCapability Shader | |
| OpMemoryModel Logical GLSL450 | |
| OpEntryPoint GLCompute %func "func" %src %dst | |
| OpDecorate %src Coherent | |
| %void = OpTypeVoid | |
| %int = OpTypeInt 32 0 | |
| %ptr_ssbo_int = OpTypePointer StorageBuffer %int | |
| %ptr_wg_int = OpTypePointer Workgroup %int | |
| %src = OpVariable %ptr_ssbo_int StorageBuffer | |
| %dst = OpVariable %ptr_wg_int Workgroup | |
| %void_fn = OpTypeFunction %void | |
| %func = OpFunction %void None %void_fn | |
| %entry = OpLabel | |
| OpCopyMemory %dst %src | |
| OpReturn | |
| OpFunctionEnd | |
| )"; | |
| SetTargetEnv(SPV_ENV_UNIVERSAL_1_4); | |
| SinglePassRunAndMatch<opt::UpgradeMemoryModel>(text, true); | |
| } | |
| TEST_F(UpgradeMemoryModelTest, SPV14CopyMemoryBothCoherentPreviousArgs) { | |
| const std::string text = R"( | |
| ; CHECK-DAG: [[queue:%\w+]] = OpConstant {{%\w+}} 5 | |
| ; CHECK-DAG: [[wg:%\w+]] = OpConstant {{%\w+}} 2 | |
| ; CHECK: OpCopyMemory {{%\w+}} {{%\w+}} Aligned|MakePointerAvailable|NonPrivatePointer 4 [[queue]] Aligned|MakePointerVisible|NonPrivatePointer 4 [[wg]] | |
| OpCapability Shader | |
| OpMemoryModel Logical GLSL450 | |
| OpEntryPoint GLCompute %func "func" %src %dst | |
| OpDecorate %dst Coherent | |
| %void = OpTypeVoid | |
| %int = OpTypeInt 32 0 | |
| %ptr_ssbo_int = OpTypePointer StorageBuffer %int | |
| %ptr_wg_int = OpTypePointer Workgroup %int | |
| %src = OpVariable %ptr_wg_int Workgroup | |
| %dst = OpVariable %ptr_ssbo_int StorageBuffer | |
| %void_fn = OpTypeFunction %void | |
| %func = OpFunction %void None %void_fn | |
| %entry = OpLabel | |
| OpCopyMemory %dst %src Aligned 4 | |
| OpReturn | |
| OpFunctionEnd | |
| )"; | |
| SetTargetEnv(SPV_ENV_UNIVERSAL_1_4); | |
| SinglePassRunAndMatch<opt::UpgradeMemoryModel>(text, true); | |
| } | |
| TEST_F(UpgradeMemoryModelTest, SPV14CopyMemoryBothVolatile) { | |
| const std::string text = R"( | |
| ; CHECK: OpCopyMemory {{%\w+}} {{%\w+}} Volatile Volatile | |
| OpCapability Shader | |
| OpMemoryModel Logical GLSL450 | |
| OpEntryPoint GLCompute %func "func" %src %dst | |
| OpDecorate %src Volatile | |
| OpDecorate %dst Volatile | |
| %void = OpTypeVoid | |
| %int = OpTypeInt 32 0 | |
| %ptr_ssbo_int = OpTypePointer StorageBuffer %int | |
| %src = OpVariable %ptr_ssbo_int StorageBuffer | |
| %dst = OpVariable %ptr_ssbo_int StorageBuffer | |
| %void_fn = OpTypeFunction %void | |
| %func = OpFunction %void None %void_fn | |
| %entry = OpLabel | |
| OpCopyMemory %dst %src | |
| OpReturn | |
| OpFunctionEnd | |
| )"; | |
| SetTargetEnv(SPV_ENV_UNIVERSAL_1_4); | |
| SinglePassRunAndMatch<opt::UpgradeMemoryModel>(text, true); | |
| } | |
| TEST_F(UpgradeMemoryModelTest, SPV14CopyMemoryBothVolatilePreviousArgs) { | |
| const std::string text = R"( | |
| ; CHECK: OpCopyMemory {{%\w+}} {{%\w+}} Volatile|Aligned 4 Volatile|Aligned 4 | |
| OpCapability Shader | |
| OpMemoryModel Logical GLSL450 | |
| OpEntryPoint GLCompute %func "func" %src %dst | |
| OpDecorate %src Volatile | |
| OpDecorate %dst Volatile | |
| %void = OpTypeVoid | |
| %int = OpTypeInt 32 0 | |
| %ptr_ssbo_int = OpTypePointer StorageBuffer %int | |
| %src = OpVariable %ptr_ssbo_int StorageBuffer | |
| %dst = OpVariable %ptr_ssbo_int StorageBuffer | |
| %void_fn = OpTypeFunction %void | |
| %func = OpFunction %void None %void_fn | |
| %entry = OpLabel | |
| OpCopyMemory %dst %src Aligned 4 | |
| OpReturn | |
| OpFunctionEnd | |
| )"; | |
| SetTargetEnv(SPV_ENV_UNIVERSAL_1_4); | |
| SinglePassRunAndMatch<opt::UpgradeMemoryModel>(text, true); | |
| } | |
| TEST_F(UpgradeMemoryModelTest, SPV14CopyMemoryDstCoherentTwoOperands) { | |
| const std::string text = R"( | |
| ; CHECK: [[scope:%\w+]] = OpConstant {{%\w+}} 5 | |
| ; CHECK: OpCopyMemory {{%\w+}} {{%\w+}} MakePointerAvailable|NonPrivatePointer [[scope]] None | |
| OpCapability Shader | |
| OpMemoryModel Logical GLSL450 | |
| OpEntryPoint GLCompute %func "func" %src %dst | |
| OpDecorate %dst Coherent | |
| %void = OpTypeVoid | |
| %int = OpTypeInt 32 0 | |
| %ptr_ssbo_int = OpTypePointer StorageBuffer %int | |
| %src = OpVariable %ptr_ssbo_int StorageBuffer | |
| %dst = OpVariable %ptr_ssbo_int StorageBuffer | |
| %void_fn = OpTypeFunction %void | |
| %func = OpFunction %void None %void_fn | |
| %entry = OpLabel | |
| OpCopyMemory %dst %src None None | |
| OpReturn | |
| OpFunctionEnd | |
| )"; | |
| SetTargetEnv(SPV_ENV_UNIVERSAL_1_4); | |
| SinglePassRunAndMatch<opt::UpgradeMemoryModel>(text, true); | |
| } | |
| TEST_F(UpgradeMemoryModelTest, | |
| SPV14CopyMemoryDstCoherentPreviousArgsTwoOperands) { | |
| const std::string text = R"( | |
| ; CHECK: [[scope:%\w+]] = OpConstant {{%\w+}} 5 | |
| ; CHECK: OpCopyMemory {{%\w+}} {{%\w+}} Aligned|MakePointerAvailable|NonPrivatePointer 4 [[scope]] Aligned 8 | |
| OpCapability Shader | |
| OpMemoryModel Logical GLSL450 | |
| OpEntryPoint GLCompute %func "func" %src %dst | |
| OpDecorate %dst Coherent | |
| %void = OpTypeVoid | |
| %int = OpTypeInt 32 0 | |
| %ptr_ssbo_int = OpTypePointer StorageBuffer %int | |
| %src = OpVariable %ptr_ssbo_int StorageBuffer | |
| %dst = OpVariable %ptr_ssbo_int StorageBuffer | |
| %void_fn = OpTypeFunction %void | |
| %func = OpFunction %void None %void_fn | |
| %entry = OpLabel | |
| OpCopyMemory %dst %src Aligned 4 Aligned 8 | |
| OpReturn | |
| OpFunctionEnd | |
| )"; | |
| SetTargetEnv(SPV_ENV_UNIVERSAL_1_4); | |
| SinglePassRunAndMatch<opt::UpgradeMemoryModel>(text, true); | |
| } | |
| TEST_F(UpgradeMemoryModelTest, VolatileAtomicLoad) { | |
| const std::string text = R"( | |
| ; CHECK-NOT: OpDecorate {{.*}} Volatile | |
| ; CHECK: [[volatile:%[a-zA-Z0-9_]+]] = OpConstant [[int:%[a-zA-Z0-9_]+]] 32768 | |
| ; CHECK: OpAtomicLoad [[int]] {{.*}} {{.*}} [[volatile]] | |
| OpCapability Shader | |
| OpCapability Linkage | |
| OpMemoryModel Logical GLSL450 | |
| OpDecorate %ssbo_var Volatile | |
| %void = OpTypeVoid | |
| %int = OpTypeInt 32 0 | |
| %device = OpConstant %int 1 | |
| %relaxed = OpConstant %int 0 | |
| %ptr_ssbo_int = OpTypePointer StorageBuffer %int | |
| %ssbo_var = OpVariable %ptr_ssbo_int StorageBuffer | |
| %void_fn = OpTypeFunction %void | |
| %func = OpFunction %void None %void_fn | |
| %entry = OpLabel | |
| %ld = OpAtomicLoad %int %ssbo_var %device %relaxed | |
| OpReturn | |
| OpFunctionEnd | |
| )"; | |
| SinglePassRunAndMatch<opt::UpgradeMemoryModel>(text, true); | |
| } | |
| TEST_F(UpgradeMemoryModelTest, VolatileAtomicLoadPreviousFlags) { | |
| const std::string text = R"( | |
| ; CHECK-NOT: OpDecorate {{.*}} Volatile | |
| ; CHECK: [[volatile:%[a-zA-Z0-9_]+]] = OpConstant [[int:%[a-zA-Z0-9_]+]] 32834 | |
| ; CHECK: OpAtomicLoad [[int]] {{.*}} {{.*}} [[volatile]] | |
| OpCapability Shader | |
| OpCapability Linkage | |
| OpMemoryModel Logical GLSL450 | |
| OpDecorate %ssbo_var Volatile | |
| %void = OpTypeVoid | |
| %int = OpTypeInt 32 0 | |
| %device = OpConstant %int 1 | |
| %acquire_ssbo = OpConstant %int 66 | |
| %ptr_ssbo_int = OpTypePointer StorageBuffer %int | |
| %ssbo_var = OpVariable %ptr_ssbo_int StorageBuffer | |
| %void_fn = OpTypeFunction %void | |
| %func = OpFunction %void None %void_fn | |
| %entry = OpLabel | |
| %ld = OpAtomicLoad %int %ssbo_var %device %acquire_ssbo | |
| OpReturn | |
| OpFunctionEnd | |
| )"; | |
| SinglePassRunAndMatch<opt::UpgradeMemoryModel>(text, true); | |
| } | |
| TEST_F(UpgradeMemoryModelTest, VolatileAtomicStore) { | |
| const std::string text = R"( | |
| ; CHECK-NOT: OpDecorate {{.*}} Volatile | |
| ; CHECK: [[volatile:%[a-zA-Z0-9_]+]] = OpConstant {{.*}} 32768 | |
| ; CHECK: OpAtomicStore {{.*}} {{.*}} [[volatile]] | |
| OpCapability Shader | |
| OpCapability Linkage | |
| OpMemoryModel Logical GLSL450 | |
| OpDecorate %ssbo_var Volatile | |
| %void = OpTypeVoid | |
| %int = OpTypeInt 32 0 | |
| %int_0 = OpConstant %int 0 | |
| %device = OpConstant %int 1 | |
| %relaxed = OpConstant %int 0 | |
| %ptr_ssbo_int = OpTypePointer StorageBuffer %int | |
| %ssbo_var = OpVariable %ptr_ssbo_int StorageBuffer | |
| %void_fn = OpTypeFunction %void | |
| %func = OpFunction %void None %void_fn | |
| %entry = OpLabel | |
| OpAtomicStore %ssbo_var %device %relaxed %int_0 | |
| OpReturn | |
| OpFunctionEnd | |
| )"; | |
| SinglePassRunAndMatch<opt::UpgradeMemoryModel>(text, true); | |
| } | |
| TEST_F(UpgradeMemoryModelTest, VolatileAtomicStorePreviousFlags) { | |
| const std::string text = R"( | |
| ; CHECK-NOT: OpDecorate {{.*}} Volatile | |
| ; CHECK: [[volatile:%[a-zA-Z0-9_]+]] = OpConstant {{.*}} 32836 | |
| ; CHECK: OpAtomicStore {{.*}} {{.*}} [[volatile]] | |
| OpCapability Shader | |
| OpCapability Linkage | |
| OpMemoryModel Logical GLSL450 | |
| OpDecorate %ssbo_var Volatile | |
| %void = OpTypeVoid | |
| %int = OpTypeInt 32 0 | |
| %int_0 = OpConstant %int 0 | |
| %device = OpConstant %int 1 | |
| %release_ssbo = OpConstant %int 68 | |
| %ptr_ssbo_int = OpTypePointer StorageBuffer %int | |
| %ssbo_var = OpVariable %ptr_ssbo_int StorageBuffer | |
| %void_fn = OpTypeFunction %void | |
| %func = OpFunction %void None %void_fn | |
| %entry = OpLabel | |
| OpAtomicStore %ssbo_var %device %release_ssbo %int_0 | |
| OpReturn | |
| OpFunctionEnd | |
| )"; | |
| SinglePassRunAndMatch<opt::UpgradeMemoryModel>(text, true); | |
| } | |
| TEST_F(UpgradeMemoryModelTest, VolatileAtomicCompareExchange) { | |
| const std::string text = R"( | |
| ; CHECK-NOT: OpDecorate {{.*}} Volatile | |
| ; CHECK: [[volatile:%[a-zA-Z0-9_]+]] = OpConstant [[int:%[a-zA-Z0-9_]+]] 32768 | |
| ; CHECK: OpAtomicCompareExchange [[int]] {{.*}} {{.*}} [[volatile]] [[volatile]] | |
| OpCapability Shader | |
| OpCapability Linkage | |
| OpMemoryModel Logical GLSL450 | |
| OpDecorate %ssbo_var Volatile | |
| %void = OpTypeVoid | |
| %int = OpTypeInt 32 0 | |
| %int_0 = OpConstant %int 0 | |
| %int_1 = OpConstant %int 1 | |
| %device = OpConstant %int 1 | |
| %relaxed = OpConstant %int 0 | |
| %ptr_ssbo_int = OpTypePointer StorageBuffer %int | |
| %ssbo_var = OpVariable %ptr_ssbo_int StorageBuffer | |
| %void_fn = OpTypeFunction %void | |
| %func = OpFunction %void None %void_fn | |
| %entry = OpLabel | |
| %ld = OpAtomicCompareExchange %int %ssbo_var %device %relaxed %relaxed %int_0 %int_1 | |
| OpReturn | |
| OpFunctionEnd | |
| )"; | |
| SinglePassRunAndMatch<opt::UpgradeMemoryModel>(text, true); | |
| } | |
| TEST_F(UpgradeMemoryModelTest, VolatileAtomicCompareExchangePreviousFlags) { | |
| const std::string text = R"( | |
| ; CHECK-NOT: OpDecorate {{.*}} Volatile | |
| ; CHECK: [[volatile_acq_rel:%[a-zA-Z0-9_]+]] = OpConstant [[int:%[a-zA-Z0-9_]+]] 32840 | |
| ; CHECK: [[volatile_acq:%[a-zA-Z0-9_]+]] = OpConstant [[int:%[a-zA-Z0-9_]+]] 32834 | |
| ; CHECK: OpAtomicCompareExchange [[int]] {{.*}} {{.*}} [[volatile_acq_rel]] [[volatile_acq]] | |
| OpCapability Shader | |
| OpCapability Linkage | |
| OpMemoryModel Logical GLSL450 | |
| OpDecorate %ssbo_var Volatile | |
| %void = OpTypeVoid | |
| %int = OpTypeInt 32 0 | |
| %int_0 = OpConstant %int 0 | |
| %int_1 = OpConstant %int 1 | |
| %device = OpConstant %int 1 | |
| %acq_ssbo = OpConstant %int 66 | |
| %acq_rel_ssbo = OpConstant %int 72 | |
| %ptr_ssbo_int = OpTypePointer StorageBuffer %int | |
| %ssbo_var = OpVariable %ptr_ssbo_int StorageBuffer | |
| %void_fn = OpTypeFunction %void | |
| %func = OpFunction %void None %void_fn | |
| %entry = OpLabel | |
| %ld = OpAtomicCompareExchange %int %ssbo_var %device %acq_rel_ssbo %acq_ssbo %int_0 %int_1 | |
| OpReturn | |
| OpFunctionEnd | |
| )"; | |
| SinglePassRunAndMatch<opt::UpgradeMemoryModel>(text, true); | |
| } | |
| TEST_F(UpgradeMemoryModelTest, VolatileAtomicLoadMemberDecoration) { | |
| const std::string text = R"( | |
| ; CHECK-NOT: OpMemberDecorate {{.*}} {{.*}} Volatile | |
| ; CHECK: [[relaxed:%[a-zA-Z0-9_]+]] = OpConstant {{.*}} 0 | |
| ; CHECK: [[volatile:%[a-zA-Z0-9_]+]] = OpConstant [[int:%[a-zA-Z0-9_]+]] 32768 | |
| ; CHECK: OpAtomicLoad [[int]] {{.*}} {{.*}} [[relaxed]] | |
| ; CHECK: OpAtomicLoad [[int]] {{.*}} {{.*}} [[volatile]] | |
| OpCapability Shader | |
| OpCapability Linkage | |
| OpMemoryModel Logical GLSL450 | |
| OpMemberDecorate %struct 1 Volatile | |
| %void = OpTypeVoid | |
| %int = OpTypeInt 32 0 | |
| %device = OpConstant %int 1 | |
| %relaxed = OpConstant %int 0 | |
| %int_0 = OpConstant %int 0 | |
| %int_1 = OpConstant %int 1 | |
| %ptr_ssbo_int = OpTypePointer StorageBuffer %int | |
| %struct = OpTypeStruct %int %int | |
| %ptr_ssbo_struct = OpTypePointer StorageBuffer %struct | |
| %ssbo_var = OpVariable %ptr_ssbo_struct StorageBuffer | |
| %void_fn = OpTypeFunction %void | |
| %func = OpFunction %void None %void_fn | |
| %entry = OpLabel | |
| %gep0 = OpAccessChain %ptr_ssbo_int %ssbo_var %int_0 | |
| %ld0 = OpAtomicLoad %int %gep0 %device %relaxed | |
| %gep1 = OpAccessChain %ptr_ssbo_int %ssbo_var %int_1 | |
| %ld1 = OpAtomicLoad %int %gep1 %device %relaxed | |
| OpReturn | |
| OpFunctionEnd | |
| )"; | |
| SinglePassRunAndMatch<opt::UpgradeMemoryModel>(text, true); | |
| } | |
| TEST_F(UpgradeMemoryModelTest, CoherentStructMemberInArray) { | |
| const std::string text = R"( | |
| ; CHECK-NOT: OpMemberDecorate | |
| ; CHECK: [[int:%[a-zA-Z0-9_]+]] = OpTypeInt 32 0 | |
| ; CHECK: [[device:%[a-zA-Z0-9_]+]] = OpConstant [[int]] 1 | |
| ; CHECK: OpLoad [[int]] {{.*}} MakePointerVisible|NonPrivatePointer | |
| OpCapability Shader | |
| OpCapability Linkage | |
| OpMemoryModel Logical GLSL450 | |
| OpMemberDecorate %inner 1 Coherent | |
| %void = OpTypeVoid | |
| %int = OpTypeInt 32 0 | |
| %int_0 = OpConstant %int 0 | |
| %int_1 = OpConstant %int 1 | |
| %int_4 = OpConstant %int 4 | |
| %inner = OpTypeStruct %int %int | |
| %array = OpTypeArray %inner %int_4 | |
| %struct = OpTypeStruct %array | |
| %ptr_ssbo_struct = OpTypePointer StorageBuffer %struct | |
| %ptr_ssbo_int = OpTypePointer StorageBuffer %int | |
| %ssbo_var = OpVariable %ptr_ssbo_struct StorageBuffer | |
| %void_fn = OpTypeFunction %void | |
| %func = OpFunction %void None %void_fn | |
| %entry = OpLabel | |
| %gep = OpAccessChain %ptr_ssbo_int %ssbo_var %int_0 %int_0 %int_1 | |
| %ld = OpLoad %int %gep | |
| OpReturn | |
| OpFunctionEnd | |
| )"; | |
| SinglePassRunAndMatch<opt::UpgradeMemoryModel>(text, true); | |
| } | |
| } // namespace |