1fd4e5da5Sopenharmony_ci// Copyright (c) 2017 Valve Corporation
2fd4e5da5Sopenharmony_ci// Copyright (c) 2017 LunarG Inc.
3fd4e5da5Sopenharmony_ci//
4fd4e5da5Sopenharmony_ci// Licensed under the Apache License, Version 2.0 (the "License");
5fd4e5da5Sopenharmony_ci// you may not use this file except in compliance with the License.
6fd4e5da5Sopenharmony_ci// You may obtain a copy of the License at
7fd4e5da5Sopenharmony_ci//
8fd4e5da5Sopenharmony_ci//     http://www.apache.org/licenses/LICENSE-2.0
9fd4e5da5Sopenharmony_ci//
10fd4e5da5Sopenharmony_ci// Unless required by applicable law or agreed to in writing, software
11fd4e5da5Sopenharmony_ci// distributed under the License is distributed on an "AS IS" BASIS,
12fd4e5da5Sopenharmony_ci// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13fd4e5da5Sopenharmony_ci// See the License for the specific language governing permissions and
14fd4e5da5Sopenharmony_ci// limitations under the License.
15fd4e5da5Sopenharmony_ci
16fd4e5da5Sopenharmony_ci#include <string>
17fd4e5da5Sopenharmony_ci
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 BlockMergeTest = PassTest<::testing::Test>;
26fd4e5da5Sopenharmony_ci
27fd4e5da5Sopenharmony_ciTEST_F(BlockMergeTest, Simple) {
28fd4e5da5Sopenharmony_ci  // Note: SPIR-V hand edited to insert block boundary
29fd4e5da5Sopenharmony_ci  // between two statements in main.
30fd4e5da5Sopenharmony_ci  //
31fd4e5da5Sopenharmony_ci  //  #version 140
32fd4e5da5Sopenharmony_ci  //
33fd4e5da5Sopenharmony_ci  //  in vec4 BaseColor;
34fd4e5da5Sopenharmony_ci  //
35fd4e5da5Sopenharmony_ci  //  void main()
36fd4e5da5Sopenharmony_ci  //  {
37fd4e5da5Sopenharmony_ci  //      vec4 v = BaseColor;
38fd4e5da5Sopenharmony_ci  //      gl_FragColor = v;
39fd4e5da5Sopenharmony_ci  //  }
40fd4e5da5Sopenharmony_ci
41fd4e5da5Sopenharmony_ci  const std::string predefs =
42fd4e5da5Sopenharmony_ci      R"(OpCapability Shader
43fd4e5da5Sopenharmony_ci%1 = OpExtInstImport "GLSL.std.450"
44fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
45fd4e5da5Sopenharmony_ciOpEntryPoint Fragment %main "main" %BaseColor %gl_FragColor
46fd4e5da5Sopenharmony_ciOpExecutionMode %main OriginUpperLeft
47fd4e5da5Sopenharmony_ciOpSource GLSL 140
48fd4e5da5Sopenharmony_ciOpName %main "main"
49fd4e5da5Sopenharmony_ciOpName %v "v"
50fd4e5da5Sopenharmony_ciOpName %BaseColor "BaseColor"
51fd4e5da5Sopenharmony_ciOpName %gl_FragColor "gl_FragColor"
52fd4e5da5Sopenharmony_ci%void = OpTypeVoid
53fd4e5da5Sopenharmony_ci%7 = OpTypeFunction %void
54fd4e5da5Sopenharmony_ci%float = OpTypeFloat 32
55fd4e5da5Sopenharmony_ci%v4float = OpTypeVector %float 4
56fd4e5da5Sopenharmony_ci%_ptr_Function_v4float = OpTypePointer Function %v4float
57fd4e5da5Sopenharmony_ci%_ptr_Input_v4float = OpTypePointer Input %v4float
58fd4e5da5Sopenharmony_ci%BaseColor = OpVariable %_ptr_Input_v4float Input
59fd4e5da5Sopenharmony_ci%_ptr_Output_v4float = OpTypePointer Output %v4float
60fd4e5da5Sopenharmony_ci%gl_FragColor = OpVariable %_ptr_Output_v4float Output
61fd4e5da5Sopenharmony_ci)";
62fd4e5da5Sopenharmony_ci
63fd4e5da5Sopenharmony_ci  const std::string before =
64fd4e5da5Sopenharmony_ci      R"(%main = OpFunction %void None %7
65fd4e5da5Sopenharmony_ci%13 = OpLabel
66fd4e5da5Sopenharmony_ci%v = OpVariable %_ptr_Function_v4float Function
67fd4e5da5Sopenharmony_ci%14 = OpLoad %v4float %BaseColor
68fd4e5da5Sopenharmony_ciOpStore %v %14
69fd4e5da5Sopenharmony_ciOpBranch %15
70fd4e5da5Sopenharmony_ci%15 = OpLabel
71fd4e5da5Sopenharmony_ci%16 = OpLoad %v4float %v
72fd4e5da5Sopenharmony_ciOpStore %gl_FragColor %16
73fd4e5da5Sopenharmony_ciOpReturn
74fd4e5da5Sopenharmony_ciOpFunctionEnd
75fd4e5da5Sopenharmony_ci)";
76fd4e5da5Sopenharmony_ci
77fd4e5da5Sopenharmony_ci  const std::string after =
78fd4e5da5Sopenharmony_ci      R"(%main = OpFunction %void None %7
79fd4e5da5Sopenharmony_ci%13 = OpLabel
80fd4e5da5Sopenharmony_ci%v = OpVariable %_ptr_Function_v4float Function
81fd4e5da5Sopenharmony_ci%14 = OpLoad %v4float %BaseColor
82fd4e5da5Sopenharmony_ciOpStore %v %14
83fd4e5da5Sopenharmony_ci%16 = OpLoad %v4float %v
84fd4e5da5Sopenharmony_ciOpStore %gl_FragColor %16
85fd4e5da5Sopenharmony_ciOpReturn
86fd4e5da5Sopenharmony_ciOpFunctionEnd
87fd4e5da5Sopenharmony_ci)";
88fd4e5da5Sopenharmony_ci
89fd4e5da5Sopenharmony_ci  SinglePassRunAndCheck<BlockMergePass>(predefs + before, predefs + after, true,
90fd4e5da5Sopenharmony_ci                                        true);
91fd4e5da5Sopenharmony_ci}
92fd4e5da5Sopenharmony_ci
93fd4e5da5Sopenharmony_ciTEST_F(BlockMergeTest, BlockMergeForLinkage) {
94fd4e5da5Sopenharmony_ci  const std::string before =
95fd4e5da5Sopenharmony_ci      R"(OpCapability Shader
96fd4e5da5Sopenharmony_ciOpCapability Linkage
97fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
98fd4e5da5Sopenharmony_ciOpSource HLSL 630
99fd4e5da5Sopenharmony_ciOpName %main "main"
100fd4e5da5Sopenharmony_ciOpName %BaseColor "BaseColor"
101fd4e5da5Sopenharmony_ciOpName %bb_entry "bb.entry"
102fd4e5da5Sopenharmony_ciOpName %v "v"
103fd4e5da5Sopenharmony_ciOpDecorate %main LinkageAttributes "main" Export
104fd4e5da5Sopenharmony_ci%float = OpTypeFloat 32
105fd4e5da5Sopenharmony_ci%v4float = OpTypeVector %float 4
106fd4e5da5Sopenharmony_ci%_ptr_Function_v4float = OpTypePointer Function %v4float
107fd4e5da5Sopenharmony_ci%8 = OpTypeFunction %v4float %_ptr_Function_v4float
108fd4e5da5Sopenharmony_ci%main = OpFunction %v4float None %8
109fd4e5da5Sopenharmony_ci%BaseColor = OpFunctionParameter %_ptr_Function_v4float
110fd4e5da5Sopenharmony_ci%bb_entry = OpLabel
111fd4e5da5Sopenharmony_ci%v = OpVariable %_ptr_Function_v4float Function
112fd4e5da5Sopenharmony_ci%9 = OpLoad %v4float %BaseColor
113fd4e5da5Sopenharmony_ciOpStore %v %9
114fd4e5da5Sopenharmony_ciOpBranch %10
115fd4e5da5Sopenharmony_ci%10 = OpLabel
116fd4e5da5Sopenharmony_ci%11 = OpLoad %v4float %v
117fd4e5da5Sopenharmony_ciOpBranch %12
118fd4e5da5Sopenharmony_ci%12 = OpLabel
119fd4e5da5Sopenharmony_ciOpReturnValue %11
120fd4e5da5Sopenharmony_ciOpFunctionEnd
121fd4e5da5Sopenharmony_ci)";
122fd4e5da5Sopenharmony_ci
123fd4e5da5Sopenharmony_ci  const std::string after =
124fd4e5da5Sopenharmony_ci      R"(OpCapability Shader
125fd4e5da5Sopenharmony_ciOpCapability Linkage
126fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
127fd4e5da5Sopenharmony_ciOpSource HLSL 630
128fd4e5da5Sopenharmony_ciOpName %main "main"
129fd4e5da5Sopenharmony_ciOpName %BaseColor "BaseColor"
130fd4e5da5Sopenharmony_ciOpName %bb_entry "bb.entry"
131fd4e5da5Sopenharmony_ciOpName %v "v"
132fd4e5da5Sopenharmony_ciOpDecorate %main LinkageAttributes "main" Export
133fd4e5da5Sopenharmony_ci%float = OpTypeFloat 32
134fd4e5da5Sopenharmony_ci%v4float = OpTypeVector %float 4
135fd4e5da5Sopenharmony_ci%_ptr_Function_v4float = OpTypePointer Function %v4float
136fd4e5da5Sopenharmony_ci%8 = OpTypeFunction %v4float %_ptr_Function_v4float
137fd4e5da5Sopenharmony_ci%main = OpFunction %v4float None %8
138fd4e5da5Sopenharmony_ci%BaseColor = OpFunctionParameter %_ptr_Function_v4float
139fd4e5da5Sopenharmony_ci%bb_entry = OpLabel
140fd4e5da5Sopenharmony_ci%v = OpVariable %_ptr_Function_v4float Function
141fd4e5da5Sopenharmony_ci%9 = OpLoad %v4float %BaseColor
142fd4e5da5Sopenharmony_ciOpStore %v %9
143fd4e5da5Sopenharmony_ci%11 = OpLoad %v4float %v
144fd4e5da5Sopenharmony_ciOpReturnValue %11
145fd4e5da5Sopenharmony_ciOpFunctionEnd
146fd4e5da5Sopenharmony_ci)";
147fd4e5da5Sopenharmony_ci  SinglePassRunAndCheck<BlockMergePass>(before, after, true, true);
148fd4e5da5Sopenharmony_ci}
149fd4e5da5Sopenharmony_ci
150fd4e5da5Sopenharmony_ciTEST_F(BlockMergeTest, EmptyBlock) {
151fd4e5da5Sopenharmony_ci  // Note: SPIR-V hand edited to insert empty block
152fd4e5da5Sopenharmony_ci  // after two statements in main.
153fd4e5da5Sopenharmony_ci  //
154fd4e5da5Sopenharmony_ci  //  #version 140
155fd4e5da5Sopenharmony_ci  //
156fd4e5da5Sopenharmony_ci  //  in vec4 BaseColor;
157fd4e5da5Sopenharmony_ci  //
158fd4e5da5Sopenharmony_ci  //  void main()
159fd4e5da5Sopenharmony_ci  //  {
160fd4e5da5Sopenharmony_ci  //      vec4 v = BaseColor;
161fd4e5da5Sopenharmony_ci  //      gl_FragColor = v;
162fd4e5da5Sopenharmony_ci  //  }
163fd4e5da5Sopenharmony_ci
164fd4e5da5Sopenharmony_ci  const std::string predefs =
165fd4e5da5Sopenharmony_ci      R"(OpCapability Shader
166fd4e5da5Sopenharmony_ci%1 = OpExtInstImport "GLSL.std.450"
167fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
168fd4e5da5Sopenharmony_ciOpEntryPoint Fragment %main "main" %BaseColor %gl_FragColor
169fd4e5da5Sopenharmony_ciOpExecutionMode %main OriginUpperLeft
170fd4e5da5Sopenharmony_ciOpSource GLSL 140
171fd4e5da5Sopenharmony_ciOpName %main "main"
172fd4e5da5Sopenharmony_ciOpName %v "v"
173fd4e5da5Sopenharmony_ciOpName %BaseColor "BaseColor"
174fd4e5da5Sopenharmony_ciOpName %gl_FragColor "gl_FragColor"
175fd4e5da5Sopenharmony_ci%void = OpTypeVoid
176fd4e5da5Sopenharmony_ci%7 = OpTypeFunction %void
177fd4e5da5Sopenharmony_ci%float = OpTypeFloat 32
178fd4e5da5Sopenharmony_ci%v4float = OpTypeVector %float 4
179fd4e5da5Sopenharmony_ci%_ptr_Function_v4float = OpTypePointer Function %v4float
180fd4e5da5Sopenharmony_ci%_ptr_Input_v4float = OpTypePointer Input %v4float
181fd4e5da5Sopenharmony_ci%BaseColor = OpVariable %_ptr_Input_v4float Input
182fd4e5da5Sopenharmony_ci%_ptr_Output_v4float = OpTypePointer Output %v4float
183fd4e5da5Sopenharmony_ci%gl_FragColor = OpVariable %_ptr_Output_v4float Output
184fd4e5da5Sopenharmony_ci)";
185fd4e5da5Sopenharmony_ci
186fd4e5da5Sopenharmony_ci  const std::string before =
187fd4e5da5Sopenharmony_ci      R"(%main = OpFunction %void None %7
188fd4e5da5Sopenharmony_ci%13 = OpLabel
189fd4e5da5Sopenharmony_ci%v = OpVariable %_ptr_Function_v4float Function
190fd4e5da5Sopenharmony_ci%14 = OpLoad %v4float %BaseColor
191fd4e5da5Sopenharmony_ciOpStore %v %14
192fd4e5da5Sopenharmony_ciOpBranch %15
193fd4e5da5Sopenharmony_ci%15 = OpLabel
194fd4e5da5Sopenharmony_ci%16 = OpLoad %v4float %v
195fd4e5da5Sopenharmony_ciOpStore %gl_FragColor %16
196fd4e5da5Sopenharmony_ciOpBranch %17
197fd4e5da5Sopenharmony_ci%17 = OpLabel
198fd4e5da5Sopenharmony_ciOpBranch %18
199fd4e5da5Sopenharmony_ci%18 = OpLabel
200fd4e5da5Sopenharmony_ciOpReturn
201fd4e5da5Sopenharmony_ciOpFunctionEnd
202fd4e5da5Sopenharmony_ci)";
203fd4e5da5Sopenharmony_ci
204fd4e5da5Sopenharmony_ci  const std::string after =
205fd4e5da5Sopenharmony_ci      R"(%main = OpFunction %void None %7
206fd4e5da5Sopenharmony_ci%13 = OpLabel
207fd4e5da5Sopenharmony_ci%v = OpVariable %_ptr_Function_v4float Function
208fd4e5da5Sopenharmony_ci%14 = OpLoad %v4float %BaseColor
209fd4e5da5Sopenharmony_ciOpStore %v %14
210fd4e5da5Sopenharmony_ci%16 = OpLoad %v4float %v
211fd4e5da5Sopenharmony_ciOpStore %gl_FragColor %16
212fd4e5da5Sopenharmony_ciOpReturn
213fd4e5da5Sopenharmony_ciOpFunctionEnd
214fd4e5da5Sopenharmony_ci)";
215fd4e5da5Sopenharmony_ci
216fd4e5da5Sopenharmony_ci  SinglePassRunAndCheck<BlockMergePass>(predefs + before, predefs + after, true,
217fd4e5da5Sopenharmony_ci                                        true);
218fd4e5da5Sopenharmony_ci}
219fd4e5da5Sopenharmony_ci
220fd4e5da5Sopenharmony_ciTEST_F(BlockMergeTest, NestedInControlFlow) {
221fd4e5da5Sopenharmony_ci  // Note: SPIR-V hand edited to insert block boundary
222fd4e5da5Sopenharmony_ci  // between OpFMul and OpStore in then-part.
223fd4e5da5Sopenharmony_ci  //
224fd4e5da5Sopenharmony_ci  // #version 140
225fd4e5da5Sopenharmony_ci  // in vec4 BaseColor;
226fd4e5da5Sopenharmony_ci  //
227fd4e5da5Sopenharmony_ci  // layout(std140) uniform U_t
228fd4e5da5Sopenharmony_ci  // {
229fd4e5da5Sopenharmony_ci  //     bool g_B ;
230fd4e5da5Sopenharmony_ci  // } ;
231fd4e5da5Sopenharmony_ci  //
232fd4e5da5Sopenharmony_ci  // void main()
233fd4e5da5Sopenharmony_ci  // {
234fd4e5da5Sopenharmony_ci  //     vec4 v = BaseColor;
235fd4e5da5Sopenharmony_ci  //     if (g_B)
236fd4e5da5Sopenharmony_ci  //       vec4 v = v * 0.25;
237fd4e5da5Sopenharmony_ci  //     gl_FragColor = v;
238fd4e5da5Sopenharmony_ci  // }
239fd4e5da5Sopenharmony_ci
240fd4e5da5Sopenharmony_ci  const std::string predefs =
241fd4e5da5Sopenharmony_ci      R"(OpCapability Shader
242fd4e5da5Sopenharmony_ci%1 = OpExtInstImport "GLSL.std.450"
243fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
244fd4e5da5Sopenharmony_ciOpEntryPoint Fragment %main "main" %BaseColor %gl_FragColor
245fd4e5da5Sopenharmony_ciOpExecutionMode %main OriginUpperLeft
246fd4e5da5Sopenharmony_ciOpSource GLSL 140
247fd4e5da5Sopenharmony_ciOpName %main "main"
248fd4e5da5Sopenharmony_ciOpName %v "v"
249fd4e5da5Sopenharmony_ciOpName %BaseColor "BaseColor"
250fd4e5da5Sopenharmony_ciOpName %U_t "U_t"
251fd4e5da5Sopenharmony_ciOpMemberName %U_t 0 "g_B"
252fd4e5da5Sopenharmony_ciOpName %_ ""
253fd4e5da5Sopenharmony_ciOpName %v_0 "v"
254fd4e5da5Sopenharmony_ciOpName %gl_FragColor "gl_FragColor"
255fd4e5da5Sopenharmony_ciOpMemberDecorate %U_t 0 Offset 0
256fd4e5da5Sopenharmony_ciOpDecorate %U_t Block
257fd4e5da5Sopenharmony_ciOpDecorate %_ DescriptorSet 0
258fd4e5da5Sopenharmony_ci%void = OpTypeVoid
259fd4e5da5Sopenharmony_ci%10 = OpTypeFunction %void
260fd4e5da5Sopenharmony_ci%float = OpTypeFloat 32
261fd4e5da5Sopenharmony_ci%v4float = OpTypeVector %float 4
262fd4e5da5Sopenharmony_ci%_ptr_Function_v4float = OpTypePointer Function %v4float
263fd4e5da5Sopenharmony_ci%_ptr_Input_v4float = OpTypePointer Input %v4float
264fd4e5da5Sopenharmony_ci%BaseColor = OpVariable %_ptr_Input_v4float Input
265fd4e5da5Sopenharmony_ci%uint = OpTypeInt 32 0
266fd4e5da5Sopenharmony_ci%U_t = OpTypeStruct %uint
267fd4e5da5Sopenharmony_ci%_ptr_Uniform_U_t = OpTypePointer Uniform %U_t
268fd4e5da5Sopenharmony_ci%_ = OpVariable %_ptr_Uniform_U_t Uniform
269fd4e5da5Sopenharmony_ci%int = OpTypeInt 32 1
270fd4e5da5Sopenharmony_ci%int_0 = OpConstant %int 0
271fd4e5da5Sopenharmony_ci%_ptr_Uniform_uint = OpTypePointer Uniform %uint
272fd4e5da5Sopenharmony_ci%bool = OpTypeBool
273fd4e5da5Sopenharmony_ci%uint_0 = OpConstant %uint 0
274fd4e5da5Sopenharmony_ci%float_0_25 = OpConstant %float 0.25
275fd4e5da5Sopenharmony_ci%_ptr_Output_v4float = OpTypePointer Output %v4float
276fd4e5da5Sopenharmony_ci%gl_FragColor = OpVariable %_ptr_Output_v4float Output
277fd4e5da5Sopenharmony_ci)";
278fd4e5da5Sopenharmony_ci
279fd4e5da5Sopenharmony_ci  const std::string before =
280fd4e5da5Sopenharmony_ci      R"(%main = OpFunction %void None %10
281fd4e5da5Sopenharmony_ci%24 = OpLabel
282fd4e5da5Sopenharmony_ci%v = OpVariable %_ptr_Function_v4float Function
283fd4e5da5Sopenharmony_ci%v_0 = OpVariable %_ptr_Function_v4float Function
284fd4e5da5Sopenharmony_ci%25 = OpLoad %v4float %BaseColor
285fd4e5da5Sopenharmony_ciOpStore %v %25
286fd4e5da5Sopenharmony_ci%26 = OpAccessChain %_ptr_Uniform_uint %_ %int_0
287fd4e5da5Sopenharmony_ci%27 = OpLoad %uint %26
288fd4e5da5Sopenharmony_ci%28 = OpINotEqual %bool %27 %uint_0
289fd4e5da5Sopenharmony_ciOpSelectionMerge %29 None
290fd4e5da5Sopenharmony_ciOpBranchConditional %28 %30 %29
291fd4e5da5Sopenharmony_ci%30 = OpLabel
292fd4e5da5Sopenharmony_ci%31 = OpLoad %v4float %v
293fd4e5da5Sopenharmony_ci%32 = OpVectorTimesScalar %v4float %31 %float_0_25
294fd4e5da5Sopenharmony_ciOpBranch %33
295fd4e5da5Sopenharmony_ci%33 = OpLabel
296fd4e5da5Sopenharmony_ciOpStore %v_0 %32
297fd4e5da5Sopenharmony_ciOpBranch %29
298fd4e5da5Sopenharmony_ci%29 = OpLabel
299fd4e5da5Sopenharmony_ci%34 = OpLoad %v4float %v
300fd4e5da5Sopenharmony_ciOpStore %gl_FragColor %34
301fd4e5da5Sopenharmony_ciOpReturn
302fd4e5da5Sopenharmony_ciOpFunctionEnd
303fd4e5da5Sopenharmony_ci)";
304fd4e5da5Sopenharmony_ci
305fd4e5da5Sopenharmony_ci  const std::string after =
306fd4e5da5Sopenharmony_ci      R"(%main = OpFunction %void None %10
307fd4e5da5Sopenharmony_ci%24 = OpLabel
308fd4e5da5Sopenharmony_ci%v = OpVariable %_ptr_Function_v4float Function
309fd4e5da5Sopenharmony_ci%v_0 = OpVariable %_ptr_Function_v4float Function
310fd4e5da5Sopenharmony_ci%25 = OpLoad %v4float %BaseColor
311fd4e5da5Sopenharmony_ciOpStore %v %25
312fd4e5da5Sopenharmony_ci%26 = OpAccessChain %_ptr_Uniform_uint %_ %int_0
313fd4e5da5Sopenharmony_ci%27 = OpLoad %uint %26
314fd4e5da5Sopenharmony_ci%28 = OpINotEqual %bool %27 %uint_0
315fd4e5da5Sopenharmony_ciOpSelectionMerge %29 None
316fd4e5da5Sopenharmony_ciOpBranchConditional %28 %30 %29
317fd4e5da5Sopenharmony_ci%30 = OpLabel
318fd4e5da5Sopenharmony_ci%31 = OpLoad %v4float %v
319fd4e5da5Sopenharmony_ci%32 = OpVectorTimesScalar %v4float %31 %float_0_25
320fd4e5da5Sopenharmony_ciOpStore %v_0 %32
321fd4e5da5Sopenharmony_ciOpBranch %29
322fd4e5da5Sopenharmony_ci%29 = OpLabel
323fd4e5da5Sopenharmony_ci%34 = OpLoad %v4float %v
324fd4e5da5Sopenharmony_ciOpStore %gl_FragColor %34
325fd4e5da5Sopenharmony_ciOpReturn
326fd4e5da5Sopenharmony_ciOpFunctionEnd
327fd4e5da5Sopenharmony_ci)";
328fd4e5da5Sopenharmony_ci
329fd4e5da5Sopenharmony_ci  SinglePassRunAndCheck<BlockMergePass>(predefs + before, predefs + after, true,
330fd4e5da5Sopenharmony_ci                                        true);
331fd4e5da5Sopenharmony_ci}
332fd4e5da5Sopenharmony_ci
333fd4e5da5Sopenharmony_ciTEST_F(BlockMergeTest, PhiInSuccessorOfMergedBlock) {
334fd4e5da5Sopenharmony_ci  const std::string text = R"(
335fd4e5da5Sopenharmony_ci; CHECK: OpSelectionMerge [[merge:%\w+]] None
336fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpBranchConditional {{%\w+}} [[then:%\w+]] [[else:%\w+]]
337fd4e5da5Sopenharmony_ci; CHECK: [[then]] = OpLabel
338fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpBranch [[merge]]
339fd4e5da5Sopenharmony_ci; CHECK: [[else]] = OpLabel
340fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpBranch [[merge]]
341fd4e5da5Sopenharmony_ci; CHECK: [[merge]] = OpLabel
342fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpPhi {{%\w+}} %true [[then]] %false [[else]]
343fd4e5da5Sopenharmony_ciOpCapability Shader
344fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
345fd4e5da5Sopenharmony_ciOpEntryPoint Fragment %func "func"
346fd4e5da5Sopenharmony_ciOpExecutionMode %func OriginUpperLeft
347fd4e5da5Sopenharmony_ci%void = OpTypeVoid
348fd4e5da5Sopenharmony_ci%bool = OpTypeBool
349fd4e5da5Sopenharmony_ci%true = OpConstantTrue %bool
350fd4e5da5Sopenharmony_ci%false = OpConstantFalse  %bool
351fd4e5da5Sopenharmony_ci%functy = OpTypeFunction %void
352fd4e5da5Sopenharmony_ci%func = OpFunction %void None %functy
353fd4e5da5Sopenharmony_ci%entry = OpLabel
354fd4e5da5Sopenharmony_ciOpSelectionMerge %merge None
355fd4e5da5Sopenharmony_ciOpBranchConditional %true %then %else
356fd4e5da5Sopenharmony_ci%then = OpLabel
357fd4e5da5Sopenharmony_ciOpBranch %then_next
358fd4e5da5Sopenharmony_ci%then_next = OpLabel
359fd4e5da5Sopenharmony_ciOpBranch %merge
360fd4e5da5Sopenharmony_ci%else = OpLabel
361fd4e5da5Sopenharmony_ciOpBranch %merge
362fd4e5da5Sopenharmony_ci%merge = OpLabel
363fd4e5da5Sopenharmony_ci%phi = OpPhi %bool %true %then_next %false %else
364fd4e5da5Sopenharmony_ciOpReturn
365fd4e5da5Sopenharmony_ciOpFunctionEnd
366fd4e5da5Sopenharmony_ci)";
367fd4e5da5Sopenharmony_ci
368fd4e5da5Sopenharmony_ci  SinglePassRunAndMatch<BlockMergePass>(text, true);
369fd4e5da5Sopenharmony_ci}
370fd4e5da5Sopenharmony_ci
371fd4e5da5Sopenharmony_ciTEST_F(BlockMergeTest, UpdateMergeInstruction) {
372fd4e5da5Sopenharmony_ci  const std::string text = R"(
373fd4e5da5Sopenharmony_ci; CHECK: OpSelectionMerge [[merge:%\w+]] None
374fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpBranchConditional {{%\w+}} [[then:%\w+]] [[else:%\w+]]
375fd4e5da5Sopenharmony_ci; CHECK: [[then]] = OpLabel
376fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpBranch [[merge]]
377fd4e5da5Sopenharmony_ci; CHECK: [[else]] = OpLabel
378fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpBranch [[merge]]
379fd4e5da5Sopenharmony_ci; CHECK: [[merge]] = OpLabel
380fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpReturn
381fd4e5da5Sopenharmony_ciOpCapability Shader
382fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
383fd4e5da5Sopenharmony_ciOpEntryPoint Fragment %func "func"
384fd4e5da5Sopenharmony_ciOpExecutionMode %func OriginUpperLeft
385fd4e5da5Sopenharmony_ci%void = OpTypeVoid
386fd4e5da5Sopenharmony_ci%bool = OpTypeBool
387fd4e5da5Sopenharmony_ci%true = OpConstantTrue %bool
388fd4e5da5Sopenharmony_ci%false = OpConstantFalse  %bool
389fd4e5da5Sopenharmony_ci%functy = OpTypeFunction %void
390fd4e5da5Sopenharmony_ci%func = OpFunction %void None %functy
391fd4e5da5Sopenharmony_ci%entry = OpLabel
392fd4e5da5Sopenharmony_ciOpSelectionMerge %real_merge None
393fd4e5da5Sopenharmony_ciOpBranchConditional %true %then %else
394fd4e5da5Sopenharmony_ci%then = OpLabel
395fd4e5da5Sopenharmony_ciOpBranch %merge
396fd4e5da5Sopenharmony_ci%else = OpLabel
397fd4e5da5Sopenharmony_ciOpBranch %merge
398fd4e5da5Sopenharmony_ci%merge = OpLabel
399fd4e5da5Sopenharmony_ciOpBranch %real_merge
400fd4e5da5Sopenharmony_ci%real_merge = OpLabel
401fd4e5da5Sopenharmony_ciOpReturn
402fd4e5da5Sopenharmony_ciOpFunctionEnd
403fd4e5da5Sopenharmony_ci)";
404fd4e5da5Sopenharmony_ci
405fd4e5da5Sopenharmony_ci  SinglePassRunAndMatch<BlockMergePass>(text, true);
406fd4e5da5Sopenharmony_ci}
407fd4e5da5Sopenharmony_ci
408fd4e5da5Sopenharmony_ciTEST_F(BlockMergeTest, TwoMergeBlocksCannotBeMerged) {
409fd4e5da5Sopenharmony_ci  const std::string text = R"(
410fd4e5da5Sopenharmony_ci; CHECK: OpSelectionMerge [[outer_merge:%\w+]] None
411fd4e5da5Sopenharmony_ci; CHECK: OpSelectionMerge [[inner_merge:%\w+]] None
412fd4e5da5Sopenharmony_ci; CHECK: [[inner_merge]] = OpLabel
413fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpBranch [[outer_merge]]
414fd4e5da5Sopenharmony_ci; CHECK: [[outer_merge]] = OpLabel
415fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpReturn
416fd4e5da5Sopenharmony_ciOpCapability Shader
417fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
418fd4e5da5Sopenharmony_ciOpEntryPoint Fragment %func "func"
419fd4e5da5Sopenharmony_ciOpExecutionMode %func OriginUpperLeft
420fd4e5da5Sopenharmony_ci%void = OpTypeVoid
421fd4e5da5Sopenharmony_ci%bool = OpTypeBool
422fd4e5da5Sopenharmony_ci%true = OpConstantTrue %bool
423fd4e5da5Sopenharmony_ci%false = OpConstantFalse  %bool
424fd4e5da5Sopenharmony_ci%functy = OpTypeFunction %void
425fd4e5da5Sopenharmony_ci%func = OpFunction %void None %functy
426fd4e5da5Sopenharmony_ci%entry = OpLabel
427fd4e5da5Sopenharmony_ciOpSelectionMerge %outer_merge None
428fd4e5da5Sopenharmony_ciOpBranchConditional %true %then %else
429fd4e5da5Sopenharmony_ci%then = OpLabel
430fd4e5da5Sopenharmony_ciOpBranch %inner_header
431fd4e5da5Sopenharmony_ci%else = OpLabel
432fd4e5da5Sopenharmony_ciOpBranch %inner_header
433fd4e5da5Sopenharmony_ci%inner_header = OpLabel
434fd4e5da5Sopenharmony_ciOpSelectionMerge %inner_merge None
435fd4e5da5Sopenharmony_ciOpBranchConditional %true %inner_then %inner_else
436fd4e5da5Sopenharmony_ci%inner_then = OpLabel
437fd4e5da5Sopenharmony_ciOpBranch %inner_merge
438fd4e5da5Sopenharmony_ci%inner_else = OpLabel
439fd4e5da5Sopenharmony_ciOpBranch %inner_merge
440fd4e5da5Sopenharmony_ci%inner_merge = OpLabel
441fd4e5da5Sopenharmony_ciOpBranch %outer_merge
442fd4e5da5Sopenharmony_ci%outer_merge = OpLabel
443fd4e5da5Sopenharmony_ciOpReturn
444fd4e5da5Sopenharmony_ciOpFunctionEnd
445fd4e5da5Sopenharmony_ci)";
446fd4e5da5Sopenharmony_ci
447fd4e5da5Sopenharmony_ci  SinglePassRunAndMatch<BlockMergePass>(text, true);
448fd4e5da5Sopenharmony_ci}
449fd4e5da5Sopenharmony_ci
450fd4e5da5Sopenharmony_ciTEST_F(BlockMergeTest, MergeContinue) {
451fd4e5da5Sopenharmony_ci  const std::string text = R"(
452fd4e5da5Sopenharmony_ci; CHECK: OpBranch [[header:%\w+]]
453fd4e5da5Sopenharmony_ci; CHECK: [[header]] = OpLabel
454fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpLogicalAnd
455fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpLoopMerge {{%\w+}} [[header]] None
456fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpBranch [[header]]
457fd4e5da5Sopenharmony_ciOpCapability Shader
458fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
459fd4e5da5Sopenharmony_ciOpEntryPoint Fragment %func "func"
460fd4e5da5Sopenharmony_ciOpExecutionMode %func OriginUpperLeft
461fd4e5da5Sopenharmony_ci%void = OpTypeVoid
462fd4e5da5Sopenharmony_ci%bool = OpTypeBool
463fd4e5da5Sopenharmony_ci%true = OpConstantTrue %bool
464fd4e5da5Sopenharmony_ci%false = OpConstantFalse  %bool
465fd4e5da5Sopenharmony_ci%functy = OpTypeFunction %void
466fd4e5da5Sopenharmony_ci%func = OpFunction %void None %functy
467fd4e5da5Sopenharmony_ci%entry = OpLabel
468fd4e5da5Sopenharmony_ciOpBranch %header
469fd4e5da5Sopenharmony_ci%header = OpLabel
470fd4e5da5Sopenharmony_ciOpLoopMerge %merge %continue None
471fd4e5da5Sopenharmony_ciOpBranch %continue
472fd4e5da5Sopenharmony_ci%continue = OpLabel
473fd4e5da5Sopenharmony_ci%op = OpLogicalAnd %bool %true %false
474fd4e5da5Sopenharmony_ciOpBranch %header
475fd4e5da5Sopenharmony_ci%merge = OpLabel
476fd4e5da5Sopenharmony_ciOpUnreachable
477fd4e5da5Sopenharmony_ciOpFunctionEnd
478fd4e5da5Sopenharmony_ci)";
479fd4e5da5Sopenharmony_ci
480fd4e5da5Sopenharmony_ci  SinglePassRunAndMatch<BlockMergePass>(text, true);
481fd4e5da5Sopenharmony_ci}
482fd4e5da5Sopenharmony_ci
483fd4e5da5Sopenharmony_ciTEST_F(BlockMergeTest, MergeContinueWithOpLine) {
484fd4e5da5Sopenharmony_ci  const std::string text = R"(
485fd4e5da5Sopenharmony_ci; CHECK: OpBranch [[header:%\w+]]
486fd4e5da5Sopenharmony_ci; CHECK: [[header]] = OpLabel
487fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpLogicalAnd
488fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpLine {{%\w+}} 1 1
489fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpLoopMerge {{%\w+}} [[header]] None
490fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpBranch [[header]]
491fd4e5da5Sopenharmony_ciOpCapability Shader
492fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
493fd4e5da5Sopenharmony_ciOpEntryPoint Fragment %func "func"
494fd4e5da5Sopenharmony_ciOpExecutionMode %func OriginUpperLeft
495fd4e5da5Sopenharmony_ci%src = OpString "test.shader"
496fd4e5da5Sopenharmony_ci%void = OpTypeVoid
497fd4e5da5Sopenharmony_ci%bool = OpTypeBool
498fd4e5da5Sopenharmony_ci%true = OpConstantTrue %bool
499fd4e5da5Sopenharmony_ci%false = OpConstantFalse  %bool
500fd4e5da5Sopenharmony_ci%functy = OpTypeFunction %void
501fd4e5da5Sopenharmony_ci%func = OpFunction %void None %functy
502fd4e5da5Sopenharmony_ci%entry = OpLabel
503fd4e5da5Sopenharmony_ciOpBranch %header
504fd4e5da5Sopenharmony_ci%header = OpLabel
505fd4e5da5Sopenharmony_ciOpLoopMerge %merge %continue None
506fd4e5da5Sopenharmony_ciOpBranch %continue
507fd4e5da5Sopenharmony_ci%continue = OpLabel
508fd4e5da5Sopenharmony_ci%op = OpLogicalAnd %bool %true %false
509fd4e5da5Sopenharmony_ciOpLine %src 1 1
510fd4e5da5Sopenharmony_ciOpBranch %header
511fd4e5da5Sopenharmony_ci%merge = OpLabel
512fd4e5da5Sopenharmony_ciOpUnreachable
513fd4e5da5Sopenharmony_ciOpFunctionEnd
514fd4e5da5Sopenharmony_ci)";
515fd4e5da5Sopenharmony_ci
516fd4e5da5Sopenharmony_ci  SinglePassRunAndMatch<BlockMergePass>(text, true);
517fd4e5da5Sopenharmony_ci}
518fd4e5da5Sopenharmony_ci
519fd4e5da5Sopenharmony_ciTEST_F(BlockMergeTest, TwoHeadersCannotBeMerged) {
520fd4e5da5Sopenharmony_ci  const std::string text = R"(
521fd4e5da5Sopenharmony_ci; CHECK: OpBranch [[loop_header:%\w+]]
522fd4e5da5Sopenharmony_ci; CHECK: [[loop_header]] = OpLabel
523fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpLoopMerge
524fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpBranch [[if_header:%\w+]]
525fd4e5da5Sopenharmony_ci; CHECK: [[if_header]] = OpLabel
526fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpSelectionMerge
527fd4e5da5Sopenharmony_ciOpCapability Shader
528fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
529fd4e5da5Sopenharmony_ciOpEntryPoint Fragment %func "func"
530fd4e5da5Sopenharmony_ciOpExecutionMode %func OriginUpperLeft
531fd4e5da5Sopenharmony_ci%void = OpTypeVoid
532fd4e5da5Sopenharmony_ci%bool = OpTypeBool
533fd4e5da5Sopenharmony_ci%true = OpConstantTrue %bool
534fd4e5da5Sopenharmony_ci%false = OpConstantFalse  %bool
535fd4e5da5Sopenharmony_ci%functy = OpTypeFunction %void
536fd4e5da5Sopenharmony_ci%func = OpFunction %void None %functy
537fd4e5da5Sopenharmony_ci%entry = OpLabel
538fd4e5da5Sopenharmony_ciOpBranch %header
539fd4e5da5Sopenharmony_ci%header = OpLabel
540fd4e5da5Sopenharmony_ciOpLoopMerge %merge %continue None
541fd4e5da5Sopenharmony_ciOpBranch %inner_header
542fd4e5da5Sopenharmony_ci%inner_header = OpLabel
543fd4e5da5Sopenharmony_ciOpSelectionMerge %if_merge None
544fd4e5da5Sopenharmony_ciOpBranchConditional %true %then %if_merge
545fd4e5da5Sopenharmony_ci%then = OpLabel
546fd4e5da5Sopenharmony_ciOpBranch %continue
547fd4e5da5Sopenharmony_ci%if_merge = OpLabel
548fd4e5da5Sopenharmony_ciOpBranch %continue
549fd4e5da5Sopenharmony_ci%continue = OpLabel
550fd4e5da5Sopenharmony_ciOpBranchConditional %false %merge %header
551fd4e5da5Sopenharmony_ci%merge = OpLabel
552fd4e5da5Sopenharmony_ciOpReturn
553fd4e5da5Sopenharmony_ciOpFunctionEnd
554fd4e5da5Sopenharmony_ci)";
555fd4e5da5Sopenharmony_ci
556fd4e5da5Sopenharmony_ci  SinglePassRunAndMatch<BlockMergePass>(text, true);
557fd4e5da5Sopenharmony_ci}
558fd4e5da5Sopenharmony_ci
559fd4e5da5Sopenharmony_ciTEST_F(BlockMergeTest, CannotMergeContinue) {
560fd4e5da5Sopenharmony_ci  const std::string text = R"(
561fd4e5da5Sopenharmony_ci; CHECK: OpBranch [[loop_header:%\w+]]
562fd4e5da5Sopenharmony_ci; CHECK: [[loop_header]] = OpLabel
563fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpLoopMerge {{%\w+}} [[continue:%\w+]]
564fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpBranchConditional {{%\w+}} [[if_header:%\w+]]
565fd4e5da5Sopenharmony_ci; CHECK: [[if_header]] = OpLabel
566fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpSelectionMerge
567fd4e5da5Sopenharmony_ci; CHECK: [[continue]] = OpLabel
568fd4e5da5Sopenharmony_ciOpCapability Shader
569fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
570fd4e5da5Sopenharmony_ciOpEntryPoint Fragment %func "func"
571fd4e5da5Sopenharmony_ciOpExecutionMode %func OriginUpperLeft
572fd4e5da5Sopenharmony_ci%void = OpTypeVoid
573fd4e5da5Sopenharmony_ci%bool = OpTypeBool
574fd4e5da5Sopenharmony_ci%true = OpConstantTrue %bool
575fd4e5da5Sopenharmony_ci%false = OpConstantFalse  %bool
576fd4e5da5Sopenharmony_ci%functy = OpTypeFunction %void
577fd4e5da5Sopenharmony_ci%func = OpFunction %void None %functy
578fd4e5da5Sopenharmony_ci%entry = OpLabel
579fd4e5da5Sopenharmony_ciOpBranch %header
580fd4e5da5Sopenharmony_ci%header = OpLabel
581fd4e5da5Sopenharmony_ciOpLoopMerge %merge %continue None
582fd4e5da5Sopenharmony_ciOpBranchConditional %true %inner_header %merge
583fd4e5da5Sopenharmony_ci%inner_header = OpLabel
584fd4e5da5Sopenharmony_ciOpSelectionMerge %if_merge None
585fd4e5da5Sopenharmony_ciOpBranchConditional %true %then %if_merge
586fd4e5da5Sopenharmony_ci%then = OpLabel
587fd4e5da5Sopenharmony_ciOpBranch %continue
588fd4e5da5Sopenharmony_ci%if_merge = OpLabel
589fd4e5da5Sopenharmony_ciOpBranch %continue
590fd4e5da5Sopenharmony_ci%continue = OpLabel
591fd4e5da5Sopenharmony_ciOpBranchConditional %false %merge %header
592fd4e5da5Sopenharmony_ci%merge = OpLabel
593fd4e5da5Sopenharmony_ciOpReturn
594fd4e5da5Sopenharmony_ciOpFunctionEnd
595fd4e5da5Sopenharmony_ci)";
596fd4e5da5Sopenharmony_ci
597fd4e5da5Sopenharmony_ci  SinglePassRunAndMatch<BlockMergePass>(text, true);
598fd4e5da5Sopenharmony_ci}
599fd4e5da5Sopenharmony_ci
600fd4e5da5Sopenharmony_ciTEST_F(BlockMergeTest, RemoveStructuredDeclaration) {
601fd4e5da5Sopenharmony_ci  // Note: SPIR-V hand edited remove dead branch and add block
602fd4e5da5Sopenharmony_ci  // before continue block
603fd4e5da5Sopenharmony_ci  //
604fd4e5da5Sopenharmony_ci  // #version 140
605fd4e5da5Sopenharmony_ci  // in vec4 BaseColor;
606fd4e5da5Sopenharmony_ci  //
607fd4e5da5Sopenharmony_ci  // void main()
608fd4e5da5Sopenharmony_ci  // {
609fd4e5da5Sopenharmony_ci  //     while (true) {
610fd4e5da5Sopenharmony_ci  //         break;
611fd4e5da5Sopenharmony_ci  //     }
612fd4e5da5Sopenharmony_ci  //     gl_FragColor = BaseColor;
613fd4e5da5Sopenharmony_ci  // }
614fd4e5da5Sopenharmony_ci
615fd4e5da5Sopenharmony_ci  const std::string assembly =
616fd4e5da5Sopenharmony_ci      R"(
617fd4e5da5Sopenharmony_ci; CHECK: OpLabel
618fd4e5da5Sopenharmony_ci; CHECK: [[header:%\w+]] = OpLabel
619fd4e5da5Sopenharmony_ci; CHECK-NOT: OpLoopMerge
620fd4e5da5Sopenharmony_ci; CHECK: OpReturn
621fd4e5da5Sopenharmony_ci; CHECK: [[continue:%\w+]] = OpLabel
622fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpBranch [[block:%\w+]]
623fd4e5da5Sopenharmony_ci; CHECK: [[block]] = OpLabel
624fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpBranch [[header]]
625fd4e5da5Sopenharmony_ciOpCapability Shader
626fd4e5da5Sopenharmony_ci%1 = OpExtInstImport "GLSL.std.450"
627fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
628fd4e5da5Sopenharmony_ciOpEntryPoint Fragment %main "main" %gl_FragColor %BaseColor
629fd4e5da5Sopenharmony_ciOpExecutionMode %main OriginUpperLeft
630fd4e5da5Sopenharmony_ciOpSource GLSL 140
631fd4e5da5Sopenharmony_ciOpName %main "main"
632fd4e5da5Sopenharmony_ciOpName %gl_FragColor "gl_FragColor"
633fd4e5da5Sopenharmony_ciOpName %BaseColor "BaseColor"
634fd4e5da5Sopenharmony_ci%void = OpTypeVoid
635fd4e5da5Sopenharmony_ci%6 = OpTypeFunction %void
636fd4e5da5Sopenharmony_ci%bool = OpTypeBool
637fd4e5da5Sopenharmony_ci%true = OpConstantTrue %bool
638fd4e5da5Sopenharmony_ci%float = OpTypeFloat 32
639fd4e5da5Sopenharmony_ci%v4float = OpTypeVector %float 4
640fd4e5da5Sopenharmony_ci%_ptr_Output_v4float = OpTypePointer Output %v4float
641fd4e5da5Sopenharmony_ci%gl_FragColor = OpVariable %_ptr_Output_v4float Output
642fd4e5da5Sopenharmony_ci%_ptr_Input_v4float = OpTypePointer Input %v4float
643fd4e5da5Sopenharmony_ci%BaseColor = OpVariable %_ptr_Input_v4float Input
644fd4e5da5Sopenharmony_ci%main = OpFunction %void None %6
645fd4e5da5Sopenharmony_ci%13 = OpLabel
646fd4e5da5Sopenharmony_ciOpBranch %14
647fd4e5da5Sopenharmony_ci%14 = OpLabel
648fd4e5da5Sopenharmony_ciOpLoopMerge %15 %16 None
649fd4e5da5Sopenharmony_ciOpBranch %17
650fd4e5da5Sopenharmony_ci%17 = OpLabel
651fd4e5da5Sopenharmony_ciOpBranch %15
652fd4e5da5Sopenharmony_ci%18 = OpLabel
653fd4e5da5Sopenharmony_ciOpBranch %16
654fd4e5da5Sopenharmony_ci%16 = OpLabel
655fd4e5da5Sopenharmony_ciOpBranch %14
656fd4e5da5Sopenharmony_ci%15 = OpLabel
657fd4e5da5Sopenharmony_ci%19 = OpLoad %v4float %BaseColor
658fd4e5da5Sopenharmony_ciOpStore %gl_FragColor %19
659fd4e5da5Sopenharmony_ciOpReturn
660fd4e5da5Sopenharmony_ciOpFunctionEnd
661fd4e5da5Sopenharmony_ci)";
662fd4e5da5Sopenharmony_ci
663fd4e5da5Sopenharmony_ci  SinglePassRunAndMatch<BlockMergePass>(assembly, true);
664fd4e5da5Sopenharmony_ci}
665fd4e5da5Sopenharmony_ci
666fd4e5da5Sopenharmony_ciTEST_F(BlockMergeTest, DontMergeKill) {
667fd4e5da5Sopenharmony_ci  const std::string text = R"(
668fd4e5da5Sopenharmony_ci; CHECK: OpLoopMerge [[merge:%\w+]] [[cont:%\w+]] None
669fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpBranch [[ret:%\w+]]
670fd4e5da5Sopenharmony_ci; CHECK: [[ret:%\w+]] = OpLabel
671fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpKill
672fd4e5da5Sopenharmony_ci; CHECK-DAG: [[cont]] = OpLabel
673fd4e5da5Sopenharmony_ci; CHECK-DAG: [[merge]] = OpLabel
674fd4e5da5Sopenharmony_ciOpCapability Shader
675fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
676fd4e5da5Sopenharmony_ciOpEntryPoint Fragment %func "func"
677fd4e5da5Sopenharmony_ciOpExecutionMode %func OriginUpperLeft
678fd4e5da5Sopenharmony_ci%void = OpTypeVoid
679fd4e5da5Sopenharmony_ci%bool = OpTypeBool
680fd4e5da5Sopenharmony_ci%functy = OpTypeFunction %void
681fd4e5da5Sopenharmony_ci%func = OpFunction %void None %functy
682fd4e5da5Sopenharmony_ci%1 = OpLabel
683fd4e5da5Sopenharmony_ciOpBranch %2
684fd4e5da5Sopenharmony_ci%2 = OpLabel
685fd4e5da5Sopenharmony_ciOpLoopMerge %3 %4 None
686fd4e5da5Sopenharmony_ciOpBranch %5
687fd4e5da5Sopenharmony_ci%5 = OpLabel
688fd4e5da5Sopenharmony_ciOpKill
689fd4e5da5Sopenharmony_ci%4 = OpLabel
690fd4e5da5Sopenharmony_ciOpBranch %2
691fd4e5da5Sopenharmony_ci%3 = OpLabel
692fd4e5da5Sopenharmony_ciOpUnreachable
693fd4e5da5Sopenharmony_ciOpFunctionEnd
694fd4e5da5Sopenharmony_ci)";
695fd4e5da5Sopenharmony_ci
696fd4e5da5Sopenharmony_ci  SinglePassRunAndMatch<BlockMergePass>(text, true);
697fd4e5da5Sopenharmony_ci}
698fd4e5da5Sopenharmony_ci
699fd4e5da5Sopenharmony_ciTEST_F(BlockMergeTest, DontMergeTerminateInvocation) {
700fd4e5da5Sopenharmony_ci  const std::string text = R"(
701fd4e5da5Sopenharmony_ci; CHECK: OpLoopMerge [[merge:%\w+]] [[cont:%\w+]] None
702fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpBranch [[ret:%\w+]]
703fd4e5da5Sopenharmony_ci; CHECK: [[ret:%\w+]] = OpLabel
704fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpTerminateInvocation
705fd4e5da5Sopenharmony_ci; CHECK-DAG: [[cont]] = OpLabel
706fd4e5da5Sopenharmony_ci; CHECK-DAG: [[merge]] = OpLabel
707fd4e5da5Sopenharmony_ciOpCapability Shader
708fd4e5da5Sopenharmony_ciOpExtension "SPV_KHR_terminate_invocation"
709fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
710fd4e5da5Sopenharmony_ciOpEntryPoint Fragment %func "func"
711fd4e5da5Sopenharmony_ciOpExecutionMode %func OriginUpperLeft
712fd4e5da5Sopenharmony_ci%void = OpTypeVoid
713fd4e5da5Sopenharmony_ci%bool = OpTypeBool
714fd4e5da5Sopenharmony_ci%functy = OpTypeFunction %void
715fd4e5da5Sopenharmony_ci%func = OpFunction %void None %functy
716fd4e5da5Sopenharmony_ci%1 = OpLabel
717fd4e5da5Sopenharmony_ciOpBranch %2
718fd4e5da5Sopenharmony_ci%2 = OpLabel
719fd4e5da5Sopenharmony_ciOpLoopMerge %3 %4 None
720fd4e5da5Sopenharmony_ciOpBranch %5
721fd4e5da5Sopenharmony_ci%5 = OpLabel
722fd4e5da5Sopenharmony_ciOpTerminateInvocation
723fd4e5da5Sopenharmony_ci%4 = OpLabel
724fd4e5da5Sopenharmony_ciOpBranch %2
725fd4e5da5Sopenharmony_ci%3 = OpLabel
726fd4e5da5Sopenharmony_ciOpUnreachable
727fd4e5da5Sopenharmony_ciOpFunctionEnd
728fd4e5da5Sopenharmony_ci)";
729fd4e5da5Sopenharmony_ci
730fd4e5da5Sopenharmony_ci  SinglePassRunAndMatch<BlockMergePass>(text, true);
731fd4e5da5Sopenharmony_ci}
732fd4e5da5Sopenharmony_ci
733fd4e5da5Sopenharmony_ciTEST_F(BlockMergeTest, DontMergeUnreachable) {
734fd4e5da5Sopenharmony_ci  const std::string text = R"(
735fd4e5da5Sopenharmony_ci; CHECK: OpLoopMerge [[merge:%\w+]] [[cont:%\w+]] None
736fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpBranch [[ret:%\w+]]
737fd4e5da5Sopenharmony_ci; CHECK: [[ret:%\w+]] = OpLabel
738fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpUnreachable
739fd4e5da5Sopenharmony_ci; CHECK-DAG: [[cont]] = OpLabel
740fd4e5da5Sopenharmony_ci; CHECK-DAG: [[merge]] = OpLabel
741fd4e5da5Sopenharmony_ciOpCapability Shader
742fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
743fd4e5da5Sopenharmony_ciOpEntryPoint Fragment %func "func"
744fd4e5da5Sopenharmony_ciOpExecutionMode %func OriginUpperLeft
745fd4e5da5Sopenharmony_ci%void = OpTypeVoid
746fd4e5da5Sopenharmony_ci%bool = OpTypeBool
747fd4e5da5Sopenharmony_ci%functy = OpTypeFunction %void
748fd4e5da5Sopenharmony_ci%func = OpFunction %void None %functy
749fd4e5da5Sopenharmony_ci%1 = OpLabel
750fd4e5da5Sopenharmony_ciOpBranch %2
751fd4e5da5Sopenharmony_ci%2 = OpLabel
752fd4e5da5Sopenharmony_ciOpLoopMerge %3 %4 None
753fd4e5da5Sopenharmony_ciOpBranch %5
754fd4e5da5Sopenharmony_ci%5 = OpLabel
755fd4e5da5Sopenharmony_ciOpUnreachable
756fd4e5da5Sopenharmony_ci%4 = OpLabel
757fd4e5da5Sopenharmony_ciOpBranch %2
758fd4e5da5Sopenharmony_ci%3 = OpLabel
759fd4e5da5Sopenharmony_ciOpUnreachable
760fd4e5da5Sopenharmony_ciOpFunctionEnd
761fd4e5da5Sopenharmony_ci)";
762fd4e5da5Sopenharmony_ci
763fd4e5da5Sopenharmony_ci  SinglePassRunAndMatch<BlockMergePass>(text, false);
764fd4e5da5Sopenharmony_ci}
765fd4e5da5Sopenharmony_ci
766fd4e5da5Sopenharmony_ciTEST_F(BlockMergeTest, DontMergeReturn) {
767fd4e5da5Sopenharmony_ci  const std::string text = R"(
768fd4e5da5Sopenharmony_ci; CHECK: OpLoopMerge [[merge:%\w+]] [[cont:%\w+]] None
769fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpBranch [[ret:%\w+]]
770fd4e5da5Sopenharmony_ci; CHECK: [[ret:%\w+]] = OpLabel
771fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpReturn
772fd4e5da5Sopenharmony_ci; CHECK-DAG: [[cont]] = OpLabel
773fd4e5da5Sopenharmony_ci; CHECK-DAG: [[merge]] = OpLabel
774fd4e5da5Sopenharmony_ciOpCapability Shader
775fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
776fd4e5da5Sopenharmony_ciOpEntryPoint Fragment %func "func"
777fd4e5da5Sopenharmony_ciOpExecutionMode %func OriginUpperLeft
778fd4e5da5Sopenharmony_ci%void = OpTypeVoid
779fd4e5da5Sopenharmony_ci%bool = OpTypeBool
780fd4e5da5Sopenharmony_ci%functy = OpTypeFunction %void
781fd4e5da5Sopenharmony_ci%func = OpFunction %void None %functy
782fd4e5da5Sopenharmony_ci%1 = OpLabel
783fd4e5da5Sopenharmony_ciOpBranch %2
784fd4e5da5Sopenharmony_ci%2 = OpLabel
785fd4e5da5Sopenharmony_ciOpLoopMerge %3 %4 None
786fd4e5da5Sopenharmony_ciOpBranch %5
787fd4e5da5Sopenharmony_ci%5 = OpLabel
788fd4e5da5Sopenharmony_ciOpReturn
789fd4e5da5Sopenharmony_ci%4 = OpLabel
790fd4e5da5Sopenharmony_ciOpBranch %2
791fd4e5da5Sopenharmony_ci%3 = OpLabel
792fd4e5da5Sopenharmony_ciOpUnreachable
793fd4e5da5Sopenharmony_ciOpFunctionEnd
794fd4e5da5Sopenharmony_ci)";
795fd4e5da5Sopenharmony_ci
796fd4e5da5Sopenharmony_ci  SinglePassRunAndMatch<BlockMergePass>(text, true);
797fd4e5da5Sopenharmony_ci}
798fd4e5da5Sopenharmony_ci
799fd4e5da5Sopenharmony_ciTEST_F(BlockMergeTest, DontMergeSwitch) {
800fd4e5da5Sopenharmony_ci  const std::string text = R"(
801fd4e5da5Sopenharmony_ci; CHECK: OpLoopMerge [[merge:%\w+]] [[cont:%\w+]] None
802fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpBranch [[ret:%\w+]]
803fd4e5da5Sopenharmony_ci; CHECK: [[ret:%\w+]] = OpLabel
804fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpSelectionMerge
805fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpSwitch
806fd4e5da5Sopenharmony_ci; CHECK-DAG: [[cont]] = OpLabel
807fd4e5da5Sopenharmony_ci; CHECK-DAG: [[merge]] = OpLabel
808fd4e5da5Sopenharmony_ciOpCapability Shader
809fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
810fd4e5da5Sopenharmony_ciOpEntryPoint Fragment %func "func"
811fd4e5da5Sopenharmony_ciOpExecutionMode %func OriginUpperLeft
812fd4e5da5Sopenharmony_ci%void = OpTypeVoid
813fd4e5da5Sopenharmony_ci%bool = OpTypeBool
814fd4e5da5Sopenharmony_ci%int = OpTypeInt 32 1
815fd4e5da5Sopenharmony_ci%int_0 = OpConstant %int 0
816fd4e5da5Sopenharmony_ci%functy = OpTypeFunction %void
817fd4e5da5Sopenharmony_ci%func = OpFunction %void None %functy
818fd4e5da5Sopenharmony_ci%1 = OpLabel
819fd4e5da5Sopenharmony_ciOpBranch %2
820fd4e5da5Sopenharmony_ci%2 = OpLabel
821fd4e5da5Sopenharmony_ciOpLoopMerge %3 %4 None
822fd4e5da5Sopenharmony_ciOpBranch %5
823fd4e5da5Sopenharmony_ci%5 = OpLabel
824fd4e5da5Sopenharmony_ciOpSelectionMerge %6 None
825fd4e5da5Sopenharmony_ciOpSwitch %int_0 %6
826fd4e5da5Sopenharmony_ci%6 = OpLabel
827fd4e5da5Sopenharmony_ciOpReturn
828fd4e5da5Sopenharmony_ci%4 = OpLabel
829fd4e5da5Sopenharmony_ciOpBranch %2
830fd4e5da5Sopenharmony_ci%3 = OpLabel
831fd4e5da5Sopenharmony_ciOpUnreachable
832fd4e5da5Sopenharmony_ciOpFunctionEnd
833fd4e5da5Sopenharmony_ci)";
834fd4e5da5Sopenharmony_ci
835fd4e5da5Sopenharmony_ci  SinglePassRunAndMatch<BlockMergePass>(text, true);
836fd4e5da5Sopenharmony_ci}
837fd4e5da5Sopenharmony_ci
838fd4e5da5Sopenharmony_ciTEST_F(BlockMergeTest, DontMergeReturnValue) {
839fd4e5da5Sopenharmony_ci  const std::string text = R"(
840fd4e5da5Sopenharmony_ci; CHECK: OpLoopMerge [[merge:%\w+]] [[cont:%\w+]] None
841fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpBranch [[ret:%\w+]]
842fd4e5da5Sopenharmony_ci; CHECK: [[ret:%\w+]] = OpLabel
843fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpReturn
844fd4e5da5Sopenharmony_ci; CHECK-DAG: [[cont]] = OpLabel
845fd4e5da5Sopenharmony_ci; CHECK-DAG: [[merge]] = OpLabel
846fd4e5da5Sopenharmony_ciOpCapability Shader
847fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
848fd4e5da5Sopenharmony_ciOpEntryPoint Fragment %func "func"
849fd4e5da5Sopenharmony_ciOpExecutionMode %func OriginUpperLeft
850fd4e5da5Sopenharmony_ci%void = OpTypeVoid
851fd4e5da5Sopenharmony_ci%bool = OpTypeBool
852fd4e5da5Sopenharmony_ci%functy = OpTypeFunction %void
853fd4e5da5Sopenharmony_ci%otherfuncty = OpTypeFunction %bool
854fd4e5da5Sopenharmony_ci%true = OpConstantTrue %bool
855fd4e5da5Sopenharmony_ci%func = OpFunction %void None %functy
856fd4e5da5Sopenharmony_ci%1 = OpLabel
857fd4e5da5Sopenharmony_ci%2 = OpFunctionCall %bool %3
858fd4e5da5Sopenharmony_ciOpReturn
859fd4e5da5Sopenharmony_ciOpFunctionEnd
860fd4e5da5Sopenharmony_ci%3 = OpFunction %bool None %otherfuncty
861fd4e5da5Sopenharmony_ci%4 = OpLabel
862fd4e5da5Sopenharmony_ciOpBranch %5
863fd4e5da5Sopenharmony_ci%5 = OpLabel
864fd4e5da5Sopenharmony_ciOpLoopMerge %6 %7 None
865fd4e5da5Sopenharmony_ciOpBranch %8
866fd4e5da5Sopenharmony_ci%8 = OpLabel
867fd4e5da5Sopenharmony_ciOpReturnValue %true
868fd4e5da5Sopenharmony_ci%7 = OpLabel
869fd4e5da5Sopenharmony_ciOpBranch %5
870fd4e5da5Sopenharmony_ci%6 = OpLabel
871fd4e5da5Sopenharmony_ciOpUnreachable
872fd4e5da5Sopenharmony_ciOpFunctionEnd
873fd4e5da5Sopenharmony_ci)";
874fd4e5da5Sopenharmony_ci
875fd4e5da5Sopenharmony_ci  SinglePassRunAndMatch<BlockMergePass>(text, true);
876fd4e5da5Sopenharmony_ci}
877fd4e5da5Sopenharmony_ci
878fd4e5da5Sopenharmony_ciTEST_F(BlockMergeTest, MergeHeaders) {
879fd4e5da5Sopenharmony_ci  // Merge two headers when the second is the merge block of the first.
880fd4e5da5Sopenharmony_ci  const std::string text = R"(
881fd4e5da5Sopenharmony_ci; CHECK: OpFunction
882fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpLabel
883fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpBranch [[header:%\w+]]
884fd4e5da5Sopenharmony_ci; CHECK-NEXT: [[header]] = OpLabel
885fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpSelectionMerge [[merge:%\w+]]
886fd4e5da5Sopenharmony_ci; CHECK: [[merge]] = OpLabel
887fd4e5da5Sopenharmony_ci; CHECK: OpReturn
888fd4e5da5Sopenharmony_ciOpCapability Shader
889fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
890fd4e5da5Sopenharmony_ciOpEntryPoint Fragment %func "func"
891fd4e5da5Sopenharmony_ciOpExecutionMode %func OriginUpperLeft
892fd4e5da5Sopenharmony_ci%void = OpTypeVoid
893fd4e5da5Sopenharmony_ci%bool = OpTypeBool
894fd4e5da5Sopenharmony_ci%functy = OpTypeFunction %void
895fd4e5da5Sopenharmony_ci%otherfuncty = OpTypeFunction %bool
896fd4e5da5Sopenharmony_ci%true = OpConstantTrue %bool
897fd4e5da5Sopenharmony_ci%func = OpFunction %void None %functy
898fd4e5da5Sopenharmony_ci%1 = OpLabel
899fd4e5da5Sopenharmony_ciOpBranch %5
900fd4e5da5Sopenharmony_ci%5 = OpLabel
901fd4e5da5Sopenharmony_ciOpLoopMerge %8 %7 None
902fd4e5da5Sopenharmony_ciOpBranch %8
903fd4e5da5Sopenharmony_ci%7 = OpLabel
904fd4e5da5Sopenharmony_ciOpBranch %5
905fd4e5da5Sopenharmony_ci%8 = OpLabel
906fd4e5da5Sopenharmony_ciOpSelectionMerge %m None
907fd4e5da5Sopenharmony_ciOpBranchConditional %true %a %m
908fd4e5da5Sopenharmony_ci%a = OpLabel
909fd4e5da5Sopenharmony_ciOpBranch %m
910fd4e5da5Sopenharmony_ci%m = OpLabel
911fd4e5da5Sopenharmony_ciOpReturn
912fd4e5da5Sopenharmony_ciOpFunctionEnd
913fd4e5da5Sopenharmony_ci)";
914fd4e5da5Sopenharmony_ci
915fd4e5da5Sopenharmony_ci  SinglePassRunAndMatch<BlockMergePass>(text, true);
916fd4e5da5Sopenharmony_ci}
917fd4e5da5Sopenharmony_ci
918fd4e5da5Sopenharmony_ciTEST_F(BlockMergeTest, OpPhiInSuccessor) {
919fd4e5da5Sopenharmony_ci  // Checks that when merging blocks A and B, the OpPhi at the start of B is
920fd4e5da5Sopenharmony_ci  // removed and uses of its definition are replaced appropriately.
921fd4e5da5Sopenharmony_ci  const std::string prefix =
922fd4e5da5Sopenharmony_ci      R"(OpCapability Shader
923fd4e5da5Sopenharmony_ci%1 = OpExtInstImport "GLSL.std.450"
924fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
925fd4e5da5Sopenharmony_ciOpEntryPoint Fragment %main "main"
926fd4e5da5Sopenharmony_ciOpExecutionMode %main OriginUpperLeft
927fd4e5da5Sopenharmony_ciOpSource ESSL 310
928fd4e5da5Sopenharmony_ciOpName %main "main"
929fd4e5da5Sopenharmony_ciOpName %x "x"
930fd4e5da5Sopenharmony_ciOpName %y "y"
931fd4e5da5Sopenharmony_ci%void = OpTypeVoid
932fd4e5da5Sopenharmony_ci%6 = OpTypeFunction %void
933fd4e5da5Sopenharmony_ci%int = OpTypeInt 32 1
934fd4e5da5Sopenharmony_ci%_ptr_Function_int = OpTypePointer Function %int
935fd4e5da5Sopenharmony_ci%int_1 = OpConstant %int 1
936fd4e5da5Sopenharmony_ci%main = OpFunction %void None %6
937fd4e5da5Sopenharmony_ci%10 = OpLabel
938fd4e5da5Sopenharmony_ci%x = OpVariable %_ptr_Function_int Function
939fd4e5da5Sopenharmony_ci%y = OpVariable %_ptr_Function_int Function
940fd4e5da5Sopenharmony_ciOpStore %x %int_1
941fd4e5da5Sopenharmony_ci%11 = OpLoad %int %x
942fd4e5da5Sopenharmony_ci)";
943fd4e5da5Sopenharmony_ci
944fd4e5da5Sopenharmony_ci  const std::string suffix_before =
945fd4e5da5Sopenharmony_ci      R"(OpBranch %12
946fd4e5da5Sopenharmony_ci%12 = OpLabel
947fd4e5da5Sopenharmony_ci%13 = OpPhi %int %11 %10
948fd4e5da5Sopenharmony_ciOpStore %y %13
949fd4e5da5Sopenharmony_ciOpReturn
950fd4e5da5Sopenharmony_ciOpFunctionEnd
951fd4e5da5Sopenharmony_ci)";
952fd4e5da5Sopenharmony_ci
953fd4e5da5Sopenharmony_ci  const std::string suffix_after =
954fd4e5da5Sopenharmony_ci      R"(OpStore %y %11
955fd4e5da5Sopenharmony_ciOpReturn
956fd4e5da5Sopenharmony_ciOpFunctionEnd
957fd4e5da5Sopenharmony_ci)";
958fd4e5da5Sopenharmony_ci  SinglePassRunAndCheck<BlockMergePass>(prefix + suffix_before,
959fd4e5da5Sopenharmony_ci                                        prefix + suffix_after, true, true);
960fd4e5da5Sopenharmony_ci}
961fd4e5da5Sopenharmony_ci
962fd4e5da5Sopenharmony_ciTEST_F(BlockMergeTest, MultipleOpPhisInSuccessor) {
963fd4e5da5Sopenharmony_ci  // Checks that when merging blocks A and B, the OpPhis at the start of B are
964fd4e5da5Sopenharmony_ci  // removed and uses of their definitions are replaced appropriately.
965fd4e5da5Sopenharmony_ci  const std::string prefix =
966fd4e5da5Sopenharmony_ci      R"(OpCapability Shader
967fd4e5da5Sopenharmony_ci%1 = OpExtInstImport "GLSL.std.450"
968fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
969fd4e5da5Sopenharmony_ciOpEntryPoint Fragment %main "main"
970fd4e5da5Sopenharmony_ciOpExecutionMode %main OriginUpperLeft
971fd4e5da5Sopenharmony_ciOpSource ESSL 310
972fd4e5da5Sopenharmony_ciOpName %main "main"
973fd4e5da5Sopenharmony_ciOpName %S "S"
974fd4e5da5Sopenharmony_ciOpMemberName %S 0 "x"
975fd4e5da5Sopenharmony_ciOpMemberName %S 1 "f"
976fd4e5da5Sopenharmony_ciOpName %s "s"
977fd4e5da5Sopenharmony_ciOpName %g "g"
978fd4e5da5Sopenharmony_ciOpName %y "y"
979fd4e5da5Sopenharmony_ciOpName %t "t"
980fd4e5da5Sopenharmony_ciOpName %z "z"
981fd4e5da5Sopenharmony_ci%void = OpTypeVoid
982fd4e5da5Sopenharmony_ci%10 = OpTypeFunction %void
983fd4e5da5Sopenharmony_ci%int = OpTypeInt 32 1
984fd4e5da5Sopenharmony_ci%float = OpTypeFloat 32
985fd4e5da5Sopenharmony_ci%S = OpTypeStruct %int %float
986fd4e5da5Sopenharmony_ci%_ptr_Function_S = OpTypePointer Function %S
987fd4e5da5Sopenharmony_ci%int_1 = OpConstant %int 1
988fd4e5da5Sopenharmony_ci%float_2 = OpConstant %float 2
989fd4e5da5Sopenharmony_ci%16 = OpConstantComposite %S %int_1 %float_2
990fd4e5da5Sopenharmony_ci%_ptr_Function_float = OpTypePointer Function %float
991fd4e5da5Sopenharmony_ci%_ptr_Function_int = OpTypePointer Function %int
992fd4e5da5Sopenharmony_ci%int_3 = OpConstant %int 3
993fd4e5da5Sopenharmony_ci%int_0 = OpConstant %int 0
994fd4e5da5Sopenharmony_ci%main = OpFunction %void None %10
995fd4e5da5Sopenharmony_ci%21 = OpLabel
996fd4e5da5Sopenharmony_ci%s = OpVariable %_ptr_Function_S Function
997fd4e5da5Sopenharmony_ci%g = OpVariable %_ptr_Function_float Function
998fd4e5da5Sopenharmony_ci%y = OpVariable %_ptr_Function_int Function
999fd4e5da5Sopenharmony_ci%t = OpVariable %_ptr_Function_S Function
1000fd4e5da5Sopenharmony_ci%z = OpVariable %_ptr_Function_float Function
1001fd4e5da5Sopenharmony_ciOpStore %s %16
1002fd4e5da5Sopenharmony_ciOpStore %g %float_2
1003fd4e5da5Sopenharmony_ciOpStore %y %int_3
1004fd4e5da5Sopenharmony_ci%22 = OpLoad %S %s
1005fd4e5da5Sopenharmony_ciOpStore %t %22
1006fd4e5da5Sopenharmony_ci%23 = OpAccessChain %_ptr_Function_float %s %int_1
1007fd4e5da5Sopenharmony_ci%24 = OpLoad %float %23
1008fd4e5da5Sopenharmony_ci%25 = OpLoad %float %g
1009fd4e5da5Sopenharmony_ci)";
1010fd4e5da5Sopenharmony_ci
1011fd4e5da5Sopenharmony_ci  const std::string suffix_before =
1012fd4e5da5Sopenharmony_ci      R"(OpBranch %26
1013fd4e5da5Sopenharmony_ci%26 = OpLabel
1014fd4e5da5Sopenharmony_ci%27 = OpPhi %float %24 %21
1015fd4e5da5Sopenharmony_ci%28 = OpPhi %float %25 %21
1016fd4e5da5Sopenharmony_ci%29 = OpFAdd %float %27 %28
1017fd4e5da5Sopenharmony_ci%30 = OpAccessChain %_ptr_Function_int %s %int_0
1018fd4e5da5Sopenharmony_ci%31 = OpLoad %int %30
1019fd4e5da5Sopenharmony_ciOpBranch %32
1020fd4e5da5Sopenharmony_ci%32 = OpLabel
1021fd4e5da5Sopenharmony_ci%33 = OpPhi %float %29 %26
1022fd4e5da5Sopenharmony_ci%34 = OpPhi %int %31 %26
1023fd4e5da5Sopenharmony_ci%35 = OpConvertSToF %float %34
1024fd4e5da5Sopenharmony_ciOpBranch %36
1025fd4e5da5Sopenharmony_ci%36 = OpLabel
1026fd4e5da5Sopenharmony_ci%37 = OpPhi %float %35 %32
1027fd4e5da5Sopenharmony_ci%38 = OpFSub %float %33 %37
1028fd4e5da5Sopenharmony_ci%39 = OpLoad %int %y
1029fd4e5da5Sopenharmony_ciOpBranch %40
1030fd4e5da5Sopenharmony_ci%40 = OpLabel
1031fd4e5da5Sopenharmony_ci%41 = OpPhi %float %38 %36
1032fd4e5da5Sopenharmony_ci%42 = OpPhi %int %39 %36
1033fd4e5da5Sopenharmony_ci%43 = OpConvertSToF %float %42
1034fd4e5da5Sopenharmony_ci%44 = OpFAdd %float %41 %43
1035fd4e5da5Sopenharmony_ciOpStore %z %44
1036fd4e5da5Sopenharmony_ciOpReturn
1037fd4e5da5Sopenharmony_ciOpFunctionEnd
1038fd4e5da5Sopenharmony_ci)";
1039fd4e5da5Sopenharmony_ci
1040fd4e5da5Sopenharmony_ci  const std::string suffix_after =
1041fd4e5da5Sopenharmony_ci      R"(%29 = OpFAdd %float %24 %25
1042fd4e5da5Sopenharmony_ci%30 = OpAccessChain %_ptr_Function_int %s %int_0
1043fd4e5da5Sopenharmony_ci%31 = OpLoad %int %30
1044fd4e5da5Sopenharmony_ci%35 = OpConvertSToF %float %31
1045fd4e5da5Sopenharmony_ci%38 = OpFSub %float %29 %35
1046fd4e5da5Sopenharmony_ci%39 = OpLoad %int %y
1047fd4e5da5Sopenharmony_ci%43 = OpConvertSToF %float %39
1048fd4e5da5Sopenharmony_ci%44 = OpFAdd %float %38 %43
1049fd4e5da5Sopenharmony_ciOpStore %z %44
1050fd4e5da5Sopenharmony_ciOpReturn
1051fd4e5da5Sopenharmony_ciOpFunctionEnd
1052fd4e5da5Sopenharmony_ci)";
1053fd4e5da5Sopenharmony_ci  SinglePassRunAndCheck<BlockMergePass>(prefix + suffix_before,
1054fd4e5da5Sopenharmony_ci                                        prefix + suffix_after, true, true);
1055fd4e5da5Sopenharmony_ci}
1056fd4e5da5Sopenharmony_ci
1057fd4e5da5Sopenharmony_ciTEST_F(BlockMergeTest, UnreachableLoop) {
1058fd4e5da5Sopenharmony_ci  const std::string spirv = R"(OpCapability Shader
1059fd4e5da5Sopenharmony_ci%1 = OpExtInstImport "GLSL.std.450"
1060fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
1061fd4e5da5Sopenharmony_ciOpEntryPoint Fragment %main "main"
1062fd4e5da5Sopenharmony_ciOpExecutionMode %main OriginUpperLeft
1063fd4e5da5Sopenharmony_ciOpSource ESSL 310
1064fd4e5da5Sopenharmony_ciOpName %main "main"
1065fd4e5da5Sopenharmony_ci%void = OpTypeVoid
1066fd4e5da5Sopenharmony_ci%4 = OpTypeFunction %void
1067fd4e5da5Sopenharmony_ci%int = OpTypeInt 32 1
1068fd4e5da5Sopenharmony_ci%_ptr_Function_int = OpTypePointer Function %int
1069fd4e5da5Sopenharmony_ci%bool = OpTypeBool
1070fd4e5da5Sopenharmony_ci%false = OpConstantFalse %bool
1071fd4e5da5Sopenharmony_ci%main = OpFunction %void None %4
1072fd4e5da5Sopenharmony_ci%9 = OpLabel
1073fd4e5da5Sopenharmony_ciOpBranch %10
1074fd4e5da5Sopenharmony_ci%11 = OpLabel
1075fd4e5da5Sopenharmony_ciOpLoopMerge %12 %13 None
1076fd4e5da5Sopenharmony_ciOpBranchConditional %false %13 %14
1077fd4e5da5Sopenharmony_ci%13 = OpLabel
1078fd4e5da5Sopenharmony_ciOpSelectionMerge %15 None
1079fd4e5da5Sopenharmony_ciOpBranchConditional %false %16 %17
1080fd4e5da5Sopenharmony_ci%16 = OpLabel
1081fd4e5da5Sopenharmony_ciOpBranch %15
1082fd4e5da5Sopenharmony_ci%17 = OpLabel
1083fd4e5da5Sopenharmony_ciOpBranch %15
1084fd4e5da5Sopenharmony_ci%15 = OpLabel
1085fd4e5da5Sopenharmony_ciOpBranch %11
1086fd4e5da5Sopenharmony_ci%14 = OpLabel
1087fd4e5da5Sopenharmony_ciOpReturn
1088fd4e5da5Sopenharmony_ci%12 = OpLabel
1089fd4e5da5Sopenharmony_ciOpBranch %10
1090fd4e5da5Sopenharmony_ci%10 = OpLabel
1091fd4e5da5Sopenharmony_ciOpReturn
1092fd4e5da5Sopenharmony_ciOpFunctionEnd
1093fd4e5da5Sopenharmony_ci)";
1094fd4e5da5Sopenharmony_ci
1095fd4e5da5Sopenharmony_ci  SinglePassRunAndCheck<BlockMergePass>(spirv, spirv, true, true);
1096fd4e5da5Sopenharmony_ci}
1097fd4e5da5Sopenharmony_ci
1098fd4e5da5Sopenharmony_ciTEST_F(BlockMergeTest, DebugMerge) {
1099fd4e5da5Sopenharmony_ci  // Verify merge can be done completely, cleanly and validly in presence of
1100fd4e5da5Sopenharmony_ci  // NonSemantic.Shader.DebugInfo.100 instructions
1101fd4e5da5Sopenharmony_ci  const std::string text = R"(
1102fd4e5da5Sopenharmony_ci; CHECK: OpLoopMerge
1103fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpBranch
1104fd4e5da5Sopenharmony_ci; CHECK-NOT: OpBranch
1105fd4e5da5Sopenharmony_ciOpCapability Shader
1106fd4e5da5Sopenharmony_ciOpExtension "SPV_KHR_non_semantic_info"
1107fd4e5da5Sopenharmony_ci%1 = OpExtInstImport "NonSemantic.Shader.DebugInfo.100"
1108fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
1109fd4e5da5Sopenharmony_ciOpEntryPoint Fragment %main "main" %in_var_COLOR %out_var_SV_TARGET
1110fd4e5da5Sopenharmony_ciOpExecutionMode %main OriginUpperLeft
1111fd4e5da5Sopenharmony_ci%5 = OpString "lexblock.hlsl"
1112fd4e5da5Sopenharmony_ci%20 = OpString "float"
1113fd4e5da5Sopenharmony_ci%32 = OpString "main"
1114fd4e5da5Sopenharmony_ci%33 = OpString ""
1115fd4e5da5Sopenharmony_ci%46 = OpString "b"
1116fd4e5da5Sopenharmony_ci%49 = OpString "a"
1117fd4e5da5Sopenharmony_ci%58 = OpString "c"
1118fd4e5da5Sopenharmony_ci%63 = OpString "color"
1119fd4e5da5Sopenharmony_ciOpName %in_var_COLOR "in.var.COLOR"
1120fd4e5da5Sopenharmony_ciOpName %out_var_SV_TARGET "out.var.SV_TARGET"
1121fd4e5da5Sopenharmony_ciOpName %main "main"
1122fd4e5da5Sopenharmony_ciOpDecorate %in_var_COLOR Location 0
1123fd4e5da5Sopenharmony_ciOpDecorate %out_var_SV_TARGET Location 0
1124fd4e5da5Sopenharmony_ci%float = OpTypeFloat 32
1125fd4e5da5Sopenharmony_ci%float_0 = OpConstant %float 0
1126fd4e5da5Sopenharmony_ci%v4float = OpTypeVector %float 4
1127fd4e5da5Sopenharmony_ci%9 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0
1128fd4e5da5Sopenharmony_ci%float_1 = OpConstant %float 1
1129fd4e5da5Sopenharmony_ci%13 = OpConstantComposite %v4float %float_1 %float_1 %float_1 %float_1
1130fd4e5da5Sopenharmony_ci%uint = OpTypeInt 32 0
1131fd4e5da5Sopenharmony_ci%uint_32 = OpConstant %uint 32
1132fd4e5da5Sopenharmony_ci%_ptr_Input_v4float = OpTypePointer Input %v4float
1133fd4e5da5Sopenharmony_ci%_ptr_Output_v4float = OpTypePointer Output %v4float
1134fd4e5da5Sopenharmony_ci%void = OpTypeVoid
1135fd4e5da5Sopenharmony_ci%uint_3 = OpConstant %uint 3
1136fd4e5da5Sopenharmony_ci%uint_0 = OpConstant %uint 0
1137fd4e5da5Sopenharmony_ci%uint_4 = OpConstant %uint 4
1138fd4e5da5Sopenharmony_ci%uint_1 = OpConstant %uint 1
1139fd4e5da5Sopenharmony_ci%uint_5 = OpConstant %uint 5
1140fd4e5da5Sopenharmony_ci%uint_12 = OpConstant %uint 12
1141fd4e5da5Sopenharmony_ci%uint_13 = OpConstant %uint 13
1142fd4e5da5Sopenharmony_ci%uint_20 = OpConstant %uint 20
1143fd4e5da5Sopenharmony_ci%uint_15 = OpConstant %uint 15
1144fd4e5da5Sopenharmony_ci%uint_17 = OpConstant %uint 17
1145fd4e5da5Sopenharmony_ci%uint_16 = OpConstant %uint 16
1146fd4e5da5Sopenharmony_ci%uint_14 = OpConstant %uint 14
1147fd4e5da5Sopenharmony_ci%uint_10 = OpConstant %uint 10
1148fd4e5da5Sopenharmony_ci%65 = OpTypeFunction %void
1149fd4e5da5Sopenharmony_ci%in_var_COLOR = OpVariable %_ptr_Input_v4float Input
1150fd4e5da5Sopenharmony_ci%out_var_SV_TARGET = OpVariable %_ptr_Output_v4float Output
1151fd4e5da5Sopenharmony_ci%62 = OpExtInst %void %1 DebugExpression
1152fd4e5da5Sopenharmony_ci%22 = OpExtInst %void %1 DebugTypeBasic %20 %uint_32 %uint_3 %uint_0
1153fd4e5da5Sopenharmony_ci%25 = OpExtInst %void %1 DebugTypeVector %22 %uint_4
1154fd4e5da5Sopenharmony_ci%27 = OpExtInst %void %1 DebugTypeFunction %uint_3 %25 %25
1155fd4e5da5Sopenharmony_ci%28 = OpExtInst %void %1 DebugSource %5
1156fd4e5da5Sopenharmony_ci%29 = OpExtInst %void %1 DebugCompilationUnit %uint_1 %uint_4 %28 %uint_5
1157fd4e5da5Sopenharmony_ci%34 = OpExtInst %void %1 DebugFunction %32 %27 %28 %uint_12 %uint_1 %29 %33 %uint_3 %uint_13
1158fd4e5da5Sopenharmony_ci%37 = OpExtInst %void %1 DebugLexicalBlock %28 %uint_13 %uint_1 %34
1159fd4e5da5Sopenharmony_ci%52 = OpExtInst %void %1 DebugLexicalBlock %28 %uint_15 %uint_12 %37
1160fd4e5da5Sopenharmony_ci%54 = OpExtInst %void %1 DebugLocalVariable %46 %25 %28 %uint_17 %uint_12 %52 %uint_4
1161fd4e5da5Sopenharmony_ci%56 = OpExtInst %void %1 DebugLocalVariable %49 %25 %28 %uint_16 %uint_12 %52 %uint_4
1162fd4e5da5Sopenharmony_ci%59 = OpExtInst %void %1 DebugLocalVariable %58 %25 %28 %uint_14 %uint_10 %37 %uint_4
1163fd4e5da5Sopenharmony_ci%64 = OpExtInst %void %1 DebugLocalVariable %63 %25 %28 %uint_12 %uint_20 %34 %uint_4 %uint_1
1164fd4e5da5Sopenharmony_ci%main = OpFunction %void None %65
1165fd4e5da5Sopenharmony_ci%66 = OpLabel
1166fd4e5da5Sopenharmony_ci%69 = OpLoad %v4float %in_var_COLOR
1167fd4e5da5Sopenharmony_ci%168 = OpExtInst %void %1 DebugValue %64 %69 %62
1168fd4e5da5Sopenharmony_ci%169 = OpExtInst %void %1 DebugScope %37
1169fd4e5da5Sopenharmony_ciOpLine %5 14 10
1170fd4e5da5Sopenharmony_ci%164 = OpExtInst %void %1 DebugValue %59 %9 %62
1171fd4e5da5Sopenharmony_ciOpLine %5 15 3
1172fd4e5da5Sopenharmony_ciOpBranch %150
1173fd4e5da5Sopenharmony_ci%150 = OpLabel
1174fd4e5da5Sopenharmony_ci%165 = OpPhi %v4float %9 %66 %158 %159
1175fd4e5da5Sopenharmony_ci%167 = OpExtInst %void %1 DebugValue %59 %165 %62
1176fd4e5da5Sopenharmony_ci%170 = OpExtInst %void %1 DebugScope %37
1177fd4e5da5Sopenharmony_ciOpLine %5 15 12
1178fd4e5da5Sopenharmony_ci%171 = OpExtInst %void %1 DebugNoScope
1179fd4e5da5Sopenharmony_ciOpLoopMerge %160 %159 None
1180fd4e5da5Sopenharmony_ciOpBranch %151
1181fd4e5da5Sopenharmony_ci%151 = OpLabel
1182fd4e5da5Sopenharmony_ciOpLine %5 16 12
1183fd4e5da5Sopenharmony_ci%162 = OpExtInst %void %1 DebugValue %56 %9 %62
1184fd4e5da5Sopenharmony_ciOpLine %5 17 12
1185fd4e5da5Sopenharmony_ci%163 = OpExtInst %void %1 DebugValue %54 %13 %62
1186fd4e5da5Sopenharmony_ciOpLine %5 18 15
1187fd4e5da5Sopenharmony_ci%158 = OpFAdd %v4float %165 %13
1188fd4e5da5Sopenharmony_ciOpLine %5 18 5
1189fd4e5da5Sopenharmony_ci%166 = OpExtInst %void %1 DebugValue %59 %158 %62
1190fd4e5da5Sopenharmony_ci%172 = OpExtInst %void %1 DebugScope %37
1191fd4e5da5Sopenharmony_ciOpLine %5 19 3
1192fd4e5da5Sopenharmony_ciOpBranch %159
1193fd4e5da5Sopenharmony_ci%159 = OpLabel
1194fd4e5da5Sopenharmony_ciOpLine %5 19 3
1195fd4e5da5Sopenharmony_ciOpBranch %150
1196fd4e5da5Sopenharmony_ci%160 = OpLabel
1197fd4e5da5Sopenharmony_ciOpUnreachable
1198fd4e5da5Sopenharmony_ciOpFunctionEnd
1199fd4e5da5Sopenharmony_ci)";
1200fd4e5da5Sopenharmony_ci
1201fd4e5da5Sopenharmony_ci  SinglePassRunAndMatch<BlockMergePass>(text, true);
1202fd4e5da5Sopenharmony_ci}
1203fd4e5da5Sopenharmony_ci
1204fd4e5da5Sopenharmony_ciTEST_F(BlockMergeTest, DontLoseCaseConstruct) {
1205fd4e5da5Sopenharmony_ci  const std::string text = R"(
1206fd4e5da5Sopenharmony_ciOpCapability Shader
1207fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
1208fd4e5da5Sopenharmony_ciOpEntryPoint GLCompute %func "func"
1209fd4e5da5Sopenharmony_ciOpExecutionMode %func LocalSize 1 1 1
1210fd4e5da5Sopenharmony_ciOpName %entry "entry";
1211fd4e5da5Sopenharmony_ciOpName %loop "loop"
1212fd4e5da5Sopenharmony_ciOpName %loop_merge "loop_merge"
1213fd4e5da5Sopenharmony_ciOpName %loop_cont "loop_cont"
1214fd4e5da5Sopenharmony_ciOpName %switch "switch"
1215fd4e5da5Sopenharmony_ciOpName %switch_merge "switch_merge"
1216fd4e5da5Sopenharmony_ci%void = OpTypeVoid
1217fd4e5da5Sopenharmony_ci%bool = OpTypeBool
1218fd4e5da5Sopenharmony_ci%int = OpTypeInt 32 0
1219fd4e5da5Sopenharmony_ci%void_fn = OpTypeFunction %void
1220fd4e5da5Sopenharmony_ci%bool_undef = OpUndef %bool
1221fd4e5da5Sopenharmony_ci%int_undef = OpUndef %int
1222fd4e5da5Sopenharmony_ci%func = OpFunction %void None %void_fn
1223fd4e5da5Sopenharmony_ci%entry = OpLabel
1224fd4e5da5Sopenharmony_ciOpBranch %loop
1225fd4e5da5Sopenharmony_ci%loop = OpLabel
1226fd4e5da5Sopenharmony_ciOpLoopMerge %loop_merge %loop_cont None
1227fd4e5da5Sopenharmony_ciOpBranch %switch
1228fd4e5da5Sopenharmony_ci%switch = OpLabel
1229fd4e5da5Sopenharmony_ciOpSelectionMerge %switch_merge None
1230fd4e5da5Sopenharmony_ciOpSwitch %int_undef %switch_merge 0 %break 1 %break
1231fd4e5da5Sopenharmony_ci%break = OpLabel
1232fd4e5da5Sopenharmony_ciOpBranch %loop_merge
1233fd4e5da5Sopenharmony_ci%switch_merge = OpLabel
1234fd4e5da5Sopenharmony_ciOpBranch %loop_cont
1235fd4e5da5Sopenharmony_ci%loop_cont = OpLabel
1236fd4e5da5Sopenharmony_ciOpBranch %loop
1237fd4e5da5Sopenharmony_ci%loop_merge = OpLabel
1238fd4e5da5Sopenharmony_ciOpReturn
1239fd4e5da5Sopenharmony_ciOpFunctionEnd
1240fd4e5da5Sopenharmony_ci)";
1241fd4e5da5Sopenharmony_ci
1242fd4e5da5Sopenharmony_ci  auto result = SinglePassRunAndDisassemble<opt::BlockMergePass>(
1243fd4e5da5Sopenharmony_ci      text, /* skip_nop = */ true, /* do_validation = */ true);
1244fd4e5da5Sopenharmony_ci  EXPECT_EQ(opt::Pass::Status::SuccessWithoutChange, std::get<1>(result));
1245fd4e5da5Sopenharmony_ci}
1246fd4e5da5Sopenharmony_ci
1247fd4e5da5Sopenharmony_ciTEST_F(BlockMergeTest, DontLoseDefaultCaseConstruct) {
1248fd4e5da5Sopenharmony_ci  const std::string text = R"(
1249fd4e5da5Sopenharmony_ciOpCapability Shader
1250fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
1251fd4e5da5Sopenharmony_ciOpEntryPoint GLCompute %func "func"
1252fd4e5da5Sopenharmony_ciOpExecutionMode %func LocalSize 1 1 1
1253fd4e5da5Sopenharmony_ciOpName %entry "entry";
1254fd4e5da5Sopenharmony_ciOpName %loop "loop"
1255fd4e5da5Sopenharmony_ciOpName %loop_merge "loop_merge"
1256fd4e5da5Sopenharmony_ciOpName %loop_cont "loop_cont"
1257fd4e5da5Sopenharmony_ciOpName %switch "switch"
1258fd4e5da5Sopenharmony_ciOpName %switch_merge "switch_merge"
1259fd4e5da5Sopenharmony_ci%void = OpTypeVoid
1260fd4e5da5Sopenharmony_ci%bool = OpTypeBool
1261fd4e5da5Sopenharmony_ci%int = OpTypeInt 32 0
1262fd4e5da5Sopenharmony_ci%void_fn = OpTypeFunction %void
1263fd4e5da5Sopenharmony_ci%bool_undef = OpUndef %bool
1264fd4e5da5Sopenharmony_ci%int_undef = OpUndef %int
1265fd4e5da5Sopenharmony_ci%func = OpFunction %void None %void_fn
1266fd4e5da5Sopenharmony_ci%entry = OpLabel
1267fd4e5da5Sopenharmony_ciOpBranch %loop
1268fd4e5da5Sopenharmony_ci%loop = OpLabel
1269fd4e5da5Sopenharmony_ciOpLoopMerge %loop_merge %loop_cont None
1270fd4e5da5Sopenharmony_ciOpBranch %switch
1271fd4e5da5Sopenharmony_ci%switch = OpLabel
1272fd4e5da5Sopenharmony_ciOpSelectionMerge %switch_merge None
1273fd4e5da5Sopenharmony_ciOpSwitch %int_undef %cont 0 %switch_merge 1 %switch_merge
1274fd4e5da5Sopenharmony_ci%cont = OpLabel
1275fd4e5da5Sopenharmony_ciOpBranch %loop_cont
1276fd4e5da5Sopenharmony_ci%switch_merge = OpLabel
1277fd4e5da5Sopenharmony_ciOpBranch %loop_merge
1278fd4e5da5Sopenharmony_ci%loop_cont = OpLabel
1279fd4e5da5Sopenharmony_ciOpBranch %loop
1280fd4e5da5Sopenharmony_ci%loop_merge = OpLabel
1281fd4e5da5Sopenharmony_ciOpReturn
1282fd4e5da5Sopenharmony_ciOpFunctionEnd
1283fd4e5da5Sopenharmony_ci)";
1284fd4e5da5Sopenharmony_ci
1285fd4e5da5Sopenharmony_ci  auto result = SinglePassRunAndDisassemble<opt::BlockMergePass>(
1286fd4e5da5Sopenharmony_ci      text, /* skip_nop = */ true, /* do_validation = */ true);
1287fd4e5da5Sopenharmony_ci  EXPECT_EQ(opt::Pass::Status::SuccessWithoutChange, std::get<1>(result));
1288fd4e5da5Sopenharmony_ci}
1289fd4e5da5Sopenharmony_ci
1290fd4e5da5Sopenharmony_ciTEST_F(BlockMergeTest, RebuildStructuredCFG) {
1291fd4e5da5Sopenharmony_ci  const std::string text = R"(
1292fd4e5da5Sopenharmony_ci; CHECK: = OpFunction
1293fd4e5da5Sopenharmony_ci; CHECK-NEXT: [[entry:%\w+]] = OpLabel
1294fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpSelectionMerge [[merge:%\w+]] None
1295fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpSwitch {{%\w+}} [[merge]] 0 [[other:%\w+]]
1296fd4e5da5Sopenharmony_ci; CHECK [[other]] = OpLabel
1297fd4e5da5Sopenharmony_ci; CHECK: OpBranch [[merge]]
1298fd4e5da5Sopenharmony_ci; CHECK [[merge]] = OpLabel
1299fd4e5da5Sopenharmony_ciOpCapability Shader
1300fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
1301fd4e5da5Sopenharmony_ciOpEntryPoint GLCompute %main "main"
1302fd4e5da5Sopenharmony_ciOpExecutionMode %main LocalSize 1 1 1
1303fd4e5da5Sopenharmony_ci%void = OpTypeVoid
1304fd4e5da5Sopenharmony_ci%int = OpTypeInt 32 0
1305fd4e5da5Sopenharmony_ci%int_1 = OpConstant %int 1
1306fd4e5da5Sopenharmony_ci%void_fn = OpTypeFunction %void
1307fd4e5da5Sopenharmony_ci%main = OpFunction %void None %void_fn
1308fd4e5da5Sopenharmony_ci%entry = OpLabel
1309fd4e5da5Sopenharmony_ciOpBranch %switch
1310fd4e5da5Sopenharmony_ci%switch = OpLabel
1311fd4e5da5Sopenharmony_ciOpSelectionMerge %merge None
1312fd4e5da5Sopenharmony_ciOpSwitch %int_1 %merge 0 %other
1313fd4e5da5Sopenharmony_ci%other = OpLabel
1314fd4e5da5Sopenharmony_ciOpBranch %merge
1315fd4e5da5Sopenharmony_ci%merge = OpLabel
1316fd4e5da5Sopenharmony_ciOpReturn
1317fd4e5da5Sopenharmony_ciOpFunctionEnd
1318fd4e5da5Sopenharmony_ci)";
1319fd4e5da5Sopenharmony_ci
1320fd4e5da5Sopenharmony_ci  SinglePassRunAndMatch<BlockMergePass>(text, true);
1321fd4e5da5Sopenharmony_ci}
1322fd4e5da5Sopenharmony_ci
1323fd4e5da5Sopenharmony_ci// TODO(greg-lunarg): Add tests to verify handling of these cases:
1324fd4e5da5Sopenharmony_ci//
1325fd4e5da5Sopenharmony_ci//    More complex control flow
1326fd4e5da5Sopenharmony_ci//    Others?
1327fd4e5da5Sopenharmony_ci
1328fd4e5da5Sopenharmony_ci}  // namespace
1329fd4e5da5Sopenharmony_ci}  // namespace opt
1330fd4e5da5Sopenharmony_ci}  // namespace spvtools
1331