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 "source/opt/scalar_replacement_pass.h"
18fd4e5da5Sopenharmony_ci#include "test/opt/assembly_builder.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 ScalarReplacementPassName = ::testing::Test;
27fd4e5da5Sopenharmony_ci
28fd4e5da5Sopenharmony_ciTEST_F(ScalarReplacementPassName, Default) {
29fd4e5da5Sopenharmony_ci  auto srp = ScalarReplacementPass();
30fd4e5da5Sopenharmony_ci  EXPECT_STREQ(srp.name(), "scalar-replacement=100");
31fd4e5da5Sopenharmony_ci}
32fd4e5da5Sopenharmony_ci
33fd4e5da5Sopenharmony_ciTEST_F(ScalarReplacementPassName, Large) {
34fd4e5da5Sopenharmony_ci  auto srp = ScalarReplacementPass(0xffffffffu);
35fd4e5da5Sopenharmony_ci  EXPECT_STREQ(srp.name(), "scalar-replacement=4294967295");
36fd4e5da5Sopenharmony_ci}
37fd4e5da5Sopenharmony_ci
38fd4e5da5Sopenharmony_ciusing ScalarReplacementTest = PassTest<::testing::Test>;
39fd4e5da5Sopenharmony_ci
40fd4e5da5Sopenharmony_ciTEST_F(ScalarReplacementTest, SimpleStruct) {
41fd4e5da5Sopenharmony_ci  const std::string text = R"(
42fd4e5da5Sopenharmony_ci;
43fd4e5da5Sopenharmony_ci; CHECK: [[struct:%\w+]] = OpTypeStruct [[elem:%\w+]]
44fd4e5da5Sopenharmony_ci; CHECK: [[struct_ptr:%\w+]] = OpTypePointer Function [[struct]]
45fd4e5da5Sopenharmony_ci; CHECK: [[elem_ptr:%\w+]] = OpTypePointer Function [[elem]]
46fd4e5da5Sopenharmony_ci; CHECK: OpConstantNull [[struct]]
47fd4e5da5Sopenharmony_ci; CHECK: [[null:%\w+]] = OpConstantNull [[elem]]
48fd4e5da5Sopenharmony_ci; CHECK-NOT: OpVariable [[struct_ptr]]
49fd4e5da5Sopenharmony_ci; CHECK: [[one:%\w+]] = OpVariable [[elem_ptr]] Function [[null]]
50fd4e5da5Sopenharmony_ci; CHECK-NEXT: [[two:%\w+]] = OpVariable [[elem_ptr]] Function [[null]]
51fd4e5da5Sopenharmony_ci; CHECK-NOT: OpVariable [[elem_ptr]] Function [[null]]
52fd4e5da5Sopenharmony_ci; CHECK-NOT: OpVariable [[struct_ptr]]
53fd4e5da5Sopenharmony_ci; CHECK-NOT: OpInBoundsAccessChain
54fd4e5da5Sopenharmony_ci; CHECK: [[l1:%\w+]] = OpLoad [[elem]] [[two]]
55fd4e5da5Sopenharmony_ci; CHECK-NOT: OpAccessChain
56fd4e5da5Sopenharmony_ci; CHECK: [[l2:%\w+]] = OpLoad [[elem]] [[one]]
57fd4e5da5Sopenharmony_ci; CHECK: OpIAdd [[elem]] [[l1]] [[l2]]
58fd4e5da5Sopenharmony_ci;
59fd4e5da5Sopenharmony_ciOpCapability Shader
60fd4e5da5Sopenharmony_ciOpCapability Linkage
61fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
62fd4e5da5Sopenharmony_ciOpName %6 "simple_struct"
63fd4e5da5Sopenharmony_ci%1 = OpTypeVoid
64fd4e5da5Sopenharmony_ci%2 = OpTypeInt 32 0
65fd4e5da5Sopenharmony_ci%3 = OpTypeStruct %2 %2 %2 %2
66fd4e5da5Sopenharmony_ci%4 = OpTypePointer Function %3
67fd4e5da5Sopenharmony_ci%5 = OpTypePointer Function %2
68fd4e5da5Sopenharmony_ci%6 = OpTypeFunction %2
69fd4e5da5Sopenharmony_ci%7 = OpConstantNull %3
70fd4e5da5Sopenharmony_ci%8 = OpConstant %2 0
71fd4e5da5Sopenharmony_ci%9 = OpConstant %2 1
72fd4e5da5Sopenharmony_ci%10 = OpConstant %2 2
73fd4e5da5Sopenharmony_ci%11 = OpConstant %2 3
74fd4e5da5Sopenharmony_ci%12 = OpFunction %2 None %6
75fd4e5da5Sopenharmony_ci%13 = OpLabel
76fd4e5da5Sopenharmony_ci%14 = OpVariable %4 Function %7
77fd4e5da5Sopenharmony_ci%15 = OpInBoundsAccessChain %5 %14 %8
78fd4e5da5Sopenharmony_ci%16 = OpLoad %2 %15
79fd4e5da5Sopenharmony_ci%17 = OpAccessChain %5 %14 %10
80fd4e5da5Sopenharmony_ci%18 = OpLoad %2 %17
81fd4e5da5Sopenharmony_ci%19 = OpIAdd %2 %16 %18
82fd4e5da5Sopenharmony_ciOpReturnValue %19
83fd4e5da5Sopenharmony_ciOpFunctionEnd
84fd4e5da5Sopenharmony_ci  )";
85fd4e5da5Sopenharmony_ci
86fd4e5da5Sopenharmony_ci  SinglePassRunAndMatch<ScalarReplacementPass>(text, true);
87fd4e5da5Sopenharmony_ci}
88fd4e5da5Sopenharmony_ci
89fd4e5da5Sopenharmony_ciTEST_F(ScalarReplacementTest, StructInitialization) {
90fd4e5da5Sopenharmony_ci  const std::string text = R"(
91fd4e5da5Sopenharmony_ci;
92fd4e5da5Sopenharmony_ci; CHECK: [[elem:%\w+]] = OpTypeInt 32 0
93fd4e5da5Sopenharmony_ci; CHECK: [[struct:%\w+]] = OpTypeStruct [[elem]] [[elem]] [[elem]] [[elem]]
94fd4e5da5Sopenharmony_ci; CHECK: [[struct_ptr:%\w+]] = OpTypePointer Function [[struct]]
95fd4e5da5Sopenharmony_ci; CHECK: [[elem_ptr:%\w+]] = OpTypePointer Function [[elem]]
96fd4e5da5Sopenharmony_ci; CHECK: [[zero:%\w+]] = OpConstant [[elem]] 0
97fd4e5da5Sopenharmony_ci; CHECK: [[undef:%\w+]] = OpUndef [[elem]]
98fd4e5da5Sopenharmony_ci; CHECK: [[two:%\w+]] = OpConstant [[elem]] 2
99fd4e5da5Sopenharmony_ci; CHECK: [[null:%\w+]] = OpConstantNull [[elem]]
100fd4e5da5Sopenharmony_ci; CHECK-NOT: OpVariable [[struct_ptr]]
101fd4e5da5Sopenharmony_ci; CHECK: OpVariable [[elem_ptr]] Function [[null]]
102fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpVariable [[elem_ptr]] Function [[two]]
103fd4e5da5Sopenharmony_ci; CHECK-NOT: OpVariable [[elem_ptr]] Function [[undef]]
104fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpVariable [[elem_ptr]] Function
105fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpVariable [[elem_ptr]] Function [[zero]]
106fd4e5da5Sopenharmony_ci; CHECK-NOT: OpVariable [[elem_ptr]] Function [[undef]]
107fd4e5da5Sopenharmony_ci;
108fd4e5da5Sopenharmony_ciOpCapability Shader
109fd4e5da5Sopenharmony_ciOpCapability Linkage
110fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
111fd4e5da5Sopenharmony_ciOpName %6 "struct_init"
112fd4e5da5Sopenharmony_ci%1 = OpTypeVoid
113fd4e5da5Sopenharmony_ci%2 = OpTypeInt 32 0
114fd4e5da5Sopenharmony_ci%3 = OpTypeStruct %2 %2 %2 %2
115fd4e5da5Sopenharmony_ci%4 = OpTypePointer Function %3
116fd4e5da5Sopenharmony_ci%20 = OpTypePointer Function %2
117fd4e5da5Sopenharmony_ci%6 = OpTypeFunction %1
118fd4e5da5Sopenharmony_ci%7 = OpConstant %2 0
119fd4e5da5Sopenharmony_ci%8 = OpUndef %2
120fd4e5da5Sopenharmony_ci%9 = OpConstant %2 2
121fd4e5da5Sopenharmony_ci%30 = OpConstant %2 1
122fd4e5da5Sopenharmony_ci%31 = OpConstant %2 3
123fd4e5da5Sopenharmony_ci%10 = OpConstantNull %2
124fd4e5da5Sopenharmony_ci%11 = OpConstantComposite %3 %7 %8 %9 %10
125fd4e5da5Sopenharmony_ci%12 = OpFunction %1 None %6
126fd4e5da5Sopenharmony_ci%13 = OpLabel
127fd4e5da5Sopenharmony_ci%14 = OpVariable %4 Function %11
128fd4e5da5Sopenharmony_ci%15 = OpAccessChain %20 %14 %7
129fd4e5da5Sopenharmony_ciOpStore %15 %10
130fd4e5da5Sopenharmony_ci%16 = OpAccessChain %20 %14 %9
131fd4e5da5Sopenharmony_ciOpStore %16 %10
132fd4e5da5Sopenharmony_ci%17 = OpAccessChain %20 %14 %30
133fd4e5da5Sopenharmony_ciOpStore %17 %10
134fd4e5da5Sopenharmony_ci%18 = OpAccessChain %20 %14 %31
135fd4e5da5Sopenharmony_ciOpStore %18 %10
136fd4e5da5Sopenharmony_ciOpReturn
137fd4e5da5Sopenharmony_ciOpFunctionEnd
138fd4e5da5Sopenharmony_ci  )";
139fd4e5da5Sopenharmony_ci
140fd4e5da5Sopenharmony_ci  SinglePassRunAndMatch<ScalarReplacementPass>(text, true);
141fd4e5da5Sopenharmony_ci}
142fd4e5da5Sopenharmony_ci
143fd4e5da5Sopenharmony_ciTEST_F(ScalarReplacementTest, SpecConstantInitialization) {
144fd4e5da5Sopenharmony_ci  const std::string text = R"(
145fd4e5da5Sopenharmony_ci;
146fd4e5da5Sopenharmony_ci; CHECK: [[int:%\w+]] = OpTypeInt 32 0
147fd4e5da5Sopenharmony_ci; CHECK: [[struct:%\w+]] = OpTypeStruct [[int]] [[int]]
148fd4e5da5Sopenharmony_ci; CHECK: [[struct_ptr:%\w+]] = OpTypePointer Function [[struct]]
149fd4e5da5Sopenharmony_ci; CHECK: [[int_ptr:%\w+]] = OpTypePointer Function [[int]]
150fd4e5da5Sopenharmony_ci; CHECK: [[spec_comp:%\w+]] = OpSpecConstantComposite [[struct]]
151fd4e5da5Sopenharmony_ci; CHECK: [[ex0:%\w+]] = OpSpecConstantOp [[int]] CompositeExtract [[spec_comp]] 0
152fd4e5da5Sopenharmony_ci; CHECK: [[ex1:%\w+]] = OpSpecConstantOp [[int]] CompositeExtract [[spec_comp]] 1
153fd4e5da5Sopenharmony_ci; CHECK-NOT: OpVariable [[struct]]
154fd4e5da5Sopenharmony_ci; CHECK: OpVariable [[int_ptr]] Function [[ex1]]
155fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpVariable [[int_ptr]] Function [[ex0]]
156fd4e5da5Sopenharmony_ci; CHECK-NOT: OpVariable [[struct]]
157fd4e5da5Sopenharmony_ci;
158fd4e5da5Sopenharmony_ciOpCapability Shader
159fd4e5da5Sopenharmony_ciOpCapability Linkage
160fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
161fd4e5da5Sopenharmony_ciOpName %6 "spec_const"
162fd4e5da5Sopenharmony_ci%1 = OpTypeVoid
163fd4e5da5Sopenharmony_ci%2 = OpTypeInt 32 0
164fd4e5da5Sopenharmony_ci%3 = OpTypeStruct %2 %2
165fd4e5da5Sopenharmony_ci%4 = OpTypePointer Function %3
166fd4e5da5Sopenharmony_ci%20 = OpTypePointer Function %2
167fd4e5da5Sopenharmony_ci%5 = OpTypeFunction %1
168fd4e5da5Sopenharmony_ci%6 = OpConstant %2 0
169fd4e5da5Sopenharmony_ci%30 = OpConstant %2 1
170fd4e5da5Sopenharmony_ci%7 = OpSpecConstant %2 0
171fd4e5da5Sopenharmony_ci%8 = OpSpecConstantOp %2 IAdd %7 %7
172fd4e5da5Sopenharmony_ci%9 = OpSpecConstantComposite %3 %7 %8
173fd4e5da5Sopenharmony_ci%10 = OpFunction %1 None %5
174fd4e5da5Sopenharmony_ci%11 = OpLabel
175fd4e5da5Sopenharmony_ci%12 = OpVariable %4 Function %9
176fd4e5da5Sopenharmony_ci%13 = OpAccessChain %20 %12 %6
177fd4e5da5Sopenharmony_ci%14 = OpLoad %2 %13
178fd4e5da5Sopenharmony_ci%15 = OpAccessChain %20 %12 %30
179fd4e5da5Sopenharmony_ci%16 = OpLoad %2 %15
180fd4e5da5Sopenharmony_ciOpReturn
181fd4e5da5Sopenharmony_ciOpFunctionEnd
182fd4e5da5Sopenharmony_ci  )";
183fd4e5da5Sopenharmony_ci
184fd4e5da5Sopenharmony_ci  SinglePassRunAndMatch<ScalarReplacementPass>(text, true);
185fd4e5da5Sopenharmony_ci}
186fd4e5da5Sopenharmony_ci
187fd4e5da5Sopenharmony_ci// TODO(alanbaker): Re-enable when vector and matrix scalarization is supported.
188fd4e5da5Sopenharmony_ci// TEST_F(ScalarReplacementTest, VectorInitialization) {
189fd4e5da5Sopenharmony_ci//  const std::string text = R"(
190fd4e5da5Sopenharmony_ci// ;
191fd4e5da5Sopenharmony_ci// ; CHECK: [[elem:%\w+]] = OpTypeInt 32 0
192fd4e5da5Sopenharmony_ci// ; CHECK: [[vector:%\w+]] = OpTypeVector [[elem]] 4
193fd4e5da5Sopenharmony_ci// ; CHECK: [[vector_ptr:%\w+]] = OpTypePointer Function [[vector]]
194fd4e5da5Sopenharmony_ci// ; CHECK: [[elem_ptr:%\w+]] = OpTypePointer Function [[elem]]
195fd4e5da5Sopenharmony_ci// ; CHECK: [[zero:%\w+]] = OpConstant [[elem]] 0
196fd4e5da5Sopenharmony_ci// ; CHECK: [[undef:%\w+]] = OpUndef [[elem]]
197fd4e5da5Sopenharmony_ci// ; CHECK: [[two:%\w+]] = OpConstant [[elem]] 2
198fd4e5da5Sopenharmony_ci// ; CHECK: [[null:%\w+]] = OpConstantNull [[elem]]
199fd4e5da5Sopenharmony_ci// ; CHECK-NOT: OpVariable [[vector_ptr]]
200fd4e5da5Sopenharmony_ci// ; CHECK: OpVariable [[elem_ptr]] Function [[zero]]
201fd4e5da5Sopenharmony_ci// ; CHECK-NOT: OpVariable [[elem_ptr]] Function [[undef]]
202fd4e5da5Sopenharmony_ci// ; CHECK-NEXT: OpVariable [[elem_ptr]] Function
203fd4e5da5Sopenharmony_ci// ; CHECK-NEXT: OpVariable [[elem_ptr]] Function [[two]]
204fd4e5da5Sopenharmony_ci// ; CHECK-NEXT: OpVariable [[elem_ptr]] Function [[null]]
205fd4e5da5Sopenharmony_ci// ; CHECK-NOT: OpVariable [[elem_ptr]] Function [[undef]]
206fd4e5da5Sopenharmony_ci// ;
207fd4e5da5Sopenharmony_ci//  OpCapability Shader
208fd4e5da5Sopenharmony_ci//  OpCapability Linkage
209fd4e5da5Sopenharmony_ci//  OpMemoryModel Logical GLSL450
210fd4e5da5Sopenharmony_ci//  OpName %6 "vector_init"
211fd4e5da5Sopenharmony_ci// %1 = OpTypeVoid
212fd4e5da5Sopenharmony_ci// %2 = OpTypeInt 32 0
213fd4e5da5Sopenharmony_ci// %3 = OpTypeVector %2 4
214fd4e5da5Sopenharmony_ci// %4 = OpTypePointer Function %3
215fd4e5da5Sopenharmony_ci// %20 = OpTypePointer Function %2
216fd4e5da5Sopenharmony_ci// %6 = OpTypeFunction %1
217fd4e5da5Sopenharmony_ci// %7 = OpConstant %2 0
218fd4e5da5Sopenharmony_ci// %8 = OpUndef %2
219fd4e5da5Sopenharmony_ci// %9 = OpConstant %2 2
220fd4e5da5Sopenharmony_ci// %30 = OpConstant %2 1
221fd4e5da5Sopenharmony_ci// %31 = OpConstant %2 3
222fd4e5da5Sopenharmony_ci// %10 = OpConstantNull %2
223fd4e5da5Sopenharmony_ci// %11 = OpConstantComposite %3 %10 %9 %8 %7
224fd4e5da5Sopenharmony_ci// %12 = OpFunction %1 None %6
225fd4e5da5Sopenharmony_ci// %13 = OpLabel
226fd4e5da5Sopenharmony_ci// %14 = OpVariable %4 Function %11
227fd4e5da5Sopenharmony_ci// %15 = OpAccessChain %20 %14 %7
228fd4e5da5Sopenharmony_ci//  OpStore %15 %10
229fd4e5da5Sopenharmony_ci// %16 = OpAccessChain %20 %14 %9
230fd4e5da5Sopenharmony_ci//  OpStore %16 %10
231fd4e5da5Sopenharmony_ci// %17 = OpAccessChain %20 %14 %30
232fd4e5da5Sopenharmony_ci//  OpStore %17 %10
233fd4e5da5Sopenharmony_ci// %18 = OpAccessChain %20 %14 %31
234fd4e5da5Sopenharmony_ci//  OpStore %18 %10
235fd4e5da5Sopenharmony_ci//  OpReturn
236fd4e5da5Sopenharmony_ci//  OpFunctionEnd
237fd4e5da5Sopenharmony_ci//   )";
238fd4e5da5Sopenharmony_ci//
239fd4e5da5Sopenharmony_ci//   SinglePassRunAndMatch<opt::ScalarReplacementPass>(text, true);
240fd4e5da5Sopenharmony_ci// }
241fd4e5da5Sopenharmony_ci//
242fd4e5da5Sopenharmony_ci//  TEST_F(ScalarReplacementTest, MatrixInitialization) {
243fd4e5da5Sopenharmony_ci//   const std::string text = R"(
244fd4e5da5Sopenharmony_ci// ;
245fd4e5da5Sopenharmony_ci// ; CHECK: [[float:%\w+]] = OpTypeFloat 32
246fd4e5da5Sopenharmony_ci// ; CHECK: [[vector:%\w+]] = OpTypeVector [[float]] 2
247fd4e5da5Sopenharmony_ci// ; CHECK: [[matrix:%\w+]] = OpTypeMatrix [[vector]] 2
248fd4e5da5Sopenharmony_ci// ; CHECK: [[matrix_ptr:%\w+]] = OpTypePointer Function [[matrix]]
249fd4e5da5Sopenharmony_ci// ; CHECK: [[float_ptr:%\w+]] = OpTypePointer Function [[float]]
250fd4e5da5Sopenharmony_ci// ; CHECK: [[vec_ptr:%\w+]] = OpTypePointer Function [[vector]]
251fd4e5da5Sopenharmony_ci// ; CHECK: [[zerof:%\w+]] = OpConstant [[float]] 0
252fd4e5da5Sopenharmony_ci// ; CHECK: [[onef:%\w+]] = OpConstant [[float]] 1
253fd4e5da5Sopenharmony_ci// ; CHECK: [[one_zero:%\w+]] = OpConstantComposite [[vector]] [[onef]]
254fd4e5da5Sopenharmony_ci// [[zerof]] ; CHECK: [[zero_one:%\w+]] = OpConstantComposite [[vector]]
255fd4e5da5Sopenharmony_ci// [[zerof]] [[onef]] ; CHECK: [[const_mat:%\w+]] = OpConstantComposite
256fd4e5da5Sopenharmony_ci// [[matrix]] [[one_zero]]
257fd4e5da5Sopenharmony_ci// [[zero_one]] ; CHECK-NOT: OpVariable [[matrix]] ; CHECK-NOT: OpVariable
258fd4e5da5Sopenharmony_ci// [[vector]] Function [[one_zero]] ; CHECK: [[f1:%\w+]] = OpVariable
259fd4e5da5Sopenharmony_ci// [[float_ptr]] Function [[zerof]] ; CHECK-NEXT: [[f2:%\w+]] = OpVariable
260fd4e5da5Sopenharmony_ci// [[float_ptr]] Function [[onef]] ; CHECK-NEXT: [[vec_var:%\w+]] = OpVariable
261fd4e5da5Sopenharmony_ci// [[vec_ptr]] Function [[zero_one]] ; CHECK-NOT: OpVariable [[matrix]] ;
262fd4e5da5Sopenharmony_ci//  CHECK-NOT: OpVariable [[vector]] Function [[one_zero]]
263fd4e5da5Sopenharmony_ci// ;
264fd4e5da5Sopenharmony_ci//  OpCapability Shader
265fd4e5da5Sopenharmony_ci//  OpCapability Linkage
266fd4e5da5Sopenharmony_ci//  OpMemoryModel Logical GLSL450
267fd4e5da5Sopenharmony_ci//  OpName %7 "matrix_init"
268fd4e5da5Sopenharmony_ci// %1 = OpTypeVoid
269fd4e5da5Sopenharmony_ci// %2 = OpTypeFloat 32
270fd4e5da5Sopenharmony_ci// %3 = OpTypeVector %2 2
271fd4e5da5Sopenharmony_ci// %4 = OpTypeMatrix %3 2
272fd4e5da5Sopenharmony_ci// %5 = OpTypePointer Function %4
273fd4e5da5Sopenharmony_ci// %6 = OpTypePointer Function %2
274fd4e5da5Sopenharmony_ci// %30 = OpTypePointer Function %3
275fd4e5da5Sopenharmony_ci// %10 = OpTypeInt 32 0
276fd4e5da5Sopenharmony_ci// %7 = OpTypeFunction %1 %10
277fd4e5da5Sopenharmony_ci// %8 = OpConstant %2 0.0
278fd4e5da5Sopenharmony_ci// %9 = OpConstant %2 1.0
279fd4e5da5Sopenharmony_ci// %11 = OpConstant %10 0
280fd4e5da5Sopenharmony_ci// %12 = OpConstant %10 1
281fd4e5da5Sopenharmony_ci// %13 = OpConstantComposite %3 %9 %8
282fd4e5da5Sopenharmony_ci// %14 = OpConstantComposite %3 %8 %9
283fd4e5da5Sopenharmony_ci// %15 = OpConstantComposite %4 %13 %14
284fd4e5da5Sopenharmony_ci// %16 = OpFunction %1 None %7
285fd4e5da5Sopenharmony_ci// %31 = OpFunctionParameter %10
286fd4e5da5Sopenharmony_ci// %17 = OpLabel
287fd4e5da5Sopenharmony_ci// %18 = OpVariable %5 Function %15
288fd4e5da5Sopenharmony_ci// %19 = OpAccessChain %6 %18 %11 %12
289fd4e5da5Sopenharmony_ci//  OpStore %19 %8
290fd4e5da5Sopenharmony_ci// %20 = OpAccessChain %6 %18 %11 %11
291fd4e5da5Sopenharmony_ci//  OpStore %20 %8
292fd4e5da5Sopenharmony_ci// %21 = OpAccessChain %30 %18 %12
293fd4e5da5Sopenharmony_ci//  OpStore %21 %14
294fd4e5da5Sopenharmony_ci//  OpReturn
295fd4e5da5Sopenharmony_ci//  OpFunctionEnd
296fd4e5da5Sopenharmony_ci//   )";
297fd4e5da5Sopenharmony_ci//
298fd4e5da5Sopenharmony_ci//   SinglePassRunAndMatch<opt::ScalarReplacementPass>(text, true);
299fd4e5da5Sopenharmony_ci// }
300fd4e5da5Sopenharmony_ci
301fd4e5da5Sopenharmony_ciTEST_F(ScalarReplacementTest, ElideAccessChain) {
302fd4e5da5Sopenharmony_ci  const std::string text = R"(
303fd4e5da5Sopenharmony_ci;
304fd4e5da5Sopenharmony_ci; CHECK: [[var:%\w+]] = OpVariable
305fd4e5da5Sopenharmony_ci; CHECK-NOT: OpAccessChain
306fd4e5da5Sopenharmony_ci; CHECK: OpStore [[var]]
307fd4e5da5Sopenharmony_ci;
308fd4e5da5Sopenharmony_ciOpCapability Shader
309fd4e5da5Sopenharmony_ciOpCapability Linkage
310fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
311fd4e5da5Sopenharmony_ciOpName %6 "elide_access_chain"
312fd4e5da5Sopenharmony_ci%1 = OpTypeVoid
313fd4e5da5Sopenharmony_ci%2 = OpTypeInt 32 0
314fd4e5da5Sopenharmony_ci%3 = OpTypeStruct %2 %2 %2 %2
315fd4e5da5Sopenharmony_ci%4 = OpTypePointer Function %3
316fd4e5da5Sopenharmony_ci%20 = OpTypePointer Function %2
317fd4e5da5Sopenharmony_ci%6 = OpTypeFunction %1
318fd4e5da5Sopenharmony_ci%7 = OpConstant %2 0
319fd4e5da5Sopenharmony_ci%8 = OpUndef %2
320fd4e5da5Sopenharmony_ci%9 = OpConstant %2 2
321fd4e5da5Sopenharmony_ci%10 = OpConstantNull %2
322fd4e5da5Sopenharmony_ci%11 = OpConstantComposite %3 %7 %8 %9 %10
323fd4e5da5Sopenharmony_ci%12 = OpFunction %1 None %6
324fd4e5da5Sopenharmony_ci%13 = OpLabel
325fd4e5da5Sopenharmony_ci%14 = OpVariable %4 Function %11
326fd4e5da5Sopenharmony_ci%15 = OpAccessChain %20 %14 %7
327fd4e5da5Sopenharmony_ciOpStore %15 %10
328fd4e5da5Sopenharmony_ciOpReturn
329fd4e5da5Sopenharmony_ciOpFunctionEnd
330fd4e5da5Sopenharmony_ci  )";
331fd4e5da5Sopenharmony_ci
332fd4e5da5Sopenharmony_ci  SinglePassRunAndMatch<ScalarReplacementPass>(text, true);
333fd4e5da5Sopenharmony_ci}
334fd4e5da5Sopenharmony_ci
335fd4e5da5Sopenharmony_ciTEST_F(ScalarReplacementTest, ElideMultipleAccessChains) {
336fd4e5da5Sopenharmony_ci  const std::string text = R"(
337fd4e5da5Sopenharmony_ci;
338fd4e5da5Sopenharmony_ci; CHECK: [[var:%\w+]] = OpVariable
339fd4e5da5Sopenharmony_ci; CHECK-NOT: OpInBoundsAccessChain
340fd4e5da5Sopenharmony_ci; CHECK OpStore [[var]]
341fd4e5da5Sopenharmony_ci;
342fd4e5da5Sopenharmony_ciOpCapability Shader
343fd4e5da5Sopenharmony_ciOpCapability Linkage
344fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
345fd4e5da5Sopenharmony_ciOpName %6 "elide_two_access_chains"
346fd4e5da5Sopenharmony_ci%1 = OpTypeVoid
347fd4e5da5Sopenharmony_ci%2 = OpTypeFloat 32
348fd4e5da5Sopenharmony_ci%3 = OpTypeStruct %2 %2
349fd4e5da5Sopenharmony_ci%4 = OpTypeStruct %3 %3
350fd4e5da5Sopenharmony_ci%5 = OpTypePointer Function %4
351fd4e5da5Sopenharmony_ci%6 = OpTypePointer Function %2
352fd4e5da5Sopenharmony_ci%7 = OpTypeFunction %1
353fd4e5da5Sopenharmony_ci%8 = OpConstant %2 0.0
354fd4e5da5Sopenharmony_ci%9 = OpConstant %2 1.0
355fd4e5da5Sopenharmony_ci%10 = OpTypeInt 32 0
356fd4e5da5Sopenharmony_ci%11 = OpConstant %10 0
357fd4e5da5Sopenharmony_ci%12 = OpConstant %10 1
358fd4e5da5Sopenharmony_ci%13 = OpConstantComposite %3 %9 %8
359fd4e5da5Sopenharmony_ci%14 = OpConstantComposite %3 %8 %9
360fd4e5da5Sopenharmony_ci%15 = OpConstantComposite %4 %13 %14
361fd4e5da5Sopenharmony_ci%16 = OpFunction %1 None %7
362fd4e5da5Sopenharmony_ci%17 = OpLabel
363fd4e5da5Sopenharmony_ci%18 = OpVariable %5 Function %15
364fd4e5da5Sopenharmony_ci%19 = OpInBoundsAccessChain %6 %18 %11 %12
365fd4e5da5Sopenharmony_ciOpStore %19 %8
366fd4e5da5Sopenharmony_ciOpReturn
367fd4e5da5Sopenharmony_ciOpFunctionEnd
368fd4e5da5Sopenharmony_ci  )";
369fd4e5da5Sopenharmony_ci
370fd4e5da5Sopenharmony_ci  SinglePassRunAndMatch<ScalarReplacementPass>(text, true);
371fd4e5da5Sopenharmony_ci}
372fd4e5da5Sopenharmony_ci
373fd4e5da5Sopenharmony_ciTEST_F(ScalarReplacementTest, ReplaceAccessChain) {
374fd4e5da5Sopenharmony_ci  const std::string text = R"(
375fd4e5da5Sopenharmony_ci;
376fd4e5da5Sopenharmony_ci; CHECK: [[param:%\w+]] = OpFunctionParameter
377fd4e5da5Sopenharmony_ci; CHECK: [[var:%\w+]] = OpVariable
378fd4e5da5Sopenharmony_ci; CHECK: [[access:%\w+]] = OpAccessChain {{%\w+}} [[var]] [[param]]
379fd4e5da5Sopenharmony_ci; CHECK: OpStore [[access]]
380fd4e5da5Sopenharmony_ci;
381fd4e5da5Sopenharmony_ciOpCapability Shader
382fd4e5da5Sopenharmony_ciOpCapability Linkage
383fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
384fd4e5da5Sopenharmony_ciOpName %7 "replace_access_chain"
385fd4e5da5Sopenharmony_ci%1 = OpTypeVoid
386fd4e5da5Sopenharmony_ci%2 = OpTypeFloat 32
387fd4e5da5Sopenharmony_ci%10 = OpTypeInt 32 0
388fd4e5da5Sopenharmony_ci%uint_2 = OpConstant %10 2
389fd4e5da5Sopenharmony_ci%3 = OpTypeArray %2 %uint_2
390fd4e5da5Sopenharmony_ci%4 = OpTypeStruct %3 %3
391fd4e5da5Sopenharmony_ci%5 = OpTypePointer Function %4
392fd4e5da5Sopenharmony_ci%20 = OpTypePointer Function %3
393fd4e5da5Sopenharmony_ci%6 = OpTypePointer Function %2
394fd4e5da5Sopenharmony_ci%7 = OpTypeFunction %1 %10
395fd4e5da5Sopenharmony_ci%8 = OpConstant %2 0.0
396fd4e5da5Sopenharmony_ci%9 = OpConstant %2 1.0
397fd4e5da5Sopenharmony_ci%11 = OpConstant %10 0
398fd4e5da5Sopenharmony_ci%12 = OpConstant %10 1
399fd4e5da5Sopenharmony_ci%13 = OpConstantComposite %3 %9 %8
400fd4e5da5Sopenharmony_ci%14 = OpConstantComposite %3 %8 %9
401fd4e5da5Sopenharmony_ci%15 = OpConstantComposite %4 %13 %14
402fd4e5da5Sopenharmony_ci%16 = OpFunction %1 None %7
403fd4e5da5Sopenharmony_ci%32 = OpFunctionParameter %10
404fd4e5da5Sopenharmony_ci%17 = OpLabel
405fd4e5da5Sopenharmony_ci%18 = OpVariable %5 Function %15
406fd4e5da5Sopenharmony_ci%19 = OpAccessChain %6 %18 %11 %32
407fd4e5da5Sopenharmony_ciOpStore %19 %8
408fd4e5da5Sopenharmony_ciOpReturn
409fd4e5da5Sopenharmony_ciOpFunctionEnd
410fd4e5da5Sopenharmony_ci  )";
411fd4e5da5Sopenharmony_ci
412fd4e5da5Sopenharmony_ci  SinglePassRunAndMatch<ScalarReplacementPass>(text, true);
413fd4e5da5Sopenharmony_ci}
414fd4e5da5Sopenharmony_ci
415fd4e5da5Sopenharmony_ciTEST_F(ScalarReplacementTest, ArrayInitialization) {
416fd4e5da5Sopenharmony_ci  const std::string text = R"(
417fd4e5da5Sopenharmony_ci;
418fd4e5da5Sopenharmony_ci; CHECK: [[float:%\w+]] = OpTypeFloat 32
419fd4e5da5Sopenharmony_ci; CHECK: [[array:%\w+]] = OpTypeArray
420fd4e5da5Sopenharmony_ci; CHECK: [[array_ptr:%\w+]] = OpTypePointer Function [[array]]
421fd4e5da5Sopenharmony_ci; CHECK: [[float_ptr:%\w+]] = OpTypePointer Function [[float]]
422fd4e5da5Sopenharmony_ci; CHECK: [[float0:%\w+]] = OpConstant [[float]] 0
423fd4e5da5Sopenharmony_ci; CHECK: [[float1:%\w+]] = OpConstant [[float]] 1
424fd4e5da5Sopenharmony_ci; CHECK: [[float2:%\w+]] = OpConstant [[float]] 2
425fd4e5da5Sopenharmony_ci; CHECK-NOT: OpVariable [[array_ptr]]
426fd4e5da5Sopenharmony_ci; CHECK: [[var0:%\w+]] = OpVariable [[float_ptr]] Function [[float0]]
427fd4e5da5Sopenharmony_ci; CHECK-NEXT: [[var1:%\w+]] = OpVariable [[float_ptr]] Function [[float1]]
428fd4e5da5Sopenharmony_ci; CHECK-NEXT: [[var2:%\w+]] = OpVariable [[float_ptr]] Function [[float2]]
429fd4e5da5Sopenharmony_ci; CHECK-NOT: OpVariable [[array_ptr]]
430fd4e5da5Sopenharmony_ci;
431fd4e5da5Sopenharmony_ciOpCapability Shader
432fd4e5da5Sopenharmony_ciOpCapability Linkage
433fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
434fd4e5da5Sopenharmony_ciOpName %func "array_init"
435fd4e5da5Sopenharmony_ci%void = OpTypeVoid
436fd4e5da5Sopenharmony_ci%uint = OpTypeInt 32 0
437fd4e5da5Sopenharmony_ci%float = OpTypeFloat 32
438fd4e5da5Sopenharmony_ci%uint_0 = OpConstant %uint 0
439fd4e5da5Sopenharmony_ci%uint_1 = OpConstant %uint 1
440fd4e5da5Sopenharmony_ci%uint_2 = OpConstant %uint 2
441fd4e5da5Sopenharmony_ci%uint_3 = OpConstant %uint 3
442fd4e5da5Sopenharmony_ci%float_array = OpTypeArray %float %uint_3
443fd4e5da5Sopenharmony_ci%array_ptr = OpTypePointer Function %float_array
444fd4e5da5Sopenharmony_ci%float_ptr = OpTypePointer Function %float
445fd4e5da5Sopenharmony_ci%float_0 = OpConstant %float 0
446fd4e5da5Sopenharmony_ci%float_1 = OpConstant %float 1
447fd4e5da5Sopenharmony_ci%float_2 = OpConstant %float 2
448fd4e5da5Sopenharmony_ci%const_array = OpConstantComposite %float_array %float_2 %float_1 %float_0
449fd4e5da5Sopenharmony_ci%func = OpTypeFunction %void
450fd4e5da5Sopenharmony_ci%1 = OpFunction %void None %func
451fd4e5da5Sopenharmony_ci%2 = OpLabel
452fd4e5da5Sopenharmony_ci%3 = OpVariable %array_ptr Function %const_array
453fd4e5da5Sopenharmony_ci%4 = OpInBoundsAccessChain %float_ptr %3 %uint_0
454fd4e5da5Sopenharmony_ciOpStore %4 %float_0
455fd4e5da5Sopenharmony_ci%5 = OpInBoundsAccessChain %float_ptr %3 %uint_1
456fd4e5da5Sopenharmony_ciOpStore %5 %float_0
457fd4e5da5Sopenharmony_ci%6 = OpInBoundsAccessChain %float_ptr %3 %uint_2
458fd4e5da5Sopenharmony_ciOpStore %6 %float_0
459fd4e5da5Sopenharmony_ciOpReturn
460fd4e5da5Sopenharmony_ciOpFunctionEnd
461fd4e5da5Sopenharmony_ci  )";
462fd4e5da5Sopenharmony_ci
463fd4e5da5Sopenharmony_ci  SinglePassRunAndMatch<ScalarReplacementPass>(text, true);
464fd4e5da5Sopenharmony_ci}
465fd4e5da5Sopenharmony_ci
466fd4e5da5Sopenharmony_ciTEST_F(ScalarReplacementTest, NonUniformCompositeInitialization) {
467fd4e5da5Sopenharmony_ci  const std::string text = R"(
468fd4e5da5Sopenharmony_ci;
469fd4e5da5Sopenharmony_ci; CHECK: [[uint:%\w+]] = OpTypeInt 32 0
470fd4e5da5Sopenharmony_ci; CHECK: [[long:%\w+]] = OpTypeInt 64 1
471fd4e5da5Sopenharmony_ci; CHECK: [[dvector:%\w+]] = OpTypeVector
472fd4e5da5Sopenharmony_ci; CHECK: [[vector:%\w+]] = OpTypeVector
473fd4e5da5Sopenharmony_ci; CHECK: [[array:%\w+]] = OpTypeArray
474fd4e5da5Sopenharmony_ci; CHECK: [[matrix:%\w+]] = OpTypeMatrix
475fd4e5da5Sopenharmony_ci; CHECK: [[struct1:%\w+]] = OpTypeStruct [[uint]] [[vector]]
476fd4e5da5Sopenharmony_ci; CHECK: [[struct2:%\w+]] = OpTypeStruct [[struct1]] [[matrix]] [[array]] [[uint]]
477fd4e5da5Sopenharmony_ci; CHECK: [[struct1_ptr:%\w+]] = OpTypePointer Function [[struct1]]
478fd4e5da5Sopenharmony_ci; CHECK: [[matrix_ptr:%\w+]] = OpTypePointer Function [[matrix]]
479fd4e5da5Sopenharmony_ci; CHECK: [[array_ptr:%\w+]] = OpTypePointer Function [[array]]
480fd4e5da5Sopenharmony_ci; CHECK: [[uint_ptr:%\w+]] = OpTypePointer Function [[uint]]
481fd4e5da5Sopenharmony_ci; CHECK: [[struct2_ptr:%\w+]] = OpTypePointer Function [[struct2]]
482fd4e5da5Sopenharmony_ci; CHECK: [[const_array:%\w+]] = OpConstantComposite [[array]]
483fd4e5da5Sopenharmony_ci; CHECK: [[const_matrix:%\w+]] = OpConstantNull [[matrix]]
484fd4e5da5Sopenharmony_ci; CHECK: [[const_struct1:%\w+]] = OpConstantComposite [[struct1]]
485fd4e5da5Sopenharmony_ci; CHECK: OpUndef [[uint]]
486fd4e5da5Sopenharmony_ci; CHECK: OpUndef [[vector]]
487fd4e5da5Sopenharmony_ci; CHECK: OpUndef [[long]]
488fd4e5da5Sopenharmony_ci; CHECK: OpFunction
489fd4e5da5Sopenharmony_ci; CHECK-NOT: OpVariable [[struct2_ptr]] Function
490fd4e5da5Sopenharmony_ci; CHECK: OpVariable [[uint_ptr]] Function
491fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpVariable [[matrix_ptr]] Function [[const_matrix]]
492fd4e5da5Sopenharmony_ci; CHECK-NOT: OpVariable [[struct1_ptr]] Function [[const_struct1]]
493fd4e5da5Sopenharmony_ci; CHECK-NOT: OpVariable [[struct2_ptr]] Function
494fd4e5da5Sopenharmony_ci;
495fd4e5da5Sopenharmony_ciOpCapability Shader
496fd4e5da5Sopenharmony_ciOpCapability Linkage
497fd4e5da5Sopenharmony_ciOpCapability Int64
498fd4e5da5Sopenharmony_ciOpCapability Float64
499fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
500fd4e5da5Sopenharmony_ciOpName %func "non_uniform_composite_init"
501fd4e5da5Sopenharmony_ci%void = OpTypeVoid
502fd4e5da5Sopenharmony_ci%uint = OpTypeInt 32 0
503fd4e5da5Sopenharmony_ci%int64 = OpTypeInt 64 1
504fd4e5da5Sopenharmony_ci%float = OpTypeFloat 32
505fd4e5da5Sopenharmony_ci%double = OpTypeFloat 64
506fd4e5da5Sopenharmony_ci%double2 = OpTypeVector %double 2
507fd4e5da5Sopenharmony_ci%float4 = OpTypeVector %float 4
508fd4e5da5Sopenharmony_ci%int64_0 = OpConstant %int64 0
509fd4e5da5Sopenharmony_ci%int64_1 = OpConstant %int64 1
510fd4e5da5Sopenharmony_ci%int64_2 = OpConstant %int64 2
511fd4e5da5Sopenharmony_ci%int64_3 = OpConstant %int64 3
512fd4e5da5Sopenharmony_ci%int64_array3 = OpTypeArray %int64 %int64_3
513fd4e5da5Sopenharmony_ci%matrix_double2 = OpTypeMatrix %double2 2
514fd4e5da5Sopenharmony_ci%struct1 = OpTypeStruct %uint %float4
515fd4e5da5Sopenharmony_ci%struct2 = OpTypeStruct %struct1 %matrix_double2 %int64_array3 %uint
516fd4e5da5Sopenharmony_ci%struct1_ptr = OpTypePointer Function %struct1
517fd4e5da5Sopenharmony_ci%matrix_double2_ptr = OpTypePointer Function %matrix_double2
518fd4e5da5Sopenharmony_ci%int64_array_ptr = OpTypePointer Function %int64_array3
519fd4e5da5Sopenharmony_ci%uint_ptr = OpTypePointer Function %uint
520fd4e5da5Sopenharmony_ci%struct2_ptr = OpTypePointer Function %struct2
521fd4e5da5Sopenharmony_ci%const_uint = OpConstant %uint 0
522fd4e5da5Sopenharmony_ci%const_int64_array = OpConstantComposite %int64_array3 %int64_0 %int64_1 %int64_2
523fd4e5da5Sopenharmony_ci%const_double2 = OpConstantNull %double2
524fd4e5da5Sopenharmony_ci%const_matrix_double2 = OpConstantNull %matrix_double2
525fd4e5da5Sopenharmony_ci%undef_float4 = OpUndef %float4
526fd4e5da5Sopenharmony_ci%const_struct1 = OpConstantComposite %struct1 %const_uint %undef_float4
527fd4e5da5Sopenharmony_ci%const_struct2 = OpConstantComposite %struct2 %const_struct1 %const_matrix_double2 %const_int64_array %const_uint
528fd4e5da5Sopenharmony_ci%func = OpTypeFunction %void
529fd4e5da5Sopenharmony_ci%1 = OpFunction %void None %func
530fd4e5da5Sopenharmony_ci%2 = OpLabel
531fd4e5da5Sopenharmony_ci%var = OpVariable %struct2_ptr Function %const_struct2
532fd4e5da5Sopenharmony_ci%3 = OpAccessChain %struct1_ptr %var %int64_0
533fd4e5da5Sopenharmony_ciOpStore %3 %const_struct1
534fd4e5da5Sopenharmony_ci%4 = OpAccessChain %matrix_double2_ptr %var %int64_1
535fd4e5da5Sopenharmony_ciOpStore %4 %const_matrix_double2
536fd4e5da5Sopenharmony_ci%5 = OpAccessChain %int64_array_ptr %var %int64_2
537fd4e5da5Sopenharmony_ciOpStore %5 %const_int64_array
538fd4e5da5Sopenharmony_ci%6 = OpAccessChain %uint_ptr %var %int64_3
539fd4e5da5Sopenharmony_ciOpStore %6 %const_uint
540fd4e5da5Sopenharmony_ciOpReturn
541fd4e5da5Sopenharmony_ciOpFunctionEnd
542fd4e5da5Sopenharmony_ci  )";
543fd4e5da5Sopenharmony_ci
544fd4e5da5Sopenharmony_ci  SinglePassRunAndMatch<ScalarReplacementPass>(text, true);
545fd4e5da5Sopenharmony_ci}
546fd4e5da5Sopenharmony_ci
547fd4e5da5Sopenharmony_ciTEST_F(ScalarReplacementTest, ElideUncombinedAccessChains) {
548fd4e5da5Sopenharmony_ci  const std::string text = R"(
549fd4e5da5Sopenharmony_ci;
550fd4e5da5Sopenharmony_ci; CHECK: [[uint:%\w+]] = OpTypeInt 32 0
551fd4e5da5Sopenharmony_ci; CHECK: [[uint_ptr:%\w+]] = OpTypePointer Function [[uint]]
552fd4e5da5Sopenharmony_ci; CHECK: [[const:%\w+]] = OpConstant [[uint]] 0
553fd4e5da5Sopenharmony_ci; CHECK: [[var:%\w+]] = OpVariable [[uint_ptr]] Function
554fd4e5da5Sopenharmony_ci; CHECK-NOT: OpAccessChain
555fd4e5da5Sopenharmony_ci; CHECK: OpStore [[var]] [[const]]
556fd4e5da5Sopenharmony_ci;
557fd4e5da5Sopenharmony_ciOpCapability Shader
558fd4e5da5Sopenharmony_ciOpCapability Linkage
559fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
560fd4e5da5Sopenharmony_ciOpName %func "elide_uncombined_access_chains"
561fd4e5da5Sopenharmony_ci%void = OpTypeVoid
562fd4e5da5Sopenharmony_ci%uint = OpTypeInt 32 0
563fd4e5da5Sopenharmony_ci%struct1 = OpTypeStruct %uint
564fd4e5da5Sopenharmony_ci%struct2 = OpTypeStruct %struct1
565fd4e5da5Sopenharmony_ci%uint_ptr = OpTypePointer Function %uint
566fd4e5da5Sopenharmony_ci%struct1_ptr = OpTypePointer Function %struct1
567fd4e5da5Sopenharmony_ci%struct2_ptr = OpTypePointer Function %struct2
568fd4e5da5Sopenharmony_ci%uint_0 = OpConstant %uint 0
569fd4e5da5Sopenharmony_ci%func = OpTypeFunction %void
570fd4e5da5Sopenharmony_ci%1 = OpFunction %void None %func
571fd4e5da5Sopenharmony_ci%2 = OpLabel
572fd4e5da5Sopenharmony_ci%var = OpVariable %struct2_ptr Function
573fd4e5da5Sopenharmony_ci%3 = OpAccessChain %struct1_ptr %var %uint_0
574fd4e5da5Sopenharmony_ci%4 = OpAccessChain %uint_ptr %3 %uint_0
575fd4e5da5Sopenharmony_ciOpStore %4 %uint_0
576fd4e5da5Sopenharmony_ciOpReturn
577fd4e5da5Sopenharmony_ciOpFunctionEnd
578fd4e5da5Sopenharmony_ci  )";
579fd4e5da5Sopenharmony_ci
580fd4e5da5Sopenharmony_ci  SinglePassRunAndMatch<ScalarReplacementPass>(text, true);
581fd4e5da5Sopenharmony_ci}
582fd4e5da5Sopenharmony_ci
583fd4e5da5Sopenharmony_ciTEST_F(ScalarReplacementTest, ElideSingleUncombinedAccessChains) {
584fd4e5da5Sopenharmony_ci  const std::string text = R"(
585fd4e5da5Sopenharmony_ci;
586fd4e5da5Sopenharmony_ci; CHECK: [[uint:%\w+]] = OpTypeInt 32 0
587fd4e5da5Sopenharmony_ci; CHECK: [[array:%\w+]] = OpTypeArray [[uint]]
588fd4e5da5Sopenharmony_ci; CHECK: [[array_ptr:%\w+]] = OpTypePointer Function [[array]]
589fd4e5da5Sopenharmony_ci; CHECK: [[const:%\w+]] = OpConstant [[uint]] 0
590fd4e5da5Sopenharmony_ci; CHECK: [[param:%\w+]] = OpFunctionParameter [[uint]]
591fd4e5da5Sopenharmony_ci; CHECK: [[var:%\w+]] = OpVariable [[array_ptr]] Function
592fd4e5da5Sopenharmony_ci; CHECK: [[access:%\w+]] = OpAccessChain {{.*}} [[var]] [[param]]
593fd4e5da5Sopenharmony_ci; CHECK: OpStore [[access]] [[const]]
594fd4e5da5Sopenharmony_ci;
595fd4e5da5Sopenharmony_ciOpCapability Shader
596fd4e5da5Sopenharmony_ciOpCapability Linkage
597fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
598fd4e5da5Sopenharmony_ciOpName %func "elide_single_uncombined_access_chains"
599fd4e5da5Sopenharmony_ci%void = OpTypeVoid
600fd4e5da5Sopenharmony_ci%uint = OpTypeInt 32 0
601fd4e5da5Sopenharmony_ci%uint_1 = OpConstant %uint 1
602fd4e5da5Sopenharmony_ci%array = OpTypeArray %uint %uint_1
603fd4e5da5Sopenharmony_ci%struct2 = OpTypeStruct %array
604fd4e5da5Sopenharmony_ci%uint_ptr = OpTypePointer Function %uint
605fd4e5da5Sopenharmony_ci%array_ptr = OpTypePointer Function %array
606fd4e5da5Sopenharmony_ci%struct2_ptr = OpTypePointer Function %struct2
607fd4e5da5Sopenharmony_ci%uint_0 = OpConstant %uint 0
608fd4e5da5Sopenharmony_ci%func = OpTypeFunction %void %uint
609fd4e5da5Sopenharmony_ci%1 = OpFunction %void None %func
610fd4e5da5Sopenharmony_ci%param = OpFunctionParameter %uint
611fd4e5da5Sopenharmony_ci%2 = OpLabel
612fd4e5da5Sopenharmony_ci%var = OpVariable %struct2_ptr Function
613fd4e5da5Sopenharmony_ci%3 = OpAccessChain %array_ptr %var %uint_0
614fd4e5da5Sopenharmony_ci%4 = OpAccessChain %uint_ptr %3 %param
615fd4e5da5Sopenharmony_ciOpStore %4 %uint_0
616fd4e5da5Sopenharmony_ciOpReturn
617fd4e5da5Sopenharmony_ciOpFunctionEnd
618fd4e5da5Sopenharmony_ci  )";
619fd4e5da5Sopenharmony_ci
620fd4e5da5Sopenharmony_ci  SinglePassRunAndMatch<ScalarReplacementPass>(text, true);
621fd4e5da5Sopenharmony_ci}
622fd4e5da5Sopenharmony_ci
623fd4e5da5Sopenharmony_ciTEST_F(ScalarReplacementTest, ReplaceWholeLoad) {
624fd4e5da5Sopenharmony_ci  const std::string text = R"(
625fd4e5da5Sopenharmony_ci;
626fd4e5da5Sopenharmony_ci; CHECK: [[uint:%\w+]] = OpTypeInt 32 0
627fd4e5da5Sopenharmony_ci; CHECK: [[struct1:%\w+]] = OpTypeStruct [[uint]] [[uint]]
628fd4e5da5Sopenharmony_ci; CHECK: [[uint_ptr:%\w+]] = OpTypePointer Function [[uint]]
629fd4e5da5Sopenharmony_ci; CHECK: [[const:%\w+]] = OpConstant [[uint]] 0
630fd4e5da5Sopenharmony_ci; CHECK: [[var1:%\w+]] = OpVariable [[uint_ptr]] Function
631fd4e5da5Sopenharmony_ci; CHECK: [[var0:%\w+]] = OpVariable [[uint_ptr]] Function
632fd4e5da5Sopenharmony_ci; CHECK: [[l1:%\w+]] = OpLoad [[uint]] [[var1]]
633fd4e5da5Sopenharmony_ci; CHECK: [[l0:%\w+]] = OpLoad [[uint]] [[var0]]
634fd4e5da5Sopenharmony_ci; CHECK: OpCompositeConstruct [[struct1]] [[l0]] [[l1]]
635fd4e5da5Sopenharmony_ci;
636fd4e5da5Sopenharmony_ciOpCapability Shader
637fd4e5da5Sopenharmony_ciOpCapability Linkage
638fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
639fd4e5da5Sopenharmony_ciOpName %func "replace_whole_load"
640fd4e5da5Sopenharmony_ci%void = OpTypeVoid
641fd4e5da5Sopenharmony_ci%uint = OpTypeInt 32 0
642fd4e5da5Sopenharmony_ci%struct1 = OpTypeStruct %uint %uint
643fd4e5da5Sopenharmony_ci%uint_ptr = OpTypePointer Function %uint
644fd4e5da5Sopenharmony_ci%struct1_ptr = OpTypePointer Function %struct1
645fd4e5da5Sopenharmony_ci%uint_0 = OpConstant %uint 0
646fd4e5da5Sopenharmony_ci%uint_1 = OpConstant %uint 1
647fd4e5da5Sopenharmony_ci%func = OpTypeFunction %void
648fd4e5da5Sopenharmony_ci%1 = OpFunction %void None %func
649fd4e5da5Sopenharmony_ci%2 = OpLabel
650fd4e5da5Sopenharmony_ci%var = OpVariable %struct1_ptr Function
651fd4e5da5Sopenharmony_ci%load = OpLoad %struct1 %var
652fd4e5da5Sopenharmony_ci%3 = OpAccessChain %uint_ptr %var %uint_0
653fd4e5da5Sopenharmony_ciOpStore %3 %uint_0
654fd4e5da5Sopenharmony_ci%4 = OpAccessChain %uint_ptr %var %uint_1
655fd4e5da5Sopenharmony_ciOpStore %4 %uint_0
656fd4e5da5Sopenharmony_ciOpReturn
657fd4e5da5Sopenharmony_ciOpFunctionEnd
658fd4e5da5Sopenharmony_ci  )";
659fd4e5da5Sopenharmony_ci
660fd4e5da5Sopenharmony_ci  SinglePassRunAndMatch<ScalarReplacementPass>(text, true);
661fd4e5da5Sopenharmony_ci}
662fd4e5da5Sopenharmony_ci
663fd4e5da5Sopenharmony_ciTEST_F(ScalarReplacementTest, ReplaceWholeLoadCopyMemoryAccess) {
664fd4e5da5Sopenharmony_ci  const std::string text = R"(
665fd4e5da5Sopenharmony_ci;
666fd4e5da5Sopenharmony_ci; CHECK: [[uint:%\w+]] = OpTypeInt 32 0
667fd4e5da5Sopenharmony_ci; CHECK: [[struct1:%\w+]] = OpTypeStruct [[uint]] [[uint]]
668fd4e5da5Sopenharmony_ci; CHECK: [[uint_ptr:%\w+]] = OpTypePointer Function [[uint]]
669fd4e5da5Sopenharmony_ci; CHECK: [[undef:%\w+]] = OpUndef [[uint]]
670fd4e5da5Sopenharmony_ci; CHECK: [[var0:%\w+]] = OpVariable [[uint_ptr]] Function
671fd4e5da5Sopenharmony_ci; CHECK: [[l0:%\w+]] = OpLoad [[uint]] [[var0]] Nontemporal
672fd4e5da5Sopenharmony_ci; CHECK: OpCompositeConstruct [[struct1]] [[l0]] [[undef]]
673fd4e5da5Sopenharmony_ci;
674fd4e5da5Sopenharmony_ciOpCapability Shader
675fd4e5da5Sopenharmony_ciOpCapability Linkage
676fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
677fd4e5da5Sopenharmony_ciOpName %func "replace_whole_load_copy_memory_access"
678fd4e5da5Sopenharmony_ci%void = OpTypeVoid
679fd4e5da5Sopenharmony_ci%uint = OpTypeInt 32 0
680fd4e5da5Sopenharmony_ci%struct1 = OpTypeStruct %uint %uint
681fd4e5da5Sopenharmony_ci%uint_ptr = OpTypePointer Function %uint
682fd4e5da5Sopenharmony_ci%struct1_ptr = OpTypePointer Function %struct1
683fd4e5da5Sopenharmony_ci%uint_0 = OpConstant %uint 0
684fd4e5da5Sopenharmony_ci%func = OpTypeFunction %void
685fd4e5da5Sopenharmony_ci%1 = OpFunction %void None %func
686fd4e5da5Sopenharmony_ci%2 = OpLabel
687fd4e5da5Sopenharmony_ci%var = OpVariable %struct1_ptr Function
688fd4e5da5Sopenharmony_ci%load = OpLoad %struct1 %var Nontemporal
689fd4e5da5Sopenharmony_ci%3 = OpAccessChain %uint_ptr %var %uint_0
690fd4e5da5Sopenharmony_ciOpStore %3 %uint_0
691fd4e5da5Sopenharmony_ciOpReturn
692fd4e5da5Sopenharmony_ciOpFunctionEnd
693fd4e5da5Sopenharmony_ci  )";
694fd4e5da5Sopenharmony_ci
695fd4e5da5Sopenharmony_ci  SinglePassRunAndMatch<ScalarReplacementPass>(text, true);
696fd4e5da5Sopenharmony_ci}
697fd4e5da5Sopenharmony_ci
698fd4e5da5Sopenharmony_ciTEST_F(ScalarReplacementTest, ReplaceWholeStore) {
699fd4e5da5Sopenharmony_ci  const std::string text = R"(
700fd4e5da5Sopenharmony_ci;
701fd4e5da5Sopenharmony_ci; CHECK: [[uint:%\w+]] = OpTypeInt 32 0
702fd4e5da5Sopenharmony_ci; CHECK: [[struct1:%\w+]] = OpTypeStruct [[uint]] [[uint]]
703fd4e5da5Sopenharmony_ci; CHECK: [[uint_ptr:%\w+]] = OpTypePointer Function [[uint]]
704fd4e5da5Sopenharmony_ci; CHECK: [[const:%\w+]] = OpConstant [[uint]] 0
705fd4e5da5Sopenharmony_ci; CHECK: [[const_struct:%\w+]] = OpConstantComposite [[struct1]] [[const]] [[const]]
706fd4e5da5Sopenharmony_ci; CHECK: [[var0:%\w+]] = OpVariable [[uint_ptr]] Function
707fd4e5da5Sopenharmony_ci; CHECK: [[ex0:%\w+]] = OpCompositeExtract [[uint]] [[const_struct]] 0
708fd4e5da5Sopenharmony_ci; CHECK: OpStore [[var0]] [[ex0]]
709fd4e5da5Sopenharmony_ci;
710fd4e5da5Sopenharmony_ciOpCapability Shader
711fd4e5da5Sopenharmony_ciOpCapability Linkage
712fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
713fd4e5da5Sopenharmony_ciOpName %func "replace_whole_store"
714fd4e5da5Sopenharmony_ci%void = OpTypeVoid
715fd4e5da5Sopenharmony_ci%uint = OpTypeInt 32 0
716fd4e5da5Sopenharmony_ci%struct1 = OpTypeStruct %uint %uint
717fd4e5da5Sopenharmony_ci%uint_ptr = OpTypePointer Function %uint
718fd4e5da5Sopenharmony_ci%struct1_ptr = OpTypePointer Function %struct1
719fd4e5da5Sopenharmony_ci%uint_0 = OpConstant %uint 0
720fd4e5da5Sopenharmony_ci%const_struct = OpConstantComposite %struct1 %uint_0 %uint_0
721fd4e5da5Sopenharmony_ci%func = OpTypeFunction %void
722fd4e5da5Sopenharmony_ci%1 = OpFunction %void None %func
723fd4e5da5Sopenharmony_ci%2 = OpLabel
724fd4e5da5Sopenharmony_ci%var = OpVariable %struct1_ptr Function
725fd4e5da5Sopenharmony_ciOpStore %var %const_struct
726fd4e5da5Sopenharmony_ci%3 = OpAccessChain %uint_ptr %var %uint_0
727fd4e5da5Sopenharmony_ci%4 = OpLoad %uint %3
728fd4e5da5Sopenharmony_ciOpReturn
729fd4e5da5Sopenharmony_ciOpFunctionEnd
730fd4e5da5Sopenharmony_ci  )";
731fd4e5da5Sopenharmony_ci
732fd4e5da5Sopenharmony_ci  SinglePassRunAndMatch<ScalarReplacementPass>(text, true);
733fd4e5da5Sopenharmony_ci}
734fd4e5da5Sopenharmony_ci
735fd4e5da5Sopenharmony_ciTEST_F(ScalarReplacementTest, ReplaceWholeStoreCopyMemoryAccess) {
736fd4e5da5Sopenharmony_ci  const std::string text = R"(
737fd4e5da5Sopenharmony_ci;
738fd4e5da5Sopenharmony_ci; CHECK: [[uint:%\w+]] = OpTypeInt 32 0
739fd4e5da5Sopenharmony_ci; CHECK: [[struct1:%\w+]] = OpTypeStruct [[uint]] [[uint]]
740fd4e5da5Sopenharmony_ci; CHECK: [[uint_ptr:%\w+]] = OpTypePointer Function [[uint]]
741fd4e5da5Sopenharmony_ci; CHECK: [[const:%\w+]] = OpConstant [[uint]] 0
742fd4e5da5Sopenharmony_ci; CHECK: [[const_struct:%\w+]] = OpConstantComposite [[struct1]] [[const]] [[const]]
743fd4e5da5Sopenharmony_ci; CHECK: [[var0:%\w+]] = OpVariable [[uint_ptr]] Function
744fd4e5da5Sopenharmony_ci; CHECK-NOT: OpVariable
745fd4e5da5Sopenharmony_ci; CHECK: [[ex0:%\w+]] = OpCompositeExtract [[uint]] [[const_struct]] 0
746fd4e5da5Sopenharmony_ci; CHECK: OpStore [[var0]] [[ex0]] Aligned 4
747fd4e5da5Sopenharmony_ci;
748fd4e5da5Sopenharmony_ciOpCapability Shader
749fd4e5da5Sopenharmony_ciOpCapability Linkage
750fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
751fd4e5da5Sopenharmony_ciOpName %func "replace_whole_store_copy_memory_access"
752fd4e5da5Sopenharmony_ci%void = OpTypeVoid
753fd4e5da5Sopenharmony_ci%uint = OpTypeInt 32 0
754fd4e5da5Sopenharmony_ci%struct1 = OpTypeStruct %uint %uint
755fd4e5da5Sopenharmony_ci%uint_ptr = OpTypePointer Function %uint
756fd4e5da5Sopenharmony_ci%struct1_ptr = OpTypePointer Function %struct1
757fd4e5da5Sopenharmony_ci%uint_0 = OpConstant %uint 0
758fd4e5da5Sopenharmony_ci%const_struct = OpConstantComposite %struct1 %uint_0 %uint_0
759fd4e5da5Sopenharmony_ci%func = OpTypeFunction %void
760fd4e5da5Sopenharmony_ci%1 = OpFunction %void None %func
761fd4e5da5Sopenharmony_ci%2 = OpLabel
762fd4e5da5Sopenharmony_ci%var = OpVariable %struct1_ptr Function
763fd4e5da5Sopenharmony_ciOpStore %var %const_struct Aligned 4
764fd4e5da5Sopenharmony_ci%3 = OpAccessChain %uint_ptr %var %uint_0
765fd4e5da5Sopenharmony_ci%4 = OpLoad %uint %3
766fd4e5da5Sopenharmony_ciOpReturn
767fd4e5da5Sopenharmony_ciOpFunctionEnd
768fd4e5da5Sopenharmony_ci  )";
769fd4e5da5Sopenharmony_ci
770fd4e5da5Sopenharmony_ci  SinglePassRunAndMatch<ScalarReplacementPass>(text, true);
771fd4e5da5Sopenharmony_ci}
772fd4e5da5Sopenharmony_ci
773fd4e5da5Sopenharmony_ciTEST_F(ScalarReplacementTest, DontTouchVolatileLoad) {
774fd4e5da5Sopenharmony_ci  const std::string text = R"(
775fd4e5da5Sopenharmony_ci;
776fd4e5da5Sopenharmony_ci; CHECK: [[struct:%\w+]] = OpTypeStruct
777fd4e5da5Sopenharmony_ci; CHECK: [[struct_ptr:%\w+]] = OpTypePointer Function [[struct]]
778fd4e5da5Sopenharmony_ci; CHECK: OpLabel
779fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpVariable [[struct_ptr]]
780fd4e5da5Sopenharmony_ci; CHECK-NOT: OpVariable
781fd4e5da5Sopenharmony_ci;
782fd4e5da5Sopenharmony_ciOpCapability Shader
783fd4e5da5Sopenharmony_ciOpCapability Linkage
784fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
785fd4e5da5Sopenharmony_ciOpName %func "dont_touch_volatile_load"
786fd4e5da5Sopenharmony_ci%void = OpTypeVoid
787fd4e5da5Sopenharmony_ci%uint = OpTypeInt 32 0
788fd4e5da5Sopenharmony_ci%struct1 = OpTypeStruct %uint
789fd4e5da5Sopenharmony_ci%uint_ptr = OpTypePointer Function %uint
790fd4e5da5Sopenharmony_ci%struct1_ptr = OpTypePointer Function %struct1
791fd4e5da5Sopenharmony_ci%uint_0 = OpConstant %uint 0
792fd4e5da5Sopenharmony_ci%func = OpTypeFunction %void
793fd4e5da5Sopenharmony_ci%1 = OpFunction %void None %func
794fd4e5da5Sopenharmony_ci%2 = OpLabel
795fd4e5da5Sopenharmony_ci%var = OpVariable %struct1_ptr Function
796fd4e5da5Sopenharmony_ci%3 = OpAccessChain %uint_ptr %var %uint_0
797fd4e5da5Sopenharmony_ci%4 = OpLoad %uint %3 Volatile
798fd4e5da5Sopenharmony_ciOpReturn
799fd4e5da5Sopenharmony_ciOpFunctionEnd
800fd4e5da5Sopenharmony_ci  )";
801fd4e5da5Sopenharmony_ci
802fd4e5da5Sopenharmony_ci  SinglePassRunAndMatch<ScalarReplacementPass>(text, true);
803fd4e5da5Sopenharmony_ci}
804fd4e5da5Sopenharmony_ci
805fd4e5da5Sopenharmony_ciTEST_F(ScalarReplacementTest, DontTouchVolatileStore) {
806fd4e5da5Sopenharmony_ci  const std::string text = R"(
807fd4e5da5Sopenharmony_ci;
808fd4e5da5Sopenharmony_ci; CHECK: [[struct:%\w+]] = OpTypeStruct
809fd4e5da5Sopenharmony_ci; CHECK: [[struct_ptr:%\w+]] = OpTypePointer Function [[struct]]
810fd4e5da5Sopenharmony_ci; CHECK: OpLabel
811fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpVariable [[struct_ptr]]
812fd4e5da5Sopenharmony_ci; CHECK-NOT: OpVariable
813fd4e5da5Sopenharmony_ci;
814fd4e5da5Sopenharmony_ciOpCapability Shader
815fd4e5da5Sopenharmony_ciOpCapability Linkage
816fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
817fd4e5da5Sopenharmony_ciOpName %func "dont_touch_volatile_store"
818fd4e5da5Sopenharmony_ci%void = OpTypeVoid
819fd4e5da5Sopenharmony_ci%uint = OpTypeInt 32 0
820fd4e5da5Sopenharmony_ci%struct1 = OpTypeStruct %uint
821fd4e5da5Sopenharmony_ci%uint_ptr = OpTypePointer Function %uint
822fd4e5da5Sopenharmony_ci%struct1_ptr = OpTypePointer Function %struct1
823fd4e5da5Sopenharmony_ci%uint_0 = OpConstant %uint 0
824fd4e5da5Sopenharmony_ci%func = OpTypeFunction %void
825fd4e5da5Sopenharmony_ci%1 = OpFunction %void None %func
826fd4e5da5Sopenharmony_ci%2 = OpLabel
827fd4e5da5Sopenharmony_ci%var = OpVariable %struct1_ptr Function
828fd4e5da5Sopenharmony_ci%3 = OpAccessChain %uint_ptr %var %uint_0
829fd4e5da5Sopenharmony_ciOpStore %3 %uint_0 Volatile
830fd4e5da5Sopenharmony_ciOpReturn
831fd4e5da5Sopenharmony_ciOpFunctionEnd
832fd4e5da5Sopenharmony_ci  )";
833fd4e5da5Sopenharmony_ci
834fd4e5da5Sopenharmony_ci  SinglePassRunAndMatch<ScalarReplacementPass>(text, true);
835fd4e5da5Sopenharmony_ci}
836fd4e5da5Sopenharmony_ci
837fd4e5da5Sopenharmony_ciTEST_F(ScalarReplacementTest, DontTouchSpecNonFunctionVariable) {
838fd4e5da5Sopenharmony_ci  const std::string text = R"(
839fd4e5da5Sopenharmony_ci;
840fd4e5da5Sopenharmony_ci; CHECK: [[struct:%\w+]] = OpTypeStruct
841fd4e5da5Sopenharmony_ci; CHECK: [[struct_ptr:%\w+]] = OpTypePointer Uniform [[struct]]
842fd4e5da5Sopenharmony_ci; CHECK: OpConstant
843fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpVariable [[struct_ptr]]
844fd4e5da5Sopenharmony_ci; CHECK-NOT: OpVariable
845fd4e5da5Sopenharmony_ci;
846fd4e5da5Sopenharmony_ciOpCapability Shader
847fd4e5da5Sopenharmony_ciOpCapability Linkage
848fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
849fd4e5da5Sopenharmony_ciOpName %func "dont_touch_spec_constant_access_chain"
850fd4e5da5Sopenharmony_ci%void = OpTypeVoid
851fd4e5da5Sopenharmony_ci%uint = OpTypeInt 32 0
852fd4e5da5Sopenharmony_ci%struct1 = OpTypeStruct %uint
853fd4e5da5Sopenharmony_ci%uint_ptr = OpTypePointer Uniform %uint
854fd4e5da5Sopenharmony_ci%struct1_ptr = OpTypePointer Uniform %struct1
855fd4e5da5Sopenharmony_ci%uint_0 = OpConstant %uint 0
856fd4e5da5Sopenharmony_ci%var = OpVariable %struct1_ptr Uniform
857fd4e5da5Sopenharmony_ci%func = OpTypeFunction %void
858fd4e5da5Sopenharmony_ci%1 = OpFunction %void None %func
859fd4e5da5Sopenharmony_ci%2 = OpLabel
860fd4e5da5Sopenharmony_ci%3 = OpAccessChain %uint_ptr %var %uint_0
861fd4e5da5Sopenharmony_ciOpStore %3 %uint_0 Volatile
862fd4e5da5Sopenharmony_ciOpReturn
863fd4e5da5Sopenharmony_ciOpFunctionEnd
864fd4e5da5Sopenharmony_ci  )";
865fd4e5da5Sopenharmony_ci
866fd4e5da5Sopenharmony_ci  SinglePassRunAndMatch<ScalarReplacementPass>(text, true);
867fd4e5da5Sopenharmony_ci}
868fd4e5da5Sopenharmony_ci
869fd4e5da5Sopenharmony_ciTEST_F(ScalarReplacementTest, DontTouchSpecConstantAccessChain) {
870fd4e5da5Sopenharmony_ci  const std::string text = R"(
871fd4e5da5Sopenharmony_ci;
872fd4e5da5Sopenharmony_ci; CHECK: [[array:%\w+]] = OpTypeArray
873fd4e5da5Sopenharmony_ci; CHECK: [[array_ptr:%\w+]] = OpTypePointer Function [[array]]
874fd4e5da5Sopenharmony_ci; CHECK: OpLabel
875fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpVariable [[array_ptr]]
876fd4e5da5Sopenharmony_ci; CHECK-NOT: OpVariable
877fd4e5da5Sopenharmony_ci;
878fd4e5da5Sopenharmony_ciOpCapability Shader
879fd4e5da5Sopenharmony_ciOpCapability Linkage
880fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
881fd4e5da5Sopenharmony_ciOpName %func "dont_touch_spec_constant_access_chain"
882fd4e5da5Sopenharmony_ci%void = OpTypeVoid
883fd4e5da5Sopenharmony_ci%uint = OpTypeInt 32 0
884fd4e5da5Sopenharmony_ci%uint_1 = OpConstant %uint 1
885fd4e5da5Sopenharmony_ci%array = OpTypeArray %uint %uint_1
886fd4e5da5Sopenharmony_ci%uint_ptr = OpTypePointer Function %uint
887fd4e5da5Sopenharmony_ci%array_ptr = OpTypePointer Function %array
888fd4e5da5Sopenharmony_ci%uint_0 = OpConstant %uint 0
889fd4e5da5Sopenharmony_ci%spec_const = OpSpecConstant %uint 0
890fd4e5da5Sopenharmony_ci%func = OpTypeFunction %void
891fd4e5da5Sopenharmony_ci%1 = OpFunction %void None %func
892fd4e5da5Sopenharmony_ci%2 = OpLabel
893fd4e5da5Sopenharmony_ci%var = OpVariable %array_ptr Function
894fd4e5da5Sopenharmony_ci%3 = OpAccessChain %uint_ptr %var %spec_const
895fd4e5da5Sopenharmony_ciOpStore %3 %uint_0 Volatile
896fd4e5da5Sopenharmony_ciOpReturn
897fd4e5da5Sopenharmony_ciOpFunctionEnd
898fd4e5da5Sopenharmony_ci  )";
899fd4e5da5Sopenharmony_ci
900fd4e5da5Sopenharmony_ci  SinglePassRunAndMatch<ScalarReplacementPass>(text, true);
901fd4e5da5Sopenharmony_ci}
902fd4e5da5Sopenharmony_ci
903fd4e5da5Sopenharmony_ciTEST_F(ScalarReplacementTest, NoPartialAccesses) {
904fd4e5da5Sopenharmony_ci  const std::string text = R"(
905fd4e5da5Sopenharmony_ci;
906fd4e5da5Sopenharmony_ci; CHECK: [[uint:%\w+]] = OpTypeInt 32 0
907fd4e5da5Sopenharmony_ci; CHECK: [[uint_ptr:%\w+]] = OpTypePointer Function [[uint]]
908fd4e5da5Sopenharmony_ci; CHECK: OpLabel
909fd4e5da5Sopenharmony_ci; CHECK-NOT: OpVariable
910fd4e5da5Sopenharmony_ci;
911fd4e5da5Sopenharmony_ciOpCapability Shader
912fd4e5da5Sopenharmony_ciOpCapability Linkage
913fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
914fd4e5da5Sopenharmony_ciOpName %func "no_partial_accesses"
915fd4e5da5Sopenharmony_ci%void = OpTypeVoid
916fd4e5da5Sopenharmony_ci%uint = OpTypeInt 32 0
917fd4e5da5Sopenharmony_ci%struct1 = OpTypeStruct %uint
918fd4e5da5Sopenharmony_ci%uint_ptr = OpTypePointer Function %uint
919fd4e5da5Sopenharmony_ci%struct1_ptr = OpTypePointer Function %struct1
920fd4e5da5Sopenharmony_ci%const = OpConstantNull %struct1
921fd4e5da5Sopenharmony_ci%func = OpTypeFunction %void
922fd4e5da5Sopenharmony_ci%1 = OpFunction %void None %func
923fd4e5da5Sopenharmony_ci%2 = OpLabel
924fd4e5da5Sopenharmony_ci%var = OpVariable %struct1_ptr Function
925fd4e5da5Sopenharmony_ciOpStore %var %const
926fd4e5da5Sopenharmony_ciOpReturn
927fd4e5da5Sopenharmony_ciOpFunctionEnd
928fd4e5da5Sopenharmony_ci  )";
929fd4e5da5Sopenharmony_ci
930fd4e5da5Sopenharmony_ci  SinglePassRunAndMatch<ScalarReplacementPass>(text, true);
931fd4e5da5Sopenharmony_ci}
932fd4e5da5Sopenharmony_ci
933fd4e5da5Sopenharmony_ciTEST_F(ScalarReplacementTest, DontTouchPtrAccessChain) {
934fd4e5da5Sopenharmony_ci  const std::string text = R"(
935fd4e5da5Sopenharmony_ci;
936fd4e5da5Sopenharmony_ci; CHECK: [[struct:%\w+]] = OpTypeStruct
937fd4e5da5Sopenharmony_ci; CHECK: [[struct_ptr:%\w+]] = OpTypePointer Function [[struct]]
938fd4e5da5Sopenharmony_ci; CHECK: OpLabel
939fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpVariable [[struct_ptr]]
940fd4e5da5Sopenharmony_ci; CHECK-NOT: OpVariable
941fd4e5da5Sopenharmony_ci;
942fd4e5da5Sopenharmony_ciOpCapability Shader
943fd4e5da5Sopenharmony_ciOpCapability Linkage
944fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
945fd4e5da5Sopenharmony_ciOpName %func "dont_touch_ptr_access_chain"
946fd4e5da5Sopenharmony_ci%void = OpTypeVoid
947fd4e5da5Sopenharmony_ci%uint = OpTypeInt 32 0
948fd4e5da5Sopenharmony_ci%struct1 = OpTypeStruct %uint
949fd4e5da5Sopenharmony_ci%uint_ptr = OpTypePointer Function %uint
950fd4e5da5Sopenharmony_ci%struct1_ptr = OpTypePointer Function %struct1
951fd4e5da5Sopenharmony_ci%uint_0 = OpConstant %uint 0
952fd4e5da5Sopenharmony_ci%func = OpTypeFunction %void
953fd4e5da5Sopenharmony_ci%1 = OpFunction %void None %func
954fd4e5da5Sopenharmony_ci%2 = OpLabel
955fd4e5da5Sopenharmony_ci%var = OpVariable %struct1_ptr Function
956fd4e5da5Sopenharmony_ci%3 = OpPtrAccessChain %uint_ptr %var %uint_0 %uint_0
957fd4e5da5Sopenharmony_ciOpStore %3 %uint_0
958fd4e5da5Sopenharmony_ci%4 = OpAccessChain %uint_ptr %var %uint_0
959fd4e5da5Sopenharmony_ciOpStore %4 %uint_0
960fd4e5da5Sopenharmony_ciOpReturn
961fd4e5da5Sopenharmony_ciOpFunctionEnd
962fd4e5da5Sopenharmony_ci  )";
963fd4e5da5Sopenharmony_ci
964fd4e5da5Sopenharmony_ci  SinglePassRunAndMatch<ScalarReplacementPass>(text, false);
965fd4e5da5Sopenharmony_ci}
966fd4e5da5Sopenharmony_ci
967fd4e5da5Sopenharmony_ciTEST_F(ScalarReplacementTest, DontTouchInBoundsPtrAccessChain) {
968fd4e5da5Sopenharmony_ci  const std::string text = R"(
969fd4e5da5Sopenharmony_ci;
970fd4e5da5Sopenharmony_ci; CHECK: [[struct:%\w+]] = OpTypeStruct
971fd4e5da5Sopenharmony_ci; CHECK: [[struct_ptr:%\w+]] = OpTypePointer Function [[struct]]
972fd4e5da5Sopenharmony_ci; CHECK: OpLabel
973fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpVariable [[struct_ptr]]
974fd4e5da5Sopenharmony_ci; CHECK-NOT: OpVariable
975fd4e5da5Sopenharmony_ci;
976fd4e5da5Sopenharmony_ciOpCapability Shader
977fd4e5da5Sopenharmony_ciOpCapability Linkage
978fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
979fd4e5da5Sopenharmony_ciOpName %func "dont_touch_in_bounds_ptr_access_chain"
980fd4e5da5Sopenharmony_ci%void = OpTypeVoid
981fd4e5da5Sopenharmony_ci%uint = OpTypeInt 32 0
982fd4e5da5Sopenharmony_ci%struct1 = OpTypeStruct %uint
983fd4e5da5Sopenharmony_ci%uint_ptr = OpTypePointer Function %uint
984fd4e5da5Sopenharmony_ci%struct1_ptr = OpTypePointer Function %struct1
985fd4e5da5Sopenharmony_ci%uint_0 = OpConstant %uint 0
986fd4e5da5Sopenharmony_ci%func = OpTypeFunction %void
987fd4e5da5Sopenharmony_ci%1 = OpFunction %void None %func
988fd4e5da5Sopenharmony_ci%2 = OpLabel
989fd4e5da5Sopenharmony_ci%var = OpVariable %struct1_ptr Function
990fd4e5da5Sopenharmony_ci%3 = OpInBoundsPtrAccessChain %uint_ptr %var %uint_0 %uint_0
991fd4e5da5Sopenharmony_ciOpStore %3 %uint_0
992fd4e5da5Sopenharmony_ci%4 = OpInBoundsAccessChain %uint_ptr %var %uint_0
993fd4e5da5Sopenharmony_ciOpStore %4 %uint_0
994fd4e5da5Sopenharmony_ciOpReturn
995fd4e5da5Sopenharmony_ciOpFunctionEnd
996fd4e5da5Sopenharmony_ci  )";
997fd4e5da5Sopenharmony_ci
998fd4e5da5Sopenharmony_ci  SinglePassRunAndMatch<ScalarReplacementPass>(text, false);
999fd4e5da5Sopenharmony_ci}
1000fd4e5da5Sopenharmony_ci
1001fd4e5da5Sopenharmony_ciTEST_F(ScalarReplacementTest, DonTouchAliasedDecoration) {
1002fd4e5da5Sopenharmony_ci  const std::string text = R"(
1003fd4e5da5Sopenharmony_ci;
1004fd4e5da5Sopenharmony_ci; CHECK: [[struct:%\w+]] = OpTypeStruct
1005fd4e5da5Sopenharmony_ci; CHECK: [[struct_ptr:%\w+]] = OpTypePointer Function [[struct]]
1006fd4e5da5Sopenharmony_ci; CHECK: OpLabel
1007fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpVariable [[struct_ptr]]
1008fd4e5da5Sopenharmony_ci; CHECK-NOT: OpVariable
1009fd4e5da5Sopenharmony_ci;
1010fd4e5da5Sopenharmony_ciOpCapability Shader
1011fd4e5da5Sopenharmony_ciOpCapability Linkage
1012fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
1013fd4e5da5Sopenharmony_ciOpName %func "aliased"
1014fd4e5da5Sopenharmony_ciOpDecorate %var Aliased
1015fd4e5da5Sopenharmony_ci%void = OpTypeVoid
1016fd4e5da5Sopenharmony_ci%uint = OpTypeInt 32 0
1017fd4e5da5Sopenharmony_ci%struct1 = OpTypeStruct %uint
1018fd4e5da5Sopenharmony_ci%uint_ptr = OpTypePointer Function %uint
1019fd4e5da5Sopenharmony_ci%struct1_ptr = OpTypePointer Function %struct1
1020fd4e5da5Sopenharmony_ci%uint_0 = OpConstant %uint 0
1021fd4e5da5Sopenharmony_ci%func = OpTypeFunction %void
1022fd4e5da5Sopenharmony_ci%1 = OpFunction %void None %func
1023fd4e5da5Sopenharmony_ci%2 = OpLabel
1024fd4e5da5Sopenharmony_ci%var = OpVariable %struct1_ptr Function
1025fd4e5da5Sopenharmony_ci%3 = OpAccessChain %uint_ptr %var %uint_0
1026fd4e5da5Sopenharmony_ci%4 = OpLoad %uint %3
1027fd4e5da5Sopenharmony_ciOpReturn
1028fd4e5da5Sopenharmony_ciOpFunctionEnd
1029fd4e5da5Sopenharmony_ci  )";
1030fd4e5da5Sopenharmony_ci
1031fd4e5da5Sopenharmony_ci  SinglePassRunAndMatch<ScalarReplacementPass>(text, true);
1032fd4e5da5Sopenharmony_ci}
1033fd4e5da5Sopenharmony_ci
1034fd4e5da5Sopenharmony_ciTEST_F(ScalarReplacementTest, CopyRestrictDecoration) {
1035fd4e5da5Sopenharmony_ci  const std::string text = R"(
1036fd4e5da5Sopenharmony_ci;
1037fd4e5da5Sopenharmony_ci; CHECK: OpName
1038fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpDecorate [[var0:%\w+]] Restrict
1039fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpDecorate [[var1:%\w+]] Restrict
1040fd4e5da5Sopenharmony_ci; CHECK: [[int:%\w+]] = OpTypeInt
1041fd4e5da5Sopenharmony_ci; CHECK: [[struct:%\w+]] = OpTypeStruct
1042fd4e5da5Sopenharmony_ci; CHECK: [[int_ptr:%\w+]] = OpTypePointer Function [[int]]
1043fd4e5da5Sopenharmony_ci; CHECK: [[struct_ptr:%\w+]] = OpTypePointer Function [[struct]]
1044fd4e5da5Sopenharmony_ci; CHECK: OpLabel
1045fd4e5da5Sopenharmony_ci; CHECK-NEXT: [[var1]] = OpVariable [[int_ptr]]
1046fd4e5da5Sopenharmony_ci; CHECK-NEXT: [[var0]] = OpVariable [[int_ptr]]
1047fd4e5da5Sopenharmony_ci; CHECK-NOT: OpVariable [[struct_ptr]]
1048fd4e5da5Sopenharmony_ci;
1049fd4e5da5Sopenharmony_ciOpCapability Shader
1050fd4e5da5Sopenharmony_ciOpCapability Linkage
1051fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
1052fd4e5da5Sopenharmony_ciOpName %func "restrict"
1053fd4e5da5Sopenharmony_ciOpDecorate %var Restrict
1054fd4e5da5Sopenharmony_ci%void = OpTypeVoid
1055fd4e5da5Sopenharmony_ci%uint = OpTypeInt 32 0
1056fd4e5da5Sopenharmony_ci%struct1 = OpTypeStruct %uint %uint
1057fd4e5da5Sopenharmony_ci%uint_ptr = OpTypePointer Function %uint
1058fd4e5da5Sopenharmony_ci%struct1_ptr = OpTypePointer Function %struct1
1059fd4e5da5Sopenharmony_ci%uint_0 = OpConstant %uint 0
1060fd4e5da5Sopenharmony_ci%uint_1 = OpConstant %uint 1
1061fd4e5da5Sopenharmony_ci%func = OpTypeFunction %void
1062fd4e5da5Sopenharmony_ci%1 = OpFunction %void None %func
1063fd4e5da5Sopenharmony_ci%2 = OpLabel
1064fd4e5da5Sopenharmony_ci%var = OpVariable %struct1_ptr Function
1065fd4e5da5Sopenharmony_ci%3 = OpAccessChain %uint_ptr %var %uint_0
1066fd4e5da5Sopenharmony_ci%4 = OpLoad %uint %3
1067fd4e5da5Sopenharmony_ci%5 = OpAccessChain %uint_ptr %var %uint_1
1068fd4e5da5Sopenharmony_ci%6 = OpLoad %uint %5
1069fd4e5da5Sopenharmony_ciOpReturn
1070fd4e5da5Sopenharmony_ciOpFunctionEnd
1071fd4e5da5Sopenharmony_ci  )";
1072fd4e5da5Sopenharmony_ci
1073fd4e5da5Sopenharmony_ci  SinglePassRunAndMatch<ScalarReplacementPass>(text, true);
1074fd4e5da5Sopenharmony_ci}
1075fd4e5da5Sopenharmony_ci
1076fd4e5da5Sopenharmony_ciTEST_F(ScalarReplacementTest, DontClobberDecoratesOnSubtypes) {
1077fd4e5da5Sopenharmony_ci  const std::string text = R"(
1078fd4e5da5Sopenharmony_ci;
1079fd4e5da5Sopenharmony_ci; CHECK: OpDecorate [[array:%\w+]] ArrayStride 1
1080fd4e5da5Sopenharmony_ci; CHECK: [[uint:%\w+]] = OpTypeInt 32 0
1081fd4e5da5Sopenharmony_ci; CHECK: [[array]] = OpTypeArray [[uint]]
1082fd4e5da5Sopenharmony_ci; CHECK: [[array_ptr:%\w+]] = OpTypePointer Function [[array]]
1083fd4e5da5Sopenharmony_ci; CHECK: OpLabel
1084fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpVariable [[array_ptr]] Function
1085fd4e5da5Sopenharmony_ci; CHECK-NOT: OpVariable
1086fd4e5da5Sopenharmony_ci;
1087fd4e5da5Sopenharmony_ciOpCapability Shader
1088fd4e5da5Sopenharmony_ciOpCapability Linkage
1089fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
1090fd4e5da5Sopenharmony_ciOpName %func "array_stride"
1091fd4e5da5Sopenharmony_ciOpDecorate %array ArrayStride 1
1092fd4e5da5Sopenharmony_ci%void = OpTypeVoid
1093fd4e5da5Sopenharmony_ci%uint = OpTypeInt 32 0
1094fd4e5da5Sopenharmony_ci%uint_1 = OpConstant %uint 1
1095fd4e5da5Sopenharmony_ci%array = OpTypeArray %uint %uint_1
1096fd4e5da5Sopenharmony_ci%struct1 = OpTypeStruct %array
1097fd4e5da5Sopenharmony_ci%uint_ptr = OpTypePointer Function %uint
1098fd4e5da5Sopenharmony_ci%struct1_ptr = OpTypePointer Function %struct1
1099fd4e5da5Sopenharmony_ci%uint_0 = OpConstant %uint 0
1100fd4e5da5Sopenharmony_ci%func = OpTypeFunction %void %uint
1101fd4e5da5Sopenharmony_ci%1 = OpFunction %void None %func
1102fd4e5da5Sopenharmony_ci%param = OpFunctionParameter %uint
1103fd4e5da5Sopenharmony_ci%2 = OpLabel
1104fd4e5da5Sopenharmony_ci%var = OpVariable %struct1_ptr Function
1105fd4e5da5Sopenharmony_ci%3 = OpAccessChain %uint_ptr %var %uint_0 %param
1106fd4e5da5Sopenharmony_ci%4 = OpLoad %uint %3
1107fd4e5da5Sopenharmony_ciOpReturn
1108fd4e5da5Sopenharmony_ciOpFunctionEnd
1109fd4e5da5Sopenharmony_ci  )";
1110fd4e5da5Sopenharmony_ci
1111fd4e5da5Sopenharmony_ci  SinglePassRunAndMatch<ScalarReplacementPass>(text, true);
1112fd4e5da5Sopenharmony_ci}
1113fd4e5da5Sopenharmony_ci
1114fd4e5da5Sopenharmony_ciTEST_F(ScalarReplacementTest, DontCopyMemberDecorate) {
1115fd4e5da5Sopenharmony_ci  const std::string text = R"(
1116fd4e5da5Sopenharmony_ci;
1117fd4e5da5Sopenharmony_ci; CHECK-NOT: OpDecorate
1118fd4e5da5Sopenharmony_ci; CHECK: [[uint:%\w+]] = OpTypeInt 32 0
1119fd4e5da5Sopenharmony_ci; CHECK: [[struct:%\w+]] = OpTypeStruct [[uint]]
1120fd4e5da5Sopenharmony_ci; CHECK: [[uint_ptr:%\w+]] = OpTypePointer Function [[uint]]
1121fd4e5da5Sopenharmony_ci; CHECK: [[struct_ptr:%\w+]] = OpTypePointer Function [[struct]]
1122fd4e5da5Sopenharmony_ci; CHECK: OpLabel
1123fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpVariable [[uint_ptr]] Function
1124fd4e5da5Sopenharmony_ci; CHECK-NOT: OpVariable
1125fd4e5da5Sopenharmony_ci;
1126fd4e5da5Sopenharmony_ciOpCapability Shader
1127fd4e5da5Sopenharmony_ciOpCapability Linkage
1128fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
1129fd4e5da5Sopenharmony_ciOpName %func "member_decorate"
1130fd4e5da5Sopenharmony_ciOpMemberDecorate %struct1 0 Offset 1
1131fd4e5da5Sopenharmony_ci%void = OpTypeVoid
1132fd4e5da5Sopenharmony_ci%uint = OpTypeInt 32 0
1133fd4e5da5Sopenharmony_ci%uint_1 = OpConstant %uint 1
1134fd4e5da5Sopenharmony_ci%struct1 = OpTypeStruct %uint
1135fd4e5da5Sopenharmony_ci%uint_ptr = OpTypePointer Function %uint
1136fd4e5da5Sopenharmony_ci%struct1_ptr = OpTypePointer Function %struct1
1137fd4e5da5Sopenharmony_ci%uint_0 = OpConstant %uint 0
1138fd4e5da5Sopenharmony_ci%func = OpTypeFunction %void %uint
1139fd4e5da5Sopenharmony_ci%1 = OpFunction %void None %func
1140fd4e5da5Sopenharmony_ci%2 = OpLabel
1141fd4e5da5Sopenharmony_ci%var = OpVariable %struct1_ptr Function
1142fd4e5da5Sopenharmony_ci%3 = OpAccessChain %uint_ptr %var %uint_0
1143fd4e5da5Sopenharmony_ci%4 = OpLoad %uint %3
1144fd4e5da5Sopenharmony_ciOpReturn
1145fd4e5da5Sopenharmony_ciOpFunctionEnd
1146fd4e5da5Sopenharmony_ci  )";
1147fd4e5da5Sopenharmony_ci
1148fd4e5da5Sopenharmony_ci  SinglePassRunAndMatch<ScalarReplacementPass>(text, true);
1149fd4e5da5Sopenharmony_ci}
1150fd4e5da5Sopenharmony_ci
1151fd4e5da5Sopenharmony_ciTEST_F(ScalarReplacementTest, NoPartialAccesses2) {
1152fd4e5da5Sopenharmony_ci  const std::string text = R"(
1153fd4e5da5Sopenharmony_ci;
1154fd4e5da5Sopenharmony_ci; CHECK: [[float:%\w+]] = OpTypeFloat 32
1155fd4e5da5Sopenharmony_ci; CHECK: [[float_ptr:%\w+]] = OpTypePointer Function [[float]]
1156fd4e5da5Sopenharmony_ci; CHECK: OpVariable [[float_ptr]] Function
1157fd4e5da5Sopenharmony_ci; CHECK: OpVariable [[float_ptr]] Function
1158fd4e5da5Sopenharmony_ci; CHECK: OpVariable [[float_ptr]] Function
1159fd4e5da5Sopenharmony_ci; CHECK: OpVariable [[float_ptr]] Function
1160fd4e5da5Sopenharmony_ci; CHECK: OpVariable [[float_ptr]] Function
1161fd4e5da5Sopenharmony_ci; CHECK: OpVariable [[float_ptr]] Function
1162fd4e5da5Sopenharmony_ci; CHECK: OpVariable [[float_ptr]] Function
1163fd4e5da5Sopenharmony_ci; CHECK-NOT: OpVariable
1164fd4e5da5Sopenharmony_ci;
1165fd4e5da5Sopenharmony_ciOpCapability Shader
1166fd4e5da5Sopenharmony_ci%1 = OpExtInstImport "GLSL.std.450"
1167fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
1168fd4e5da5Sopenharmony_ciOpEntryPoint Fragment %main "main" %fo
1169fd4e5da5Sopenharmony_ciOpExecutionMode %main OriginUpperLeft
1170fd4e5da5Sopenharmony_ciOpSource GLSL 430
1171fd4e5da5Sopenharmony_ciOpName %main "main"
1172fd4e5da5Sopenharmony_ciOpName %S "S"
1173fd4e5da5Sopenharmony_ciOpMemberName %S 0 "x"
1174fd4e5da5Sopenharmony_ciOpMemberName %S 1 "y"
1175fd4e5da5Sopenharmony_ciOpName %ts1 "ts1"
1176fd4e5da5Sopenharmony_ciOpName %S_0 "S"
1177fd4e5da5Sopenharmony_ciOpMemberName %S_0 0 "x"
1178fd4e5da5Sopenharmony_ciOpMemberName %S_0 1 "y"
1179fd4e5da5Sopenharmony_ciOpName %U_t "U_t"
1180fd4e5da5Sopenharmony_ciOpMemberName %U_t 0 "g_s1"
1181fd4e5da5Sopenharmony_ciOpMemberName %U_t 1 "g_s2"
1182fd4e5da5Sopenharmony_ciOpMemberName %U_t 2 "g_s3"
1183fd4e5da5Sopenharmony_ciOpName %_ ""
1184fd4e5da5Sopenharmony_ciOpName %ts2 "ts2"
1185fd4e5da5Sopenharmony_ciOpName %_Globals_ "_Globals_"
1186fd4e5da5Sopenharmony_ciOpMemberName %_Globals_ 0 "g_b"
1187fd4e5da5Sopenharmony_ciOpName %__0 ""
1188fd4e5da5Sopenharmony_ciOpName %ts3 "ts3"
1189fd4e5da5Sopenharmony_ciOpName %ts4 "ts4"
1190fd4e5da5Sopenharmony_ciOpName %fo "fo"
1191fd4e5da5Sopenharmony_ciOpMemberDecorate %S_0 0 Offset 0
1192fd4e5da5Sopenharmony_ciOpMemberDecorate %S_0 1 Offset 4
1193fd4e5da5Sopenharmony_ciOpMemberDecorate %U_t 0 Offset 0
1194fd4e5da5Sopenharmony_ciOpMemberDecorate %U_t 1 Offset 8
1195fd4e5da5Sopenharmony_ciOpMemberDecorate %U_t 2 Offset 16
1196fd4e5da5Sopenharmony_ciOpDecorate %U_t BufferBlock
1197fd4e5da5Sopenharmony_ciOpDecorate %_ DescriptorSet 0
1198fd4e5da5Sopenharmony_ciOpMemberDecorate %_Globals_ 0 Offset 0
1199fd4e5da5Sopenharmony_ciOpDecorate %_Globals_ Block
1200fd4e5da5Sopenharmony_ciOpDecorate %__0 DescriptorSet 0
1201fd4e5da5Sopenharmony_ciOpDecorate %__0 Binding 0
1202fd4e5da5Sopenharmony_ciOpDecorate %fo Location 0
1203fd4e5da5Sopenharmony_ci%void = OpTypeVoid
1204fd4e5da5Sopenharmony_ci%15 = OpTypeFunction %void
1205fd4e5da5Sopenharmony_ci%float = OpTypeFloat 32
1206fd4e5da5Sopenharmony_ci%S = OpTypeStruct %float %float
1207fd4e5da5Sopenharmony_ci%_ptr_Function_S = OpTypePointer Function %S
1208fd4e5da5Sopenharmony_ci%S_0 = OpTypeStruct %float %float
1209fd4e5da5Sopenharmony_ci%U_t = OpTypeStruct %S_0 %S_0 %S_0
1210fd4e5da5Sopenharmony_ci%_ptr_Uniform_U_t = OpTypePointer Uniform %U_t
1211fd4e5da5Sopenharmony_ci%_ = OpVariable %_ptr_Uniform_U_t Uniform
1212fd4e5da5Sopenharmony_ci%int = OpTypeInt 32 1
1213fd4e5da5Sopenharmony_ci%int_0 = OpConstant %int 0
1214fd4e5da5Sopenharmony_ci%_ptr_Uniform_S_0 = OpTypePointer Uniform %S_0
1215fd4e5da5Sopenharmony_ci%_ptr_Function_float = OpTypePointer Function %float
1216fd4e5da5Sopenharmony_ci%int_1 = OpConstant %int 1
1217fd4e5da5Sopenharmony_ci%uint = OpTypeInt 32 0
1218fd4e5da5Sopenharmony_ci%_Globals_ = OpTypeStruct %uint
1219fd4e5da5Sopenharmony_ci%_ptr_Uniform__Globals_ = OpTypePointer Uniform %_Globals_
1220fd4e5da5Sopenharmony_ci%__0 = OpVariable %_ptr_Uniform__Globals_ Uniform
1221fd4e5da5Sopenharmony_ci%_ptr_Uniform_uint = OpTypePointer Uniform %uint
1222fd4e5da5Sopenharmony_ci%bool = OpTypeBool
1223fd4e5da5Sopenharmony_ci%uint_0 = OpConstant %uint 0
1224fd4e5da5Sopenharmony_ci%_ptr_Output_float = OpTypePointer Output %float
1225fd4e5da5Sopenharmony_ci%fo = OpVariable %_ptr_Output_float Output
1226fd4e5da5Sopenharmony_ci%main = OpFunction %void None %15
1227fd4e5da5Sopenharmony_ci%30 = OpLabel
1228fd4e5da5Sopenharmony_ci%ts1 = OpVariable %_ptr_Function_S Function
1229fd4e5da5Sopenharmony_ci%ts2 = OpVariable %_ptr_Function_S Function
1230fd4e5da5Sopenharmony_ci%ts3 = OpVariable %_ptr_Function_S Function
1231fd4e5da5Sopenharmony_ci%ts4 = OpVariable %_ptr_Function_S Function
1232fd4e5da5Sopenharmony_ci%31 = OpAccessChain %_ptr_Uniform_S_0 %_ %int_0
1233fd4e5da5Sopenharmony_ci%32 = OpLoad %S_0 %31
1234fd4e5da5Sopenharmony_ci%33 = OpCompositeExtract %float %32 0
1235fd4e5da5Sopenharmony_ci%34 = OpAccessChain %_ptr_Function_float %ts1 %int_0
1236fd4e5da5Sopenharmony_ciOpStore %34 %33
1237fd4e5da5Sopenharmony_ci%35 = OpCompositeExtract %float %32 1
1238fd4e5da5Sopenharmony_ci%36 = OpAccessChain %_ptr_Function_float %ts1 %int_1
1239fd4e5da5Sopenharmony_ciOpStore %36 %35
1240fd4e5da5Sopenharmony_ci%37 = OpAccessChain %_ptr_Uniform_S_0 %_ %int_1
1241fd4e5da5Sopenharmony_ci%38 = OpLoad %S_0 %37
1242fd4e5da5Sopenharmony_ci%39 = OpCompositeExtract %float %38 0
1243fd4e5da5Sopenharmony_ci%40 = OpAccessChain %_ptr_Function_float %ts2 %int_0
1244fd4e5da5Sopenharmony_ciOpStore %40 %39
1245fd4e5da5Sopenharmony_ci%41 = OpCompositeExtract %float %38 1
1246fd4e5da5Sopenharmony_ci%42 = OpAccessChain %_ptr_Function_float %ts2 %int_1
1247fd4e5da5Sopenharmony_ciOpStore %42 %41
1248fd4e5da5Sopenharmony_ci%43 = OpAccessChain %_ptr_Uniform_uint %__0 %int_0
1249fd4e5da5Sopenharmony_ci%44 = OpLoad %uint %43
1250fd4e5da5Sopenharmony_ci%45 = OpINotEqual %bool %44 %uint_0
1251fd4e5da5Sopenharmony_ciOpSelectionMerge %46 None
1252fd4e5da5Sopenharmony_ciOpBranchConditional %45 %47 %48
1253fd4e5da5Sopenharmony_ci%47 = OpLabel
1254fd4e5da5Sopenharmony_ci%49 = OpLoad %S %ts1
1255fd4e5da5Sopenharmony_ciOpStore %ts3 %49
1256fd4e5da5Sopenharmony_ciOpBranch %46
1257fd4e5da5Sopenharmony_ci%48 = OpLabel
1258fd4e5da5Sopenharmony_ci%50 = OpLoad %S %ts2
1259fd4e5da5Sopenharmony_ciOpStore %ts3 %50
1260fd4e5da5Sopenharmony_ciOpBranch %46
1261fd4e5da5Sopenharmony_ci%46 = OpLabel
1262fd4e5da5Sopenharmony_ci%51 = OpLoad %S %ts3
1263fd4e5da5Sopenharmony_ciOpStore %ts4 %51
1264fd4e5da5Sopenharmony_ci%52 = OpAccessChain %_ptr_Function_float %ts4 %int_1
1265fd4e5da5Sopenharmony_ci%53 = OpLoad %float %52
1266fd4e5da5Sopenharmony_ciOpStore %fo %53
1267fd4e5da5Sopenharmony_ciOpReturn
1268fd4e5da5Sopenharmony_ciOpFunctionEnd
1269fd4e5da5Sopenharmony_ci  )";
1270fd4e5da5Sopenharmony_ci
1271fd4e5da5Sopenharmony_ci  SinglePassRunAndMatch<ScalarReplacementPass>(text, true);
1272fd4e5da5Sopenharmony_ci}
1273fd4e5da5Sopenharmony_ci
1274fd4e5da5Sopenharmony_ciTEST_F(ScalarReplacementTest, ReplaceWholeLoadAndStore) {
1275fd4e5da5Sopenharmony_ci  const std::string text = R"(
1276fd4e5da5Sopenharmony_ci;
1277fd4e5da5Sopenharmony_ci; CHECK: [[uint:%\w+]] = OpTypeInt 32 0
1278fd4e5da5Sopenharmony_ci; CHECK: [[struct1:%\w+]] = OpTypeStruct [[uint]] [[uint]]
1279fd4e5da5Sopenharmony_ci; CHECK: [[uint_ptr:%\w+]] = OpTypePointer Function [[uint]]
1280fd4e5da5Sopenharmony_ci; CHECK: [[const:%\w+]] = OpConstant [[uint]] 0
1281fd4e5da5Sopenharmony_ci; CHECK: [[undef:%\w+]] = OpUndef [[uint]]
1282fd4e5da5Sopenharmony_ci; CHECK: [[var0:%\w+]] = OpVariable [[uint_ptr]] Function
1283fd4e5da5Sopenharmony_ci; CHECK: [[var1:%\w+]] = OpVariable [[uint_ptr]] Function
1284fd4e5da5Sopenharmony_ci; CHECK-NOT: OpVariable
1285fd4e5da5Sopenharmony_ci; CHECK: [[l0:%\w+]] = OpLoad [[uint]] [[var0]]
1286fd4e5da5Sopenharmony_ci; CHECK: [[c0:%\w+]] = OpCompositeConstruct [[struct1]] [[l0]] [[undef]]
1287fd4e5da5Sopenharmony_ci; CHECK: [[e0:%\w+]] = OpCompositeExtract [[uint]] [[c0]] 0
1288fd4e5da5Sopenharmony_ci; CHECK: OpStore [[var1]] [[e0]]
1289fd4e5da5Sopenharmony_ci; CHECK: [[l1:%\w+]] = OpLoad [[uint]] [[var1]]
1290fd4e5da5Sopenharmony_ci; CHECK: [[c1:%\w+]] = OpCompositeConstruct [[struct1]] [[l1]] [[undef]]
1291fd4e5da5Sopenharmony_ci; CHECK: [[e1:%\w+]] = OpCompositeExtract [[uint]] [[c1]] 0
1292fd4e5da5Sopenharmony_ci;
1293fd4e5da5Sopenharmony_ciOpCapability Shader
1294fd4e5da5Sopenharmony_ciOpCapability Linkage
1295fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
1296fd4e5da5Sopenharmony_ciOpName %func "replace_whole_load"
1297fd4e5da5Sopenharmony_ci%void = OpTypeVoid
1298fd4e5da5Sopenharmony_ci%uint = OpTypeInt 32 0
1299fd4e5da5Sopenharmony_ci%struct1 = OpTypeStruct %uint %uint
1300fd4e5da5Sopenharmony_ci%uint_ptr = OpTypePointer Function %uint
1301fd4e5da5Sopenharmony_ci%struct1_ptr = OpTypePointer Function %struct1
1302fd4e5da5Sopenharmony_ci%uint_0 = OpConstant %uint 0
1303fd4e5da5Sopenharmony_ci%uint_1 = OpConstant %uint 1
1304fd4e5da5Sopenharmony_ci%func = OpTypeFunction %void
1305fd4e5da5Sopenharmony_ci%1 = OpFunction %void None %func
1306fd4e5da5Sopenharmony_ci%2 = OpLabel
1307fd4e5da5Sopenharmony_ci%var2 = OpVariable %struct1_ptr Function
1308fd4e5da5Sopenharmony_ci%var1 = OpVariable %struct1_ptr Function
1309fd4e5da5Sopenharmony_ci%load1 = OpLoad %struct1 %var1
1310fd4e5da5Sopenharmony_ciOpStore %var2 %load1
1311fd4e5da5Sopenharmony_ci%load2 = OpLoad %struct1 %var2
1312fd4e5da5Sopenharmony_ci%3 = OpCompositeExtract %uint %load2 0
1313fd4e5da5Sopenharmony_ciOpReturn
1314fd4e5da5Sopenharmony_ciOpFunctionEnd
1315fd4e5da5Sopenharmony_ci  )";
1316fd4e5da5Sopenharmony_ci
1317fd4e5da5Sopenharmony_ci  SinglePassRunAndMatch<ScalarReplacementPass>(text, true);
1318fd4e5da5Sopenharmony_ci}
1319fd4e5da5Sopenharmony_ci
1320fd4e5da5Sopenharmony_ciTEST_F(ScalarReplacementTest, ReplaceWholeLoadAndStore2) {
1321fd4e5da5Sopenharmony_ci  // TODO: We can improve this case by ensuring that |var2| is processed first.
1322fd4e5da5Sopenharmony_ci  const std::string text = R"(
1323fd4e5da5Sopenharmony_ci;
1324fd4e5da5Sopenharmony_ci; CHECK: [[uint:%\w+]] = OpTypeInt 32 0
1325fd4e5da5Sopenharmony_ci; CHECK: [[struct1:%\w+]] = OpTypeStruct [[uint]] [[uint]]
1326fd4e5da5Sopenharmony_ci; CHECK: [[uint_ptr:%\w+]] = OpTypePointer Function [[uint]]
1327fd4e5da5Sopenharmony_ci; CHECK: [[const:%\w+]] = OpConstant [[uint]] 0
1328fd4e5da5Sopenharmony_ci; CHECK: [[undef:%\w+]] = OpUndef [[uint]]
1329fd4e5da5Sopenharmony_ci; CHECK: [[var1:%\w+]] = OpVariable [[uint_ptr]] Function
1330fd4e5da5Sopenharmony_ci; CHECK: [[var0a:%\w+]] = OpVariable [[uint_ptr]] Function
1331fd4e5da5Sopenharmony_ci; CHECK: [[var0b:%\w+]] = OpVariable [[uint_ptr]] Function
1332fd4e5da5Sopenharmony_ci; CHECK-NOT: OpVariable
1333fd4e5da5Sopenharmony_ci; CHECK: [[l0a:%\w+]] = OpLoad [[uint]] [[var0a]]
1334fd4e5da5Sopenharmony_ci; CHECK: [[l0b:%\w+]] = OpLoad [[uint]] [[var0b]]
1335fd4e5da5Sopenharmony_ci; CHECK: [[c0:%\w+]] = OpCompositeConstruct [[struct1]] [[l0b]] [[l0a]]
1336fd4e5da5Sopenharmony_ci; CHECK: [[e0:%\w+]] = OpCompositeExtract [[uint]] [[c0]] 0
1337fd4e5da5Sopenharmony_ci; CHECK: OpStore [[var1]] [[e0]]
1338fd4e5da5Sopenharmony_ci; CHECK: [[l1:%\w+]] = OpLoad [[uint]] [[var1]]
1339fd4e5da5Sopenharmony_ci; CHECK: [[c1:%\w+]] = OpCompositeConstruct [[struct1]] [[l1]] [[undef]]
1340fd4e5da5Sopenharmony_ci; CHECK: [[e1:%\w+]] = OpCompositeExtract [[uint]] [[c1]] 0
1341fd4e5da5Sopenharmony_ci;
1342fd4e5da5Sopenharmony_ciOpCapability Shader
1343fd4e5da5Sopenharmony_ciOpCapability Linkage
1344fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
1345fd4e5da5Sopenharmony_ciOpName %func "replace_whole_load"
1346fd4e5da5Sopenharmony_ci%void = OpTypeVoid
1347fd4e5da5Sopenharmony_ci%uint = OpTypeInt 32 0
1348fd4e5da5Sopenharmony_ci%struct1 = OpTypeStruct %uint %uint
1349fd4e5da5Sopenharmony_ci%uint_ptr = OpTypePointer Function %uint
1350fd4e5da5Sopenharmony_ci%struct1_ptr = OpTypePointer Function %struct1
1351fd4e5da5Sopenharmony_ci%uint_0 = OpConstant %uint 0
1352fd4e5da5Sopenharmony_ci%uint_1 = OpConstant %uint 1
1353fd4e5da5Sopenharmony_ci%func = OpTypeFunction %void
1354fd4e5da5Sopenharmony_ci%1 = OpFunction %void None %func
1355fd4e5da5Sopenharmony_ci%2 = OpLabel
1356fd4e5da5Sopenharmony_ci%var1 = OpVariable %struct1_ptr Function
1357fd4e5da5Sopenharmony_ci%var2 = OpVariable %struct1_ptr Function
1358fd4e5da5Sopenharmony_ci%load1 = OpLoad %struct1 %var1
1359fd4e5da5Sopenharmony_ciOpStore %var2 %load1
1360fd4e5da5Sopenharmony_ci%load2 = OpLoad %struct1 %var2
1361fd4e5da5Sopenharmony_ci%3 = OpCompositeExtract %uint %load2 0
1362fd4e5da5Sopenharmony_ciOpReturn
1363fd4e5da5Sopenharmony_ciOpFunctionEnd
1364fd4e5da5Sopenharmony_ci  )";
1365fd4e5da5Sopenharmony_ci
1366fd4e5da5Sopenharmony_ci  SinglePassRunAndMatch<ScalarReplacementPass>(text, true);
1367fd4e5da5Sopenharmony_ci}
1368fd4e5da5Sopenharmony_ci
1369fd4e5da5Sopenharmony_ciTEST_F(ScalarReplacementTest, CreateAmbiguousNullConstant1) {
1370fd4e5da5Sopenharmony_ci  const std::string text = R"(
1371fd4e5da5Sopenharmony_ci;
1372fd4e5da5Sopenharmony_ci; CHECK: [[uint:%\w+]] = OpTypeInt 32 0
1373fd4e5da5Sopenharmony_ci; CHECK: [[struct1:%\w+]] = OpTypeStruct [[uint]] [[struct_member:%\w+]]
1374fd4e5da5Sopenharmony_ci; CHECK: [[uint_ptr:%\w+]] = OpTypePointer Function [[uint]]
1375fd4e5da5Sopenharmony_ci; CHECK: [[const:%\w+]] = OpConstant [[uint]] 0
1376fd4e5da5Sopenharmony_ci; CHECK: [[undef:%\w+]] = OpUndef [[struct_member]]
1377fd4e5da5Sopenharmony_ci; CHECK: [[var0a:%\w+]] = OpVariable [[uint_ptr]] Function
1378fd4e5da5Sopenharmony_ci; CHECK: [[var1:%\w+]] = OpVariable [[uint_ptr]] Function
1379fd4e5da5Sopenharmony_ci; CHECK: [[var0b:%\w+]] = OpVariable [[uint_ptr]] Function
1380fd4e5da5Sopenharmony_ci; CHECK-NOT: OpVariable
1381fd4e5da5Sopenharmony_ci; CHECK: OpStore [[var1]]
1382fd4e5da5Sopenharmony_ci; CHECK: [[l1:%\w+]] = OpLoad [[uint]] [[var1]]
1383fd4e5da5Sopenharmony_ci; CHECK: [[c1:%\w+]] = OpCompositeConstruct [[struct1]] [[l1]] [[undef]]
1384fd4e5da5Sopenharmony_ci; CHECK: [[e1:%\w+]] = OpCompositeExtract [[uint]] [[c1]] 0
1385fd4e5da5Sopenharmony_ci;
1386fd4e5da5Sopenharmony_ciOpCapability Shader
1387fd4e5da5Sopenharmony_ciOpCapability Linkage
1388fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
1389fd4e5da5Sopenharmony_ciOpName %func "replace_whole_load"
1390fd4e5da5Sopenharmony_ci%void = OpTypeVoid
1391fd4e5da5Sopenharmony_ci%uint = OpTypeInt 32 0
1392fd4e5da5Sopenharmony_ci%struct2 = OpTypeStruct %uint
1393fd4e5da5Sopenharmony_ci%struct3 = OpTypeStruct %uint
1394fd4e5da5Sopenharmony_ci%struct1 = OpTypeStruct %uint %struct2
1395fd4e5da5Sopenharmony_ci%uint_ptr = OpTypePointer Function %uint
1396fd4e5da5Sopenharmony_ci%struct1_ptr = OpTypePointer Function %struct1
1397fd4e5da5Sopenharmony_ci%uint_0 = OpConstant %uint 0
1398fd4e5da5Sopenharmony_ci%uint_1 = OpConstant %uint 1
1399fd4e5da5Sopenharmony_ci%func = OpTypeFunction %void
1400fd4e5da5Sopenharmony_ci%1 = OpFunction %void None %func
1401fd4e5da5Sopenharmony_ci%2 = OpLabel
1402fd4e5da5Sopenharmony_ci%var1 = OpVariable %struct1_ptr Function
1403fd4e5da5Sopenharmony_ci%var2 = OpVariable %struct1_ptr Function
1404fd4e5da5Sopenharmony_ci%load1 = OpLoad %struct1 %var1
1405fd4e5da5Sopenharmony_ciOpStore %var2 %load1
1406fd4e5da5Sopenharmony_ci%load2 = OpLoad %struct1 %var2
1407fd4e5da5Sopenharmony_ci%3 = OpCompositeExtract %uint %load2 0
1408fd4e5da5Sopenharmony_ciOpReturn
1409fd4e5da5Sopenharmony_ciOpFunctionEnd
1410fd4e5da5Sopenharmony_ci  )";
1411fd4e5da5Sopenharmony_ci
1412fd4e5da5Sopenharmony_ci  SinglePassRunAndMatch<ScalarReplacementPass>(text, true);
1413fd4e5da5Sopenharmony_ci}
1414fd4e5da5Sopenharmony_ci
1415fd4e5da5Sopenharmony_ciTEST_F(ScalarReplacementTest, SpecConstantArray) {
1416fd4e5da5Sopenharmony_ci  const std::string text = R"(
1417fd4e5da5Sopenharmony_ci; CHECK: [[int:%\w+]] = OpTypeInt
1418fd4e5da5Sopenharmony_ci; CHECK: [[spec_const:%\w+]] = OpSpecConstant [[int]] 4
1419fd4e5da5Sopenharmony_ci; CHECK: [[spec_op:%\w+]] = OpSpecConstantOp [[int]] IAdd [[spec_const]] [[spec_const]]
1420fd4e5da5Sopenharmony_ci; CHECK: [[array1:%\w+]] = OpTypeArray [[int]] [[spec_const]]
1421fd4e5da5Sopenharmony_ci; CHECK: [[array2:%\w+]] = OpTypeArray [[int]] [[spec_op]]
1422fd4e5da5Sopenharmony_ci; CHECK: [[ptr_array1:%\w+]] = OpTypePointer Function [[array1]]
1423fd4e5da5Sopenharmony_ci; CHECK: [[ptr_array2:%\w+]] = OpTypePointer Function [[array2]]
1424fd4e5da5Sopenharmony_ci; CHECK: OpLabel
1425fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpVariable [[ptr_array1]] Function
1426fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpVariable [[ptr_array2]] Function
1427fd4e5da5Sopenharmony_ci; CHECK-NOT: OpVariable
1428fd4e5da5Sopenharmony_ciOpCapability Shader
1429fd4e5da5Sopenharmony_ciOpCapability Linkage
1430fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
1431fd4e5da5Sopenharmony_ci%void = OpTypeVoid
1432fd4e5da5Sopenharmony_ci%void_fn = OpTypeFunction %void
1433fd4e5da5Sopenharmony_ci%int = OpTypeInt 32 0
1434fd4e5da5Sopenharmony_ci%spec_const = OpSpecConstant %int 4
1435fd4e5da5Sopenharmony_ci%spec_op = OpSpecConstantOp %int IAdd %spec_const %spec_const
1436fd4e5da5Sopenharmony_ci%array_1 = OpTypeArray %int %spec_const
1437fd4e5da5Sopenharmony_ci%array_2 = OpTypeArray %int %spec_op
1438fd4e5da5Sopenharmony_ci%ptr_array_1_Function = OpTypePointer Function %array_1
1439fd4e5da5Sopenharmony_ci%ptr_array_2_Function = OpTypePointer Function %array_2
1440fd4e5da5Sopenharmony_ci%func = OpFunction %void None %void_fn
1441fd4e5da5Sopenharmony_ci%1 = OpLabel
1442fd4e5da5Sopenharmony_ci%var_1 = OpVariable %ptr_array_1_Function Function
1443fd4e5da5Sopenharmony_ci%var_2 = OpVariable %ptr_array_2_Function Function
1444fd4e5da5Sopenharmony_ciOpReturn
1445fd4e5da5Sopenharmony_ciOpFunctionEnd
1446fd4e5da5Sopenharmony_ci)";
1447fd4e5da5Sopenharmony_ci
1448fd4e5da5Sopenharmony_ci  SinglePassRunAndMatch<ScalarReplacementPass>(text, true);
1449fd4e5da5Sopenharmony_ci}
1450fd4e5da5Sopenharmony_ci
1451fd4e5da5Sopenharmony_ciTEST_F(ScalarReplacementTest, CreateAmbiguousNullConstant2) {
1452fd4e5da5Sopenharmony_ci  const std::string text = R"(
1453fd4e5da5Sopenharmony_ci;
1454fd4e5da5Sopenharmony_ci; CHECK: [[uint:%\w+]] = OpTypeInt 32 0
1455fd4e5da5Sopenharmony_ci; CHECK: [[struct1:%\w+]] = OpTypeStruct [[uint]] [[struct_member:%\w+]]
1456fd4e5da5Sopenharmony_ci; CHECK: [[uint_ptr:%\w+]] = OpTypePointer Function [[uint]]
1457fd4e5da5Sopenharmony_ci; CHECK: [[const:%\w+]] = OpConstant [[uint]] 0
1458fd4e5da5Sopenharmony_ci; CHECK: [[undef:%\w+]] = OpUndef [[struct_member]]
1459fd4e5da5Sopenharmony_ci; CHECK: [[var0a:%\w+]] = OpVariable [[uint_ptr]] Function
1460fd4e5da5Sopenharmony_ci; CHECK: [[var1:%\w+]] = OpVariable [[uint_ptr]] Function
1461fd4e5da5Sopenharmony_ci; CHECK: [[var0b:%\w+]] = OpVariable [[uint_ptr]] Function
1462fd4e5da5Sopenharmony_ci; CHECK: OpStore [[var1]]
1463fd4e5da5Sopenharmony_ci; CHECK: [[l1:%\w+]] = OpLoad [[uint]] [[var1]]
1464fd4e5da5Sopenharmony_ci; CHECK: [[c1:%\w+]] = OpCompositeConstruct [[struct1]] [[l1]] [[undef]]
1465fd4e5da5Sopenharmony_ci; CHECK: [[e1:%\w+]] = OpCompositeExtract [[uint]] [[c1]] 0
1466fd4e5da5Sopenharmony_ci;
1467fd4e5da5Sopenharmony_ciOpCapability Shader
1468fd4e5da5Sopenharmony_ciOpCapability Linkage
1469fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
1470fd4e5da5Sopenharmony_ciOpName %func "replace_whole_load"
1471fd4e5da5Sopenharmony_ci%void = OpTypeVoid
1472fd4e5da5Sopenharmony_ci%uint = OpTypeInt 32 0
1473fd4e5da5Sopenharmony_ci%struct3 = OpTypeStruct %uint
1474fd4e5da5Sopenharmony_ci%struct2 = OpTypeStruct %uint
1475fd4e5da5Sopenharmony_ci%struct1 = OpTypeStruct %uint %struct2
1476fd4e5da5Sopenharmony_ci%uint_ptr = OpTypePointer Function %uint
1477fd4e5da5Sopenharmony_ci%struct1_ptr = OpTypePointer Function %struct1
1478fd4e5da5Sopenharmony_ci%uint_0 = OpConstant %uint 0
1479fd4e5da5Sopenharmony_ci%uint_1 = OpConstant %uint 1
1480fd4e5da5Sopenharmony_ci%func = OpTypeFunction %void
1481fd4e5da5Sopenharmony_ci%1 = OpFunction %void None %func
1482fd4e5da5Sopenharmony_ci%2 = OpLabel
1483fd4e5da5Sopenharmony_ci%var1 = OpVariable %struct1_ptr Function
1484fd4e5da5Sopenharmony_ci%var2 = OpVariable %struct1_ptr Function
1485fd4e5da5Sopenharmony_ci%load1 = OpLoad %struct1 %var1
1486fd4e5da5Sopenharmony_ciOpStore %var2 %load1
1487fd4e5da5Sopenharmony_ci%load2 = OpLoad %struct1 %var2
1488fd4e5da5Sopenharmony_ci%3 = OpCompositeExtract %uint %load2 0
1489fd4e5da5Sopenharmony_ciOpReturn
1490fd4e5da5Sopenharmony_ciOpFunctionEnd
1491fd4e5da5Sopenharmony_ci  )";
1492fd4e5da5Sopenharmony_ci
1493fd4e5da5Sopenharmony_ci  SinglePassRunAndMatch<ScalarReplacementPass>(text, true);
1494fd4e5da5Sopenharmony_ci}
1495fd4e5da5Sopenharmony_ci
1496fd4e5da5Sopenharmony_ci// Test that a struct of size 4 is not replaced when there is a limit of 2.
1497fd4e5da5Sopenharmony_ciTEST_F(ScalarReplacementTest, TestLimit) {
1498fd4e5da5Sopenharmony_ci  const std::string text = R"(
1499fd4e5da5Sopenharmony_ciOpCapability Shader
1500fd4e5da5Sopenharmony_ciOpCapability Linkage
1501fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
1502fd4e5da5Sopenharmony_ciOpName %6 "simple_struct"
1503fd4e5da5Sopenharmony_ci%1 = OpTypeVoid
1504fd4e5da5Sopenharmony_ci%2 = OpTypeInt 32 0
1505fd4e5da5Sopenharmony_ci%3 = OpTypeStruct %2 %2 %2 %2
1506fd4e5da5Sopenharmony_ci%4 = OpTypePointer Function %3
1507fd4e5da5Sopenharmony_ci%5 = OpTypePointer Function %2
1508fd4e5da5Sopenharmony_ci%6 = OpTypeFunction %2
1509fd4e5da5Sopenharmony_ci%7 = OpConstantNull %3
1510fd4e5da5Sopenharmony_ci%8 = OpConstant %2 0
1511fd4e5da5Sopenharmony_ci%9 = OpConstant %2 1
1512fd4e5da5Sopenharmony_ci%10 = OpConstant %2 2
1513fd4e5da5Sopenharmony_ci%11 = OpConstant %2 3
1514fd4e5da5Sopenharmony_ci%12 = OpFunction %2 None %6
1515fd4e5da5Sopenharmony_ci%13 = OpLabel
1516fd4e5da5Sopenharmony_ci%14 = OpVariable %4 Function %7
1517fd4e5da5Sopenharmony_ci%15 = OpInBoundsAccessChain %5 %14 %8
1518fd4e5da5Sopenharmony_ci%16 = OpLoad %2 %15
1519fd4e5da5Sopenharmony_ci%17 = OpAccessChain %5 %14 %10
1520fd4e5da5Sopenharmony_ci%18 = OpLoad %2 %17
1521fd4e5da5Sopenharmony_ci%19 = OpIAdd %2 %16 %18
1522fd4e5da5Sopenharmony_ciOpReturnValue %19
1523fd4e5da5Sopenharmony_ciOpFunctionEnd
1524fd4e5da5Sopenharmony_ci  )";
1525fd4e5da5Sopenharmony_ci
1526fd4e5da5Sopenharmony_ci  auto result =
1527fd4e5da5Sopenharmony_ci      SinglePassRunAndDisassemble<ScalarReplacementPass>(text, true, false, 2);
1528fd4e5da5Sopenharmony_ci  EXPECT_EQ(Pass::Status::SuccessWithoutChange, std::get<1>(result));
1529fd4e5da5Sopenharmony_ci}
1530fd4e5da5Sopenharmony_ci
1531fd4e5da5Sopenharmony_ci// Test that a struct of size 4 is replaced when there is a limit of 0 (no
1532fd4e5da5Sopenharmony_ci// limit).  This is the same spir-v as a test above, so we do not check that it
1533fd4e5da5Sopenharmony_ci// is correctly transformed.  We leave that to the test above.
1534fd4e5da5Sopenharmony_ciTEST_F(ScalarReplacementTest, TestUnimited) {
1535fd4e5da5Sopenharmony_ci  const std::string text = R"(
1536fd4e5da5Sopenharmony_ciOpCapability Shader
1537fd4e5da5Sopenharmony_ciOpCapability Linkage
1538fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
1539fd4e5da5Sopenharmony_ciOpName %6 "simple_struct"
1540fd4e5da5Sopenharmony_ci%1 = OpTypeVoid
1541fd4e5da5Sopenharmony_ci%2 = OpTypeInt 32 0
1542fd4e5da5Sopenharmony_ci%3 = OpTypeStruct %2 %2 %2 %2
1543fd4e5da5Sopenharmony_ci%4 = OpTypePointer Function %3
1544fd4e5da5Sopenharmony_ci%5 = OpTypePointer Function %2
1545fd4e5da5Sopenharmony_ci%6 = OpTypeFunction %2
1546fd4e5da5Sopenharmony_ci%7 = OpConstantNull %3
1547fd4e5da5Sopenharmony_ci%8 = OpConstant %2 0
1548fd4e5da5Sopenharmony_ci%9 = OpConstant %2 1
1549fd4e5da5Sopenharmony_ci%10 = OpConstant %2 2
1550fd4e5da5Sopenharmony_ci%11 = OpConstant %2 3
1551fd4e5da5Sopenharmony_ci%12 = OpFunction %2 None %6
1552fd4e5da5Sopenharmony_ci%13 = OpLabel
1553fd4e5da5Sopenharmony_ci%14 = OpVariable %4 Function %7
1554fd4e5da5Sopenharmony_ci%15 = OpInBoundsAccessChain %5 %14 %8
1555fd4e5da5Sopenharmony_ci%16 = OpLoad %2 %15
1556fd4e5da5Sopenharmony_ci%17 = OpAccessChain %5 %14 %10
1557fd4e5da5Sopenharmony_ci%18 = OpLoad %2 %17
1558fd4e5da5Sopenharmony_ci%19 = OpIAdd %2 %16 %18
1559fd4e5da5Sopenharmony_ciOpReturnValue %19
1560fd4e5da5Sopenharmony_ciOpFunctionEnd
1561fd4e5da5Sopenharmony_ci  )";
1562fd4e5da5Sopenharmony_ci
1563fd4e5da5Sopenharmony_ci  auto result =
1564fd4e5da5Sopenharmony_ci      SinglePassRunAndDisassemble<ScalarReplacementPass>(text, true, false, 0);
1565fd4e5da5Sopenharmony_ci  EXPECT_EQ(Pass::Status::SuccessWithChange, std::get<1>(result));
1566fd4e5da5Sopenharmony_ci}
1567fd4e5da5Sopenharmony_ci
1568fd4e5da5Sopenharmony_ciTEST_F(ScalarReplacementTest, AmbigousPointer) {
1569fd4e5da5Sopenharmony_ci  const std::string text = R"(
1570fd4e5da5Sopenharmony_ci; CHECK: [[s1:%\w+]] = OpTypeStruct %uint
1571fd4e5da5Sopenharmony_ci; CHECK: [[s2:%\w+]] = OpTypeStruct %uint
1572fd4e5da5Sopenharmony_ci; CHECK: [[s3:%\w+]] = OpTypeStruct [[s2]]
1573fd4e5da5Sopenharmony_ci; CHECK: [[s3_const:%\w+]] = OpConstantComposite [[s3]]
1574fd4e5da5Sopenharmony_ci; CHECK: [[s2_ptr:%\w+]] = OpTypePointer Function [[s2]]
1575fd4e5da5Sopenharmony_ci; CHECK: OpCompositeExtract [[s2]] [[s3_const]]
1576fd4e5da5Sopenharmony_ci
1577fd4e5da5Sopenharmony_ci               OpCapability Shader
1578fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
1579fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
1580fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %2 "main"
1581fd4e5da5Sopenharmony_ci               OpExecutionMode %2 OriginUpperLeft
1582fd4e5da5Sopenharmony_ci               OpSource ESSL 310
1583fd4e5da5Sopenharmony_ci       %void = OpTypeVoid
1584fd4e5da5Sopenharmony_ci          %5 = OpTypeFunction %void
1585fd4e5da5Sopenharmony_ci       %uint = OpTypeInt 32 0
1586fd4e5da5Sopenharmony_ci  %_struct_7 = OpTypeStruct %uint
1587fd4e5da5Sopenharmony_ci  %_struct_8 = OpTypeStruct %uint
1588fd4e5da5Sopenharmony_ci  %_struct_9 = OpTypeStruct %_struct_8
1589fd4e5da5Sopenharmony_ci     %uint_1 = OpConstant %uint 1
1590fd4e5da5Sopenharmony_ci         %11 = OpConstantComposite %_struct_8 %uint_1
1591fd4e5da5Sopenharmony_ci         %12 = OpConstantComposite %_struct_9 %11
1592fd4e5da5Sopenharmony_ci%_ptr_Function__struct_9 = OpTypePointer Function %_struct_9
1593fd4e5da5Sopenharmony_ci%_ptr_Function__struct_7 = OpTypePointer Function %_struct_7
1594fd4e5da5Sopenharmony_ci          %2 = OpFunction %void None %5
1595fd4e5da5Sopenharmony_ci         %15 = OpLabel
1596fd4e5da5Sopenharmony_ci        %var = OpVariable %_ptr_Function__struct_9 Function
1597fd4e5da5Sopenharmony_ci               OpStore %var %12
1598fd4e5da5Sopenharmony_ci         %ld = OpLoad %_struct_9 %var
1599fd4e5da5Sopenharmony_ci         %ex = OpCompositeExtract %_struct_8 %ld 0
1600fd4e5da5Sopenharmony_ci               OpReturn
1601fd4e5da5Sopenharmony_ci               OpFunctionEnd
1602fd4e5da5Sopenharmony_ci  )";
1603fd4e5da5Sopenharmony_ci
1604fd4e5da5Sopenharmony_ci  SinglePassRunAndMatch<ScalarReplacementPass>(text, true);
1605fd4e5da5Sopenharmony_ci}
1606fd4e5da5Sopenharmony_ci
1607fd4e5da5Sopenharmony_ci// Test that scalar replacement does not crash when there is an OpAccessChain
1608fd4e5da5Sopenharmony_ci// with no index.  If we choose to handle this case in the future, then the
1609fd4e5da5Sopenharmony_ci// result can change.
1610fd4e5da5Sopenharmony_ciTEST_F(ScalarReplacementTest, TestAccessChainWithNoIndexes) {
1611fd4e5da5Sopenharmony_ci  const std::string text = R"(
1612fd4e5da5Sopenharmony_ci               OpCapability Shader
1613fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
1614fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %1 "main"
1615fd4e5da5Sopenharmony_ci               OpExecutionMode %1 OriginLowerLeft
1616fd4e5da5Sopenharmony_ci       %void = OpTypeVoid
1617fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %void
1618fd4e5da5Sopenharmony_ci      %float = OpTypeFloat 32
1619fd4e5da5Sopenharmony_ci  %_struct_5 = OpTypeStruct %float
1620fd4e5da5Sopenharmony_ci%_ptr_Function__struct_5 = OpTypePointer Function %_struct_5
1621fd4e5da5Sopenharmony_ci          %1 = OpFunction %void None %3
1622fd4e5da5Sopenharmony_ci          %7 = OpLabel
1623fd4e5da5Sopenharmony_ci          %8 = OpVariable %_ptr_Function__struct_5 Function
1624fd4e5da5Sopenharmony_ci          %9 = OpAccessChain %_ptr_Function__struct_5 %8
1625fd4e5da5Sopenharmony_ci               OpReturn
1626fd4e5da5Sopenharmony_ci               OpFunctionEnd
1627fd4e5da5Sopenharmony_ci  )";
1628fd4e5da5Sopenharmony_ci
1629fd4e5da5Sopenharmony_ci  auto result =
1630fd4e5da5Sopenharmony_ci      SinglePassRunAndDisassemble<ScalarReplacementPass>(text, true, false);
1631fd4e5da5Sopenharmony_ci  EXPECT_EQ(Pass::Status::SuccessWithoutChange, std::get<1>(result));
1632fd4e5da5Sopenharmony_ci}
1633fd4e5da5Sopenharmony_ci
1634fd4e5da5Sopenharmony_ci// Test that id overflow is handled gracefully.
1635fd4e5da5Sopenharmony_ciTEST_F(ScalarReplacementTest, IdBoundOverflow1) {
1636fd4e5da5Sopenharmony_ci  const std::string text = R"(
1637fd4e5da5Sopenharmony_ciOpCapability ImageQuery
1638fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
1639fd4e5da5Sopenharmony_ciOpEntryPoint Fragment %4 "main"
1640fd4e5da5Sopenharmony_ciOpExecutionMode %4 OriginUpperLeft
1641fd4e5da5Sopenharmony_ciOpDecorate %4194302 DescriptorSet 1073495039
1642fd4e5da5Sopenharmony_ci%2 = OpTypeVoid
1643fd4e5da5Sopenharmony_ci%3 = OpTypeFunction %2
1644fd4e5da5Sopenharmony_ci%6 = OpTypeFloat 32
1645fd4e5da5Sopenharmony_ci%7 = OpTypeStruct %6 %6
1646fd4e5da5Sopenharmony_ci%557056 = OpTypeStruct %7
1647fd4e5da5Sopenharmony_ci%9 = OpTypePointer Function %7
1648fd4e5da5Sopenharmony_ci%18 = OpTypeFunction %7 %9
1649fd4e5da5Sopenharmony_ci%4 = OpFunction %2 Pure|Const %3
1650fd4e5da5Sopenharmony_ci%1836763 = OpLabel
1651fd4e5da5Sopenharmony_ci%4194302 = OpVariable %9 Function
1652fd4e5da5Sopenharmony_ci%10 = OpVariable %9 Function
1653fd4e5da5Sopenharmony_ciOpKill
1654fd4e5da5Sopenharmony_ci%4194301 = OpLabel
1655fd4e5da5Sopenharmony_ci%524296 = OpLoad %7 %4194302
1656fd4e5da5Sopenharmony_ciOpKill
1657fd4e5da5Sopenharmony_ciOpFunctionEnd
1658fd4e5da5Sopenharmony_ci  )";
1659fd4e5da5Sopenharmony_ci
1660fd4e5da5Sopenharmony_ci  SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
1661fd4e5da5Sopenharmony_ci
1662fd4e5da5Sopenharmony_ci  std::vector<Message> messages = {
1663fd4e5da5Sopenharmony_ci      {SPV_MSG_ERROR, "", 0, 0, "ID overflow. Try running compact-ids."},
1664fd4e5da5Sopenharmony_ci      {SPV_MSG_ERROR, "", 0, 0, "ID overflow. Try running compact-ids."}};
1665fd4e5da5Sopenharmony_ci  SetMessageConsumer(GetTestMessageConsumer(messages));
1666fd4e5da5Sopenharmony_ci  auto result = SinglePassRunToBinary<ScalarReplacementPass>(text, true, false);
1667fd4e5da5Sopenharmony_ci  EXPECT_EQ(Pass::Status::Failure, std::get<1>(result));
1668fd4e5da5Sopenharmony_ci}
1669fd4e5da5Sopenharmony_ci
1670fd4e5da5Sopenharmony_ci// Test that id overflow is handled gracefully.
1671fd4e5da5Sopenharmony_ciTEST_F(ScalarReplacementTest, IdBoundOverflow2) {
1672fd4e5da5Sopenharmony_ci  const std::string text = R"(
1673fd4e5da5Sopenharmony_ciOpCapability Shader
1674fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
1675fd4e5da5Sopenharmony_ciOpEntryPoint Fragment %4 "main" %17
1676fd4e5da5Sopenharmony_ciOpExecutionMode %4 OriginUpperLeft
1677fd4e5da5Sopenharmony_ci%2 = OpTypeVoid
1678fd4e5da5Sopenharmony_ci%3 = OpTypeFunction %2
1679fd4e5da5Sopenharmony_ci%6 = OpTypeFloat 32
1680fd4e5da5Sopenharmony_ci%7 = OpTypeVector %6 4
1681fd4e5da5Sopenharmony_ci%8 = OpTypeStruct %7
1682fd4e5da5Sopenharmony_ci%9 = OpTypePointer Function %8
1683fd4e5da5Sopenharmony_ci%16 = OpTypePointer Output %7
1684fd4e5da5Sopenharmony_ci%21 = OpTypeInt 32 1
1685fd4e5da5Sopenharmony_ci%22 = OpConstant %21 0
1686fd4e5da5Sopenharmony_ci%23 = OpTypePointer Function %7
1687fd4e5da5Sopenharmony_ci%17 = OpVariable %16 Output
1688fd4e5da5Sopenharmony_ci%4 = OpFunction %2 None %3
1689fd4e5da5Sopenharmony_ci%5 = OpLabel
1690fd4e5da5Sopenharmony_ci%4194300 = OpVariable %23 Function
1691fd4e5da5Sopenharmony_ci%10 = OpVariable %9 Function
1692fd4e5da5Sopenharmony_ci%4194301 = OpAccessChain %23 %10 %22
1693fd4e5da5Sopenharmony_ci%4194302 = OpLoad %7 %4194301
1694fd4e5da5Sopenharmony_ciOpStore %4194300 %4194302
1695fd4e5da5Sopenharmony_ci%15 = OpLoad %7 %4194300
1696fd4e5da5Sopenharmony_ciOpStore %17 %15
1697fd4e5da5Sopenharmony_ciOpReturn
1698fd4e5da5Sopenharmony_ciOpFunctionEnd
1699fd4e5da5Sopenharmony_ci  )";
1700fd4e5da5Sopenharmony_ci
1701fd4e5da5Sopenharmony_ci  SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
1702fd4e5da5Sopenharmony_ci
1703fd4e5da5Sopenharmony_ci  std::vector<Message> messages = {
1704fd4e5da5Sopenharmony_ci      {SPV_MSG_ERROR, "", 0, 0, "ID overflow. Try running compact-ids."}};
1705fd4e5da5Sopenharmony_ci  SetMessageConsumer(GetTestMessageConsumer(messages));
1706fd4e5da5Sopenharmony_ci  auto result = SinglePassRunToBinary<ScalarReplacementPass>(text, true, false);
1707fd4e5da5Sopenharmony_ci  EXPECT_EQ(Pass::Status::Failure, std::get<1>(result));
1708fd4e5da5Sopenharmony_ci}
1709fd4e5da5Sopenharmony_ci
1710fd4e5da5Sopenharmony_ci// Test that id overflow is handled gracefully.
1711fd4e5da5Sopenharmony_ciTEST_F(ScalarReplacementTest, IdBoundOverflow3) {
1712fd4e5da5Sopenharmony_ci  const std::string text = R"(
1713fd4e5da5Sopenharmony_ciOpCapability InterpolationFunction
1714fd4e5da5Sopenharmony_ciOpExtension "z"
1715fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
1716fd4e5da5Sopenharmony_ciOpEntryPoint Fragment %4 "main"
1717fd4e5da5Sopenharmony_ciOpExecutionMode %4 OriginUpperLeft
1718fd4e5da5Sopenharmony_ci%2 = OpTypeVoid
1719fd4e5da5Sopenharmony_ci%3 = OpTypeFunction %2
1720fd4e5da5Sopenharmony_ci%6 = OpTypeFloat 32
1721fd4e5da5Sopenharmony_ci%7 = OpTypeStruct %6 %6
1722fd4e5da5Sopenharmony_ci%9 = OpTypePointer Function %7
1723fd4e5da5Sopenharmony_ci%18 = OpTypeFunction %7 %9
1724fd4e5da5Sopenharmony_ci%21 = OpTypeInt 32 0
1725fd4e5da5Sopenharmony_ci%22 = OpConstant %21 4293000676
1726fd4e5da5Sopenharmony_ci%4194302 = OpConstantNull %6
1727fd4e5da5Sopenharmony_ci%4 = OpFunction %2 Inline|Pure %3
1728fd4e5da5Sopenharmony_ci%786464 = OpLabel
1729fd4e5da5Sopenharmony_ci%4194298 = OpVariable %9 Function
1730fd4e5da5Sopenharmony_ci%10 = OpVariable %9 Function
1731fd4e5da5Sopenharmony_ci%4194299 = OpUDiv %21 %22 %22
1732fd4e5da5Sopenharmony_ci%4194300 = OpLoad %7 %10
1733fd4e5da5Sopenharmony_ci%50959 = OpLoad %7 %4194298
1734fd4e5da5Sopenharmony_ciOpKill
1735fd4e5da5Sopenharmony_ciOpFunctionEnd
1736fd4e5da5Sopenharmony_ci%1 = OpFunction %7 None %18
1737fd4e5da5Sopenharmony_ci%19 = OpFunctionParameter %9
1738fd4e5da5Sopenharmony_ci%147667 = OpLabel
1739fd4e5da5Sopenharmony_ci%2044391 = OpUDiv %21 %22 %22
1740fd4e5da5Sopenharmony_ci%25 = OpLoad %7 %19
1741fd4e5da5Sopenharmony_ciOpReturnValue %25
1742fd4e5da5Sopenharmony_ciOpFunctionEnd
1743fd4e5da5Sopenharmony_ci%4194295 = OpFunction %2 None %3
1744fd4e5da5Sopenharmony_ci%4194296 = OpLabel
1745fd4e5da5Sopenharmony_ciOpKill
1746fd4e5da5Sopenharmony_ciOpFunctionEnd
1747fd4e5da5Sopenharmony_ci  )";
1748fd4e5da5Sopenharmony_ci
1749fd4e5da5Sopenharmony_ci  SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
1750fd4e5da5Sopenharmony_ci
1751fd4e5da5Sopenharmony_ci  std::vector<Message> messages = {
1752fd4e5da5Sopenharmony_ci      {SPV_MSG_ERROR, "", 0, 0, "ID overflow. Try running compact-ids."},
1753fd4e5da5Sopenharmony_ci      {SPV_MSG_ERROR, "", 0, 0, "ID overflow. Try running compact-ids."},
1754fd4e5da5Sopenharmony_ci      {SPV_MSG_ERROR, "", 0, 0, "ID overflow. Try running compact-ids."},
1755fd4e5da5Sopenharmony_ci      {SPV_MSG_ERROR, "", 0, 0, "ID overflow. Try running compact-ids."},
1756fd4e5da5Sopenharmony_ci      {SPV_MSG_ERROR, "", 0, 0, "ID overflow. Try running compact-ids."},
1757fd4e5da5Sopenharmony_ci      {SPV_MSG_ERROR, "", 0, 0, "ID overflow. Try running compact-ids."},
1758fd4e5da5Sopenharmony_ci      {SPV_MSG_ERROR, "", 0, 0, "ID overflow. Try running compact-ids."},
1759fd4e5da5Sopenharmony_ci      {SPV_MSG_ERROR, "", 0, 0, "ID overflow. Try running compact-ids."},
1760fd4e5da5Sopenharmony_ci      {SPV_MSG_ERROR, "", 0, 0, "ID overflow. Try running compact-ids."}};
1761fd4e5da5Sopenharmony_ci  SetMessageConsumer(GetTestMessageConsumer(messages));
1762fd4e5da5Sopenharmony_ci  auto result = SinglePassRunToBinary<ScalarReplacementPass>(text, true, false);
1763fd4e5da5Sopenharmony_ci  EXPECT_EQ(Pass::Status::Failure, std::get<1>(result));
1764fd4e5da5Sopenharmony_ci}
1765fd4e5da5Sopenharmony_ci
1766fd4e5da5Sopenharmony_ci// Test that replacements for OpAccessChain do not go out of bounds.
1767fd4e5da5Sopenharmony_ci// https://github.com/KhronosGroup/SPIRV-Tools/issues/2609.
1768fd4e5da5Sopenharmony_ciTEST_F(ScalarReplacementTest, OutOfBoundOpAccessChain) {
1769fd4e5da5Sopenharmony_ci  const std::string text = R"(
1770fd4e5da5Sopenharmony_ci               OpCapability Shader
1771fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
1772fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
1773fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %main "main" %_GLF_color
1774fd4e5da5Sopenharmony_ci               OpExecutionMode %main OriginUpperLeft
1775fd4e5da5Sopenharmony_ci               OpSource ESSL 310
1776fd4e5da5Sopenharmony_ci               OpName %main "main"
1777fd4e5da5Sopenharmony_ci               OpName %a "a"
1778fd4e5da5Sopenharmony_ci               OpName %_GLF_color "_GLF_color"
1779fd4e5da5Sopenharmony_ci               OpDecorate %_GLF_color Location 0
1780fd4e5da5Sopenharmony_ci       %void = OpTypeVoid
1781fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %void
1782fd4e5da5Sopenharmony_ci        %int = OpTypeInt 32 1
1783fd4e5da5Sopenharmony_ci%_ptr_Function_int = OpTypePointer Function %int
1784fd4e5da5Sopenharmony_ci      %int_1 = OpConstant %int 1
1785fd4e5da5Sopenharmony_ci      %float = OpTypeFloat 32
1786fd4e5da5Sopenharmony_ci       %uint = OpTypeInt 32 0
1787fd4e5da5Sopenharmony_ci     %uint_1 = OpConstant %uint 1
1788fd4e5da5Sopenharmony_ci%_arr_float_uint_1 = OpTypeArray %float %uint_1
1789fd4e5da5Sopenharmony_ci%_ptr_Function__arr_float_uint_1 = OpTypePointer Function %_arr_float_uint_1
1790fd4e5da5Sopenharmony_ci%_ptr_Function_float = OpTypePointer Function %float
1791fd4e5da5Sopenharmony_ci%_ptr_Output_float = OpTypePointer Output %float
1792fd4e5da5Sopenharmony_ci %_GLF_color = OpVariable %_ptr_Output_float Output
1793fd4e5da5Sopenharmony_ci       %main = OpFunction %void None %3
1794fd4e5da5Sopenharmony_ci          %5 = OpLabel
1795fd4e5da5Sopenharmony_ci          %a = OpVariable %_ptr_Function__arr_float_uint_1 Function
1796fd4e5da5Sopenharmony_ci         %21 = OpAccessChain %_ptr_Function_float %a %int_1
1797fd4e5da5Sopenharmony_ci         %22 = OpLoad %float %21
1798fd4e5da5Sopenharmony_ci               OpStore %_GLF_color %22
1799fd4e5da5Sopenharmony_ci               OpReturn
1800fd4e5da5Sopenharmony_ci               OpFunctionEnd
1801fd4e5da5Sopenharmony_ci  )";
1802fd4e5da5Sopenharmony_ci
1803fd4e5da5Sopenharmony_ci  SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
1804fd4e5da5Sopenharmony_ci
1805fd4e5da5Sopenharmony_ci  auto result =
1806fd4e5da5Sopenharmony_ci      SinglePassRunAndDisassemble<ScalarReplacementPass>(text, true, false);
1807fd4e5da5Sopenharmony_ci  EXPECT_EQ(Pass::Status::SuccessWithoutChange, std::get<1>(result));
1808fd4e5da5Sopenharmony_ci}
1809fd4e5da5Sopenharmony_ci
1810fd4e5da5Sopenharmony_ciTEST_F(ScalarReplacementTest, CharIndex) {
1811fd4e5da5Sopenharmony_ci  const std::string text = R"(
1812fd4e5da5Sopenharmony_ci; CHECK: [[int:%\w+]] = OpTypeInt 32 0
1813fd4e5da5Sopenharmony_ci; CHECK: [[ptr:%\w+]] = OpTypePointer Function [[int]]
1814fd4e5da5Sopenharmony_ci; CHECK: OpVariable [[ptr]] Function
1815fd4e5da5Sopenharmony_ciOpCapability Shader
1816fd4e5da5Sopenharmony_ciOpCapability Int8
1817fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
1818fd4e5da5Sopenharmony_ciOpEntryPoint GLCompute %main "main"
1819fd4e5da5Sopenharmony_ciOpExecutionMode %main LocalSize 1 1 1
1820fd4e5da5Sopenharmony_ci%void = OpTypeVoid
1821fd4e5da5Sopenharmony_ci%int = OpTypeInt 32 0
1822fd4e5da5Sopenharmony_ci%int_1024 = OpConstant %int 1024
1823fd4e5da5Sopenharmony_ci%char = OpTypeInt 8 0
1824fd4e5da5Sopenharmony_ci%char_1 = OpConstant %char 1
1825fd4e5da5Sopenharmony_ci%array = OpTypeArray %int %int_1024
1826fd4e5da5Sopenharmony_ci%ptr_func_array = OpTypePointer Function %array
1827fd4e5da5Sopenharmony_ci%ptr_func_int = OpTypePointer Function %int
1828fd4e5da5Sopenharmony_ci%void_fn = OpTypeFunction %void
1829fd4e5da5Sopenharmony_ci%main = OpFunction %void None %void_fn
1830fd4e5da5Sopenharmony_ci%entry = OpLabel
1831fd4e5da5Sopenharmony_ci%var = OpVariable %ptr_func_array Function
1832fd4e5da5Sopenharmony_ci%gep = OpAccessChain %ptr_func_int %var %char_1
1833fd4e5da5Sopenharmony_ciOpStore %gep %int_1024
1834fd4e5da5Sopenharmony_ciOpReturn
1835fd4e5da5Sopenharmony_ciOpFunctionEnd
1836fd4e5da5Sopenharmony_ci)";
1837fd4e5da5Sopenharmony_ci
1838fd4e5da5Sopenharmony_ci  SinglePassRunAndMatch<ScalarReplacementPass>(text, true, 0);
1839fd4e5da5Sopenharmony_ci}
1840fd4e5da5Sopenharmony_ci
1841fd4e5da5Sopenharmony_ciTEST_F(ScalarReplacementTest, OutOfBoundsOpAccessChainNegative) {
1842fd4e5da5Sopenharmony_ci  const std::string text = R"(
1843fd4e5da5Sopenharmony_ciOpCapability Shader
1844fd4e5da5Sopenharmony_ciOpCapability Int8
1845fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
1846fd4e5da5Sopenharmony_ciOpEntryPoint GLCompute %main "main"
1847fd4e5da5Sopenharmony_ciOpExecutionMode %main LocalSize 1 1 1
1848fd4e5da5Sopenharmony_ci%void = OpTypeVoid
1849fd4e5da5Sopenharmony_ci%int = OpTypeInt 32 0
1850fd4e5da5Sopenharmony_ci%int_1024 = OpConstant %int 1024
1851fd4e5da5Sopenharmony_ci%char = OpTypeInt 8 1
1852fd4e5da5Sopenharmony_ci%char_n1 = OpConstant %char -1
1853fd4e5da5Sopenharmony_ci%array = OpTypeArray %int %int_1024
1854fd4e5da5Sopenharmony_ci%ptr_func_array = OpTypePointer Function %array
1855fd4e5da5Sopenharmony_ci%ptr_func_int = OpTypePointer Function %int
1856fd4e5da5Sopenharmony_ci%void_fn = OpTypeFunction %void
1857fd4e5da5Sopenharmony_ci%main = OpFunction %void None %void_fn
1858fd4e5da5Sopenharmony_ci%entry = OpLabel
1859fd4e5da5Sopenharmony_ci%var = OpVariable %ptr_func_array Function
1860fd4e5da5Sopenharmony_ci%gep = OpAccessChain %ptr_func_int %var %char_n1
1861fd4e5da5Sopenharmony_ciOpStore %gep %int_1024
1862fd4e5da5Sopenharmony_ciOpReturn
1863fd4e5da5Sopenharmony_ciOpFunctionEnd
1864fd4e5da5Sopenharmony_ci)";
1865fd4e5da5Sopenharmony_ci
1866fd4e5da5Sopenharmony_ci  auto result =
1867fd4e5da5Sopenharmony_ci      SinglePassRunAndDisassemble<ScalarReplacementPass>(text, true, true, 0);
1868fd4e5da5Sopenharmony_ci  EXPECT_EQ(Pass::Status::SuccessWithoutChange, std::get<1>(result));
1869fd4e5da5Sopenharmony_ci}
1870fd4e5da5Sopenharmony_ci
1871fd4e5da5Sopenharmony_ciTEST_F(ScalarReplacementTest, RelaxedPrecisionMemberDecoration) {
1872fd4e5da5Sopenharmony_ci  const std::string text = R"(
1873fd4e5da5Sopenharmony_ci; CHECK: OpDecorate {{%\w+}} RelaxedPrecision
1874fd4e5da5Sopenharmony_ci; CHECK: OpDecorate [[new_var:%\w+]] RelaxedPrecision
1875fd4e5da5Sopenharmony_ci; CHECK: [[new_var]] = OpVariable %_ptr_Function_v3float Function
1876fd4e5da5Sopenharmony_ci; CHECK: OpLoad %v3float [[new_var]]
1877fd4e5da5Sopenharmony_ci               OpCapability Shader
1878fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
1879fd4e5da5Sopenharmony_ci               OpEntryPoint Vertex %1 "Draw2DTexCol_VS" %2 %3
1880fd4e5da5Sopenharmony_ci               OpSource HLSL 600
1881fd4e5da5Sopenharmony_ci               OpDecorate %2 Location 0
1882fd4e5da5Sopenharmony_ci               OpDecorate %3 Location 1
1883fd4e5da5Sopenharmony_ci               OpDecorate %3 RelaxedPrecision
1884fd4e5da5Sopenharmony_ci               OpMemberDecorate %_struct_4 1 RelaxedPrecision
1885fd4e5da5Sopenharmony_ci      %float = OpTypeFloat 32
1886fd4e5da5Sopenharmony_ci        %int = OpTypeInt 32 1
1887fd4e5da5Sopenharmony_ci      %int_1 = OpConstant %int 1
1888fd4e5da5Sopenharmony_ci    %v3float = OpTypeVector %float 3
1889fd4e5da5Sopenharmony_ci%_ptr_Input_v3float = OpTypePointer Input %v3float
1890fd4e5da5Sopenharmony_ci       %void = OpTypeVoid
1891fd4e5da5Sopenharmony_ci         %11 = OpTypeFunction %void
1892fd4e5da5Sopenharmony_ci  %_struct_4 = OpTypeStruct %v3float %v3float
1893fd4e5da5Sopenharmony_ci%_ptr_Function__struct_4 = OpTypePointer Function %_struct_4
1894fd4e5da5Sopenharmony_ci%_ptr_Function_v3float = OpTypePointer Function %v3float
1895fd4e5da5Sopenharmony_ci          %2 = OpVariable %_ptr_Input_v3float Input
1896fd4e5da5Sopenharmony_ci          %3 = OpVariable %_ptr_Input_v3float Input
1897fd4e5da5Sopenharmony_ci          %1 = OpFunction %void None %11
1898fd4e5da5Sopenharmony_ci         %14 = OpLabel
1899fd4e5da5Sopenharmony_ci         %15 = OpVariable %_ptr_Function__struct_4 Function
1900fd4e5da5Sopenharmony_ci         %16 = OpLoad %v3float %2
1901fd4e5da5Sopenharmony_ci         %17 = OpLoad %v3float %3
1902fd4e5da5Sopenharmony_ci         %18 = OpCompositeConstruct %_struct_4 %16 %17
1903fd4e5da5Sopenharmony_ci               OpStore %15 %18
1904fd4e5da5Sopenharmony_ci         %19 = OpAccessChain %_ptr_Function_v3float %15 %int_1
1905fd4e5da5Sopenharmony_ci         %20 = OpLoad %v3float %19
1906fd4e5da5Sopenharmony_ci               OpReturn
1907fd4e5da5Sopenharmony_ci               OpFunctionEnd
1908fd4e5da5Sopenharmony_ci)";
1909fd4e5da5Sopenharmony_ci
1910fd4e5da5Sopenharmony_ci  SinglePassRunAndMatch<ScalarReplacementPass>(text, true);
1911fd4e5da5Sopenharmony_ci}
1912fd4e5da5Sopenharmony_ci
1913fd4e5da5Sopenharmony_ciTEST_F(ScalarReplacementTest, DebugDeclare) {
1914fd4e5da5Sopenharmony_ci  const std::string text = R"(
1915fd4e5da5Sopenharmony_ciOpCapability Shader
1916fd4e5da5Sopenharmony_ciOpCapability Linkage
1917fd4e5da5Sopenharmony_ci%ext = OpExtInstImport "OpenCL.DebugInfo.100"
1918fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
1919fd4e5da5Sopenharmony_ci%test = OpString "test"
1920fd4e5da5Sopenharmony_ciOpName %6 "simple_struct"
1921fd4e5da5Sopenharmony_ci%1 = OpTypeVoid
1922fd4e5da5Sopenharmony_ci%2 = OpTypeInt 32 0
1923fd4e5da5Sopenharmony_ci%uint_32 = OpConstant %2 32
1924fd4e5da5Sopenharmony_ci%3 = OpTypeStruct %2 %2 %2 %2
1925fd4e5da5Sopenharmony_ci%4 = OpTypePointer Function %3
1926fd4e5da5Sopenharmony_ci%5 = OpTypePointer Function %2
1927fd4e5da5Sopenharmony_ci%6 = OpTypeFunction %2
1928fd4e5da5Sopenharmony_ci%7 = OpConstantNull %3
1929fd4e5da5Sopenharmony_ci%8 = OpConstant %2 0
1930fd4e5da5Sopenharmony_ci%9 = OpConstant %2 1
1931fd4e5da5Sopenharmony_ci%10 = OpConstant %2 2
1932fd4e5da5Sopenharmony_ci%11 = OpConstant %2 3
1933fd4e5da5Sopenharmony_ci%null_expr = OpExtInst %1 %ext DebugExpression
1934fd4e5da5Sopenharmony_ci%src = OpExtInst %1 %ext DebugSource %test
1935fd4e5da5Sopenharmony_ci%cu = OpExtInst %1 %ext DebugCompilationUnit 1 4 %src HLSL
1936fd4e5da5Sopenharmony_ci%dbg_tf = OpExtInst %1 %ext DebugTypeBasic %test %uint_32 Float
1937fd4e5da5Sopenharmony_ci%main_ty = OpExtInst %1 %ext DebugTypeFunction FlagIsProtected|FlagIsPrivate %1
1938fd4e5da5Sopenharmony_ci%dbg_main = OpExtInst %1 %ext DebugFunction %test %main_ty %src 0 0 %cu %test FlagIsProtected|FlagIsPrivate 0 %12
1939fd4e5da5Sopenharmony_ci%dbg_foo = OpExtInst %1 %ext DebugLocalVariable %test %dbg_tf %src 0 0 %dbg_main FlagIsLocal
1940fd4e5da5Sopenharmony_ci%12 = OpFunction %2 None %6
1941fd4e5da5Sopenharmony_ci%13 = OpLabel
1942fd4e5da5Sopenharmony_ci%scope = OpExtInst %1 %ext DebugScope %dbg_main
1943fd4e5da5Sopenharmony_ci%14 = OpVariable %4 Function %7
1944fd4e5da5Sopenharmony_ci
1945fd4e5da5Sopenharmony_ci; CHECK: [[deref:%\w+]] = OpExtInst %void [[ext:%\w+]] DebugOperation Deref
1946fd4e5da5Sopenharmony_ci; CHECK: [[dbg_local_var:%\w+]] = OpExtInst %void [[ext]] DebugLocalVariable
1947fd4e5da5Sopenharmony_ci; CHECK: [[deref_expr:%\w+]] = OpExtInst %void [[ext]] DebugExpression [[deref]]
1948fd4e5da5Sopenharmony_ci; CHECK: [[repl3:%\w+]] = OpVariable %_ptr_Function_uint Function
1949fd4e5da5Sopenharmony_ci; CHECK: [[repl2:%\w+]] = OpVariable %_ptr_Function_uint Function
1950fd4e5da5Sopenharmony_ci; CHECK: [[repl1:%\w+]] = OpVariable %_ptr_Function_uint Function
1951fd4e5da5Sopenharmony_ci; CHECK: [[repl0:%\w+]] = OpVariable %_ptr_Function_uint Function
1952fd4e5da5Sopenharmony_ci; CHECK: OpExtInst %void [[ext]] DebugValue [[dbg_local_var]] [[repl3]] [[deref_expr]] %int_3
1953fd4e5da5Sopenharmony_ci; CHECK: OpExtInst %void [[ext]] DebugValue [[dbg_local_var]] [[repl2]] [[deref_expr]] %int_2
1954fd4e5da5Sopenharmony_ci; CHECK: OpExtInst %void [[ext]] DebugValue [[dbg_local_var]] [[repl1]] [[deref_expr]] %int_1
1955fd4e5da5Sopenharmony_ci; CHECK: OpExtInst %void [[ext]] DebugValue [[dbg_local_var]] [[repl0]] [[deref_expr]] %int_0
1956fd4e5da5Sopenharmony_ci; CHECK-NOT: DebugDeclare
1957fd4e5da5Sopenharmony_ci%decl = OpExtInst %1 %ext DebugDeclare %dbg_foo %14 %null_expr
1958fd4e5da5Sopenharmony_ci
1959fd4e5da5Sopenharmony_ci%15 = OpInBoundsAccessChain %5 %14 %8
1960fd4e5da5Sopenharmony_ci%16 = OpLoad %2 %15
1961fd4e5da5Sopenharmony_ci%17 = OpAccessChain %5 %14 %10
1962fd4e5da5Sopenharmony_ci%18 = OpLoad %2 %17
1963fd4e5da5Sopenharmony_ci%19 = OpIAdd %2 %16 %18
1964fd4e5da5Sopenharmony_ciOpReturnValue %19
1965fd4e5da5Sopenharmony_ciOpFunctionEnd
1966fd4e5da5Sopenharmony_ci)";
1967fd4e5da5Sopenharmony_ci
1968fd4e5da5Sopenharmony_ci  SinglePassRunAndMatch<ScalarReplacementPass>(text, true);
1969fd4e5da5Sopenharmony_ci}
1970fd4e5da5Sopenharmony_ci
1971fd4e5da5Sopenharmony_ciTEST_F(ScalarReplacementTest, DebugValue) {
1972fd4e5da5Sopenharmony_ci  const std::string text = R"(
1973fd4e5da5Sopenharmony_ciOpCapability Shader
1974fd4e5da5Sopenharmony_ciOpCapability Linkage
1975fd4e5da5Sopenharmony_ci%ext = OpExtInstImport "OpenCL.DebugInfo.100"
1976fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
1977fd4e5da5Sopenharmony_ci%test = OpString "test"
1978fd4e5da5Sopenharmony_ciOpName %6 "simple_struct"
1979fd4e5da5Sopenharmony_ci%1 = OpTypeVoid
1980fd4e5da5Sopenharmony_ci%2 = OpTypeInt 32 0
1981fd4e5da5Sopenharmony_ci%uint_32 = OpConstant %2 32
1982fd4e5da5Sopenharmony_ci%3 = OpTypeStruct %2 %2 %2 %2
1983fd4e5da5Sopenharmony_ci%4 = OpTypePointer Function %3
1984fd4e5da5Sopenharmony_ci%5 = OpTypePointer Function %2
1985fd4e5da5Sopenharmony_ci%6 = OpTypeFunction %2
1986fd4e5da5Sopenharmony_ci%7 = OpConstantNull %3
1987fd4e5da5Sopenharmony_ci%8 = OpConstant %2 0
1988fd4e5da5Sopenharmony_ci%9 = OpConstant %2 1
1989fd4e5da5Sopenharmony_ci%10 = OpConstant %2 2
1990fd4e5da5Sopenharmony_ci%11 = OpConstant %2 3
1991fd4e5da5Sopenharmony_ci%deref = OpExtInst %1 %ext DebugOperation Deref
1992fd4e5da5Sopenharmony_ci%deref_expr = OpExtInst %1 %ext DebugExpression %deref
1993fd4e5da5Sopenharmony_ci%null_expr = OpExtInst %1 %ext DebugExpression
1994fd4e5da5Sopenharmony_ci%src = OpExtInst %1 %ext DebugSource %test
1995fd4e5da5Sopenharmony_ci%cu = OpExtInst %1 %ext DebugCompilationUnit 1 4 %src HLSL
1996fd4e5da5Sopenharmony_ci%dbg_tf = OpExtInst %1 %ext DebugTypeBasic %test %uint_32 Float
1997fd4e5da5Sopenharmony_ci%main_ty = OpExtInst %1 %ext DebugTypeFunction FlagIsProtected|FlagIsPrivate %1
1998fd4e5da5Sopenharmony_ci%dbg_main = OpExtInst %1 %ext DebugFunction %test %main_ty %src 0 0 %cu %test FlagIsProtected|FlagIsPrivate 0 %12
1999fd4e5da5Sopenharmony_ci%dbg_foo = OpExtInst %1 %ext DebugLocalVariable %test %dbg_tf %src 0 0 %dbg_main FlagIsLocal
2000fd4e5da5Sopenharmony_ci%12 = OpFunction %2 None %6
2001fd4e5da5Sopenharmony_ci%13 = OpLabel
2002fd4e5da5Sopenharmony_ci%scope = OpExtInst %1 %ext DebugScope %dbg_main
2003fd4e5da5Sopenharmony_ci%14 = OpVariable %4 Function %7
2004fd4e5da5Sopenharmony_ci
2005fd4e5da5Sopenharmony_ci; CHECK: [[deref:%\w+]] = OpExtInst %void [[ext:%\w+]] DebugOperation Deref
2006fd4e5da5Sopenharmony_ci; CHECK: [[deref_expr:%\w+]] = OpExtInst %void [[ext]] DebugExpression [[deref]]
2007fd4e5da5Sopenharmony_ci; CHECK: [[dbg_local_var:%\w+]] = OpExtInst %void [[ext]] DebugLocalVariable
2008fd4e5da5Sopenharmony_ci; CHECK: [[repl3:%\w+]] = OpVariable %_ptr_Function_uint Function
2009fd4e5da5Sopenharmony_ci; CHECK: [[repl2:%\w+]] = OpVariable %_ptr_Function_uint Function
2010fd4e5da5Sopenharmony_ci; CHECK: [[repl1:%\w+]] = OpVariable %_ptr_Function_uint Function
2011fd4e5da5Sopenharmony_ci; CHECK: [[repl0:%\w+]] = OpVariable %_ptr_Function_uint Function
2012fd4e5da5Sopenharmony_ci; CHECK: OpExtInst %void [[ext]] DebugValue [[dbg_local_var]] [[repl0]] [[deref_expr]] %int_0
2013fd4e5da5Sopenharmony_ci; CHECK: OpExtInst %void [[ext]] DebugValue [[dbg_local_var]] [[repl1]] [[deref_expr]] %int_1
2014fd4e5da5Sopenharmony_ci; CHECK: OpExtInst %void [[ext]] DebugValue [[dbg_local_var]] [[repl2]] [[deref_expr]] %int_2
2015fd4e5da5Sopenharmony_ci; CHECK: OpExtInst %void [[ext]] DebugValue [[dbg_local_var]] [[repl3]] [[deref_expr]] %int_3
2016fd4e5da5Sopenharmony_ci%value = OpExtInst %1 %ext DebugValue %dbg_foo %14 %deref_expr
2017fd4e5da5Sopenharmony_ci
2018fd4e5da5Sopenharmony_ci%15 = OpInBoundsAccessChain %5 %14 %8
2019fd4e5da5Sopenharmony_ci%16 = OpLoad %2 %15
2020fd4e5da5Sopenharmony_ci%17 = OpAccessChain %5 %14 %10
2021fd4e5da5Sopenharmony_ci%18 = OpLoad %2 %17
2022fd4e5da5Sopenharmony_ci%19 = OpIAdd %2 %16 %18
2023fd4e5da5Sopenharmony_ciOpReturnValue %19
2024fd4e5da5Sopenharmony_ciOpFunctionEnd
2025fd4e5da5Sopenharmony_ci)";
2026fd4e5da5Sopenharmony_ci
2027fd4e5da5Sopenharmony_ci  SinglePassRunAndMatch<ScalarReplacementPass>(text, true);
2028fd4e5da5Sopenharmony_ci}
2029fd4e5da5Sopenharmony_ci
2030fd4e5da5Sopenharmony_ciTEST_F(ScalarReplacementTest, DebugDeclareRecursive) {
2031fd4e5da5Sopenharmony_ci  const std::string text = R"(
2032fd4e5da5Sopenharmony_ciOpCapability Shader
2033fd4e5da5Sopenharmony_ciOpCapability Linkage
2034fd4e5da5Sopenharmony_ci%ext = OpExtInstImport "OpenCL.DebugInfo.100"
2035fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
2036fd4e5da5Sopenharmony_ci%test = OpString "test"
2037fd4e5da5Sopenharmony_ciOpName %6 "simple_struct"
2038fd4e5da5Sopenharmony_ci%1 = OpTypeVoid
2039fd4e5da5Sopenharmony_ci%2 = OpTypeInt 32 0
2040fd4e5da5Sopenharmony_ci%uint_32 = OpConstant %2 32
2041fd4e5da5Sopenharmony_ci%float = OpTypeFloat 32
2042fd4e5da5Sopenharmony_ci%float_1 = OpConstant %float 1
2043fd4e5da5Sopenharmony_ci%member = OpTypeStruct %2 %float
2044fd4e5da5Sopenharmony_ci%3 = OpTypeStruct %2 %member %float
2045fd4e5da5Sopenharmony_ci%4 = OpTypePointer Function %3
2046fd4e5da5Sopenharmony_ci%5 = OpTypePointer Function %2
2047fd4e5da5Sopenharmony_ci%ptr_float_Function = OpTypePointer Function %float
2048fd4e5da5Sopenharmony_ci%6 = OpTypeFunction %2
2049fd4e5da5Sopenharmony_ci%cmember = OpConstantComposite %member %uint_32 %float_1
2050fd4e5da5Sopenharmony_ci%7 = OpConstantComposite %3 %uint_32 %cmember %float_1
2051fd4e5da5Sopenharmony_ci%8 = OpConstant %2 0
2052fd4e5da5Sopenharmony_ci%9 = OpConstant %2 1
2053fd4e5da5Sopenharmony_ci%10 = OpConstant %2 2
2054fd4e5da5Sopenharmony_ci%null_expr = OpExtInst %1 %ext DebugExpression
2055fd4e5da5Sopenharmony_ci%src = OpExtInst %1 %ext DebugSource %test
2056fd4e5da5Sopenharmony_ci%cu = OpExtInst %1 %ext DebugCompilationUnit 1 4 %src HLSL
2057fd4e5da5Sopenharmony_ci%dbg_tf = OpExtInst %1 %ext DebugTypeBasic %test %uint_32 Float
2058fd4e5da5Sopenharmony_ci%main_ty = OpExtInst %1 %ext DebugTypeFunction FlagIsProtected|FlagIsPrivate %1
2059fd4e5da5Sopenharmony_ci%dbg_main = OpExtInst %1 %ext DebugFunction %test %main_ty %src 0 0 %cu %test FlagIsProtected|FlagIsPrivate 0 %12
2060fd4e5da5Sopenharmony_ci%dbg_foo = OpExtInst %1 %ext DebugLocalVariable %test %dbg_tf %src 0 0 %dbg_main FlagIsLocal
2061fd4e5da5Sopenharmony_ci%12 = OpFunction %2 None %6
2062fd4e5da5Sopenharmony_ci%13 = OpLabel
2063fd4e5da5Sopenharmony_ci%scope = OpExtInst %1 %ext DebugScope %dbg_main
2064fd4e5da5Sopenharmony_ci%14 = OpVariable %4 Function %7
2065fd4e5da5Sopenharmony_ci
2066fd4e5da5Sopenharmony_ci; CHECK: [[deref:%\w+]] = OpExtInst %void [[ext:%\w+]] DebugOperation Deref
2067fd4e5da5Sopenharmony_ci; CHECK: [[dbg_local_var:%\w+]] = OpExtInst %void [[ext]] DebugLocalVariable
2068fd4e5da5Sopenharmony_ci; CHECK: [[deref_expr:%\w+]] = OpExtInst %void [[ext]] DebugExpression [[deref]]
2069fd4e5da5Sopenharmony_ci; CHECK: [[repl2:%\w+]] = OpVariable %_ptr_Function_float Function %float_1
2070fd4e5da5Sopenharmony_ci; CHECK: [[repl1:%\w+]] = OpVariable %_ptr_Function_uint Function %uint_32
2071fd4e5da5Sopenharmony_ci; CHECK: [[repl3:%\w+]] = OpVariable %_ptr_Function_float Function %float_1
2072fd4e5da5Sopenharmony_ci; CHECK: [[repl0:%\w+]] = OpVariable %_ptr_Function_uint Function %uint_32
2073fd4e5da5Sopenharmony_ci; CHECK: OpExtInst %void [[ext]] DebugValue [[dbg_local_var]] [[repl3]] [[deref_expr]] %int_2
2074fd4e5da5Sopenharmony_ci; CHECK: OpExtInst %void [[ext]] DebugValue [[dbg_local_var]] [[repl1]] [[deref_expr]] %int_1 %int_0
2075fd4e5da5Sopenharmony_ci; CHECK: OpExtInst %void [[ext]] DebugValue [[dbg_local_var]] [[repl2]] [[deref_expr]] %int_1 %int_1
2076fd4e5da5Sopenharmony_ci; CHECK: OpExtInst %void [[ext]] DebugValue [[dbg_local_var]] [[repl0]] [[deref_expr]] %int_0
2077fd4e5da5Sopenharmony_ci; CHECK-NOT: DebugDeclare
2078fd4e5da5Sopenharmony_ci%decl = OpExtInst %1 %ext DebugDeclare %dbg_foo %14 %null_expr
2079fd4e5da5Sopenharmony_ci
2080fd4e5da5Sopenharmony_ci%15 = OpInBoundsAccessChain %5 %14 %8
2081fd4e5da5Sopenharmony_ci%16 = OpLoad %2 %15
2082fd4e5da5Sopenharmony_ci%17 = OpAccessChain %ptr_float_Function %14 %10
2083fd4e5da5Sopenharmony_ci%18 = OpLoad %float %17
2084fd4e5da5Sopenharmony_ci%value = OpConvertFToU %2 %18
2085fd4e5da5Sopenharmony_ci%19 = OpIAdd %2 %16 %value
2086fd4e5da5Sopenharmony_ciOpReturnValue %19
2087fd4e5da5Sopenharmony_ciOpFunctionEnd
2088fd4e5da5Sopenharmony_ci)";
2089fd4e5da5Sopenharmony_ci
2090fd4e5da5Sopenharmony_ci  SinglePassRunAndMatch<ScalarReplacementPass>(text, true);
2091fd4e5da5Sopenharmony_ci}
2092fd4e5da5Sopenharmony_ci
2093fd4e5da5Sopenharmony_ciTEST_F(ScalarReplacementTest, DebugValueWithIndex) {
2094fd4e5da5Sopenharmony_ci  const std::string text = R"(
2095fd4e5da5Sopenharmony_ciOpCapability Shader
2096fd4e5da5Sopenharmony_ciOpCapability Linkage
2097fd4e5da5Sopenharmony_ci%ext = OpExtInstImport "OpenCL.DebugInfo.100"
2098fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
2099fd4e5da5Sopenharmony_ci%test = OpString "test"
2100fd4e5da5Sopenharmony_ciOpName %6 "simple_struct"
2101fd4e5da5Sopenharmony_ci%1 = OpTypeVoid
2102fd4e5da5Sopenharmony_ci%2 = OpTypeInt 32 0
2103fd4e5da5Sopenharmony_ci%uint_32 = OpConstant %2 32
2104fd4e5da5Sopenharmony_ci%3 = OpTypeStruct %2 %2 %2 %2
2105fd4e5da5Sopenharmony_ci%4 = OpTypePointer Function %3
2106fd4e5da5Sopenharmony_ci%5 = OpTypePointer Function %2
2107fd4e5da5Sopenharmony_ci%6 = OpTypeFunction %2
2108fd4e5da5Sopenharmony_ci%7 = OpConstantNull %3
2109fd4e5da5Sopenharmony_ci%8 = OpConstant %2 0
2110fd4e5da5Sopenharmony_ci%9 = OpConstant %2 1
2111fd4e5da5Sopenharmony_ci%10 = OpConstant %2 2
2112fd4e5da5Sopenharmony_ci%11 = OpConstant %2 3
2113fd4e5da5Sopenharmony_ci%deref = OpExtInst %1 %ext DebugOperation Deref
2114fd4e5da5Sopenharmony_ci%deref_expr = OpExtInst %1 %ext DebugExpression %deref
2115fd4e5da5Sopenharmony_ci%null_expr = OpExtInst %1 %ext DebugExpression
2116fd4e5da5Sopenharmony_ci%src = OpExtInst %1 %ext DebugSource %test
2117fd4e5da5Sopenharmony_ci%cu = OpExtInst %1 %ext DebugCompilationUnit 1 4 %src HLSL
2118fd4e5da5Sopenharmony_ci%dbg_tf = OpExtInst %1 %ext DebugTypeBasic %test %uint_32 Float
2119fd4e5da5Sopenharmony_ci%main_ty = OpExtInst %1 %ext DebugTypeFunction FlagIsProtected|FlagIsPrivate %1
2120fd4e5da5Sopenharmony_ci%dbg_main = OpExtInst %1 %ext DebugFunction %test %main_ty %src 0 0 %cu %test FlagIsProtected|FlagIsPrivate 0 %12
2121fd4e5da5Sopenharmony_ci%dbg_foo = OpExtInst %1 %ext DebugLocalVariable %test %dbg_tf %src 0 0 %dbg_main FlagIsLocal
2122fd4e5da5Sopenharmony_ci%12 = OpFunction %2 None %6
2123fd4e5da5Sopenharmony_ci%13 = OpLabel
2124fd4e5da5Sopenharmony_ci%scope = OpExtInst %1 %ext DebugScope %dbg_main
2125fd4e5da5Sopenharmony_ci%14 = OpVariable %4 Function %7
2126fd4e5da5Sopenharmony_ci
2127fd4e5da5Sopenharmony_ci; CHECK: [[deref:%\w+]] = OpExtInst %void [[ext:%\w+]] DebugOperation Deref
2128fd4e5da5Sopenharmony_ci; CHECK: [[deref_expr:%\w+]] = OpExtInst %void [[ext]] DebugExpression [[deref]]
2129fd4e5da5Sopenharmony_ci; CHECK: [[dbg_local_var:%\w+]] = OpExtInst %void [[ext]] DebugLocalVariable
2130fd4e5da5Sopenharmony_ci; CHECK: [[repl3:%\w+]] = OpVariable %_ptr_Function_uint Function
2131fd4e5da5Sopenharmony_ci; CHECK: [[repl2:%\w+]] = OpVariable %_ptr_Function_uint Function
2132fd4e5da5Sopenharmony_ci; CHECK: [[repl1:%\w+]] = OpVariable %_ptr_Function_uint Function
2133fd4e5da5Sopenharmony_ci; CHECK: [[repl0:%\w+]] = OpVariable %_ptr_Function_uint Function
2134fd4e5da5Sopenharmony_ci; CHECK: OpExtInst %void [[ext]] DebugValue [[dbg_local_var]] [[repl0]] [[deref_expr]] %uint_0 %uint_1 %uint_2 %int_0
2135fd4e5da5Sopenharmony_ci; CHECK: OpExtInst %void [[ext]] DebugValue [[dbg_local_var]] [[repl1]] [[deref_expr]] %uint_0 %uint_1 %uint_2 %int_1
2136fd4e5da5Sopenharmony_ci; CHECK: OpExtInst %void [[ext]] DebugValue [[dbg_local_var]] [[repl2]] [[deref_expr]] %uint_0 %uint_1 %uint_2 %int_2
2137fd4e5da5Sopenharmony_ci; CHECK: OpExtInst %void [[ext]] DebugValue [[dbg_local_var]] [[repl3]] [[deref_expr]] %uint_0 %uint_1 %uint_2 %int_3
2138fd4e5da5Sopenharmony_ci%value = OpExtInst %1 %ext DebugValue %dbg_foo %14 %deref_expr %8 %9 %10
2139fd4e5da5Sopenharmony_ci
2140fd4e5da5Sopenharmony_ci%15 = OpInBoundsAccessChain %5 %14 %8
2141fd4e5da5Sopenharmony_ci%16 = OpLoad %2 %15
2142fd4e5da5Sopenharmony_ci%17 = OpAccessChain %5 %14 %10
2143fd4e5da5Sopenharmony_ci%18 = OpLoad %2 %17
2144fd4e5da5Sopenharmony_ci%19 = OpIAdd %2 %16 %18
2145fd4e5da5Sopenharmony_ciOpReturnValue %19
2146fd4e5da5Sopenharmony_ciOpFunctionEnd
2147fd4e5da5Sopenharmony_ci)";
2148fd4e5da5Sopenharmony_ci
2149fd4e5da5Sopenharmony_ci  SinglePassRunAndMatch<ScalarReplacementPass>(text, true);
2150fd4e5da5Sopenharmony_ci}
2151fd4e5da5Sopenharmony_ci
2152fd4e5da5Sopenharmony_ciTEST_F(ScalarReplacementTest, DebugDeclareForVariableInOtherBB) {
2153fd4e5da5Sopenharmony_ci  const std::string text = R"(
2154fd4e5da5Sopenharmony_ciOpCapability Shader
2155fd4e5da5Sopenharmony_ciOpCapability Linkage
2156fd4e5da5Sopenharmony_ci%ext = OpExtInstImport "OpenCL.DebugInfo.100"
2157fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
2158fd4e5da5Sopenharmony_ci%test = OpString "test"
2159fd4e5da5Sopenharmony_ciOpName %6 "simple_struct"
2160fd4e5da5Sopenharmony_ci%1 = OpTypeVoid
2161fd4e5da5Sopenharmony_ci%2 = OpTypeInt 32 0
2162fd4e5da5Sopenharmony_ci%uint_32 = OpConstant %2 32
2163fd4e5da5Sopenharmony_ci%3 = OpTypeStruct %2 %2 %2 %2
2164fd4e5da5Sopenharmony_ci%4 = OpTypePointer Function %3
2165fd4e5da5Sopenharmony_ci%5 = OpTypePointer Function %2
2166fd4e5da5Sopenharmony_ci%6 = OpTypeFunction %2
2167fd4e5da5Sopenharmony_ci%7 = OpConstantNull %3
2168fd4e5da5Sopenharmony_ci%8 = OpConstant %2 0
2169fd4e5da5Sopenharmony_ci%9 = OpConstant %2 1
2170fd4e5da5Sopenharmony_ci%10 = OpConstant %2 2
2171fd4e5da5Sopenharmony_ci%11 = OpConstant %2 3
2172fd4e5da5Sopenharmony_ci%deref = OpExtInst %1 %ext DebugOperation Deref
2173fd4e5da5Sopenharmony_ci%deref_expr = OpExtInst %1 %ext DebugExpression %deref
2174fd4e5da5Sopenharmony_ci%null_expr = OpExtInst %1 %ext DebugExpression
2175fd4e5da5Sopenharmony_ci%src = OpExtInst %1 %ext DebugSource %test
2176fd4e5da5Sopenharmony_ci%cu = OpExtInst %1 %ext DebugCompilationUnit 1 4 %src HLSL
2177fd4e5da5Sopenharmony_ci%dbg_tf = OpExtInst %1 %ext DebugTypeBasic %test %uint_32 Float
2178fd4e5da5Sopenharmony_ci%main_ty = OpExtInst %1 %ext DebugTypeFunction FlagIsProtected|FlagIsPrivate %1
2179fd4e5da5Sopenharmony_ci%dbg_main = OpExtInst %1 %ext DebugFunction %test %main_ty %src 0 0 %cu %test FlagIsProtected|FlagIsPrivate 0 %12
2180fd4e5da5Sopenharmony_ci%dbg_foo = OpExtInst %1 %ext DebugLocalVariable %test %dbg_tf %src 0 0 %dbg_main FlagIsLocal
2181fd4e5da5Sopenharmony_ci%12 = OpFunction %2 None %6
2182fd4e5da5Sopenharmony_ci%13 = OpLabel
2183fd4e5da5Sopenharmony_ci%scope = OpExtInst %1 %ext DebugScope %dbg_main
2184fd4e5da5Sopenharmony_ci%14 = OpVariable %4 Function %7
2185fd4e5da5Sopenharmony_ci
2186fd4e5da5Sopenharmony_ci; CHECK: [[dbg_local_var:%\w+]] = OpExtInst %void [[ext:%\w+]] DebugLocalVariable
2187fd4e5da5Sopenharmony_ci; CHECK: [[repl3:%\w+]] = OpVariable %_ptr_Function_uint Function
2188fd4e5da5Sopenharmony_ci; CHECK: [[repl2:%\w+]] = OpVariable %_ptr_Function_uint Function
2189fd4e5da5Sopenharmony_ci; CHECK: [[repl1:%\w+]] = OpVariable %_ptr_Function_uint Function
2190fd4e5da5Sopenharmony_ci; CHECK: [[repl0:%\w+]] = OpVariable %_ptr_Function_uint Function
2191fd4e5da5Sopenharmony_ci; CHECK: OpExtInst %void [[ext]] DebugValue [[dbg_local_var]] [[repl3]] [[deref_expr:%\w+]] %int_3
2192fd4e5da5Sopenharmony_ci; CHECK: OpExtInst %void [[ext]] DebugValue [[dbg_local_var]] [[repl2]] [[deref_expr]] %int_2
2193fd4e5da5Sopenharmony_ci; CHECK: OpExtInst %void [[ext]] DebugValue [[dbg_local_var]] [[repl1]] [[deref_expr]] %int_1
2194fd4e5da5Sopenharmony_ci; CHECK: OpExtInst %void [[ext]] DebugValue [[dbg_local_var]] [[repl0]] [[deref_expr]] %int_0
2195fd4e5da5Sopenharmony_ci
2196fd4e5da5Sopenharmony_ciOpBranch %20
2197fd4e5da5Sopenharmony_ci%20 = OpLabel
2198fd4e5da5Sopenharmony_ci%value = OpExtInst %1 %ext DebugDeclare %dbg_foo %14 %null_expr
2199fd4e5da5Sopenharmony_ci%15 = OpInBoundsAccessChain %5 %14 %8
2200fd4e5da5Sopenharmony_ci%16 = OpLoad %2 %15
2201fd4e5da5Sopenharmony_ci%17 = OpAccessChain %5 %14 %10
2202fd4e5da5Sopenharmony_ci%18 = OpLoad %2 %17
2203fd4e5da5Sopenharmony_ci%19 = OpIAdd %2 %16 %18
2204fd4e5da5Sopenharmony_ciOpReturnValue %19
2205fd4e5da5Sopenharmony_ciOpFunctionEnd
2206fd4e5da5Sopenharmony_ci)";
2207fd4e5da5Sopenharmony_ci
2208fd4e5da5Sopenharmony_ci  SinglePassRunAndMatch<ScalarReplacementPass>(text, true);
2209fd4e5da5Sopenharmony_ci}
2210fd4e5da5Sopenharmony_ci
2211fd4e5da5Sopenharmony_ciTEST_F(ScalarReplacementTest, ImageTexelPointer) {
2212fd4e5da5Sopenharmony_ci  // Test whether the scalar replacement correctly checks the
2213fd4e5da5Sopenharmony_ci  // OpImageTexelPointer user of an aggregate with an image type.
2214fd4e5da5Sopenharmony_ci  const std::string text = R"(
2215fd4e5da5Sopenharmony_ci;
2216fd4e5da5Sopenharmony_ci; CHECK: [[imgTy:%\w+]] = OpTypeImage %uint Buffer 2 0 0 2 R32ui
2217fd4e5da5Sopenharmony_ci; CHECK: [[ptrImgTy:%\w+]] = OpTypePointer Function [[imgTy]]
2218fd4e5da5Sopenharmony_ci; CHECK: [[img:%\w+]] = OpVariable [[ptrImgTy]] Function
2219fd4e5da5Sopenharmony_ci; CHECK: [[imgTexelPtr:%\w+]] = OpImageTexelPointer {{%\w+}} [[img]] %uint_0 %uint_0
2220fd4e5da5Sopenharmony_ci; CHECK: OpAtomicIAdd %uint [[imgTexelPtr]] %uint_1 %uint_0 %uint_1
2221fd4e5da5Sopenharmony_ci;
2222fd4e5da5Sopenharmony_ciOpCapability Shader
2223fd4e5da5Sopenharmony_ciOpCapability SampledBuffer
2224fd4e5da5Sopenharmony_ciOpCapability ImageBuffer
2225fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
2226fd4e5da5Sopenharmony_ciOpEntryPoint GLCompute %1 "main"
2227fd4e5da5Sopenharmony_ciOpExecutionMode %1 LocalSize 64 1 1
2228fd4e5da5Sopenharmony_ci%void = OpTypeVoid
2229fd4e5da5Sopenharmony_ci%uint = OpTypeInt 32 0
2230fd4e5da5Sopenharmony_ci%uint_0 = OpConstant %uint 0
2231fd4e5da5Sopenharmony_ci%uint_1 = OpConstant %uint 1
2232fd4e5da5Sopenharmony_ci%_ptr_Image_uint = OpTypePointer Image %uint
2233fd4e5da5Sopenharmony_ci%type_buffer_image = OpTypeImage %uint Buffer 2 0 0 2 R32ui
2234fd4e5da5Sopenharmony_ci%_ptr_Function_type_buffer_image = OpTypePointer Function %type_buffer_image
2235fd4e5da5Sopenharmony_ci%image_struct = OpTypeStruct %type_buffer_image %type_buffer_image
2236fd4e5da5Sopenharmony_ci%_ptr_Function_image_struct = OpTypePointer Function %image_struct
2237fd4e5da5Sopenharmony_ci%func = OpTypeFunction %void
2238fd4e5da5Sopenharmony_ci%1 = OpFunction %void None %func
2239fd4e5da5Sopenharmony_ci%2 = OpLabel
2240fd4e5da5Sopenharmony_ci%3 = OpVariable %_ptr_Function_image_struct Function
2241fd4e5da5Sopenharmony_ci%4 = OpAccessChain %_ptr_Function_type_buffer_image %3 %uint_1
2242fd4e5da5Sopenharmony_ci%5 = OpImageTexelPointer %_ptr_Image_uint %4 %uint_0 %uint_0
2243fd4e5da5Sopenharmony_ci%6 = OpAtomicIAdd %uint %5 %uint_1 %uint_0 %uint_1
2244fd4e5da5Sopenharmony_ciOpReturn
2245fd4e5da5Sopenharmony_ciOpFunctionEnd
2246fd4e5da5Sopenharmony_ci  )";
2247fd4e5da5Sopenharmony_ci
2248fd4e5da5Sopenharmony_ci  SinglePassRunAndMatch<ScalarReplacementPass>(text, false);
2249fd4e5da5Sopenharmony_ci}
2250fd4e5da5Sopenharmony_ci
2251fd4e5da5Sopenharmony_ciTEST_F(ScalarReplacementTest, FunctionDeclaration) {
2252fd4e5da5Sopenharmony_ci  // Make sure the pass works with a function declaration that is called.
2253fd4e5da5Sopenharmony_ci  const std::string text = R"(OpCapability Addresses
2254fd4e5da5Sopenharmony_ciOpCapability Linkage
2255fd4e5da5Sopenharmony_ciOpCapability Kernel
2256fd4e5da5Sopenharmony_ciOpCapability Int8
2257fd4e5da5Sopenharmony_ci%1 = OpExtInstImport "OpenCL.std"
2258fd4e5da5Sopenharmony_ciOpMemoryModel Physical64 OpenCL
2259fd4e5da5Sopenharmony_ciOpEntryPoint Kernel %2 "_Z23julia__1166_kernel_77094Bool"
2260fd4e5da5Sopenharmony_ciOpExecutionMode %2 ContractionOff
2261fd4e5da5Sopenharmony_ciOpSource Unknown 0
2262fd4e5da5Sopenharmony_ciOpDecorate %3 LinkageAttributes "julia_error_7712" Import
2263fd4e5da5Sopenharmony_ci%void = OpTypeVoid
2264fd4e5da5Sopenharmony_ci%5 = OpTypeFunction %void
2265fd4e5da5Sopenharmony_ci%3 = OpFunction %void None %5
2266fd4e5da5Sopenharmony_ciOpFunctionEnd
2267fd4e5da5Sopenharmony_ci%2 = OpFunction %void None %5
2268fd4e5da5Sopenharmony_ci%6 = OpLabel
2269fd4e5da5Sopenharmony_ci%7 = OpFunctionCall %void %3
2270fd4e5da5Sopenharmony_ciOpReturn
2271fd4e5da5Sopenharmony_ciOpFunctionEnd
2272fd4e5da5Sopenharmony_ci)";
2273fd4e5da5Sopenharmony_ci
2274fd4e5da5Sopenharmony_ci  SinglePassRunAndCheck<ScalarReplacementPass>(text, text, false);
2275fd4e5da5Sopenharmony_ci}
2276fd4e5da5Sopenharmony_ci
2277fd4e5da5Sopenharmony_ciTEST_F(ScalarReplacementTest, UndefImageMember) {
2278fd4e5da5Sopenharmony_ci  // Test that scalar replacement creates an undef for a type that cannot have
2279fd4e5da5Sopenharmony_ci  // and OpConstantNull.
2280fd4e5da5Sopenharmony_ci  const std::string text = R"(
2281fd4e5da5Sopenharmony_ci; CHECK: [[image_type:%\w+]] = OpTypeSampledImage {{%\w+}}
2282fd4e5da5Sopenharmony_ci; CHECK: [[struct_type:%\w+]] = OpTypeStruct [[image_type]]
2283fd4e5da5Sopenharmony_ci; CHECK: [[undef:%\w+]] = OpUndef [[image_type]]
2284fd4e5da5Sopenharmony_ci; CHECK: {{%\w+}} = OpCompositeConstruct [[struct_type]] [[undef]]
2285fd4e5da5Sopenharmony_ci               OpCapability Shader
2286fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
2287fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
2288fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %2 "main"
2289fd4e5da5Sopenharmony_ci               OpExecutionMode %2 OriginUpperLeft
2290fd4e5da5Sopenharmony_ci       %void = OpTypeVoid
2291fd4e5da5Sopenharmony_ci          %4 = OpTypeFunction %void
2292fd4e5da5Sopenharmony_ci      %float = OpTypeFloat 32
2293fd4e5da5Sopenharmony_ci          %6 = OpTypeImage %float 2D 0 0 0 1 Unknown
2294fd4e5da5Sopenharmony_ci          %7 = OpTypeSampledImage %6
2295fd4e5da5Sopenharmony_ci  %_struct_8 = OpTypeStruct %7
2296fd4e5da5Sopenharmony_ci          %9 = OpTypeFunction %_struct_8
2297fd4e5da5Sopenharmony_ci         %10 = OpUndef %_struct_8
2298fd4e5da5Sopenharmony_ci%_ptr_Function__struct_8 = OpTypePointer Function %_struct_8
2299fd4e5da5Sopenharmony_ci          %2 = OpFunction %void None %4
2300fd4e5da5Sopenharmony_ci         %11 = OpLabel
2301fd4e5da5Sopenharmony_ci         %16 = OpVariable %_ptr_Function__struct_8 Function
2302fd4e5da5Sopenharmony_ci               OpStore %16 %10
2303fd4e5da5Sopenharmony_ci         %12 = OpLoad %_struct_8 %16
2304fd4e5da5Sopenharmony_ci               OpReturn
2305fd4e5da5Sopenharmony_ci               OpFunctionEnd
2306fd4e5da5Sopenharmony_ci  )";
2307fd4e5da5Sopenharmony_ci
2308fd4e5da5Sopenharmony_ci  SinglePassRunAndMatch<ScalarReplacementPass>(text, true);
2309fd4e5da5Sopenharmony_ci}
2310fd4e5da5Sopenharmony_ci
2311fd4e5da5Sopenharmony_ciTEST_F(ScalarReplacementTest, RestrictPointer) {
2312fd4e5da5Sopenharmony_ci  // This test makes sure that a variable with the restrict pointer decoration
2313fd4e5da5Sopenharmony_ci  // is replaced, and that the pointer is applied to the new variable.
2314fd4e5da5Sopenharmony_ci  const std::string text = R"(
2315fd4e5da5Sopenharmony_ci; CHECK: OpDecorate [[new_var:%\w+]] RestrictPointer
2316fd4e5da5Sopenharmony_ci; CHECK: [[struct_type:%\w+]] = OpTypeStruct %int
2317fd4e5da5Sopenharmony_ci; CHECK: [[ptr_type:%\w+]] = OpTypePointer PhysicalStorageBuffer [[struct_type]]
2318fd4e5da5Sopenharmony_ci; CHECK: [[dup_struct_type:%\w+]] = OpTypeStruct %int
2319fd4e5da5Sopenharmony_ci; CHECK: {{%\w+}} = OpTypePointer PhysicalStorageBuffer [[dup_struct_type]]
2320fd4e5da5Sopenharmony_ci; CHECK: [[var_type:%\w+]] = OpTypePointer Function [[ptr_type]]
2321fd4e5da5Sopenharmony_ci; CHECK: [[new_var]] = OpVariable [[var_type]] Function
2322fd4e5da5Sopenharmony_ci               OpCapability Shader
2323fd4e5da5Sopenharmony_ci               OpCapability PhysicalStorageBufferAddresses
2324fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
2325fd4e5da5Sopenharmony_ci               OpMemoryModel PhysicalStorageBuffer64 GLSL450
2326fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %2 "main"
2327fd4e5da5Sopenharmony_ci               OpExecutionMode %2 OriginUpperLeft
2328fd4e5da5Sopenharmony_ci               OpMemberDecorate %3 0 Offset 0
2329fd4e5da5Sopenharmony_ci               OpDecorate %3 Block
2330fd4e5da5Sopenharmony_ci               OpMemberDecorate %4 0 Offset 0
2331fd4e5da5Sopenharmony_ci               OpDecorate %4 Block
2332fd4e5da5Sopenharmony_ci               OpDecorate %5 RestrictPointer
2333fd4e5da5Sopenharmony_ci          %6 = OpTypeVoid
2334fd4e5da5Sopenharmony_ci          %7 = OpTypeFunction %6
2335fd4e5da5Sopenharmony_ci          %8 = OpTypeInt 32 1
2336fd4e5da5Sopenharmony_ci          %9 = OpConstant %8 0
2337fd4e5da5Sopenharmony_ci          %3 = OpTypeStruct %8
2338fd4e5da5Sopenharmony_ci         %10 = OpTypePointer PhysicalStorageBuffer %3
2339fd4e5da5Sopenharmony_ci         %11 = OpTypeStruct %10
2340fd4e5da5Sopenharmony_ci          %4 = OpTypeStruct %8
2341fd4e5da5Sopenharmony_ci         %12 = OpTypePointer PhysicalStorageBuffer %4
2342fd4e5da5Sopenharmony_ci         %13 = OpTypePointer Function %11
2343fd4e5da5Sopenharmony_ci         %14 = OpTypePointer Function %10
2344fd4e5da5Sopenharmony_ci         %15 = OpTypePointer Function %12
2345fd4e5da5Sopenharmony_ci         %16 = OpUndef %11
2346fd4e5da5Sopenharmony_ci          %2 = OpFunction %6 None %7
2347fd4e5da5Sopenharmony_ci         %17 = OpLabel
2348fd4e5da5Sopenharmony_ci          %5 = OpVariable %13 Function
2349fd4e5da5Sopenharmony_ci               OpStore %5 %16
2350fd4e5da5Sopenharmony_ci         %18 = OpAccessChain %14 %5 %9
2351fd4e5da5Sopenharmony_ci               OpReturn
2352fd4e5da5Sopenharmony_ci               OpFunctionEnd
2353fd4e5da5Sopenharmony_ci  )";
2354fd4e5da5Sopenharmony_ci
2355fd4e5da5Sopenharmony_ci  SetTargetEnv(SPV_ENV_UNIVERSAL_1_6);
2356fd4e5da5Sopenharmony_ci  SinglePassRunAndMatch<ScalarReplacementPass>(text, true);
2357fd4e5da5Sopenharmony_ci}
2358fd4e5da5Sopenharmony_ci
2359fd4e5da5Sopenharmony_ci}  // namespace
2360fd4e5da5Sopenharmony_ci}  // namespace opt
2361fd4e5da5Sopenharmony_ci}  // namespace spvtools
2362