SPIRV-Tools/test/opt/upgrade_memory_model_test.cpp
alan-baker e510b1bac5
Update memory model (#1904)
Upgrade to VulkanKHR memory model

* Converts Logical GLSL450 memory model to Logical VulkanKHR
* Adds extension and capability
* Removes deprecated decorations and replaces them with appropriate
flags on downstream instructions
* Support for Workgroup upgrades
* Support for copy memory
* Adding support for image functions
* Adding barrier upgrades and tests
* Use QueueFamilyKHR scope instead of device
2018-11-30 14:15:51 -05:00

1436 lines
47 KiB
C++

// 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>;
#ifdef SPIRV_EFFCEE
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, InvalidMemoryModelVulkanKHR) {
const std::string text = R"(
; CHECK: OpMemoryModel Logical VulkanKHR
OpCapability Shader
OpCapability Linkage
OpCapability VulkanMemoryModelKHR
OpExtension "SPV_KHR_vulkan_memory_model"
OpMemoryModel Logical VulkanKHR
)";
SinglePassRunAndMatch<opt::UpgradeMemoryModel>(text, true);
}
TEST_F(UpgradeMemoryModelTest, JustMemoryModel) {
const std::string text = R"(
; CHECK: OpCapability VulkanMemoryModelKHR
; CHECK: OpExtension "SPV_KHR_vulkan_memory_model"
; CHECK: OpMemoryModel Logical VulkanKHR
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+}} MakePointerAvailableKHR|NonPrivatePointerKHR [[scope]]
; CHECK: OpStore {{%\w+}} {{%\w+}} MakePointerVisibleKHR|NonPrivatePointerKHR [[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
%st = 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+}} MakePointerAvailableKHR|NonPrivatePointerKHR [[scope]]
; CHECK: OpStore {{%\w+}} {{%\w+}} MakePointerVisibleKHR|NonPrivatePointerKHR [[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
%st = 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|MakePointerAvailableKHR|NonPrivatePointerKHR [[scope]]
; CHECK: OpStore {{%\w+}} {{%\w+}} Volatile|MakePointerVisibleKHR|NonPrivatePointerKHR [[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|MakePointerAvailableKHR|NonPrivatePointerKHR [[scope]]
; CHECK: OpStore {{%\w+}} {{%\w+}} Volatile|MakePointerVisibleKHR|NonPrivatePointerKHR [[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|MakePointerAvailableKHR|NonPrivatePointerKHR [[scope]]
; CHECK: OpStore {{%\w+}} {{%\w+}} Volatile|MakePointerVisibleKHR|NonPrivatePointerKHR [[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|MakePointerAvailableKHR|NonPrivatePointerKHR [[scope]]
; CHECK: OpStore {{%\w+}} {{%\w+}} Volatile|MakePointerVisibleKHR|NonPrivatePointerKHR [[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|MakePointerAvailableKHR|NonPrivatePointerKHR [[scope]]
; CHECK: OpStore {{%\w+}} {{%\w+}} Volatile|MakePointerVisibleKHR|NonPrivatePointerKHR [[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|MakePointerAvailableKHR|NonPrivatePointerKHR [[scope]]
; CHECK: OpStore {{%\w+}} {{%\w+}} Volatile|MakePointerVisibleKHR|NonPrivatePointerKHR [[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|MakePointerAvailableKHR|NonPrivatePointerKHR [[scope]]
; CHECK: OpStore {{%\w+}} {{%\w+}} Volatile|MakePointerVisibleKHR|NonPrivatePointerKHR [[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|MakePointerAvailableKHR|NonPrivatePointerKHR [[scope]]
; CHECK: OpStore {{%\w+}} {{%\w+}} Volatile|MakePointerVisibleKHR|NonPrivatePointerKHR [[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+}} MakePointerAvailableKHR|NonPrivatePointerKHR [[scope]]
; CHECK: OpStore {{%\w+}} {{%\w+}} MakePointerVisibleKHR|NonPrivatePointerKHR [[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+}} MakePointerAvailableKHR|NonPrivatePointerKHR [[scope]]
; CHECK: OpStore {{%\w+}} {{%\w+}} MakePointerVisibleKHR|NonPrivatePointerKHR [[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+}} MakePointerAvailableKHR|NonPrivatePointerKHR [[scope]]
; CHECK: OpStore {{%\w+}} {{%\w+}} MakePointerVisibleKHR|NonPrivatePointerKHR [[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: MakePointerAvailableKHR
; CHECK-NOT: NonPrivatePointerKHR
; CHECK-NOT: MakePointerVisibleKHR
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+}} MakePointerAvailableKHR|NonPrivatePointerKHR [[scope]]
; CHECK: OpStore {{%\w+}} {{%\w+}} MakePointerVisibleKHR|NonPrivatePointerKHR [[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: MakePointerAvailableKHR
; CHECK-NOT: NonPrivatePointerKHR
; CHECK-NOT: MakePointerVisibleKHR
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+}} MakePointerAvailableKHR|NonPrivatePointerKHR [[scope]]
; CHECK: OpStore {{%\w+}} {{%\w+}} MakePointerVisibleKHR|NonPrivatePointerKHR [[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: MakePointerAvailableKHR
; CHECK-NOT: NonPrivatePointerKHR
; CHECK-NOT: MakePointerVisibleKHR
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+}} MakePointerAvailableKHR|NonPrivatePointerKHR [[scope]]
; CHECK: OpStore {{%\w+}} {{%\w+}} MakePointerVisibleKHR|NonPrivatePointerKHR [[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: MakePointerAvailableKHR
; CHECK: OpStore {{%\w+}} {{%\w+}} MakePointerVisibleKHR|NonPrivatePointerKHR [[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|MakePointerVisibleKHR|NonPrivatePointerKHR [[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|MakePointerAvailableKHR|NonPrivatePointerKHR [[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+}} MakePointerAvailableKHR|MakePointerVisibleKHR|NonPrivatePointerKHR [[queuefamily]] [[workgroup]]
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+}} VolatileTexelKHR
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+}} MakePointerAvailableKHR|NonPrivatePointerKHR [[scope]]
; CHECK: OpImageRead {{%\w+}} {{%\w+}} {{%\w+}} MakeTexelAvailableKHR|NonPrivateTexelKHR [[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+}} MakePointerAvailableKHR|NonPrivatePointerKHR [[scope]]
; CHECK-NOT: NonPrivatePointerKHR
; CHECK: OpImageRead {{%\w+}} {{%\w+}} {{%\w+}} MakeTexelAvailableKHR|NonPrivateTexelKHR [[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+}} VolatileTexelKHR
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+}} MakePointerAvailableKHR|NonPrivatePointerKHR
; CHECK: OpImageWrite {{%\w+}} {{%\w+}} {{%\w+}} MakeTexelVisibleKHR|NonPrivateTexelKHR [[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+}} MakePointerAvailableKHR|NonPrivatePointerKHR
; CHECK-NOT: NonPrivatePointerKHR
; CHECK: OpImageWrite {{%\w+}} {{%\w+}} {{%\w+}} MakeTexelVisibleKHR|NonPrivateTexelKHR [[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+}} VolatileTexelKHR
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+}} MakePointerAvailableKHR|NonPrivatePointerKHR [[scope]]
; CHECK: OpImageSparseRead {{%\w+}} {{%\w+}} {{%\w+}} MakeTexelAvailableKHR|NonPrivateTexelKHR [[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+}} MakePointerAvailableKHR|NonPrivatePointerKHR [[scope]]
; CHECK-NOT: NonPrivatePointerKHR
; CHECK: OpImageSparseRead {{%\w+}} {{%\w+}} {{%\w+}} MakeTexelAvailableKHR|NonPrivateTexelKHR [[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);
}
#endif
} // namespace