1fd4e5da5Sopenharmony_ci// Copyright (c) 2019 Google LLC
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 <string>
16fd4e5da5Sopenharmony_ci
17fd4e5da5Sopenharmony_ci#include "test/opt/assembly_builder.h"
18fd4e5da5Sopenharmony_ci#include "test/opt/pass_fixture.h"
19fd4e5da5Sopenharmony_ci#include "test/opt/pass_utils.h"
20fd4e5da5Sopenharmony_ci
21fd4e5da5Sopenharmony_cinamespace spvtools {
22fd4e5da5Sopenharmony_cinamespace opt {
23fd4e5da5Sopenharmony_cinamespace {
24fd4e5da5Sopenharmony_ci
25fd4e5da5Sopenharmony_ciusing CodeSinkTest = PassTest<::testing::Test>;
26fd4e5da5Sopenharmony_ci
27fd4e5da5Sopenharmony_ciTEST_F(CodeSinkTest, MoveToNextBlock) {
28fd4e5da5Sopenharmony_ci  const std::string text = R"(
29fd4e5da5Sopenharmony_ci;CHECK: OpFunction
30fd4e5da5Sopenharmony_ci;CHECK: OpLabel
31fd4e5da5Sopenharmony_ci;CHECK: OpLabel
32fd4e5da5Sopenharmony_ci;CHECK: [[ac:%\w+]] = OpAccessChain
33fd4e5da5Sopenharmony_ci;CHECK: [[ld:%\w+]] = OpLoad %uint [[ac]]
34fd4e5da5Sopenharmony_ci;CHECK: OpCopyObject %uint [[ld]]
35fd4e5da5Sopenharmony_ci               OpCapability Shader
36fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
37fd4e5da5Sopenharmony_ci               OpEntryPoint GLCompute %1 "main"
38fd4e5da5Sopenharmony_ci       %void = OpTypeVoid
39fd4e5da5Sopenharmony_ci       %uint = OpTypeInt 32 0
40fd4e5da5Sopenharmony_ci     %uint_0 = OpConstant %uint 0
41fd4e5da5Sopenharmony_ci     %uint_4 = OpConstant %uint 4
42fd4e5da5Sopenharmony_ci%_arr_uint_uint_4 = OpTypeArray %uint %uint_4
43fd4e5da5Sopenharmony_ci%_ptr_Uniform_uint = OpTypePointer Uniform %uint
44fd4e5da5Sopenharmony_ci%_ptr_Uniform__arr_uint_uint_4 = OpTypePointer Uniform %_arr_uint_uint_4
45fd4e5da5Sopenharmony_ci          %9 = OpVariable %_ptr_Uniform__arr_uint_uint_4 Uniform
46fd4e5da5Sopenharmony_ci         %10 = OpTypeFunction %void
47fd4e5da5Sopenharmony_ci          %1 = OpFunction %void None %10
48fd4e5da5Sopenharmony_ci         %11 = OpLabel
49fd4e5da5Sopenharmony_ci         %12 = OpAccessChain %_ptr_Uniform_uint %9 %uint_0
50fd4e5da5Sopenharmony_ci         %13 = OpLoad %uint %12
51fd4e5da5Sopenharmony_ci               OpBranch %14
52fd4e5da5Sopenharmony_ci         %14 = OpLabel
53fd4e5da5Sopenharmony_ci         %15 = OpCopyObject %uint %13
54fd4e5da5Sopenharmony_ci               OpReturn
55fd4e5da5Sopenharmony_ci               OpFunctionEnd
56fd4e5da5Sopenharmony_ci)";
57fd4e5da5Sopenharmony_ci
58fd4e5da5Sopenharmony_ci  SinglePassRunAndMatch<CodeSinkingPass>(text, true);
59fd4e5da5Sopenharmony_ci}
60fd4e5da5Sopenharmony_ci
61fd4e5da5Sopenharmony_ciTEST_F(CodeSinkTest, MovePastSelection) {
62fd4e5da5Sopenharmony_ci  const std::string text = R"(
63fd4e5da5Sopenharmony_ci;CHECK: OpFunction
64fd4e5da5Sopenharmony_ci;CHECK: OpLabel
65fd4e5da5Sopenharmony_ci;CHECK: OpSelectionMerge [[merge_bb:%\w+]]
66fd4e5da5Sopenharmony_ci;CHECK: [[merge_bb]] = OpLabel
67fd4e5da5Sopenharmony_ci;CHECK: [[ac:%\w+]] = OpAccessChain
68fd4e5da5Sopenharmony_ci;CHECK: [[ld:%\w+]] = OpLoad %uint [[ac]]
69fd4e5da5Sopenharmony_ci;CHECK: OpCopyObject %uint [[ld]]
70fd4e5da5Sopenharmony_ci               OpCapability Shader
71fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
72fd4e5da5Sopenharmony_ci               OpEntryPoint GLCompute %1 "main"
73fd4e5da5Sopenharmony_ci       %void = OpTypeVoid
74fd4e5da5Sopenharmony_ci       %bool = OpTypeBool
75fd4e5da5Sopenharmony_ci       %true = OpConstantTrue %bool
76fd4e5da5Sopenharmony_ci       %uint = OpTypeInt 32 0
77fd4e5da5Sopenharmony_ci     %uint_0 = OpConstant %uint 0
78fd4e5da5Sopenharmony_ci     %uint_4 = OpConstant %uint 4
79fd4e5da5Sopenharmony_ci%_arr_uint_uint_4 = OpTypeArray %uint %uint_4
80fd4e5da5Sopenharmony_ci%_ptr_Uniform_uint = OpTypePointer Uniform %uint
81fd4e5da5Sopenharmony_ci%_ptr_Uniform__arr_uint_uint_4 = OpTypePointer Uniform %_arr_uint_uint_4
82fd4e5da5Sopenharmony_ci         %11 = OpVariable %_ptr_Uniform__arr_uint_uint_4 Uniform
83fd4e5da5Sopenharmony_ci         %12 = OpTypeFunction %void
84fd4e5da5Sopenharmony_ci          %1 = OpFunction %void None %12
85fd4e5da5Sopenharmony_ci         %13 = OpLabel
86fd4e5da5Sopenharmony_ci         %14 = OpAccessChain %_ptr_Uniform_uint %11 %uint_0
87fd4e5da5Sopenharmony_ci         %15 = OpLoad %uint %14
88fd4e5da5Sopenharmony_ci               OpSelectionMerge %16 None
89fd4e5da5Sopenharmony_ci               OpBranchConditional %true %17 %16
90fd4e5da5Sopenharmony_ci         %17 = OpLabel
91fd4e5da5Sopenharmony_ci               OpBranch %16
92fd4e5da5Sopenharmony_ci         %16 = OpLabel
93fd4e5da5Sopenharmony_ci         %18 = OpCopyObject %uint %15
94fd4e5da5Sopenharmony_ci               OpReturn
95fd4e5da5Sopenharmony_ci               OpFunctionEnd
96fd4e5da5Sopenharmony_ci)";
97fd4e5da5Sopenharmony_ci
98fd4e5da5Sopenharmony_ci  SinglePassRunAndMatch<CodeSinkingPass>(text, true);
99fd4e5da5Sopenharmony_ci}
100fd4e5da5Sopenharmony_ci
101fd4e5da5Sopenharmony_ciTEST_F(CodeSinkTest, MoveIntoSelection) {
102fd4e5da5Sopenharmony_ci  const std::string text = R"(
103fd4e5da5Sopenharmony_ci;CHECK: OpFunction
104fd4e5da5Sopenharmony_ci;CHECK: OpLabel
105fd4e5da5Sopenharmony_ci;CHECK: OpSelectionMerge [[merge_bb:%\w+]]
106fd4e5da5Sopenharmony_ci;CHECK-NEXT: OpBranchConditional %true [[bb:%\w+]] [[merge_bb]]
107fd4e5da5Sopenharmony_ci;CHECK: [[bb]] = OpLabel
108fd4e5da5Sopenharmony_ci;CHECK-NEXT: [[ac:%\w+]] = OpAccessChain
109fd4e5da5Sopenharmony_ci;CHECK-NEXT: [[ld:%\w+]] = OpLoad %uint [[ac]]
110fd4e5da5Sopenharmony_ci;CHECK-NEXT: OpCopyObject %uint [[ld]]
111fd4e5da5Sopenharmony_ci               OpCapability Shader
112fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
113fd4e5da5Sopenharmony_ci               OpEntryPoint GLCompute %1 "main"
114fd4e5da5Sopenharmony_ci       %void = OpTypeVoid
115fd4e5da5Sopenharmony_ci       %bool = OpTypeBool
116fd4e5da5Sopenharmony_ci       %true = OpConstantTrue %bool
117fd4e5da5Sopenharmony_ci       %uint = OpTypeInt 32 0
118fd4e5da5Sopenharmony_ci     %uint_0 = OpConstant %uint 0
119fd4e5da5Sopenharmony_ci     %uint_4 = OpConstant %uint 4
120fd4e5da5Sopenharmony_ci%_arr_uint_uint_4 = OpTypeArray %uint %uint_4
121fd4e5da5Sopenharmony_ci%_ptr_Uniform_uint = OpTypePointer Uniform %uint
122fd4e5da5Sopenharmony_ci%_ptr_Uniform__arr_uint_uint_4 = OpTypePointer Uniform %_arr_uint_uint_4
123fd4e5da5Sopenharmony_ci         %11 = OpVariable %_ptr_Uniform__arr_uint_uint_4 Uniform
124fd4e5da5Sopenharmony_ci         %12 = OpTypeFunction %void
125fd4e5da5Sopenharmony_ci          %1 = OpFunction %void None %12
126fd4e5da5Sopenharmony_ci         %13 = OpLabel
127fd4e5da5Sopenharmony_ci         %14 = OpAccessChain %_ptr_Uniform_uint %11 %uint_0
128fd4e5da5Sopenharmony_ci         %15 = OpLoad %uint %14
129fd4e5da5Sopenharmony_ci               OpSelectionMerge %16 None
130fd4e5da5Sopenharmony_ci               OpBranchConditional %true %17 %16
131fd4e5da5Sopenharmony_ci         %17 = OpLabel
132fd4e5da5Sopenharmony_ci         %18 = OpCopyObject %uint %15
133fd4e5da5Sopenharmony_ci               OpBranch %16
134fd4e5da5Sopenharmony_ci         %16 = OpLabel
135fd4e5da5Sopenharmony_ci               OpReturn
136fd4e5da5Sopenharmony_ci               OpFunctionEnd
137fd4e5da5Sopenharmony_ci)";
138fd4e5da5Sopenharmony_ci
139fd4e5da5Sopenharmony_ci  SinglePassRunAndMatch<CodeSinkingPass>(text, true);
140fd4e5da5Sopenharmony_ci}
141fd4e5da5Sopenharmony_ci
142fd4e5da5Sopenharmony_ciTEST_F(CodeSinkTest, LeaveBeforeSelection) {
143fd4e5da5Sopenharmony_ci  const std::string text = R"(
144fd4e5da5Sopenharmony_ci               OpCapability Shader
145fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
146fd4e5da5Sopenharmony_ci               OpEntryPoint GLCompute %1 "main"
147fd4e5da5Sopenharmony_ci       %void = OpTypeVoid
148fd4e5da5Sopenharmony_ci       %bool = OpTypeBool
149fd4e5da5Sopenharmony_ci       %true = OpConstantTrue %bool
150fd4e5da5Sopenharmony_ci       %uint = OpTypeInt 32 0
151fd4e5da5Sopenharmony_ci     %uint_0 = OpConstant %uint 0
152fd4e5da5Sopenharmony_ci     %uint_4 = OpConstant %uint 4
153fd4e5da5Sopenharmony_ci%_arr_uint_uint_4 = OpTypeArray %uint %uint_4
154fd4e5da5Sopenharmony_ci%_ptr_Uniform_uint = OpTypePointer Uniform %uint
155fd4e5da5Sopenharmony_ci%_ptr_Uniform__arr_uint_uint_4 = OpTypePointer Uniform %_arr_uint_uint_4
156fd4e5da5Sopenharmony_ci         %11 = OpVariable %_ptr_Uniform__arr_uint_uint_4 Uniform
157fd4e5da5Sopenharmony_ci         %12 = OpTypeFunction %void
158fd4e5da5Sopenharmony_ci          %1 = OpFunction %void None %12
159fd4e5da5Sopenharmony_ci         %13 = OpLabel
160fd4e5da5Sopenharmony_ci         %14 = OpAccessChain %_ptr_Uniform_uint %11 %uint_0
161fd4e5da5Sopenharmony_ci         %15 = OpLoad %uint %14
162fd4e5da5Sopenharmony_ci               OpSelectionMerge %16 None
163fd4e5da5Sopenharmony_ci               OpBranchConditional %true %17 %20
164fd4e5da5Sopenharmony_ci         %20 = OpLabel
165fd4e5da5Sopenharmony_ci               OpBranch %16
166fd4e5da5Sopenharmony_ci         %17 = OpLabel
167fd4e5da5Sopenharmony_ci         %18 = OpCopyObject %uint %15
168fd4e5da5Sopenharmony_ci               OpBranch %16
169fd4e5da5Sopenharmony_ci         %16 = OpLabel
170fd4e5da5Sopenharmony_ci         %19 = OpCopyObject %uint %15
171fd4e5da5Sopenharmony_ci               OpReturn
172fd4e5da5Sopenharmony_ci               OpFunctionEnd
173fd4e5da5Sopenharmony_ci)";
174fd4e5da5Sopenharmony_ci
175fd4e5da5Sopenharmony_ci  auto result = SinglePassRunAndDisassemble<CodeSinkingPass>(
176fd4e5da5Sopenharmony_ci      text, /* skip_nop = */ true, /* do_validation = */ true);
177fd4e5da5Sopenharmony_ci  EXPECT_EQ(Pass::Status::SuccessWithoutChange, std::get<1>(result));
178fd4e5da5Sopenharmony_ci}
179fd4e5da5Sopenharmony_ci
180fd4e5da5Sopenharmony_ciTEST_F(CodeSinkTest, LeaveAloneUseInSameBlock) {
181fd4e5da5Sopenharmony_ci  const std::string text = R"(
182fd4e5da5Sopenharmony_ci               OpCapability Shader
183fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
184fd4e5da5Sopenharmony_ci               OpEntryPoint GLCompute %1 "main"
185fd4e5da5Sopenharmony_ci       %void = OpTypeVoid
186fd4e5da5Sopenharmony_ci       %bool = OpTypeBool
187fd4e5da5Sopenharmony_ci       %true = OpConstantTrue %bool
188fd4e5da5Sopenharmony_ci       %uint = OpTypeInt 32 0
189fd4e5da5Sopenharmony_ci     %uint_0 = OpConstant %uint 0
190fd4e5da5Sopenharmony_ci     %uint_4 = OpConstant %uint 4
191fd4e5da5Sopenharmony_ci%_arr_uint_uint_4 = OpTypeArray %uint %uint_4
192fd4e5da5Sopenharmony_ci%_ptr_Uniform_uint = OpTypePointer Uniform %uint
193fd4e5da5Sopenharmony_ci%_ptr_Uniform__arr_uint_uint_4 = OpTypePointer Uniform %_arr_uint_uint_4
194fd4e5da5Sopenharmony_ci         %11 = OpVariable %_ptr_Uniform__arr_uint_uint_4 Uniform
195fd4e5da5Sopenharmony_ci         %12 = OpTypeFunction %void
196fd4e5da5Sopenharmony_ci          %1 = OpFunction %void None %12
197fd4e5da5Sopenharmony_ci         %13 = OpLabel
198fd4e5da5Sopenharmony_ci         %14 = OpAccessChain %_ptr_Uniform_uint %11 %uint_0
199fd4e5da5Sopenharmony_ci         %15 = OpLoad %uint %14
200fd4e5da5Sopenharmony_ci       %cond = OpIEqual %bool %15 %uint_0
201fd4e5da5Sopenharmony_ci               OpSelectionMerge %16 None
202fd4e5da5Sopenharmony_ci               OpBranchConditional %cond %17 %16
203fd4e5da5Sopenharmony_ci         %17 = OpLabel
204fd4e5da5Sopenharmony_ci               OpBranch %16
205fd4e5da5Sopenharmony_ci         %16 = OpLabel
206fd4e5da5Sopenharmony_ci         %19 = OpCopyObject %uint %15
207fd4e5da5Sopenharmony_ci               OpReturn
208fd4e5da5Sopenharmony_ci               OpFunctionEnd
209fd4e5da5Sopenharmony_ci)";
210fd4e5da5Sopenharmony_ci
211fd4e5da5Sopenharmony_ci  auto result = SinglePassRunAndDisassemble<CodeSinkingPass>(
212fd4e5da5Sopenharmony_ci      text, /* skip_nop = */ true, /* do_validation = */ true);
213fd4e5da5Sopenharmony_ci  EXPECT_EQ(Pass::Status::SuccessWithoutChange, std::get<1>(result));
214fd4e5da5Sopenharmony_ci}
215fd4e5da5Sopenharmony_ci
216fd4e5da5Sopenharmony_ciTEST_F(CodeSinkTest, DontMoveIntoLoop) {
217fd4e5da5Sopenharmony_ci  const std::string text = R"(
218fd4e5da5Sopenharmony_ci               OpCapability Shader
219fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
220fd4e5da5Sopenharmony_ci               OpEntryPoint GLCompute %1 "main"
221fd4e5da5Sopenharmony_ci       %void = OpTypeVoid
222fd4e5da5Sopenharmony_ci       %bool = OpTypeBool
223fd4e5da5Sopenharmony_ci       %true = OpConstantTrue %bool
224fd4e5da5Sopenharmony_ci       %uint = OpTypeInt 32 0
225fd4e5da5Sopenharmony_ci     %uint_0 = OpConstant %uint 0
226fd4e5da5Sopenharmony_ci     %uint_4 = OpConstant %uint 4
227fd4e5da5Sopenharmony_ci%_arr_uint_uint_4 = OpTypeArray %uint %uint_4
228fd4e5da5Sopenharmony_ci%_ptr_Uniform_uint = OpTypePointer Uniform %uint
229fd4e5da5Sopenharmony_ci%_ptr_Uniform__arr_uint_uint_4 = OpTypePointer Uniform %_arr_uint_uint_4
230fd4e5da5Sopenharmony_ci         %11 = OpVariable %_ptr_Uniform__arr_uint_uint_4 Uniform
231fd4e5da5Sopenharmony_ci         %12 = OpTypeFunction %void
232fd4e5da5Sopenharmony_ci          %1 = OpFunction %void None %12
233fd4e5da5Sopenharmony_ci         %13 = OpLabel
234fd4e5da5Sopenharmony_ci         %14 = OpAccessChain %_ptr_Uniform_uint %11 %uint_0
235fd4e5da5Sopenharmony_ci         %15 = OpLoad %uint %14
236fd4e5da5Sopenharmony_ci               OpBranch %17
237fd4e5da5Sopenharmony_ci         %17 = OpLabel
238fd4e5da5Sopenharmony_ci               OpLoopMerge %merge %cont None
239fd4e5da5Sopenharmony_ci               OpBranch %cont
240fd4e5da5Sopenharmony_ci       %cont = OpLabel
241fd4e5da5Sopenharmony_ci       %cond = OpIEqual %bool %15 %uint_0
242fd4e5da5Sopenharmony_ci               OpBranchConditional %cond %merge %17
243fd4e5da5Sopenharmony_ci      %merge = OpLabel
244fd4e5da5Sopenharmony_ci               OpReturn
245fd4e5da5Sopenharmony_ci               OpFunctionEnd
246fd4e5da5Sopenharmony_ci)";
247fd4e5da5Sopenharmony_ci
248fd4e5da5Sopenharmony_ci  auto result = SinglePassRunAndDisassemble<CodeSinkingPass>(
249fd4e5da5Sopenharmony_ci      text, /* skip_nop = */ true, /* do_validation = */ true);
250fd4e5da5Sopenharmony_ci  EXPECT_EQ(Pass::Status::SuccessWithoutChange, std::get<1>(result));
251fd4e5da5Sopenharmony_ci}
252fd4e5da5Sopenharmony_ci
253fd4e5da5Sopenharmony_ciTEST_F(CodeSinkTest, DontMoveIntoLoop2) {
254fd4e5da5Sopenharmony_ci  const std::string text = R"(
255fd4e5da5Sopenharmony_ci               OpCapability Shader
256fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
257fd4e5da5Sopenharmony_ci               OpEntryPoint GLCompute %1 "main"
258fd4e5da5Sopenharmony_ci       %void = OpTypeVoid
259fd4e5da5Sopenharmony_ci       %bool = OpTypeBool
260fd4e5da5Sopenharmony_ci       %true = OpConstantTrue %bool
261fd4e5da5Sopenharmony_ci       %uint = OpTypeInt 32 0
262fd4e5da5Sopenharmony_ci     %uint_0 = OpConstant %uint 0
263fd4e5da5Sopenharmony_ci     %uint_4 = OpConstant %uint 4
264fd4e5da5Sopenharmony_ci%_arr_uint_uint_4 = OpTypeArray %uint %uint_4
265fd4e5da5Sopenharmony_ci%_ptr_Uniform_uint = OpTypePointer Uniform %uint
266fd4e5da5Sopenharmony_ci%_ptr_Uniform__arr_uint_uint_4 = OpTypePointer Uniform %_arr_uint_uint_4
267fd4e5da5Sopenharmony_ci         %11 = OpVariable %_ptr_Uniform__arr_uint_uint_4 Uniform
268fd4e5da5Sopenharmony_ci         %12 = OpTypeFunction %void
269fd4e5da5Sopenharmony_ci          %1 = OpFunction %void None %12
270fd4e5da5Sopenharmony_ci         %13 = OpLabel
271fd4e5da5Sopenharmony_ci         %14 = OpAccessChain %_ptr_Uniform_uint %11 %uint_0
272fd4e5da5Sopenharmony_ci         %15 = OpLoad %uint %14
273fd4e5da5Sopenharmony_ci               OpSelectionMerge %16 None
274fd4e5da5Sopenharmony_ci               OpBranchConditional %true %17 %16
275fd4e5da5Sopenharmony_ci         %17 = OpLabel
276fd4e5da5Sopenharmony_ci               OpLoopMerge %merge %cont None
277fd4e5da5Sopenharmony_ci               OpBranch %cont
278fd4e5da5Sopenharmony_ci       %cont = OpLabel
279fd4e5da5Sopenharmony_ci       %cond = OpIEqual %bool %15 %uint_0
280fd4e5da5Sopenharmony_ci               OpBranchConditional %cond %merge %17
281fd4e5da5Sopenharmony_ci      %merge = OpLabel
282fd4e5da5Sopenharmony_ci               OpBranch %16
283fd4e5da5Sopenharmony_ci         %16 = OpLabel
284fd4e5da5Sopenharmony_ci               OpReturn
285fd4e5da5Sopenharmony_ci               OpFunctionEnd
286fd4e5da5Sopenharmony_ci)";
287fd4e5da5Sopenharmony_ci
288fd4e5da5Sopenharmony_ci  auto result = SinglePassRunAndDisassemble<CodeSinkingPass>(
289fd4e5da5Sopenharmony_ci      text, /* skip_nop = */ true, /* do_validation = */ true);
290fd4e5da5Sopenharmony_ci  EXPECT_EQ(Pass::Status::SuccessWithoutChange, std::get<1>(result));
291fd4e5da5Sopenharmony_ci}
292fd4e5da5Sopenharmony_ci
293fd4e5da5Sopenharmony_ciTEST_F(CodeSinkTest, DontMoveSelectionUsedInBothSides) {
294fd4e5da5Sopenharmony_ci  const std::string text = R"(
295fd4e5da5Sopenharmony_ci               OpCapability Shader
296fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
297fd4e5da5Sopenharmony_ci               OpEntryPoint GLCompute %1 "main"
298fd4e5da5Sopenharmony_ci       %void = OpTypeVoid
299fd4e5da5Sopenharmony_ci       %bool = OpTypeBool
300fd4e5da5Sopenharmony_ci       %true = OpConstantTrue %bool
301fd4e5da5Sopenharmony_ci       %uint = OpTypeInt 32 0
302fd4e5da5Sopenharmony_ci     %uint_0 = OpConstant %uint 0
303fd4e5da5Sopenharmony_ci     %uint_4 = OpConstant %uint 4
304fd4e5da5Sopenharmony_ci%_arr_uint_uint_4 = OpTypeArray %uint %uint_4
305fd4e5da5Sopenharmony_ci%_ptr_Uniform_uint = OpTypePointer Uniform %uint
306fd4e5da5Sopenharmony_ci%_ptr_Uniform__arr_uint_uint_4 = OpTypePointer Uniform %_arr_uint_uint_4
307fd4e5da5Sopenharmony_ci         %11 = OpVariable %_ptr_Uniform__arr_uint_uint_4 Uniform
308fd4e5da5Sopenharmony_ci         %12 = OpTypeFunction %void
309fd4e5da5Sopenharmony_ci          %1 = OpFunction %void None %12
310fd4e5da5Sopenharmony_ci         %13 = OpLabel
311fd4e5da5Sopenharmony_ci         %14 = OpAccessChain %_ptr_Uniform_uint %11 %uint_0
312fd4e5da5Sopenharmony_ci         %15 = OpLoad %uint %14
313fd4e5da5Sopenharmony_ci               OpSelectionMerge %16 None
314fd4e5da5Sopenharmony_ci               OpBranchConditional %true %17 %20
315fd4e5da5Sopenharmony_ci         %20 = OpLabel
316fd4e5da5Sopenharmony_ci         %19 = OpCopyObject %uint %15
317fd4e5da5Sopenharmony_ci               OpBranch %16
318fd4e5da5Sopenharmony_ci         %17 = OpLabel
319fd4e5da5Sopenharmony_ci         %18 = OpCopyObject %uint %15
320fd4e5da5Sopenharmony_ci               OpBranch %16
321fd4e5da5Sopenharmony_ci         %16 = OpLabel
322fd4e5da5Sopenharmony_ci               OpReturn
323fd4e5da5Sopenharmony_ci               OpFunctionEnd
324fd4e5da5Sopenharmony_ci)";
325fd4e5da5Sopenharmony_ci
326fd4e5da5Sopenharmony_ci  auto result = SinglePassRunAndDisassemble<CodeSinkingPass>(
327fd4e5da5Sopenharmony_ci      text, /* skip_nop = */ true, /* do_validation = */ true);
328fd4e5da5Sopenharmony_ci  EXPECT_EQ(Pass::Status::SuccessWithoutChange, std::get<1>(result));
329fd4e5da5Sopenharmony_ci}
330fd4e5da5Sopenharmony_ci
331fd4e5da5Sopenharmony_ciTEST_F(CodeSinkTest, DontMoveBecauseOfStore) {
332fd4e5da5Sopenharmony_ci  const std::string text = R"(
333fd4e5da5Sopenharmony_ci               OpCapability Shader
334fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
335fd4e5da5Sopenharmony_ci               OpEntryPoint GLCompute %1 "main"
336fd4e5da5Sopenharmony_ci       %void = OpTypeVoid
337fd4e5da5Sopenharmony_ci       %bool = OpTypeBool
338fd4e5da5Sopenharmony_ci       %true = OpConstantTrue %bool
339fd4e5da5Sopenharmony_ci       %uint = OpTypeInt 32 0
340fd4e5da5Sopenharmony_ci     %uint_0 = OpConstant %uint 0
341fd4e5da5Sopenharmony_ci     %uint_4 = OpConstant %uint 4
342fd4e5da5Sopenharmony_ci%_arr_uint_uint_4 = OpTypeArray %uint %uint_4
343fd4e5da5Sopenharmony_ci%_ptr_Uniform_uint = OpTypePointer Uniform %uint
344fd4e5da5Sopenharmony_ci%_ptr_Uniform__arr_uint_uint_4 = OpTypePointer Uniform %_arr_uint_uint_4
345fd4e5da5Sopenharmony_ci         %11 = OpVariable %_ptr_Uniform__arr_uint_uint_4 Uniform
346fd4e5da5Sopenharmony_ci         %12 = OpTypeFunction %void
347fd4e5da5Sopenharmony_ci          %1 = OpFunction %void None %12
348fd4e5da5Sopenharmony_ci         %13 = OpLabel
349fd4e5da5Sopenharmony_ci         %14 = OpAccessChain %_ptr_Uniform_uint %11 %uint_0
350fd4e5da5Sopenharmony_ci         %15 = OpLoad %uint %14
351fd4e5da5Sopenharmony_ci               OpStore %14 %15
352fd4e5da5Sopenharmony_ci               OpSelectionMerge %16 None
353fd4e5da5Sopenharmony_ci               OpBranchConditional %true %17 %20
354fd4e5da5Sopenharmony_ci         %20 = OpLabel
355fd4e5da5Sopenharmony_ci               OpBranch %16
356fd4e5da5Sopenharmony_ci         %17 = OpLabel
357fd4e5da5Sopenharmony_ci         %18 = OpCopyObject %uint %15
358fd4e5da5Sopenharmony_ci               OpBranch %16
359fd4e5da5Sopenharmony_ci         %16 = OpLabel
360fd4e5da5Sopenharmony_ci               OpReturn
361fd4e5da5Sopenharmony_ci               OpFunctionEnd
362fd4e5da5Sopenharmony_ci)";
363fd4e5da5Sopenharmony_ci
364fd4e5da5Sopenharmony_ci  auto result = SinglePassRunAndDisassemble<CodeSinkingPass>(
365fd4e5da5Sopenharmony_ci      text, /* skip_nop = */ true, /* do_validation = */ true);
366fd4e5da5Sopenharmony_ci  EXPECT_EQ(Pass::Status::SuccessWithoutChange, std::get<1>(result));
367fd4e5da5Sopenharmony_ci}
368fd4e5da5Sopenharmony_ci
369fd4e5da5Sopenharmony_ciTEST_F(CodeSinkTest, MoveReadOnlyLoadWithSync) {
370fd4e5da5Sopenharmony_ci  const std::string text = R"(
371fd4e5da5Sopenharmony_ci               OpCapability Shader
372fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
373fd4e5da5Sopenharmony_ci               OpEntryPoint GLCompute %1 "main"
374fd4e5da5Sopenharmony_ci       %void = OpTypeVoid
375fd4e5da5Sopenharmony_ci       %bool = OpTypeBool
376fd4e5da5Sopenharmony_ci       %true = OpConstantTrue %bool
377fd4e5da5Sopenharmony_ci       %uint = OpTypeInt 32 0
378fd4e5da5Sopenharmony_ci     %uint_0 = OpConstant %uint 0
379fd4e5da5Sopenharmony_ci     %uint_4 = OpConstant %uint 4
380fd4e5da5Sopenharmony_ci%mem_semantics = OpConstant %uint 0x42 ; Uniform memory arquire
381fd4e5da5Sopenharmony_ci%_arr_uint_uint_4 = OpTypeArray %uint %uint_4
382fd4e5da5Sopenharmony_ci%_ptr_Uniform_uint = OpTypePointer Uniform %uint
383fd4e5da5Sopenharmony_ci%_ptr_Uniform__arr_uint_uint_4 = OpTypePointer Uniform %_arr_uint_uint_4
384fd4e5da5Sopenharmony_ci         %11 = OpVariable %_ptr_Uniform__arr_uint_uint_4 Uniform
385fd4e5da5Sopenharmony_ci         %12 = OpTypeFunction %void
386fd4e5da5Sopenharmony_ci          %1 = OpFunction %void None %12
387fd4e5da5Sopenharmony_ci         %13 = OpLabel
388fd4e5da5Sopenharmony_ci         %14 = OpAccessChain %_ptr_Uniform_uint %11 %uint_0
389fd4e5da5Sopenharmony_ci         %15 = OpLoad %uint %14
390fd4e5da5Sopenharmony_ci               OpMemoryBarrier %uint_4 %mem_semantics
391fd4e5da5Sopenharmony_ci               OpSelectionMerge %16 None
392fd4e5da5Sopenharmony_ci               OpBranchConditional %true %17 %20
393fd4e5da5Sopenharmony_ci         %20 = OpLabel
394fd4e5da5Sopenharmony_ci               OpBranch %16
395fd4e5da5Sopenharmony_ci         %17 = OpLabel
396fd4e5da5Sopenharmony_ci         %18 = OpCopyObject %uint %15
397fd4e5da5Sopenharmony_ci               OpBranch %16
398fd4e5da5Sopenharmony_ci         %16 = OpLabel
399fd4e5da5Sopenharmony_ci               OpReturn
400fd4e5da5Sopenharmony_ci               OpFunctionEnd
401fd4e5da5Sopenharmony_ci)";
402fd4e5da5Sopenharmony_ci
403fd4e5da5Sopenharmony_ci  auto result = SinglePassRunAndDisassemble<CodeSinkingPass>(
404fd4e5da5Sopenharmony_ci      text, /* skip_nop = */ true, /* do_validation = */ true);
405fd4e5da5Sopenharmony_ci  EXPECT_EQ(Pass::Status::SuccessWithChange, std::get<1>(result));
406fd4e5da5Sopenharmony_ci}
407fd4e5da5Sopenharmony_ci
408fd4e5da5Sopenharmony_ciTEST_F(CodeSinkTest, DontMoveBecauseOfSync) {
409fd4e5da5Sopenharmony_ci  const std::string text = R"(
410fd4e5da5Sopenharmony_ci               OpCapability Shader
411fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
412fd4e5da5Sopenharmony_ci               OpEntryPoint GLCompute %1 "main"
413fd4e5da5Sopenharmony_ci               OpDecorate %_arr_uint_uint_4 BufferBlock
414fd4e5da5Sopenharmony_ci               OpMemberDecorate %_arr_uint_uint_4 0 Offset 0
415fd4e5da5Sopenharmony_ci       %void = OpTypeVoid
416fd4e5da5Sopenharmony_ci       %bool = OpTypeBool
417fd4e5da5Sopenharmony_ci       %true = OpConstantTrue %bool
418fd4e5da5Sopenharmony_ci       %uint = OpTypeInt 32 0
419fd4e5da5Sopenharmony_ci     %uint_0 = OpConstant %uint 0
420fd4e5da5Sopenharmony_ci     %uint_4 = OpConstant %uint 4
421fd4e5da5Sopenharmony_ci%mem_semantics = OpConstant %uint 0x42 ; Uniform memory arquire
422fd4e5da5Sopenharmony_ci%_arr_uint_uint_4 = OpTypeStruct %uint
423fd4e5da5Sopenharmony_ci%_ptr_Uniform_uint = OpTypePointer Uniform %uint
424fd4e5da5Sopenharmony_ci%_ptr_Uniform__arr_uint_uint_4 = OpTypePointer Uniform %_arr_uint_uint_4
425fd4e5da5Sopenharmony_ci         %11 = OpVariable %_ptr_Uniform__arr_uint_uint_4 Uniform
426fd4e5da5Sopenharmony_ci         %12 = OpTypeFunction %void
427fd4e5da5Sopenharmony_ci          %1 = OpFunction %void None %12
428fd4e5da5Sopenharmony_ci         %13 = OpLabel
429fd4e5da5Sopenharmony_ci         %14 = OpAccessChain %_ptr_Uniform_uint %11 %uint_0
430fd4e5da5Sopenharmony_ci         %15 = OpLoad %uint %14
431fd4e5da5Sopenharmony_ci               OpMemoryBarrier %uint_4 %mem_semantics
432fd4e5da5Sopenharmony_ci               OpSelectionMerge %16 None
433fd4e5da5Sopenharmony_ci               OpBranchConditional %true %17 %20
434fd4e5da5Sopenharmony_ci         %20 = OpLabel
435fd4e5da5Sopenharmony_ci               OpBranch %16
436fd4e5da5Sopenharmony_ci         %17 = OpLabel
437fd4e5da5Sopenharmony_ci         %18 = OpCopyObject %uint %15
438fd4e5da5Sopenharmony_ci               OpBranch %16
439fd4e5da5Sopenharmony_ci         %16 = OpLabel
440fd4e5da5Sopenharmony_ci               OpReturn
441fd4e5da5Sopenharmony_ci               OpFunctionEnd
442fd4e5da5Sopenharmony_ci)";
443fd4e5da5Sopenharmony_ci
444fd4e5da5Sopenharmony_ci  auto result = SinglePassRunAndDisassemble<CodeSinkingPass>(
445fd4e5da5Sopenharmony_ci      text, /* skip_nop = */ true, /* do_validation = */ true);
446fd4e5da5Sopenharmony_ci  EXPECT_EQ(Pass::Status::SuccessWithoutChange, std::get<1>(result));
447fd4e5da5Sopenharmony_ci}
448fd4e5da5Sopenharmony_ci
449fd4e5da5Sopenharmony_ciTEST_F(CodeSinkTest, DontMoveBecauseOfAtomicWithSync) {
450fd4e5da5Sopenharmony_ci  const std::string text = R"(
451fd4e5da5Sopenharmony_ci               OpCapability Shader
452fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
453fd4e5da5Sopenharmony_ci               OpEntryPoint GLCompute %1 "main"
454fd4e5da5Sopenharmony_ci               OpDecorate %_arr_uint_uint_4 BufferBlock
455fd4e5da5Sopenharmony_ci               OpMemberDecorate %_arr_uint_uint_4 0 Offset 0
456fd4e5da5Sopenharmony_ci       %void = OpTypeVoid
457fd4e5da5Sopenharmony_ci       %bool = OpTypeBool
458fd4e5da5Sopenharmony_ci       %true = OpConstantTrue %bool
459fd4e5da5Sopenharmony_ci       %uint = OpTypeInt 32 0
460fd4e5da5Sopenharmony_ci     %uint_0 = OpConstant %uint 0
461fd4e5da5Sopenharmony_ci     %uint_4 = OpConstant %uint 4
462fd4e5da5Sopenharmony_ci%mem_semantics = OpConstant %uint 0x42 ; Uniform memory arquire
463fd4e5da5Sopenharmony_ci%_arr_uint_uint_4 = OpTypeStruct %uint
464fd4e5da5Sopenharmony_ci%_ptr_Uniform_uint = OpTypePointer Uniform %uint
465fd4e5da5Sopenharmony_ci%_ptr_Uniform__arr_uint_uint_4 = OpTypePointer Uniform %_arr_uint_uint_4
466fd4e5da5Sopenharmony_ci         %11 = OpVariable %_ptr_Uniform__arr_uint_uint_4 Uniform
467fd4e5da5Sopenharmony_ci         %12 = OpTypeFunction %void
468fd4e5da5Sopenharmony_ci          %1 = OpFunction %void None %12
469fd4e5da5Sopenharmony_ci         %13 = OpLabel
470fd4e5da5Sopenharmony_ci         %14 = OpAccessChain %_ptr_Uniform_uint %11 %uint_0
471fd4e5da5Sopenharmony_ci         %15 = OpLoad %uint %14
472fd4e5da5Sopenharmony_ci         %al = OpAtomicLoad %uint %14 %uint_4 %mem_semantics
473fd4e5da5Sopenharmony_ci               OpSelectionMerge %16 None
474fd4e5da5Sopenharmony_ci               OpBranchConditional %true %17 %20
475fd4e5da5Sopenharmony_ci         %20 = OpLabel
476fd4e5da5Sopenharmony_ci               OpBranch %16
477fd4e5da5Sopenharmony_ci         %17 = OpLabel
478fd4e5da5Sopenharmony_ci         %18 = OpCopyObject %uint %15
479fd4e5da5Sopenharmony_ci               OpBranch %16
480fd4e5da5Sopenharmony_ci         %16 = OpLabel
481fd4e5da5Sopenharmony_ci               OpReturn
482fd4e5da5Sopenharmony_ci               OpFunctionEnd
483fd4e5da5Sopenharmony_ci)";
484fd4e5da5Sopenharmony_ci
485fd4e5da5Sopenharmony_ci  auto result = SinglePassRunAndDisassemble<CodeSinkingPass>(
486fd4e5da5Sopenharmony_ci      text, /* skip_nop = */ true, /* do_validation = */ true);
487fd4e5da5Sopenharmony_ci  EXPECT_EQ(Pass::Status::SuccessWithoutChange, std::get<1>(result));
488fd4e5da5Sopenharmony_ci}
489fd4e5da5Sopenharmony_ci
490fd4e5da5Sopenharmony_ciTEST_F(CodeSinkTest, MoveWithAtomicWithoutSync) {
491fd4e5da5Sopenharmony_ci  const std::string text = R"(
492fd4e5da5Sopenharmony_ci               OpCapability Shader
493fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
494fd4e5da5Sopenharmony_ci               OpEntryPoint GLCompute %1 "main"
495fd4e5da5Sopenharmony_ci               OpDecorate %_arr_uint_uint_4 BufferBlock
496fd4e5da5Sopenharmony_ci               OpMemberDecorate %_arr_uint_uint_4 0 Offset 0
497fd4e5da5Sopenharmony_ci       %void = OpTypeVoid
498fd4e5da5Sopenharmony_ci       %bool = OpTypeBool
499fd4e5da5Sopenharmony_ci       %true = OpConstantTrue %bool
500fd4e5da5Sopenharmony_ci       %uint = OpTypeInt 32 0
501fd4e5da5Sopenharmony_ci     %uint_0 = OpConstant %uint 0
502fd4e5da5Sopenharmony_ci     %uint_4 = OpConstant %uint 4
503fd4e5da5Sopenharmony_ci%_arr_uint_uint_4 = OpTypeStruct %uint
504fd4e5da5Sopenharmony_ci%_ptr_Uniform_uint = OpTypePointer Uniform %uint
505fd4e5da5Sopenharmony_ci%_ptr_Uniform__arr_uint_uint_4 = OpTypePointer Uniform %_arr_uint_uint_4
506fd4e5da5Sopenharmony_ci         %11 = OpVariable %_ptr_Uniform__arr_uint_uint_4 Uniform
507fd4e5da5Sopenharmony_ci         %12 = OpTypeFunction %void
508fd4e5da5Sopenharmony_ci          %1 = OpFunction %void None %12
509fd4e5da5Sopenharmony_ci         %13 = OpLabel
510fd4e5da5Sopenharmony_ci         %14 = OpAccessChain %_ptr_Uniform_uint %11 %uint_0
511fd4e5da5Sopenharmony_ci         %15 = OpLoad %uint %14
512fd4e5da5Sopenharmony_ci         %al = OpAtomicLoad %uint %14 %uint_4 %uint_0
513fd4e5da5Sopenharmony_ci               OpSelectionMerge %16 None
514fd4e5da5Sopenharmony_ci               OpBranchConditional %true %17 %20
515fd4e5da5Sopenharmony_ci         %20 = OpLabel
516fd4e5da5Sopenharmony_ci               OpBranch %16
517fd4e5da5Sopenharmony_ci         %17 = OpLabel
518fd4e5da5Sopenharmony_ci         %18 = OpCopyObject %uint %15
519fd4e5da5Sopenharmony_ci               OpBranch %16
520fd4e5da5Sopenharmony_ci         %16 = OpLabel
521fd4e5da5Sopenharmony_ci               OpReturn
522fd4e5da5Sopenharmony_ci               OpFunctionEnd
523fd4e5da5Sopenharmony_ci)";
524fd4e5da5Sopenharmony_ci
525fd4e5da5Sopenharmony_ci  auto result = SinglePassRunAndDisassemble<CodeSinkingPass>(
526fd4e5da5Sopenharmony_ci      text, /* skip_nop = */ true, /* do_validation = */ true);
527fd4e5da5Sopenharmony_ci  EXPECT_EQ(Pass::Status::SuccessWithChange, std::get<1>(result));
528fd4e5da5Sopenharmony_ci}
529fd4e5da5Sopenharmony_ci
530fd4e5da5Sopenharmony_ciTEST_F(CodeSinkTest, DecorationOnLoad) {
531fd4e5da5Sopenharmony_ci  const std::string text = R"(
532fd4e5da5Sopenharmony_ci               OpCapability Shader
533fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
534fd4e5da5Sopenharmony_ci               OpEntryPoint GLCompute %1 "main" %2
535fd4e5da5Sopenharmony_ci               OpDecorate %3 RelaxedPrecision
536fd4e5da5Sopenharmony_ci       %void = OpTypeVoid
537fd4e5da5Sopenharmony_ci          %5 = OpTypeFunction %void
538fd4e5da5Sopenharmony_ci      %float = OpTypeFloat 32
539fd4e5da5Sopenharmony_ci%_ptr_Input_float = OpTypePointer Input %float
540fd4e5da5Sopenharmony_ci          %2 = OpVariable %_ptr_Input_float Input
541fd4e5da5Sopenharmony_ci          %1 = OpFunction %void None %5
542fd4e5da5Sopenharmony_ci          %8 = OpLabel
543fd4e5da5Sopenharmony_ci          %3 = OpLoad %float %2
544fd4e5da5Sopenharmony_ci               OpReturn
545fd4e5da5Sopenharmony_ci               OpFunctionEnd
546fd4e5da5Sopenharmony_ci)";
547fd4e5da5Sopenharmony_ci
548fd4e5da5Sopenharmony_ci  // We just want to make sure the code does not crash.
549fd4e5da5Sopenharmony_ci  auto result = SinglePassRunAndDisassemble<CodeSinkingPass>(
550fd4e5da5Sopenharmony_ci      text, /* skip_nop = */ true, /* do_validation = */ true);
551fd4e5da5Sopenharmony_ci  EXPECT_EQ(Pass::Status::SuccessWithoutChange, std::get<1>(result));
552fd4e5da5Sopenharmony_ci}
553fd4e5da5Sopenharmony_ci
554fd4e5da5Sopenharmony_ci}  // namespace
555fd4e5da5Sopenharmony_ci}  // namespace opt
556fd4e5da5Sopenharmony_ci}  // namespace spvtools
557