1fd4e5da5Sopenharmony_ci// Copyright (c) 2023 Google Inc. 2fd4e5da5Sopenharmony_ci// 3fd4e5da5Sopenharmony_ci// Licensed under the Apache License, Version 2.0 (the "License"); 4fd4e5da5Sopenharmony_ci// you may not use this file except in compliance with the License. 5fd4e5da5Sopenharmony_ci// You may obtain a copy of the License at 6fd4e5da5Sopenharmony_ci// 7fd4e5da5Sopenharmony_ci// http://www.apache.org/licenses/LICENSE-2.0 8fd4e5da5Sopenharmony_ci// 9fd4e5da5Sopenharmony_ci// Unless required by applicable law or agreed to in writing, software 10fd4e5da5Sopenharmony_ci// distributed under the License is distributed on an "AS IS" BASIS, 11fd4e5da5Sopenharmony_ci// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12fd4e5da5Sopenharmony_ci// See the License for the specific language governing permissions and 13fd4e5da5Sopenharmony_ci// limitations under the License. 14fd4e5da5Sopenharmony_ci 15fd4e5da5Sopenharmony_ci#include "spirv-tools/optimizer.hpp" 16fd4e5da5Sopenharmony_ci#include "test/opt/pass_fixture.h" 17fd4e5da5Sopenharmony_ci#include "test/opt/pass_utils.h" 18fd4e5da5Sopenharmony_ci 19fd4e5da5Sopenharmony_cinamespace spvtools { 20fd4e5da5Sopenharmony_cinamespace opt { 21fd4e5da5Sopenharmony_cinamespace { 22fd4e5da5Sopenharmony_ci 23fd4e5da5Sopenharmony_ciusing InterlockInvocationPlacementTest = PassTest<::testing::Test>; 24fd4e5da5Sopenharmony_ci 25fd4e5da5Sopenharmony_ciTEST_F(InterlockInvocationPlacementTest, CheckUnchangedIfNotFragment) { 26fd4e5da5Sopenharmony_ci const std::string kTest = R"( 27fd4e5da5Sopenharmony_ci OpCapability Shader 28fd4e5da5Sopenharmony_ci OpCapability FragmentShaderSampleInterlockEXT 29fd4e5da5Sopenharmony_ci OpExtension "SPV_EXT_fragment_shader_interlock" 30fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 31fd4e5da5Sopenharmony_ci OpEntryPoint Vertex %main "main" 32fd4e5da5Sopenharmony_ci OpExecutionMode %main SampleInterlockOrderedEXT 33fd4e5da5Sopenharmony_ci OpName %main "main" 34fd4e5da5Sopenharmony_ci %void = OpTypeVoid 35fd4e5da5Sopenharmony_ci %1 = OpTypeFunction %void 36fd4e5da5Sopenharmony_ci %main = OpFunction %void None %1 37fd4e5da5Sopenharmony_ci %2 = OpLabel 38fd4e5da5Sopenharmony_ci OpBeginInvocationInterlockEXT 39fd4e5da5Sopenharmony_ci OpBeginInvocationInterlockEXT 40fd4e5da5Sopenharmony_ci OpEndInvocationInterlockEXT 41fd4e5da5Sopenharmony_ci OpBeginInvocationInterlockEXT 42fd4e5da5Sopenharmony_ci OpEndInvocationInterlockEXT 43fd4e5da5Sopenharmony_ci OpReturn 44fd4e5da5Sopenharmony_ci OpFunctionEnd 45fd4e5da5Sopenharmony_ci )"; 46fd4e5da5Sopenharmony_ci SetTargetEnv(SPV_ENV_VULKAN_1_3); 47fd4e5da5Sopenharmony_ci EXPECT_EQ( 48fd4e5da5Sopenharmony_ci Pass::Status::SuccessWithoutChange, 49fd4e5da5Sopenharmony_ci std::get<1>(SinglePassRunAndDisassemble<InvocationInterlockPlacementPass>( 50fd4e5da5Sopenharmony_ci kTest, /* skip_nop= */ false, /* do_validation= */ false))); 51fd4e5da5Sopenharmony_ci} 52fd4e5da5Sopenharmony_ci 53fd4e5da5Sopenharmony_ciTEST_F(InterlockInvocationPlacementTest, CheckUnchangedWithoutCapability) { 54fd4e5da5Sopenharmony_ci const std::string kTest = R"( 55fd4e5da5Sopenharmony_ci OpCapability Shader 56fd4e5da5Sopenharmony_ci OpExtension "SPV_EXT_fragment_shader_interlock" 57fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 58fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %main "main" 59fd4e5da5Sopenharmony_ci OpExecutionMode %main OriginUpperLeft 60fd4e5da5Sopenharmony_ci OpExecutionMode %main SampleInterlockOrderedEXT 61fd4e5da5Sopenharmony_ci OpName %main "main" 62fd4e5da5Sopenharmony_ci %void = OpTypeVoid 63fd4e5da5Sopenharmony_ci %1 = OpTypeFunction %void 64fd4e5da5Sopenharmony_ci %main = OpFunction %void None %1 65fd4e5da5Sopenharmony_ci %2 = OpLabel 66fd4e5da5Sopenharmony_ci OpBeginInvocationInterlockEXT 67fd4e5da5Sopenharmony_ci OpBeginInvocationInterlockEXT 68fd4e5da5Sopenharmony_ci OpEndInvocationInterlockEXT 69fd4e5da5Sopenharmony_ci OpBeginInvocationInterlockEXT 70fd4e5da5Sopenharmony_ci OpEndInvocationInterlockEXT 71fd4e5da5Sopenharmony_ci OpReturn 72fd4e5da5Sopenharmony_ci OpFunctionEnd 73fd4e5da5Sopenharmony_ci )"; 74fd4e5da5Sopenharmony_ci SetTargetEnv(SPV_ENV_VULKAN_1_3); 75fd4e5da5Sopenharmony_ci EXPECT_EQ( 76fd4e5da5Sopenharmony_ci Pass::Status::SuccessWithoutChange, 77fd4e5da5Sopenharmony_ci std::get<1>(SinglePassRunAndDisassemble<InvocationInterlockPlacementPass>( 78fd4e5da5Sopenharmony_ci kTest, /* skip_nop= */ false, /* do_validation= */ false))); 79fd4e5da5Sopenharmony_ci} 80fd4e5da5Sopenharmony_ci 81fd4e5da5Sopenharmony_ciTEST_F(InterlockInvocationPlacementTest, CheckSingleBasicBlock) { 82fd4e5da5Sopenharmony_ci // We're using OpNoLine as a generic standin for any other instruction, to 83fd4e5da5Sopenharmony_ci // test that begin and end aren't moved. 84fd4e5da5Sopenharmony_ci const std::string kTest = R"( 85fd4e5da5Sopenharmony_ci OpCapability Shader 86fd4e5da5Sopenharmony_ci OpCapability FragmentShaderSampleInterlockEXT 87fd4e5da5Sopenharmony_ci OpExtension "SPV_EXT_fragment_shader_interlock" 88fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 89fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %main "main" 90fd4e5da5Sopenharmony_ci OpExecutionMode %main OriginUpperLeft 91fd4e5da5Sopenharmony_ci OpExecutionMode %main SampleInterlockOrderedEXT 92fd4e5da5Sopenharmony_ci OpName %main "main" 93fd4e5da5Sopenharmony_ci %void = OpTypeVoid 94fd4e5da5Sopenharmony_ci %1 = OpTypeFunction %void 95fd4e5da5Sopenharmony_ci %main = OpFunction %void None %1 96fd4e5da5Sopenharmony_ci; CHECK: OpLabel 97fd4e5da5Sopenharmony_ci %2 = OpLabel 98fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpNoLine 99fd4e5da5Sopenharmony_ci OpNoLine 100fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpBeginInvocationInterlockEXT 101fd4e5da5Sopenharmony_ci OpBeginInvocationInterlockEXT 102fd4e5da5Sopenharmony_ci OpBeginInvocationInterlockEXT 103fd4e5da5Sopenharmony_ci OpEndInvocationInterlockEXT 104fd4e5da5Sopenharmony_ci OpBeginInvocationInterlockEXT 105fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpNoLine 106fd4e5da5Sopenharmony_ci OpNoLine 107fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpEndInvocationInterlockEXT 108fd4e5da5Sopenharmony_ci OpEndInvocationInterlockEXT 109fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpNoLine 110fd4e5da5Sopenharmony_ci OpNoLine 111fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpReturn 112fd4e5da5Sopenharmony_ci OpReturn 113fd4e5da5Sopenharmony_ci OpFunctionEnd 114fd4e5da5Sopenharmony_ci )"; 115fd4e5da5Sopenharmony_ci SetTargetEnv(SPV_ENV_VULKAN_1_3); 116fd4e5da5Sopenharmony_ci const auto result = SinglePassRunAndMatch<InvocationInterlockPlacementPass>( 117fd4e5da5Sopenharmony_ci kTest, /* skip_nop= */ false); 118fd4e5da5Sopenharmony_ci EXPECT_EQ(std::get<1>(result), Pass::Status::SuccessWithChange); 119fd4e5da5Sopenharmony_ci} 120fd4e5da5Sopenharmony_ci 121fd4e5da5Sopenharmony_ciTEST_F(InterlockInvocationPlacementTest, CheckFunctionCallExtractionBegin) { 122fd4e5da5Sopenharmony_ci const std::string kTest = R"( 123fd4e5da5Sopenharmony_ci OpCapability Shader 124fd4e5da5Sopenharmony_ci OpCapability FragmentShaderSampleInterlockEXT 125fd4e5da5Sopenharmony_ci OpExtension "SPV_EXT_fragment_shader_interlock" 126fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 127fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %main "main" 128fd4e5da5Sopenharmony_ci OpExecutionMode %main OriginUpperLeft 129fd4e5da5Sopenharmony_ci OpExecutionMode %main SampleInterlockOrderedEXT 130fd4e5da5Sopenharmony_ci OpName %main "main" 131fd4e5da5Sopenharmony_ci %void = OpTypeVoid 132fd4e5da5Sopenharmony_ci %1 = OpTypeFunction %void 133fd4e5da5Sopenharmony_ci %foo = OpFunction %void None %1 134fd4e5da5Sopenharmony_ci; CHECK: OpLabel 135fd4e5da5Sopenharmony_ci; CHECK-NOT: OpBeginInvocationInterlockEXT 136fd4e5da5Sopenharmony_ci %2 = OpLabel 137fd4e5da5Sopenharmony_ci OpBeginInvocationInterlockEXT 138fd4e5da5Sopenharmony_ci OpBeginInvocationInterlockEXT 139fd4e5da5Sopenharmony_ci OpReturn 140fd4e5da5Sopenharmony_ci; CHECK: OpFunctionEnd 141fd4e5da5Sopenharmony_ci OpFunctionEnd 142fd4e5da5Sopenharmony_ci %main = OpFunction %void None %1 143fd4e5da5Sopenharmony_ci; CHECK: OpLabel 144fd4e5da5Sopenharmony_ci %3 = OpLabel 145fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpBeginInvocationInterlockEXT 146fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpFunctionCall 147fd4e5da5Sopenharmony_ci %4 = OpFunctionCall %void %foo 148fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpReturn 149fd4e5da5Sopenharmony_ci OpReturn 150fd4e5da5Sopenharmony_ci OpFunctionEnd 151fd4e5da5Sopenharmony_ci )"; 152fd4e5da5Sopenharmony_ci SetTargetEnv(SPV_ENV_VULKAN_1_3); 153fd4e5da5Sopenharmony_ci const auto result = SinglePassRunAndMatch<InvocationInterlockPlacementPass>( 154fd4e5da5Sopenharmony_ci kTest, /* skip_nop= */ false); 155fd4e5da5Sopenharmony_ci EXPECT_EQ(std::get<1>(result), Pass::Status::SuccessWithChange); 156fd4e5da5Sopenharmony_ci} 157fd4e5da5Sopenharmony_ci 158fd4e5da5Sopenharmony_ciTEST_F(InterlockInvocationPlacementTest, CheckFunctionCallExtractionEnd) { 159fd4e5da5Sopenharmony_ci const std::string kTest = R"( 160fd4e5da5Sopenharmony_ci OpCapability Shader 161fd4e5da5Sopenharmony_ci OpCapability FragmentShaderSampleInterlockEXT 162fd4e5da5Sopenharmony_ci OpExtension "SPV_EXT_fragment_shader_interlock" 163fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 164fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %main "main" 165fd4e5da5Sopenharmony_ci OpExecutionMode %main OriginUpperLeft 166fd4e5da5Sopenharmony_ci OpExecutionMode %main SampleInterlockOrderedEXT 167fd4e5da5Sopenharmony_ci OpName %main "main" 168fd4e5da5Sopenharmony_ci %void = OpTypeVoid 169fd4e5da5Sopenharmony_ci %1 = OpTypeFunction %void 170fd4e5da5Sopenharmony_ci %foo = OpFunction %void None %1 171fd4e5da5Sopenharmony_ci; CHECK: OpLabel 172fd4e5da5Sopenharmony_ci; CHECK-NOT: OpEndInvocationInterlockEXT 173fd4e5da5Sopenharmony_ci %2 = OpLabel 174fd4e5da5Sopenharmony_ci OpEndInvocationInterlockEXT 175fd4e5da5Sopenharmony_ci OpEndInvocationInterlockEXT 176fd4e5da5Sopenharmony_ci OpReturn 177fd4e5da5Sopenharmony_ci; CHECK: OpFunctionEnd 178fd4e5da5Sopenharmony_ci OpFunctionEnd 179fd4e5da5Sopenharmony_ci %main = OpFunction %void None %1 180fd4e5da5Sopenharmony_ci; CHECK: OpLabel 181fd4e5da5Sopenharmony_ci %3 = OpLabel 182fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpFunctionCall 183fd4e5da5Sopenharmony_ci %4 = OpFunctionCall %void %foo 184fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpEndInvocationInterlockEXT 185fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpReturn 186fd4e5da5Sopenharmony_ci OpReturn 187fd4e5da5Sopenharmony_ci OpFunctionEnd 188fd4e5da5Sopenharmony_ci )"; 189fd4e5da5Sopenharmony_ci SetTargetEnv(SPV_ENV_VULKAN_1_3); 190fd4e5da5Sopenharmony_ci const auto result = SinglePassRunAndMatch<InvocationInterlockPlacementPass>( 191fd4e5da5Sopenharmony_ci kTest, /* skip_nop= */ false); 192fd4e5da5Sopenharmony_ci EXPECT_EQ(std::get<1>(result), Pass::Status::SuccessWithChange); 193fd4e5da5Sopenharmony_ci} 194fd4e5da5Sopenharmony_ci 195fd4e5da5Sopenharmony_ciTEST_F(InterlockInvocationPlacementTest, 196fd4e5da5Sopenharmony_ci CheckFunctionCallExtractionRepeatedCall) { 197fd4e5da5Sopenharmony_ci const std::string kTest = R"( 198fd4e5da5Sopenharmony_ci OpCapability Shader 199fd4e5da5Sopenharmony_ci OpCapability FragmentShaderSampleInterlockEXT 200fd4e5da5Sopenharmony_ci OpExtension "SPV_EXT_fragment_shader_interlock" 201fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 202fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %main "main" 203fd4e5da5Sopenharmony_ci OpExecutionMode %main OriginUpperLeft 204fd4e5da5Sopenharmony_ci OpExecutionMode %main SampleInterlockOrderedEXT 205fd4e5da5Sopenharmony_ci OpName %main "main" 206fd4e5da5Sopenharmony_ci %void = OpTypeVoid 207fd4e5da5Sopenharmony_ci %1 = OpTypeFunction %void 208fd4e5da5Sopenharmony_ci %foo = OpFunction %void None %1 209fd4e5da5Sopenharmony_ci; CHECK: OpLabel 210fd4e5da5Sopenharmony_ci; CHECK-NOT: OpBeginInvocationInterlockEXT 211fd4e5da5Sopenharmony_ci; CHECK-NOT: OpEndInvocationInterlockEXT 212fd4e5da5Sopenharmony_ci %2 = OpLabel 213fd4e5da5Sopenharmony_ci OpBeginInvocationInterlockEXT 214fd4e5da5Sopenharmony_ci OpEndInvocationInterlockEXT 215fd4e5da5Sopenharmony_ci OpReturn 216fd4e5da5Sopenharmony_ci; CHECK: OpFunctionEnd 217fd4e5da5Sopenharmony_ci OpFunctionEnd 218fd4e5da5Sopenharmony_ci %main = OpFunction %void None %1 219fd4e5da5Sopenharmony_ci; CHECK: OpLabel 220fd4e5da5Sopenharmony_ci %3 = OpLabel 221fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpBeginInvocationInterlockEXT 222fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpFunctionCall 223fd4e5da5Sopenharmony_ci %4 = OpFunctionCall %void %foo 224fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpFunctionCall 225fd4e5da5Sopenharmony_ci %5 = OpFunctionCall %void %foo 226fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpEndInvocationInterlockEXT 227fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpReturn 228fd4e5da5Sopenharmony_ci OpReturn 229fd4e5da5Sopenharmony_ci OpFunctionEnd 230fd4e5da5Sopenharmony_ci )"; 231fd4e5da5Sopenharmony_ci SetTargetEnv(SPV_ENV_VULKAN_1_3); 232fd4e5da5Sopenharmony_ci const auto result = SinglePassRunAndMatch<InvocationInterlockPlacementPass>( 233fd4e5da5Sopenharmony_ci kTest, /* skip_nop= */ false); 234fd4e5da5Sopenharmony_ci EXPECT_EQ(std::get<1>(result), Pass::Status::SuccessWithChange); 235fd4e5da5Sopenharmony_ci} 236fd4e5da5Sopenharmony_ci 237fd4e5da5Sopenharmony_ciTEST_F(InterlockInvocationPlacementTest, 238fd4e5da5Sopenharmony_ci CheckFunctionCallExtractionNestedCall) { 239fd4e5da5Sopenharmony_ci const std::string kTest = R"( 240fd4e5da5Sopenharmony_ci OpCapability Shader 241fd4e5da5Sopenharmony_ci OpCapability FragmentShaderSampleInterlockEXT 242fd4e5da5Sopenharmony_ci OpExtension "SPV_EXT_fragment_shader_interlock" 243fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 244fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %main "main" 245fd4e5da5Sopenharmony_ci OpExecutionMode %main OriginUpperLeft 246fd4e5da5Sopenharmony_ci OpExecutionMode %main SampleInterlockOrderedEXT 247fd4e5da5Sopenharmony_ci OpName %main "main" 248fd4e5da5Sopenharmony_ci %void = OpTypeVoid 249fd4e5da5Sopenharmony_ci %1 = OpTypeFunction %void 250fd4e5da5Sopenharmony_ci %foo = OpFunction %void None %1 251fd4e5da5Sopenharmony_ci; CHECK: OpLabel 252fd4e5da5Sopenharmony_ci; CHECK-NOT: OpBeginInvocationInterlockEXT 253fd4e5da5Sopenharmony_ci; CHECK-NOT: OpEndInvocationInterlockEXT 254fd4e5da5Sopenharmony_ci %2 = OpLabel 255fd4e5da5Sopenharmony_ci OpBeginInvocationInterlockEXT 256fd4e5da5Sopenharmony_ci OpEndInvocationInterlockEXT 257fd4e5da5Sopenharmony_ci OpReturn 258fd4e5da5Sopenharmony_ci; CHECK: OpFunctionEnd 259fd4e5da5Sopenharmony_ci OpFunctionEnd 260fd4e5da5Sopenharmony_ci %bar = OpFunction %void None %1 261fd4e5da5Sopenharmony_ci; CHECK: OpLabel 262fd4e5da5Sopenharmony_ci; CHECK-NOT: OpBeginInvocationInterlockEXT 263fd4e5da5Sopenharmony_ci; CHECK-NOT: OpEndInvocationInterlockEXT 264fd4e5da5Sopenharmony_ci %3 = OpLabel 265fd4e5da5Sopenharmony_ci %4 = OpFunctionCall %void %foo 266fd4e5da5Sopenharmony_ci OpReturn 267fd4e5da5Sopenharmony_ci; CHECK: OpFunctionEnd 268fd4e5da5Sopenharmony_ci OpFunctionEnd 269fd4e5da5Sopenharmony_ci %main = OpFunction %void None %1 270fd4e5da5Sopenharmony_ci; CHECK: OpLabel 271fd4e5da5Sopenharmony_ci %5 = OpLabel 272fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpBeginInvocationInterlockEXT 273fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpFunctionCall 274fd4e5da5Sopenharmony_ci %6 = OpFunctionCall %void %bar 275fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpEndInvocationInterlockEXT 276fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpReturn 277fd4e5da5Sopenharmony_ci OpReturn 278fd4e5da5Sopenharmony_ci OpFunctionEnd 279fd4e5da5Sopenharmony_ci )"; 280fd4e5da5Sopenharmony_ci SetTargetEnv(SPV_ENV_VULKAN_1_3); 281fd4e5da5Sopenharmony_ci const auto result = SinglePassRunAndMatch<InvocationInterlockPlacementPass>( 282fd4e5da5Sopenharmony_ci kTest, /* skip_nop= */ false); 283fd4e5da5Sopenharmony_ci EXPECT_EQ(std::get<1>(result), Pass::Status::SuccessWithChange); 284fd4e5da5Sopenharmony_ci} 285fd4e5da5Sopenharmony_ci 286fd4e5da5Sopenharmony_ciTEST_F(InterlockInvocationPlacementTest, CheckLoopExtraction) { 287fd4e5da5Sopenharmony_ci // Tests that any begin or end instructions in a loop are moved outside of the 288fd4e5da5Sopenharmony_ci // loop. 289fd4e5da5Sopenharmony_ci const std::string kTest = R"( 290fd4e5da5Sopenharmony_ci OpCapability Shader 291fd4e5da5Sopenharmony_ci OpCapability FragmentShaderSampleInterlockEXT 292fd4e5da5Sopenharmony_ci OpExtension "SPV_EXT_fragment_shader_interlock" 293fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 294fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %main "main" 295fd4e5da5Sopenharmony_ci OpExecutionMode %main OriginUpperLeft 296fd4e5da5Sopenharmony_ci OpExecutionMode %main SampleInterlockOrderedEXT 297fd4e5da5Sopenharmony_ci %void = OpTypeVoid 298fd4e5da5Sopenharmony_ci %bool = OpTypeBool 299fd4e5da5Sopenharmony_ci %true = OpConstantTrue %bool 300fd4e5da5Sopenharmony_ci %1 = OpTypeFunction %void 301fd4e5da5Sopenharmony_ci %main = OpFunction %void None %1 302fd4e5da5Sopenharmony_ci 303fd4e5da5Sopenharmony_ci %2 = OpLabel 304fd4e5da5Sopenharmony_ci; CHECK: OpBeginInvocationInterlockEXT 305fd4e5da5Sopenharmony_ci; CHECK-NOT: OpBeginInvocationInterlockEXT 306fd4e5da5Sopenharmony_ci; CHECK-NOT: OpEndInvocationInterlockEXT 307fd4e5da5Sopenharmony_ci OpBranch %3 308fd4e5da5Sopenharmony_ci 309fd4e5da5Sopenharmony_ci %3 = OpLabel 310fd4e5da5Sopenharmony_ci OpLoopMerge %3 %4 None 311fd4e5da5Sopenharmony_ci; CHECK: OpBranchConditional 312fd4e5da5Sopenharmony_ci; CHECK-NOT: OpBeginInvocationInterlockEXT 313fd4e5da5Sopenharmony_ci; CHECK-NOT: OpEndInvocationInterlockEXT 314fd4e5da5Sopenharmony_ci OpBranchConditional %true %4 %5 315fd4e5da5Sopenharmony_ci 316fd4e5da5Sopenharmony_ci %4 = OpLabel 317fd4e5da5Sopenharmony_ci OpBeginInvocationInterlockEXT 318fd4e5da5Sopenharmony_ci OpEndInvocationInterlockEXT 319fd4e5da5Sopenharmony_ci; CHECK: OpBranch 320fd4e5da5Sopenharmony_ci OpBranch %3 321fd4e5da5Sopenharmony_ci 322fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpLabel 323fd4e5da5Sopenharmony_ci %5 = OpLabel 324fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpEndInvocationInterlockEXT 325fd4e5da5Sopenharmony_ci; CHECK-NOT: OpEndInvocationInterlockEXT 326fd4e5da5Sopenharmony_ci OpEndInvocationInterlockEXT 327fd4e5da5Sopenharmony_ci OpReturn 328fd4e5da5Sopenharmony_ci OpFunctionEnd 329fd4e5da5Sopenharmony_ci )"; 330fd4e5da5Sopenharmony_ci SetTargetEnv(SPV_ENV_VULKAN_1_3); 331fd4e5da5Sopenharmony_ci const auto result = SinglePassRunAndMatch<InvocationInterlockPlacementPass>( 332fd4e5da5Sopenharmony_ci kTest, /* skip_nop= */ false); 333fd4e5da5Sopenharmony_ci EXPECT_EQ(std::get<1>(result), Pass::Status::SuccessWithChange); 334fd4e5da5Sopenharmony_ci} 335fd4e5da5Sopenharmony_ci 336fd4e5da5Sopenharmony_ciTEST_F(InterlockInvocationPlacementTest, CheckAddBeginToElse) { 337fd4e5da5Sopenharmony_ci // Test that if there is a begin in a single branch of a conditional, begin 338fd4e5da5Sopenharmony_ci // will be added to the other branch. 339fd4e5da5Sopenharmony_ci const std::string kTest = R"( 340fd4e5da5Sopenharmony_ci OpCapability Shader 341fd4e5da5Sopenharmony_ci OpCapability FragmentShaderSampleInterlockEXT 342fd4e5da5Sopenharmony_ci OpExtension "SPV_EXT_fragment_shader_interlock" 343fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 344fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %main "main" 345fd4e5da5Sopenharmony_ci OpExecutionMode %main OriginUpperLeft 346fd4e5da5Sopenharmony_ci OpExecutionMode %main SampleInterlockOrderedEXT 347fd4e5da5Sopenharmony_ci OpName %main "main" 348fd4e5da5Sopenharmony_ci %void = OpTypeVoid 349fd4e5da5Sopenharmony_ci %bool = OpTypeBool 350fd4e5da5Sopenharmony_ci %true = OpConstantTrue %bool 351fd4e5da5Sopenharmony_ci %1 = OpTypeFunction %void 352fd4e5da5Sopenharmony_ci %main = OpFunction %void None %1 353fd4e5da5Sopenharmony_ci 354fd4e5da5Sopenharmony_ci %2 = OpLabel 355fd4e5da5Sopenharmony_ci; CHECK-NOT: OpBeginInvocationInterlockEXT 356fd4e5da5Sopenharmony_ci OpSelectionMerge %5 None 357fd4e5da5Sopenharmony_ci; CHECK: OpBranchConditional 358fd4e5da5Sopenharmony_ci OpBranchConditional %true %3 %4 359fd4e5da5Sopenharmony_ci 360fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpLabel 361fd4e5da5Sopenharmony_ci %3 = OpLabel 362fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpBeginInvocationInterlockEXT 363fd4e5da5Sopenharmony_ci OpBeginInvocationInterlockEXT 364fd4e5da5Sopenharmony_ci OpEndInvocationInterlockEXT 365fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpBranch 366fd4e5da5Sopenharmony_ci OpBranch %5 367fd4e5da5Sopenharmony_ci 368fd4e5da5Sopenharmony_ci %4 = OpLabel 369fd4e5da5Sopenharmony_ci; CHECK: OpBeginInvocationInterlockEXT 370fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpBranch 371fd4e5da5Sopenharmony_ci OpBranch %5 372fd4e5da5Sopenharmony_ci 373fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpLabel 374fd4e5da5Sopenharmony_ci %5 = OpLabel 375fd4e5da5Sopenharmony_ci OpBeginInvocationInterlockEXT 376fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpEndInvocationInterlockEXT 377fd4e5da5Sopenharmony_ci OpEndInvocationInterlockEXT 378fd4e5da5Sopenharmony_ci OpReturn 379fd4e5da5Sopenharmony_ci OpFunctionEnd 380fd4e5da5Sopenharmony_ci )"; 381fd4e5da5Sopenharmony_ci SetTargetEnv(SPV_ENV_VULKAN_1_3); 382fd4e5da5Sopenharmony_ci const auto result = SinglePassRunAndMatch<InvocationInterlockPlacementPass>( 383fd4e5da5Sopenharmony_ci kTest, /* skip_nop= */ false); 384fd4e5da5Sopenharmony_ci EXPECT_EQ(std::get<1>(result), Pass::Status::SuccessWithChange); 385fd4e5da5Sopenharmony_ci} 386fd4e5da5Sopenharmony_ci 387fd4e5da5Sopenharmony_ciTEST_F(InterlockInvocationPlacementTest, CheckAddEndToElse) { 388fd4e5da5Sopenharmony_ci const std::string kTest = R"( 389fd4e5da5Sopenharmony_ci OpCapability Shader 390fd4e5da5Sopenharmony_ci OpCapability FragmentShaderSampleInterlockEXT 391fd4e5da5Sopenharmony_ci OpExtension "SPV_EXT_fragment_shader_interlock" 392fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 393fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %main "main" 394fd4e5da5Sopenharmony_ci OpExecutionMode %main OriginUpperLeft 395fd4e5da5Sopenharmony_ci OpExecutionMode %main SampleInterlockOrderedEXT 396fd4e5da5Sopenharmony_ci OpName %main "main" 397fd4e5da5Sopenharmony_ci %void = OpTypeVoid 398fd4e5da5Sopenharmony_ci %bool = OpTypeBool 399fd4e5da5Sopenharmony_ci %true = OpConstantTrue %bool 400fd4e5da5Sopenharmony_ci %1 = OpTypeFunction %void 401fd4e5da5Sopenharmony_ci %main = OpFunction %void None %1 402fd4e5da5Sopenharmony_ci 403fd4e5da5Sopenharmony_ci %2 = OpLabel 404fd4e5da5Sopenharmony_ci; CHECK: OpBeginInvocationInterlockEXT 405fd4e5da5Sopenharmony_ci OpBeginInvocationInterlockEXT 406fd4e5da5Sopenharmony_ci; CHECK-NOT: OpEndInvocationInterlockEXT 407fd4e5da5Sopenharmony_ci OpEndInvocationInterlockEXT 408fd4e5da5Sopenharmony_ci OpSelectionMerge %5 None 409fd4e5da5Sopenharmony_ci; CHECK: OpBranchConditional 410fd4e5da5Sopenharmony_ci OpBranchConditional %true %3 %4 411fd4e5da5Sopenharmony_ci 412fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpLabel 413fd4e5da5Sopenharmony_ci %3 = OpLabel 414fd4e5da5Sopenharmony_ci OpBeginInvocationInterlockEXT 415fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpEndInvocationInterlockEXT 416fd4e5da5Sopenharmony_ci OpEndInvocationInterlockEXT 417fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpBranch 418fd4e5da5Sopenharmony_ci OpBranch %5 419fd4e5da5Sopenharmony_ci 420fd4e5da5Sopenharmony_ci %4 = OpLabel 421fd4e5da5Sopenharmony_ci; CHECK: OpEndInvocationInterlockEXT 422fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpBranch 423fd4e5da5Sopenharmony_ci OpBranch %5 424fd4e5da5Sopenharmony_ci 425fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpLabel 426fd4e5da5Sopenharmony_ci %5 = OpLabel 427fd4e5da5Sopenharmony_ci; CHECK-NOT: OpEndInvocationInterlockEXT 428fd4e5da5Sopenharmony_ci OpReturn 429fd4e5da5Sopenharmony_ci OpFunctionEnd 430fd4e5da5Sopenharmony_ci )"; 431fd4e5da5Sopenharmony_ci SetTargetEnv(SPV_ENV_VULKAN_1_3); 432fd4e5da5Sopenharmony_ci const auto result = SinglePassRunAndMatch<InvocationInterlockPlacementPass>( 433fd4e5da5Sopenharmony_ci kTest, /* skip_nop= */ false); 434fd4e5da5Sopenharmony_ci EXPECT_EQ(std::get<1>(result), Pass::Status::SuccessWithChange); 435fd4e5da5Sopenharmony_ci} 436fd4e5da5Sopenharmony_ci 437fd4e5da5Sopenharmony_ciTEST_F(InterlockInvocationPlacementTest, CheckSplitIfWithoutElseBegin) { 438fd4e5da5Sopenharmony_ci // Test that if there is a begin in the then branch of a conditional, and no 439fd4e5da5Sopenharmony_ci // else branch, an else branch with a begin will created. 440fd4e5da5Sopenharmony_ci const std::string kTest = R"( 441fd4e5da5Sopenharmony_ci OpCapability Shader 442fd4e5da5Sopenharmony_ci OpCapability FragmentShaderSampleInterlockEXT 443fd4e5da5Sopenharmony_ci OpExtension "SPV_EXT_fragment_shader_interlock" 444fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 445fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %main "main" 446fd4e5da5Sopenharmony_ci OpExecutionMode %main OriginUpperLeft 447fd4e5da5Sopenharmony_ci OpExecutionMode %main SampleInterlockOrderedEXT 448fd4e5da5Sopenharmony_ci OpName %main "main" 449fd4e5da5Sopenharmony_ci %void = OpTypeVoid 450fd4e5da5Sopenharmony_ci %bool = OpTypeBool 451fd4e5da5Sopenharmony_ci %true = OpConstantTrue %bool 452fd4e5da5Sopenharmony_ci %1 = OpTypeFunction %void 453fd4e5da5Sopenharmony_ci %main = OpFunction %void None %1 454fd4e5da5Sopenharmony_ci 455fd4e5da5Sopenharmony_ci %2 = OpLabel 456fd4e5da5Sopenharmony_ci; CHECK-NOT: OpBeginInvocationInterlockEXT 457fd4e5da5Sopenharmony_ci OpSelectionMerge %5 None 458fd4e5da5Sopenharmony_ci; CHECK: OpBranchConditional 459fd4e5da5Sopenharmony_ci OpBranchConditional %true %3 %5 460fd4e5da5Sopenharmony_ci 461fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpLabel 462fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpBeginInvocationInterlockEXT 463fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpBranch 464fd4e5da5Sopenharmony_ci 465fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpLabel 466fd4e5da5Sopenharmony_ci %3 = OpLabel 467fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpBeginInvocationInterlockEXT 468fd4e5da5Sopenharmony_ci; CHECK-NOT: OpEndInvocationInterlockEXT 469fd4e5da5Sopenharmony_ci OpBeginInvocationInterlockEXT 470fd4e5da5Sopenharmony_ci OpEndInvocationInterlockEXT 471fd4e5da5Sopenharmony_ci OpBranch %5 472fd4e5da5Sopenharmony_ci 473fd4e5da5Sopenharmony_ci; CHECK: OpLabel 474fd4e5da5Sopenharmony_ci %5 = OpLabel 475fd4e5da5Sopenharmony_ci; CHECK-NOT: OpBeginInvocationInterlockEXT 476fd4e5da5Sopenharmony_ci OpBeginInvocationInterlockEXT 477fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpEndInvocationInterlockEXT 478fd4e5da5Sopenharmony_ci OpEndInvocationInterlockEXT 479fd4e5da5Sopenharmony_ci OpReturn 480fd4e5da5Sopenharmony_ci OpFunctionEnd 481fd4e5da5Sopenharmony_ci )"; 482fd4e5da5Sopenharmony_ci SetTargetEnv(SPV_ENV_VULKAN_1_3); 483fd4e5da5Sopenharmony_ci const auto result = SinglePassRunAndMatch<InvocationInterlockPlacementPass>( 484fd4e5da5Sopenharmony_ci kTest, /* skip_nop= */ false); 485fd4e5da5Sopenharmony_ci EXPECT_EQ(std::get<1>(result), Pass::Status::SuccessWithChange); 486fd4e5da5Sopenharmony_ci} 487fd4e5da5Sopenharmony_ci 488fd4e5da5Sopenharmony_ciTEST_F(InterlockInvocationPlacementTest, CheckSplitIfWithoutElseEnd) { 489fd4e5da5Sopenharmony_ci const std::string kTest = R"( 490fd4e5da5Sopenharmony_ci OpCapability Shader 491fd4e5da5Sopenharmony_ci OpCapability FragmentShaderSampleInterlockEXT 492fd4e5da5Sopenharmony_ci OpExtension "SPV_EXT_fragment_shader_interlock" 493fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 494fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %main "main" 495fd4e5da5Sopenharmony_ci OpExecutionMode %main OriginUpperLeft 496fd4e5da5Sopenharmony_ci OpExecutionMode %main SampleInterlockOrderedEXT 497fd4e5da5Sopenharmony_ci OpName %main "main" 498fd4e5da5Sopenharmony_ci %void = OpTypeVoid 499fd4e5da5Sopenharmony_ci %bool = OpTypeBool 500fd4e5da5Sopenharmony_ci %true = OpConstantTrue %bool 501fd4e5da5Sopenharmony_ci %1 = OpTypeFunction %void 502fd4e5da5Sopenharmony_ci %main = OpFunction %void None %1 503fd4e5da5Sopenharmony_ci 504fd4e5da5Sopenharmony_ci %2 = OpLabel 505fd4e5da5Sopenharmony_ci 506fd4e5da5Sopenharmony_ci; CHECK: OpBeginInvocationInterlockEXT 507fd4e5da5Sopenharmony_ci OpBeginInvocationInterlockEXT 508fd4e5da5Sopenharmony_ci; CHECK-NOT: OpEndInvocationInterlockEXT 509fd4e5da5Sopenharmony_ci OpEndInvocationInterlockEXT 510fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpSelectionMerge [[merge:%\d+]] 511fd4e5da5Sopenharmony_ci OpSelectionMerge %5 None 512fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpBranchConditional %true [[then:%\d+]] [[else:%\d+]] 513fd4e5da5Sopenharmony_ci OpBranchConditional %true %3 %5 514fd4e5da5Sopenharmony_ci 515fd4e5da5Sopenharmony_ci; CHECK-NEXT: [[else]] = OpLabel 516fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpEndInvocationInterlockEXT 517fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpBranch [[merge]] 518fd4e5da5Sopenharmony_ci 519fd4e5da5Sopenharmony_ci; CHECK-NEXT: [[then]] = OpLabel 520fd4e5da5Sopenharmony_ci %3 = OpLabel 521fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpEndInvocationInterlockEXT 522fd4e5da5Sopenharmony_ci OpBeginInvocationInterlockEXT 523fd4e5da5Sopenharmony_ci OpEndInvocationInterlockEXT 524fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpBranch [[merge]] 525fd4e5da5Sopenharmony_ci OpBranch %5 526fd4e5da5Sopenharmony_ci 527fd4e5da5Sopenharmony_ci; CHECK-NEXT: [[merge]] = OpLabel 528fd4e5da5Sopenharmony_ci %5 = OpLabel 529fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpReturn 530fd4e5da5Sopenharmony_ci OpReturn 531fd4e5da5Sopenharmony_ci OpFunctionEnd 532fd4e5da5Sopenharmony_ci )"; 533fd4e5da5Sopenharmony_ci SetTargetEnv(SPV_ENV_VULKAN_1_3); 534fd4e5da5Sopenharmony_ci const auto result = SinglePassRunAndMatch<InvocationInterlockPlacementPass>( 535fd4e5da5Sopenharmony_ci kTest, /* skip_nop= */ false); 536fd4e5da5Sopenharmony_ci EXPECT_EQ(std::get<1>(result), Pass::Status::SuccessWithChange); 537fd4e5da5Sopenharmony_ci} 538fd4e5da5Sopenharmony_ci 539fd4e5da5Sopenharmony_ciTEST_F(InterlockInvocationPlacementTest, CheckSplitSwitch) { 540fd4e5da5Sopenharmony_ci // Test that if there is a begin or end in a single branch of a switch, begin 541fd4e5da5Sopenharmony_ci // or end will be added to all the other branches. 542fd4e5da5Sopenharmony_ci const std::string kTest = R"( 543fd4e5da5Sopenharmony_ci OpCapability Shader 544fd4e5da5Sopenharmony_ci OpCapability FragmentShaderSampleInterlockEXT 545fd4e5da5Sopenharmony_ci OpExtension "SPV_EXT_fragment_shader_interlock" 546fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 547fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %main "main" 548fd4e5da5Sopenharmony_ci OpExecutionMode %main OriginUpperLeft 549fd4e5da5Sopenharmony_ci OpExecutionMode %main SampleInterlockOrderedEXT 550fd4e5da5Sopenharmony_ci OpName %main "main" 551fd4e5da5Sopenharmony_ci %void = OpTypeVoid 552fd4e5da5Sopenharmony_ci %uint = OpTypeInt 32 0 553fd4e5da5Sopenharmony_ci %uint_1 = OpConstant %uint 1 554fd4e5da5Sopenharmony_ci %1 = OpTypeFunction %void 555fd4e5da5Sopenharmony_ci %main = OpFunction %void None %1 556fd4e5da5Sopenharmony_ci 557fd4e5da5Sopenharmony_ci; CHECK: OpLabel 558fd4e5da5Sopenharmony_ci %2 = OpLabel 559fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpSelectionMerge [[merge:%\d+]] 560fd4e5da5Sopenharmony_ci OpSelectionMerge %8 None 561fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpSwitch %uint_1 [[default:%\d+]] 0 [[case_0:%\d+]] 1 [[case_1:%\d+]] 2 [[case_2:%\d+]] 562fd4e5da5Sopenharmony_ci OpSwitch %uint_1 %8 0 %4 1 %5 2 %8 563fd4e5da5Sopenharmony_ci 564fd4e5da5Sopenharmony_ci; CHECK-NEXT: [[case_2]] = OpLabel 565fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpBeginInvocationInterlockEXT 566fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpBranch [[merge]] 567fd4e5da5Sopenharmony_ci 568fd4e5da5Sopenharmony_ci; CHECK-NEXT: [[default]] = OpLabel 569fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpBeginInvocationInterlockEXT 570fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpBranch [[merge]] 571fd4e5da5Sopenharmony_ci 572fd4e5da5Sopenharmony_ci; CHECK-NEXT: [[case_0]] = OpLabel 573fd4e5da5Sopenharmony_ci %4 = OpLabel 574fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpBeginInvocationInterlockEXT 575fd4e5da5Sopenharmony_ci; CHECK-NOT: OpEndInvocationInterlockEXT 576fd4e5da5Sopenharmony_ci OpBeginInvocationInterlockEXT 577fd4e5da5Sopenharmony_ci OpEndInvocationInterlockEXT 578fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpNoLine 579fd4e5da5Sopenharmony_ci OpNoLine 580fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpBranch [[merge]] 581fd4e5da5Sopenharmony_ci OpBranch %8 582fd4e5da5Sopenharmony_ci 583fd4e5da5Sopenharmony_ci; CHECK-NEXT: [[case_1]] = OpLabel 584fd4e5da5Sopenharmony_ci %5 = OpLabel 585fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpBeginInvocationInterlockEXT 586fd4e5da5Sopenharmony_ci; CHECK-NOT: OpEndInvocationInterlockEXT 587fd4e5da5Sopenharmony_ci OpBeginInvocationInterlockEXT 588fd4e5da5Sopenharmony_ci OpEndInvocationInterlockEXT 589fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpNoLine 590fd4e5da5Sopenharmony_ci OpNoLine 591fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpNoLine 592fd4e5da5Sopenharmony_ci OpNoLine 593fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpBranch [[merge]] 594fd4e5da5Sopenharmony_ci OpBranch %8 595fd4e5da5Sopenharmony_ci 596fd4e5da5Sopenharmony_ci; CHECK-NEXT: [[merge]] = OpLabel 597fd4e5da5Sopenharmony_ci %8 = OpLabel 598fd4e5da5Sopenharmony_ci; CHECK-NOT: OpBeginInvocationInterlockEXT 599fd4e5da5Sopenharmony_ci OpBeginInvocationInterlockEXT 600fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpEndInvocationInterlockEXT 601fd4e5da5Sopenharmony_ci OpEndInvocationInterlockEXT 602fd4e5da5Sopenharmony_ci OpReturn 603fd4e5da5Sopenharmony_ci OpFunctionEnd 604fd4e5da5Sopenharmony_ci )"; 605fd4e5da5Sopenharmony_ci SetTargetEnv(SPV_ENV_VULKAN_1_3); 606fd4e5da5Sopenharmony_ci const auto result = SinglePassRunAndMatch<InvocationInterlockPlacementPass>( 607fd4e5da5Sopenharmony_ci kTest, /* skip_nop= */ false); 608fd4e5da5Sopenharmony_ci EXPECT_EQ(std::get<1>(result), Pass::Status::SuccessWithChange); 609fd4e5da5Sopenharmony_ci} 610fd4e5da5Sopenharmony_ci 611fd4e5da5Sopenharmony_ci} // namespace 612fd4e5da5Sopenharmony_ci} // namespace opt 613fd4e5da5Sopenharmony_ci} // namespace spvtools 614