1fd4e5da5Sopenharmony_ci// Copyright (c) 2017 Google Inc.
2fd4e5da5Sopenharmony_ci//
3fd4e5da5Sopenharmony_ci// Licensed under the Apache License, Version 2.0 (the "License");
4fd4e5da5Sopenharmony_ci// you may not use this file except in compliance with the License.
5fd4e5da5Sopenharmony_ci// You may obtain a copy of the License at
6fd4e5da5Sopenharmony_ci//
7fd4e5da5Sopenharmony_ci//     http://www.apache.org/licenses/LICENSE-2.0
8fd4e5da5Sopenharmony_ci//
9fd4e5da5Sopenharmony_ci// Unless required by applicable law or agreed to in writing, software
10fd4e5da5Sopenharmony_ci// distributed under the License is distributed on an "AS IS" BASIS,
11fd4e5da5Sopenharmony_ci// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12fd4e5da5Sopenharmony_ci// See the License for the specific language governing permissions and
13fd4e5da5Sopenharmony_ci// limitations under the License.
14fd4e5da5Sopenharmony_ci
15fd4e5da5Sopenharmony_ci#include <string>
16fd4e5da5Sopenharmony_ci
17fd4e5da5Sopenharmony_ci#include "gtest/gtest.h"
18fd4e5da5Sopenharmony_ci#include "source/opt/ccp_pass.h"
19fd4e5da5Sopenharmony_ci#include "test/opt/pass_fixture.h"
20fd4e5da5Sopenharmony_ci#include "test/opt/pass_utils.h"
21fd4e5da5Sopenharmony_ci
22fd4e5da5Sopenharmony_cinamespace spvtools {
23fd4e5da5Sopenharmony_cinamespace opt {
24fd4e5da5Sopenharmony_cinamespace {
25fd4e5da5Sopenharmony_ci
26fd4e5da5Sopenharmony_ciusing CCPTest = PassTest<::testing::Test>;
27fd4e5da5Sopenharmony_ci
28fd4e5da5Sopenharmony_ciTEST_F(CCPTest, PropagateThroughPhis) {
29fd4e5da5Sopenharmony_ci  const std::string spv_asm = R"(
30fd4e5da5Sopenharmony_ci               OpCapability Shader
31fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
32fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
33fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %main "main" %x %outparm
34fd4e5da5Sopenharmony_ci               OpExecutionMode %main OriginUpperLeft
35fd4e5da5Sopenharmony_ci               OpSource GLSL 450
36fd4e5da5Sopenharmony_ci               OpName %main "main"
37fd4e5da5Sopenharmony_ci               OpName %x "x"
38fd4e5da5Sopenharmony_ci               OpName %outparm "outparm"
39fd4e5da5Sopenharmony_ci               OpDecorate %x Flat
40fd4e5da5Sopenharmony_ci               OpDecorate %x Location 0
41fd4e5da5Sopenharmony_ci               OpDecorate %outparm Location 0
42fd4e5da5Sopenharmony_ci       %void = OpTypeVoid
43fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %void
44fd4e5da5Sopenharmony_ci        %int = OpTypeInt 32 1
45fd4e5da5Sopenharmony_ci       %bool = OpTypeBool
46fd4e5da5Sopenharmony_ci%_ptr_Function_int = OpTypePointer Function %int
47fd4e5da5Sopenharmony_ci      %int_4 = OpConstant %int 4
48fd4e5da5Sopenharmony_ci      %int_3 = OpConstant %int 3
49fd4e5da5Sopenharmony_ci      %int_1 = OpConstant %int 1
50fd4e5da5Sopenharmony_ci%_ptr_Input_int = OpTypePointer Input %int
51fd4e5da5Sopenharmony_ci          %x = OpVariable %_ptr_Input_int Input
52fd4e5da5Sopenharmony_ci%_ptr_Output_int = OpTypePointer Output %int
53fd4e5da5Sopenharmony_ci    %outparm = OpVariable %_ptr_Output_int Output
54fd4e5da5Sopenharmony_ci       %main = OpFunction %void None %3
55fd4e5da5Sopenharmony_ci          %4 = OpLabel
56fd4e5da5Sopenharmony_ci          %5 = OpLoad %int %x
57fd4e5da5Sopenharmony_ci          %9 = OpIAdd %int %int_1 %int_3
58fd4e5da5Sopenharmony_ci          %6 = OpSGreaterThan %bool %5 %int_3
59fd4e5da5Sopenharmony_ci               OpSelectionMerge %25 None
60fd4e5da5Sopenharmony_ci               OpBranchConditional %6 %22 %23
61fd4e5da5Sopenharmony_ci         %22 = OpLabel
62fd4e5da5Sopenharmony_ci
63fd4e5da5Sopenharmony_ci; CHECK: OpCopyObject %int %int_4
64fd4e5da5Sopenharmony_ci          %7 = OpCopyObject %int %9
65fd4e5da5Sopenharmony_ci
66fd4e5da5Sopenharmony_ci               OpBranch %25
67fd4e5da5Sopenharmony_ci         %23 = OpLabel
68fd4e5da5Sopenharmony_ci          %8 = OpCopyObject %int %int_4
69fd4e5da5Sopenharmony_ci               OpBranch %25
70fd4e5da5Sopenharmony_ci         %25 = OpLabel
71fd4e5da5Sopenharmony_ci
72fd4e5da5Sopenharmony_ci; %int_4 should have propagated to both OpPhi operands.
73fd4e5da5Sopenharmony_ci; CHECK: OpPhi %int %int_4 {{%\d+}} %int_4 {{%\d+}}
74fd4e5da5Sopenharmony_ci         %35 = OpPhi %int %7 %22 %8 %23
75fd4e5da5Sopenharmony_ci
76fd4e5da5Sopenharmony_ci; This function always returns 4. DCE should get rid of everything else.
77fd4e5da5Sopenharmony_ci; CHECK OpStore %outparm %int_4
78fd4e5da5Sopenharmony_ci               OpStore %outparm %35
79fd4e5da5Sopenharmony_ci               OpReturn
80fd4e5da5Sopenharmony_ci               OpFunctionEnd
81fd4e5da5Sopenharmony_ci               )";
82fd4e5da5Sopenharmony_ci
83fd4e5da5Sopenharmony_ci  SinglePassRunAndMatch<CCPPass>(spv_asm, true);
84fd4e5da5Sopenharmony_ci}
85fd4e5da5Sopenharmony_ci
86fd4e5da5Sopenharmony_ciTEST_F(CCPTest, SimplifyConditionals) {
87fd4e5da5Sopenharmony_ci  const std::string spv_asm = R"(
88fd4e5da5Sopenharmony_ci               OpCapability Shader
89fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
90fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
91fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %main "main" %outparm
92fd4e5da5Sopenharmony_ci               OpExecutionMode %main OriginUpperLeft
93fd4e5da5Sopenharmony_ci               OpSource GLSL 450
94fd4e5da5Sopenharmony_ci               OpName %main "main"
95fd4e5da5Sopenharmony_ci               OpName %outparm "outparm"
96fd4e5da5Sopenharmony_ci               OpDecorate %outparm Location 0
97fd4e5da5Sopenharmony_ci       %void = OpTypeVoid
98fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %void
99fd4e5da5Sopenharmony_ci        %int = OpTypeInt 32 1
100fd4e5da5Sopenharmony_ci       %bool = OpTypeBool
101fd4e5da5Sopenharmony_ci%_ptr_Function_int = OpTypePointer Function %int
102fd4e5da5Sopenharmony_ci      %int_4 = OpConstant %int 4
103fd4e5da5Sopenharmony_ci      %int_3 = OpConstant %int 3
104fd4e5da5Sopenharmony_ci      %int_1 = OpConstant %int 1
105fd4e5da5Sopenharmony_ci%_ptr_Output_int = OpTypePointer Output %int
106fd4e5da5Sopenharmony_ci    %outparm = OpVariable %_ptr_Output_int Output
107fd4e5da5Sopenharmony_ci       %main = OpFunction %void None %3
108fd4e5da5Sopenharmony_ci          %4 = OpLabel
109fd4e5da5Sopenharmony_ci          %9 = OpIAdd %int %int_4 %int_3
110fd4e5da5Sopenharmony_ci          %6 = OpSGreaterThan %bool %9 %int_3
111fd4e5da5Sopenharmony_ci               OpSelectionMerge %25 None
112fd4e5da5Sopenharmony_ci; CHECK: OpBranchConditional %true [[bb_taken:%\d+]] [[bb_not_taken:%\d+]]
113fd4e5da5Sopenharmony_ci               OpBranchConditional %6 %22 %23
114fd4e5da5Sopenharmony_ci; CHECK: [[bb_taken]] = OpLabel
115fd4e5da5Sopenharmony_ci         %22 = OpLabel
116fd4e5da5Sopenharmony_ci; CHECK: OpCopyObject %int %int_7
117fd4e5da5Sopenharmony_ci          %7 = OpCopyObject %int %9
118fd4e5da5Sopenharmony_ci               OpBranch %25
119fd4e5da5Sopenharmony_ci; CHECK: [[bb_not_taken]] = OpLabel
120fd4e5da5Sopenharmony_ci         %23 = OpLabel
121fd4e5da5Sopenharmony_ci; CHECK: [[id_not_evaluated:%\d+]] = OpCopyObject %int %int_4
122fd4e5da5Sopenharmony_ci          %8 = OpCopyObject %int %int_4
123fd4e5da5Sopenharmony_ci               OpBranch %25
124fd4e5da5Sopenharmony_ci         %25 = OpLabel
125fd4e5da5Sopenharmony_ci
126fd4e5da5Sopenharmony_ci; %int_7 should have propagated to the first OpPhi operand. But the else branch
127fd4e5da5Sopenharmony_ci; is not executable (conditional is always true), so no values should be
128fd4e5da5Sopenharmony_ci; propagated there and the value of the OpPhi should always be %int_7.
129fd4e5da5Sopenharmony_ci; CHECK: OpPhi %int %int_7 [[bb_taken]] [[id_not_evaluated]] [[bb_not_taken]]
130fd4e5da5Sopenharmony_ci         %35 = OpPhi %int %7 %22 %8 %23
131fd4e5da5Sopenharmony_ci
132fd4e5da5Sopenharmony_ci; Only the true path of the conditional is ever executed. The output of this
133fd4e5da5Sopenharmony_ci; function is always %int_7.
134fd4e5da5Sopenharmony_ci; CHECK: OpStore %outparm %int_7
135fd4e5da5Sopenharmony_ci               OpStore %outparm %35
136fd4e5da5Sopenharmony_ci               OpReturn
137fd4e5da5Sopenharmony_ci               OpFunctionEnd
138fd4e5da5Sopenharmony_ci               )";
139fd4e5da5Sopenharmony_ci
140fd4e5da5Sopenharmony_ci  SinglePassRunAndMatch<CCPPass>(spv_asm, true);
141fd4e5da5Sopenharmony_ci}
142fd4e5da5Sopenharmony_ci
143fd4e5da5Sopenharmony_ciTEST_F(CCPTest, SimplifySwitches) {
144fd4e5da5Sopenharmony_ci  const std::string spv_asm = R"(
145fd4e5da5Sopenharmony_ci               OpCapability Shader
146fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
147fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
148fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %main "main" %outparm
149fd4e5da5Sopenharmony_ci               OpExecutionMode %main OriginUpperLeft
150fd4e5da5Sopenharmony_ci               OpSource GLSL 450
151fd4e5da5Sopenharmony_ci               OpName %main "main"
152fd4e5da5Sopenharmony_ci               OpName %outparm "outparm"
153fd4e5da5Sopenharmony_ci               OpDecorate %outparm Location 0
154fd4e5da5Sopenharmony_ci       %void = OpTypeVoid
155fd4e5da5Sopenharmony_ci          %6 = OpTypeFunction %void
156fd4e5da5Sopenharmony_ci        %int = OpTypeInt 32 1
157fd4e5da5Sopenharmony_ci%_ptr_Function_int = OpTypePointer Function %int
158fd4e5da5Sopenharmony_ci     %int_23 = OpConstant %int 23
159fd4e5da5Sopenharmony_ci     %int_42 = OpConstant %int 42
160fd4e5da5Sopenharmony_ci     %int_14 = OpConstant %int 14
161fd4e5da5Sopenharmony_ci     %int_15 = OpConstant %int 15
162fd4e5da5Sopenharmony_ci      %int_4 = OpConstant %int 4
163fd4e5da5Sopenharmony_ci%_ptr_Output_int = OpTypePointer Output %int
164fd4e5da5Sopenharmony_ci    %outparm = OpVariable %_ptr_Output_int Output
165fd4e5da5Sopenharmony_ci       %main = OpFunction %void None %6
166fd4e5da5Sopenharmony_ci         %15 = OpLabel
167fd4e5da5Sopenharmony_ci               OpSelectionMerge %17 None
168fd4e5da5Sopenharmony_ci               OpSwitch %int_23 %17 10 %18 13 %19 23 %20
169fd4e5da5Sopenharmony_ci         %18 = OpLabel
170fd4e5da5Sopenharmony_ci               OpBranch %17
171fd4e5da5Sopenharmony_ci         %19 = OpLabel
172fd4e5da5Sopenharmony_ci               OpBranch %17
173fd4e5da5Sopenharmony_ci         %20 = OpLabel
174fd4e5da5Sopenharmony_ci               OpBranch %17
175fd4e5da5Sopenharmony_ci         %17 = OpLabel
176fd4e5da5Sopenharmony_ci         %24 = OpPhi %int %int_23 %15 %int_42 %18 %int_14 %19 %int_15 %20
177fd4e5da5Sopenharmony_ci
178fd4e5da5Sopenharmony_ci; The switch will always jump to label %20, which carries the value %int_15.
179fd4e5da5Sopenharmony_ci; CHECK: OpIAdd %int %int_15 %int_4
180fd4e5da5Sopenharmony_ci         %22 = OpIAdd %int %24 %int_4
181fd4e5da5Sopenharmony_ci
182fd4e5da5Sopenharmony_ci; Consequently, the return value will always be %int_19.
183fd4e5da5Sopenharmony_ci; CHECK: OpStore %outparm %int_19
184fd4e5da5Sopenharmony_ci               OpStore %outparm %22
185fd4e5da5Sopenharmony_ci               OpReturn
186fd4e5da5Sopenharmony_ci               OpFunctionEnd
187fd4e5da5Sopenharmony_ci               )";
188fd4e5da5Sopenharmony_ci
189fd4e5da5Sopenharmony_ci  SinglePassRunAndMatch<CCPPass>(spv_asm, true);
190fd4e5da5Sopenharmony_ci}
191fd4e5da5Sopenharmony_ci
192fd4e5da5Sopenharmony_ciTEST_F(CCPTest, SimplifySwitchesDefaultBranch) {
193fd4e5da5Sopenharmony_ci  const std::string spv_asm = R"(
194fd4e5da5Sopenharmony_ci               OpCapability Shader
195fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
196fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
197fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %main "main" %outparm
198fd4e5da5Sopenharmony_ci               OpExecutionMode %main OriginUpperLeft
199fd4e5da5Sopenharmony_ci               OpSource GLSL 450
200fd4e5da5Sopenharmony_ci               OpName %main "main"
201fd4e5da5Sopenharmony_ci               OpName %outparm "outparm"
202fd4e5da5Sopenharmony_ci               OpDecorate %outparm Location 0
203fd4e5da5Sopenharmony_ci       %void = OpTypeVoid
204fd4e5da5Sopenharmony_ci          %6 = OpTypeFunction %void
205fd4e5da5Sopenharmony_ci        %int = OpTypeInt 32 1
206fd4e5da5Sopenharmony_ci%_ptr_Function_int = OpTypePointer Function %int
207fd4e5da5Sopenharmony_ci     %int_42 = OpConstant %int 42
208fd4e5da5Sopenharmony_ci      %int_4 = OpConstant %int 4
209fd4e5da5Sopenharmony_ci      %int_1 = OpConstant %int 1
210fd4e5da5Sopenharmony_ci%_ptr_Output_int = OpTypePointer Output %int
211fd4e5da5Sopenharmony_ci    %outparm = OpVariable %_ptr_Output_int Output
212fd4e5da5Sopenharmony_ci       %main = OpFunction %void None %6
213fd4e5da5Sopenharmony_ci         %13 = OpLabel
214fd4e5da5Sopenharmony_ci         %15 = OpIAdd %int %int_42 %int_4
215fd4e5da5Sopenharmony_ci               OpSelectionMerge %16 None
216fd4e5da5Sopenharmony_ci
217fd4e5da5Sopenharmony_ci; CHECK: OpSwitch %int_46 {{%\d+}} 10 {{%\d+}}
218fd4e5da5Sopenharmony_ci               OpSwitch %15 %17 10 %18
219fd4e5da5Sopenharmony_ci         %18 = OpLabel
220fd4e5da5Sopenharmony_ci               OpBranch %16
221fd4e5da5Sopenharmony_ci         %17 = OpLabel
222fd4e5da5Sopenharmony_ci               OpBranch %16
223fd4e5da5Sopenharmony_ci         %16 = OpLabel
224fd4e5da5Sopenharmony_ci         %22 = OpPhi %int %int_42 %18 %int_1 %17
225fd4e5da5Sopenharmony_ci
226fd4e5da5Sopenharmony_ci; The switch will always jump to the default label %17.  This carries the value
227fd4e5da5Sopenharmony_ci; %int_1.
228fd4e5da5Sopenharmony_ci; CHECK: OpIAdd %int %int_1 %int_4
229fd4e5da5Sopenharmony_ci         %20 = OpIAdd %int %22 %int_4
230fd4e5da5Sopenharmony_ci
231fd4e5da5Sopenharmony_ci; Resulting in a return value of %int_5.
232fd4e5da5Sopenharmony_ci; CHECK: OpStore %outparm %int_5
233fd4e5da5Sopenharmony_ci               OpStore %outparm %20
234fd4e5da5Sopenharmony_ci               OpReturn
235fd4e5da5Sopenharmony_ci               OpFunctionEnd
236fd4e5da5Sopenharmony_ci               )";
237fd4e5da5Sopenharmony_ci
238fd4e5da5Sopenharmony_ci  SinglePassRunAndMatch<CCPPass>(spv_asm, true);
239fd4e5da5Sopenharmony_ci}
240fd4e5da5Sopenharmony_ci
241fd4e5da5Sopenharmony_ciTEST_F(CCPTest, SimplifyIntVector) {
242fd4e5da5Sopenharmony_ci  const std::string spv_asm = R"(
243fd4e5da5Sopenharmony_ci               OpCapability Shader
244fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
245fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
246fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %main "main" %OutColor
247fd4e5da5Sopenharmony_ci               OpExecutionMode %main OriginUpperLeft
248fd4e5da5Sopenharmony_ci               OpSource GLSL 450
249fd4e5da5Sopenharmony_ci               OpName %main "main"
250fd4e5da5Sopenharmony_ci               OpName %v "v"
251fd4e5da5Sopenharmony_ci               OpName %OutColor "OutColor"
252fd4e5da5Sopenharmony_ci               OpDecorate %OutColor Location 0
253fd4e5da5Sopenharmony_ci       %void = OpTypeVoid
254fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %void
255fd4e5da5Sopenharmony_ci        %int = OpTypeInt 32 1
256fd4e5da5Sopenharmony_ci      %v4int = OpTypeVector %int 4
257fd4e5da5Sopenharmony_ci%_ptr_Function_v4int = OpTypePointer Function %v4int
258fd4e5da5Sopenharmony_ci      %int_1 = OpConstant %int 1
259fd4e5da5Sopenharmony_ci      %int_2 = OpConstant %int 2
260fd4e5da5Sopenharmony_ci      %int_3 = OpConstant %int 3
261fd4e5da5Sopenharmony_ci      %int_4 = OpConstant %int 4
262fd4e5da5Sopenharmony_ci         %14 = OpConstantComposite %v4int %int_1 %int_2 %int_3 %int_4
263fd4e5da5Sopenharmony_ci       %uint = OpTypeInt 32 0
264fd4e5da5Sopenharmony_ci     %uint_0 = OpConstant %uint 0
265fd4e5da5Sopenharmony_ci%_ptr_Function_int = OpTypePointer Function %int
266fd4e5da5Sopenharmony_ci%_ptr_Output_v4int = OpTypePointer Output %v4int
267fd4e5da5Sopenharmony_ci   %OutColor = OpVariable %_ptr_Output_v4int Output
268fd4e5da5Sopenharmony_ci       %main = OpFunction %void None %3
269fd4e5da5Sopenharmony_ci          %5 = OpLabel
270fd4e5da5Sopenharmony_ci          %v = OpVariable %_ptr_Function_v4int Function
271fd4e5da5Sopenharmony_ci               OpStore %v %14
272fd4e5da5Sopenharmony_ci         %18 = OpAccessChain %_ptr_Function_int %v %uint_0
273fd4e5da5Sopenharmony_ci         %19 = OpLoad %int %18
274fd4e5da5Sopenharmony_ci
275fd4e5da5Sopenharmony_ci; The constant folder does not see through access chains. To get this, the
276fd4e5da5Sopenharmony_ci; vector would have to be scalarized.
277fd4e5da5Sopenharmony_ci; CHECK: [[result_id:%\d+]] = OpIAdd %int {{%\d+}} %int_1
278fd4e5da5Sopenharmony_ci         %20 = OpIAdd %int %19 %int_1
279fd4e5da5Sopenharmony_ci         %21 = OpAccessChain %_ptr_Function_int %v %uint_0
280fd4e5da5Sopenharmony_ci
281fd4e5da5Sopenharmony_ci; CHECK: OpStore {{%\d+}} [[result_id]]
282fd4e5da5Sopenharmony_ci               OpStore %21 %20
283fd4e5da5Sopenharmony_ci         %24 = OpLoad %v4int %v
284fd4e5da5Sopenharmony_ci               OpStore %OutColor %24
285fd4e5da5Sopenharmony_ci               OpReturn
286fd4e5da5Sopenharmony_ci               OpFunctionEnd
287fd4e5da5Sopenharmony_ci               )";
288fd4e5da5Sopenharmony_ci
289fd4e5da5Sopenharmony_ci  SinglePassRunAndMatch<CCPPass>(spv_asm, true);
290fd4e5da5Sopenharmony_ci}
291fd4e5da5Sopenharmony_ci
292fd4e5da5Sopenharmony_ciTEST_F(CCPTest, BadSimplifyFloatVector) {
293fd4e5da5Sopenharmony_ci  const std::string spv_asm = R"(
294fd4e5da5Sopenharmony_ci               OpCapability Shader
295fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
296fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
297fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %main "main" %OutColor
298fd4e5da5Sopenharmony_ci               OpExecutionMode %main OriginUpperLeft
299fd4e5da5Sopenharmony_ci               OpSource GLSL 450
300fd4e5da5Sopenharmony_ci               OpName %main "main"
301fd4e5da5Sopenharmony_ci               OpName %v "v"
302fd4e5da5Sopenharmony_ci               OpName %OutColor "OutColor"
303fd4e5da5Sopenharmony_ci               OpDecorate %OutColor Location 0
304fd4e5da5Sopenharmony_ci       %void = OpTypeVoid
305fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %void
306fd4e5da5Sopenharmony_ci      %float = OpTypeFloat 32
307fd4e5da5Sopenharmony_ci    %v4float = OpTypeVector %float 4
308fd4e5da5Sopenharmony_ci%_ptr_Function_v4float = OpTypePointer Function %v4float
309fd4e5da5Sopenharmony_ci    %float_1 = OpConstant %float 1
310fd4e5da5Sopenharmony_ci    %float_2 = OpConstant %float 2
311fd4e5da5Sopenharmony_ci    %float_3 = OpConstant %float 3
312fd4e5da5Sopenharmony_ci    %float_4 = OpConstant %float 4
313fd4e5da5Sopenharmony_ci         %14 = OpConstantComposite %v4float %float_1 %float_2 %float_3 %float_4
314fd4e5da5Sopenharmony_ci       %uint = OpTypeInt 32 0
315fd4e5da5Sopenharmony_ci     %uint_0 = OpConstant %uint 0
316fd4e5da5Sopenharmony_ci%_ptr_Function_float = OpTypePointer Function %float
317fd4e5da5Sopenharmony_ci%_ptr_Output_v4float = OpTypePointer Output %v4float
318fd4e5da5Sopenharmony_ci   %OutColor = OpVariable %_ptr_Output_v4float Output
319fd4e5da5Sopenharmony_ci       %main = OpFunction %void None %3
320fd4e5da5Sopenharmony_ci          %5 = OpLabel
321fd4e5da5Sopenharmony_ci          %v = OpVariable %_ptr_Function_v4float Function
322fd4e5da5Sopenharmony_ci               OpStore %v %14
323fd4e5da5Sopenharmony_ci         %18 = OpAccessChain %_ptr_Function_float %v %uint_0
324fd4e5da5Sopenharmony_ci         %19 = OpLoad %float %18
325fd4e5da5Sopenharmony_ci
326fd4e5da5Sopenharmony_ci; NOTE: This test should start failing once floating point folding is
327fd4e5da5Sopenharmony_ci;       implemented (https://github.com/KhronosGroup/SPIRV-Tools/issues/943).
328fd4e5da5Sopenharmony_ci;       This should be checking that we are adding %float_1 + %float_1.
329fd4e5da5Sopenharmony_ci; CHECK: [[result_id:%\d+]] = OpFAdd %float {{%\d+}} %float_1
330fd4e5da5Sopenharmony_ci         %20 = OpFAdd %float %19 %float_1
331fd4e5da5Sopenharmony_ci         %21 = OpAccessChain %_ptr_Function_float %v %uint_0
332fd4e5da5Sopenharmony_ci
333fd4e5da5Sopenharmony_ci; This should be checkint that we are storing %float_2 instead of result_it.
334fd4e5da5Sopenharmony_ci; CHECK: OpStore {{%\d+}} [[result_id]]
335fd4e5da5Sopenharmony_ci               OpStore %21 %20
336fd4e5da5Sopenharmony_ci         %24 = OpLoad %v4float %v
337fd4e5da5Sopenharmony_ci               OpStore %OutColor %24
338fd4e5da5Sopenharmony_ci               OpReturn
339fd4e5da5Sopenharmony_ci               OpFunctionEnd
340fd4e5da5Sopenharmony_ci               )";
341fd4e5da5Sopenharmony_ci
342fd4e5da5Sopenharmony_ci  SinglePassRunAndMatch<CCPPass>(spv_asm, true);
343fd4e5da5Sopenharmony_ci}
344fd4e5da5Sopenharmony_ci
345fd4e5da5Sopenharmony_ciTEST_F(CCPTest, NoLoadStorePropagation) {
346fd4e5da5Sopenharmony_ci  const std::string spv_asm = R"(
347fd4e5da5Sopenharmony_ci               OpCapability Shader
348fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
349fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
350fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %main "main" %outparm
351fd4e5da5Sopenharmony_ci               OpExecutionMode %main OriginUpperLeft
352fd4e5da5Sopenharmony_ci               OpSource GLSL 450
353fd4e5da5Sopenharmony_ci               OpName %main "main"
354fd4e5da5Sopenharmony_ci               OpName %x "x"
355fd4e5da5Sopenharmony_ci               OpName %outparm "outparm"
356fd4e5da5Sopenharmony_ci               OpDecorate %outparm Location 0
357fd4e5da5Sopenharmony_ci       %void = OpTypeVoid
358fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %void
359fd4e5da5Sopenharmony_ci        %int = OpTypeInt 32 1
360fd4e5da5Sopenharmony_ci%_ptr_Function_int = OpTypePointer Function %int
361fd4e5da5Sopenharmony_ci     %int_23 = OpConstant %int 23
362fd4e5da5Sopenharmony_ci%_ptr_Output_int = OpTypePointer Output %int
363fd4e5da5Sopenharmony_ci    %outparm = OpVariable %_ptr_Output_int Output
364fd4e5da5Sopenharmony_ci       %main = OpFunction %void None %3
365fd4e5da5Sopenharmony_ci          %5 = OpLabel
366fd4e5da5Sopenharmony_ci          %x = OpVariable %_ptr_Function_int Function
367fd4e5da5Sopenharmony_ci               OpStore %x %int_23
368fd4e5da5Sopenharmony_ci
369fd4e5da5Sopenharmony_ci; int_23 should not propagate into this load.
370fd4e5da5Sopenharmony_ci; CHECK: [[load_id:%\d+]] = OpLoad %int %x
371fd4e5da5Sopenharmony_ci         %12 = OpLoad %int %x
372fd4e5da5Sopenharmony_ci
373fd4e5da5Sopenharmony_ci; Nor into this copy operation.
374fd4e5da5Sopenharmony_ci; CHECK: [[copy_id:%\d+]] = OpCopyObject %int [[load_id]]
375fd4e5da5Sopenharmony_ci         %13 = OpCopyObject %int %12
376fd4e5da5Sopenharmony_ci
377fd4e5da5Sopenharmony_ci; Likewise here.
378fd4e5da5Sopenharmony_ci; CHECK: OpStore %outparm [[copy_id]]
379fd4e5da5Sopenharmony_ci               OpStore %outparm %13
380fd4e5da5Sopenharmony_ci               OpReturn
381fd4e5da5Sopenharmony_ci               OpFunctionEnd
382fd4e5da5Sopenharmony_ci               )";
383fd4e5da5Sopenharmony_ci
384fd4e5da5Sopenharmony_ci  SinglePassRunAndMatch<CCPPass>(spv_asm, true);
385fd4e5da5Sopenharmony_ci}
386fd4e5da5Sopenharmony_ci
387fd4e5da5Sopenharmony_ciTEST_F(CCPTest, HandleAbortInstructions) {
388fd4e5da5Sopenharmony_ci  const std::string spv_asm = R"(
389fd4e5da5Sopenharmony_ci               OpCapability Shader
390fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
391fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
392fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %main "main"
393fd4e5da5Sopenharmony_ci               OpExecutionMode %main OriginUpperLeft
394fd4e5da5Sopenharmony_ci               OpSource HLSL 500
395fd4e5da5Sopenharmony_ci               OpName %main "main"
396fd4e5da5Sopenharmony_ci       %void = OpTypeVoid
397fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %void
398fd4e5da5Sopenharmony_ci        %int = OpTypeInt 32 1
399fd4e5da5Sopenharmony_ci       %bool = OpTypeBool
400fd4e5da5Sopenharmony_ci; CHECK: %true = OpConstantTrue %bool
401fd4e5da5Sopenharmony_ci      %int_3 = OpConstant %int 3
402fd4e5da5Sopenharmony_ci      %int_1 = OpConstant %int 1
403fd4e5da5Sopenharmony_ci       %main = OpFunction %void None %3
404fd4e5da5Sopenharmony_ci          %4 = OpLabel
405fd4e5da5Sopenharmony_ci          %9 = OpIAdd %int %int_3 %int_1
406fd4e5da5Sopenharmony_ci          %6 = OpSGreaterThan %bool %9 %int_3
407fd4e5da5Sopenharmony_ci               OpSelectionMerge %23 None
408fd4e5da5Sopenharmony_ci; CHECK: OpBranchConditional %true {{%\d+}} {{%\d+}}
409fd4e5da5Sopenharmony_ci               OpBranchConditional %6 %22 %23
410fd4e5da5Sopenharmony_ci         %22 = OpLabel
411fd4e5da5Sopenharmony_ci               OpKill
412fd4e5da5Sopenharmony_ci         %23 = OpLabel
413fd4e5da5Sopenharmony_ci               OpReturn
414fd4e5da5Sopenharmony_ci               OpFunctionEnd
415fd4e5da5Sopenharmony_ci  )";
416fd4e5da5Sopenharmony_ci
417fd4e5da5Sopenharmony_ci  SinglePassRunAndMatch<CCPPass>(spv_asm, true);
418fd4e5da5Sopenharmony_ci}
419fd4e5da5Sopenharmony_ci
420fd4e5da5Sopenharmony_ciTEST_F(CCPTest, SSAWebCycles) {
421fd4e5da5Sopenharmony_ci  // Test reduced from https://github.com/KhronosGroup/SPIRV-Tools/issues/1159
422fd4e5da5Sopenharmony_ci  // When there is a cycle in the SSA def-use web, the propagator was getting
423fd4e5da5Sopenharmony_ci  // into an infinite loop.  SSA edges for Phi instructions should not be
424fd4e5da5Sopenharmony_ci  // added to the edges to simulate.
425fd4e5da5Sopenharmony_ci  const std::string spv_asm = R"(
426fd4e5da5Sopenharmony_ci               OpCapability Shader
427fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
428fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
429fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %main "main"
430fd4e5da5Sopenharmony_ci               OpExecutionMode %main OriginUpperLeft
431fd4e5da5Sopenharmony_ci               OpSource GLSL 450
432fd4e5da5Sopenharmony_ci               OpName %main "main"
433fd4e5da5Sopenharmony_ci       %void = OpTypeVoid
434fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %void
435fd4e5da5Sopenharmony_ci        %int = OpTypeInt 32 1
436fd4e5da5Sopenharmony_ci%_ptr_Function_int = OpTypePointer Function %int
437fd4e5da5Sopenharmony_ci      %int_0 = OpConstant %int 0
438fd4e5da5Sopenharmony_ci      %int_4 = OpConstant %int 4
439fd4e5da5Sopenharmony_ci       %bool = OpTypeBool
440fd4e5da5Sopenharmony_ci      %int_1 = OpConstant %int 1
441fd4e5da5Sopenharmony_ci%_ptr_Output_int = OpTypePointer Output %int
442fd4e5da5Sopenharmony_ci       %main = OpFunction %void None %3
443fd4e5da5Sopenharmony_ci          %5 = OpLabel
444fd4e5da5Sopenharmony_ci               OpBranch %11
445fd4e5da5Sopenharmony_ci         %11 = OpLabel
446fd4e5da5Sopenharmony_ci         %29 = OpPhi %int %int_0 %5 %22 %14
447fd4e5da5Sopenharmony_ci         %30 = OpPhi %int %int_0 %5 %25 %14
448fd4e5da5Sopenharmony_ci               OpLoopMerge %13 %14 None
449fd4e5da5Sopenharmony_ci               OpBranch %15
450fd4e5da5Sopenharmony_ci         %15 = OpLabel
451fd4e5da5Sopenharmony_ci         %19 = OpSLessThan %bool %30 %int_4
452fd4e5da5Sopenharmony_ci; CHECK: OpBranchConditional %true {{%\d+}} {{%\d+}}
453fd4e5da5Sopenharmony_ci               OpBranchConditional %19 %12 %13
454fd4e5da5Sopenharmony_ci         %12 = OpLabel
455fd4e5da5Sopenharmony_ci; CHECK: OpIAdd %int %int_0 %int_0
456fd4e5da5Sopenharmony_ci         %22 = OpIAdd %int %29 %30
457fd4e5da5Sopenharmony_ci               OpBranch %14
458fd4e5da5Sopenharmony_ci         %14 = OpLabel
459fd4e5da5Sopenharmony_ci; CHECK: OpPhi %int %int_0 {{%\d+}}
460fd4e5da5Sopenharmony_ci         %25 = OpPhi %int %30 %12
461fd4e5da5Sopenharmony_ci               OpBranch %11
462fd4e5da5Sopenharmony_ci         %13 = OpLabel
463fd4e5da5Sopenharmony_ci               OpReturn
464fd4e5da5Sopenharmony_ci               OpFunctionEnd
465fd4e5da5Sopenharmony_ci  )";
466fd4e5da5Sopenharmony_ci
467fd4e5da5Sopenharmony_ci  SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
468fd4e5da5Sopenharmony_ci  SinglePassRunAndMatch<CCPPass>(spv_asm, true);
469fd4e5da5Sopenharmony_ci}
470fd4e5da5Sopenharmony_ci
471fd4e5da5Sopenharmony_ciTEST_F(CCPTest, LoopInductionVariables) {
472fd4e5da5Sopenharmony_ci  // Test reduced from https://github.com/KhronosGroup/SPIRV-Tools/issues/1143
473fd4e5da5Sopenharmony_ci  // We are failing to properly consider the induction variable for this loop
474fd4e5da5Sopenharmony_ci  // as Varying.
475fd4e5da5Sopenharmony_ci  const std::string spv_asm = R"(
476fd4e5da5Sopenharmony_ci               OpCapability Shader
477fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
478fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
479fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %main "main"
480fd4e5da5Sopenharmony_ci               OpExecutionMode %main OriginUpperLeft
481fd4e5da5Sopenharmony_ci               OpSource GLSL 430
482fd4e5da5Sopenharmony_ci               OpName %main "main"
483fd4e5da5Sopenharmony_ci       %void = OpTypeVoid
484fd4e5da5Sopenharmony_ci          %5 = OpTypeFunction %void
485fd4e5da5Sopenharmony_ci        %int = OpTypeInt 32 1
486fd4e5da5Sopenharmony_ci%_ptr_Function_int = OpTypePointer Function %int
487fd4e5da5Sopenharmony_ci      %int_0 = OpConstant %int 0
488fd4e5da5Sopenharmony_ci     %int_10 = OpConstant %int 10
489fd4e5da5Sopenharmony_ci       %bool = OpTypeBool
490fd4e5da5Sopenharmony_ci      %int_1 = OpConstant %int 1
491fd4e5da5Sopenharmony_ci       %main = OpFunction %void None %5
492fd4e5da5Sopenharmony_ci         %12 = OpLabel
493fd4e5da5Sopenharmony_ci               OpBranch %13
494fd4e5da5Sopenharmony_ci         %13 = OpLabel
495fd4e5da5Sopenharmony_ci
496fd4e5da5Sopenharmony_ci; This Phi should not have all constant arguments:
497fd4e5da5Sopenharmony_ci; CHECK: [[phi_id:%\d+]] = OpPhi %int %int_0 {{%\d+}} {{%\d+}} {{%\d+}}
498fd4e5da5Sopenharmony_ci         %22 = OpPhi %int %int_0 %12 %21 %15
499fd4e5da5Sopenharmony_ci               OpLoopMerge %14 %15 None
500fd4e5da5Sopenharmony_ci               OpBranch %16
501fd4e5da5Sopenharmony_ci         %16 = OpLabel
502fd4e5da5Sopenharmony_ci
503fd4e5da5Sopenharmony_ci; The Phi should never be considered to have the value %int_0.
504fd4e5da5Sopenharmony_ci; CHECK: [[branch_selector:%\d+]] = OpSLessThan %bool [[phi_id]] %int_10
505fd4e5da5Sopenharmony_ci         %18 = OpSLessThan %bool %22 %int_10
506fd4e5da5Sopenharmony_ci
507fd4e5da5Sopenharmony_ci; This conditional was wrongly converted into an always-true jump due to the
508fd4e5da5Sopenharmony_ci; bad meet evaluation of %22.
509fd4e5da5Sopenharmony_ci; CHECK: OpBranchConditional [[branch_selector]] {{%\d+}} {{%\d+}}
510fd4e5da5Sopenharmony_ci               OpBranchConditional %18 %19 %14
511fd4e5da5Sopenharmony_ci         %19 = OpLabel
512fd4e5da5Sopenharmony_ci               OpBranch %15
513fd4e5da5Sopenharmony_ci         %15 = OpLabel
514fd4e5da5Sopenharmony_ci; CHECK: OpIAdd %int [[phi_id]] %int_1
515fd4e5da5Sopenharmony_ci         %21 = OpIAdd %int %22 %int_1
516fd4e5da5Sopenharmony_ci               OpBranch %13
517fd4e5da5Sopenharmony_ci         %14 = OpLabel
518fd4e5da5Sopenharmony_ci               OpReturn
519fd4e5da5Sopenharmony_ci               OpFunctionEnd
520fd4e5da5Sopenharmony_ci  )";
521fd4e5da5Sopenharmony_ci
522fd4e5da5Sopenharmony_ci  SinglePassRunAndMatch<CCPPass>(spv_asm, true);
523fd4e5da5Sopenharmony_ci}
524fd4e5da5Sopenharmony_ci
525fd4e5da5Sopenharmony_ciTEST_F(CCPTest, HandleCompositeWithUndef) {
526fd4e5da5Sopenharmony_ci  // Check to make sure that CCP does not crash when given a "constant" struct
527fd4e5da5Sopenharmony_ci  // with an undef.  If at a later time CCP is enhanced to optimize this case,
528fd4e5da5Sopenharmony_ci  // it is not wrong.
529fd4e5da5Sopenharmony_ci  const std::string spv_asm = R"(
530fd4e5da5Sopenharmony_ci               OpCapability Shader
531fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
532fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
533fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %main "main"
534fd4e5da5Sopenharmony_ci               OpExecutionMode %main OriginUpperLeft
535fd4e5da5Sopenharmony_ci               OpSource HLSL 500
536fd4e5da5Sopenharmony_ci               OpName %main "main"
537fd4e5da5Sopenharmony_ci       %void = OpTypeVoid
538fd4e5da5Sopenharmony_ci          %4 = OpTypeFunction %void
539fd4e5da5Sopenharmony_ci        %int = OpTypeInt 32 1
540fd4e5da5Sopenharmony_ci       %bool = OpTypeBool
541fd4e5da5Sopenharmony_ci  %_struct_7 = OpTypeStruct %int %int
542fd4e5da5Sopenharmony_ci      %int_1 = OpConstant %int 1
543fd4e5da5Sopenharmony_ci          %9 = OpUndef %int
544fd4e5da5Sopenharmony_ci         %10 = OpConstantComposite %_struct_7 %int_1 %9
545fd4e5da5Sopenharmony_ci       %main = OpFunction %void None %4
546fd4e5da5Sopenharmony_ci         %11 = OpLabel
547fd4e5da5Sopenharmony_ci         %12 = OpCompositeExtract %int %10 0
548fd4e5da5Sopenharmony_ci         %13 = OpCopyObject %int %12
549fd4e5da5Sopenharmony_ci               OpReturn
550fd4e5da5Sopenharmony_ci               OpFunctionEnd
551fd4e5da5Sopenharmony_ci  )";
552fd4e5da5Sopenharmony_ci
553fd4e5da5Sopenharmony_ci  auto res = SinglePassRunToBinary<CCPPass>(spv_asm, true);
554fd4e5da5Sopenharmony_ci  EXPECT_EQ(std::get<1>(res), Pass::Status::SuccessWithoutChange);
555fd4e5da5Sopenharmony_ci}
556fd4e5da5Sopenharmony_ci
557fd4e5da5Sopenharmony_ciTEST_F(CCPTest, SkipSpecConstantInstrucitons) {
558fd4e5da5Sopenharmony_ci  const std::string spv_asm = R"(
559fd4e5da5Sopenharmony_ci               OpCapability Shader
560fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
561fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
562fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %main "main"
563fd4e5da5Sopenharmony_ci               OpExecutionMode %main OriginUpperLeft
564fd4e5da5Sopenharmony_ci               OpSource HLSL 500
565fd4e5da5Sopenharmony_ci               OpName %main "main"
566fd4e5da5Sopenharmony_ci       %void = OpTypeVoid
567fd4e5da5Sopenharmony_ci          %4 = OpTypeFunction %void
568fd4e5da5Sopenharmony_ci       %bool = OpTypeBool
569fd4e5da5Sopenharmony_ci         %10 = OpSpecConstantFalse %bool
570fd4e5da5Sopenharmony_ci       %main = OpFunction %void None %4
571fd4e5da5Sopenharmony_ci         %11 = OpLabel
572fd4e5da5Sopenharmony_ci               OpBranchConditional %10 %L1 %L2
573fd4e5da5Sopenharmony_ci         %L1 = OpLabel
574fd4e5da5Sopenharmony_ci               OpReturn
575fd4e5da5Sopenharmony_ci         %L2 = OpLabel
576fd4e5da5Sopenharmony_ci               OpReturn
577fd4e5da5Sopenharmony_ci               OpFunctionEnd
578fd4e5da5Sopenharmony_ci  )";
579fd4e5da5Sopenharmony_ci
580fd4e5da5Sopenharmony_ci  auto res = SinglePassRunToBinary<CCPPass>(spv_asm, true);
581fd4e5da5Sopenharmony_ci  EXPECT_EQ(std::get<1>(res), Pass::Status::SuccessWithoutChange);
582fd4e5da5Sopenharmony_ci}
583fd4e5da5Sopenharmony_ci
584fd4e5da5Sopenharmony_ciTEST_F(CCPTest, FoldConstantCompositeInstrucitonsWithSpecConst) {
585fd4e5da5Sopenharmony_ci  const std::string spv_asm = R"(
586fd4e5da5Sopenharmony_ci               OpCapability Shader
587fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
588fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %1 "main"
589fd4e5da5Sopenharmony_ci               OpExecutionMode %1 OriginUpperLeft
590fd4e5da5Sopenharmony_ci       %void = OpTypeVoid
591fd4e5da5Sopenharmony_ci          %4 = OpTypeFunction %void
592fd4e5da5Sopenharmony_ci       %bool = OpTypeBool
593fd4e5da5Sopenharmony_ci     %v3bool = OpTypeVector %bool 3
594fd4e5da5Sopenharmony_ci  %_struct_8 = OpTypeStruct %v3bool
595fd4e5da5Sopenharmony_ci       %true = OpConstantTrue %bool
596fd4e5da5Sopenharmony_ci; CHECK: [[spec_const:%\w+]] = OpSpecConstantComposite %v3bool
597fd4e5da5Sopenharmony_ci         %11 = OpSpecConstantComposite %v3bool %true %true %true
598fd4e5da5Sopenharmony_ci         %12 = OpConstantComposite %_struct_8 %11
599fd4e5da5Sopenharmony_ci; CHECK: OpFunction
600fd4e5da5Sopenharmony_ci          %1 = OpFunction %void None %4
601fd4e5da5Sopenharmony_ci         %29 = OpLabel
602fd4e5da5Sopenharmony_ci         %31 = OpCompositeExtract %v3bool %12 0
603fd4e5da5Sopenharmony_ci; CHECK: OpCompositeExtract %bool [[spec_const]] 0
604fd4e5da5Sopenharmony_ci         %32 = OpCompositeExtract %bool %31 0
605fd4e5da5Sopenharmony_ci               OpReturn
606fd4e5da5Sopenharmony_ci               OpFunctionEnd
607fd4e5da5Sopenharmony_ci  )";
608fd4e5da5Sopenharmony_ci
609fd4e5da5Sopenharmony_ci  auto result = SinglePassRunAndMatch<CCPPass>(spv_asm, true);
610fd4e5da5Sopenharmony_ci  EXPECT_EQ(std::get<1>(result), Pass::Status::SuccessWithChange);
611fd4e5da5Sopenharmony_ci}
612fd4e5da5Sopenharmony_ci
613fd4e5da5Sopenharmony_ciTEST_F(CCPTest, UpdateSubsequentPhisToVarying) {
614fd4e5da5Sopenharmony_ci  const std::string text = R"(
615fd4e5da5Sopenharmony_ciOpCapability Shader
616fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
617fd4e5da5Sopenharmony_ciOpEntryPoint Fragment %func "func" %in
618fd4e5da5Sopenharmony_ciOpExecutionMode %func OriginUpperLeft
619fd4e5da5Sopenharmony_ci%void = OpTypeVoid
620fd4e5da5Sopenharmony_ci%bool = OpTypeBool
621fd4e5da5Sopenharmony_ci%int = OpTypeInt 32 1
622fd4e5da5Sopenharmony_ci%false = OpConstantFalse %bool
623fd4e5da5Sopenharmony_ci%int0 = OpConstant %int 0
624fd4e5da5Sopenharmony_ci%int1 = OpConstant %int 1
625fd4e5da5Sopenharmony_ci%int6 = OpConstant %int 6
626fd4e5da5Sopenharmony_ci%int_ptr_Input = OpTypePointer Input %int
627fd4e5da5Sopenharmony_ci%in = OpVariable %int_ptr_Input Input
628fd4e5da5Sopenharmony_ci%undef = OpUndef %int
629fd4e5da5Sopenharmony_ci
630fd4e5da5Sopenharmony_ci; Although no constants are propagated in this function, the propagator
631fd4e5da5Sopenharmony_ci; generates a new %true value while visiting conditional statements.
632fd4e5da5Sopenharmony_ci; CHECK: %true = OpConstantTrue %bool
633fd4e5da5Sopenharmony_ci
634fd4e5da5Sopenharmony_ci%functy = OpTypeFunction %void
635fd4e5da5Sopenharmony_ci%func = OpFunction %void None %functy
636fd4e5da5Sopenharmony_ci%1 = OpLabel
637fd4e5da5Sopenharmony_ciOpBranch %2
638fd4e5da5Sopenharmony_ci%2 = OpLabel
639fd4e5da5Sopenharmony_ci%outer_phi = OpPhi %int %int0 %1 %outer_add %15
640fd4e5da5Sopenharmony_ci%cond1 = OpSLessThanEqual %bool %outer_phi %int6
641fd4e5da5Sopenharmony_ciOpLoopMerge %3 %15 None
642fd4e5da5Sopenharmony_ciOpBranchConditional %cond1 %4 %3
643fd4e5da5Sopenharmony_ci%4 = OpLabel
644fd4e5da5Sopenharmony_ci%ld = OpLoad %int %in
645fd4e5da5Sopenharmony_ci%cond2 = OpSGreaterThanEqual %bool %int1 %ld
646fd4e5da5Sopenharmony_ciOpSelectionMerge %10 None
647fd4e5da5Sopenharmony_ciOpBranchConditional %cond2 %8 %9
648fd4e5da5Sopenharmony_ci%8 = OpLabel
649fd4e5da5Sopenharmony_ciOpBranch %10
650fd4e5da5Sopenharmony_ci%9 = OpLabel
651fd4e5da5Sopenharmony_ciOpBranch %10
652fd4e5da5Sopenharmony_ci%10 = OpLabel
653fd4e5da5Sopenharmony_ci%extra_phi = OpPhi %int %outer_phi %8 %outer_phi %9
654fd4e5da5Sopenharmony_ciOpBranch %11
655fd4e5da5Sopenharmony_ci%11 = OpLabel
656fd4e5da5Sopenharmony_ci%inner_phi = OpPhi %int %int0 %10 %inner_add %13
657fd4e5da5Sopenharmony_ci%cond3 = OpSLessThanEqual %bool %inner_phi %int6
658fd4e5da5Sopenharmony_ciOpLoopMerge %14 %13 None
659fd4e5da5Sopenharmony_ciOpBranchConditional %cond3 %12 %14
660fd4e5da5Sopenharmony_ci%12 = OpLabel
661fd4e5da5Sopenharmony_ciOpBranch %13
662fd4e5da5Sopenharmony_ci%13 = OpLabel
663fd4e5da5Sopenharmony_ci%inner_add = OpIAdd %int %inner_phi %int1
664fd4e5da5Sopenharmony_ciOpBranch %11
665fd4e5da5Sopenharmony_ci%14 = OpLabel
666fd4e5da5Sopenharmony_ciOpBranch %15
667fd4e5da5Sopenharmony_ci%15 = OpLabel
668fd4e5da5Sopenharmony_ci%outer_add = OpIAdd %int %extra_phi %int1
669fd4e5da5Sopenharmony_ciOpBranch %2
670fd4e5da5Sopenharmony_ci%3 = OpLabel
671fd4e5da5Sopenharmony_ciOpReturn
672fd4e5da5Sopenharmony_ciOpFunctionEnd
673fd4e5da5Sopenharmony_ci)";
674fd4e5da5Sopenharmony_ci
675fd4e5da5Sopenharmony_ci  auto result = SinglePassRunAndMatch<CCPPass>(text, true);
676fd4e5da5Sopenharmony_ci  EXPECT_EQ(std::get<1>(result), Pass::Status::SuccessWithChange);
677fd4e5da5Sopenharmony_ci}
678fd4e5da5Sopenharmony_ci
679fd4e5da5Sopenharmony_ciTEST_F(CCPTest, UndefInPhi) {
680fd4e5da5Sopenharmony_ci  const std::string text = R"(
681fd4e5da5Sopenharmony_ci; CHECK: [[uint1:%\w+]] = OpConstant {{%\w+}} 1
682fd4e5da5Sopenharmony_ci; CHECK: [[phi:%\w+]] = OpPhi
683fd4e5da5Sopenharmony_ci; CHECK: OpIAdd {{%\w+}} [[phi]] [[uint1]]
684fd4e5da5Sopenharmony_ci               OpCapability Kernel
685fd4e5da5Sopenharmony_ci               OpCapability Linkage
686fd4e5da5Sopenharmony_ci               OpMemoryModel Logical OpenCL
687fd4e5da5Sopenharmony_ci               OpDecorate %1 LinkageAttributes "func" Export
688fd4e5da5Sopenharmony_ci       %void = OpTypeVoid
689fd4e5da5Sopenharmony_ci       %bool = OpTypeBool
690fd4e5da5Sopenharmony_ci       %uint = OpTypeInt 32 0
691fd4e5da5Sopenharmony_ci     %uint_0 = OpConstant %uint 0
692fd4e5da5Sopenharmony_ci     %uint_1 = OpConstant %uint 1
693fd4e5da5Sopenharmony_ci          %7 = OpUndef %uint
694fd4e5da5Sopenharmony_ci          %8 = OpTypeFunction %void %bool
695fd4e5da5Sopenharmony_ci          %1 = OpFunction %void None %8
696fd4e5da5Sopenharmony_ci          %9 = OpFunctionParameter %bool
697fd4e5da5Sopenharmony_ci         %10 = OpLabel
698fd4e5da5Sopenharmony_ci               OpBranchConditional %9 %11 %12
699fd4e5da5Sopenharmony_ci         %11 = OpLabel
700fd4e5da5Sopenharmony_ci               OpBranch %13
701fd4e5da5Sopenharmony_ci         %12 = OpLabel
702fd4e5da5Sopenharmony_ci               OpBranch %14
703fd4e5da5Sopenharmony_ci         %14 = OpLabel
704fd4e5da5Sopenharmony_ci               OpBranchConditional %9 %13 %15
705fd4e5da5Sopenharmony_ci         %15 = OpLabel
706fd4e5da5Sopenharmony_ci               OpBranch %13
707fd4e5da5Sopenharmony_ci         %13 = OpLabel
708fd4e5da5Sopenharmony_ci         %16 = OpPhi %uint %uint_0 %11 %7 %14 %uint_1 %15
709fd4e5da5Sopenharmony_ci         %17 = OpIAdd %uint %16 %uint_1
710fd4e5da5Sopenharmony_ci               OpReturn
711fd4e5da5Sopenharmony_ci               OpFunctionEnd
712fd4e5da5Sopenharmony_ci)";
713fd4e5da5Sopenharmony_ci
714fd4e5da5Sopenharmony_ci  SinglePassRunAndMatch<CCPPass>(text, true);
715fd4e5da5Sopenharmony_ci}
716fd4e5da5Sopenharmony_ci
717fd4e5da5Sopenharmony_ci// Just test to make sure the constant fold rules are being used.  Will rely on
718fd4e5da5Sopenharmony_ci// the folding test for specific testing of specific rules.
719fd4e5da5Sopenharmony_ciTEST_F(CCPTest, UseConstantFoldingRules) {
720fd4e5da5Sopenharmony_ci  const std::string text = R"(
721fd4e5da5Sopenharmony_ci; CHECK: [[float1:%\w+]] = OpConstant {{%\w+}} 1
722fd4e5da5Sopenharmony_ci; CHECK: OpReturnValue [[float1]]
723fd4e5da5Sopenharmony_ci               OpCapability Shader
724fd4e5da5Sopenharmony_ci               OpCapability Linkage
725fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
726fd4e5da5Sopenharmony_ci               OpDecorate %1 LinkageAttributes "func" Export
727fd4e5da5Sopenharmony_ci       %void = OpTypeVoid
728fd4e5da5Sopenharmony_ci       %bool = OpTypeBool
729fd4e5da5Sopenharmony_ci      %float = OpTypeFloat 32
730fd4e5da5Sopenharmony_ci    %float_0 = OpConstant %float 0
731fd4e5da5Sopenharmony_ci    %float_1 = OpConstant %float 1
732fd4e5da5Sopenharmony_ci          %8 = OpTypeFunction %float
733fd4e5da5Sopenharmony_ci          %1 = OpFunction %float None %8
734fd4e5da5Sopenharmony_ci         %10 = OpLabel
735fd4e5da5Sopenharmony_ci         %17 = OpFAdd %float %float_0 %float_1
736fd4e5da5Sopenharmony_ci               OpReturnValue %17
737fd4e5da5Sopenharmony_ci               OpFunctionEnd
738fd4e5da5Sopenharmony_ci)";
739fd4e5da5Sopenharmony_ci
740fd4e5da5Sopenharmony_ci  SinglePassRunAndMatch<CCPPass>(text, true);
741fd4e5da5Sopenharmony_ci}
742fd4e5da5Sopenharmony_ci
743fd4e5da5Sopenharmony_ci// Test for #1300. Previously value for %5 would not settle during simulation.
744fd4e5da5Sopenharmony_ciTEST_F(CCPTest, SettlePhiLatticeValue) {
745fd4e5da5Sopenharmony_ci  const std::string text = R"(
746fd4e5da5Sopenharmony_ciOpCapability Kernel
747fd4e5da5Sopenharmony_ciOpCapability Linkage
748fd4e5da5Sopenharmony_ciOpMemoryModel Logical OpenCL
749fd4e5da5Sopenharmony_ciOpDecorate %func LinkageAttributes "func" Export
750fd4e5da5Sopenharmony_ci%void = OpTypeVoid
751fd4e5da5Sopenharmony_ci%bool = OpTypeBool
752fd4e5da5Sopenharmony_ci%true = OpConstantTrue %bool
753fd4e5da5Sopenharmony_ci%false = OpConstantFalse %bool
754fd4e5da5Sopenharmony_ci%functy = OpTypeFunction %void
755fd4e5da5Sopenharmony_ci%func = OpFunction %void None %functy
756fd4e5da5Sopenharmony_ci%1 = OpLabel
757fd4e5da5Sopenharmony_ciOpBranchConditional %true %2 %3
758fd4e5da5Sopenharmony_ci%3 = OpLabel
759fd4e5da5Sopenharmony_ciOpBranch %2
760fd4e5da5Sopenharmony_ci%2 = OpLabel
761fd4e5da5Sopenharmony_ci%5 = OpPhi %bool %true %1 %false %3
762fd4e5da5Sopenharmony_ciOpReturn
763fd4e5da5Sopenharmony_ciOpFunctionEnd
764fd4e5da5Sopenharmony_ci)";
765fd4e5da5Sopenharmony_ci
766fd4e5da5Sopenharmony_ci  SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
767fd4e5da5Sopenharmony_ci  SinglePassRunToBinary<CCPPass>(text, true);
768fd4e5da5Sopenharmony_ci}
769fd4e5da5Sopenharmony_ci
770fd4e5da5Sopenharmony_ciTEST_F(CCPTest, NullBranchCondition) {
771fd4e5da5Sopenharmony_ci  const std::string text = R"(
772fd4e5da5Sopenharmony_ci; CHECK: [[int1:%\w+]] = OpConstant {{%\w+}} 1
773fd4e5da5Sopenharmony_ci; CHECK: [[int2:%\w+]] = OpConstant {{%\w+}} 2
774fd4e5da5Sopenharmony_ci; CHECK: OpIAdd {{%\w+}} [[int1]] [[int2]]
775fd4e5da5Sopenharmony_ciOpCapability Shader
776fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
777fd4e5da5Sopenharmony_ciOpEntryPoint Fragment %func "func"
778fd4e5da5Sopenharmony_ciOpExecutionMode %func OriginUpperLeft
779fd4e5da5Sopenharmony_ci%void = OpTypeVoid
780fd4e5da5Sopenharmony_ci%bool = OpTypeBool
781fd4e5da5Sopenharmony_ci%int = OpTypeInt 32 1
782fd4e5da5Sopenharmony_ci%null = OpConstantNull %bool
783fd4e5da5Sopenharmony_ci%int_1 = OpConstant %int 1
784fd4e5da5Sopenharmony_ci%int_2 = OpConstant %int 2
785fd4e5da5Sopenharmony_ci%functy = OpTypeFunction %void
786fd4e5da5Sopenharmony_ci%func = OpFunction %void None %functy
787fd4e5da5Sopenharmony_ci%1 = OpLabel
788fd4e5da5Sopenharmony_ciOpSelectionMerge %2 None
789fd4e5da5Sopenharmony_ciOpBranchConditional %null %2 %3
790fd4e5da5Sopenharmony_ci%3 = OpLabel
791fd4e5da5Sopenharmony_ciOpBranch %2
792fd4e5da5Sopenharmony_ci%2 = OpLabel
793fd4e5da5Sopenharmony_ci%phi = OpPhi %int %int_1 %1 %int_2 %3
794fd4e5da5Sopenharmony_ci%add = OpIAdd %int %int_1 %phi
795fd4e5da5Sopenharmony_ciOpReturn
796fd4e5da5Sopenharmony_ciOpFunctionEnd
797fd4e5da5Sopenharmony_ci)";
798fd4e5da5Sopenharmony_ci
799fd4e5da5Sopenharmony_ci  SinglePassRunAndMatch<CCPPass>(text, true);
800fd4e5da5Sopenharmony_ci}
801fd4e5da5Sopenharmony_ci
802fd4e5da5Sopenharmony_ciTEST_F(CCPTest, UndefBranchCondition) {
803fd4e5da5Sopenharmony_ci  const std::string text = R"(
804fd4e5da5Sopenharmony_ci; CHECK: [[int1:%\w+]] = OpConstant {{%\w+}} 1
805fd4e5da5Sopenharmony_ci; CHECK: [[phi:%\w+]] = OpPhi
806fd4e5da5Sopenharmony_ci; CHECK: OpIAdd {{%\w+}} [[int1]] [[phi]]
807fd4e5da5Sopenharmony_ciOpCapability Shader
808fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
809fd4e5da5Sopenharmony_ciOpEntryPoint Fragment %func "func"
810fd4e5da5Sopenharmony_ciOpExecutionMode %func OriginUpperLeft
811fd4e5da5Sopenharmony_ci%void = OpTypeVoid
812fd4e5da5Sopenharmony_ci%bool = OpTypeBool
813fd4e5da5Sopenharmony_ci%int = OpTypeInt 32 1
814fd4e5da5Sopenharmony_ci%undef = OpUndef %bool
815fd4e5da5Sopenharmony_ci%int_1 = OpConstant %int 1
816fd4e5da5Sopenharmony_ci%int_2 = OpConstant %int 2
817fd4e5da5Sopenharmony_ci%functy = OpTypeFunction %void
818fd4e5da5Sopenharmony_ci%func = OpFunction %void None %functy
819fd4e5da5Sopenharmony_ci%1 = OpLabel
820fd4e5da5Sopenharmony_ciOpSelectionMerge %2 None
821fd4e5da5Sopenharmony_ciOpBranchConditional %undef %2 %3
822fd4e5da5Sopenharmony_ci%3 = OpLabel
823fd4e5da5Sopenharmony_ciOpBranch %2
824fd4e5da5Sopenharmony_ci%2 = OpLabel
825fd4e5da5Sopenharmony_ci%phi = OpPhi %int %int_1 %1 %int_2 %3
826fd4e5da5Sopenharmony_ci%add = OpIAdd %int %int_1 %phi
827fd4e5da5Sopenharmony_ciOpReturn
828fd4e5da5Sopenharmony_ciOpFunctionEnd
829fd4e5da5Sopenharmony_ci)";
830fd4e5da5Sopenharmony_ci
831fd4e5da5Sopenharmony_ci  SinglePassRunAndMatch<CCPPass>(text, true);
832fd4e5da5Sopenharmony_ci}
833fd4e5da5Sopenharmony_ci
834fd4e5da5Sopenharmony_ciTEST_F(CCPTest, NullSwitchCondition) {
835fd4e5da5Sopenharmony_ci  const std::string text = R"(
836fd4e5da5Sopenharmony_ci; CHECK: [[int1:%\w+]] = OpConstant {{%\w+}} 1
837fd4e5da5Sopenharmony_ci; CHECK: [[int2:%\w+]] = OpConstant {{%\w+}} 2
838fd4e5da5Sopenharmony_ci; CHECK: OpIAdd {{%\w+}} [[int1]] [[int2]]
839fd4e5da5Sopenharmony_ciOpCapability Shader
840fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
841fd4e5da5Sopenharmony_ciOpEntryPoint Fragment %func "func"
842fd4e5da5Sopenharmony_ciOpExecutionMode %func OriginUpperLeft
843fd4e5da5Sopenharmony_ci%void = OpTypeVoid
844fd4e5da5Sopenharmony_ci%int = OpTypeInt 32 1
845fd4e5da5Sopenharmony_ci%null = OpConstantNull %int
846fd4e5da5Sopenharmony_ci%int_1 = OpConstant %int 1
847fd4e5da5Sopenharmony_ci%int_2 = OpConstant %int 2
848fd4e5da5Sopenharmony_ci%functy = OpTypeFunction %void
849fd4e5da5Sopenharmony_ci%func = OpFunction %void None %functy
850fd4e5da5Sopenharmony_ci%1 = OpLabel
851fd4e5da5Sopenharmony_ciOpSelectionMerge %2 None
852fd4e5da5Sopenharmony_ciOpSwitch %null %2 0 %3
853fd4e5da5Sopenharmony_ci%3 = OpLabel
854fd4e5da5Sopenharmony_ciOpBranch %2
855fd4e5da5Sopenharmony_ci%2 = OpLabel
856fd4e5da5Sopenharmony_ci%phi = OpPhi %int %int_1 %1 %int_2 %3
857fd4e5da5Sopenharmony_ci%add = OpIAdd %int %int_1 %phi
858fd4e5da5Sopenharmony_ciOpReturn
859fd4e5da5Sopenharmony_ciOpFunctionEnd
860fd4e5da5Sopenharmony_ci)";
861fd4e5da5Sopenharmony_ci
862fd4e5da5Sopenharmony_ci  SinglePassRunAndMatch<CCPPass>(text, true);
863fd4e5da5Sopenharmony_ci}
864fd4e5da5Sopenharmony_ci
865fd4e5da5Sopenharmony_ciTEST_F(CCPTest, UndefSwitchCondition) {
866fd4e5da5Sopenharmony_ci  const std::string text = R"(
867fd4e5da5Sopenharmony_ci; CHECK: [[int1:%\w+]] = OpConstant {{%\w+}} 1
868fd4e5da5Sopenharmony_ci; CHECK: [[phi:%\w+]] = OpPhi
869fd4e5da5Sopenharmony_ci; CHECK: OpIAdd {{%\w+}} [[int1]] [[phi]]
870fd4e5da5Sopenharmony_ciOpCapability Shader
871fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
872fd4e5da5Sopenharmony_ciOpEntryPoint Fragment %func "func"
873fd4e5da5Sopenharmony_ciOpExecutionMode %func OriginUpperLeft
874fd4e5da5Sopenharmony_ci%void = OpTypeVoid
875fd4e5da5Sopenharmony_ci%int = OpTypeInt 32 1
876fd4e5da5Sopenharmony_ci%undef = OpUndef %int
877fd4e5da5Sopenharmony_ci%int_1 = OpConstant %int 1
878fd4e5da5Sopenharmony_ci%int_2 = OpConstant %int 2
879fd4e5da5Sopenharmony_ci%functy = OpTypeFunction %void
880fd4e5da5Sopenharmony_ci%func = OpFunction %void None %functy
881fd4e5da5Sopenharmony_ci%1 = OpLabel
882fd4e5da5Sopenharmony_ciOpSelectionMerge %2 None
883fd4e5da5Sopenharmony_ciOpSwitch %undef %2 0 %3
884fd4e5da5Sopenharmony_ci%3 = OpLabel
885fd4e5da5Sopenharmony_ciOpBranch %2
886fd4e5da5Sopenharmony_ci%2 = OpLabel
887fd4e5da5Sopenharmony_ci%phi = OpPhi %int %int_1 %1 %int_2 %3
888fd4e5da5Sopenharmony_ci%add = OpIAdd %int %int_1 %phi
889fd4e5da5Sopenharmony_ciOpReturn
890fd4e5da5Sopenharmony_ciOpFunctionEnd
891fd4e5da5Sopenharmony_ci)";
892fd4e5da5Sopenharmony_ci
893fd4e5da5Sopenharmony_ci  SinglePassRunAndMatch<CCPPass>(text, true);
894fd4e5da5Sopenharmony_ci}
895fd4e5da5Sopenharmony_ci
896fd4e5da5Sopenharmony_ci// Test for #1361.
897fd4e5da5Sopenharmony_ciTEST_F(CCPTest, CompositeConstructOfGlobalValue) {
898fd4e5da5Sopenharmony_ci  const std::string text = R"(
899fd4e5da5Sopenharmony_ci; CHECK: [[phi:%\w+]] = OpPhi
900fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpCompositeExtract {{%\w+}} [[phi]] 0
901fd4e5da5Sopenharmony_ciOpCapability Shader
902fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
903fd4e5da5Sopenharmony_ciOpEntryPoint Fragment %func "func" %in
904fd4e5da5Sopenharmony_ciOpExecutionMode %func OriginUpperLeft
905fd4e5da5Sopenharmony_ci%void = OpTypeVoid
906fd4e5da5Sopenharmony_ci%int = OpTypeInt 32 1
907fd4e5da5Sopenharmony_ci%bool = OpTypeBool
908fd4e5da5Sopenharmony_ci%functy = OpTypeFunction %void
909fd4e5da5Sopenharmony_ci%ptr_int_Input = OpTypePointer Input %int
910fd4e5da5Sopenharmony_ci%in = OpVariable %ptr_int_Input Input
911fd4e5da5Sopenharmony_ci%struct = OpTypeStruct %ptr_int_Input %ptr_int_Input
912fd4e5da5Sopenharmony_ci%struct_null = OpConstantNull %struct
913fd4e5da5Sopenharmony_ci%func = OpFunction %void None %functy
914fd4e5da5Sopenharmony_ci%1 = OpLabel
915fd4e5da5Sopenharmony_ciOpBranch %2
916fd4e5da5Sopenharmony_ci%2 = OpLabel
917fd4e5da5Sopenharmony_ci%phi = OpPhi %struct %struct_null %1 %5 %4
918fd4e5da5Sopenharmony_ci%extract = OpCompositeExtract %ptr_int_Input %phi 0
919fd4e5da5Sopenharmony_ciOpLoopMerge %3 %4 None
920fd4e5da5Sopenharmony_ciOpBranch %4
921fd4e5da5Sopenharmony_ci%4 = OpLabel
922fd4e5da5Sopenharmony_ci%5 = OpCompositeConstruct %struct %in %in
923fd4e5da5Sopenharmony_ciOpBranch %2
924fd4e5da5Sopenharmony_ci%3 = OpLabel
925fd4e5da5Sopenharmony_ciOpReturn
926fd4e5da5Sopenharmony_ciOpFunctionEnd
927fd4e5da5Sopenharmony_ci)";
928fd4e5da5Sopenharmony_ci
929fd4e5da5Sopenharmony_ci  SinglePassRunAndMatch<CCPPass>(text, true);
930fd4e5da5Sopenharmony_ci}
931fd4e5da5Sopenharmony_ci
932fd4e5da5Sopenharmony_ciTEST_F(CCPTest, FoldWithDecoration) {
933fd4e5da5Sopenharmony_ci  const std::string text = R"(
934fd4e5da5Sopenharmony_ci; CHECK: OpCapability
935fd4e5da5Sopenharmony_ci; CHECK-NOT: OpDecorate
936fd4e5da5Sopenharmony_ci; CHECK: OpFunctionEnd
937fd4e5da5Sopenharmony_ci               OpCapability Shader
938fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
939fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
940fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %2 "main"
941fd4e5da5Sopenharmony_ci               OpExecutionMode %2 OriginUpperLeft
942fd4e5da5Sopenharmony_ci               OpSource ESSL 310
943fd4e5da5Sopenharmony_ci               OpDecorate %3 RelaxedPrecision
944fd4e5da5Sopenharmony_ci       %void = OpTypeVoid
945fd4e5da5Sopenharmony_ci          %5 = OpTypeFunction %void
946fd4e5da5Sopenharmony_ci      %float = OpTypeFloat 32
947fd4e5da5Sopenharmony_ci    %v3float = OpTypeVector %float 3
948fd4e5da5Sopenharmony_ci    %float_0 = OpConstant %float 0
949fd4e5da5Sopenharmony_ci    %v4float = OpTypeVector %float 4
950fd4e5da5Sopenharmony_ci         %10 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0
951fd4e5da5Sopenharmony_ci          %2 = OpFunction %void None %5
952fd4e5da5Sopenharmony_ci         %11 = OpLabel
953fd4e5da5Sopenharmony_ci          %3 = OpVectorShuffle %v3float %10 %10 0 1 2
954fd4e5da5Sopenharmony_ci               OpReturn
955fd4e5da5Sopenharmony_ci               OpFunctionEnd
956fd4e5da5Sopenharmony_ci)";
957fd4e5da5Sopenharmony_ci
958fd4e5da5Sopenharmony_ci  SinglePassRunAndMatch<CCPPass>(text, true);
959fd4e5da5Sopenharmony_ci}
960fd4e5da5Sopenharmony_ci
961fd4e5da5Sopenharmony_ciTEST_F(CCPTest, DebugSimpleFoldConstant) {
962fd4e5da5Sopenharmony_ci  const std::string text = R"(
963fd4e5da5Sopenharmony_ci               OpCapability Shader
964fd4e5da5Sopenharmony_ci               OpCapability Linkage
965fd4e5da5Sopenharmony_ci        %ext = OpExtInstImport "OpenCL.DebugInfo.100"
966fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
967fd4e5da5Sopenharmony_ci  %file_name = OpString "test"
968fd4e5da5Sopenharmony_ci %float_name = OpString "float"
969fd4e5da5Sopenharmony_ci  %main_name = OpString "main"
970fd4e5da5Sopenharmony_ci     %f_name = OpString "f"
971fd4e5da5Sopenharmony_ci               OpDecorate %1 LinkageAttributes "func" Export
972fd4e5da5Sopenharmony_ci       %void = OpTypeVoid
973fd4e5da5Sopenharmony_ci       %bool = OpTypeBool
974fd4e5da5Sopenharmony_ci      %float = OpTypeFloat 32
975fd4e5da5Sopenharmony_ci    %float_0 = OpConstant %float 0
976fd4e5da5Sopenharmony_ci
977fd4e5da5Sopenharmony_ci; CHECK: [[float1:%\w+]] = OpConstant {{%\w+}} 1
978fd4e5da5Sopenharmony_ci    %float_1 = OpConstant %float 1
979fd4e5da5Sopenharmony_ci       %uint = OpTypeInt 32 0
980fd4e5da5Sopenharmony_ci    %uint_32 = OpConstant %uint 32
981fd4e5da5Sopenharmony_ci          %8 = OpTypeFunction %float
982fd4e5da5Sopenharmony_ci  %null_expr = OpExtInst %void %ext DebugExpression
983fd4e5da5Sopenharmony_ci        %src = OpExtInst %void %ext DebugSource %file_name
984fd4e5da5Sopenharmony_ci         %cu = OpExtInst %void %ext DebugCompilationUnit 1 4 %src HLSL
985fd4e5da5Sopenharmony_ci     %dbg_tf = OpExtInst %void %ext DebugTypeBasic %float_name %uint_32 Float
986fd4e5da5Sopenharmony_ci    %main_ty = OpExtInst %void %ext DebugTypeFunction FlagIsProtected|FlagIsPrivate %dbg_tf
987fd4e5da5Sopenharmony_ci   %dbg_main = OpExtInst %void %ext DebugFunction %main_name %main_ty %src 0 0 %cu %main_name FlagIsProtected|FlagIsPrivate 10 %1
988fd4e5da5Sopenharmony_ci      %dbg_f = OpExtInst %void %ext DebugLocalVariable %f_name %dbg_tf %src 0 0 %dbg_main FlagIsLocal
989fd4e5da5Sopenharmony_ci          %1 = OpFunction %float None %8
990fd4e5da5Sopenharmony_ci         %10 = OpLabel
991fd4e5da5Sopenharmony_ci
992fd4e5da5Sopenharmony_ci; CHECK: OpExtInst %void [[ext:%\w+]] DebugScope
993fd4e5da5Sopenharmony_ci; CHECK: OpLine [[file:%\w+]] 1 0
994fd4e5da5Sopenharmony_ci; CHECK: OpExtInst %void [[ext]] DebugValue {{%\w+}} %float_1
995fd4e5da5Sopenharmony_ci         %s0 = OpExtInst %void %ext DebugScope %dbg_main
996fd4e5da5Sopenharmony_ci               OpLine %file_name 1 0
997fd4e5da5Sopenharmony_ci         %17 = OpFAdd %float %float_0 %float_1
998fd4e5da5Sopenharmony_ci        %val = OpExtInst %void %ext DebugValue %dbg_f %17 %null_expr
999fd4e5da5Sopenharmony_ci
1000fd4e5da5Sopenharmony_ci; CHECK: OpLine [[file]] 2 0
1001fd4e5da5Sopenharmony_ci; CHECK: OpReturnValue [[float1]]
1002fd4e5da5Sopenharmony_ci               OpLine %file_name 2 0
1003fd4e5da5Sopenharmony_ci               OpReturnValue %17
1004fd4e5da5Sopenharmony_ci               OpFunctionEnd
1005fd4e5da5Sopenharmony_ci)";
1006fd4e5da5Sopenharmony_ci
1007fd4e5da5Sopenharmony_ci  SinglePassRunAndMatch<CCPPass>(text, true);
1008fd4e5da5Sopenharmony_ci}
1009fd4e5da5Sopenharmony_ci
1010fd4e5da5Sopenharmony_ciTEST_F(CCPTest, DebugFoldMultipleForSingleConstant) {
1011fd4e5da5Sopenharmony_ci  const std::string text = R"(
1012fd4e5da5Sopenharmony_ci               OpCapability Shader
1013fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
1014fd4e5da5Sopenharmony_ci        %ext = OpExtInstImport "OpenCL.DebugInfo.100"
1015fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
1016fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %main "main" %outparm
1017fd4e5da5Sopenharmony_ci               OpExecutionMode %main OriginUpperLeft
1018fd4e5da5Sopenharmony_ci               OpSource GLSL 450
1019fd4e5da5Sopenharmony_ci  %file_name = OpString "test"
1020fd4e5da5Sopenharmony_ci %float_name = OpString "float"
1021fd4e5da5Sopenharmony_ci  %main_name = OpString "main"
1022fd4e5da5Sopenharmony_ci     %f_name = OpString "f"
1023fd4e5da5Sopenharmony_ci               OpName %main "main"
1024fd4e5da5Sopenharmony_ci               OpName %outparm "outparm"
1025fd4e5da5Sopenharmony_ci               OpDecorate %outparm Location 0
1026fd4e5da5Sopenharmony_ci       %void = OpTypeVoid
1027fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %void
1028fd4e5da5Sopenharmony_ci        %int = OpTypeInt 32 1
1029fd4e5da5Sopenharmony_ci       %bool = OpTypeBool
1030fd4e5da5Sopenharmony_ci%_ptr_Function_int = OpTypePointer Function %int
1031fd4e5da5Sopenharmony_ci      %int_4 = OpConstant %int 4
1032fd4e5da5Sopenharmony_ci      %int_3 = OpConstant %int 3
1033fd4e5da5Sopenharmony_ci      %int_1 = OpConstant %int 1
1034fd4e5da5Sopenharmony_ci       %uint = OpTypeInt 32 0
1035fd4e5da5Sopenharmony_ci    %uint_32 = OpConstant %uint 32
1036fd4e5da5Sopenharmony_ci%_ptr_Output_int = OpTypePointer Output %int
1037fd4e5da5Sopenharmony_ci    %outparm = OpVariable %_ptr_Output_int Output
1038fd4e5da5Sopenharmony_ci  %null_expr = OpExtInst %void %ext DebugExpression
1039fd4e5da5Sopenharmony_ci        %src = OpExtInst %void %ext DebugSource %file_name
1040fd4e5da5Sopenharmony_ci         %cu = OpExtInst %void %ext DebugCompilationUnit 1 4 %src HLSL
1041fd4e5da5Sopenharmony_ci     %dbg_tf = OpExtInst %void %ext DebugTypeBasic %float_name %uint_32 Float
1042fd4e5da5Sopenharmony_ci    %main_ty = OpExtInst %void %ext DebugTypeFunction FlagIsProtected|FlagIsPrivate %dbg_tf
1043fd4e5da5Sopenharmony_ci   %dbg_main = OpExtInst %void %ext DebugFunction %main_name %main_ty %src 0 0 %cu %main_name FlagIsProtected|FlagIsPrivate 10 %main
1044fd4e5da5Sopenharmony_ci        %bb0 = OpExtInst %void %ext DebugLexicalBlock %src 0 0 %dbg_main
1045fd4e5da5Sopenharmony_ci        %bb1 = OpExtInst %void %ext DebugLexicalBlock %src 1 0 %dbg_main
1046fd4e5da5Sopenharmony_ci        %bb2 = OpExtInst %void %ext DebugLexicalBlock %src 2 0 %dbg_main
1047fd4e5da5Sopenharmony_ci        %bb3 = OpExtInst %void %ext DebugLexicalBlock %src 3 0 %dbg_main
1048fd4e5da5Sopenharmony_ci      %dbg_f0 = OpExtInst %void %ext DebugLocalVariable %f_name %dbg_tf %src 0 0 %dbg_main FlagIsLocal
1049fd4e5da5Sopenharmony_ci      %dbg_f1 = OpExtInst %void %ext DebugLocalVariable %f_name %dbg_tf %src 1 0 %dbg_main FlagIsLocal
1050fd4e5da5Sopenharmony_ci      %dbg_f2 = OpExtInst %void %ext DebugLocalVariable %f_name %dbg_tf %src 2 0 %dbg_main FlagIsLocal
1051fd4e5da5Sopenharmony_ci       %main = OpFunction %void None %3
1052fd4e5da5Sopenharmony_ci          %4 = OpLabel
1053fd4e5da5Sopenharmony_ci
1054fd4e5da5Sopenharmony_ci; CHECK: OpExtInst %void [[ext:%\w+]] DebugScope
1055fd4e5da5Sopenharmony_ci; CHECK: OpLine [[file:%\w+]] 1 0
1056fd4e5da5Sopenharmony_ci; CHECK: OpIAdd %int %int_4 %int_3
1057fd4e5da5Sopenharmony_ci; CHECK: OpExtInst %void [[ext]] DebugValue {{%\w+}} %int_7
1058fd4e5da5Sopenharmony_ci         %s0 = OpExtInst %void %ext DebugScope %bb0
1059fd4e5da5Sopenharmony_ci               OpLine %file_name 1 0
1060fd4e5da5Sopenharmony_ci          %9 = OpIAdd %int %int_4 %int_3
1061fd4e5da5Sopenharmony_ci       %val0 = OpExtInst %void %ext DebugValue %dbg_f0 %9 %null_expr
1062fd4e5da5Sopenharmony_ci
1063fd4e5da5Sopenharmony_ci; CHECK: OpLine [[file]] 2 0
1064fd4e5da5Sopenharmony_ci; CHECK: OpSGreaterThan %bool %int_7 %int_3
1065fd4e5da5Sopenharmony_ci; CHECK: OpExtInst %void [[ext]] DebugValue {{%\w+}} %true
1066fd4e5da5Sopenharmony_ci               OpLine %file_name 2 0
1067fd4e5da5Sopenharmony_ci          %6 = OpSGreaterThan %bool %9 %int_3
1068fd4e5da5Sopenharmony_ci       %val1 = OpExtInst %void %ext DebugValue %dbg_f1 %6 %null_expr
1069fd4e5da5Sopenharmony_ci
1070fd4e5da5Sopenharmony_ci               OpSelectionMerge %25 None
1071fd4e5da5Sopenharmony_ci               OpBranchConditional %6 %22 %23
1072fd4e5da5Sopenharmony_ci         %22 = OpLabel
1073fd4e5da5Sopenharmony_ci         %s1 = OpExtInst %void %ext DebugScope %bb1
1074fd4e5da5Sopenharmony_ci          %7 = OpCopyObject %int %9
1075fd4e5da5Sopenharmony_ci       %val2 = OpExtInst %void %ext DebugValue %dbg_f2 %7 %null_expr
1076fd4e5da5Sopenharmony_ci               OpBranch %25
1077fd4e5da5Sopenharmony_ci         %23 = OpLabel
1078fd4e5da5Sopenharmony_ci         %s2 = OpExtInst %void %ext DebugScope %bb2
1079fd4e5da5Sopenharmony_ci          %8 = OpCopyObject %int %int_4
1080fd4e5da5Sopenharmony_ci               OpBranch %25
1081fd4e5da5Sopenharmony_ci         %25 = OpLabel
1082fd4e5da5Sopenharmony_ci         %s3 = OpExtInst %void %ext DebugScope %bb3
1083fd4e5da5Sopenharmony_ci         %35 = OpPhi %int %7 %22 %8 %23
1084fd4e5da5Sopenharmony_ci               OpStore %outparm %35
1085fd4e5da5Sopenharmony_ci               OpReturn
1086fd4e5da5Sopenharmony_ci               OpFunctionEnd
1087fd4e5da5Sopenharmony_ci)";
1088fd4e5da5Sopenharmony_ci
1089fd4e5da5Sopenharmony_ci  SinglePassRunAndMatch<CCPPass>(text, true);
1090fd4e5da5Sopenharmony_ci}
1091fd4e5da5Sopenharmony_ci
1092fd4e5da5Sopenharmony_ci// Test from https://github.com/KhronosGroup/SPIRV-Tools/issues/3636
1093fd4e5da5Sopenharmony_ciTEST_F(CCPTest, CCPNoChangeFailure) {
1094fd4e5da5Sopenharmony_ci  const std::string text = R"(
1095fd4e5da5Sopenharmony_ci               OpCapability Shader
1096fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
1097fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
1098fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %4 "main"
1099fd4e5da5Sopenharmony_ci               OpExecutionMode %4 OriginUpperLeft
1100fd4e5da5Sopenharmony_ci               OpSource ESSL 320
1101fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
1102fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
1103fd4e5da5Sopenharmony_ci          %6 = OpTypeInt 32 1
1104fd4e5da5Sopenharmony_ci          %7 = OpConstant %6 2
1105fd4e5da5Sopenharmony_ci         %13 = OpConstant %6 4
1106fd4e5da5Sopenharmony_ci         %21 = OpConstant %6 1
1107fd4e5da5Sopenharmony_ci         %10 = OpTypeBool
1108fd4e5da5Sopenharmony_ci         %17 = OpTypePointer Function %6
1109fd4e5da5Sopenharmony_ci
1110fd4e5da5Sopenharmony_ci; CCP is generating two new constants during propagation that end up being
1111fd4e5da5Sopenharmony_ci; dead because they cannot be replaced anywhere in the IR.  CCP was wrongly
1112fd4e5da5Sopenharmony_ci; considering the IR to be unmodified because of this.
1113fd4e5da5Sopenharmony_ci; CHECK: %true = OpConstantTrue %bool
1114fd4e5da5Sopenharmony_ci; CHECK: %int_3 = OpConstant %int 3
1115fd4e5da5Sopenharmony_ci
1116fd4e5da5Sopenharmony_ci          %4 = OpFunction %2 None %3
1117fd4e5da5Sopenharmony_ci         %11 = OpLabel
1118fd4e5da5Sopenharmony_ci               OpBranch %5
1119fd4e5da5Sopenharmony_ci          %5 = OpLabel
1120fd4e5da5Sopenharmony_ci         %23 = OpPhi %6 %7 %11 %20 %15
1121fd4e5da5Sopenharmony_ci          %9 = OpSLessThan %10 %23 %13
1122fd4e5da5Sopenharmony_ci               OpLoopMerge %8 %15 None
1123fd4e5da5Sopenharmony_ci               OpBranchConditional %9 %15 %8
1124fd4e5da5Sopenharmony_ci         %15 = OpLabel
1125fd4e5da5Sopenharmony_ci         %20 = OpIAdd %6 %23 %21
1126fd4e5da5Sopenharmony_ci               OpBranch %5
1127fd4e5da5Sopenharmony_ci          %8 = OpLabel
1128fd4e5da5Sopenharmony_ci               OpReturn
1129fd4e5da5Sopenharmony_ci               OpFunctionEnd
1130fd4e5da5Sopenharmony_ci)";
1131fd4e5da5Sopenharmony_ci
1132fd4e5da5Sopenharmony_ci  auto result = SinglePassRunAndMatch<CCPPass>(text, true);
1133fd4e5da5Sopenharmony_ci  EXPECT_EQ(std::get<1>(result), Pass::Status::SuccessWithChange);
1134fd4e5da5Sopenharmony_ci}
1135fd4e5da5Sopenharmony_ci
1136fd4e5da5Sopenharmony_ci// Test from https://github.com/KhronosGroup/SPIRV-Tools/issues/3738
1137fd4e5da5Sopenharmony_ci// Similar to the previous one but more than one constant is generated in a
1138fd4e5da5Sopenharmony_ci// single call to the instruction folder.
1139fd4e5da5Sopenharmony_ciTEST_F(CCPTest, CCPNoChangeFailureSeveralConstantsDuringFolding) {
1140fd4e5da5Sopenharmony_ci  const std::string text = R"(
1141fd4e5da5Sopenharmony_ci               OpCapability Shader
1142fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
1143fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
1144fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %2 "main"
1145fd4e5da5Sopenharmony_ci               OpExecutionMode %2 OriginUpperLeft
1146fd4e5da5Sopenharmony_ci       %void = OpTypeVoid
1147fd4e5da5Sopenharmony_ci          %4 = OpTypeFunction %void
1148fd4e5da5Sopenharmony_ci      %float = OpTypeFloat 32
1149fd4e5da5Sopenharmony_ci    %v3float = OpTypeVector %float 3
1150fd4e5da5Sopenharmony_ci       %uint = OpTypeInt 32 0
1151fd4e5da5Sopenharmony_ci     %uint_0 = OpConstant %uint 0
1152fd4e5da5Sopenharmony_ci       %bool = OpTypeBool
1153fd4e5da5Sopenharmony_ci     %v3bool = OpTypeVector %bool 3
1154fd4e5da5Sopenharmony_ci    %float_0 = OpConstant %float 0
1155fd4e5da5Sopenharmony_ci         %12 = OpConstantComposite %v3float %float_0 %float_0 %float_0
1156fd4e5da5Sopenharmony_ci%float_0_300000012 = OpConstant %float 0.300000012
1157fd4e5da5Sopenharmony_ci         %14 = OpConstantComposite %v3float %float_0_300000012 %float_0_300000012 %float_0_300000012
1158fd4e5da5Sopenharmony_ci
1159fd4e5da5Sopenharmony_ci; CCP is generating several constants during a single instruction evaluation.
1160fd4e5da5Sopenharmony_ci; When folding %19, it generates the constants %true and %24.  They are dead
1161fd4e5da5Sopenharmony_ci; because they cannot be replaced anywhere in the IR.  CCP was wrongly
1162fd4e5da5Sopenharmony_ci; considering the IR to be unmodified because of this.
1163fd4e5da5Sopenharmony_ci;
1164fd4e5da5Sopenharmony_ci; CHECK: %true = OpConstantTrue %bool
1165fd4e5da5Sopenharmony_ci; CHECK: %24 = OpConstantComposite %v3bool %true %true %true
1166fd4e5da5Sopenharmony_ci; CHECK: %float_1 = OpConstant %float 1
1167fd4e5da5Sopenharmony_ci; CHECK: %float_0_699999988 = OpConstant %float 0.699999988
1168fd4e5da5Sopenharmony_ci
1169fd4e5da5Sopenharmony_ci          %2 = OpFunction %void None %4
1170fd4e5da5Sopenharmony_ci         %15 = OpLabel
1171fd4e5da5Sopenharmony_ci               OpBranch %16
1172fd4e5da5Sopenharmony_ci         %16 = OpLabel
1173fd4e5da5Sopenharmony_ci         %17 = OpPhi %v3float %12 %15 %14 %18
1174fd4e5da5Sopenharmony_ci         %19 = OpFOrdLessThan %v3bool %17 %14
1175fd4e5da5Sopenharmony_ci         %20 = OpAll %bool %19
1176fd4e5da5Sopenharmony_ci               OpLoopMerge %21 %18 None
1177fd4e5da5Sopenharmony_ci               OpBranchConditional %20 %18 %21
1178fd4e5da5Sopenharmony_ci         %18 = OpLabel
1179fd4e5da5Sopenharmony_ci               OpBranch %16
1180fd4e5da5Sopenharmony_ci         %21 = OpLabel
1181fd4e5da5Sopenharmony_ci         %22 = OpExtInst %v3float %1 FMix %12 %17 %14
1182fd4e5da5Sopenharmony_ci               OpReturn
1183fd4e5da5Sopenharmony_ci               OpFunctionEnd
1184fd4e5da5Sopenharmony_ci)";
1185fd4e5da5Sopenharmony_ci
1186fd4e5da5Sopenharmony_ci  auto result = SinglePassRunAndMatch<CCPPass>(text, true);
1187fd4e5da5Sopenharmony_ci  EXPECT_EQ(std::get<1>(result), Pass::Status::SuccessWithChange);
1188fd4e5da5Sopenharmony_ci}
1189fd4e5da5Sopenharmony_ci
1190fd4e5da5Sopenharmony_ci// Test from https://github.com/KhronosGroup/SPIRV-Tools/issues/3991
1191fd4e5da5Sopenharmony_ci// Similar to the previous one but constants are created even when no
1192fd4e5da5Sopenharmony_ci// instruction are ever folded during propagation.
1193fd4e5da5Sopenharmony_ciTEST_F(CCPTest, CCPNoChangeFailureWithUnfoldableInstr) {
1194fd4e5da5Sopenharmony_ci  const std::string text = R"(
1195fd4e5da5Sopenharmony_ci               OpCapability Shader
1196fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
1197fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
1198fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %2 "main"
1199fd4e5da5Sopenharmony_ci               OpExecutionMode %2 OriginUpperLeft
1200fd4e5da5Sopenharmony_ci       %void = OpTypeVoid
1201fd4e5da5Sopenharmony_ci          %4 = OpTypeFunction %void
1202fd4e5da5Sopenharmony_ci      %float = OpTypeFloat 32
1203fd4e5da5Sopenharmony_ci    %v3float = OpTypeVector %float 3
1204fd4e5da5Sopenharmony_ci       %uint = OpTypeInt 32 0
1205fd4e5da5Sopenharmony_ci     %uint_0 = OpConstant %uint 0
1206fd4e5da5Sopenharmony_ci       %bool = OpTypeBool
1207fd4e5da5Sopenharmony_ci    %float_0 = OpConstant %float 0
1208fd4e5da5Sopenharmony_ci         %11 = OpConstantComposite %v3float %float_0 %float_0 %float_0
1209fd4e5da5Sopenharmony_ci%float_0_300000012 = OpConstant %float 0.300000012
1210fd4e5da5Sopenharmony_ci         %13 = OpConstantComposite %v3float %float_0_300000012 %float_0_300000012 %float_0_300000012
1211fd4e5da5Sopenharmony_ci
1212fd4e5da5Sopenharmony_ci; CCP generates two constants when trying to fold an instruction, which it
1213fd4e5da5Sopenharmony_ci; ultimately fails to fold. The instruction folder in CCP was only
1214fd4e5da5Sopenharmony_ci; checking for newly added constants if the instruction folds successfully.
1215fd4e5da5Sopenharmony_ci;
1216fd4e5da5Sopenharmony_ci; CHECK: %float_1 = OpConstant %float 1
1217fd4e5da5Sopenharmony_ci; CHECK: %float_0_699999988 = OpConstant %float 0.69999998
1218fd4e5da5Sopenharmony_ci
1219fd4e5da5Sopenharmony_ci          %2 = OpFunction %void None %4
1220fd4e5da5Sopenharmony_ci         %14 = OpLabel
1221fd4e5da5Sopenharmony_ci         %15 = OpBitcast %uint %float_0_300000012
1222fd4e5da5Sopenharmony_ci         %16 = OpUGreaterThan %bool %15 %uint_0
1223fd4e5da5Sopenharmony_ci               OpBranch %17
1224fd4e5da5Sopenharmony_ci         %17 = OpLabel
1225fd4e5da5Sopenharmony_ci         %18 = OpPhi %v3float %11 %14 %13 %19
1226fd4e5da5Sopenharmony_ci               OpLoopMerge %20 %19 None
1227fd4e5da5Sopenharmony_ci               OpBranchConditional %16 %19 %20
1228fd4e5da5Sopenharmony_ci         %19 = OpLabel
1229fd4e5da5Sopenharmony_ci               OpBranch %17
1230fd4e5da5Sopenharmony_ci         %20 = OpLabel
1231fd4e5da5Sopenharmony_ci         %21 = OpExtInst %v3float %1 FMix %11 %18 %13
1232fd4e5da5Sopenharmony_ci               OpReturn
1233fd4e5da5Sopenharmony_ci               OpFunctionEnd
1234fd4e5da5Sopenharmony_ci)";
1235fd4e5da5Sopenharmony_ci
1236fd4e5da5Sopenharmony_ci  auto result = SinglePassRunAndMatch<CCPPass>(text, true);
1237fd4e5da5Sopenharmony_ci  EXPECT_EQ(std::get<1>(result), Pass::Status::SuccessWithChange);
1238fd4e5da5Sopenharmony_ci}
1239fd4e5da5Sopenharmony_ci
1240fd4e5da5Sopenharmony_ciTEST_F(CCPTest, FunctionDeclaration) {
1241fd4e5da5Sopenharmony_ci  // Make sure the pass works with a function declaration that is called.
1242fd4e5da5Sopenharmony_ci  const std::string text = R"(OpCapability Addresses
1243fd4e5da5Sopenharmony_ciOpCapability Linkage
1244fd4e5da5Sopenharmony_ciOpCapability Kernel
1245fd4e5da5Sopenharmony_ciOpCapability Int8
1246fd4e5da5Sopenharmony_ci%1 = OpExtInstImport "OpenCL.std"
1247fd4e5da5Sopenharmony_ciOpMemoryModel Physical64 OpenCL
1248fd4e5da5Sopenharmony_ciOpEntryPoint Kernel %2 "_Z23julia__1166_kernel_77094Bool"
1249fd4e5da5Sopenharmony_ciOpExecutionMode %2 ContractionOff
1250fd4e5da5Sopenharmony_ciOpSource Unknown 0
1251fd4e5da5Sopenharmony_ciOpDecorate %3 LinkageAttributes "julia_error_7712" Import
1252fd4e5da5Sopenharmony_ci%void = OpTypeVoid
1253fd4e5da5Sopenharmony_ci%5 = OpTypeFunction %void
1254fd4e5da5Sopenharmony_ci%3 = OpFunction %void None %5
1255fd4e5da5Sopenharmony_ciOpFunctionEnd
1256fd4e5da5Sopenharmony_ci%2 = OpFunction %void None %5
1257fd4e5da5Sopenharmony_ci%6 = OpLabel
1258fd4e5da5Sopenharmony_ci%7 = OpFunctionCall %void %3
1259fd4e5da5Sopenharmony_ciOpReturn
1260fd4e5da5Sopenharmony_ciOpFunctionEnd
1261fd4e5da5Sopenharmony_ci)";
1262fd4e5da5Sopenharmony_ci
1263fd4e5da5Sopenharmony_ci  SinglePassRunAndCheck<CCPPass>(text, text, false);
1264fd4e5da5Sopenharmony_ci}
1265fd4e5da5Sopenharmony_ci
1266fd4e5da5Sopenharmony_ci// Test from https://github.com/KhronosGroup/SPIRV-Tools/issues/4462.
1267fd4e5da5Sopenharmony_ci// The test was causing a lateral movement in the constant lattice, which was
1268fd4e5da5Sopenharmony_ci// not being detected as varying by CCP. In this test, FClamp is evaluated
1269fd4e5da5Sopenharmony_ci// twice.  On the first evaluation, if computes FClamp(0.5, 0.5, -1) which
1270fd4e5da5Sopenharmony_ci// returns -1.  On the second evaluation, it computes FClamp(0.5, 0.5, VARYING)
1271fd4e5da5Sopenharmony_ci// which returns 0.5.
1272fd4e5da5Sopenharmony_ci//
1273fd4e5da5Sopenharmony_ci// Both fold() computations are correct given the semantics of FClamp() but
1274fd4e5da5Sopenharmony_ci// this causes a lateral transition in the constant lattice which was not being
1275fd4e5da5Sopenharmony_ci// considered VARYING by CCP.
1276fd4e5da5Sopenharmony_ciTEST_F(CCPTest, LateralLatticeTransition) {
1277fd4e5da5Sopenharmony_ci  const std::string text = R"(OpCapability Shader
1278fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
1279fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
1280fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %main "main" %gl_FragCoord %outColor
1281fd4e5da5Sopenharmony_ci               OpExecutionMode %main OriginUpperLeft
1282fd4e5da5Sopenharmony_ci               OpSource ESSL 310
1283fd4e5da5Sopenharmony_ci               OpName %main "main"
1284fd4e5da5Sopenharmony_ci               OpName %gl_FragCoord "gl_FragCoord"
1285fd4e5da5Sopenharmony_ci               OpName %outColor "outColor"
1286fd4e5da5Sopenharmony_ci               OpDecorate %gl_FragCoord BuiltIn FragCoord
1287fd4e5da5Sopenharmony_ci               OpDecorate %outColor Location 0
1288fd4e5da5Sopenharmony_ci       %void = OpTypeVoid
1289fd4e5da5Sopenharmony_ci          %6 = OpTypeFunction %void
1290fd4e5da5Sopenharmony_ci      %float = OpTypeFloat 32
1291fd4e5da5Sopenharmony_ci  %float_0_5 = OpConstant %float 0.5
1292fd4e5da5Sopenharmony_ci    %v4float = OpTypeVector %float 4
1293fd4e5da5Sopenharmony_ci%_ptr_Input_v4float = OpTypePointer Input %v4float
1294fd4e5da5Sopenharmony_ci%gl_FragCoord = OpVariable %_ptr_Input_v4float Input
1295fd4e5da5Sopenharmony_ci       %uint = OpTypeInt 32 0
1296fd4e5da5Sopenharmony_ci     %uint_0 = OpConstant %uint 0
1297fd4e5da5Sopenharmony_ci%_ptr_Input_float = OpTypePointer Input %float
1298fd4e5da5Sopenharmony_ci    %float_0 = OpConstant %float 0
1299fd4e5da5Sopenharmony_ci       %bool = OpTypeBool
1300fd4e5da5Sopenharmony_ci   %float_n1 = OpConstant %float -1
1301fd4e5da5Sopenharmony_ci    %float_1 = OpConstant %float 1
1302fd4e5da5Sopenharmony_ci%_ptr_Output_v4float = OpTypePointer Output %v4float
1303fd4e5da5Sopenharmony_ci   %outColor = OpVariable %_ptr_Output_v4float Output
1304fd4e5da5Sopenharmony_ci
1305fd4e5da5Sopenharmony_ci; This constant is created during the first evaluation of the CompositeConstruct
1306fd4e5da5Sopenharmony_ci; CHECK: [[new_constant:%\d+]] = OpConstantComposite %v4float %float_n1 %float_0_5 %float_0 %float_1
1307fd4e5da5Sopenharmony_ci
1308fd4e5da5Sopenharmony_ci       %main = OpFunction %void None %6
1309fd4e5da5Sopenharmony_ci         %19 = OpLabel
1310fd4e5da5Sopenharmony_ci         %20 = OpAccessChain %_ptr_Input_float %gl_FragCoord %uint_0
1311fd4e5da5Sopenharmony_ci         %21 = OpLoad %float %20
1312fd4e5da5Sopenharmony_ci         %22 = OpFOrdLessThan %bool %21 %float_0
1313fd4e5da5Sopenharmony_ci               OpSelectionMerge %23 None
1314fd4e5da5Sopenharmony_ci               OpBranchConditional %22 %24 %25
1315fd4e5da5Sopenharmony_ci         %24 = OpLabel
1316fd4e5da5Sopenharmony_ci               OpBranch %23
1317fd4e5da5Sopenharmony_ci         %25 = OpLabel
1318fd4e5da5Sopenharmony_ci               OpBranch %26
1319fd4e5da5Sopenharmony_ci         %26 = OpLabel
1320fd4e5da5Sopenharmony_ci               OpBranch %23
1321fd4e5da5Sopenharmony_ci         %23 = OpLabel
1322fd4e5da5Sopenharmony_ci         %27 = OpPhi %float %float_n1 %24 %float_0_5 %26
1323fd4e5da5Sopenharmony_ci         %28 = OpExtInst %float %1 FClamp %float_0_5 %float_0_5 %27
1324fd4e5da5Sopenharmony_ci
1325fd4e5da5Sopenharmony_ci         ; On first evaluation, the result from FClamp will return 0.5.
1326fd4e5da5Sopenharmony_ci         ; But on second evaluation, FClamp should return VARYING.  Check
1327fd4e5da5Sopenharmony_ci         ; that CCP is not keeping the first result.
1328fd4e5da5Sopenharmony_ci         ; CHECK-NOT: %29 = OpCompositeConstruct %v4float %float_0_5 %float_0_5 %float_0 %float_1
1329fd4e5da5Sopenharmony_ci         %29 = OpCompositeConstruct %v4float %28 %float_0_5 %float_0 %float_1
1330fd4e5da5Sopenharmony_ci
1331fd4e5da5Sopenharmony_ci         ; CHECK-NOT: OpCopyObject %v4float [[new_constant]]
1332fd4e5da5Sopenharmony_ci         %42 = OpCopyObject %v4float %29
1333fd4e5da5Sopenharmony_ci
1334fd4e5da5Sopenharmony_ci         ; CHECK-NOT: OpStore %outColor [[new_constant]]
1335fd4e5da5Sopenharmony_ci               OpStore %outColor %42
1336fd4e5da5Sopenharmony_ci
1337fd4e5da5Sopenharmony_ci               OpReturn
1338fd4e5da5Sopenharmony_ci               OpFunctionEnd
1339fd4e5da5Sopenharmony_ci)";
1340fd4e5da5Sopenharmony_ci
1341fd4e5da5Sopenharmony_ci  auto result = SinglePassRunAndMatch<CCPPass>(text, true);
1342fd4e5da5Sopenharmony_ci  EXPECT_EQ(std::get<1>(result), Pass::Status::SuccessWithChange);
1343fd4e5da5Sopenharmony_ci}
1344fd4e5da5Sopenharmony_ci
1345fd4e5da5Sopenharmony_ci}  // namespace
1346fd4e5da5Sopenharmony_ci}  // namespace opt
1347fd4e5da5Sopenharmony_ci}  // namespace spvtools
1348