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 DeadBranchElimTest = PassTest<::testing::Test>;
26fd4e5da5Sopenharmony_ci
27fd4e5da5Sopenharmony_ciTEST_F(DeadBranchElimTest, IfThenElseTrue) {
28fd4e5da5Sopenharmony_ci  // #version 140
29fd4e5da5Sopenharmony_ci  //
30fd4e5da5Sopenharmony_ci  // in vec4 BaseColor;
31fd4e5da5Sopenharmony_ci  //
32fd4e5da5Sopenharmony_ci  // void main()
33fd4e5da5Sopenharmony_ci  // {
34fd4e5da5Sopenharmony_ci  //     vec4 v;
35fd4e5da5Sopenharmony_ci  //     if (true)
36fd4e5da5Sopenharmony_ci  //       v = vec4(0.0,0.0,0.0,0.0);
37fd4e5da5Sopenharmony_ci  //     else
38fd4e5da5Sopenharmony_ci  //       v = vec4(1.0,1.0,1.0,1.0);
39fd4e5da5Sopenharmony_ci  //     gl_FragColor = v;
40fd4e5da5Sopenharmony_ci  // }
41fd4e5da5Sopenharmony_ci
42fd4e5da5Sopenharmony_ci  const std::string predefs =
43fd4e5da5Sopenharmony_ci      R"(OpCapability Shader
44fd4e5da5Sopenharmony_ci%1 = OpExtInstImport "GLSL.std.450"
45fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
46fd4e5da5Sopenharmony_ciOpEntryPoint Fragment %main "main" %gl_FragColor %BaseColor
47fd4e5da5Sopenharmony_ciOpExecutionMode %main OriginUpperLeft
48fd4e5da5Sopenharmony_ciOpSource GLSL 140
49fd4e5da5Sopenharmony_ciOpName %main "main"
50fd4e5da5Sopenharmony_ciOpName %v "v"
51fd4e5da5Sopenharmony_ciOpName %gl_FragColor "gl_FragColor"
52fd4e5da5Sopenharmony_ciOpName %BaseColor "BaseColor"
53fd4e5da5Sopenharmony_ci%void = OpTypeVoid
54fd4e5da5Sopenharmony_ci%7 = OpTypeFunction %void
55fd4e5da5Sopenharmony_ci%bool = OpTypeBool
56fd4e5da5Sopenharmony_ci%true = OpConstantTrue %bool
57fd4e5da5Sopenharmony_ci%float = OpTypeFloat 32
58fd4e5da5Sopenharmony_ci%v4float = OpTypeVector %float 4
59fd4e5da5Sopenharmony_ci%_ptr_Function_v4float = OpTypePointer Function %v4float
60fd4e5da5Sopenharmony_ci%float_0 = OpConstant %float 0
61fd4e5da5Sopenharmony_ci%14 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0
62fd4e5da5Sopenharmony_ci%float_1 = OpConstant %float 1
63fd4e5da5Sopenharmony_ci%16 = OpConstantComposite %v4float %float_1 %float_1 %float_1 %float_1
64fd4e5da5Sopenharmony_ci%_ptr_Output_v4float = OpTypePointer Output %v4float
65fd4e5da5Sopenharmony_ci%gl_FragColor = OpVariable %_ptr_Output_v4float Output
66fd4e5da5Sopenharmony_ci%_ptr_Input_v4float = OpTypePointer Input %v4float
67fd4e5da5Sopenharmony_ci%BaseColor = OpVariable %_ptr_Input_v4float Input
68fd4e5da5Sopenharmony_ci)";
69fd4e5da5Sopenharmony_ci
70fd4e5da5Sopenharmony_ci  const std::string before =
71fd4e5da5Sopenharmony_ci      R"(%main = OpFunction %void None %7
72fd4e5da5Sopenharmony_ci%19 = OpLabel
73fd4e5da5Sopenharmony_ci%v = OpVariable %_ptr_Function_v4float Function
74fd4e5da5Sopenharmony_ciOpSelectionMerge %20 None
75fd4e5da5Sopenharmony_ciOpBranchConditional %true %21 %22
76fd4e5da5Sopenharmony_ci%21 = OpLabel
77fd4e5da5Sopenharmony_ciOpStore %v %14
78fd4e5da5Sopenharmony_ciOpBranch %20
79fd4e5da5Sopenharmony_ci%22 = OpLabel
80fd4e5da5Sopenharmony_ciOpStore %v %16
81fd4e5da5Sopenharmony_ciOpBranch %20
82fd4e5da5Sopenharmony_ci%20 = OpLabel
83fd4e5da5Sopenharmony_ci%23 = OpLoad %v4float %v
84fd4e5da5Sopenharmony_ciOpStore %gl_FragColor %23
85fd4e5da5Sopenharmony_ciOpReturn
86fd4e5da5Sopenharmony_ciOpFunctionEnd
87fd4e5da5Sopenharmony_ci)";
88fd4e5da5Sopenharmony_ci
89fd4e5da5Sopenharmony_ci  const std::string after =
90fd4e5da5Sopenharmony_ci      R"(%main = OpFunction %void None %7
91fd4e5da5Sopenharmony_ci%19 = OpLabel
92fd4e5da5Sopenharmony_ci%v = OpVariable %_ptr_Function_v4float Function
93fd4e5da5Sopenharmony_ciOpBranch %21
94fd4e5da5Sopenharmony_ci%21 = OpLabel
95fd4e5da5Sopenharmony_ciOpStore %v %14
96fd4e5da5Sopenharmony_ciOpBranch %20
97fd4e5da5Sopenharmony_ci%20 = OpLabel
98fd4e5da5Sopenharmony_ci%23 = OpLoad %v4float %v
99fd4e5da5Sopenharmony_ciOpStore %gl_FragColor %23
100fd4e5da5Sopenharmony_ciOpReturn
101fd4e5da5Sopenharmony_ciOpFunctionEnd
102fd4e5da5Sopenharmony_ci)";
103fd4e5da5Sopenharmony_ci
104fd4e5da5Sopenharmony_ci  SinglePassRunAndCheck<DeadBranchElimPass>(predefs + before, predefs + after,
105fd4e5da5Sopenharmony_ci                                            true, true);
106fd4e5da5Sopenharmony_ci}
107fd4e5da5Sopenharmony_ci
108fd4e5da5Sopenharmony_ciTEST_F(DeadBranchElimTest, IfThenElseFalse) {
109fd4e5da5Sopenharmony_ci  // #version 140
110fd4e5da5Sopenharmony_ci  //
111fd4e5da5Sopenharmony_ci  // in vec4 BaseColor;
112fd4e5da5Sopenharmony_ci  //
113fd4e5da5Sopenharmony_ci  // void main()
114fd4e5da5Sopenharmony_ci  // {
115fd4e5da5Sopenharmony_ci  //     vec4 v;
116fd4e5da5Sopenharmony_ci  //     if (false)
117fd4e5da5Sopenharmony_ci  //       v = vec4(0.0,0.0,0.0,0.0);
118fd4e5da5Sopenharmony_ci  //     else
119fd4e5da5Sopenharmony_ci  //       v = vec4(1.0,1.0,1.0,1.0);
120fd4e5da5Sopenharmony_ci  //     gl_FragColor = v;
121fd4e5da5Sopenharmony_ci  // }
122fd4e5da5Sopenharmony_ci
123fd4e5da5Sopenharmony_ci  const std::string predefs =
124fd4e5da5Sopenharmony_ci      R"(OpCapability Shader
125fd4e5da5Sopenharmony_ci%1 = OpExtInstImport "GLSL.std.450"
126fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
127fd4e5da5Sopenharmony_ciOpEntryPoint Fragment %main "main" %gl_FragColor %BaseColor
128fd4e5da5Sopenharmony_ciOpExecutionMode %main OriginUpperLeft
129fd4e5da5Sopenharmony_ciOpSource GLSL 140
130fd4e5da5Sopenharmony_ciOpName %main "main"
131fd4e5da5Sopenharmony_ciOpName %v "v"
132fd4e5da5Sopenharmony_ciOpName %gl_FragColor "gl_FragColor"
133fd4e5da5Sopenharmony_ciOpName %BaseColor "BaseColor"
134fd4e5da5Sopenharmony_ci%void = OpTypeVoid
135fd4e5da5Sopenharmony_ci%7 = OpTypeFunction %void
136fd4e5da5Sopenharmony_ci%bool = OpTypeBool
137fd4e5da5Sopenharmony_ci%false = OpConstantFalse %bool
138fd4e5da5Sopenharmony_ci%float = OpTypeFloat 32
139fd4e5da5Sopenharmony_ci%v4float = OpTypeVector %float 4
140fd4e5da5Sopenharmony_ci%_ptr_Function_v4float = OpTypePointer Function %v4float
141fd4e5da5Sopenharmony_ci%float_0 = OpConstant %float 0
142fd4e5da5Sopenharmony_ci%14 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0
143fd4e5da5Sopenharmony_ci%float_1 = OpConstant %float 1
144fd4e5da5Sopenharmony_ci%16 = OpConstantComposite %v4float %float_1 %float_1 %float_1 %float_1
145fd4e5da5Sopenharmony_ci%_ptr_Output_v4float = OpTypePointer Output %v4float
146fd4e5da5Sopenharmony_ci%gl_FragColor = OpVariable %_ptr_Output_v4float Output
147fd4e5da5Sopenharmony_ci%_ptr_Input_v4float = OpTypePointer Input %v4float
148fd4e5da5Sopenharmony_ci%BaseColor = OpVariable %_ptr_Input_v4float Input
149fd4e5da5Sopenharmony_ci)";
150fd4e5da5Sopenharmony_ci
151fd4e5da5Sopenharmony_ci  const std::string before =
152fd4e5da5Sopenharmony_ci      R"(%main = OpFunction %void None %7
153fd4e5da5Sopenharmony_ci%19 = OpLabel
154fd4e5da5Sopenharmony_ci%v = OpVariable %_ptr_Function_v4float Function
155fd4e5da5Sopenharmony_ciOpSelectionMerge %20 None
156fd4e5da5Sopenharmony_ciOpBranchConditional %false %21 %22
157fd4e5da5Sopenharmony_ci%21 = OpLabel
158fd4e5da5Sopenharmony_ciOpStore %v %14
159fd4e5da5Sopenharmony_ciOpBranch %20
160fd4e5da5Sopenharmony_ci%22 = OpLabel
161fd4e5da5Sopenharmony_ciOpStore %v %16
162fd4e5da5Sopenharmony_ciOpBranch %20
163fd4e5da5Sopenharmony_ci%20 = OpLabel
164fd4e5da5Sopenharmony_ci%23 = OpLoad %v4float %v
165fd4e5da5Sopenharmony_ciOpStore %gl_FragColor %23
166fd4e5da5Sopenharmony_ciOpReturn
167fd4e5da5Sopenharmony_ciOpFunctionEnd
168fd4e5da5Sopenharmony_ci)";
169fd4e5da5Sopenharmony_ci
170fd4e5da5Sopenharmony_ci  const std::string after =
171fd4e5da5Sopenharmony_ci      R"(%main = OpFunction %void None %7
172fd4e5da5Sopenharmony_ci%19 = OpLabel
173fd4e5da5Sopenharmony_ci%v = OpVariable %_ptr_Function_v4float Function
174fd4e5da5Sopenharmony_ciOpBranch %22
175fd4e5da5Sopenharmony_ci%22 = OpLabel
176fd4e5da5Sopenharmony_ciOpStore %v %16
177fd4e5da5Sopenharmony_ciOpBranch %20
178fd4e5da5Sopenharmony_ci%20 = OpLabel
179fd4e5da5Sopenharmony_ci%23 = OpLoad %v4float %v
180fd4e5da5Sopenharmony_ciOpStore %gl_FragColor %23
181fd4e5da5Sopenharmony_ciOpReturn
182fd4e5da5Sopenharmony_ciOpFunctionEnd
183fd4e5da5Sopenharmony_ci)";
184fd4e5da5Sopenharmony_ci
185fd4e5da5Sopenharmony_ci  SinglePassRunAndCheck<DeadBranchElimPass>(predefs + before, predefs + after,
186fd4e5da5Sopenharmony_ci                                            true, true);
187fd4e5da5Sopenharmony_ci}
188fd4e5da5Sopenharmony_ci
189fd4e5da5Sopenharmony_ciTEST_F(DeadBranchElimTest, IfThenElseNull) {
190fd4e5da5Sopenharmony_ci  // For booleans OpConstantNull should be treated similar to OpConstantFalse.
191fd4e5da5Sopenharmony_ci  //
192fd4e5da5Sopenharmony_ci  // From the SPIR-V spec:
193fd4e5da5Sopenharmony_ci  // OpConstantNull: Declares a new null constant value.
194fd4e5da5Sopenharmony_ci  // The null value is type dependent, defined as follows:
195fd4e5da5Sopenharmony_ci  // - Scalar Boolean: false
196fd4e5da5Sopenharmony_ci  // ...
197fd4e5da5Sopenharmony_ci
198fd4e5da5Sopenharmony_ci  const std::string predefs =
199fd4e5da5Sopenharmony_ci      R"(OpCapability Shader
200fd4e5da5Sopenharmony_ci%1 = OpExtInstImport "GLSL.std.450"
201fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
202fd4e5da5Sopenharmony_ciOpEntryPoint Fragment %main "main" %gl_FragColor %BaseColor
203fd4e5da5Sopenharmony_ciOpExecutionMode %main OriginUpperLeft
204fd4e5da5Sopenharmony_ciOpSource GLSL 140
205fd4e5da5Sopenharmony_ciOpName %main "main"
206fd4e5da5Sopenharmony_ciOpName %v "v"
207fd4e5da5Sopenharmony_ciOpName %gl_FragColor "gl_FragColor"
208fd4e5da5Sopenharmony_ciOpName %BaseColor "BaseColor"
209fd4e5da5Sopenharmony_ci%void = OpTypeVoid
210fd4e5da5Sopenharmony_ci%7 = OpTypeFunction %void
211fd4e5da5Sopenharmony_ci%bool = OpTypeBool
212fd4e5da5Sopenharmony_ci%9 = OpConstantNull %bool
213fd4e5da5Sopenharmony_ci%float = OpTypeFloat 32
214fd4e5da5Sopenharmony_ci%v4float = OpTypeVector %float 4
215fd4e5da5Sopenharmony_ci%_ptr_Function_v4float = OpTypePointer Function %v4float
216fd4e5da5Sopenharmony_ci%float_0 = OpConstant %float 0
217fd4e5da5Sopenharmony_ci%14 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0
218fd4e5da5Sopenharmony_ci%float_1 = OpConstant %float 1
219fd4e5da5Sopenharmony_ci%16 = OpConstantComposite %v4float %float_1 %float_1 %float_1 %float_1
220fd4e5da5Sopenharmony_ci%_ptr_Output_v4float = OpTypePointer Output %v4float
221fd4e5da5Sopenharmony_ci%gl_FragColor = OpVariable %_ptr_Output_v4float Output
222fd4e5da5Sopenharmony_ci%_ptr_Input_v4float = OpTypePointer Input %v4float
223fd4e5da5Sopenharmony_ci%BaseColor = OpVariable %_ptr_Input_v4float Input
224fd4e5da5Sopenharmony_ci)";
225fd4e5da5Sopenharmony_ci
226fd4e5da5Sopenharmony_ci  const std::string before =
227fd4e5da5Sopenharmony_ci      R"(%main = OpFunction %void None %7
228fd4e5da5Sopenharmony_ci%19 = OpLabel
229fd4e5da5Sopenharmony_ci%v = OpVariable %_ptr_Function_v4float Function
230fd4e5da5Sopenharmony_ciOpSelectionMerge %20 None
231fd4e5da5Sopenharmony_ciOpBranchConditional %9 %21 %22
232fd4e5da5Sopenharmony_ci%21 = OpLabel
233fd4e5da5Sopenharmony_ciOpStore %v %14
234fd4e5da5Sopenharmony_ciOpBranch %20
235fd4e5da5Sopenharmony_ci%22 = OpLabel
236fd4e5da5Sopenharmony_ciOpStore %v %16
237fd4e5da5Sopenharmony_ciOpBranch %20
238fd4e5da5Sopenharmony_ci%20 = OpLabel
239fd4e5da5Sopenharmony_ci%23 = OpLoad %v4float %v
240fd4e5da5Sopenharmony_ciOpStore %gl_FragColor %23
241fd4e5da5Sopenharmony_ciOpReturn
242fd4e5da5Sopenharmony_ciOpFunctionEnd
243fd4e5da5Sopenharmony_ci)";
244fd4e5da5Sopenharmony_ci
245fd4e5da5Sopenharmony_ci  const std::string after =
246fd4e5da5Sopenharmony_ci      R"(%main = OpFunction %void None %7
247fd4e5da5Sopenharmony_ci%19 = OpLabel
248fd4e5da5Sopenharmony_ci%v = OpVariable %_ptr_Function_v4float Function
249fd4e5da5Sopenharmony_ciOpBranch %22
250fd4e5da5Sopenharmony_ci%22 = OpLabel
251fd4e5da5Sopenharmony_ciOpStore %v %16
252fd4e5da5Sopenharmony_ciOpBranch %20
253fd4e5da5Sopenharmony_ci%20 = OpLabel
254fd4e5da5Sopenharmony_ci%23 = OpLoad %v4float %v
255fd4e5da5Sopenharmony_ciOpStore %gl_FragColor %23
256fd4e5da5Sopenharmony_ciOpReturn
257fd4e5da5Sopenharmony_ciOpFunctionEnd
258fd4e5da5Sopenharmony_ci)";
259fd4e5da5Sopenharmony_ci
260fd4e5da5Sopenharmony_ci  SinglePassRunAndCheck<DeadBranchElimPass>(predefs + before, predefs + after,
261fd4e5da5Sopenharmony_ci                                            true, true);
262fd4e5da5Sopenharmony_ci}
263fd4e5da5Sopenharmony_ci
264fd4e5da5Sopenharmony_ciTEST_F(DeadBranchElimTest, IfThenTrue) {
265fd4e5da5Sopenharmony_ci  // #version 140
266fd4e5da5Sopenharmony_ci  //
267fd4e5da5Sopenharmony_ci  // in vec4 BaseColor;
268fd4e5da5Sopenharmony_ci  //
269fd4e5da5Sopenharmony_ci  // void main()
270fd4e5da5Sopenharmony_ci  // {
271fd4e5da5Sopenharmony_ci  //     vec4 v = BaseColor;
272fd4e5da5Sopenharmony_ci  //     if (true)
273fd4e5da5Sopenharmony_ci  //       v = v * vec4(0.5,0.5,0.5,0.5);
274fd4e5da5Sopenharmony_ci  //     gl_FragColor = v;
275fd4e5da5Sopenharmony_ci  // }
276fd4e5da5Sopenharmony_ci
277fd4e5da5Sopenharmony_ci  const std::string predefs =
278fd4e5da5Sopenharmony_ci      R"(OpCapability Shader
279fd4e5da5Sopenharmony_ci%1 = OpExtInstImport "GLSL.std.450"
280fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
281fd4e5da5Sopenharmony_ciOpEntryPoint Fragment %main "main" %BaseColor %gl_FragColor
282fd4e5da5Sopenharmony_ciOpExecutionMode %main OriginUpperLeft
283fd4e5da5Sopenharmony_ciOpSource GLSL 140
284fd4e5da5Sopenharmony_ciOpName %main "main"
285fd4e5da5Sopenharmony_ciOpName %v "v"
286fd4e5da5Sopenharmony_ciOpName %BaseColor "BaseColor"
287fd4e5da5Sopenharmony_ciOpName %gl_FragColor "gl_FragColor"
288fd4e5da5Sopenharmony_ci%void = OpTypeVoid
289fd4e5da5Sopenharmony_ci%7 = OpTypeFunction %void
290fd4e5da5Sopenharmony_ci%float = OpTypeFloat 32
291fd4e5da5Sopenharmony_ci%v4float = OpTypeVector %float 4
292fd4e5da5Sopenharmony_ci%_ptr_Function_v4float = OpTypePointer Function %v4float
293fd4e5da5Sopenharmony_ci%_ptr_Input_v4float = OpTypePointer Input %v4float
294fd4e5da5Sopenharmony_ci%BaseColor = OpVariable %_ptr_Input_v4float Input
295fd4e5da5Sopenharmony_ci%bool = OpTypeBool
296fd4e5da5Sopenharmony_ci%true = OpConstantTrue %bool
297fd4e5da5Sopenharmony_ci%float_0_5 = OpConstant %float 0.5
298fd4e5da5Sopenharmony_ci%15 = OpConstantComposite %v4float %float_0_5 %float_0_5 %float_0_5 %float_0_5
299fd4e5da5Sopenharmony_ci%_ptr_Output_v4float = OpTypePointer Output %v4float
300fd4e5da5Sopenharmony_ci%gl_FragColor = OpVariable %_ptr_Output_v4float Output
301fd4e5da5Sopenharmony_ci)";
302fd4e5da5Sopenharmony_ci
303fd4e5da5Sopenharmony_ci  const std::string before =
304fd4e5da5Sopenharmony_ci      R"(%main = OpFunction %void None %7
305fd4e5da5Sopenharmony_ci%17 = OpLabel
306fd4e5da5Sopenharmony_ci%v = OpVariable %_ptr_Function_v4float Function
307fd4e5da5Sopenharmony_ci%18 = OpLoad %v4float %BaseColor
308fd4e5da5Sopenharmony_ciOpStore %v %18
309fd4e5da5Sopenharmony_ciOpSelectionMerge %19 None
310fd4e5da5Sopenharmony_ciOpBranchConditional %true %20 %19
311fd4e5da5Sopenharmony_ci%20 = OpLabel
312fd4e5da5Sopenharmony_ci%21 = OpLoad %v4float %v
313fd4e5da5Sopenharmony_ci%22 = OpFMul %v4float %21 %15
314fd4e5da5Sopenharmony_ciOpStore %v %22
315fd4e5da5Sopenharmony_ciOpBranch %19
316fd4e5da5Sopenharmony_ci%19 = OpLabel
317fd4e5da5Sopenharmony_ci%23 = OpLoad %v4float %v
318fd4e5da5Sopenharmony_ciOpStore %gl_FragColor %23
319fd4e5da5Sopenharmony_ciOpReturn
320fd4e5da5Sopenharmony_ciOpFunctionEnd
321fd4e5da5Sopenharmony_ci)";
322fd4e5da5Sopenharmony_ci
323fd4e5da5Sopenharmony_ci  const std::string after =
324fd4e5da5Sopenharmony_ci      R"(%main = OpFunction %void None %7
325fd4e5da5Sopenharmony_ci%17 = OpLabel
326fd4e5da5Sopenharmony_ci%v = OpVariable %_ptr_Function_v4float Function
327fd4e5da5Sopenharmony_ci%18 = OpLoad %v4float %BaseColor
328fd4e5da5Sopenharmony_ciOpStore %v %18
329fd4e5da5Sopenharmony_ciOpBranch %20
330fd4e5da5Sopenharmony_ci%20 = OpLabel
331fd4e5da5Sopenharmony_ci%21 = OpLoad %v4float %v
332fd4e5da5Sopenharmony_ci%22 = OpFMul %v4float %21 %15
333fd4e5da5Sopenharmony_ciOpStore %v %22
334fd4e5da5Sopenharmony_ciOpBranch %19
335fd4e5da5Sopenharmony_ci%19 = OpLabel
336fd4e5da5Sopenharmony_ci%23 = OpLoad %v4float %v
337fd4e5da5Sopenharmony_ciOpStore %gl_FragColor %23
338fd4e5da5Sopenharmony_ciOpReturn
339fd4e5da5Sopenharmony_ciOpFunctionEnd
340fd4e5da5Sopenharmony_ci)";
341fd4e5da5Sopenharmony_ci
342fd4e5da5Sopenharmony_ci  SinglePassRunAndCheck<DeadBranchElimPass>(predefs + before, predefs + after,
343fd4e5da5Sopenharmony_ci                                            true, true);
344fd4e5da5Sopenharmony_ci}
345fd4e5da5Sopenharmony_ci
346fd4e5da5Sopenharmony_ciTEST_F(DeadBranchElimTest, IfThenFalse) {
347fd4e5da5Sopenharmony_ci  // #version 140
348fd4e5da5Sopenharmony_ci  //
349fd4e5da5Sopenharmony_ci  // in vec4 BaseColor;
350fd4e5da5Sopenharmony_ci  //
351fd4e5da5Sopenharmony_ci  // void main()
352fd4e5da5Sopenharmony_ci  // {
353fd4e5da5Sopenharmony_ci  //     vec4 v = BaseColor;
354fd4e5da5Sopenharmony_ci  //     if (false)
355fd4e5da5Sopenharmony_ci  //       v = v * vec4(0.5,0.5,0.5,0.5);
356fd4e5da5Sopenharmony_ci  //     gl_FragColor = v;
357fd4e5da5Sopenharmony_ci  // }
358fd4e5da5Sopenharmony_ci
359fd4e5da5Sopenharmony_ci  const std::string predefs =
360fd4e5da5Sopenharmony_ci      R"(OpCapability Shader
361fd4e5da5Sopenharmony_ci%1 = OpExtInstImport "GLSL.std.450"
362fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
363fd4e5da5Sopenharmony_ciOpEntryPoint Fragment %main "main" %BaseColor %gl_FragColor
364fd4e5da5Sopenharmony_ciOpExecutionMode %main OriginUpperLeft
365fd4e5da5Sopenharmony_ciOpSource GLSL 140
366fd4e5da5Sopenharmony_ciOpName %main "main"
367fd4e5da5Sopenharmony_ciOpName %v "v"
368fd4e5da5Sopenharmony_ciOpName %BaseColor "BaseColor"
369fd4e5da5Sopenharmony_ciOpName %gl_FragColor "gl_FragColor"
370fd4e5da5Sopenharmony_ci%void = OpTypeVoid
371fd4e5da5Sopenharmony_ci%7 = OpTypeFunction %void
372fd4e5da5Sopenharmony_ci%float = OpTypeFloat 32
373fd4e5da5Sopenharmony_ci%v4float = OpTypeVector %float 4
374fd4e5da5Sopenharmony_ci%_ptr_Function_v4float = OpTypePointer Function %v4float
375fd4e5da5Sopenharmony_ci%_ptr_Input_v4float = OpTypePointer Input %v4float
376fd4e5da5Sopenharmony_ci%BaseColor = OpVariable %_ptr_Input_v4float Input
377fd4e5da5Sopenharmony_ci%bool = OpTypeBool
378fd4e5da5Sopenharmony_ci%false = OpConstantFalse %bool
379fd4e5da5Sopenharmony_ci%float_0_5 = OpConstant %float 0.5
380fd4e5da5Sopenharmony_ci%15 = OpConstantComposite %v4float %float_0_5 %float_0_5 %float_0_5 %float_0_5
381fd4e5da5Sopenharmony_ci%_ptr_Output_v4float = OpTypePointer Output %v4float
382fd4e5da5Sopenharmony_ci%gl_FragColor = OpVariable %_ptr_Output_v4float Output
383fd4e5da5Sopenharmony_ci)";
384fd4e5da5Sopenharmony_ci
385fd4e5da5Sopenharmony_ci  const std::string before =
386fd4e5da5Sopenharmony_ci      R"(%main = OpFunction %void None %7
387fd4e5da5Sopenharmony_ci%17 = OpLabel
388fd4e5da5Sopenharmony_ci%v = OpVariable %_ptr_Function_v4float Function
389fd4e5da5Sopenharmony_ci%18 = OpLoad %v4float %BaseColor
390fd4e5da5Sopenharmony_ciOpStore %v %18
391fd4e5da5Sopenharmony_ciOpSelectionMerge %19 None
392fd4e5da5Sopenharmony_ciOpBranchConditional %false %20 %19
393fd4e5da5Sopenharmony_ci%20 = OpLabel
394fd4e5da5Sopenharmony_ci%21 = OpLoad %v4float %v
395fd4e5da5Sopenharmony_ci%22 = OpFMul %v4float %21 %15
396fd4e5da5Sopenharmony_ciOpStore %v %22
397fd4e5da5Sopenharmony_ciOpBranch %19
398fd4e5da5Sopenharmony_ci%19 = OpLabel
399fd4e5da5Sopenharmony_ci%23 = OpLoad %v4float %v
400fd4e5da5Sopenharmony_ciOpStore %gl_FragColor %23
401fd4e5da5Sopenharmony_ciOpReturn
402fd4e5da5Sopenharmony_ciOpFunctionEnd
403fd4e5da5Sopenharmony_ci)";
404fd4e5da5Sopenharmony_ci
405fd4e5da5Sopenharmony_ci  const std::string after =
406fd4e5da5Sopenharmony_ci      R"(%main = OpFunction %void None %7
407fd4e5da5Sopenharmony_ci%17 = OpLabel
408fd4e5da5Sopenharmony_ci%v = OpVariable %_ptr_Function_v4float Function
409fd4e5da5Sopenharmony_ci%18 = OpLoad %v4float %BaseColor
410fd4e5da5Sopenharmony_ciOpStore %v %18
411fd4e5da5Sopenharmony_ciOpBranch %19
412fd4e5da5Sopenharmony_ci%19 = OpLabel
413fd4e5da5Sopenharmony_ci%23 = OpLoad %v4float %v
414fd4e5da5Sopenharmony_ciOpStore %gl_FragColor %23
415fd4e5da5Sopenharmony_ciOpReturn
416fd4e5da5Sopenharmony_ciOpFunctionEnd
417fd4e5da5Sopenharmony_ci)";
418fd4e5da5Sopenharmony_ci
419fd4e5da5Sopenharmony_ci  SinglePassRunAndCheck<DeadBranchElimPass>(predefs + before, predefs + after,
420fd4e5da5Sopenharmony_ci                                            true, true);
421fd4e5da5Sopenharmony_ci}
422fd4e5da5Sopenharmony_ci
423fd4e5da5Sopenharmony_ciTEST_F(DeadBranchElimTest, IfThenElsePhiTrue) {
424fd4e5da5Sopenharmony_ci  // Test handling of phi in merge block after dead branch elimination.
425fd4e5da5Sopenharmony_ci  // Note: The SPIR-V has had store/load elimination and phi insertion
426fd4e5da5Sopenharmony_ci  //
427fd4e5da5Sopenharmony_ci  // #version 140
428fd4e5da5Sopenharmony_ci  //
429fd4e5da5Sopenharmony_ci  // void main()
430fd4e5da5Sopenharmony_ci  // {
431fd4e5da5Sopenharmony_ci  //     vec4 v;
432fd4e5da5Sopenharmony_ci  //     if (true)
433fd4e5da5Sopenharmony_ci  //       v = vec4(0.0,0.0,0.0,0.0);
434fd4e5da5Sopenharmony_ci  //     else
435fd4e5da5Sopenharmony_ci  //       v = vec4(1.0,1.0,1.0,1.0);
436fd4e5da5Sopenharmony_ci  //     gl_FragColor = v;
437fd4e5da5Sopenharmony_ci  // }
438fd4e5da5Sopenharmony_ci
439fd4e5da5Sopenharmony_ci  const std::string predefs =
440fd4e5da5Sopenharmony_ci      R"(OpCapability Shader
441fd4e5da5Sopenharmony_ci%1 = OpExtInstImport "GLSL.std.450"
442fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
443fd4e5da5Sopenharmony_ciOpEntryPoint Fragment %main "main" %gl_FragColor
444fd4e5da5Sopenharmony_ciOpExecutionMode %main OriginUpperLeft
445fd4e5da5Sopenharmony_ciOpSource GLSL 140
446fd4e5da5Sopenharmony_ciOpName %main "main"
447fd4e5da5Sopenharmony_ciOpName %gl_FragColor "gl_FragColor"
448fd4e5da5Sopenharmony_ci%void = OpTypeVoid
449fd4e5da5Sopenharmony_ci%5 = OpTypeFunction %void
450fd4e5da5Sopenharmony_ci%bool = OpTypeBool
451fd4e5da5Sopenharmony_ci%true = OpConstantTrue %bool
452fd4e5da5Sopenharmony_ci%float = OpTypeFloat 32
453fd4e5da5Sopenharmony_ci%v4float = OpTypeVector %float 4
454fd4e5da5Sopenharmony_ci%_ptr_Function_v4float = OpTypePointer Function %v4float
455fd4e5da5Sopenharmony_ci%float_0 = OpConstant %float 0
456fd4e5da5Sopenharmony_ci%12 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0
457fd4e5da5Sopenharmony_ci%float_1 = OpConstant %float 1
458fd4e5da5Sopenharmony_ci%14 = OpConstantComposite %v4float %float_1 %float_1 %float_1 %float_1
459fd4e5da5Sopenharmony_ci%_ptr_Output_v4float = OpTypePointer Output %v4float
460fd4e5da5Sopenharmony_ci%gl_FragColor = OpVariable %_ptr_Output_v4float Output
461fd4e5da5Sopenharmony_ci%_ptr_Input_v4float = OpTypePointer Input %v4float
462fd4e5da5Sopenharmony_ci)";
463fd4e5da5Sopenharmony_ci
464fd4e5da5Sopenharmony_ci  const std::string before =
465fd4e5da5Sopenharmony_ci      R"(%main = OpFunction %void None %5
466fd4e5da5Sopenharmony_ci%17 = OpLabel
467fd4e5da5Sopenharmony_ciOpSelectionMerge %18 None
468fd4e5da5Sopenharmony_ciOpBranchConditional %true %19 %20
469fd4e5da5Sopenharmony_ci%19 = OpLabel
470fd4e5da5Sopenharmony_ciOpBranch %18
471fd4e5da5Sopenharmony_ci%20 = OpLabel
472fd4e5da5Sopenharmony_ciOpBranch %18
473fd4e5da5Sopenharmony_ci%18 = OpLabel
474fd4e5da5Sopenharmony_ci%21 = OpPhi %v4float %12 %19 %14 %20
475fd4e5da5Sopenharmony_ciOpStore %gl_FragColor %21
476fd4e5da5Sopenharmony_ciOpReturn
477fd4e5da5Sopenharmony_ciOpFunctionEnd
478fd4e5da5Sopenharmony_ci)";
479fd4e5da5Sopenharmony_ci
480fd4e5da5Sopenharmony_ci  const std::string after =
481fd4e5da5Sopenharmony_ci      R"(%main = OpFunction %void None %5
482fd4e5da5Sopenharmony_ci%17 = OpLabel
483fd4e5da5Sopenharmony_ciOpBranch %19
484fd4e5da5Sopenharmony_ci%19 = OpLabel
485fd4e5da5Sopenharmony_ciOpBranch %18
486fd4e5da5Sopenharmony_ci%18 = OpLabel
487fd4e5da5Sopenharmony_ciOpStore %gl_FragColor %12
488fd4e5da5Sopenharmony_ciOpReturn
489fd4e5da5Sopenharmony_ciOpFunctionEnd
490fd4e5da5Sopenharmony_ci)";
491fd4e5da5Sopenharmony_ci
492fd4e5da5Sopenharmony_ci  SinglePassRunAndCheck<DeadBranchElimPass>(predefs + before, predefs + after,
493fd4e5da5Sopenharmony_ci                                            true, true);
494fd4e5da5Sopenharmony_ci}
495fd4e5da5Sopenharmony_ci
496fd4e5da5Sopenharmony_ciTEST_F(DeadBranchElimTest, IfThenElsePhiFalse) {
497fd4e5da5Sopenharmony_ci  // Test handling of phi in merge block after dead branch elimination.
498fd4e5da5Sopenharmony_ci  // Note: The SPIR-V has had store/load elimination and phi insertion
499fd4e5da5Sopenharmony_ci  //
500fd4e5da5Sopenharmony_ci  // #version 140
501fd4e5da5Sopenharmony_ci  //
502fd4e5da5Sopenharmony_ci  // void main()
503fd4e5da5Sopenharmony_ci  // {
504fd4e5da5Sopenharmony_ci  //     vec4 v;
505fd4e5da5Sopenharmony_ci  //     if (true)
506fd4e5da5Sopenharmony_ci  //       v = vec4(0.0,0.0,0.0,0.0);
507fd4e5da5Sopenharmony_ci  //     else
508fd4e5da5Sopenharmony_ci  //       v = vec4(1.0,1.0,1.0,1.0);
509fd4e5da5Sopenharmony_ci  //     gl_FragColor = v;
510fd4e5da5Sopenharmony_ci  // }
511fd4e5da5Sopenharmony_ci
512fd4e5da5Sopenharmony_ci  const std::string predefs =
513fd4e5da5Sopenharmony_ci      R"(OpCapability Shader
514fd4e5da5Sopenharmony_ci%1 = OpExtInstImport "GLSL.std.450"
515fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
516fd4e5da5Sopenharmony_ciOpEntryPoint Fragment %main "main" %gl_FragColor
517fd4e5da5Sopenharmony_ciOpExecutionMode %main OriginUpperLeft
518fd4e5da5Sopenharmony_ciOpSource GLSL 140
519fd4e5da5Sopenharmony_ciOpName %main "main"
520fd4e5da5Sopenharmony_ciOpName %gl_FragColor "gl_FragColor"
521fd4e5da5Sopenharmony_ci%void = OpTypeVoid
522fd4e5da5Sopenharmony_ci%5 = OpTypeFunction %void
523fd4e5da5Sopenharmony_ci%bool = OpTypeBool
524fd4e5da5Sopenharmony_ci%false = OpConstantFalse %bool
525fd4e5da5Sopenharmony_ci%float = OpTypeFloat 32
526fd4e5da5Sopenharmony_ci%v4float = OpTypeVector %float 4
527fd4e5da5Sopenharmony_ci%_ptr_Function_v4float = OpTypePointer Function %v4float
528fd4e5da5Sopenharmony_ci%float_0 = OpConstant %float 0
529fd4e5da5Sopenharmony_ci%12 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0
530fd4e5da5Sopenharmony_ci%float_1 = OpConstant %float 1
531fd4e5da5Sopenharmony_ci%14 = OpConstantComposite %v4float %float_1 %float_1 %float_1 %float_1
532fd4e5da5Sopenharmony_ci%_ptr_Output_v4float = OpTypePointer Output %v4float
533fd4e5da5Sopenharmony_ci%gl_FragColor = OpVariable %_ptr_Output_v4float Output
534fd4e5da5Sopenharmony_ci%_ptr_Input_v4float = OpTypePointer Input %v4float
535fd4e5da5Sopenharmony_ci)";
536fd4e5da5Sopenharmony_ci
537fd4e5da5Sopenharmony_ci  const std::string before =
538fd4e5da5Sopenharmony_ci      R"(%main = OpFunction %void None %5
539fd4e5da5Sopenharmony_ci%17 = OpLabel
540fd4e5da5Sopenharmony_ciOpSelectionMerge %18 None
541fd4e5da5Sopenharmony_ciOpBranchConditional %false %19 %20
542fd4e5da5Sopenharmony_ci%19 = OpLabel
543fd4e5da5Sopenharmony_ciOpBranch %18
544fd4e5da5Sopenharmony_ci%20 = OpLabel
545fd4e5da5Sopenharmony_ciOpBranch %18
546fd4e5da5Sopenharmony_ci%18 = OpLabel
547fd4e5da5Sopenharmony_ci%21 = OpPhi %v4float %12 %19 %14 %20
548fd4e5da5Sopenharmony_ciOpStore %gl_FragColor %21
549fd4e5da5Sopenharmony_ciOpReturn
550fd4e5da5Sopenharmony_ciOpFunctionEnd
551fd4e5da5Sopenharmony_ci)";
552fd4e5da5Sopenharmony_ci
553fd4e5da5Sopenharmony_ci  const std::string after =
554fd4e5da5Sopenharmony_ci      R"(%main = OpFunction %void None %5
555fd4e5da5Sopenharmony_ci%17 = OpLabel
556fd4e5da5Sopenharmony_ciOpBranch %20
557fd4e5da5Sopenharmony_ci%20 = OpLabel
558fd4e5da5Sopenharmony_ciOpBranch %18
559fd4e5da5Sopenharmony_ci%18 = OpLabel
560fd4e5da5Sopenharmony_ciOpStore %gl_FragColor %14
561fd4e5da5Sopenharmony_ciOpReturn
562fd4e5da5Sopenharmony_ciOpFunctionEnd
563fd4e5da5Sopenharmony_ci)";
564fd4e5da5Sopenharmony_ci
565fd4e5da5Sopenharmony_ci  SinglePassRunAndCheck<DeadBranchElimPass>(predefs + before, predefs + after,
566fd4e5da5Sopenharmony_ci                                            true, true);
567fd4e5da5Sopenharmony_ci}
568fd4e5da5Sopenharmony_ci
569fd4e5da5Sopenharmony_ciTEST_F(DeadBranchElimTest, CompoundIfThenElseFalse) {
570fd4e5da5Sopenharmony_ci  // #version 140
571fd4e5da5Sopenharmony_ci  //
572fd4e5da5Sopenharmony_ci  // layout(std140) uniform U_t
573fd4e5da5Sopenharmony_ci  // {
574fd4e5da5Sopenharmony_ci  //     bool g_B ;
575fd4e5da5Sopenharmony_ci  // } ;
576fd4e5da5Sopenharmony_ci  //
577fd4e5da5Sopenharmony_ci  // void main()
578fd4e5da5Sopenharmony_ci  // {
579fd4e5da5Sopenharmony_ci  //     vec4 v;
580fd4e5da5Sopenharmony_ci  //     if (false) {
581fd4e5da5Sopenharmony_ci  //       if (g_B)
582fd4e5da5Sopenharmony_ci  //         v = vec4(0.0,0.0,0.0,0.0);
583fd4e5da5Sopenharmony_ci  //       else
584fd4e5da5Sopenharmony_ci  //         v = vec4(1.0,1.0,1.0,1.0);
585fd4e5da5Sopenharmony_ci  //     } else {
586fd4e5da5Sopenharmony_ci  //       if (g_B)
587fd4e5da5Sopenharmony_ci  //         v = vec4(1.0,1.0,1.0,1.0);
588fd4e5da5Sopenharmony_ci  //       else
589fd4e5da5Sopenharmony_ci  //         v = vec4(0.0,0.0,0.0,0.0);
590fd4e5da5Sopenharmony_ci  //     }
591fd4e5da5Sopenharmony_ci  //     gl_FragColor = v;
592fd4e5da5Sopenharmony_ci  // }
593fd4e5da5Sopenharmony_ci
594fd4e5da5Sopenharmony_ci  const std::string predefs =
595fd4e5da5Sopenharmony_ci      R"(OpCapability Shader
596fd4e5da5Sopenharmony_ci%1 = OpExtInstImport "GLSL.std.450"
597fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
598fd4e5da5Sopenharmony_ciOpEntryPoint Fragment %main "main" %gl_FragColor
599fd4e5da5Sopenharmony_ciOpExecutionMode %main OriginUpperLeft
600fd4e5da5Sopenharmony_ciOpSource GLSL 140
601fd4e5da5Sopenharmony_ciOpName %main "main"
602fd4e5da5Sopenharmony_ciOpName %U_t "U_t"
603fd4e5da5Sopenharmony_ciOpMemberName %U_t 0 "g_B"
604fd4e5da5Sopenharmony_ciOpName %_ ""
605fd4e5da5Sopenharmony_ciOpName %v "v"
606fd4e5da5Sopenharmony_ciOpName %gl_FragColor "gl_FragColor"
607fd4e5da5Sopenharmony_ciOpMemberDecorate %U_t 0 Offset 0
608fd4e5da5Sopenharmony_ciOpDecorate %U_t Block
609fd4e5da5Sopenharmony_ciOpDecorate %_ DescriptorSet 0
610fd4e5da5Sopenharmony_ci%void = OpTypeVoid
611fd4e5da5Sopenharmony_ci%8 = OpTypeFunction %void
612fd4e5da5Sopenharmony_ci%bool = OpTypeBool
613fd4e5da5Sopenharmony_ci%false = OpConstantFalse %bool
614fd4e5da5Sopenharmony_ci%uint = OpTypeInt 32 0
615fd4e5da5Sopenharmony_ci%U_t = OpTypeStruct %uint
616fd4e5da5Sopenharmony_ci%_ptr_Uniform_U_t = OpTypePointer Uniform %U_t
617fd4e5da5Sopenharmony_ci%_ = OpVariable %_ptr_Uniform_U_t Uniform
618fd4e5da5Sopenharmony_ci%int = OpTypeInt 32 1
619fd4e5da5Sopenharmony_ci%int_0 = OpConstant %int 0
620fd4e5da5Sopenharmony_ci%_ptr_Uniform_uint = OpTypePointer Uniform %uint
621fd4e5da5Sopenharmony_ci%uint_0 = OpConstant %uint 0
622fd4e5da5Sopenharmony_ci%float = OpTypeFloat 32
623fd4e5da5Sopenharmony_ci%v4float = OpTypeVector %float 4
624fd4e5da5Sopenharmony_ci%_ptr_Function_v4float = OpTypePointer Function %v4float
625fd4e5da5Sopenharmony_ci%float_0 = OpConstant %float 0
626fd4e5da5Sopenharmony_ci%21 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0
627fd4e5da5Sopenharmony_ci%float_1 = OpConstant %float 1
628fd4e5da5Sopenharmony_ci%23 = OpConstantComposite %v4float %float_1 %float_1 %float_1 %float_1
629fd4e5da5Sopenharmony_ci%_ptr_Output_v4float = OpTypePointer Output %v4float
630fd4e5da5Sopenharmony_ci%gl_FragColor = OpVariable %_ptr_Output_v4float Output
631fd4e5da5Sopenharmony_ci)";
632fd4e5da5Sopenharmony_ci
633fd4e5da5Sopenharmony_ci  const std::string before =
634fd4e5da5Sopenharmony_ci      R"(%main = OpFunction %void None %8
635fd4e5da5Sopenharmony_ci%25 = OpLabel
636fd4e5da5Sopenharmony_ci%v = OpVariable %_ptr_Function_v4float Function
637fd4e5da5Sopenharmony_ciOpSelectionMerge %26 None
638fd4e5da5Sopenharmony_ciOpBranchConditional %false %27 %28
639fd4e5da5Sopenharmony_ci%27 = OpLabel
640fd4e5da5Sopenharmony_ci%29 = OpAccessChain %_ptr_Uniform_uint %_ %int_0
641fd4e5da5Sopenharmony_ci%30 = OpLoad %uint %29
642fd4e5da5Sopenharmony_ci%31 = OpINotEqual %bool %30 %uint_0
643fd4e5da5Sopenharmony_ciOpSelectionMerge %32 None
644fd4e5da5Sopenharmony_ciOpBranchConditional %31 %33 %34
645fd4e5da5Sopenharmony_ci%33 = OpLabel
646fd4e5da5Sopenharmony_ciOpStore %v %21
647fd4e5da5Sopenharmony_ciOpBranch %32
648fd4e5da5Sopenharmony_ci%34 = OpLabel
649fd4e5da5Sopenharmony_ciOpStore %v %23
650fd4e5da5Sopenharmony_ciOpBranch %32
651fd4e5da5Sopenharmony_ci%32 = OpLabel
652fd4e5da5Sopenharmony_ciOpBranch %26
653fd4e5da5Sopenharmony_ci%28 = OpLabel
654fd4e5da5Sopenharmony_ci%35 = OpAccessChain %_ptr_Uniform_uint %_ %int_0
655fd4e5da5Sopenharmony_ci%36 = OpLoad %uint %35
656fd4e5da5Sopenharmony_ci%37 = OpINotEqual %bool %36 %uint_0
657fd4e5da5Sopenharmony_ciOpSelectionMerge %38 None
658fd4e5da5Sopenharmony_ciOpBranchConditional %37 %39 %40
659fd4e5da5Sopenharmony_ci%39 = OpLabel
660fd4e5da5Sopenharmony_ciOpStore %v %23
661fd4e5da5Sopenharmony_ciOpBranch %38
662fd4e5da5Sopenharmony_ci%40 = OpLabel
663fd4e5da5Sopenharmony_ciOpStore %v %21
664fd4e5da5Sopenharmony_ciOpBranch %38
665fd4e5da5Sopenharmony_ci%38 = OpLabel
666fd4e5da5Sopenharmony_ciOpBranch %26
667fd4e5da5Sopenharmony_ci%26 = OpLabel
668fd4e5da5Sopenharmony_ci%41 = OpLoad %v4float %v
669fd4e5da5Sopenharmony_ciOpStore %gl_FragColor %41
670fd4e5da5Sopenharmony_ciOpReturn
671fd4e5da5Sopenharmony_ciOpFunctionEnd
672fd4e5da5Sopenharmony_ci)";
673fd4e5da5Sopenharmony_ci
674fd4e5da5Sopenharmony_ci  const std::string after =
675fd4e5da5Sopenharmony_ci      R"(%main = OpFunction %void None %8
676fd4e5da5Sopenharmony_ci%25 = OpLabel
677fd4e5da5Sopenharmony_ci%v = OpVariable %_ptr_Function_v4float Function
678fd4e5da5Sopenharmony_ciOpBranch %28
679fd4e5da5Sopenharmony_ci%28 = OpLabel
680fd4e5da5Sopenharmony_ci%35 = OpAccessChain %_ptr_Uniform_uint %_ %int_0
681fd4e5da5Sopenharmony_ci%36 = OpLoad %uint %35
682fd4e5da5Sopenharmony_ci%37 = OpINotEqual %bool %36 %uint_0
683fd4e5da5Sopenharmony_ciOpSelectionMerge %38 None
684fd4e5da5Sopenharmony_ciOpBranchConditional %37 %39 %40
685fd4e5da5Sopenharmony_ci%40 = OpLabel
686fd4e5da5Sopenharmony_ciOpStore %v %21
687fd4e5da5Sopenharmony_ciOpBranch %38
688fd4e5da5Sopenharmony_ci%39 = OpLabel
689fd4e5da5Sopenharmony_ciOpStore %v %23
690fd4e5da5Sopenharmony_ciOpBranch %38
691fd4e5da5Sopenharmony_ci%38 = OpLabel
692fd4e5da5Sopenharmony_ciOpBranch %26
693fd4e5da5Sopenharmony_ci%26 = OpLabel
694fd4e5da5Sopenharmony_ci%41 = OpLoad %v4float %v
695fd4e5da5Sopenharmony_ciOpStore %gl_FragColor %41
696fd4e5da5Sopenharmony_ciOpReturn
697fd4e5da5Sopenharmony_ciOpFunctionEnd
698fd4e5da5Sopenharmony_ci)";
699fd4e5da5Sopenharmony_ci
700fd4e5da5Sopenharmony_ci  SinglePassRunAndCheck<DeadBranchElimPass>(predefs + before, predefs + after,
701fd4e5da5Sopenharmony_ci                                            true, true);
702fd4e5da5Sopenharmony_ci}
703fd4e5da5Sopenharmony_ci
704fd4e5da5Sopenharmony_ciTEST_F(DeadBranchElimTest, PreventOrphanMerge) {
705fd4e5da5Sopenharmony_ci  const std::string predefs =
706fd4e5da5Sopenharmony_ci      R"(OpCapability Shader
707fd4e5da5Sopenharmony_ci%1 = OpExtInstImport "GLSL.std.450"
708fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
709fd4e5da5Sopenharmony_ciOpEntryPoint Fragment %main "main" %BaseColor %gl_FragColor
710fd4e5da5Sopenharmony_ciOpExecutionMode %main OriginUpperLeft
711fd4e5da5Sopenharmony_ciOpSource GLSL 140
712fd4e5da5Sopenharmony_ciOpName %main "main"
713fd4e5da5Sopenharmony_ciOpName %v "v"
714fd4e5da5Sopenharmony_ciOpName %BaseColor "BaseColor"
715fd4e5da5Sopenharmony_ciOpName %gl_FragColor "gl_FragColor"
716fd4e5da5Sopenharmony_ci%void = OpTypeVoid
717fd4e5da5Sopenharmony_ci%7 = OpTypeFunction %void
718fd4e5da5Sopenharmony_ci%float = OpTypeFloat 32
719fd4e5da5Sopenharmony_ci%v4float = OpTypeVector %float 4
720fd4e5da5Sopenharmony_ci%_ptr_Function_v4float = OpTypePointer Function %v4float
721fd4e5da5Sopenharmony_ci%_ptr_Input_v4float = OpTypePointer Input %v4float
722fd4e5da5Sopenharmony_ci%BaseColor = OpVariable %_ptr_Input_v4float Input
723fd4e5da5Sopenharmony_ci%bool = OpTypeBool
724fd4e5da5Sopenharmony_ci%true = OpConstantTrue %bool
725fd4e5da5Sopenharmony_ci%float_0_5 = OpConstant %float 0.5
726fd4e5da5Sopenharmony_ci%_ptr_Output_v4float = OpTypePointer Output %v4float
727fd4e5da5Sopenharmony_ci%gl_FragColor = OpVariable %_ptr_Output_v4float Output
728fd4e5da5Sopenharmony_ci)";
729fd4e5da5Sopenharmony_ci
730fd4e5da5Sopenharmony_ci  const std::string before =
731fd4e5da5Sopenharmony_ci      R"(%main = OpFunction %void None %7
732fd4e5da5Sopenharmony_ci%16 = OpLabel
733fd4e5da5Sopenharmony_ci%v = OpVariable %_ptr_Function_v4float Function
734fd4e5da5Sopenharmony_ci%17 = OpLoad %v4float %BaseColor
735fd4e5da5Sopenharmony_ciOpStore %v %17
736fd4e5da5Sopenharmony_ciOpSelectionMerge %18 None
737fd4e5da5Sopenharmony_ciOpBranchConditional %true %19 %20
738fd4e5da5Sopenharmony_ci%19 = OpLabel
739fd4e5da5Sopenharmony_ciOpKill
740fd4e5da5Sopenharmony_ci%20 = OpLabel
741fd4e5da5Sopenharmony_ci%21 = OpLoad %v4float %v
742fd4e5da5Sopenharmony_ci%22 = OpVectorTimesScalar %v4float %21 %float_0_5
743fd4e5da5Sopenharmony_ciOpStore %v %22
744fd4e5da5Sopenharmony_ciOpBranch %18
745fd4e5da5Sopenharmony_ci%18 = OpLabel
746fd4e5da5Sopenharmony_ci%23 = OpLoad %v4float %v
747fd4e5da5Sopenharmony_ciOpStore %gl_FragColor %23
748fd4e5da5Sopenharmony_ciOpReturn
749fd4e5da5Sopenharmony_ciOpFunctionEnd
750fd4e5da5Sopenharmony_ci)";
751fd4e5da5Sopenharmony_ci
752fd4e5da5Sopenharmony_ci  const std::string after =
753fd4e5da5Sopenharmony_ci      R"(%main = OpFunction %void None %7
754fd4e5da5Sopenharmony_ci%16 = OpLabel
755fd4e5da5Sopenharmony_ci%v = OpVariable %_ptr_Function_v4float Function
756fd4e5da5Sopenharmony_ci%17 = OpLoad %v4float %BaseColor
757fd4e5da5Sopenharmony_ciOpStore %v %17
758fd4e5da5Sopenharmony_ciOpBranch %19
759fd4e5da5Sopenharmony_ci%19 = OpLabel
760fd4e5da5Sopenharmony_ciOpKill
761fd4e5da5Sopenharmony_ciOpFunctionEnd
762fd4e5da5Sopenharmony_ci)";
763fd4e5da5Sopenharmony_ci
764fd4e5da5Sopenharmony_ci  SinglePassRunAndCheck<DeadBranchElimPass>(predefs + before, predefs + after,
765fd4e5da5Sopenharmony_ci                                            true, true);
766fd4e5da5Sopenharmony_ci}
767fd4e5da5Sopenharmony_ci
768fd4e5da5Sopenharmony_ciTEST_F(DeadBranchElimTest, HandleOrphanMerge) {
769fd4e5da5Sopenharmony_ci  const std::string predefs =
770fd4e5da5Sopenharmony_ci      R"(OpCapability Shader
771fd4e5da5Sopenharmony_ci%1 = OpExtInstImport "GLSL.std.450"
772fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
773fd4e5da5Sopenharmony_ciOpEntryPoint Fragment %main "main" %gl_FragColor
774fd4e5da5Sopenharmony_ciOpExecutionMode %main OriginUpperLeft
775fd4e5da5Sopenharmony_ciOpSource GLSL 140
776fd4e5da5Sopenharmony_ciOpName %main "main"
777fd4e5da5Sopenharmony_ciOpName %foo_ "foo("
778fd4e5da5Sopenharmony_ciOpName %gl_FragColor "gl_FragColor"
779fd4e5da5Sopenharmony_ciOpDecorate %gl_FragColor Location 0
780fd4e5da5Sopenharmony_ci%void = OpTypeVoid
781fd4e5da5Sopenharmony_ci%6 = OpTypeFunction %void
782fd4e5da5Sopenharmony_ci%float = OpTypeFloat 32
783fd4e5da5Sopenharmony_ci%v4float = OpTypeVector %float 4
784fd4e5da5Sopenharmony_ci%9 = OpTypeFunction %v4float
785fd4e5da5Sopenharmony_ci%bool = OpTypeBool
786fd4e5da5Sopenharmony_ci%true = OpConstantTrue %bool
787fd4e5da5Sopenharmony_ci%float_0 = OpConstant %float 0
788fd4e5da5Sopenharmony_ci%13 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0
789fd4e5da5Sopenharmony_ci%float_1 = OpConstant %float 1
790fd4e5da5Sopenharmony_ci%15 = OpConstantComposite %v4float %float_1 %float_1 %float_1 %float_1
791fd4e5da5Sopenharmony_ci%_ptr_Output_v4float = OpTypePointer Output %v4float
792fd4e5da5Sopenharmony_ci%gl_FragColor = OpVariable %_ptr_Output_v4float Output
793fd4e5da5Sopenharmony_ci%main = OpFunction %void None %6
794fd4e5da5Sopenharmony_ci%17 = OpLabel
795fd4e5da5Sopenharmony_ci%18 = OpFunctionCall %v4float %foo_
796fd4e5da5Sopenharmony_ciOpStore %gl_FragColor %18
797fd4e5da5Sopenharmony_ciOpReturn
798fd4e5da5Sopenharmony_ciOpFunctionEnd
799fd4e5da5Sopenharmony_ci)";
800fd4e5da5Sopenharmony_ci
801fd4e5da5Sopenharmony_ci  const std::string before =
802fd4e5da5Sopenharmony_ci      R"(%foo_ = OpFunction %v4float None %9
803fd4e5da5Sopenharmony_ci%19 = OpLabel
804fd4e5da5Sopenharmony_ciOpSelectionMerge %20 None
805fd4e5da5Sopenharmony_ciOpBranchConditional %true %21 %22
806fd4e5da5Sopenharmony_ci%21 = OpLabel
807fd4e5da5Sopenharmony_ciOpReturnValue %13
808fd4e5da5Sopenharmony_ci%22 = OpLabel
809fd4e5da5Sopenharmony_ciOpReturnValue %15
810fd4e5da5Sopenharmony_ci%20 = OpLabel
811fd4e5da5Sopenharmony_ci%23 = OpUndef %v4float
812fd4e5da5Sopenharmony_ciOpReturnValue %23
813fd4e5da5Sopenharmony_ciOpFunctionEnd
814fd4e5da5Sopenharmony_ci)";
815fd4e5da5Sopenharmony_ci
816fd4e5da5Sopenharmony_ci  const std::string after =
817fd4e5da5Sopenharmony_ci      R"(%foo_ = OpFunction %v4float None %9
818fd4e5da5Sopenharmony_ci%19 = OpLabel
819fd4e5da5Sopenharmony_ciOpBranch %21
820fd4e5da5Sopenharmony_ci%21 = OpLabel
821fd4e5da5Sopenharmony_ciOpReturnValue %13
822fd4e5da5Sopenharmony_ciOpFunctionEnd
823fd4e5da5Sopenharmony_ci)";
824fd4e5da5Sopenharmony_ci
825fd4e5da5Sopenharmony_ci  SinglePassRunAndCheck<DeadBranchElimPass>(predefs + before, predefs + after,
826fd4e5da5Sopenharmony_ci                                            true, true);
827fd4e5da5Sopenharmony_ci}
828fd4e5da5Sopenharmony_ci
829fd4e5da5Sopenharmony_ciTEST_F(DeadBranchElimTest, KeepContinueTargetWhenKillAfterMerge) {
830fd4e5da5Sopenharmony_ci  // #version 450
831fd4e5da5Sopenharmony_ci  // void main() {
832fd4e5da5Sopenharmony_ci  //   bool c;
833fd4e5da5Sopenharmony_ci  //   bool d;
834fd4e5da5Sopenharmony_ci  //   while(c) {
835fd4e5da5Sopenharmony_ci  //     if(d) {
836fd4e5da5Sopenharmony_ci  //      continue;
837fd4e5da5Sopenharmony_ci  //     }
838fd4e5da5Sopenharmony_ci  //     if(false) {
839fd4e5da5Sopenharmony_ci  //      continue;
840fd4e5da5Sopenharmony_ci  //     }
841fd4e5da5Sopenharmony_ci  //     discard;
842fd4e5da5Sopenharmony_ci  //   }
843fd4e5da5Sopenharmony_ci  // }
844fd4e5da5Sopenharmony_ci
845fd4e5da5Sopenharmony_ci  const std::string predefs =
846fd4e5da5Sopenharmony_ci      R"(OpCapability Shader
847fd4e5da5Sopenharmony_ci%1 = OpExtInstImport "GLSL.std.450"
848fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
849fd4e5da5Sopenharmony_ciOpEntryPoint Fragment %main "main"
850fd4e5da5Sopenharmony_ciOpExecutionMode %main OriginUpperLeft
851fd4e5da5Sopenharmony_ciOpSource GLSL 450
852fd4e5da5Sopenharmony_ciOpName %main "main"
853fd4e5da5Sopenharmony_ciOpName %c "c"
854fd4e5da5Sopenharmony_ciOpName %d "d"
855fd4e5da5Sopenharmony_ci%void = OpTypeVoid
856fd4e5da5Sopenharmony_ci%6 = OpTypeFunction %void
857fd4e5da5Sopenharmony_ci%bool = OpTypeBool
858fd4e5da5Sopenharmony_ci%_ptr_Function_bool = OpTypePointer Function %bool
859fd4e5da5Sopenharmony_ci%false = OpConstantFalse %bool
860fd4e5da5Sopenharmony_ci)";
861fd4e5da5Sopenharmony_ci
862fd4e5da5Sopenharmony_ci  const std::string before =
863fd4e5da5Sopenharmony_ci      R"(%main = OpFunction %void None %6
864fd4e5da5Sopenharmony_ci%10 = OpLabel
865fd4e5da5Sopenharmony_ci%c = OpVariable %_ptr_Function_bool Function
866fd4e5da5Sopenharmony_ci%d = OpVariable %_ptr_Function_bool Function
867fd4e5da5Sopenharmony_ciOpBranch %11
868fd4e5da5Sopenharmony_ci%11 = OpLabel
869fd4e5da5Sopenharmony_ciOpLoopMerge %12 %13 None
870fd4e5da5Sopenharmony_ciOpBranch %14
871fd4e5da5Sopenharmony_ci%14 = OpLabel
872fd4e5da5Sopenharmony_ci%15 = OpLoad %bool %c
873fd4e5da5Sopenharmony_ciOpBranchConditional %15 %16 %12
874fd4e5da5Sopenharmony_ci%16 = OpLabel
875fd4e5da5Sopenharmony_ci%17 = OpLoad %bool %d
876fd4e5da5Sopenharmony_ciOpSelectionMerge %18 None
877fd4e5da5Sopenharmony_ciOpBranchConditional %17 %19 %18
878fd4e5da5Sopenharmony_ci%19 = OpLabel
879fd4e5da5Sopenharmony_ciOpBranch %13
880fd4e5da5Sopenharmony_ci%18 = OpLabel
881fd4e5da5Sopenharmony_ciOpSelectionMerge %20 None
882fd4e5da5Sopenharmony_ciOpBranchConditional %false %21 %20
883fd4e5da5Sopenharmony_ci%21 = OpLabel
884fd4e5da5Sopenharmony_ciOpBranch %13
885fd4e5da5Sopenharmony_ci%20 = OpLabel
886fd4e5da5Sopenharmony_ciOpKill
887fd4e5da5Sopenharmony_ci%13 = OpLabel
888fd4e5da5Sopenharmony_ciOpBranch %11
889fd4e5da5Sopenharmony_ci%12 = OpLabel
890fd4e5da5Sopenharmony_ciOpReturn
891fd4e5da5Sopenharmony_ciOpFunctionEnd
892fd4e5da5Sopenharmony_ci)";
893fd4e5da5Sopenharmony_ci
894fd4e5da5Sopenharmony_ci  const std::string after =
895fd4e5da5Sopenharmony_ci      R"(%main = OpFunction %void None %6
896fd4e5da5Sopenharmony_ci%10 = OpLabel
897fd4e5da5Sopenharmony_ci%c = OpVariable %_ptr_Function_bool Function
898fd4e5da5Sopenharmony_ci%d = OpVariable %_ptr_Function_bool Function
899fd4e5da5Sopenharmony_ciOpBranch %11
900fd4e5da5Sopenharmony_ci%11 = OpLabel
901fd4e5da5Sopenharmony_ciOpLoopMerge %12 %13 None
902fd4e5da5Sopenharmony_ciOpBranch %14
903fd4e5da5Sopenharmony_ci%14 = OpLabel
904fd4e5da5Sopenharmony_ci%15 = OpLoad %bool %c
905fd4e5da5Sopenharmony_ciOpBranchConditional %15 %16 %12
906fd4e5da5Sopenharmony_ci%16 = OpLabel
907fd4e5da5Sopenharmony_ci%17 = OpLoad %bool %d
908fd4e5da5Sopenharmony_ciOpSelectionMerge %18 None
909fd4e5da5Sopenharmony_ciOpBranchConditional %17 %19 %18
910fd4e5da5Sopenharmony_ci%19 = OpLabel
911fd4e5da5Sopenharmony_ciOpBranch %13
912fd4e5da5Sopenharmony_ci%18 = OpLabel
913fd4e5da5Sopenharmony_ciOpBranch %20
914fd4e5da5Sopenharmony_ci%20 = OpLabel
915fd4e5da5Sopenharmony_ciOpKill
916fd4e5da5Sopenharmony_ci%13 = OpLabel
917fd4e5da5Sopenharmony_ciOpBranch %11
918fd4e5da5Sopenharmony_ci%12 = OpLabel
919fd4e5da5Sopenharmony_ciOpReturn
920fd4e5da5Sopenharmony_ciOpFunctionEnd
921fd4e5da5Sopenharmony_ci)";
922fd4e5da5Sopenharmony_ci
923fd4e5da5Sopenharmony_ci  SinglePassRunAndCheck<DeadBranchElimPass>(predefs + before, predefs + after,
924fd4e5da5Sopenharmony_ci                                            true, true);
925fd4e5da5Sopenharmony_ci}
926fd4e5da5Sopenharmony_ci
927fd4e5da5Sopenharmony_ciTEST_F(DeadBranchElimTest, DecorateDeleted) {
928fd4e5da5Sopenharmony_ci  // Note: SPIR-V hand-edited to add decoration
929fd4e5da5Sopenharmony_ci  // #version 140
930fd4e5da5Sopenharmony_ci  //
931fd4e5da5Sopenharmony_ci  // in vec4 BaseColor;
932fd4e5da5Sopenharmony_ci  //
933fd4e5da5Sopenharmony_ci  // void main()
934fd4e5da5Sopenharmony_ci  // {
935fd4e5da5Sopenharmony_ci  //     vec4 v = BaseColor;
936fd4e5da5Sopenharmony_ci  //     if (false)
937fd4e5da5Sopenharmony_ci  //       v = v * vec4(0.5,0.5,0.5,0.5);
938fd4e5da5Sopenharmony_ci  //     gl_FragColor = v;
939fd4e5da5Sopenharmony_ci  // }
940fd4e5da5Sopenharmony_ci
941fd4e5da5Sopenharmony_ci  const std::string predefs_before =
942fd4e5da5Sopenharmony_ci      R"(OpCapability Shader
943fd4e5da5Sopenharmony_ci%1 = OpExtInstImport "GLSL.std.450"
944fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
945fd4e5da5Sopenharmony_ciOpEntryPoint Fragment %main "main" %BaseColor %gl_FragColor
946fd4e5da5Sopenharmony_ciOpExecutionMode %main OriginUpperLeft
947fd4e5da5Sopenharmony_ciOpSource GLSL 140
948fd4e5da5Sopenharmony_ciOpName %main "main"
949fd4e5da5Sopenharmony_ciOpName %v "v"
950fd4e5da5Sopenharmony_ciOpName %BaseColor "BaseColor"
951fd4e5da5Sopenharmony_ciOpName %gl_FragColor "gl_FragColor"
952fd4e5da5Sopenharmony_ciOpDecorate %22 RelaxedPrecision
953fd4e5da5Sopenharmony_ci%void = OpTypeVoid
954fd4e5da5Sopenharmony_ci%7 = OpTypeFunction %void
955fd4e5da5Sopenharmony_ci%float = OpTypeFloat 32
956fd4e5da5Sopenharmony_ci%v4float = OpTypeVector %float 4
957fd4e5da5Sopenharmony_ci%_ptr_Function_v4float = OpTypePointer Function %v4float
958fd4e5da5Sopenharmony_ci%_ptr_Input_v4float = OpTypePointer Input %v4float
959fd4e5da5Sopenharmony_ci%BaseColor = OpVariable %_ptr_Input_v4float Input
960fd4e5da5Sopenharmony_ci%bool = OpTypeBool
961fd4e5da5Sopenharmony_ci%false = OpConstantFalse %bool
962fd4e5da5Sopenharmony_ci%float_0_5 = OpConstant %float 0.5
963fd4e5da5Sopenharmony_ci%15 = OpConstantComposite %v4float %float_0_5 %float_0_5 %float_0_5 %float_0_5
964fd4e5da5Sopenharmony_ci%_ptr_Output_v4float = OpTypePointer Output %v4float
965fd4e5da5Sopenharmony_ci%gl_FragColor = OpVariable %_ptr_Output_v4float Output
966fd4e5da5Sopenharmony_ci)";
967fd4e5da5Sopenharmony_ci
968fd4e5da5Sopenharmony_ci  const std::string predefs_after =
969fd4e5da5Sopenharmony_ci      R"(OpCapability Shader
970fd4e5da5Sopenharmony_ci%1 = OpExtInstImport "GLSL.std.450"
971fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
972fd4e5da5Sopenharmony_ciOpEntryPoint Fragment %main "main" %BaseColor %gl_FragColor
973fd4e5da5Sopenharmony_ciOpExecutionMode %main OriginUpperLeft
974fd4e5da5Sopenharmony_ciOpSource GLSL 140
975fd4e5da5Sopenharmony_ciOpName %main "main"
976fd4e5da5Sopenharmony_ciOpName %v "v"
977fd4e5da5Sopenharmony_ciOpName %BaseColor "BaseColor"
978fd4e5da5Sopenharmony_ciOpName %gl_FragColor "gl_FragColor"
979fd4e5da5Sopenharmony_ci%void = OpTypeVoid
980fd4e5da5Sopenharmony_ci%8 = OpTypeFunction %void
981fd4e5da5Sopenharmony_ci%float = OpTypeFloat 32
982fd4e5da5Sopenharmony_ci%v4float = OpTypeVector %float 4
983fd4e5da5Sopenharmony_ci%_ptr_Function_v4float = OpTypePointer Function %v4float
984fd4e5da5Sopenharmony_ci%_ptr_Input_v4float = OpTypePointer Input %v4float
985fd4e5da5Sopenharmony_ci%BaseColor = OpVariable %_ptr_Input_v4float Input
986fd4e5da5Sopenharmony_ci%bool = OpTypeBool
987fd4e5da5Sopenharmony_ci%false = OpConstantFalse %bool
988fd4e5da5Sopenharmony_ci%float_0_5 = OpConstant %float 0.5
989fd4e5da5Sopenharmony_ci%16 = OpConstantComposite %v4float %float_0_5 %float_0_5 %float_0_5 %float_0_5
990fd4e5da5Sopenharmony_ci%_ptr_Output_v4float = OpTypePointer Output %v4float
991fd4e5da5Sopenharmony_ci%gl_FragColor = OpVariable %_ptr_Output_v4float Output
992fd4e5da5Sopenharmony_ci)";
993fd4e5da5Sopenharmony_ci
994fd4e5da5Sopenharmony_ci  const std::string before =
995fd4e5da5Sopenharmony_ci      R"(%main = OpFunction %void None %7
996fd4e5da5Sopenharmony_ci%17 = OpLabel
997fd4e5da5Sopenharmony_ci%v = OpVariable %_ptr_Function_v4float Function
998fd4e5da5Sopenharmony_ci%18 = OpLoad %v4float %BaseColor
999fd4e5da5Sopenharmony_ciOpStore %v %18
1000fd4e5da5Sopenharmony_ciOpSelectionMerge %19 None
1001fd4e5da5Sopenharmony_ciOpBranchConditional %false %20 %19
1002fd4e5da5Sopenharmony_ci%20 = OpLabel
1003fd4e5da5Sopenharmony_ci%21 = OpLoad %v4float %v
1004fd4e5da5Sopenharmony_ci%22 = OpFMul %v4float %21 %15
1005fd4e5da5Sopenharmony_ciOpStore %v %22
1006fd4e5da5Sopenharmony_ciOpBranch %19
1007fd4e5da5Sopenharmony_ci%19 = OpLabel
1008fd4e5da5Sopenharmony_ci%23 = OpLoad %v4float %v
1009fd4e5da5Sopenharmony_ciOpStore %gl_FragColor %23
1010fd4e5da5Sopenharmony_ciOpReturn
1011fd4e5da5Sopenharmony_ciOpFunctionEnd
1012fd4e5da5Sopenharmony_ci)";
1013fd4e5da5Sopenharmony_ci
1014fd4e5da5Sopenharmony_ci  const std::string after =
1015fd4e5da5Sopenharmony_ci      R"(%main = OpFunction %void None %8
1016fd4e5da5Sopenharmony_ci%18 = OpLabel
1017fd4e5da5Sopenharmony_ci%v = OpVariable %_ptr_Function_v4float Function
1018fd4e5da5Sopenharmony_ci%19 = OpLoad %v4float %BaseColor
1019fd4e5da5Sopenharmony_ciOpStore %v %19
1020fd4e5da5Sopenharmony_ciOpBranch %20
1021fd4e5da5Sopenharmony_ci%20 = OpLabel
1022fd4e5da5Sopenharmony_ci%23 = OpLoad %v4float %v
1023fd4e5da5Sopenharmony_ciOpStore %gl_FragColor %23
1024fd4e5da5Sopenharmony_ciOpReturn
1025fd4e5da5Sopenharmony_ciOpFunctionEnd
1026fd4e5da5Sopenharmony_ci)";
1027fd4e5da5Sopenharmony_ci
1028fd4e5da5Sopenharmony_ci  SinglePassRunAndCheck<DeadBranchElimPass>(predefs_before + before,
1029fd4e5da5Sopenharmony_ci                                            predefs_after + after, true, true);
1030fd4e5da5Sopenharmony_ci}
1031fd4e5da5Sopenharmony_ci
1032fd4e5da5Sopenharmony_ciTEST_F(DeadBranchElimTest, LoopInDeadBranch) {
1033fd4e5da5Sopenharmony_ci  // #version 450
1034fd4e5da5Sopenharmony_ci  //
1035fd4e5da5Sopenharmony_ci  // layout(location = 0) in vec4 BaseColor;
1036fd4e5da5Sopenharmony_ci  // layout(location = 0) out vec4 OutColor;
1037fd4e5da5Sopenharmony_ci  //
1038fd4e5da5Sopenharmony_ci  // void main()
1039fd4e5da5Sopenharmony_ci  // {
1040fd4e5da5Sopenharmony_ci  //     vec4 v = BaseColor;
1041fd4e5da5Sopenharmony_ci  //     if (false)
1042fd4e5da5Sopenharmony_ci  //       for (int i=0; i<3; i++)
1043fd4e5da5Sopenharmony_ci  //         v = v * 0.5;
1044fd4e5da5Sopenharmony_ci  //     OutColor = v;
1045fd4e5da5Sopenharmony_ci  // }
1046fd4e5da5Sopenharmony_ci
1047fd4e5da5Sopenharmony_ci  const std::string predefs =
1048fd4e5da5Sopenharmony_ci      R"(OpCapability Shader
1049fd4e5da5Sopenharmony_ci%1 = OpExtInstImport "GLSL.std.450"
1050fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
1051fd4e5da5Sopenharmony_ciOpEntryPoint Fragment %main "main" %BaseColor %OutColor
1052fd4e5da5Sopenharmony_ciOpExecutionMode %main OriginUpperLeft
1053fd4e5da5Sopenharmony_ciOpSource GLSL 450
1054fd4e5da5Sopenharmony_ciOpName %main "main"
1055fd4e5da5Sopenharmony_ciOpName %v "v"
1056fd4e5da5Sopenharmony_ciOpName %BaseColor "BaseColor"
1057fd4e5da5Sopenharmony_ciOpName %i "i"
1058fd4e5da5Sopenharmony_ciOpName %OutColor "OutColor"
1059fd4e5da5Sopenharmony_ciOpDecorate %BaseColor Location 0
1060fd4e5da5Sopenharmony_ciOpDecorate %OutColor Location 0
1061fd4e5da5Sopenharmony_ci%void = OpTypeVoid
1062fd4e5da5Sopenharmony_ci%8 = OpTypeFunction %void
1063fd4e5da5Sopenharmony_ci%float = OpTypeFloat 32
1064fd4e5da5Sopenharmony_ci%v4float = OpTypeVector %float 4
1065fd4e5da5Sopenharmony_ci%_ptr_Function_v4float = OpTypePointer Function %v4float
1066fd4e5da5Sopenharmony_ci%_ptr_Input_v4float = OpTypePointer Input %v4float
1067fd4e5da5Sopenharmony_ci%BaseColor = OpVariable %_ptr_Input_v4float Input
1068fd4e5da5Sopenharmony_ci%bool = OpTypeBool
1069fd4e5da5Sopenharmony_ci%false = OpConstantFalse %bool
1070fd4e5da5Sopenharmony_ci%int = OpTypeInt 32 1
1071fd4e5da5Sopenharmony_ci%_ptr_Function_int = OpTypePointer Function %int
1072fd4e5da5Sopenharmony_ci%int_0 = OpConstant %int 0
1073fd4e5da5Sopenharmony_ci%int_3 = OpConstant %int 3
1074fd4e5da5Sopenharmony_ci%float_0_5 = OpConstant %float 0.5
1075fd4e5da5Sopenharmony_ci%int_1 = OpConstant %int 1
1076fd4e5da5Sopenharmony_ci%_ptr_Output_v4float = OpTypePointer Output %v4float
1077fd4e5da5Sopenharmony_ci%OutColor = OpVariable %_ptr_Output_v4float Output
1078fd4e5da5Sopenharmony_ci)";
1079fd4e5da5Sopenharmony_ci
1080fd4e5da5Sopenharmony_ci  const std::string before =
1081fd4e5da5Sopenharmony_ci      R"(%main = OpFunction %void None %8
1082fd4e5da5Sopenharmony_ci%22 = OpLabel
1083fd4e5da5Sopenharmony_ci%v = OpVariable %_ptr_Function_v4float Function
1084fd4e5da5Sopenharmony_ci%i = OpVariable %_ptr_Function_int Function
1085fd4e5da5Sopenharmony_ci%23 = OpLoad %v4float %BaseColor
1086fd4e5da5Sopenharmony_ciOpStore %v %23
1087fd4e5da5Sopenharmony_ciOpSelectionMerge %24 None
1088fd4e5da5Sopenharmony_ciOpBranchConditional %false %25 %24
1089fd4e5da5Sopenharmony_ci%25 = OpLabel
1090fd4e5da5Sopenharmony_ciOpStore %i %int_0
1091fd4e5da5Sopenharmony_ciOpBranch %26
1092fd4e5da5Sopenharmony_ci%26 = OpLabel
1093fd4e5da5Sopenharmony_ciOpLoopMerge %27 %28 None
1094fd4e5da5Sopenharmony_ciOpBranch %29
1095fd4e5da5Sopenharmony_ci%29 = OpLabel
1096fd4e5da5Sopenharmony_ci%30 = OpLoad %int %i
1097fd4e5da5Sopenharmony_ci%31 = OpSLessThan %bool %30 %int_3
1098fd4e5da5Sopenharmony_ciOpBranchConditional %31 %32 %27
1099fd4e5da5Sopenharmony_ci%32 = OpLabel
1100fd4e5da5Sopenharmony_ci%33 = OpLoad %v4float %v
1101fd4e5da5Sopenharmony_ci%34 = OpVectorTimesScalar %v4float %33 %float_0_5
1102fd4e5da5Sopenharmony_ciOpStore %v %34
1103fd4e5da5Sopenharmony_ciOpBranch %28
1104fd4e5da5Sopenharmony_ci%28 = OpLabel
1105fd4e5da5Sopenharmony_ci%35 = OpLoad %int %i
1106fd4e5da5Sopenharmony_ci%36 = OpIAdd %int %35 %int_1
1107fd4e5da5Sopenharmony_ciOpStore %i %36
1108fd4e5da5Sopenharmony_ciOpBranch %26
1109fd4e5da5Sopenharmony_ci%27 = OpLabel
1110fd4e5da5Sopenharmony_ciOpBranch %24
1111fd4e5da5Sopenharmony_ci%24 = OpLabel
1112fd4e5da5Sopenharmony_ci%37 = OpLoad %v4float %v
1113fd4e5da5Sopenharmony_ciOpStore %OutColor %37
1114fd4e5da5Sopenharmony_ciOpReturn
1115fd4e5da5Sopenharmony_ciOpFunctionEnd
1116fd4e5da5Sopenharmony_ci)";
1117fd4e5da5Sopenharmony_ci
1118fd4e5da5Sopenharmony_ci  const std::string after =
1119fd4e5da5Sopenharmony_ci      R"(%main = OpFunction %void None %8
1120fd4e5da5Sopenharmony_ci%22 = OpLabel
1121fd4e5da5Sopenharmony_ci%v = OpVariable %_ptr_Function_v4float Function
1122fd4e5da5Sopenharmony_ci%i = OpVariable %_ptr_Function_int Function
1123fd4e5da5Sopenharmony_ci%23 = OpLoad %v4float %BaseColor
1124fd4e5da5Sopenharmony_ciOpStore %v %23
1125fd4e5da5Sopenharmony_ciOpBranch %24
1126fd4e5da5Sopenharmony_ci%24 = OpLabel
1127fd4e5da5Sopenharmony_ci%37 = OpLoad %v4float %v
1128fd4e5da5Sopenharmony_ciOpStore %OutColor %37
1129fd4e5da5Sopenharmony_ciOpReturn
1130fd4e5da5Sopenharmony_ciOpFunctionEnd
1131fd4e5da5Sopenharmony_ci)";
1132fd4e5da5Sopenharmony_ci
1133fd4e5da5Sopenharmony_ci  SinglePassRunAndCheck<DeadBranchElimPass>(predefs + before, predefs + after,
1134fd4e5da5Sopenharmony_ci                                            true, true);
1135fd4e5da5Sopenharmony_ci}
1136fd4e5da5Sopenharmony_ci
1137fd4e5da5Sopenharmony_ciTEST_F(DeadBranchElimTest, SwitchLiveCase) {
1138fd4e5da5Sopenharmony_ci  // #version 450
1139fd4e5da5Sopenharmony_ci  //
1140fd4e5da5Sopenharmony_ci  // layout (location=0) in vec4 BaseColor;
1141fd4e5da5Sopenharmony_ci  // layout (location=0) out vec4 OutColor;
1142fd4e5da5Sopenharmony_ci  //
1143fd4e5da5Sopenharmony_ci  // void main()
1144fd4e5da5Sopenharmony_ci  // {
1145fd4e5da5Sopenharmony_ci  //     switch (1) {
1146fd4e5da5Sopenharmony_ci  //       case 0:
1147fd4e5da5Sopenharmony_ci  //         OutColor = vec4(0.0,0.0,0.0,0.0);
1148fd4e5da5Sopenharmony_ci  //         break;
1149fd4e5da5Sopenharmony_ci  //       case 1:
1150fd4e5da5Sopenharmony_ci  //         OutColor = vec4(0.125,0.125,0.125,0.125);
1151fd4e5da5Sopenharmony_ci  //         break;
1152fd4e5da5Sopenharmony_ci  //       case 2:
1153fd4e5da5Sopenharmony_ci  //         OutColor = vec4(0.25,0.25,0.25,0.25);
1154fd4e5da5Sopenharmony_ci  //         break;
1155fd4e5da5Sopenharmony_ci  //       default:
1156fd4e5da5Sopenharmony_ci  //         OutColor = vec4(1.0,1.0,1.0,1.0);
1157fd4e5da5Sopenharmony_ci  //     }
1158fd4e5da5Sopenharmony_ci  // }
1159fd4e5da5Sopenharmony_ci
1160fd4e5da5Sopenharmony_ci  const std::string predefs =
1161fd4e5da5Sopenharmony_ci      R"(OpCapability Shader
1162fd4e5da5Sopenharmony_ci%1 = OpExtInstImport "GLSL.std.450"
1163fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
1164fd4e5da5Sopenharmony_ciOpEntryPoint Fragment %main "main" %OutColor %BaseColor
1165fd4e5da5Sopenharmony_ciOpExecutionMode %main OriginUpperLeft
1166fd4e5da5Sopenharmony_ciOpSource GLSL 450
1167fd4e5da5Sopenharmony_ciOpName %main "main"
1168fd4e5da5Sopenharmony_ciOpName %OutColor "OutColor"
1169fd4e5da5Sopenharmony_ciOpName %BaseColor "BaseColor"
1170fd4e5da5Sopenharmony_ciOpDecorate %OutColor Location 0
1171fd4e5da5Sopenharmony_ciOpDecorate %BaseColor Location 0
1172fd4e5da5Sopenharmony_ci%void = OpTypeVoid
1173fd4e5da5Sopenharmony_ci%6 = OpTypeFunction %void
1174fd4e5da5Sopenharmony_ci%int = OpTypeInt 32 1
1175fd4e5da5Sopenharmony_ci%int_1 = OpConstant %int 1
1176fd4e5da5Sopenharmony_ci%float = OpTypeFloat 32
1177fd4e5da5Sopenharmony_ci%v4float = OpTypeVector %float 4
1178fd4e5da5Sopenharmony_ci%_ptr_Output_v4float = OpTypePointer Output %v4float
1179fd4e5da5Sopenharmony_ci%OutColor = OpVariable %_ptr_Output_v4float Output
1180fd4e5da5Sopenharmony_ci%float_0 = OpConstant %float 0
1181fd4e5da5Sopenharmony_ci%13 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0
1182fd4e5da5Sopenharmony_ci%float_0_125 = OpConstant %float 0.125
1183fd4e5da5Sopenharmony_ci%15 = OpConstantComposite %v4float %float_0_125 %float_0_125 %float_0_125 %float_0_125
1184fd4e5da5Sopenharmony_ci%float_0_25 = OpConstant %float 0.25
1185fd4e5da5Sopenharmony_ci%17 = OpConstantComposite %v4float %float_0_25 %float_0_25 %float_0_25 %float_0_25
1186fd4e5da5Sopenharmony_ci%float_1 = OpConstant %float 1
1187fd4e5da5Sopenharmony_ci%19 = OpConstantComposite %v4float %float_1 %float_1 %float_1 %float_1
1188fd4e5da5Sopenharmony_ci%_ptr_Input_v4float = OpTypePointer Input %v4float
1189fd4e5da5Sopenharmony_ci%BaseColor = OpVariable %_ptr_Input_v4float Input
1190fd4e5da5Sopenharmony_ci)";
1191fd4e5da5Sopenharmony_ci
1192fd4e5da5Sopenharmony_ci  const std::string before =
1193fd4e5da5Sopenharmony_ci      R"(%main = OpFunction %void None %6
1194fd4e5da5Sopenharmony_ci%21 = OpLabel
1195fd4e5da5Sopenharmony_ciOpSelectionMerge %22 None
1196fd4e5da5Sopenharmony_ciOpSwitch %int_1 %23 0 %24 1 %25 2 %26
1197fd4e5da5Sopenharmony_ci%23 = OpLabel
1198fd4e5da5Sopenharmony_ciOpStore %OutColor %19
1199fd4e5da5Sopenharmony_ciOpBranch %22
1200fd4e5da5Sopenharmony_ci%24 = OpLabel
1201fd4e5da5Sopenharmony_ciOpStore %OutColor %13
1202fd4e5da5Sopenharmony_ciOpBranch %22
1203fd4e5da5Sopenharmony_ci%25 = OpLabel
1204fd4e5da5Sopenharmony_ciOpStore %OutColor %15
1205fd4e5da5Sopenharmony_ciOpBranch %22
1206fd4e5da5Sopenharmony_ci%26 = OpLabel
1207fd4e5da5Sopenharmony_ciOpStore %OutColor %17
1208fd4e5da5Sopenharmony_ciOpBranch %22
1209fd4e5da5Sopenharmony_ci%22 = OpLabel
1210fd4e5da5Sopenharmony_ciOpReturn
1211fd4e5da5Sopenharmony_ciOpFunctionEnd
1212fd4e5da5Sopenharmony_ci)";
1213fd4e5da5Sopenharmony_ci
1214fd4e5da5Sopenharmony_ci  const std::string after =
1215fd4e5da5Sopenharmony_ci      R"(%main = OpFunction %void None %6
1216fd4e5da5Sopenharmony_ci%21 = OpLabel
1217fd4e5da5Sopenharmony_ciOpBranch %25
1218fd4e5da5Sopenharmony_ci%25 = OpLabel
1219fd4e5da5Sopenharmony_ciOpStore %OutColor %15
1220fd4e5da5Sopenharmony_ciOpBranch %22
1221fd4e5da5Sopenharmony_ci%22 = OpLabel
1222fd4e5da5Sopenharmony_ciOpReturn
1223fd4e5da5Sopenharmony_ciOpFunctionEnd
1224fd4e5da5Sopenharmony_ci)";
1225fd4e5da5Sopenharmony_ci
1226fd4e5da5Sopenharmony_ci  SinglePassRunAndCheck<DeadBranchElimPass>(predefs + before, predefs + after,
1227fd4e5da5Sopenharmony_ci                                            true, true);
1228fd4e5da5Sopenharmony_ci}
1229fd4e5da5Sopenharmony_ci
1230fd4e5da5Sopenharmony_ciTEST_F(DeadBranchElimTest, SwitchLiveDefault) {
1231fd4e5da5Sopenharmony_ci  // #version 450
1232fd4e5da5Sopenharmony_ci  //
1233fd4e5da5Sopenharmony_ci  // layout (location=0) in vec4 BaseColor;
1234fd4e5da5Sopenharmony_ci  // layout (location=0) out vec4 OutColor;
1235fd4e5da5Sopenharmony_ci  //
1236fd4e5da5Sopenharmony_ci  // void main()
1237fd4e5da5Sopenharmony_ci  // {
1238fd4e5da5Sopenharmony_ci  //     switch (7) {
1239fd4e5da5Sopenharmony_ci  //       case 0:
1240fd4e5da5Sopenharmony_ci  //         OutColor = vec4(0.0,0.0,0.0,0.0);
1241fd4e5da5Sopenharmony_ci  //         break;
1242fd4e5da5Sopenharmony_ci  //       case 1:
1243fd4e5da5Sopenharmony_ci  //         OutColor = vec4(0.125,0.125,0.125,0.125);
1244fd4e5da5Sopenharmony_ci  //         break;
1245fd4e5da5Sopenharmony_ci  //       case 2:
1246fd4e5da5Sopenharmony_ci  //         OutColor = vec4(0.25,0.25,0.25,0.25);
1247fd4e5da5Sopenharmony_ci  //         break;
1248fd4e5da5Sopenharmony_ci  //       default:
1249fd4e5da5Sopenharmony_ci  //         OutColor = vec4(1.0,1.0,1.0,1.0);
1250fd4e5da5Sopenharmony_ci  //     }
1251fd4e5da5Sopenharmony_ci  // }
1252fd4e5da5Sopenharmony_ci
1253fd4e5da5Sopenharmony_ci  const std::string predefs =
1254fd4e5da5Sopenharmony_ci      R"(OpCapability Shader
1255fd4e5da5Sopenharmony_ci%1 = OpExtInstImport "GLSL.std.450"
1256fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
1257fd4e5da5Sopenharmony_ciOpEntryPoint Fragment %main "main" %OutColor %BaseColor
1258fd4e5da5Sopenharmony_ciOpExecutionMode %main OriginUpperLeft
1259fd4e5da5Sopenharmony_ciOpSource GLSL 450
1260fd4e5da5Sopenharmony_ciOpName %main "main"
1261fd4e5da5Sopenharmony_ciOpName %OutColor "OutColor"
1262fd4e5da5Sopenharmony_ciOpName %BaseColor "BaseColor"
1263fd4e5da5Sopenharmony_ciOpDecorate %OutColor Location 0
1264fd4e5da5Sopenharmony_ciOpDecorate %BaseColor Location 0
1265fd4e5da5Sopenharmony_ci%void = OpTypeVoid
1266fd4e5da5Sopenharmony_ci%6 = OpTypeFunction %void
1267fd4e5da5Sopenharmony_ci%int = OpTypeInt 32 1
1268fd4e5da5Sopenharmony_ci%int_7 = OpConstant %int 7
1269fd4e5da5Sopenharmony_ci%float = OpTypeFloat 32
1270fd4e5da5Sopenharmony_ci%v4float = OpTypeVector %float 4
1271fd4e5da5Sopenharmony_ci%_ptr_Output_v4float = OpTypePointer Output %v4float
1272fd4e5da5Sopenharmony_ci%OutColor = OpVariable %_ptr_Output_v4float Output
1273fd4e5da5Sopenharmony_ci%float_0 = OpConstant %float 0
1274fd4e5da5Sopenharmony_ci%13 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0
1275fd4e5da5Sopenharmony_ci%float_0_125 = OpConstant %float 0.125
1276fd4e5da5Sopenharmony_ci%15 = OpConstantComposite %v4float %float_0_125 %float_0_125 %float_0_125 %float_0_125
1277fd4e5da5Sopenharmony_ci%float_0_25 = OpConstant %float 0.25
1278fd4e5da5Sopenharmony_ci%17 = OpConstantComposite %v4float %float_0_25 %float_0_25 %float_0_25 %float_0_25
1279fd4e5da5Sopenharmony_ci%float_1 = OpConstant %float 1
1280fd4e5da5Sopenharmony_ci%19 = OpConstantComposite %v4float %float_1 %float_1 %float_1 %float_1
1281fd4e5da5Sopenharmony_ci%_ptr_Input_v4float = OpTypePointer Input %v4float
1282fd4e5da5Sopenharmony_ci%BaseColor = OpVariable %_ptr_Input_v4float Input
1283fd4e5da5Sopenharmony_ci)";
1284fd4e5da5Sopenharmony_ci
1285fd4e5da5Sopenharmony_ci  const std::string before =
1286fd4e5da5Sopenharmony_ci      R"(%main = OpFunction %void None %6
1287fd4e5da5Sopenharmony_ci%21 = OpLabel
1288fd4e5da5Sopenharmony_ciOpSelectionMerge %22 None
1289fd4e5da5Sopenharmony_ciOpSwitch %int_7 %23 0 %24 1 %25 2 %26
1290fd4e5da5Sopenharmony_ci%23 = OpLabel
1291fd4e5da5Sopenharmony_ciOpStore %OutColor %19
1292fd4e5da5Sopenharmony_ciOpBranch %22
1293fd4e5da5Sopenharmony_ci%24 = OpLabel
1294fd4e5da5Sopenharmony_ciOpStore %OutColor %13
1295fd4e5da5Sopenharmony_ciOpBranch %22
1296fd4e5da5Sopenharmony_ci%25 = OpLabel
1297fd4e5da5Sopenharmony_ciOpStore %OutColor %15
1298fd4e5da5Sopenharmony_ciOpBranch %22
1299fd4e5da5Sopenharmony_ci%26 = OpLabel
1300fd4e5da5Sopenharmony_ciOpStore %OutColor %17
1301fd4e5da5Sopenharmony_ciOpBranch %22
1302fd4e5da5Sopenharmony_ci%22 = OpLabel
1303fd4e5da5Sopenharmony_ciOpReturn
1304fd4e5da5Sopenharmony_ciOpFunctionEnd
1305fd4e5da5Sopenharmony_ci)";
1306fd4e5da5Sopenharmony_ci
1307fd4e5da5Sopenharmony_ci  const std::string after =
1308fd4e5da5Sopenharmony_ci      R"(%main = OpFunction %void None %6
1309fd4e5da5Sopenharmony_ci%21 = OpLabel
1310fd4e5da5Sopenharmony_ciOpBranch %23
1311fd4e5da5Sopenharmony_ci%23 = OpLabel
1312fd4e5da5Sopenharmony_ciOpStore %OutColor %19
1313fd4e5da5Sopenharmony_ciOpBranch %22
1314fd4e5da5Sopenharmony_ci%22 = OpLabel
1315fd4e5da5Sopenharmony_ciOpReturn
1316fd4e5da5Sopenharmony_ciOpFunctionEnd
1317fd4e5da5Sopenharmony_ci)";
1318fd4e5da5Sopenharmony_ci
1319fd4e5da5Sopenharmony_ci  SinglePassRunAndCheck<DeadBranchElimPass>(predefs + before, predefs + after,
1320fd4e5da5Sopenharmony_ci                                            true, true);
1321fd4e5da5Sopenharmony_ci}
1322fd4e5da5Sopenharmony_ci
1323fd4e5da5Sopenharmony_ciTEST_F(DeadBranchElimTest, SwitchLiveCaseBreakFromLoop) {
1324fd4e5da5Sopenharmony_ci  // This sample does not directly translate to GLSL/HLSL as
1325fd4e5da5Sopenharmony_ci  // direct breaks from a loop cannot be made from a switch.
1326fd4e5da5Sopenharmony_ci  // This construct is currently formed by inlining a function
1327fd4e5da5Sopenharmony_ci  // containing early returns from the cases of a switch. The
1328fd4e5da5Sopenharmony_ci  // function is wrapped in a one-trip loop and returns are
1329fd4e5da5Sopenharmony_ci  // translated to branches to the loop's merge block.
1330fd4e5da5Sopenharmony_ci
1331fd4e5da5Sopenharmony_ci  const std::string predefs =
1332fd4e5da5Sopenharmony_ci      R"(OpCapability Shader
1333fd4e5da5Sopenharmony_ci%1 = OpExtInstImport "GLSL.std.450"
1334fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
1335fd4e5da5Sopenharmony_ciOpEntryPoint Fragment %main "main" %OutColor %BaseColor
1336fd4e5da5Sopenharmony_ciOpExecutionMode %main OriginUpperLeft
1337fd4e5da5Sopenharmony_ciOpSource GLSL 450
1338fd4e5da5Sopenharmony_ciOpName %main "main"
1339fd4e5da5Sopenharmony_ciOpName %oc "oc"
1340fd4e5da5Sopenharmony_ciOpName %OutColor "OutColor"
1341fd4e5da5Sopenharmony_ciOpName %BaseColor "BaseColor"
1342fd4e5da5Sopenharmony_ciOpDecorate %OutColor Location 0
1343fd4e5da5Sopenharmony_ciOpDecorate %BaseColor Location 0
1344fd4e5da5Sopenharmony_ci%void = OpTypeVoid
1345fd4e5da5Sopenharmony_ci%7 = OpTypeFunction %void
1346fd4e5da5Sopenharmony_ci%bool = OpTypeBool
1347fd4e5da5Sopenharmony_ci%true = OpConstantTrue %bool
1348fd4e5da5Sopenharmony_ci%false = OpConstantFalse %bool
1349fd4e5da5Sopenharmony_ci%int = OpTypeInt 32 1
1350fd4e5da5Sopenharmony_ci%int_1 = OpConstant %int 1
1351fd4e5da5Sopenharmony_ci%float = OpTypeFloat 32
1352fd4e5da5Sopenharmony_ci%v4float = OpTypeVector %float 4
1353fd4e5da5Sopenharmony_ci%_ptr_Function_v4float = OpTypePointer Function %v4float
1354fd4e5da5Sopenharmony_ci%float_0 = OpConstant %float 0
1355fd4e5da5Sopenharmony_ci%17 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0
1356fd4e5da5Sopenharmony_ci%float_0_125 = OpConstant %float 0.125
1357fd4e5da5Sopenharmony_ci%19 = OpConstantComposite %v4float %float_0_125 %float_0_125 %float_0_125 %float_0_125
1358fd4e5da5Sopenharmony_ci%float_0_25 = OpConstant %float 0.25
1359fd4e5da5Sopenharmony_ci%21 = OpConstantComposite %v4float %float_0_25 %float_0_25 %float_0_25 %float_0_25
1360fd4e5da5Sopenharmony_ci%float_1 = OpConstant %float 1
1361fd4e5da5Sopenharmony_ci%23 = OpConstantComposite %v4float %float_1 %float_1 %float_1 %float_1
1362fd4e5da5Sopenharmony_ci%_ptr_Output_v4float = OpTypePointer Output %v4float
1363fd4e5da5Sopenharmony_ci%OutColor = OpVariable %_ptr_Output_v4float Output
1364fd4e5da5Sopenharmony_ci%_ptr_Input_v4float = OpTypePointer Input %v4float
1365fd4e5da5Sopenharmony_ci%BaseColor = OpVariable %_ptr_Input_v4float Input
1366fd4e5da5Sopenharmony_ci)";
1367fd4e5da5Sopenharmony_ci
1368fd4e5da5Sopenharmony_ci  const std::string before =
1369fd4e5da5Sopenharmony_ci      R"(%main = OpFunction %void None %7
1370fd4e5da5Sopenharmony_ci%26 = OpLabel
1371fd4e5da5Sopenharmony_ci%oc = OpVariable %_ptr_Function_v4float Function
1372fd4e5da5Sopenharmony_ciOpBranch %27
1373fd4e5da5Sopenharmony_ci%27 = OpLabel
1374fd4e5da5Sopenharmony_ciOpLoopMerge %28 %29 None
1375fd4e5da5Sopenharmony_ciOpBranch %30
1376fd4e5da5Sopenharmony_ci%30 = OpLabel
1377fd4e5da5Sopenharmony_ciOpSelectionMerge %31 None
1378fd4e5da5Sopenharmony_ciOpSwitch %int_1 %31 0 %32 1 %33 2 %34
1379fd4e5da5Sopenharmony_ci%32 = OpLabel
1380fd4e5da5Sopenharmony_ciOpStore %oc %17
1381fd4e5da5Sopenharmony_ciOpBranch %28
1382fd4e5da5Sopenharmony_ci%33 = OpLabel
1383fd4e5da5Sopenharmony_ciOpStore %oc %19
1384fd4e5da5Sopenharmony_ciOpBranch %28
1385fd4e5da5Sopenharmony_ci%34 = OpLabel
1386fd4e5da5Sopenharmony_ciOpStore %oc %21
1387fd4e5da5Sopenharmony_ciOpBranch %28
1388fd4e5da5Sopenharmony_ci%31 = OpLabel
1389fd4e5da5Sopenharmony_ciOpStore %oc %23
1390fd4e5da5Sopenharmony_ciOpBranch %28
1391fd4e5da5Sopenharmony_ci%29 = OpLabel
1392fd4e5da5Sopenharmony_ciOpBranchConditional %false %27 %28
1393fd4e5da5Sopenharmony_ci%28 = OpLabel
1394fd4e5da5Sopenharmony_ci%35 = OpLoad %v4float %oc
1395fd4e5da5Sopenharmony_ciOpStore %OutColor %35
1396fd4e5da5Sopenharmony_ciOpReturn
1397fd4e5da5Sopenharmony_ciOpFunctionEnd
1398fd4e5da5Sopenharmony_ci)";
1399fd4e5da5Sopenharmony_ci
1400fd4e5da5Sopenharmony_ci  const std::string after =
1401fd4e5da5Sopenharmony_ci      R"(%main = OpFunction %void None %7
1402fd4e5da5Sopenharmony_ci%26 = OpLabel
1403fd4e5da5Sopenharmony_ci%oc = OpVariable %_ptr_Function_v4float Function
1404fd4e5da5Sopenharmony_ciOpBranch %27
1405fd4e5da5Sopenharmony_ci%27 = OpLabel
1406fd4e5da5Sopenharmony_ciOpLoopMerge %28 %29 None
1407fd4e5da5Sopenharmony_ciOpBranch %30
1408fd4e5da5Sopenharmony_ci%30 = OpLabel
1409fd4e5da5Sopenharmony_ciOpBranch %33
1410fd4e5da5Sopenharmony_ci%33 = OpLabel
1411fd4e5da5Sopenharmony_ciOpStore %oc %19
1412fd4e5da5Sopenharmony_ciOpBranch %28
1413fd4e5da5Sopenharmony_ci%29 = OpLabel
1414fd4e5da5Sopenharmony_ciOpBranch %27
1415fd4e5da5Sopenharmony_ci%28 = OpLabel
1416fd4e5da5Sopenharmony_ci%35 = OpLoad %v4float %oc
1417fd4e5da5Sopenharmony_ciOpStore %OutColor %35
1418fd4e5da5Sopenharmony_ciOpReturn
1419fd4e5da5Sopenharmony_ciOpFunctionEnd
1420fd4e5da5Sopenharmony_ci)";
1421fd4e5da5Sopenharmony_ci
1422fd4e5da5Sopenharmony_ci  SinglePassRunAndCheck<DeadBranchElimPass>(predefs + before, predefs + after,
1423fd4e5da5Sopenharmony_ci                                            true, true);
1424fd4e5da5Sopenharmony_ci}
1425fd4e5da5Sopenharmony_ci
1426fd4e5da5Sopenharmony_ciTEST_F(DeadBranchElimTest, LeaveContinueBackedge) {
1427fd4e5da5Sopenharmony_ci  const std::string text = R"(
1428fd4e5da5Sopenharmony_ci; CHECK: OpLoopMerge [[merge:%\w+]] [[continue:%\w+]] None
1429fd4e5da5Sopenharmony_ci; CHECK: [[continue]] = OpLabel
1430fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpBranchConditional {{%\w+}} {{%\w+}} [[merge]]
1431fd4e5da5Sopenharmony_ci; CHECK-NEXT: [[merge]] = OpLabel
1432fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpReturn
1433fd4e5da5Sopenharmony_ciOpCapability Kernel
1434fd4e5da5Sopenharmony_ciOpCapability Linkage
1435fd4e5da5Sopenharmony_ciOpMemoryModel Logical OpenCL
1436fd4e5da5Sopenharmony_ci%bool = OpTypeBool
1437fd4e5da5Sopenharmony_ci%false = OpConstantFalse %bool
1438fd4e5da5Sopenharmony_ci%void = OpTypeVoid
1439fd4e5da5Sopenharmony_ci%funcTy = OpTypeFunction %void
1440fd4e5da5Sopenharmony_ci%func = OpFunction %void None %funcTy
1441fd4e5da5Sopenharmony_ci%1 = OpLabel
1442fd4e5da5Sopenharmony_ciOpBranch %2
1443fd4e5da5Sopenharmony_ci%2 = OpLabel
1444fd4e5da5Sopenharmony_ciOpLoopMerge %3 %4 None
1445fd4e5da5Sopenharmony_ciOpBranch %4
1446fd4e5da5Sopenharmony_ci%4 = OpLabel
1447fd4e5da5Sopenharmony_ci; Be careful we don't remove the backedge to %2 despite never taking it.
1448fd4e5da5Sopenharmony_ciOpBranchConditional %false %2 %3
1449fd4e5da5Sopenharmony_ci%3 = OpLabel
1450fd4e5da5Sopenharmony_ciOpReturn
1451fd4e5da5Sopenharmony_ciOpFunctionEnd
1452fd4e5da5Sopenharmony_ci)";
1453fd4e5da5Sopenharmony_ci
1454fd4e5da5Sopenharmony_ci  SinglePassRunAndMatch<DeadBranchElimPass>(text, true);
1455fd4e5da5Sopenharmony_ci}
1456fd4e5da5Sopenharmony_ci
1457fd4e5da5Sopenharmony_ciTEST_F(DeadBranchElimTest, LeaveContinueBackedgeExtraBlock) {
1458fd4e5da5Sopenharmony_ci  const std::string text = R"(
1459fd4e5da5Sopenharmony_ci; CHECK: OpBranch [[header:%\w+]]
1460fd4e5da5Sopenharmony_ci; CHECK: OpLoopMerge [[merge:%\w+]] [[continue:%\w+]] None
1461fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpBranch [[continue]]
1462fd4e5da5Sopenharmony_ci; CHECK-NEXT: [[continue]] = OpLabel
1463fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpBranchConditional {{%\w+}} [[extra:%\w+]] [[merge]]
1464fd4e5da5Sopenharmony_ci; CHECK-NEXT: [[extra]] = OpLabel
1465fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpBranch [[header]]
1466fd4e5da5Sopenharmony_ci; CHECK-NEXT: [[merge]] = OpLabel
1467fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpReturn
1468fd4e5da5Sopenharmony_ciOpCapability Kernel
1469fd4e5da5Sopenharmony_ciOpCapability Linkage
1470fd4e5da5Sopenharmony_ciOpMemoryModel Logical OpenCL
1471fd4e5da5Sopenharmony_ci%bool = OpTypeBool
1472fd4e5da5Sopenharmony_ci%false = OpConstantFalse %bool
1473fd4e5da5Sopenharmony_ci%void = OpTypeVoid
1474fd4e5da5Sopenharmony_ci%funcTy = OpTypeFunction %void
1475fd4e5da5Sopenharmony_ci%func = OpFunction %void None %funcTy
1476fd4e5da5Sopenharmony_ci%1 = OpLabel
1477fd4e5da5Sopenharmony_ciOpBranch %2
1478fd4e5da5Sopenharmony_ci%2 = OpLabel
1479fd4e5da5Sopenharmony_ciOpLoopMerge %3 %4 None
1480fd4e5da5Sopenharmony_ciOpBranch %4
1481fd4e5da5Sopenharmony_ci%4 = OpLabel
1482fd4e5da5Sopenharmony_ci; Be careful we don't remove the backedge to %2 despite never taking it.
1483fd4e5da5Sopenharmony_ciOpBranchConditional %false %5 %3
1484fd4e5da5Sopenharmony_ci; This block remains live despite being unreachable.
1485fd4e5da5Sopenharmony_ci%5 = OpLabel
1486fd4e5da5Sopenharmony_ciOpBranch %2
1487fd4e5da5Sopenharmony_ci%3 = OpLabel
1488fd4e5da5Sopenharmony_ciOpReturn
1489fd4e5da5Sopenharmony_ciOpFunctionEnd
1490fd4e5da5Sopenharmony_ci)";
1491fd4e5da5Sopenharmony_ci
1492fd4e5da5Sopenharmony_ci  SinglePassRunAndMatch<DeadBranchElimPass>(text, true);
1493fd4e5da5Sopenharmony_ci}
1494fd4e5da5Sopenharmony_ci
1495fd4e5da5Sopenharmony_ciTEST_F(DeadBranchElimTest, RemovePhiWithUnreachableContinue) {
1496fd4e5da5Sopenharmony_ci  const std::string text = R"(
1497fd4e5da5Sopenharmony_ci; CHECK: [[entry:%\w+]] = OpLabel
1498fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpBranch [[header:%\w+]]
1499fd4e5da5Sopenharmony_ci; CHECK: OpLoopMerge [[merge:%\w+]] [[continue:%\w+]] None
1500fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpBranch [[ret:%\w+]]
1501fd4e5da5Sopenharmony_ci; CHECK-NEXT: [[ret]] = OpLabel
1502fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpReturn
1503fd4e5da5Sopenharmony_ci; CHECK: [[continue]] = OpLabel
1504fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpBranch [[header]]
1505fd4e5da5Sopenharmony_ci; CHECK: [[merge]] = OpLabel
1506fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpUnreachable
1507fd4e5da5Sopenharmony_ciOpCapability Kernel
1508fd4e5da5Sopenharmony_ciOpCapability Linkage
1509fd4e5da5Sopenharmony_ciOpMemoryModel Logical OpenCL
1510fd4e5da5Sopenharmony_ciOpName %func "func"
1511fd4e5da5Sopenharmony_ciOpDecorate %func LinkageAttributes "func" Export
1512fd4e5da5Sopenharmony_ci%bool = OpTypeBool
1513fd4e5da5Sopenharmony_ci%false = OpConstantFalse %bool
1514fd4e5da5Sopenharmony_ci%true = OpConstantTrue %bool
1515fd4e5da5Sopenharmony_ci%void = OpTypeVoid
1516fd4e5da5Sopenharmony_ci%funcTy = OpTypeFunction %void
1517fd4e5da5Sopenharmony_ci%func = OpFunction %void None %funcTy
1518fd4e5da5Sopenharmony_ci%1 = OpLabel
1519fd4e5da5Sopenharmony_ciOpBranch %2
1520fd4e5da5Sopenharmony_ci%2 = OpLabel
1521fd4e5da5Sopenharmony_ci%phi = OpPhi %bool %false %1 %true %continue
1522fd4e5da5Sopenharmony_ciOpLoopMerge %merge %continue None
1523fd4e5da5Sopenharmony_ciOpBranch %3
1524fd4e5da5Sopenharmony_ci%3 = OpLabel
1525fd4e5da5Sopenharmony_ciOpReturn
1526fd4e5da5Sopenharmony_ci%continue = OpLabel
1527fd4e5da5Sopenharmony_ciOpBranch %2
1528fd4e5da5Sopenharmony_ci%merge = OpLabel
1529fd4e5da5Sopenharmony_ciOpReturn
1530fd4e5da5Sopenharmony_ciOpFunctionEnd
1531fd4e5da5Sopenharmony_ci)";
1532fd4e5da5Sopenharmony_ci
1533fd4e5da5Sopenharmony_ci  SinglePassRunAndMatch<DeadBranchElimPass>(text, true);
1534fd4e5da5Sopenharmony_ci}
1535fd4e5da5Sopenharmony_ci
1536fd4e5da5Sopenharmony_ciTEST_F(DeadBranchElimTest, UnreachableLoopMergeAndContinueTargets) {
1537fd4e5da5Sopenharmony_ci  const std::string text = R"(
1538fd4e5da5Sopenharmony_ci; CHECK: [[undef:%\w+]] = OpUndef %bool
1539fd4e5da5Sopenharmony_ci; CHECK: OpSelectionMerge [[header:%\w+]]
1540fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpBranchConditional {{%\w+}} [[if_lab:%\w+]] [[else_lab:%\w+]]
1541fd4e5da5Sopenharmony_ci; CHECK: OpPhi %bool %false [[if_lab]] %false [[else_lab]] [[undef]] [[continue:%\w+]]
1542fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpLoopMerge [[merge:%\w+]] [[continue]] None
1543fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpBranch [[ret:%\w+]]
1544fd4e5da5Sopenharmony_ci; CHECK-NEXT: [[ret]] = OpLabel
1545fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpReturn
1546fd4e5da5Sopenharmony_ci; CHECK: [[continue]] = OpLabel
1547fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpBranch [[header]]
1548fd4e5da5Sopenharmony_ci; CHECK: [[merge]] = OpLabel
1549fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpUnreachable
1550fd4e5da5Sopenharmony_ciOpCapability Kernel
1551fd4e5da5Sopenharmony_ciOpCapability Linkage
1552fd4e5da5Sopenharmony_ciOpMemoryModel Logical OpenCL
1553fd4e5da5Sopenharmony_ciOpName %func "func"
1554fd4e5da5Sopenharmony_ciOpDecorate %func LinkageAttributes "func" Export
1555fd4e5da5Sopenharmony_ci%bool = OpTypeBool
1556fd4e5da5Sopenharmony_ci%false = OpConstantFalse %bool
1557fd4e5da5Sopenharmony_ci%true = OpConstantTrue %bool
1558fd4e5da5Sopenharmony_ci%void = OpTypeVoid
1559fd4e5da5Sopenharmony_ci%funcTy = OpTypeFunction %void
1560fd4e5da5Sopenharmony_ci%func = OpFunction %void None %funcTy
1561fd4e5da5Sopenharmony_ci%1 = OpLabel
1562fd4e5da5Sopenharmony_ci%c = OpUndef %bool
1563fd4e5da5Sopenharmony_ciOpSelectionMerge %2 None
1564fd4e5da5Sopenharmony_ciOpBranchConditional %c %if %else
1565fd4e5da5Sopenharmony_ci%if = OpLabel
1566fd4e5da5Sopenharmony_ciOpBranch %2
1567fd4e5da5Sopenharmony_ci%else = OpLabel
1568fd4e5da5Sopenharmony_ciOpBranch %2
1569fd4e5da5Sopenharmony_ci%2 = OpLabel
1570fd4e5da5Sopenharmony_ci%phi = OpPhi %bool %false %if %false %else %true %continue
1571fd4e5da5Sopenharmony_ciOpLoopMerge %merge %continue None
1572fd4e5da5Sopenharmony_ciOpBranch %3
1573fd4e5da5Sopenharmony_ci%3 = OpLabel
1574fd4e5da5Sopenharmony_ciOpReturn
1575fd4e5da5Sopenharmony_ci%continue = OpLabel
1576fd4e5da5Sopenharmony_ciOpBranch %2
1577fd4e5da5Sopenharmony_ci%merge = OpLabel
1578fd4e5da5Sopenharmony_ciOpReturn
1579fd4e5da5Sopenharmony_ciOpFunctionEnd
1580fd4e5da5Sopenharmony_ci)";
1581fd4e5da5Sopenharmony_ci
1582fd4e5da5Sopenharmony_ci  SinglePassRunAndMatch<DeadBranchElimPass>(text, true);
1583fd4e5da5Sopenharmony_ci}
1584fd4e5da5Sopenharmony_ciTEST_F(DeadBranchElimTest, EarlyReconvergence) {
1585fd4e5da5Sopenharmony_ci  const std::string text = R"(
1586fd4e5da5Sopenharmony_ci; CHECK-NOT: OpBranchConditional
1587fd4e5da5Sopenharmony_ci; CHECK: [[logical:%\w+]] = OpLogicalOr
1588fd4e5da5Sopenharmony_ci; CHECK-NOT: OpPhi
1589fd4e5da5Sopenharmony_ci; CHECK: OpLogicalAnd {{%\w+}} {{%\w+}} [[logical]]
1590fd4e5da5Sopenharmony_ciOpCapability Shader
1591fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
1592fd4e5da5Sopenharmony_ciOpEntryPoint Fragment %func "func"
1593fd4e5da5Sopenharmony_ciOpExecutionMode %func OriginUpperLeft
1594fd4e5da5Sopenharmony_ci%void = OpTypeVoid
1595fd4e5da5Sopenharmony_ci%bool = OpTypeBool
1596fd4e5da5Sopenharmony_ci%false = OpConstantFalse %bool
1597fd4e5da5Sopenharmony_ci%true = OpConstantTrue %bool
1598fd4e5da5Sopenharmony_ci%func_ty = OpTypeFunction %void
1599fd4e5da5Sopenharmony_ci%func = OpFunction %void None %func_ty
1600fd4e5da5Sopenharmony_ci%1 = OpLabel
1601fd4e5da5Sopenharmony_ciOpSelectionMerge %2 None
1602fd4e5da5Sopenharmony_ciOpBranchConditional %false %3 %4
1603fd4e5da5Sopenharmony_ci%3 = OpLabel
1604fd4e5da5Sopenharmony_ci%12 = OpLogicalNot %bool %true
1605fd4e5da5Sopenharmony_ciOpBranch %2
1606fd4e5da5Sopenharmony_ci%4 = OpLabel
1607fd4e5da5Sopenharmony_ciOpSelectionMerge %14 None
1608fd4e5da5Sopenharmony_ciOpBranchConditional %false %5 %6
1609fd4e5da5Sopenharmony_ci%5 = OpLabel
1610fd4e5da5Sopenharmony_ci%10 = OpLogicalAnd %bool %true %false
1611fd4e5da5Sopenharmony_ciOpBranch %7
1612fd4e5da5Sopenharmony_ci%6 = OpLabel
1613fd4e5da5Sopenharmony_ci%11 = OpLogicalOr %bool %true %false
1614fd4e5da5Sopenharmony_ciOpBranch %7
1615fd4e5da5Sopenharmony_ci%7 = OpLabel
1616fd4e5da5Sopenharmony_ci; This phi is in a block preceding the merge %14!
1617fd4e5da5Sopenharmony_ci%8 = OpPhi %bool %10 %5 %11 %6
1618fd4e5da5Sopenharmony_ciOpBranch %14
1619fd4e5da5Sopenharmony_ci%14 = OpLabel
1620fd4e5da5Sopenharmony_ciOpBranch %2
1621fd4e5da5Sopenharmony_ci%2 = OpLabel
1622fd4e5da5Sopenharmony_ci%9 = OpPhi %bool %12 %3 %8 %14
1623fd4e5da5Sopenharmony_ci%13 = OpLogicalAnd %bool %true %9
1624fd4e5da5Sopenharmony_ciOpReturn
1625fd4e5da5Sopenharmony_ciOpFunctionEnd
1626fd4e5da5Sopenharmony_ci)";
1627fd4e5da5Sopenharmony_ci
1628fd4e5da5Sopenharmony_ci  SinglePassRunAndMatch<DeadBranchElimPass>(text, true);
1629fd4e5da5Sopenharmony_ci}
1630fd4e5da5Sopenharmony_ci
1631fd4e5da5Sopenharmony_ciTEST_F(DeadBranchElimTest, RemoveUnreachableBlocksFloating) {
1632fd4e5da5Sopenharmony_ci  const std::string text = R"(
1633fd4e5da5Sopenharmony_ci; CHECK: OpFunction
1634fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpLabel
1635fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpReturn
1636fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpFunctionEnd
1637fd4e5da5Sopenharmony_ciOpCapability Kernel
1638fd4e5da5Sopenharmony_ciOpCapability Linkage
1639fd4e5da5Sopenharmony_ciOpMemoryModel Logical OpenCL
1640fd4e5da5Sopenharmony_ciOpName %func "func"
1641fd4e5da5Sopenharmony_ciOpDecorate %func LinkageAttributes "func" Export
1642fd4e5da5Sopenharmony_ci%void = OpTypeVoid
1643fd4e5da5Sopenharmony_ci%1 = OpTypeFunction %void
1644fd4e5da5Sopenharmony_ci%func = OpFunction %void None %1
1645fd4e5da5Sopenharmony_ci%2 = OpLabel
1646fd4e5da5Sopenharmony_ciOpReturn
1647fd4e5da5Sopenharmony_ci%3 = OpLabel
1648fd4e5da5Sopenharmony_ciOpReturn
1649fd4e5da5Sopenharmony_ciOpFunctionEnd
1650fd4e5da5Sopenharmony_ci)";
1651fd4e5da5Sopenharmony_ci
1652fd4e5da5Sopenharmony_ci  SinglePassRunAndMatch<DeadBranchElimPass>(text, true);
1653fd4e5da5Sopenharmony_ci}
1654fd4e5da5Sopenharmony_ci
1655fd4e5da5Sopenharmony_ciTEST_F(DeadBranchElimTest, RemoveUnreachableBlocksFloatingJoin) {
1656fd4e5da5Sopenharmony_ci  const std::string text = R"(
1657fd4e5da5Sopenharmony_ci; CHECK: OpFunction
1658fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpFunctionParameter
1659fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpLabel
1660fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpReturn
1661fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpFunctionEnd
1662fd4e5da5Sopenharmony_ciOpCapability Kernel
1663fd4e5da5Sopenharmony_ciOpCapability Linkage
1664fd4e5da5Sopenharmony_ciOpMemoryModel Logical OpenCL
1665fd4e5da5Sopenharmony_ciOpName %func "func"
1666fd4e5da5Sopenharmony_ciOpDecorate %func LinkageAttributes "func" Export
1667fd4e5da5Sopenharmony_ci%void = OpTypeVoid
1668fd4e5da5Sopenharmony_ci%bool = OpTypeBool
1669fd4e5da5Sopenharmony_ci%false = OpConstantFalse %bool
1670fd4e5da5Sopenharmony_ci%true = OpConstantTrue %bool
1671fd4e5da5Sopenharmony_ci%1 = OpTypeFunction %void %bool
1672fd4e5da5Sopenharmony_ci%func = OpFunction %void None %1
1673fd4e5da5Sopenharmony_ci%bool_param = OpFunctionParameter %bool
1674fd4e5da5Sopenharmony_ci%2 = OpLabel
1675fd4e5da5Sopenharmony_ciOpReturn
1676fd4e5da5Sopenharmony_ci%3 = OpLabel
1677fd4e5da5Sopenharmony_ciOpSelectionMerge %6 None
1678fd4e5da5Sopenharmony_ciOpBranchConditional %bool_param %4 %5
1679fd4e5da5Sopenharmony_ci%4 = OpLabel
1680fd4e5da5Sopenharmony_ciOpBranch %6
1681fd4e5da5Sopenharmony_ci%5 = OpLabel
1682fd4e5da5Sopenharmony_ciOpBranch %6
1683fd4e5da5Sopenharmony_ci%6 = OpLabel
1684fd4e5da5Sopenharmony_ci%7 = OpPhi %bool %true %4 %false %6
1685fd4e5da5Sopenharmony_ciOpReturn
1686fd4e5da5Sopenharmony_ciOpFunctionEnd
1687fd4e5da5Sopenharmony_ci)";
1688fd4e5da5Sopenharmony_ci
1689fd4e5da5Sopenharmony_ci  SinglePassRunAndMatch<DeadBranchElimPass>(text, true);
1690fd4e5da5Sopenharmony_ci}
1691fd4e5da5Sopenharmony_ci
1692fd4e5da5Sopenharmony_ciTEST_F(DeadBranchElimTest, RemoveUnreachableBlocksDeadPhi) {
1693fd4e5da5Sopenharmony_ci  const std::string text = R"(
1694fd4e5da5Sopenharmony_ci; CHECK: OpFunction
1695fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpFunctionParameter
1696fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpLabel
1697fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpBranch [[label:%\w+]]
1698fd4e5da5Sopenharmony_ci; CHECK-NEXT: [[label]] = OpLabel
1699fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpLogicalNot %bool %true
1700fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpReturn
1701fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpFunctionEnd
1702fd4e5da5Sopenharmony_ciOpCapability Kernel
1703fd4e5da5Sopenharmony_ciOpCapability Linkage
1704fd4e5da5Sopenharmony_ciOpMemoryModel Logical OpenCL
1705fd4e5da5Sopenharmony_ciOpName %func "func"
1706fd4e5da5Sopenharmony_ciOpDecorate %func LinkageAttributes "func" Export
1707fd4e5da5Sopenharmony_ci%void = OpTypeVoid
1708fd4e5da5Sopenharmony_ci%bool = OpTypeBool
1709fd4e5da5Sopenharmony_ci%false = OpConstantFalse %bool
1710fd4e5da5Sopenharmony_ci%true = OpConstantTrue %bool
1711fd4e5da5Sopenharmony_ci%1 = OpTypeFunction %void %bool
1712fd4e5da5Sopenharmony_ci%func = OpFunction %void None %1
1713fd4e5da5Sopenharmony_ci%bool_param = OpFunctionParameter %bool
1714fd4e5da5Sopenharmony_ci%2 = OpLabel
1715fd4e5da5Sopenharmony_ciOpBranch %3
1716fd4e5da5Sopenharmony_ci%4 = OpLabel
1717fd4e5da5Sopenharmony_ciOpBranch %3
1718fd4e5da5Sopenharmony_ci%3 = OpLabel
1719fd4e5da5Sopenharmony_ci%5 = OpPhi %bool %true %2 %false %4
1720fd4e5da5Sopenharmony_ci%6 = OpLogicalNot %bool %5
1721fd4e5da5Sopenharmony_ciOpReturn
1722fd4e5da5Sopenharmony_ciOpFunctionEnd
1723fd4e5da5Sopenharmony_ci)";
1724fd4e5da5Sopenharmony_ci
1725fd4e5da5Sopenharmony_ci  SinglePassRunAndMatch<DeadBranchElimPass>(text, true);
1726fd4e5da5Sopenharmony_ci}
1727fd4e5da5Sopenharmony_ci
1728fd4e5da5Sopenharmony_ciTEST_F(DeadBranchElimTest, RemoveUnreachableBlocksPartiallyDeadPhi) {
1729fd4e5da5Sopenharmony_ci  const std::string text = R"(
1730fd4e5da5Sopenharmony_ci; CHECK: OpFunction
1731fd4e5da5Sopenharmony_ci; CHECK-NEXT: [[param:%\w+]] = OpFunctionParameter
1732fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpLabel
1733fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpBranchConditional [[param]] [[merge:%\w+]] [[br:%\w+]]
1734fd4e5da5Sopenharmony_ci; CHECK-NEXT: [[merge]] = OpLabel
1735fd4e5da5Sopenharmony_ci; CHECK-NEXT: [[phi:%\w+]] = OpPhi %bool %true %2 %false [[br]]
1736fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpLogicalNot %bool [[phi]]
1737fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpReturn
1738fd4e5da5Sopenharmony_ci; CHECK-NEXT: [[br]] = OpLabel
1739fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpBranch [[merge]]
1740fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpFunctionEnd
1741fd4e5da5Sopenharmony_ciOpCapability Kernel
1742fd4e5da5Sopenharmony_ciOpCapability Linkage
1743fd4e5da5Sopenharmony_ciOpMemoryModel Logical OpenCL
1744fd4e5da5Sopenharmony_ciOpName %func "func"
1745fd4e5da5Sopenharmony_ciOpDecorate %func LinkageAttributes "func" Export
1746fd4e5da5Sopenharmony_ci%void = OpTypeVoid
1747fd4e5da5Sopenharmony_ci%bool = OpTypeBool
1748fd4e5da5Sopenharmony_ci%false = OpConstantFalse %bool
1749fd4e5da5Sopenharmony_ci%true = OpConstantTrue %bool
1750fd4e5da5Sopenharmony_ci%1 = OpTypeFunction %void %bool
1751fd4e5da5Sopenharmony_ci%func = OpFunction %void None %1
1752fd4e5da5Sopenharmony_ci%bool_param = OpFunctionParameter %bool
1753fd4e5da5Sopenharmony_ci%2 = OpLabel
1754fd4e5da5Sopenharmony_ciOpBranchConditional %bool_param %3 %7
1755fd4e5da5Sopenharmony_ci%7 = OpLabel
1756fd4e5da5Sopenharmony_ciOpBranch %3
1757fd4e5da5Sopenharmony_ci%4 = OpLabel
1758fd4e5da5Sopenharmony_ciOpBranch %3
1759fd4e5da5Sopenharmony_ci%3 = OpLabel
1760fd4e5da5Sopenharmony_ci%5 = OpPhi %bool %true %2 %false %7 %false %4
1761fd4e5da5Sopenharmony_ci%6 = OpLogicalNot %bool %5
1762fd4e5da5Sopenharmony_ciOpReturn
1763fd4e5da5Sopenharmony_ciOpFunctionEnd
1764fd4e5da5Sopenharmony_ci)";
1765fd4e5da5Sopenharmony_ci
1766fd4e5da5Sopenharmony_ci  SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
1767fd4e5da5Sopenharmony_ci  SinglePassRunAndMatch<DeadBranchElimPass>(text, true);
1768fd4e5da5Sopenharmony_ci}
1769fd4e5da5Sopenharmony_ci
1770fd4e5da5Sopenharmony_ciTEST_F(DeadBranchElimTest, LiveHeaderDeadPhi) {
1771fd4e5da5Sopenharmony_ci  const std::string text = R"(
1772fd4e5da5Sopenharmony_ci; CHECK: OpLabel
1773fd4e5da5Sopenharmony_ci; CHECK-NOT: OpBranchConditional
1774fd4e5da5Sopenharmony_ci; CHECK-NOT: OpPhi
1775fd4e5da5Sopenharmony_ci; CHECK: OpLogicalNot %bool %false
1776fd4e5da5Sopenharmony_ciOpCapability Kernel
1777fd4e5da5Sopenharmony_ciOpCapability Linkage
1778fd4e5da5Sopenharmony_ciOpMemoryModel Logical OpenCL
1779fd4e5da5Sopenharmony_ciOpName %func "func"
1780fd4e5da5Sopenharmony_ciOpDecorate %func LinkageAttributes "func" Export
1781fd4e5da5Sopenharmony_ci%void = OpTypeVoid
1782fd4e5da5Sopenharmony_ci%bool = OpTypeBool
1783fd4e5da5Sopenharmony_ci%true = OpConstantTrue %bool
1784fd4e5da5Sopenharmony_ci%false = OpConstantFalse %bool
1785fd4e5da5Sopenharmony_ci%func_ty = OpTypeFunction %void
1786fd4e5da5Sopenharmony_ci%func = OpFunction %void None %func_ty
1787fd4e5da5Sopenharmony_ci%1 = OpLabel
1788fd4e5da5Sopenharmony_ciOpSelectionMerge %3 None
1789fd4e5da5Sopenharmony_ciOpBranchConditional %true %2 %3
1790fd4e5da5Sopenharmony_ci%2 = OpLabel
1791fd4e5da5Sopenharmony_ciOpBranch %3
1792fd4e5da5Sopenharmony_ci%3 = OpLabel
1793fd4e5da5Sopenharmony_ci%5 = OpPhi %bool %true %3 %false %2
1794fd4e5da5Sopenharmony_ci%6 = OpLogicalNot %bool %5
1795fd4e5da5Sopenharmony_ciOpReturn
1796fd4e5da5Sopenharmony_ciOpFunctionEnd
1797fd4e5da5Sopenharmony_ci)";
1798fd4e5da5Sopenharmony_ci
1799fd4e5da5Sopenharmony_ci  SinglePassRunAndMatch<DeadBranchElimPass>(text, true);
1800fd4e5da5Sopenharmony_ci}
1801fd4e5da5Sopenharmony_ci
1802fd4e5da5Sopenharmony_ciTEST_F(DeadBranchElimTest, ExtraBackedgeBlocksLive) {
1803fd4e5da5Sopenharmony_ci  const std::string text = R"(
1804fd4e5da5Sopenharmony_ci; CHECK: [[entry:%\w+]] = OpLabel
1805fd4e5da5Sopenharmony_ci; CHECK-NOT: OpSelectionMerge
1806fd4e5da5Sopenharmony_ci; CHECK: OpBranch [[header:%\w+]]
1807fd4e5da5Sopenharmony_ci; CHECK-NEXT: [[header]] = OpLabel
1808fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpPhi %bool %true [[entry]] %false [[backedge:%\w+]]
1809fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpLoopMerge
1810fd4e5da5Sopenharmony_ciOpCapability Kernel
1811fd4e5da5Sopenharmony_ciOpCapability Linkage
1812fd4e5da5Sopenharmony_ciOpMemoryModel Logical OpenCL
1813fd4e5da5Sopenharmony_ciOpName %func "func"
1814fd4e5da5Sopenharmony_ciOpDecorate %func LinkageAttributes "func" Export
1815fd4e5da5Sopenharmony_ci%void = OpTypeVoid
1816fd4e5da5Sopenharmony_ci%bool = OpTypeBool
1817fd4e5da5Sopenharmony_ci%true = OpConstantTrue %bool
1818fd4e5da5Sopenharmony_ci%false = OpConstantFalse %bool
1819fd4e5da5Sopenharmony_ci%func_ty = OpTypeFunction %void %bool
1820fd4e5da5Sopenharmony_ci%func = OpFunction %void None %func_ty
1821fd4e5da5Sopenharmony_ci%param = OpFunctionParameter %bool
1822fd4e5da5Sopenharmony_ci%entry = OpLabel
1823fd4e5da5Sopenharmony_ciOpSelectionMerge %if_merge None
1824fd4e5da5Sopenharmony_ci; This dead branch is included to ensure the pass does work.
1825fd4e5da5Sopenharmony_ciOpBranchConditional %false %if_merge %loop_header
1826fd4e5da5Sopenharmony_ci%loop_header = OpLabel
1827fd4e5da5Sopenharmony_ci; Both incoming edges are live, so the phi should be untouched.
1828fd4e5da5Sopenharmony_ci%phi = OpPhi %bool %true %entry %false %backedge
1829fd4e5da5Sopenharmony_ciOpLoopMerge %loop_merge %continue None
1830fd4e5da5Sopenharmony_ciOpBranchConditional %param %loop_merge %continue
1831fd4e5da5Sopenharmony_ci%continue = OpLabel
1832fd4e5da5Sopenharmony_ciOpBranch %backedge
1833fd4e5da5Sopenharmony_ci%backedge = OpLabel
1834fd4e5da5Sopenharmony_ciOpBranch %loop_header
1835fd4e5da5Sopenharmony_ci%loop_merge = OpLabel
1836fd4e5da5Sopenharmony_ciOpBranch %if_merge
1837fd4e5da5Sopenharmony_ci%if_merge = OpLabel
1838fd4e5da5Sopenharmony_ciOpReturn
1839fd4e5da5Sopenharmony_ciOpFunctionEnd
1840fd4e5da5Sopenharmony_ci)";
1841fd4e5da5Sopenharmony_ci
1842fd4e5da5Sopenharmony_ci  SinglePassRunAndMatch<DeadBranchElimPass>(text, true);
1843fd4e5da5Sopenharmony_ci}
1844fd4e5da5Sopenharmony_ci
1845fd4e5da5Sopenharmony_ciTEST_F(DeadBranchElimTest, ExtraBackedgeBlocksUnreachable) {
1846fd4e5da5Sopenharmony_ci  const std::string text = R"(
1847fd4e5da5Sopenharmony_ci; CHECK: [[entry:%\w+]] = OpLabel
1848fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpBranch [[header:%\w+]]
1849fd4e5da5Sopenharmony_ci; CHECK-NEXT: [[header]] = OpLabel
1850fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpLoopMerge [[merge:%\w+]] [[continue:%\w+]] None
1851fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpBranch [[merge]]
1852fd4e5da5Sopenharmony_ci; CHECK-NEXT: [[merge]] = OpLabel
1853fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpReturn
1854fd4e5da5Sopenharmony_ci; CHECK-NEXT: [[continue]] = OpLabel
1855fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpBranch [[header]]
1856fd4e5da5Sopenharmony_ciOpCapability Kernel
1857fd4e5da5Sopenharmony_ciOpCapability Linkage
1858fd4e5da5Sopenharmony_ciOpMemoryModel Logical OpenCL
1859fd4e5da5Sopenharmony_ciOpName %func "func"
1860fd4e5da5Sopenharmony_ciOpDecorate %func LinkageAttributes "func" Export
1861fd4e5da5Sopenharmony_ci%void = OpTypeVoid
1862fd4e5da5Sopenharmony_ci%bool = OpTypeBool
1863fd4e5da5Sopenharmony_ci%true = OpConstantTrue %bool
1864fd4e5da5Sopenharmony_ci%false = OpConstantFalse %bool
1865fd4e5da5Sopenharmony_ci%func_ty = OpTypeFunction %void %bool
1866fd4e5da5Sopenharmony_ci%func = OpFunction %void None %func_ty
1867fd4e5da5Sopenharmony_ci%param = OpFunctionParameter %bool
1868fd4e5da5Sopenharmony_ci%entry = OpLabel
1869fd4e5da5Sopenharmony_ciOpBranch %loop_header
1870fd4e5da5Sopenharmony_ci%loop_header = OpLabel
1871fd4e5da5Sopenharmony_ci; Since the continue is unreachable, %backedge will be removed. The phi will
1872fd4e5da5Sopenharmony_ci; instead require an edge from %continue.
1873fd4e5da5Sopenharmony_ci%phi = OpPhi %bool %true %entry %false %backedge
1874fd4e5da5Sopenharmony_ciOpLoopMerge %merge %continue None
1875fd4e5da5Sopenharmony_ciOpBranch %merge
1876fd4e5da5Sopenharmony_ci%continue = OpLabel
1877fd4e5da5Sopenharmony_ciOpBranch %backedge
1878fd4e5da5Sopenharmony_ci%backedge = OpLabel
1879fd4e5da5Sopenharmony_ciOpBranch %loop_header
1880fd4e5da5Sopenharmony_ci%merge = OpLabel
1881fd4e5da5Sopenharmony_ciOpReturn
1882fd4e5da5Sopenharmony_ciOpFunctionEnd
1883fd4e5da5Sopenharmony_ci)";
1884fd4e5da5Sopenharmony_ci
1885fd4e5da5Sopenharmony_ci  SinglePassRunAndMatch<DeadBranchElimPass>(text, true);
1886fd4e5da5Sopenharmony_ci}
1887fd4e5da5Sopenharmony_ci
1888fd4e5da5Sopenharmony_ciTEST_F(DeadBranchElimTest, NoUnnecessaryChanges) {
1889fd4e5da5Sopenharmony_ci  const std::string text = R"(
1890fd4e5da5Sopenharmony_ciOpCapability Shader
1891fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
1892fd4e5da5Sopenharmony_ciOpEntryPoint Fragment %func "func"
1893fd4e5da5Sopenharmony_ci%void = OpTypeVoid
1894fd4e5da5Sopenharmony_ci%bool = OpTypeBool
1895fd4e5da5Sopenharmony_ci%true = OpConstantTrue %bool
1896fd4e5da5Sopenharmony_ci%undef = OpUndef %bool
1897fd4e5da5Sopenharmony_ci%functy = OpTypeFunction %void
1898fd4e5da5Sopenharmony_ci%func = OpFunction %void None %functy
1899fd4e5da5Sopenharmony_ci%1 = OpLabel
1900fd4e5da5Sopenharmony_ciOpBranch %2
1901fd4e5da5Sopenharmony_ci%2 = OpLabel
1902fd4e5da5Sopenharmony_ciOpLoopMerge %4 %5 None
1903fd4e5da5Sopenharmony_ciOpBranch %6
1904fd4e5da5Sopenharmony_ci%6 = OpLabel
1905fd4e5da5Sopenharmony_ciOpReturn
1906fd4e5da5Sopenharmony_ci%5 = OpLabel
1907fd4e5da5Sopenharmony_ciOpBranch %2
1908fd4e5da5Sopenharmony_ci%4 = OpLabel
1909fd4e5da5Sopenharmony_ciOpUnreachable
1910fd4e5da5Sopenharmony_ciOpFunctionEnd
1911fd4e5da5Sopenharmony_ci)";
1912fd4e5da5Sopenharmony_ci
1913fd4e5da5Sopenharmony_ci  auto result = SinglePassRunToBinary<DeadBranchElimPass>(text, true);
1914fd4e5da5Sopenharmony_ci  EXPECT_EQ(std::get<1>(result), Pass::Status::SuccessWithoutChange);
1915fd4e5da5Sopenharmony_ci}
1916fd4e5da5Sopenharmony_ci
1917fd4e5da5Sopenharmony_ciTEST_F(DeadBranchElimTest, ExtraBackedgePartiallyDead) {
1918fd4e5da5Sopenharmony_ci  const std::string text = R"(
1919fd4e5da5Sopenharmony_ci; CHECK: OpLabel
1920fd4e5da5Sopenharmony_ci; CHECK: [[header:%\w+]] = OpLabel
1921fd4e5da5Sopenharmony_ci; CHECK: OpLoopMerge [[merge:%\w+]] [[continue:%\w+]] None
1922fd4e5da5Sopenharmony_ci; CHECK: [[merge]] = OpLabel
1923fd4e5da5Sopenharmony_ci; CHECK: [[continue]] = OpLabel
1924fd4e5da5Sopenharmony_ci; CHECK: OpBranch [[extra:%\w+]]
1925fd4e5da5Sopenharmony_ci; CHECK: [[extra]] = OpLabel
1926fd4e5da5Sopenharmony_ci; CHECK-NOT: OpSelectionMerge
1927fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpBranch [[else:%\w+]]
1928fd4e5da5Sopenharmony_ci; CHECK-NEXT: [[else]] = OpLabel
1929fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpLogicalOr
1930fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpBranch [[backedge:%\w+]]
1931fd4e5da5Sopenharmony_ci; CHECK-NEXT: [[backedge:%\w+]] = OpLabel
1932fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpBranch [[header]]
1933fd4e5da5Sopenharmony_ciOpCapability Kernel
1934fd4e5da5Sopenharmony_ciOpCapability Linkage
1935fd4e5da5Sopenharmony_ciOpMemoryModel Logical OpenCL
1936fd4e5da5Sopenharmony_ciOpName %func "func"
1937fd4e5da5Sopenharmony_ciOpDecorate %func LinkageAttributes "func" Export
1938fd4e5da5Sopenharmony_ci%void = OpTypeVoid
1939fd4e5da5Sopenharmony_ci%bool = OpTypeBool
1940fd4e5da5Sopenharmony_ci%true = OpConstantTrue %bool
1941fd4e5da5Sopenharmony_ci%false = OpConstantFalse %bool
1942fd4e5da5Sopenharmony_ci%func_ty = OpTypeFunction %void %bool
1943fd4e5da5Sopenharmony_ci%func = OpFunction %void None %func_ty
1944fd4e5da5Sopenharmony_ci%param = OpFunctionParameter %bool
1945fd4e5da5Sopenharmony_ci%entry = OpLabel
1946fd4e5da5Sopenharmony_ciOpBranch %loop_header
1947fd4e5da5Sopenharmony_ci%loop_header = OpLabel
1948fd4e5da5Sopenharmony_ciOpLoopMerge %loop_merge %continue None
1949fd4e5da5Sopenharmony_ciOpBranchConditional %param %loop_merge %continue
1950fd4e5da5Sopenharmony_ci%continue = OpLabel
1951fd4e5da5Sopenharmony_ciOpBranch %extra
1952fd4e5da5Sopenharmony_ci%extra = OpLabel
1953fd4e5da5Sopenharmony_ciOpSelectionMerge %backedge None
1954fd4e5da5Sopenharmony_ciOpBranchConditional %false %then %else
1955fd4e5da5Sopenharmony_ci%then = OpLabel
1956fd4e5da5Sopenharmony_ci%and = OpLogicalAnd %bool %true %false
1957fd4e5da5Sopenharmony_ciOpBranch %backedge
1958fd4e5da5Sopenharmony_ci%else = OpLabel
1959fd4e5da5Sopenharmony_ci%or = OpLogicalOr %bool %true %false
1960fd4e5da5Sopenharmony_ciOpBranch %backedge
1961fd4e5da5Sopenharmony_ci%backedge = OpLabel
1962fd4e5da5Sopenharmony_ciOpBranch %loop_header
1963fd4e5da5Sopenharmony_ci%loop_merge = OpLabel
1964fd4e5da5Sopenharmony_ciOpReturn
1965fd4e5da5Sopenharmony_ciOpFunctionEnd
1966fd4e5da5Sopenharmony_ci)";
1967fd4e5da5Sopenharmony_ci
1968fd4e5da5Sopenharmony_ci  SinglePassRunAndMatch<DeadBranchElimPass>(text, true);
1969fd4e5da5Sopenharmony_ci}
1970fd4e5da5Sopenharmony_ci
1971fd4e5da5Sopenharmony_ciTEST_F(DeadBranchElimTest, UnreachableContinuePhiInMerge) {
1972fd4e5da5Sopenharmony_ci  const std::string text = R"(
1973fd4e5da5Sopenharmony_ci; CHECK: [[entry:%\w+]] = OpLabel
1974fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpBranch [[header:%\w+]]
1975fd4e5da5Sopenharmony_ci; CHECK-NEXT: [[header]] = OpLabel
1976fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpLoopMerge [[merge:%\w+]] [[continue:%\w+]] None
1977fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpBranch [[label:%\w+]]
1978fd4e5da5Sopenharmony_ci; CHECK-NEXT: [[label]] = OpLabel
1979fd4e5da5Sopenharmony_ci; CHECK-NEXT: [[fadd:%\w+]] = OpFAdd
1980fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpBranch [[label:%\w+]]
1981fd4e5da5Sopenharmony_ci; CHECK-NEXT: [[label]] = OpLabel
1982fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpBranch [[merge]]
1983fd4e5da5Sopenharmony_ci; CHECK-NEXT: [[continue]] = OpLabel
1984fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpBranch [[header]]
1985fd4e5da5Sopenharmony_ci; CHECK-NEXT: [[merge]] = OpLabel
1986fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpStore {{%\w+}} [[fadd]]
1987fd4e5da5Sopenharmony_ci               OpCapability Shader
1988fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
1989fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
1990fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %main "main" %o
1991fd4e5da5Sopenharmony_ci               OpExecutionMode %main OriginUpperLeft
1992fd4e5da5Sopenharmony_ci               OpSource GLSL 430
1993fd4e5da5Sopenharmony_ci               OpSourceExtension "GL_GOOGLE_cpp_style_line_directive"
1994fd4e5da5Sopenharmony_ci               OpSourceExtension "GL_GOOGLE_include_directive"
1995fd4e5da5Sopenharmony_ci               OpName %main "main"
1996fd4e5da5Sopenharmony_ci               OpName %o "o"
1997fd4e5da5Sopenharmony_ci               OpName %S "S"
1998fd4e5da5Sopenharmony_ci               OpMemberName %S 0 "a"
1999fd4e5da5Sopenharmony_ci               OpName %U_t "U_t"
2000fd4e5da5Sopenharmony_ci               OpMemberName %U_t 0 "g_F"
2001fd4e5da5Sopenharmony_ci               OpMemberName %U_t 1 "g_F2"
2002fd4e5da5Sopenharmony_ci               OpDecorate %o Location 0
2003fd4e5da5Sopenharmony_ci               OpMemberDecorate %S 0 Offset 0
2004fd4e5da5Sopenharmony_ci               OpMemberDecorate %U_t 0 Volatile
2005fd4e5da5Sopenharmony_ci               OpMemberDecorate %U_t 0 Offset 0
2006fd4e5da5Sopenharmony_ci               OpMemberDecorate %U_t 1 Offset 4
2007fd4e5da5Sopenharmony_ci               OpDecorate %U_t BufferBlock
2008fd4e5da5Sopenharmony_ci       %void = OpTypeVoid
2009fd4e5da5Sopenharmony_ci          %7 = OpTypeFunction %void
2010fd4e5da5Sopenharmony_ci      %float = OpTypeFloat 32
2011fd4e5da5Sopenharmony_ci%_ptr_Function_float = OpTypePointer Function %float
2012fd4e5da5Sopenharmony_ci    %float_0 = OpConstant %float 0
2013fd4e5da5Sopenharmony_ci        %int = OpTypeInt 32 1
2014fd4e5da5Sopenharmony_ci%_ptr_Function_int = OpTypePointer Function %int
2015fd4e5da5Sopenharmony_ci      %int_0 = OpConstant %int 0
2016fd4e5da5Sopenharmony_ci     %int_10 = OpConstant %int 10
2017fd4e5da5Sopenharmony_ci       %bool = OpTypeBool
2018fd4e5da5Sopenharmony_ci       %true = OpConstantTrue %bool
2019fd4e5da5Sopenharmony_ci    %float_1 = OpConstant %float 1
2020fd4e5da5Sopenharmony_ci    %float_5 = OpConstant %float 5
2021fd4e5da5Sopenharmony_ci      %int_1 = OpConstant %int 1
2022fd4e5da5Sopenharmony_ci%_ptr_Output_float = OpTypePointer Output %float
2023fd4e5da5Sopenharmony_ci          %o = OpVariable %_ptr_Output_float Output
2024fd4e5da5Sopenharmony_ci          %S = OpTypeStruct %float
2025fd4e5da5Sopenharmony_ci        %U_t = OpTypeStruct %S %S
2026fd4e5da5Sopenharmony_ci%_ptr_Uniform_U_t = OpTypePointer Uniform %U_t
2027fd4e5da5Sopenharmony_ci       %main = OpFunction %void None %7
2028fd4e5da5Sopenharmony_ci         %22 = OpLabel
2029fd4e5da5Sopenharmony_ci               OpBranch %23
2030fd4e5da5Sopenharmony_ci         %23 = OpLabel
2031fd4e5da5Sopenharmony_ci         %24 = OpPhi %float %float_0 %22 %25 %26
2032fd4e5da5Sopenharmony_ci         %27 = OpPhi %int %int_0 %22 %28 %26
2033fd4e5da5Sopenharmony_ci               OpLoopMerge %29 %26 None
2034fd4e5da5Sopenharmony_ci               OpBranch %40
2035fd4e5da5Sopenharmony_ci         %40 = OpLabel
2036fd4e5da5Sopenharmony_ci         %25 = OpFAdd %float %24 %float_1
2037fd4e5da5Sopenharmony_ci               OpSelectionMerge %30 None
2038fd4e5da5Sopenharmony_ci               OpBranchConditional %true %31 %30
2039fd4e5da5Sopenharmony_ci         %31 = OpLabel
2040fd4e5da5Sopenharmony_ci               OpBranch %29
2041fd4e5da5Sopenharmony_ci         %30 = OpLabel
2042fd4e5da5Sopenharmony_ci               OpBranch %26
2043fd4e5da5Sopenharmony_ci         %26 = OpLabel
2044fd4e5da5Sopenharmony_ci         %28 = OpIAdd %int %27 %int_1
2045fd4e5da5Sopenharmony_ci         %32 = OpSLessThan %bool %27 %int_10
2046fd4e5da5Sopenharmony_ci; continue block branches to the header or another none dead block.
2047fd4e5da5Sopenharmony_ci               OpBranchConditional %32 %23 %29
2048fd4e5da5Sopenharmony_ci         %29 = OpLabel
2049fd4e5da5Sopenharmony_ci         %33 = OpPhi %float %24 %26 %25 %31
2050fd4e5da5Sopenharmony_ci               OpStore %o %33
2051fd4e5da5Sopenharmony_ci               OpReturn
2052fd4e5da5Sopenharmony_ci               OpFunctionEnd
2053fd4e5da5Sopenharmony_ci)";
2054fd4e5da5Sopenharmony_ci
2055fd4e5da5Sopenharmony_ci  SinglePassRunAndMatch<DeadBranchElimPass>(text, true);
2056fd4e5da5Sopenharmony_ci}
2057fd4e5da5Sopenharmony_ci
2058fd4e5da5Sopenharmony_ciTEST_F(DeadBranchElimTest, NonStructuredIf) {
2059fd4e5da5Sopenharmony_ci  const std::string text = R"(
2060fd4e5da5Sopenharmony_ci; CHECK-NOT: OpBranchConditional
2061fd4e5da5Sopenharmony_ciOpCapability Kernel
2062fd4e5da5Sopenharmony_ciOpCapability Linkage
2063fd4e5da5Sopenharmony_ciOpMemoryModel Logical OpenCL
2064fd4e5da5Sopenharmony_ciOpDecorate %func LinkageAttributes "func" Export
2065fd4e5da5Sopenharmony_ci%void = OpTypeVoid
2066fd4e5da5Sopenharmony_ci%bool = OpTypeBool
2067fd4e5da5Sopenharmony_ci%true = OpConstantTrue %bool
2068fd4e5da5Sopenharmony_ci%functy = OpTypeFunction %void
2069fd4e5da5Sopenharmony_ci%func = OpFunction %void None %functy
2070fd4e5da5Sopenharmony_ci%entry = OpLabel
2071fd4e5da5Sopenharmony_ciOpBranchConditional %true %then %else
2072fd4e5da5Sopenharmony_ci%then = OpLabel
2073fd4e5da5Sopenharmony_ciOpBranch %final
2074fd4e5da5Sopenharmony_ci%else = OpLabel
2075fd4e5da5Sopenharmony_ciOpBranch %final
2076fd4e5da5Sopenharmony_ci%final = OpLabel
2077fd4e5da5Sopenharmony_ciOpReturn
2078fd4e5da5Sopenharmony_ciOpFunctionEnd
2079fd4e5da5Sopenharmony_ci)";
2080fd4e5da5Sopenharmony_ci
2081fd4e5da5Sopenharmony_ci  SinglePassRunAndMatch<DeadBranchElimPass>(text, true);
2082fd4e5da5Sopenharmony_ci}
2083fd4e5da5Sopenharmony_ci
2084fd4e5da5Sopenharmony_ciTEST_F(DeadBranchElimTest, ReorderBlocks) {
2085fd4e5da5Sopenharmony_ci  const std::string text = R"(
2086fd4e5da5Sopenharmony_ci; CHECK: OpLabel
2087fd4e5da5Sopenharmony_ci; CHECK: OpBranch [[label:%\w+]]
2088fd4e5da5Sopenharmony_ci; CHECK: [[label:%\w+]] = OpLabel
2089fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpLogicalNot
2090fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpBranch [[label:%\w+]]
2091fd4e5da5Sopenharmony_ci; CHECK: [[label]] = OpLabel
2092fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpReturn
2093fd4e5da5Sopenharmony_ciOpCapability Shader
2094fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
2095fd4e5da5Sopenharmony_ciOpEntryPoint Fragment %func "func"
2096fd4e5da5Sopenharmony_ciOpExecutionMode %func OriginUpperLeft
2097fd4e5da5Sopenharmony_ci%void = OpTypeVoid
2098fd4e5da5Sopenharmony_ci%bool = OpTypeBool
2099fd4e5da5Sopenharmony_ci%true = OpConstantTrue %bool
2100fd4e5da5Sopenharmony_ci%func_ty = OpTypeFunction %void
2101fd4e5da5Sopenharmony_ci%func = OpFunction %void None %func_ty
2102fd4e5da5Sopenharmony_ci%1 = OpLabel
2103fd4e5da5Sopenharmony_ciOpSelectionMerge %3 None
2104fd4e5da5Sopenharmony_ciOpBranchConditional %true %2 %3
2105fd4e5da5Sopenharmony_ci%3 = OpLabel
2106fd4e5da5Sopenharmony_ciOpReturn
2107fd4e5da5Sopenharmony_ci%2 = OpLabel
2108fd4e5da5Sopenharmony_ci%not = OpLogicalNot %bool %true
2109fd4e5da5Sopenharmony_ciOpBranch %3
2110fd4e5da5Sopenharmony_ciOpFunctionEnd
2111fd4e5da5Sopenharmony_ci)";
2112fd4e5da5Sopenharmony_ci
2113fd4e5da5Sopenharmony_ci  SinglePassRunAndMatch<DeadBranchElimPass>(text, true);
2114fd4e5da5Sopenharmony_ci}
2115fd4e5da5Sopenharmony_ci
2116fd4e5da5Sopenharmony_ciTEST_F(DeadBranchElimTest, ReorderBlocksMultiple) {
2117fd4e5da5Sopenharmony_ci  // Checks are not important. The validation post optimization is the
2118fd4e5da5Sopenharmony_ci  // important part.
2119fd4e5da5Sopenharmony_ci  const std::string text = R"(
2120fd4e5da5Sopenharmony_ci; CHECK: OpLabel
2121fd4e5da5Sopenharmony_ciOpCapability Shader
2122fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
2123fd4e5da5Sopenharmony_ciOpEntryPoint Fragment %func "func"
2124fd4e5da5Sopenharmony_ciOpExecutionMode %func OriginUpperLeft
2125fd4e5da5Sopenharmony_ci%void = OpTypeVoid
2126fd4e5da5Sopenharmony_ci%bool = OpTypeBool
2127fd4e5da5Sopenharmony_ci%true = OpConstantTrue %bool
2128fd4e5da5Sopenharmony_ci%func_ty = OpTypeFunction %void
2129fd4e5da5Sopenharmony_ci%func = OpFunction %void None %func_ty
2130fd4e5da5Sopenharmony_ci%1 = OpLabel
2131fd4e5da5Sopenharmony_ciOpSelectionMerge %3 None
2132fd4e5da5Sopenharmony_ciOpBranchConditional %true %2 %3
2133fd4e5da5Sopenharmony_ci%3 = OpLabel
2134fd4e5da5Sopenharmony_ciOpReturn
2135fd4e5da5Sopenharmony_ci%2 = OpLabel
2136fd4e5da5Sopenharmony_ciOpBranch %4
2137fd4e5da5Sopenharmony_ci%4 = OpLabel
2138fd4e5da5Sopenharmony_ciOpBranch %3
2139fd4e5da5Sopenharmony_ciOpFunctionEnd
2140fd4e5da5Sopenharmony_ci)";
2141fd4e5da5Sopenharmony_ci
2142fd4e5da5Sopenharmony_ci  SinglePassRunAndMatch<DeadBranchElimPass>(text, true);
2143fd4e5da5Sopenharmony_ci}
2144fd4e5da5Sopenharmony_ci
2145fd4e5da5Sopenharmony_ciTEST_F(DeadBranchElimTest, ReorderBlocksMultiple2) {
2146fd4e5da5Sopenharmony_ci  // Checks are not important. The validation post optimization is the
2147fd4e5da5Sopenharmony_ci  // important part.
2148fd4e5da5Sopenharmony_ci  const std::string text = R"(
2149fd4e5da5Sopenharmony_ci; CHECK: OpLabel
2150fd4e5da5Sopenharmony_ciOpCapability Shader
2151fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
2152fd4e5da5Sopenharmony_ciOpEntryPoint Fragment %func "func"
2153fd4e5da5Sopenharmony_ciOpExecutionMode %func OriginUpperLeft
2154fd4e5da5Sopenharmony_ci%void = OpTypeVoid
2155fd4e5da5Sopenharmony_ci%bool = OpTypeBool
2156fd4e5da5Sopenharmony_ci%true = OpConstantTrue %bool
2157fd4e5da5Sopenharmony_ci%func_ty = OpTypeFunction %void
2158fd4e5da5Sopenharmony_ci%func = OpFunction %void None %func_ty
2159fd4e5da5Sopenharmony_ci%1 = OpLabel
2160fd4e5da5Sopenharmony_ciOpSelectionMerge %3 None
2161fd4e5da5Sopenharmony_ciOpBranchConditional %true %2 %3
2162fd4e5da5Sopenharmony_ci%3 = OpLabel
2163fd4e5da5Sopenharmony_ciOpBranch %5
2164fd4e5da5Sopenharmony_ci%5 = OpLabel
2165fd4e5da5Sopenharmony_ciOpReturn
2166fd4e5da5Sopenharmony_ci%2 = OpLabel
2167fd4e5da5Sopenharmony_ciOpBranch %4
2168fd4e5da5Sopenharmony_ci%4 = OpLabel
2169fd4e5da5Sopenharmony_ciOpBranch %3
2170fd4e5da5Sopenharmony_ciOpFunctionEnd
2171fd4e5da5Sopenharmony_ci)";
2172fd4e5da5Sopenharmony_ci
2173fd4e5da5Sopenharmony_ci  SinglePassRunAndMatch<DeadBranchElimPass>(text, true);
2174fd4e5da5Sopenharmony_ci}
2175fd4e5da5Sopenharmony_ci
2176fd4e5da5Sopenharmony_ciTEST_F(DeadBranchElimTest, SelectionMergeWithEarlyExit1) {
2177fd4e5da5Sopenharmony_ci  // Checks  that if a selection merge construct contains a conditional branch
2178fd4e5da5Sopenharmony_ci  // to the merge node, then the OpSelectionMerge instruction is positioned
2179fd4e5da5Sopenharmony_ci  // correctly.
2180fd4e5da5Sopenharmony_ci  const std::string predefs = R"(
2181fd4e5da5Sopenharmony_ciOpCapability Shader
2182fd4e5da5Sopenharmony_ci%1 = OpExtInstImport "GLSL.std.450"
2183fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
2184fd4e5da5Sopenharmony_ciOpEntryPoint Fragment %main "main"
2185fd4e5da5Sopenharmony_ciOpExecutionMode %main OriginUpperLeft
2186fd4e5da5Sopenharmony_ciOpSource GLSL 140
2187fd4e5da5Sopenharmony_ci%void = OpTypeVoid
2188fd4e5da5Sopenharmony_ci%func_type = OpTypeFunction %void
2189fd4e5da5Sopenharmony_ci%bool = OpTypeBool
2190fd4e5da5Sopenharmony_ci%true = OpConstantTrue %bool
2191fd4e5da5Sopenharmony_ci%undef_bool = OpUndef %bool
2192fd4e5da5Sopenharmony_ci)";
2193fd4e5da5Sopenharmony_ci
2194fd4e5da5Sopenharmony_ci  const std::string body =
2195fd4e5da5Sopenharmony_ci      R"(
2196fd4e5da5Sopenharmony_ci; CHECK: OpFunction
2197fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpLabel
2198fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpBranch [[taken_branch:%\w+]]
2199fd4e5da5Sopenharmony_ci; CHECK-NEXT: [[taken_branch]] = OpLabel
2200fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpSelectionMerge [[merge:%\w+]]
2201fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpBranchConditional {{%\w+}} [[merge]] {{%\w+}}
2202fd4e5da5Sopenharmony_ci%main = OpFunction %void None %func_type
2203fd4e5da5Sopenharmony_ci%entry_bb = OpLabel
2204fd4e5da5Sopenharmony_ciOpSelectionMerge %outer_merge None
2205fd4e5da5Sopenharmony_ciOpBranchConditional %true %bb1 %bb3
2206fd4e5da5Sopenharmony_ci%bb1 = OpLabel
2207fd4e5da5Sopenharmony_ciOpBranchConditional %undef_bool %outer_merge %bb2
2208fd4e5da5Sopenharmony_ci%bb2 = OpLabel
2209fd4e5da5Sopenharmony_ciOpBranch %outer_merge
2210fd4e5da5Sopenharmony_ci%bb3 = OpLabel
2211fd4e5da5Sopenharmony_ciOpBranch %outer_merge
2212fd4e5da5Sopenharmony_ci%outer_merge = OpLabel
2213fd4e5da5Sopenharmony_ciOpReturn
2214fd4e5da5Sopenharmony_ciOpFunctionEnd
2215fd4e5da5Sopenharmony_ci)";
2216fd4e5da5Sopenharmony_ci
2217fd4e5da5Sopenharmony_ci  SinglePassRunAndMatch<DeadBranchElimPass>(predefs + body, true);
2218fd4e5da5Sopenharmony_ci}
2219fd4e5da5Sopenharmony_ci
2220fd4e5da5Sopenharmony_ciTEST_F(DeadBranchElimTest, SelectionMergeWithEarlyExit2) {
2221fd4e5da5Sopenharmony_ci  // Checks  that if a selection merge construct contains a conditional branch
2222fd4e5da5Sopenharmony_ci  // to the merge node, then the OpSelectionMerge instruction is positioned
2223fd4e5da5Sopenharmony_ci  // correctly.
2224fd4e5da5Sopenharmony_ci  const std::string predefs = R"(
2225fd4e5da5Sopenharmony_ciOpCapability Shader
2226fd4e5da5Sopenharmony_ci%1 = OpExtInstImport "GLSL.std.450"
2227fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
2228fd4e5da5Sopenharmony_ciOpEntryPoint Fragment %main "main"
2229fd4e5da5Sopenharmony_ciOpExecutionMode %main OriginUpperLeft
2230fd4e5da5Sopenharmony_ciOpSource GLSL 140
2231fd4e5da5Sopenharmony_ci%void = OpTypeVoid
2232fd4e5da5Sopenharmony_ci%func_type = OpTypeFunction %void
2233fd4e5da5Sopenharmony_ci%bool = OpTypeBool
2234fd4e5da5Sopenharmony_ci%true = OpConstantTrue %bool
2235fd4e5da5Sopenharmony_ci%undef_bool = OpUndef %bool
2236fd4e5da5Sopenharmony_ci)";
2237fd4e5da5Sopenharmony_ci
2238fd4e5da5Sopenharmony_ci  const std::string body =
2239fd4e5da5Sopenharmony_ci      R"(
2240fd4e5da5Sopenharmony_ci; CHECK: OpFunction
2241fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpLabel
2242fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpBranch [[bb1:%\w+]]
2243fd4e5da5Sopenharmony_ci; CHECK-NEXT: [[bb1]] = OpLabel
2244fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpSelectionMerge [[inner_merge:%\w+]]
2245fd4e5da5Sopenharmony_ci; CHECK: [[inner_merge]] = OpLabel
2246fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpSelectionMerge [[outer_merge:%\w+]]
2247fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpBranchConditional {{%\w+}} [[outer_merge]:%\w+]] {{%\w+}}
2248fd4e5da5Sopenharmony_ci; CHECK: [[outer_merge]] = OpLabel
2249fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpReturn
2250fd4e5da5Sopenharmony_ci%main = OpFunction %void None %func_type
2251fd4e5da5Sopenharmony_ci%entry_bb = OpLabel
2252fd4e5da5Sopenharmony_ciOpSelectionMerge %outer_merge None
2253fd4e5da5Sopenharmony_ciOpBranchConditional %true %bb1 %bb5
2254fd4e5da5Sopenharmony_ci%bb1 = OpLabel
2255fd4e5da5Sopenharmony_ciOpSelectionMerge %inner_merge None
2256fd4e5da5Sopenharmony_ciOpBranchConditional %undef_bool %bb2 %bb3
2257fd4e5da5Sopenharmony_ci%bb2 = OpLabel
2258fd4e5da5Sopenharmony_ciOpBranch %inner_merge
2259fd4e5da5Sopenharmony_ci%bb3 = OpLabel
2260fd4e5da5Sopenharmony_ciOpBranch %inner_merge
2261fd4e5da5Sopenharmony_ci%inner_merge = OpLabel
2262fd4e5da5Sopenharmony_ciOpBranchConditional %undef_bool %outer_merge %bb4
2263fd4e5da5Sopenharmony_ci%bb4 = OpLabel
2264fd4e5da5Sopenharmony_ciOpBranch %outer_merge
2265fd4e5da5Sopenharmony_ci%bb5 = OpLabel
2266fd4e5da5Sopenharmony_ciOpBranch %outer_merge
2267fd4e5da5Sopenharmony_ci%outer_merge = OpLabel
2268fd4e5da5Sopenharmony_ciOpReturn
2269fd4e5da5Sopenharmony_ciOpFunctionEnd
2270fd4e5da5Sopenharmony_ci)";
2271fd4e5da5Sopenharmony_ci
2272fd4e5da5Sopenharmony_ci  SinglePassRunAndMatch<DeadBranchElimPass>(predefs + body, true);
2273fd4e5da5Sopenharmony_ci}
2274fd4e5da5Sopenharmony_ci
2275fd4e5da5Sopenharmony_ciTEST_F(DeadBranchElimTest, SelectionMergeWithConditionalExit) {
2276fd4e5da5Sopenharmony_ci  // Checks that if a selection merge construct contains a conditional branch
2277fd4e5da5Sopenharmony_ci  // to the merge node, then we keep the OpSelectionMerge on that branch.
2278fd4e5da5Sopenharmony_ci  const std::string predefs = R"(
2279fd4e5da5Sopenharmony_ciOpCapability Shader
2280fd4e5da5Sopenharmony_ci%1 = OpExtInstImport "GLSL.std.450"
2281fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
2282fd4e5da5Sopenharmony_ciOpEntryPoint Fragment %main "main"
2283fd4e5da5Sopenharmony_ciOpExecutionMode %main OriginUpperLeft
2284fd4e5da5Sopenharmony_ciOpSource GLSL 140
2285fd4e5da5Sopenharmony_ci%void = OpTypeVoid
2286fd4e5da5Sopenharmony_ci%func_type = OpTypeFunction %void
2287fd4e5da5Sopenharmony_ci%bool = OpTypeBool
2288fd4e5da5Sopenharmony_ci%true = OpConstantTrue %bool
2289fd4e5da5Sopenharmony_ci%uint = OpTypeInt 32 0
2290fd4e5da5Sopenharmony_ci%undef_int = OpUndef %uint
2291fd4e5da5Sopenharmony_ci)";
2292fd4e5da5Sopenharmony_ci
2293fd4e5da5Sopenharmony_ci  const std::string body =
2294fd4e5da5Sopenharmony_ci      R"(
2295fd4e5da5Sopenharmony_ci; CHECK: OpLoopMerge [[loop_merge:%\w+]]
2296fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpBranch [[bb1:%\w+]]
2297fd4e5da5Sopenharmony_ci; CHECK: [[bb1]] = OpLabel
2298fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpBranch [[bb2:%\w+]]
2299fd4e5da5Sopenharmony_ci; CHECK: [[bb2]] = OpLabel
2300fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpSelectionMerge [[sel_merge:%\w+]] None
2301fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpSwitch {{%\w+}} [[sel_merge]] 1 [[bb3:%\w+]]
2302fd4e5da5Sopenharmony_ci; CHECK: [[bb3]] = OpLabel
2303fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpBranch [[sel_merge]]
2304fd4e5da5Sopenharmony_ci; CHECK: [[sel_merge]] = OpLabel
2305fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpBranch [[loop_merge]]
2306fd4e5da5Sopenharmony_ci; CHECK: [[loop_merge]] = OpLabel
2307fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpReturn
2308fd4e5da5Sopenharmony_ci%main = OpFunction %void None %func_type
2309fd4e5da5Sopenharmony_ci%entry_bb = OpLabel
2310fd4e5da5Sopenharmony_ciOpBranch %loop_header
2311fd4e5da5Sopenharmony_ci%loop_header = OpLabel
2312fd4e5da5Sopenharmony_ciOpLoopMerge %loop_merge %cont None
2313fd4e5da5Sopenharmony_ciOpBranch %bb1
2314fd4e5da5Sopenharmony_ci%bb1 = OpLabel
2315fd4e5da5Sopenharmony_ciOpSelectionMerge %sel_merge None
2316fd4e5da5Sopenharmony_ciOpBranchConditional %true %bb2 %bb4
2317fd4e5da5Sopenharmony_ci%bb2 = OpLabel
2318fd4e5da5Sopenharmony_ciOpSwitch %undef_int %sel_merge 1 %bb3
2319fd4e5da5Sopenharmony_ci%bb3 = OpLabel
2320fd4e5da5Sopenharmony_ciOpBranch %sel_merge
2321fd4e5da5Sopenharmony_ci%bb4 = OpLabel
2322fd4e5da5Sopenharmony_ciOpBranch %sel_merge
2323fd4e5da5Sopenharmony_ci%sel_merge = OpLabel
2324fd4e5da5Sopenharmony_ciOpBranch %loop_merge
2325fd4e5da5Sopenharmony_ci%cont = OpLabel
2326fd4e5da5Sopenharmony_ciOpBranch %loop_header
2327fd4e5da5Sopenharmony_ci%loop_merge = OpLabel
2328fd4e5da5Sopenharmony_ciOpReturn
2329fd4e5da5Sopenharmony_ciOpFunctionEnd
2330fd4e5da5Sopenharmony_ci)";
2331fd4e5da5Sopenharmony_ci
2332fd4e5da5Sopenharmony_ci  SinglePassRunAndMatch<DeadBranchElimPass>(predefs + body, true);
2333fd4e5da5Sopenharmony_ci}
2334fd4e5da5Sopenharmony_ci
2335fd4e5da5Sopenharmony_ciTEST_F(DeadBranchElimTest, SelectionMergeWithExitToLoop) {
2336fd4e5da5Sopenharmony_ci  // Checks  that if a selection merge construct contains a conditional branch
2337fd4e5da5Sopenharmony_ci  // to a loop surrounding the selection merge, then we do not keep the
2338fd4e5da5Sopenharmony_ci  // OpSelectionMerge instruction.
2339fd4e5da5Sopenharmony_ci  const std::string predefs = R"(
2340fd4e5da5Sopenharmony_ciOpCapability Shader
2341fd4e5da5Sopenharmony_ci%1 = OpExtInstImport "GLSL.std.450"
2342fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
2343fd4e5da5Sopenharmony_ciOpEntryPoint Fragment %main "main"
2344fd4e5da5Sopenharmony_ciOpExecutionMode %main OriginUpperLeft
2345fd4e5da5Sopenharmony_ciOpSource GLSL 140
2346fd4e5da5Sopenharmony_ci%void = OpTypeVoid
2347fd4e5da5Sopenharmony_ci%func_type = OpTypeFunction %void
2348fd4e5da5Sopenharmony_ci%bool = OpTypeBool
2349fd4e5da5Sopenharmony_ci%true = OpConstantTrue %bool
2350fd4e5da5Sopenharmony_ci%undef_bool = OpUndef %bool
2351fd4e5da5Sopenharmony_ci)";
2352fd4e5da5Sopenharmony_ci
2353fd4e5da5Sopenharmony_ci  const std::string body =
2354fd4e5da5Sopenharmony_ci      R"(
2355fd4e5da5Sopenharmony_ci; CHECK: OpLoopMerge [[loop_merge:%\w+]]
2356fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpBranch [[bb1:%\w+]]
2357fd4e5da5Sopenharmony_ci; CHECK: [[bb1]] = OpLabel
2358fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpBranch [[bb2:%\w+]]
2359fd4e5da5Sopenharmony_ci; CHECK: [[bb2]] = OpLabel
2360fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpBranchConditional {{%\w+}} [[bb3:%\w+]] [[loop_merge]]
2361fd4e5da5Sopenharmony_ci; CHECK: [[bb3]] = OpLabel
2362fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpBranch [[sel_merge:%\w+]]
2363fd4e5da5Sopenharmony_ci; CHECK: [[sel_merge]] = OpLabel
2364fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpBranch [[loop_merge]]
2365fd4e5da5Sopenharmony_ci; CHECK: [[loop_merge]] = OpLabel
2366fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpReturn
2367fd4e5da5Sopenharmony_ci%main = OpFunction %void None %func_type
2368fd4e5da5Sopenharmony_ci%entry_bb = OpLabel
2369fd4e5da5Sopenharmony_ciOpBranch %loop_header
2370fd4e5da5Sopenharmony_ci%loop_header = OpLabel
2371fd4e5da5Sopenharmony_ciOpLoopMerge %loop_merge %cont None
2372fd4e5da5Sopenharmony_ciOpBranch %bb1
2373fd4e5da5Sopenharmony_ci%bb1 = OpLabel
2374fd4e5da5Sopenharmony_ciOpSelectionMerge %sel_merge None
2375fd4e5da5Sopenharmony_ciOpBranchConditional %true %bb2 %bb4
2376fd4e5da5Sopenharmony_ci%bb2 = OpLabel
2377fd4e5da5Sopenharmony_ciOpBranchConditional %undef_bool %bb3 %loop_merge
2378fd4e5da5Sopenharmony_ci%bb3 = OpLabel
2379fd4e5da5Sopenharmony_ciOpBranch %sel_merge
2380fd4e5da5Sopenharmony_ci%bb4 = OpLabel
2381fd4e5da5Sopenharmony_ciOpBranch %sel_merge
2382fd4e5da5Sopenharmony_ci%sel_merge = OpLabel
2383fd4e5da5Sopenharmony_ciOpBranch %loop_merge
2384fd4e5da5Sopenharmony_ci%cont = OpLabel
2385fd4e5da5Sopenharmony_ciOpBranch %loop_header
2386fd4e5da5Sopenharmony_ci%loop_merge = OpLabel
2387fd4e5da5Sopenharmony_ciOpReturn
2388fd4e5da5Sopenharmony_ciOpFunctionEnd
2389fd4e5da5Sopenharmony_ci)";
2390fd4e5da5Sopenharmony_ci
2391fd4e5da5Sopenharmony_ci  SinglePassRunAndMatch<DeadBranchElimPass>(predefs + body, true);
2392fd4e5da5Sopenharmony_ci}
2393fd4e5da5Sopenharmony_ci
2394fd4e5da5Sopenharmony_ciTEST_F(DeadBranchElimTest, SelectionMergeWithExitToLoopContinue) {
2395fd4e5da5Sopenharmony_ci  // Checks  that if a selection merge construct contains a conditional branch
2396fd4e5da5Sopenharmony_ci  // to continue of a loop surrounding the selection merge, then we do not keep
2397fd4e5da5Sopenharmony_ci  // the OpSelectionMerge instruction.
2398fd4e5da5Sopenharmony_ci  const std::string predefs = R"(
2399fd4e5da5Sopenharmony_ciOpCapability Shader
2400fd4e5da5Sopenharmony_ci%1 = OpExtInstImport "GLSL.std.450"
2401fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
2402fd4e5da5Sopenharmony_ciOpEntryPoint Fragment %main "main"
2403fd4e5da5Sopenharmony_ciOpExecutionMode %main OriginUpperLeft
2404fd4e5da5Sopenharmony_ciOpSource GLSL 140
2405fd4e5da5Sopenharmony_ci%void = OpTypeVoid
2406fd4e5da5Sopenharmony_ci%func_type = OpTypeFunction %void
2407fd4e5da5Sopenharmony_ci%bool = OpTypeBool
2408fd4e5da5Sopenharmony_ci%true = OpConstantTrue %bool
2409fd4e5da5Sopenharmony_ci%undef_bool = OpUndef %bool
2410fd4e5da5Sopenharmony_ci)";
2411fd4e5da5Sopenharmony_ci
2412fd4e5da5Sopenharmony_ci  const std::string body =
2413fd4e5da5Sopenharmony_ci      R"(;
2414fd4e5da5Sopenharmony_ci; CHECK: OpLabel
2415fd4e5da5Sopenharmony_ci; CHECK: [[loop_header:%\w+]] = OpLabel
2416fd4e5da5Sopenharmony_ci; CHECK: OpLoopMerge [[loop_merge:%\w+]] [[loop_cont:%\w+]]
2417fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpBranch [[bb1:%\w+]]
2418fd4e5da5Sopenharmony_ci; CHECK: [[bb1]] = OpLabel
2419fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpBranch [[bb2:%\w+]]
2420fd4e5da5Sopenharmony_ci; CHECK: [[bb2]] = OpLabel
2421fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpBranchConditional {{%\w+}} [[bb3:%\w+]] [[loop_cont]]
2422fd4e5da5Sopenharmony_ci; CHECK: [[bb3]] = OpLabel
2423fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpBranch [[sel_merge:%\w+]]
2424fd4e5da5Sopenharmony_ci; CHECK: [[sel_merge]] = OpLabel
2425fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpBranch [[loop_merge]]
2426fd4e5da5Sopenharmony_ci; CHECK: [[loop_cont]] = OpLabel
2427fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpBranch [[loop_header]]
2428fd4e5da5Sopenharmony_ci; CHECK: [[loop_merge]] = OpLabel
2429fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpReturn
2430fd4e5da5Sopenharmony_ci%main = OpFunction %void None %func_type
2431fd4e5da5Sopenharmony_ci%entry_bb = OpLabel
2432fd4e5da5Sopenharmony_ciOpBranch %loop_header
2433fd4e5da5Sopenharmony_ci%loop_header = OpLabel
2434fd4e5da5Sopenharmony_ciOpLoopMerge %loop_merge %cont None
2435fd4e5da5Sopenharmony_ciOpBranch %bb1
2436fd4e5da5Sopenharmony_ci%bb1 = OpLabel
2437fd4e5da5Sopenharmony_ciOpSelectionMerge %sel_merge None
2438fd4e5da5Sopenharmony_ciOpBranchConditional %true %bb2 %bb4
2439fd4e5da5Sopenharmony_ci%bb2 = OpLabel
2440fd4e5da5Sopenharmony_ciOpBranchConditional %undef_bool %bb3 %cont
2441fd4e5da5Sopenharmony_ci%bb3 = OpLabel
2442fd4e5da5Sopenharmony_ciOpBranch %sel_merge
2443fd4e5da5Sopenharmony_ci%bb4 = OpLabel
2444fd4e5da5Sopenharmony_ciOpBranch %sel_merge
2445fd4e5da5Sopenharmony_ci%sel_merge = OpLabel
2446fd4e5da5Sopenharmony_ciOpBranch %loop_merge
2447fd4e5da5Sopenharmony_ci%cont = OpLabel
2448fd4e5da5Sopenharmony_ciOpBranch %loop_header
2449fd4e5da5Sopenharmony_ci%loop_merge = OpLabel
2450fd4e5da5Sopenharmony_ciOpReturn
2451fd4e5da5Sopenharmony_ciOpFunctionEnd
2452fd4e5da5Sopenharmony_ci)";
2453fd4e5da5Sopenharmony_ci
2454fd4e5da5Sopenharmony_ci  SinglePassRunAndMatch<DeadBranchElimPass>(predefs + body, true);
2455fd4e5da5Sopenharmony_ci}
2456fd4e5da5Sopenharmony_ci
2457fd4e5da5Sopenharmony_ciTEST_F(DeadBranchElimTest, SelectionMergeWithExitToLoop2) {
2458fd4e5da5Sopenharmony_ci  // Same as |SelectionMergeWithExitToLoop|, except the switch goes to the loop
2459fd4e5da5Sopenharmony_ci  // merge or the selection merge.  In this case, we do not need an
2460fd4e5da5Sopenharmony_ci  // OpSelectionMerge either.
2461fd4e5da5Sopenharmony_ci  const std::string predefs = R"(
2462fd4e5da5Sopenharmony_ciOpCapability Shader
2463fd4e5da5Sopenharmony_ci%1 = OpExtInstImport "GLSL.std.450"
2464fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
2465fd4e5da5Sopenharmony_ciOpEntryPoint Fragment %main "main"
2466fd4e5da5Sopenharmony_ciOpExecutionMode %main OriginUpperLeft
2467fd4e5da5Sopenharmony_ciOpSource GLSL 140
2468fd4e5da5Sopenharmony_ci%void = OpTypeVoid
2469fd4e5da5Sopenharmony_ci%func_type = OpTypeFunction %void
2470fd4e5da5Sopenharmony_ci%bool = OpTypeBool
2471fd4e5da5Sopenharmony_ci%true = OpConstantTrue %bool
2472fd4e5da5Sopenharmony_ci%undef_bool = OpUndef %bool
2473fd4e5da5Sopenharmony_ci)";
2474fd4e5da5Sopenharmony_ci
2475fd4e5da5Sopenharmony_ci  const std::string body =
2476fd4e5da5Sopenharmony_ci      R"(
2477fd4e5da5Sopenharmony_ci; CHECK: OpLoopMerge [[loop_merge:%\w+]]
2478fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpBranch [[bb1:%\w+]]
2479fd4e5da5Sopenharmony_ci; CHECK: [[bb1]] = OpLabel
2480fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpBranch [[bb2:%\w+]]
2481fd4e5da5Sopenharmony_ci; CHECK: [[bb2]] = OpLabel
2482fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpBranchConditional {{%\w+}} [[sel_merge:%\w+]] [[loop_merge]]
2483fd4e5da5Sopenharmony_ci; CHECK: [[sel_merge]] = OpLabel
2484fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpBranch [[loop_merge]]
2485fd4e5da5Sopenharmony_ci; CHECK: [[loop_merge]] = OpLabel
2486fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpReturn
2487fd4e5da5Sopenharmony_ci%main = OpFunction %void None %func_type
2488fd4e5da5Sopenharmony_ci%entry_bb = OpLabel
2489fd4e5da5Sopenharmony_ciOpBranch %loop_header
2490fd4e5da5Sopenharmony_ci%loop_header = OpLabel
2491fd4e5da5Sopenharmony_ciOpLoopMerge %loop_merge %cont None
2492fd4e5da5Sopenharmony_ciOpBranch %bb1
2493fd4e5da5Sopenharmony_ci%bb1 = OpLabel
2494fd4e5da5Sopenharmony_ciOpSelectionMerge %sel_merge None
2495fd4e5da5Sopenharmony_ciOpBranchConditional %true %bb2 %bb4
2496fd4e5da5Sopenharmony_ci%bb2 = OpLabel
2497fd4e5da5Sopenharmony_ciOpBranchConditional %undef_bool %sel_merge %loop_merge
2498fd4e5da5Sopenharmony_ci%bb4 = OpLabel
2499fd4e5da5Sopenharmony_ciOpBranch %sel_merge
2500fd4e5da5Sopenharmony_ci%sel_merge = OpLabel
2501fd4e5da5Sopenharmony_ciOpBranch %loop_merge
2502fd4e5da5Sopenharmony_ci%cont = OpLabel
2503fd4e5da5Sopenharmony_ciOpBranch %loop_header
2504fd4e5da5Sopenharmony_ci%loop_merge = OpLabel
2505fd4e5da5Sopenharmony_ciOpReturn
2506fd4e5da5Sopenharmony_ciOpFunctionEnd
2507fd4e5da5Sopenharmony_ci)";
2508fd4e5da5Sopenharmony_ci
2509fd4e5da5Sopenharmony_ci  SinglePassRunAndMatch<DeadBranchElimPass>(predefs + body, true);
2510fd4e5da5Sopenharmony_ci}
2511fd4e5da5Sopenharmony_ci
2512fd4e5da5Sopenharmony_ciTEST_F(DeadBranchElimTest, SelectionMergeWithExitToLoopContinue2) {
2513fd4e5da5Sopenharmony_ci  // Same as |SelectionMergeWithExitToLoopContinue|, except the branch goes to
2514fd4e5da5Sopenharmony_ci  // the loop continue or the selection merge.  In this case, we do not need an
2515fd4e5da5Sopenharmony_ci  // OpSelectionMerge either.
2516fd4e5da5Sopenharmony_ci  const std::string predefs = R"(
2517fd4e5da5Sopenharmony_ciOpCapability Shader
2518fd4e5da5Sopenharmony_ci%1 = OpExtInstImport "GLSL.std.450"
2519fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
2520fd4e5da5Sopenharmony_ciOpEntryPoint Fragment %main "main"
2521fd4e5da5Sopenharmony_ciOpExecutionMode %main OriginUpperLeft
2522fd4e5da5Sopenharmony_ciOpSource GLSL 140
2523fd4e5da5Sopenharmony_ci%void = OpTypeVoid
2524fd4e5da5Sopenharmony_ci%func_type = OpTypeFunction %void
2525fd4e5da5Sopenharmony_ci%bool = OpTypeBool
2526fd4e5da5Sopenharmony_ci%true = OpConstantTrue %bool
2527fd4e5da5Sopenharmony_ci%undef_bool = OpUndef %bool
2528fd4e5da5Sopenharmony_ci)";
2529fd4e5da5Sopenharmony_ci
2530fd4e5da5Sopenharmony_ci  const std::string body =
2531fd4e5da5Sopenharmony_ci      R"(
2532fd4e5da5Sopenharmony_ci; CHECK: OpLabel
2533fd4e5da5Sopenharmony_ci; CHECK: [[loop_header:%\w+]] = OpLabel
2534fd4e5da5Sopenharmony_ci; CHECK: OpLoopMerge [[loop_merge:%\w+]] [[loop_cont:%\w+]]
2535fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpBranch [[bb1:%\w+]]
2536fd4e5da5Sopenharmony_ci; CHECK: [[bb1]] = OpLabel
2537fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpBranch [[bb2:%\w+]]
2538fd4e5da5Sopenharmony_ci; CHECK: [[bb2]] = OpLabel
2539fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpBranchConditional {{%\w+}} [[sel_merge:%\w+]] [[loop_cont]]
2540fd4e5da5Sopenharmony_ci; CHECK: [[sel_merge]] = OpLabel
2541fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpBranch [[loop_merge]]
2542fd4e5da5Sopenharmony_ci; CHECK: [[loop_cont]] = OpLabel
2543fd4e5da5Sopenharmony_ci; CHECK: OpBranch [[loop_header]]
2544fd4e5da5Sopenharmony_ci; CHECK: [[loop_merge]] = OpLabel
2545fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpReturn
2546fd4e5da5Sopenharmony_ci%main = OpFunction %void None %func_type
2547fd4e5da5Sopenharmony_ci%entry_bb = OpLabel
2548fd4e5da5Sopenharmony_ciOpBranch %loop_header
2549fd4e5da5Sopenharmony_ci%loop_header = OpLabel
2550fd4e5da5Sopenharmony_ciOpLoopMerge %loop_merge %cont None
2551fd4e5da5Sopenharmony_ciOpBranch %bb1
2552fd4e5da5Sopenharmony_ci%bb1 = OpLabel
2553fd4e5da5Sopenharmony_ciOpSelectionMerge %sel_merge None
2554fd4e5da5Sopenharmony_ciOpBranchConditional %true %bb2 %bb4
2555fd4e5da5Sopenharmony_ci%bb2 = OpLabel
2556fd4e5da5Sopenharmony_ciOpBranchConditional %undef_bool %sel_merge %cont
2557fd4e5da5Sopenharmony_ci%bb4 = OpLabel
2558fd4e5da5Sopenharmony_ciOpBranch %sel_merge
2559fd4e5da5Sopenharmony_ci%sel_merge = OpLabel
2560fd4e5da5Sopenharmony_ciOpBranch %loop_merge
2561fd4e5da5Sopenharmony_ci%cont = OpLabel
2562fd4e5da5Sopenharmony_ciOpBranch %loop_header
2563fd4e5da5Sopenharmony_ci%loop_merge = OpLabel
2564fd4e5da5Sopenharmony_ciOpReturn
2565fd4e5da5Sopenharmony_ciOpFunctionEnd
2566fd4e5da5Sopenharmony_ci)";
2567fd4e5da5Sopenharmony_ci
2568fd4e5da5Sopenharmony_ci  SinglePassRunAndMatch<DeadBranchElimPass>(predefs + body, true);
2569fd4e5da5Sopenharmony_ci}
2570fd4e5da5Sopenharmony_ci
2571fd4e5da5Sopenharmony_ciTEST_F(DeadBranchElimTest, SelectionMergeWithExitToLoop3) {
2572fd4e5da5Sopenharmony_ci  // Checks that if a selection merge construct contains a conditional branch
2573fd4e5da5Sopenharmony_ci  // to the selection merge, and another block inside the selection merge,
2574fd4e5da5Sopenharmony_ci  // then we must keep the OpSelectionMerge instruction on that branch.
2575fd4e5da5Sopenharmony_ci  const std::string predefs = R"(
2576fd4e5da5Sopenharmony_ciOpCapability Shader
2577fd4e5da5Sopenharmony_ci%1 = OpExtInstImport "GLSL.std.450"
2578fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
2579fd4e5da5Sopenharmony_ciOpEntryPoint Fragment %main "main"
2580fd4e5da5Sopenharmony_ciOpExecutionMode %main OriginUpperLeft
2581fd4e5da5Sopenharmony_ciOpSource GLSL 140
2582fd4e5da5Sopenharmony_ci%void = OpTypeVoid
2583fd4e5da5Sopenharmony_ci%func_type = OpTypeFunction %void
2584fd4e5da5Sopenharmony_ci%bool = OpTypeBool
2585fd4e5da5Sopenharmony_ci%true = OpConstantTrue %bool
2586fd4e5da5Sopenharmony_ci%uint = OpTypeInt 32 0
2587fd4e5da5Sopenharmony_ci%undef_int = OpUndef %uint
2588fd4e5da5Sopenharmony_ci%undef_bool = OpUndef %bool
2589fd4e5da5Sopenharmony_ci)";
2590fd4e5da5Sopenharmony_ci
2591fd4e5da5Sopenharmony_ci  const std::string body =
2592fd4e5da5Sopenharmony_ci      R"(
2593fd4e5da5Sopenharmony_ci; CHECK: OpLoopMerge [[loop_merge:%\w+]]
2594fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpBranch [[bb1:%\w+]]
2595fd4e5da5Sopenharmony_ci; CHECK: [[bb1]] = OpLabel
2596fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpBranch [[bb2:%\w+]]
2597fd4e5da5Sopenharmony_ci; CHECK: [[bb2]] = OpLabel
2598fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpSelectionMerge [[sel_merge:%\w+]] None
2599fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpBranchConditional {{%\w+}} [[sel_merge]] [[bb3:%\w+]]
2600fd4e5da5Sopenharmony_ci; CHECK: [[bb3]] = OpLabel
2601fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpBranch [[sel_merge]]
2602fd4e5da5Sopenharmony_ci; CHECK: [[sel_merge]] = OpLabel
2603fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpBranch [[loop_merge]]
2604fd4e5da5Sopenharmony_ci; CHECK: [[loop_merge]] = OpLabel
2605fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpReturn
2606fd4e5da5Sopenharmony_ci%main = OpFunction %void None %func_type
2607fd4e5da5Sopenharmony_ci%entry_bb = OpLabel
2608fd4e5da5Sopenharmony_ciOpBranch %loop_header
2609fd4e5da5Sopenharmony_ci%loop_header = OpLabel
2610fd4e5da5Sopenharmony_ciOpLoopMerge %loop_merge %cont None
2611fd4e5da5Sopenharmony_ciOpBranch %bb1
2612fd4e5da5Sopenharmony_ci%bb1 = OpLabel
2613fd4e5da5Sopenharmony_ciOpSelectionMerge %sel_merge None
2614fd4e5da5Sopenharmony_ciOpBranchConditional %true %bb2 %bb4
2615fd4e5da5Sopenharmony_ci%bb2 = OpLabel
2616fd4e5da5Sopenharmony_ci;OpSwitch %undef_int %sel_merge 0 %loop_merge 1 %bb3
2617fd4e5da5Sopenharmony_ciOpBranchConditional %undef_bool %sel_merge %bb3
2618fd4e5da5Sopenharmony_ci%bb3 = OpLabel
2619fd4e5da5Sopenharmony_ciOpBranch %sel_merge
2620fd4e5da5Sopenharmony_ci%bb4 = OpLabel
2621fd4e5da5Sopenharmony_ciOpBranch %sel_merge
2622fd4e5da5Sopenharmony_ci%sel_merge = OpLabel
2623fd4e5da5Sopenharmony_ciOpBranch %loop_merge
2624fd4e5da5Sopenharmony_ci%cont = OpLabel
2625fd4e5da5Sopenharmony_ciOpBranch %loop_header
2626fd4e5da5Sopenharmony_ci%loop_merge = OpLabel
2627fd4e5da5Sopenharmony_ciOpReturn
2628fd4e5da5Sopenharmony_ciOpFunctionEnd
2629fd4e5da5Sopenharmony_ci)";
2630fd4e5da5Sopenharmony_ci
2631fd4e5da5Sopenharmony_ci  SinglePassRunAndMatch<DeadBranchElimPass>(predefs + body, true);
2632fd4e5da5Sopenharmony_ci}
2633fd4e5da5Sopenharmony_ci
2634fd4e5da5Sopenharmony_ciTEST_F(DeadBranchElimTest, SelectionMergeWithExitToLoopContinue3) {
2635fd4e5da5Sopenharmony_ci  // Checks that if a selection merge construct contains a conditional branch
2636fd4e5da5Sopenharmony_ci  // the selection merge, and another block inside the selection merge, then we
2637fd4e5da5Sopenharmony_ci  // must keep the OpSelectionMerge instruction on that branch.
2638fd4e5da5Sopenharmony_ci  const std::string predefs = R"(
2639fd4e5da5Sopenharmony_ciOpCapability Shader
2640fd4e5da5Sopenharmony_ci%1 = OpExtInstImport "GLSL.std.450"
2641fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
2642fd4e5da5Sopenharmony_ciOpEntryPoint Fragment %main "main"
2643fd4e5da5Sopenharmony_ciOpExecutionMode %main OriginUpperLeft
2644fd4e5da5Sopenharmony_ciOpSource GLSL 140
2645fd4e5da5Sopenharmony_ci%void = OpTypeVoid
2646fd4e5da5Sopenharmony_ci%func_type = OpTypeFunction %void
2647fd4e5da5Sopenharmony_ci%bool = OpTypeBool
2648fd4e5da5Sopenharmony_ci%true = OpConstantTrue %bool
2649fd4e5da5Sopenharmony_ci%uint = OpTypeInt 32 0
2650fd4e5da5Sopenharmony_ci%undef_int = OpUndef %uint
2651fd4e5da5Sopenharmony_ci%undef_bool = OpUndef %bool
2652fd4e5da5Sopenharmony_ci)";
2653fd4e5da5Sopenharmony_ci
2654fd4e5da5Sopenharmony_ci  const std::string body =
2655fd4e5da5Sopenharmony_ci      R"(
2656fd4e5da5Sopenharmony_ci; CHECK: OpLabel
2657fd4e5da5Sopenharmony_ci; CHECK: [[loop_header:%\w+]] = OpLabel
2658fd4e5da5Sopenharmony_ci; CHECK: OpLoopMerge [[loop_merge:%\w+]] [[loop_continue:%\w+]]
2659fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpBranch [[bb1:%\w+]]
2660fd4e5da5Sopenharmony_ci; CHECK: [[bb1]] = OpLabel
2661fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpBranch [[bb2:%\w+]]
2662fd4e5da5Sopenharmony_ci; CHECK: [[bb2]] = OpLabel
2663fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpSelectionMerge [[sel_merge:%\w+]] None
2664fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpBranchConditional {{%\w+}} [[sel_merge]] [[bb3:%\w+]]
2665fd4e5da5Sopenharmony_ci; CHECK: [[bb3]] = OpLabel
2666fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpBranch [[sel_merge]]
2667fd4e5da5Sopenharmony_ci; CHECK: [[sel_merge]] = OpLabel
2668fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpBranch [[loop_merge]]
2669fd4e5da5Sopenharmony_ci; CHECK: [[loop_continue]] = OpLabel
2670fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpBranch [[loop_header]]
2671fd4e5da5Sopenharmony_ci; CHECK: [[loop_merge]] = OpLabel
2672fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpReturn
2673fd4e5da5Sopenharmony_ci%main = OpFunction %void None %func_type
2674fd4e5da5Sopenharmony_ci%entry_bb = OpLabel
2675fd4e5da5Sopenharmony_ciOpBranch %loop_header
2676fd4e5da5Sopenharmony_ci%loop_header = OpLabel
2677fd4e5da5Sopenharmony_ciOpLoopMerge %loop_merge %cont None
2678fd4e5da5Sopenharmony_ciOpBranch %bb1
2679fd4e5da5Sopenharmony_ci%bb1 = OpLabel
2680fd4e5da5Sopenharmony_ciOpSelectionMerge %sel_merge None
2681fd4e5da5Sopenharmony_ciOpBranchConditional %true %bb2 %bb4
2682fd4e5da5Sopenharmony_ci%bb2 = OpLabel
2683fd4e5da5Sopenharmony_ciOpBranchConditional %undef_bool %sel_merge %bb3
2684fd4e5da5Sopenharmony_ci%bb3 = OpLabel
2685fd4e5da5Sopenharmony_ciOpBranch %sel_merge
2686fd4e5da5Sopenharmony_ci%bb4 = OpLabel
2687fd4e5da5Sopenharmony_ciOpBranch %sel_merge
2688fd4e5da5Sopenharmony_ci%sel_merge = OpLabel
2689fd4e5da5Sopenharmony_ciOpBranch %loop_merge
2690fd4e5da5Sopenharmony_ci%cont = OpLabel
2691fd4e5da5Sopenharmony_ciOpBranch %loop_header
2692fd4e5da5Sopenharmony_ci%loop_merge = OpLabel
2693fd4e5da5Sopenharmony_ciOpReturn
2694fd4e5da5Sopenharmony_ciOpFunctionEnd
2695fd4e5da5Sopenharmony_ci)";
2696fd4e5da5Sopenharmony_ci
2697fd4e5da5Sopenharmony_ci  SinglePassRunAndMatch<DeadBranchElimPass>(predefs + body, true);
2698fd4e5da5Sopenharmony_ci}
2699fd4e5da5Sopenharmony_ci
2700fd4e5da5Sopenharmony_ciTEST_F(DeadBranchElimTest, SelectionMergeSameAsLoopContinue) {
2701fd4e5da5Sopenharmony_ci  // Same as |SelectionMergeWithExitToLoopContinue|, except the branch in the
2702fd4e5da5Sopenharmony_ci  // selection construct is an |OpSwitch| instead of an |OpConditionalBranch|.
2703fd4e5da5Sopenharmony_ci  // The OpSelectionMerge instruction is not needed in this case either.
2704fd4e5da5Sopenharmony_ci  const std::string predefs = R"(
2705fd4e5da5Sopenharmony_ciOpCapability Shader
2706fd4e5da5Sopenharmony_ci%1 = OpExtInstImport "GLSL.std.450"
2707fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
2708fd4e5da5Sopenharmony_ciOpEntryPoint Fragment %main "main"
2709fd4e5da5Sopenharmony_ciOpExecutionMode %main OriginUpperLeft
2710fd4e5da5Sopenharmony_ciOpSource GLSL 140
2711fd4e5da5Sopenharmony_ci%void = OpTypeVoid
2712fd4e5da5Sopenharmony_ci%func_type = OpTypeFunction %void
2713fd4e5da5Sopenharmony_ci%bool = OpTypeBool
2714fd4e5da5Sopenharmony_ci%true = OpConstantTrue %bool
2715fd4e5da5Sopenharmony_ci%uint = OpTypeInt 32 0
2716fd4e5da5Sopenharmony_ci%undef_bool = OpUndef %bool
2717fd4e5da5Sopenharmony_ci)";
2718fd4e5da5Sopenharmony_ci
2719fd4e5da5Sopenharmony_ci  const std::string body =
2720fd4e5da5Sopenharmony_ci      R"(
2721fd4e5da5Sopenharmony_ci; CHECK: OpLabel
2722fd4e5da5Sopenharmony_ci; CHECK: [[loop_header:%\w+]] = OpLabel
2723fd4e5da5Sopenharmony_ci; CHECK: OpLoopMerge [[loop_merge:%\w+]] [[loop_cont:%\w+]]
2724fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpBranch [[bb1:%\w+]]
2725fd4e5da5Sopenharmony_ci; CHECK: [[bb1]] = OpLabel
2726fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpBranch [[bb2:%\w+]]
2727fd4e5da5Sopenharmony_ci; CHECK: [[bb2]] = OpLabel
2728fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpSelectionMerge [[loop_cont]]
2729fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpBranchConditional {{%\w+}} [[bb3:%\w+]] [[loop_cont]]
2730fd4e5da5Sopenharmony_ci; CHECK: [[bb3]] = OpLabel
2731fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpBranch [[loop_cont]]
2732fd4e5da5Sopenharmony_ci; CHECK: [[loop_cont]] = OpLabel
2733fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpBranchConditional {{%\w+}} [[loop_header]] [[loop_merge]]
2734fd4e5da5Sopenharmony_ci; CHECK: [[loop_merge]] = OpLabel
2735fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpReturn
2736fd4e5da5Sopenharmony_ci%main = OpFunction %void None %func_type
2737fd4e5da5Sopenharmony_ci%entry_bb = OpLabel
2738fd4e5da5Sopenharmony_ciOpBranch %loop_header
2739fd4e5da5Sopenharmony_ci%loop_header = OpLabel
2740fd4e5da5Sopenharmony_ciOpLoopMerge %loop_merge %cont None
2741fd4e5da5Sopenharmony_ciOpBranch %bb1
2742fd4e5da5Sopenharmony_ci%bb1 = OpLabel
2743fd4e5da5Sopenharmony_ciOpSelectionMerge %cont None
2744fd4e5da5Sopenharmony_ciOpBranchConditional %true %bb2 %bb4
2745fd4e5da5Sopenharmony_ci%bb2 = OpLabel
2746fd4e5da5Sopenharmony_ciOpBranchConditional %undef_bool %bb3 %cont
2747fd4e5da5Sopenharmony_ci%bb3 = OpLabel
2748fd4e5da5Sopenharmony_ciOpBranch %cont
2749fd4e5da5Sopenharmony_ci%bb4 = OpLabel
2750fd4e5da5Sopenharmony_ciOpBranch %cont
2751fd4e5da5Sopenharmony_ci%cont = OpLabel
2752fd4e5da5Sopenharmony_ciOpBranchConditional %undef_bool %loop_header %loop_merge
2753fd4e5da5Sopenharmony_ci%loop_merge = OpLabel
2754fd4e5da5Sopenharmony_ciOpReturn
2755fd4e5da5Sopenharmony_ciOpFunctionEnd
2756fd4e5da5Sopenharmony_ci)";
2757fd4e5da5Sopenharmony_ci
2758fd4e5da5Sopenharmony_ci  // The selection merge in the loop naming the continue target as merge is
2759fd4e5da5Sopenharmony_ci  // invalid, but handled by this pass so validation is disabled.
2760fd4e5da5Sopenharmony_ci  SinglePassRunAndMatch<DeadBranchElimPass>(predefs + body, false);
2761fd4e5da5Sopenharmony_ci}
2762fd4e5da5Sopenharmony_ci
2763fd4e5da5Sopenharmony_ciTEST_F(DeadBranchElimTest, SelectionMergeWithNestedLoop) {
2764fd4e5da5Sopenharmony_ci  const std::string body =
2765fd4e5da5Sopenharmony_ci      R"(
2766fd4e5da5Sopenharmony_ci; CHECK: OpSelectionMerge [[merge1:%\w+]]
2767fd4e5da5Sopenharmony_ci; CHECK: [[merge1]] = OpLabel
2768fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpBranch [[preheader:%\w+]]
2769fd4e5da5Sopenharmony_ci; CHECK: [[preheader]] = OpLabel
2770fd4e5da5Sopenharmony_ci; CHECK-NOT: OpLabel
2771fd4e5da5Sopenharmony_ci; CHECK: OpBranch [[header:%\w+]]
2772fd4e5da5Sopenharmony_ci; CHECK: [[header]] = OpLabel
2773fd4e5da5Sopenharmony_ci; CHECK-NOT: OpLabel
2774fd4e5da5Sopenharmony_ci; CHECK: OpLoopMerge [[merge2:%\w+]]
2775fd4e5da5Sopenharmony_ci; CHECK: [[merge2]] = OpLabel
2776fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpUnreachable
2777fd4e5da5Sopenharmony_ci                 OpCapability Shader
2778fd4e5da5Sopenharmony_ci            %1 = OpExtInstImport "GLSL.std.450"
2779fd4e5da5Sopenharmony_ci                 OpMemoryModel Logical GLSL450
2780fd4e5da5Sopenharmony_ci                 OpEntryPoint Fragment %main "main"
2781fd4e5da5Sopenharmony_ci                 OpExecutionMode %main OriginUpperLeft
2782fd4e5da5Sopenharmony_ci                 OpSource ESSL 310
2783fd4e5da5Sopenharmony_ci                 OpName %main "main"
2784fd4e5da5Sopenharmony_ci                 OpName %h "h"
2785fd4e5da5Sopenharmony_ci                 OpName %i "i"
2786fd4e5da5Sopenharmony_ci         %void = OpTypeVoid
2787fd4e5da5Sopenharmony_ci            %3 = OpTypeFunction %void
2788fd4e5da5Sopenharmony_ci         %bool = OpTypeBool
2789fd4e5da5Sopenharmony_ci  %_ptr_Function_bool = OpTypePointer Function %bool
2790fd4e5da5Sopenharmony_ci         %true = OpConstantTrue %bool
2791fd4e5da5Sopenharmony_ci          %int = OpTypeInt 32 1
2792fd4e5da5Sopenharmony_ci  %_ptr_Function_int = OpTypePointer Function %int
2793fd4e5da5Sopenharmony_ci        %int_1 = OpConstant %int 1
2794fd4e5da5Sopenharmony_ci        %int_0 = OpConstant %int 0
2795fd4e5da5Sopenharmony_ci           %27 = OpUndef %bool
2796fd4e5da5Sopenharmony_ci         %main = OpFunction %void None %3
2797fd4e5da5Sopenharmony_ci            %5 = OpLabel
2798fd4e5da5Sopenharmony_ci            %h = OpVariable %_ptr_Function_bool Function
2799fd4e5da5Sopenharmony_ci            %i = OpVariable %_ptr_Function_int Function
2800fd4e5da5Sopenharmony_ci                 OpSelectionMerge %11 None
2801fd4e5da5Sopenharmony_ci                 OpBranchConditional %27 %10 %11
2802fd4e5da5Sopenharmony_ci           %10 = OpLabel
2803fd4e5da5Sopenharmony_ci                 OpBranch %11
2804fd4e5da5Sopenharmony_ci           %11 = OpLabel
2805fd4e5da5Sopenharmony_ci                 OpSelectionMerge %14 None
2806fd4e5da5Sopenharmony_ci                 OpBranchConditional %true %13 %14
2807fd4e5da5Sopenharmony_ci           %13 = OpLabel
2808fd4e5da5Sopenharmony_ci                 OpStore %i %int_1
2809fd4e5da5Sopenharmony_ci                 OpBranch %19
2810fd4e5da5Sopenharmony_ci           %19 = OpLabel
2811fd4e5da5Sopenharmony_ci                 OpLoopMerge %21 %22 None
2812fd4e5da5Sopenharmony_ci                 OpBranch %23
2813fd4e5da5Sopenharmony_ci           %23 = OpLabel
2814fd4e5da5Sopenharmony_ci           %26 = OpSGreaterThan %bool %int_1 %int_0
2815fd4e5da5Sopenharmony_ci                 OpBranchConditional %true %20 %21
2816fd4e5da5Sopenharmony_ci           %20 = OpLabel
2817fd4e5da5Sopenharmony_ci                 OpBranch %22
2818fd4e5da5Sopenharmony_ci           %22 = OpLabel
2819fd4e5da5Sopenharmony_ci                 OpBranch %19
2820fd4e5da5Sopenharmony_ci           %21 = OpLabel
2821fd4e5da5Sopenharmony_ci                 OpBranch %14
2822fd4e5da5Sopenharmony_ci           %14 = OpLabel
2823fd4e5da5Sopenharmony_ci                 OpReturn
2824fd4e5da5Sopenharmony_ci                 OpFunctionEnd
2825fd4e5da5Sopenharmony_ci)";
2826fd4e5da5Sopenharmony_ci
2827fd4e5da5Sopenharmony_ci  SinglePassRunAndMatch<DeadBranchElimPass>(body, true);
2828fd4e5da5Sopenharmony_ci}
2829fd4e5da5Sopenharmony_ci
2830fd4e5da5Sopenharmony_ciTEST_F(DeadBranchElimTest, DontFoldBackedge) {
2831fd4e5da5Sopenharmony_ci  const std::string body =
2832fd4e5da5Sopenharmony_ci      R"(OpCapability Shader
2833fd4e5da5Sopenharmony_ci%1 = OpExtInstImport "GLSL.std.450"
2834fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
2835fd4e5da5Sopenharmony_ciOpEntryPoint Fragment %2 "main"
2836fd4e5da5Sopenharmony_ciOpExecutionMode %2 OriginUpperLeft
2837fd4e5da5Sopenharmony_ci%void = OpTypeVoid
2838fd4e5da5Sopenharmony_ci%4 = OpTypeFunction %void
2839fd4e5da5Sopenharmony_ci%bool = OpTypeBool
2840fd4e5da5Sopenharmony_ci%false = OpConstantFalse %bool
2841fd4e5da5Sopenharmony_ci%2 = OpFunction %void None %4
2842fd4e5da5Sopenharmony_ci%7 = OpLabel
2843fd4e5da5Sopenharmony_ciOpBranch %8
2844fd4e5da5Sopenharmony_ci%8 = OpLabel
2845fd4e5da5Sopenharmony_ciOpLoopMerge %9 %10 None
2846fd4e5da5Sopenharmony_ciOpBranch %11
2847fd4e5da5Sopenharmony_ci%11 = OpLabel
2848fd4e5da5Sopenharmony_ci%12 = OpUndef %bool
2849fd4e5da5Sopenharmony_ciOpSelectionMerge %10 None
2850fd4e5da5Sopenharmony_ciOpBranchConditional %12 %13 %10
2851fd4e5da5Sopenharmony_ci%13 = OpLabel
2852fd4e5da5Sopenharmony_ciOpBranch %9
2853fd4e5da5Sopenharmony_ci%10 = OpLabel
2854fd4e5da5Sopenharmony_ciOpBranch %14
2855fd4e5da5Sopenharmony_ci%14 = OpLabel
2856fd4e5da5Sopenharmony_ciOpBranchConditional %false %8 %9
2857fd4e5da5Sopenharmony_ci%9 = OpLabel
2858fd4e5da5Sopenharmony_ciOpReturn
2859fd4e5da5Sopenharmony_ciOpFunctionEnd
2860fd4e5da5Sopenharmony_ci)";
2861fd4e5da5Sopenharmony_ci
2862fd4e5da5Sopenharmony_ci  SinglePassRunAndCheck<DeadBranchElimPass>(body, body, true);
2863fd4e5da5Sopenharmony_ci}
2864fd4e5da5Sopenharmony_ci
2865fd4e5da5Sopenharmony_ciTEST_F(DeadBranchElimTest, FoldBackedgeToHeader) {
2866fd4e5da5Sopenharmony_ci  const std::string body =
2867fd4e5da5Sopenharmony_ci      R"(
2868fd4e5da5Sopenharmony_ci; CHECK: OpLabel
2869fd4e5da5Sopenharmony_ci; CHECK: [[header:%\w+]] = OpLabel
2870fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpLoopMerge {{%\w+}} [[cont:%\w+]]
2871fd4e5da5Sopenharmony_ci; CHECK: [[cont]] = OpLabel
2872fd4e5da5Sopenharmony_ci; This branch may not be in the continue block, but must come after it.
2873fd4e5da5Sopenharmony_ci; CHECK: OpBranch [[header]]
2874fd4e5da5Sopenharmony_ciOpCapability Shader
2875fd4e5da5Sopenharmony_ci%1 = OpExtInstImport "GLSL.std.450"
2876fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
2877fd4e5da5Sopenharmony_ciOpEntryPoint Fragment %2 "main"
2878fd4e5da5Sopenharmony_ciOpExecutionMode %2 OriginUpperLeft
2879fd4e5da5Sopenharmony_ci%void = OpTypeVoid
2880fd4e5da5Sopenharmony_ci%4 = OpTypeFunction %void
2881fd4e5da5Sopenharmony_ci%bool = OpTypeBool
2882fd4e5da5Sopenharmony_ci%true = OpConstantTrue %bool
2883fd4e5da5Sopenharmony_ci%2 = OpFunction %void None %4
2884fd4e5da5Sopenharmony_ci%7 = OpLabel
2885fd4e5da5Sopenharmony_ciOpBranch %8
2886fd4e5da5Sopenharmony_ci%8 = OpLabel
2887fd4e5da5Sopenharmony_ciOpLoopMerge %9 %10 None
2888fd4e5da5Sopenharmony_ciOpBranch %11
2889fd4e5da5Sopenharmony_ci%11 = OpLabel
2890fd4e5da5Sopenharmony_ci%12 = OpUndef %bool
2891fd4e5da5Sopenharmony_ciOpSelectionMerge %10 None
2892fd4e5da5Sopenharmony_ciOpBranchConditional %12 %13 %10
2893fd4e5da5Sopenharmony_ci%13 = OpLabel
2894fd4e5da5Sopenharmony_ciOpBranch %9
2895fd4e5da5Sopenharmony_ci%10 = OpLabel
2896fd4e5da5Sopenharmony_ciOpBranch %14
2897fd4e5da5Sopenharmony_ci%14 = OpLabel
2898fd4e5da5Sopenharmony_ciOpBranchConditional %true %8 %9
2899fd4e5da5Sopenharmony_ci%9 = OpLabel
2900fd4e5da5Sopenharmony_ciOpReturn
2901fd4e5da5Sopenharmony_ciOpFunctionEnd
2902fd4e5da5Sopenharmony_ci)";
2903fd4e5da5Sopenharmony_ci
2904fd4e5da5Sopenharmony_ci  // The selection merge in the loop naming the continue target as merge is
2905fd4e5da5Sopenharmony_ci  // invalid, but handled by this pass so validation is disabled.
2906fd4e5da5Sopenharmony_ci  SinglePassRunAndMatch<DeadBranchElimPass>(body, false);
2907fd4e5da5Sopenharmony_ci}
2908fd4e5da5Sopenharmony_ci
2909fd4e5da5Sopenharmony_ciTEST_F(DeadBranchElimTest, UnreachableMergeAndContinueSameBlock) {
2910fd4e5da5Sopenharmony_ci  const std::string spirv = R"(
2911fd4e5da5Sopenharmony_ci; CHECK: OpLabel
2912fd4e5da5Sopenharmony_ci; CHECK: [[outer:%\w+]] = OpLabel
2913fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpLoopMerge [[outer_merge:%\w+]] [[outer_cont:%\w+]] None
2914fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpBranch [[inner:%\w+]]
2915fd4e5da5Sopenharmony_ci; CHECK: [[inner]] = OpLabel
2916fd4e5da5Sopenharmony_ci; CHECK: OpLoopMerge [[inner_merge:%\w+]] [[inner_cont:%\w+]] None
2917fd4e5da5Sopenharmony_ci; CHECK: [[inner_cont]] = OpLabel
2918fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpBranch [[inner]]
2919fd4e5da5Sopenharmony_ci; CHECK: [[inner_merge]] = OpLabel
2920fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpUnreachable
2921fd4e5da5Sopenharmony_ci; CHECK: [[outer_cont]] = OpLabel
2922fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpBranch [[outer]]
2923fd4e5da5Sopenharmony_ci; CHECK: [[outer_merge]] = OpLabel
2924fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpUnreachable
2925fd4e5da5Sopenharmony_ciOpCapability Shader
2926fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
2927fd4e5da5Sopenharmony_ciOpEntryPoint GLCompute %main "main"
2928fd4e5da5Sopenharmony_ciOpExecutionMode %main LocalSize 1 1 1
2929fd4e5da5Sopenharmony_ci%void = OpTypeVoid
2930fd4e5da5Sopenharmony_ci%bool = OpTypeBool
2931fd4e5da5Sopenharmony_ci%true = OpConstantTrue %bool
2932fd4e5da5Sopenharmony_ci%void_fn = OpTypeFunction %void
2933fd4e5da5Sopenharmony_ci%main = OpFunction %void None %void_fn
2934fd4e5da5Sopenharmony_ci%entry = OpLabel
2935fd4e5da5Sopenharmony_ciOpBranch %outer_loop
2936fd4e5da5Sopenharmony_ci%outer_loop = OpLabel
2937fd4e5da5Sopenharmony_ciOpLoopMerge %outer_merge %outer_continue None
2938fd4e5da5Sopenharmony_ciOpBranch %inner_loop
2939fd4e5da5Sopenharmony_ci%inner_loop = OpLabel
2940fd4e5da5Sopenharmony_ciOpLoopMerge %inner_merge %inner_continue None
2941fd4e5da5Sopenharmony_ciOpBranch %inner_body
2942fd4e5da5Sopenharmony_ci%inner_body = OpLabel
2943fd4e5da5Sopenharmony_ciOpSelectionMerge %inner_continue None
2944fd4e5da5Sopenharmony_ciOpBranchConditional %true %ret %inner_continue
2945fd4e5da5Sopenharmony_ci%ret = OpLabel
2946fd4e5da5Sopenharmony_ciOpReturn
2947fd4e5da5Sopenharmony_ci%inner_continue = OpLabel
2948fd4e5da5Sopenharmony_ciOpBranchConditional %true %inner_merge %inner_loop
2949fd4e5da5Sopenharmony_ci%inner_merge = OpLabel
2950fd4e5da5Sopenharmony_ciOpBranch %outer_continue
2951fd4e5da5Sopenharmony_ci%outer_continue = OpLabel
2952fd4e5da5Sopenharmony_ciOpBranchConditional %true %outer_merge %outer_loop
2953fd4e5da5Sopenharmony_ci%outer_merge = OpLabel
2954fd4e5da5Sopenharmony_ciOpReturn
2955fd4e5da5Sopenharmony_ciOpFunctionEnd
2956fd4e5da5Sopenharmony_ci)";
2957fd4e5da5Sopenharmony_ci
2958fd4e5da5Sopenharmony_ci  SinglePassRunAndMatch<DeadBranchElimPass>(spirv, true);
2959fd4e5da5Sopenharmony_ci}
2960fd4e5da5Sopenharmony_ci
2961fd4e5da5Sopenharmony_ci// Fold a switch with a nested break.  The only case should be the default.
2962fd4e5da5Sopenharmony_ciTEST_F(DeadBranchElimTest, FoldSwitchWithNestedBreak) {
2963fd4e5da5Sopenharmony_ci  const std::string spirv = R"(
2964fd4e5da5Sopenharmony_ci; CHECK: OpSwitch %int_3 [[case_bb:%\w+]]{{[[:space:]]}}
2965fd4e5da5Sopenharmony_ci; CHECK: [[case_bb]] = OpLabel
2966fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpUndef
2967fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpSelectionMerge
2968fd4e5da5Sopenharmony_ci               OpCapability Shader
2969fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
2970fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
2971fd4e5da5Sopenharmony_ci               OpEntryPoint Vertex %2 "main"
2972fd4e5da5Sopenharmony_ci               OpSource GLSL 450
2973fd4e5da5Sopenharmony_ci       %void = OpTypeVoid
2974fd4e5da5Sopenharmony_ci          %4 = OpTypeFunction %void
2975fd4e5da5Sopenharmony_ci        %int = OpTypeInt 32 1
2976fd4e5da5Sopenharmony_ci%_ptr_Function_int = OpTypePointer Function %int
2977fd4e5da5Sopenharmony_ci      %int_3 = OpConstant %int 3
2978fd4e5da5Sopenharmony_ci      %int_1 = OpConstant %int 1
2979fd4e5da5Sopenharmony_ci       %bool = OpTypeBool
2980fd4e5da5Sopenharmony_ci          %2 = OpFunction %void None %4
2981fd4e5da5Sopenharmony_ci         %10 = OpLabel
2982fd4e5da5Sopenharmony_ci               OpSelectionMerge %11 None
2983fd4e5da5Sopenharmony_ci               OpSwitch %int_3 %12 3 %13
2984fd4e5da5Sopenharmony_ci         %12 = OpLabel
2985fd4e5da5Sopenharmony_ci               OpBranch %11
2986fd4e5da5Sopenharmony_ci         %13 = OpLabel
2987fd4e5da5Sopenharmony_ci         %14 = OpUndef %bool
2988fd4e5da5Sopenharmony_ci               OpSelectionMerge %15 None
2989fd4e5da5Sopenharmony_ci               OpBranchConditional %14 %16 %15
2990fd4e5da5Sopenharmony_ci         %16 = OpLabel
2991fd4e5da5Sopenharmony_ci               OpBranch %11
2992fd4e5da5Sopenharmony_ci         %15 = OpLabel
2993fd4e5da5Sopenharmony_ci               OpBranch %11
2994fd4e5da5Sopenharmony_ci         %11 = OpLabel
2995fd4e5da5Sopenharmony_ci               OpReturn
2996fd4e5da5Sopenharmony_ci               OpFunctionEnd
2997fd4e5da5Sopenharmony_ci)";
2998fd4e5da5Sopenharmony_ci
2999fd4e5da5Sopenharmony_ci  SinglePassRunAndMatch<DeadBranchElimPass>(spirv, true);
3000fd4e5da5Sopenharmony_ci}
3001fd4e5da5Sopenharmony_ci
3002fd4e5da5Sopenharmony_ciTEST_F(DeadBranchElimTest, FoldBranchWithBreakToSwitch) {
3003fd4e5da5Sopenharmony_ci  const std::string spirv = R"(
3004fd4e5da5Sopenharmony_ci; CHECK: OpSelectionMerge [[sel_merge:%\w+]]
3005fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpSwitch {{%\w+}} {{%\w+}} 3 [[bb:%\w+]]
3006fd4e5da5Sopenharmony_ci; CHECK: [[bb]] = OpLabel
3007fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpBranch [[bb2:%\w+]]
3008fd4e5da5Sopenharmony_ci; CHECK: [[bb2]] = OpLabel
3009fd4e5da5Sopenharmony_ci; CHECK-NOT: OpSelectionMerge
3010fd4e5da5Sopenharmony_ci; CHECK: OpFunctionEnd
3011fd4e5da5Sopenharmony_ci               OpCapability Shader
3012fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
3013fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
3014fd4e5da5Sopenharmony_ci               OpEntryPoint Vertex %2 "main"
3015fd4e5da5Sopenharmony_ci               OpSource GLSL 450
3016fd4e5da5Sopenharmony_ci       %void = OpTypeVoid
3017fd4e5da5Sopenharmony_ci          %4 = OpTypeFunction %void
3018fd4e5da5Sopenharmony_ci        %int = OpTypeInt 32 1
3019fd4e5da5Sopenharmony_ci%_ptr_Function_int = OpTypePointer Function %int
3020fd4e5da5Sopenharmony_ci      %int_3 = OpConstant %int 3
3021fd4e5da5Sopenharmony_ci      %int_1 = OpConstant %int 1
3022fd4e5da5Sopenharmony_ci       %bool = OpTypeBool
3023fd4e5da5Sopenharmony_ci       %true = OpConstantTrue %bool
3024fd4e5da5Sopenharmony_ci          %2 = OpFunction %void None %4
3025fd4e5da5Sopenharmony_ci         %10 = OpLabel
3026fd4e5da5Sopenharmony_ci  %undef_int = OpUndef %int
3027fd4e5da5Sopenharmony_ci               OpSelectionMerge %11 None
3028fd4e5da5Sopenharmony_ci               OpSwitch %undef_int %12 3 %13
3029fd4e5da5Sopenharmony_ci         %12 = OpLabel
3030fd4e5da5Sopenharmony_ci               OpBranch %11
3031fd4e5da5Sopenharmony_ci         %13 = OpLabel
3032fd4e5da5Sopenharmony_ci               OpSelectionMerge %15 None
3033fd4e5da5Sopenharmony_ci               OpBranchConditional %true %16 %15
3034fd4e5da5Sopenharmony_ci         %16 = OpLabel
3035fd4e5da5Sopenharmony_ci         %14 = OpUndef %bool
3036fd4e5da5Sopenharmony_ci               OpBranchConditional %14 %11 %17
3037fd4e5da5Sopenharmony_ci         %17 = OpLabel
3038fd4e5da5Sopenharmony_ci               OpBranch %15
3039fd4e5da5Sopenharmony_ci         %15 = OpLabel
3040fd4e5da5Sopenharmony_ci               OpBranch %11
3041fd4e5da5Sopenharmony_ci         %11 = OpLabel
3042fd4e5da5Sopenharmony_ci               OpReturn
3043fd4e5da5Sopenharmony_ci               OpFunctionEnd
3044fd4e5da5Sopenharmony_ci)";
3045fd4e5da5Sopenharmony_ci
3046fd4e5da5Sopenharmony_ci  SinglePassRunAndMatch<DeadBranchElimPass>(spirv, true);
3047fd4e5da5Sopenharmony_ci}
3048fd4e5da5Sopenharmony_ci
3049fd4e5da5Sopenharmony_ciTEST_F(DeadBranchElimTest, IfInSwitch) {
3050fd4e5da5Sopenharmony_ci  // #version 310 es
3051fd4e5da5Sopenharmony_ci  //
3052fd4e5da5Sopenharmony_ci  // void main()
3053fd4e5da5Sopenharmony_ci  // {
3054fd4e5da5Sopenharmony_ci  //  switch(0)
3055fd4e5da5Sopenharmony_ci  //  {
3056fd4e5da5Sopenharmony_ci  //   case 0:
3057fd4e5da5Sopenharmony_ci  //   if(false)
3058fd4e5da5Sopenharmony_ci  //   {
3059fd4e5da5Sopenharmony_ci  //   }
3060fd4e5da5Sopenharmony_ci  //   else
3061fd4e5da5Sopenharmony_ci  //   {
3062fd4e5da5Sopenharmony_ci  //   }
3063fd4e5da5Sopenharmony_ci  //  }
3064fd4e5da5Sopenharmony_ci  // }
3065fd4e5da5Sopenharmony_ci
3066fd4e5da5Sopenharmony_ci  const std::string before =
3067fd4e5da5Sopenharmony_ci      R"(OpCapability Shader
3068fd4e5da5Sopenharmony_ci%1 = OpExtInstImport "GLSL.std.450"
3069fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
3070fd4e5da5Sopenharmony_ciOpEntryPoint Fragment %main "main"
3071fd4e5da5Sopenharmony_ciOpExecutionMode %main OriginUpperLeft
3072fd4e5da5Sopenharmony_ciOpSource ESSL 310
3073fd4e5da5Sopenharmony_ciOpName %main "main"
3074fd4e5da5Sopenharmony_ci%void = OpTypeVoid
3075fd4e5da5Sopenharmony_ci%3 = OpTypeFunction %void
3076fd4e5da5Sopenharmony_ci%int = OpTypeInt 32 1
3077fd4e5da5Sopenharmony_ci%int_0 = OpConstant %int 0
3078fd4e5da5Sopenharmony_ci%bool = OpTypeBool
3079fd4e5da5Sopenharmony_ci%false = OpConstantFalse %bool
3080fd4e5da5Sopenharmony_ci%main = OpFunction %void None %3
3081fd4e5da5Sopenharmony_ci%5 = OpLabel
3082fd4e5da5Sopenharmony_ciOpSelectionMerge %9 None
3083fd4e5da5Sopenharmony_ciOpSwitch %int_0 %9 0 %8
3084fd4e5da5Sopenharmony_ci%8 = OpLabel
3085fd4e5da5Sopenharmony_ciOpSelectionMerge %13 None
3086fd4e5da5Sopenharmony_ciOpBranchConditional %false %12 %13
3087fd4e5da5Sopenharmony_ci%12 = OpLabel
3088fd4e5da5Sopenharmony_ciOpBranch %13
3089fd4e5da5Sopenharmony_ci%13 = OpLabel
3090fd4e5da5Sopenharmony_ciOpBranch %9
3091fd4e5da5Sopenharmony_ci%9 = OpLabel
3092fd4e5da5Sopenharmony_ciOpReturn
3093fd4e5da5Sopenharmony_ciOpFunctionEnd
3094fd4e5da5Sopenharmony_ci)";
3095fd4e5da5Sopenharmony_ci
3096fd4e5da5Sopenharmony_ci  const std::string after =
3097fd4e5da5Sopenharmony_ci      R"(OpCapability Shader
3098fd4e5da5Sopenharmony_ci%1 = OpExtInstImport "GLSL.std.450"
3099fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
3100fd4e5da5Sopenharmony_ciOpEntryPoint Fragment %main "main"
3101fd4e5da5Sopenharmony_ciOpExecutionMode %main OriginUpperLeft
3102fd4e5da5Sopenharmony_ciOpSource ESSL 310
3103fd4e5da5Sopenharmony_ciOpName %main "main"
3104fd4e5da5Sopenharmony_ci%void = OpTypeVoid
3105fd4e5da5Sopenharmony_ci%4 = OpTypeFunction %void
3106fd4e5da5Sopenharmony_ci%int = OpTypeInt 32 1
3107fd4e5da5Sopenharmony_ci%int_0 = OpConstant %int 0
3108fd4e5da5Sopenharmony_ci%bool = OpTypeBool
3109fd4e5da5Sopenharmony_ci%false = OpConstantFalse %bool
3110fd4e5da5Sopenharmony_ci%main = OpFunction %void None %4
3111fd4e5da5Sopenharmony_ci%9 = OpLabel
3112fd4e5da5Sopenharmony_ciOpBranch %11
3113fd4e5da5Sopenharmony_ci%11 = OpLabel
3114fd4e5da5Sopenharmony_ciOpBranch %12
3115fd4e5da5Sopenharmony_ci%12 = OpLabel
3116fd4e5da5Sopenharmony_ciOpBranch %10
3117fd4e5da5Sopenharmony_ci%10 = OpLabel
3118fd4e5da5Sopenharmony_ciOpReturn
3119fd4e5da5Sopenharmony_ciOpFunctionEnd
3120fd4e5da5Sopenharmony_ci)";
3121fd4e5da5Sopenharmony_ci
3122fd4e5da5Sopenharmony_ci  SinglePassRunAndCheck<DeadBranchElimPass>(before, after, true, true);
3123fd4e5da5Sopenharmony_ci}
3124fd4e5da5Sopenharmony_ci
3125fd4e5da5Sopenharmony_ciTEST_F(DeadBranchElimTest, BreakInNestedHeaderWithSingleCase) {
3126fd4e5da5Sopenharmony_ci  const std::string text = R"(OpCapability Shader
3127fd4e5da5Sopenharmony_ci%1 = OpExtInstImport "GLSL.std.450"
3128fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
3129fd4e5da5Sopenharmony_ciOpEntryPoint Fragment %main "main"
3130fd4e5da5Sopenharmony_ciOpExecutionMode %main OriginUpperLeft
3131fd4e5da5Sopenharmony_ciOpSource GLSL 450
3132fd4e5da5Sopenharmony_ciOpName %main "main"
3133fd4e5da5Sopenharmony_ci%void = OpTypeVoid
3134fd4e5da5Sopenharmony_ci%4 = OpTypeFunction %void
3135fd4e5da5Sopenharmony_ci%bool = OpTypeBool
3136fd4e5da5Sopenharmony_ci%uint = OpTypeInt 32 0
3137fd4e5da5Sopenharmony_ci%uint_0 = OpConstant %uint 0
3138fd4e5da5Sopenharmony_ci%8 = OpUndef %bool
3139fd4e5da5Sopenharmony_ci%main = OpFunction %void None %4
3140fd4e5da5Sopenharmony_ci%9 = OpLabel
3141fd4e5da5Sopenharmony_ciOpSelectionMerge %10 None
3142fd4e5da5Sopenharmony_ciOpSwitch %uint_0 %11
3143fd4e5da5Sopenharmony_ci%11 = OpLabel
3144fd4e5da5Sopenharmony_ciOpSelectionMerge %12 None
3145fd4e5da5Sopenharmony_ciOpBranchConditional %8 %10 %12
3146fd4e5da5Sopenharmony_ci%12 = OpLabel
3147fd4e5da5Sopenharmony_ciOpBranch %10
3148fd4e5da5Sopenharmony_ci%10 = OpLabel
3149fd4e5da5Sopenharmony_ciOpReturn
3150fd4e5da5Sopenharmony_ciOpFunctionEnd
3151fd4e5da5Sopenharmony_ci)";
3152fd4e5da5Sopenharmony_ci
3153fd4e5da5Sopenharmony_ci  SinglePassRunAndCheck<DeadBranchElimPass>(text, text, true, true);
3154fd4e5da5Sopenharmony_ci}
3155fd4e5da5Sopenharmony_ci
3156fd4e5da5Sopenharmony_ciTEST_F(DeadBranchElimTest, BreakInNestedHeaderWithTwoCases) {
3157fd4e5da5Sopenharmony_ci  const std::string text = R"(
3158fd4e5da5Sopenharmony_ci; CHECK: OpSelectionMerge [[merge:%\w+]] None
3159fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpSwitch %uint_0 [[bb:%\w+\n]]
3160fd4e5da5Sopenharmony_ciOpCapability Shader
3161fd4e5da5Sopenharmony_ci%1 = OpExtInstImport "GLSL.std.450"
3162fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
3163fd4e5da5Sopenharmony_ciOpEntryPoint Fragment %main "main"
3164fd4e5da5Sopenharmony_ciOpExecutionMode %main OriginUpperLeft
3165fd4e5da5Sopenharmony_ciOpSource GLSL 450
3166fd4e5da5Sopenharmony_ciOpName %main "main"
3167fd4e5da5Sopenharmony_ci%void = OpTypeVoid
3168fd4e5da5Sopenharmony_ci%4 = OpTypeFunction %void
3169fd4e5da5Sopenharmony_ci%bool = OpTypeBool
3170fd4e5da5Sopenharmony_ci%uint = OpTypeInt 32 0
3171fd4e5da5Sopenharmony_ci%uint_0 = OpConstant %uint 0
3172fd4e5da5Sopenharmony_ci%8 = OpUndef %bool
3173fd4e5da5Sopenharmony_ci%main = OpFunction %void None %4
3174fd4e5da5Sopenharmony_ci%9 = OpLabel
3175fd4e5da5Sopenharmony_ciOpSelectionMerge %10 None
3176fd4e5da5Sopenharmony_ciOpSwitch %uint_0 %11 1 %12
3177fd4e5da5Sopenharmony_ci%11 = OpLabel
3178fd4e5da5Sopenharmony_ciOpSelectionMerge %13 None
3179fd4e5da5Sopenharmony_ciOpBranchConditional %8 %10 %13
3180fd4e5da5Sopenharmony_ci%13 = OpLabel
3181fd4e5da5Sopenharmony_ciOpBranch %10
3182fd4e5da5Sopenharmony_ci%12 = OpLabel
3183fd4e5da5Sopenharmony_ciOpBranch %10
3184fd4e5da5Sopenharmony_ci%10 = OpLabel
3185fd4e5da5Sopenharmony_ciOpReturn
3186fd4e5da5Sopenharmony_ciOpFunctionEnd
3187fd4e5da5Sopenharmony_ci)";
3188fd4e5da5Sopenharmony_ci
3189fd4e5da5Sopenharmony_ci  SinglePassRunAndMatch<DeadBranchElimPass>(text, true);
3190fd4e5da5Sopenharmony_ci}
3191fd4e5da5Sopenharmony_ci
3192fd4e5da5Sopenharmony_ciTEST_F(DeadBranchElimTest, DebugInformation) {
3193fd4e5da5Sopenharmony_ci  const std::string text = R"(
3194fd4e5da5Sopenharmony_ciOpCapability Shader
3195fd4e5da5Sopenharmony_ci%1 = OpExtInstImport "GLSL.std.450"
3196fd4e5da5Sopenharmony_ci%ext = OpExtInstImport "OpenCL.DebugInfo.100"
3197fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
3198fd4e5da5Sopenharmony_ciOpEntryPoint Fragment %main "main" %gl_FragColor
3199fd4e5da5Sopenharmony_ciOpExecutionMode %main OriginUpperLeft
3200fd4e5da5Sopenharmony_ciOpSource GLSL 140
3201fd4e5da5Sopenharmony_ci%name = OpString "test"
3202fd4e5da5Sopenharmony_ciOpName %main "main"
3203fd4e5da5Sopenharmony_ciOpName %gl_FragColor "gl_FragColor"
3204fd4e5da5Sopenharmony_ci%void = OpTypeVoid
3205fd4e5da5Sopenharmony_ci%5 = OpTypeFunction %void
3206fd4e5da5Sopenharmony_ci%bool = OpTypeBool
3207fd4e5da5Sopenharmony_ci%true = OpConstantTrue %bool
3208fd4e5da5Sopenharmony_ci%float = OpTypeFloat 32
3209fd4e5da5Sopenharmony_ci%v4float = OpTypeVector %float 4
3210fd4e5da5Sopenharmony_ci%_ptr_Function_v4float = OpTypePointer Function %v4float
3211fd4e5da5Sopenharmony_ci%float_0 = OpConstant %float 0
3212fd4e5da5Sopenharmony_ci
3213fd4e5da5Sopenharmony_ci; CHECK: [[value:%\w+]] = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0
3214fd4e5da5Sopenharmony_ci%12 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0
3215fd4e5da5Sopenharmony_ci%float_1 = OpConstant %float 1
3216fd4e5da5Sopenharmony_ci%14 = OpConstantComposite %v4float %float_1 %float_1 %float_1 %float_1
3217fd4e5da5Sopenharmony_ci%_ptr_Output_v4float = OpTypePointer Output %v4float
3218fd4e5da5Sopenharmony_ci%gl_FragColor = OpVariable %_ptr_Output_v4float Output
3219fd4e5da5Sopenharmony_ci%_ptr_Input_v4float = OpTypePointer Input %v4float
3220fd4e5da5Sopenharmony_ci%uint = OpTypeInt 32 0
3221fd4e5da5Sopenharmony_ci%uint_32 = OpConstant %uint 32
3222fd4e5da5Sopenharmony_ci
3223fd4e5da5Sopenharmony_ci%null_expr = OpExtInst %void %ext DebugExpression
3224fd4e5da5Sopenharmony_ci%src = OpExtInst %void %ext DebugSource %name
3225fd4e5da5Sopenharmony_ci%cu = OpExtInst %void %ext DebugCompilationUnit 1 4 %src HLSL
3226fd4e5da5Sopenharmony_ci%ty = OpExtInst %void %ext DebugTypeFunction FlagIsProtected|FlagIsPrivate %void
3227fd4e5da5Sopenharmony_ci%dbg_main = OpExtInst %void %ext DebugFunction %name %ty %src 0 0 %cu %name FlagIsProtected|FlagIsPrivate 0 %main
3228fd4e5da5Sopenharmony_ci
3229fd4e5da5Sopenharmony_ci; CHECK: [[bb1:%\w+]] = OpExtInst %void [[ext:%\w+]] DebugLexicalBlock [[src:%\w+]] 1 0 [[dbg_main:%\w+]]
3230fd4e5da5Sopenharmony_ci; CHECK: [[bb2:%\w+]] = OpExtInst %void [[ext]] DebugLexicalBlock [[src]] 2 0 [[dbg_main]]
3231fd4e5da5Sopenharmony_ci; CHECK: [[bb3:%\w+]] = OpExtInst %void [[ext]] DebugLexicalBlock [[src]] 3 0 [[dbg_main]]
3232fd4e5da5Sopenharmony_ci%bb1 = OpExtInst %void %ext DebugLexicalBlock %src 1 0 %dbg_main
3233fd4e5da5Sopenharmony_ci%bb2 = OpExtInst %void %ext DebugLexicalBlock %src 2 0 %dbg_main
3234fd4e5da5Sopenharmony_ci%bb3 = OpExtInst %void %ext DebugLexicalBlock %src 3 0 %dbg_main
3235fd4e5da5Sopenharmony_ci
3236fd4e5da5Sopenharmony_ci%dbg_f = OpExtInst %void %ext DebugTypeBasic %name %uint_32 Float
3237fd4e5da5Sopenharmony_ci; CHECK: [[dbg_foo:%\w+]] = OpExtInst %void [[ext]] DebugLocalVariable {{%\w+}} [[ty:%\w+]] [[src]] 0 0 [[dbg_main]]
3238fd4e5da5Sopenharmony_ci%dbg_foo = OpExtInst %void %ext DebugLocalVariable %name %dbg_f %src 0 0 %dbg_main FlagIsLocal
3239fd4e5da5Sopenharmony_ci; CHECK: [[dbg_bar:%\w+]] = OpExtInst %void [[ext]] DebugLocalVariable {{%\w+}} [[ty]] [[src]] 1 0 [[bb3]]
3240fd4e5da5Sopenharmony_ci%dbg_bar = OpExtInst %void %ext DebugLocalVariable %name %dbg_f %src 1 0 %bb3 FlagIsLocal
3241fd4e5da5Sopenharmony_ci
3242fd4e5da5Sopenharmony_ci%main = OpFunction %void None %5
3243fd4e5da5Sopenharmony_ci%17 = OpLabel
3244fd4e5da5Sopenharmony_ci; CHECK-NOT: DebugScope [[dbg_main]]
3245fd4e5da5Sopenharmony_ci; CHECK-NOT: OpLine {{%\w+}} 0 0
3246fd4e5da5Sopenharmony_ci%scope0 = OpExtInst %void %ext DebugScope %dbg_main
3247fd4e5da5Sopenharmony_ciOpLine %name 0 0
3248fd4e5da5Sopenharmony_ciOpSelectionMerge %18 None
3249fd4e5da5Sopenharmony_ciOpBranchConditional %true %19 %20
3250fd4e5da5Sopenharmony_ci%19 = OpLabel
3251fd4e5da5Sopenharmony_ci; CHECK: DebugScope [[bb1]]
3252fd4e5da5Sopenharmony_ci; CHECK: OpLine {{%\w+}} 1 0
3253fd4e5da5Sopenharmony_ci%scope1 = OpExtInst %void %ext DebugScope %bb1
3254fd4e5da5Sopenharmony_ciOpLine %name 1 0
3255fd4e5da5Sopenharmony_ciOpBranch %18
3256fd4e5da5Sopenharmony_ci%20 = OpLabel
3257fd4e5da5Sopenharmony_ci; CHECK-NOT: DebugScope [[bb2]]
3258fd4e5da5Sopenharmony_ci; CHECK-NOT: OpLine {{%\w+}} 2 0
3259fd4e5da5Sopenharmony_ci%scope2 = OpExtInst %void %ext DebugScope %bb2
3260fd4e5da5Sopenharmony_ciOpLine %name 2 0
3261fd4e5da5Sopenharmony_ciOpBranch %18
3262fd4e5da5Sopenharmony_ci%18 = OpLabel
3263fd4e5da5Sopenharmony_ci
3264fd4e5da5Sopenharmony_ci; CHECK: DebugScope [[bb3]]
3265fd4e5da5Sopenharmony_ci; CHECK: OpLine {{%\w+}} 3 0
3266fd4e5da5Sopenharmony_ci; CHECK: DebugValue [[dbg_foo]] [[value]]
3267fd4e5da5Sopenharmony_ci; CHECK: OpLine {{%\w+}} 4 0
3268fd4e5da5Sopenharmony_ci; CHECK: OpStore %gl_FragColor [[value]]
3269fd4e5da5Sopenharmony_ci; CHECK: DebugDeclare [[dbg_bar]] %gl_FragColor
3270fd4e5da5Sopenharmony_ci; CHECK: DebugValue [[dbg_bar]] [[value]]
3271fd4e5da5Sopenharmony_ci%scope3 = OpExtInst %void %ext DebugScope %bb3
3272fd4e5da5Sopenharmony_ciOpLine %name 3 0
3273fd4e5da5Sopenharmony_ci%21 = OpPhi %v4float %12 %19 %14 %20
3274fd4e5da5Sopenharmony_ci%decl0 = OpExtInst %void %ext DebugValue %dbg_foo %21 %null_expr
3275fd4e5da5Sopenharmony_ciOpLine %name 4 0
3276fd4e5da5Sopenharmony_ciOpStore %gl_FragColor %21
3277fd4e5da5Sopenharmony_ci%decl1 = OpExtInst %void %ext DebugDeclare %dbg_bar %gl_FragColor %null_expr
3278fd4e5da5Sopenharmony_ci%decl2 = OpExtInst %void %ext DebugValue %dbg_bar %21 %null_expr
3279fd4e5da5Sopenharmony_ciOpLine %name 5 0
3280fd4e5da5Sopenharmony_ciOpReturn
3281fd4e5da5Sopenharmony_ciOpFunctionEnd
3282fd4e5da5Sopenharmony_ci)";
3283fd4e5da5Sopenharmony_ci
3284fd4e5da5Sopenharmony_ci  SinglePassRunAndMatch<DeadBranchElimPass>(text, true);
3285fd4e5da5Sopenharmony_ci}
3286fd4e5da5Sopenharmony_ci
3287fd4e5da5Sopenharmony_ciTEST_F(DeadBranchElimTest, DontTransferDecorations) {
3288fd4e5da5Sopenharmony_ci  // When replacing %4 with %14, we don't want %14 to inherit %4's decorations.
3289fd4e5da5Sopenharmony_ci  const std::string text = R"(
3290fd4e5da5Sopenharmony_ci; CHECK-NOT: OpDecorate {{%\w+}} RelaxedPrecision
3291fd4e5da5Sopenharmony_ci; CHECK: [[div:%\w+]] = OpFDiv
3292fd4e5da5Sopenharmony_ci; CHECK: {{%\w+}} = OpCopyObject %float [[div]]
3293fd4e5da5Sopenharmony_ci               OpCapability Shader
3294fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
3295fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
3296fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %2 "main"
3297fd4e5da5Sopenharmony_ci               OpExecutionMode %2 OriginUpperLeft
3298fd4e5da5Sopenharmony_ci          %3 = OpString "STEVEN"
3299fd4e5da5Sopenharmony_ci               OpDecorate %4 RelaxedPrecision
3300fd4e5da5Sopenharmony_ci      %float = OpTypeFloat 32
3301fd4e5da5Sopenharmony_ci       %uint = OpTypeInt 32 0
3302fd4e5da5Sopenharmony_ci       %void = OpTypeVoid
3303fd4e5da5Sopenharmony_ci    %float_1 = OpConstant %float 1
3304fd4e5da5Sopenharmony_ci     %uint_0 = OpConstant %uint 0
3305fd4e5da5Sopenharmony_ci         %10 = OpTypeFunction %void
3306fd4e5da5Sopenharmony_ci          %2 = OpFunction %void None %10
3307fd4e5da5Sopenharmony_ci         %11 = OpLabel
3308fd4e5da5Sopenharmony_ci               OpSelectionMerge %12 None
3309fd4e5da5Sopenharmony_ci               OpSwitch %uint_0 %13
3310fd4e5da5Sopenharmony_ci         %13 = OpLabel
3311fd4e5da5Sopenharmony_ci         %14 = OpFDiv %float %float_1 %float_1
3312fd4e5da5Sopenharmony_ci               OpLine %3 0 0
3313fd4e5da5Sopenharmony_ci               OpBranch %12
3314fd4e5da5Sopenharmony_ci         %15 = OpLabel
3315fd4e5da5Sopenharmony_ci               OpBranch %12
3316fd4e5da5Sopenharmony_ci         %12 = OpLabel
3317fd4e5da5Sopenharmony_ci          %4 = OpPhi %float %float_1 %15 %14 %13
3318fd4e5da5Sopenharmony_ci         %16 = OpCopyObject %float %4
3319fd4e5da5Sopenharmony_ci               OpReturn
3320fd4e5da5Sopenharmony_ci               OpFunctionEnd
3321fd4e5da5Sopenharmony_ci)";
3322fd4e5da5Sopenharmony_ci
3323fd4e5da5Sopenharmony_ci  SinglePassRunAndMatch<DeadBranchElimPass>(text, true);
3324fd4e5da5Sopenharmony_ci}
3325fd4e5da5Sopenharmony_ci
3326fd4e5da5Sopenharmony_ciTEST_F(DeadBranchElimTest, FunctionDeclaration) {
3327fd4e5da5Sopenharmony_ci  // Make sure the pass works with a function declaration that is called.
3328fd4e5da5Sopenharmony_ci  const std::string text = R"(OpCapability Addresses
3329fd4e5da5Sopenharmony_ciOpCapability Linkage
3330fd4e5da5Sopenharmony_ciOpCapability Kernel
3331fd4e5da5Sopenharmony_ciOpCapability Int8
3332fd4e5da5Sopenharmony_ci%1 = OpExtInstImport "OpenCL.std"
3333fd4e5da5Sopenharmony_ciOpMemoryModel Physical64 OpenCL
3334fd4e5da5Sopenharmony_ciOpEntryPoint Kernel %2 "_Z23julia__1166_kernel_77094Bool"
3335fd4e5da5Sopenharmony_ciOpExecutionMode %2 ContractionOff
3336fd4e5da5Sopenharmony_ciOpSource Unknown 0
3337fd4e5da5Sopenharmony_ciOpDecorate %3 LinkageAttributes "julia_error_7712" Import
3338fd4e5da5Sopenharmony_ci%void = OpTypeVoid
3339fd4e5da5Sopenharmony_ci%5 = OpTypeFunction %void
3340fd4e5da5Sopenharmony_ci%3 = OpFunction %void None %5
3341fd4e5da5Sopenharmony_ciOpFunctionEnd
3342fd4e5da5Sopenharmony_ci%2 = OpFunction %void None %5
3343fd4e5da5Sopenharmony_ci%6 = OpLabel
3344fd4e5da5Sopenharmony_ci%7 = OpFunctionCall %void %3
3345fd4e5da5Sopenharmony_ciOpReturn
3346fd4e5da5Sopenharmony_ciOpFunctionEnd
3347fd4e5da5Sopenharmony_ci)";
3348fd4e5da5Sopenharmony_ci
3349fd4e5da5Sopenharmony_ci  SinglePassRunAndCheck<DeadBranchElimPass>(text, text, false);
3350fd4e5da5Sopenharmony_ci}
3351fd4e5da5Sopenharmony_ci
3352fd4e5da5Sopenharmony_ci// TODO(greg-lunarg): Add tests to verify handling of these cases:
3353fd4e5da5Sopenharmony_ci//
3354fd4e5da5Sopenharmony_ci//    More complex control flow
3355fd4e5da5Sopenharmony_ci//    Others?
3356fd4e5da5Sopenharmony_ci
3357fd4e5da5Sopenharmony_ci}  // namespace
3358fd4e5da5Sopenharmony_ci}  // namespace opt
3359fd4e5da5Sopenharmony_ci}  // namespace spvtools
3360