| // 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 "gmock/gmock.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 %param 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 |