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