1fd4e5da5Sopenharmony_ci// Copyright (c) 2017 Valve Corporation
2fd4e5da5Sopenharmony_ci// Copyright (c) 2017 LunarG Inc.
3fd4e5da5Sopenharmony_ci//
4fd4e5da5Sopenharmony_ci// Licensed under the Apache License, Version 2.0 (the "License");
5fd4e5da5Sopenharmony_ci// you may not use this file except in compliance with the License.
6fd4e5da5Sopenharmony_ci// You may obtain a copy of the License at
7fd4e5da5Sopenharmony_ci//
8fd4e5da5Sopenharmony_ci//     http://www.apache.org/licenses/LICENSE-2.0
9fd4e5da5Sopenharmony_ci//
10fd4e5da5Sopenharmony_ci// Unless required by applicable law or agreed to in writing, software
11fd4e5da5Sopenharmony_ci// distributed under the License is distributed on an "AS IS" BASIS,
12fd4e5da5Sopenharmony_ci// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13fd4e5da5Sopenharmony_ci// See the License for the specific language governing permissions and
14fd4e5da5Sopenharmony_ci// limitations under the License.
15fd4e5da5Sopenharmony_ci
16fd4e5da5Sopenharmony_ci#include <string>
17fd4e5da5Sopenharmony_ci
18fd4e5da5Sopenharmony_ci#include "test/opt/pass_fixture.h"
19fd4e5da5Sopenharmony_ci#include "test/opt/pass_utils.h"
20fd4e5da5Sopenharmony_ci
21fd4e5da5Sopenharmony_cinamespace spvtools {
22fd4e5da5Sopenharmony_cinamespace opt {
23fd4e5da5Sopenharmony_cinamespace {
24fd4e5da5Sopenharmony_ci
25fd4e5da5Sopenharmony_ciusing LocalAccessChainConvertTest = PassTest<::testing::Test>;
26fd4e5da5Sopenharmony_ci
27fd4e5da5Sopenharmony_ciTEST_F(LocalAccessChainConvertTest, StructOfVecsOfFloatConverted) {
28fd4e5da5Sopenharmony_ci  //  #version 140
29fd4e5da5Sopenharmony_ci  //
30fd4e5da5Sopenharmony_ci  //  in vec4 BaseColor;
31fd4e5da5Sopenharmony_ci  //
32fd4e5da5Sopenharmony_ci  //  struct S_t {
33fd4e5da5Sopenharmony_ci  //      vec4 v0;
34fd4e5da5Sopenharmony_ci  //      vec4 v1;
35fd4e5da5Sopenharmony_ci  //  };
36fd4e5da5Sopenharmony_ci  //
37fd4e5da5Sopenharmony_ci  //  void main()
38fd4e5da5Sopenharmony_ci  //  {
39fd4e5da5Sopenharmony_ci  //      S_t s0;
40fd4e5da5Sopenharmony_ci  //      s0.v1 = BaseColor;
41fd4e5da5Sopenharmony_ci  //      gl_FragColor = s0.v1;
42fd4e5da5Sopenharmony_ci  //  }
43fd4e5da5Sopenharmony_ci
44fd4e5da5Sopenharmony_ci  const std::string predefs_before =
45fd4e5da5Sopenharmony_ci      R"(OpCapability Shader
46fd4e5da5Sopenharmony_ci%1 = OpExtInstImport "GLSL.std.450"
47fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
48fd4e5da5Sopenharmony_ciOpEntryPoint Fragment %main "main" %BaseColor %gl_FragColor
49fd4e5da5Sopenharmony_ciOpExecutionMode %main OriginUpperLeft
50fd4e5da5Sopenharmony_ciOpSource GLSL 140
51fd4e5da5Sopenharmony_ciOpName %main "main"
52fd4e5da5Sopenharmony_ciOpName %S_t "S_t"
53fd4e5da5Sopenharmony_ciOpMemberName %S_t 0 "v0"
54fd4e5da5Sopenharmony_ciOpMemberName %S_t 1 "v1"
55fd4e5da5Sopenharmony_ciOpName %s0 "s0"
56fd4e5da5Sopenharmony_ciOpName %BaseColor "BaseColor"
57fd4e5da5Sopenharmony_ciOpName %gl_FragColor "gl_FragColor"
58fd4e5da5Sopenharmony_ci%void = OpTypeVoid
59fd4e5da5Sopenharmony_ci%8 = OpTypeFunction %void
60fd4e5da5Sopenharmony_ci%float = OpTypeFloat 32
61fd4e5da5Sopenharmony_ci%v4float = OpTypeVector %float 4
62fd4e5da5Sopenharmony_ci%S_t = OpTypeStruct %v4float %v4float
63fd4e5da5Sopenharmony_ci%_ptr_Function_S_t = OpTypePointer Function %S_t
64fd4e5da5Sopenharmony_ci%int = OpTypeInt 32 1
65fd4e5da5Sopenharmony_ci%int_1 = OpConstant %int 1
66fd4e5da5Sopenharmony_ci%_ptr_Input_v4float = OpTypePointer Input %v4float
67fd4e5da5Sopenharmony_ci%BaseColor = OpVariable %_ptr_Input_v4float Input
68fd4e5da5Sopenharmony_ci%_ptr_Function_v4float = OpTypePointer Function %v4float
69fd4e5da5Sopenharmony_ci%_ptr_Output_v4float = OpTypePointer Output %v4float
70fd4e5da5Sopenharmony_ci%gl_FragColor = OpVariable %_ptr_Output_v4float Output
71fd4e5da5Sopenharmony_ci)";
72fd4e5da5Sopenharmony_ci
73fd4e5da5Sopenharmony_ci  const std::string before =
74fd4e5da5Sopenharmony_ci      R"(
75fd4e5da5Sopenharmony_ci; CHECK: [[st_id:%\w+]] = OpLoad %v4float %BaseColor
76fd4e5da5Sopenharmony_ci; CHECK: [[ld1:%\w+]] = OpLoad %S_t %s0
77fd4e5da5Sopenharmony_ci; CHECK: [[ex1:%\w+]] = OpCompositeInsert %S_t [[st_id]] [[ld1]] 1
78fd4e5da5Sopenharmony_ci; CHECK: OpStore %s0 [[ex1]]
79fd4e5da5Sopenharmony_ci; CHECK: [[ld2:%\w+]] = OpLoad %S_t %s0
80fd4e5da5Sopenharmony_ci; CHECK: [[ex2:%\w+]] = OpCompositeExtract %v4float [[ld2]] 1
81fd4e5da5Sopenharmony_ci; CHECK: OpStore %gl_FragColor [[ex2]]
82fd4e5da5Sopenharmony_ci%main = OpFunction %void None %8
83fd4e5da5Sopenharmony_ci%17 = OpLabel
84fd4e5da5Sopenharmony_ci%s0 = OpVariable %_ptr_Function_S_t Function
85fd4e5da5Sopenharmony_ci%18 = OpLoad %v4float %BaseColor
86fd4e5da5Sopenharmony_ci%19 = OpAccessChain %_ptr_Function_v4float %s0 %int_1
87fd4e5da5Sopenharmony_ciOpStore %19 %18
88fd4e5da5Sopenharmony_ci%20 = OpAccessChain %_ptr_Function_v4float %s0 %int_1
89fd4e5da5Sopenharmony_ci%21 = OpLoad %v4float %20
90fd4e5da5Sopenharmony_ciOpStore %gl_FragColor %21
91fd4e5da5Sopenharmony_ciOpReturn
92fd4e5da5Sopenharmony_ciOpFunctionEnd
93fd4e5da5Sopenharmony_ci)";
94fd4e5da5Sopenharmony_ci
95fd4e5da5Sopenharmony_ci  SinglePassRunAndMatch<LocalAccessChainConvertPass>(predefs_before + before,
96fd4e5da5Sopenharmony_ci                                                     true);
97fd4e5da5Sopenharmony_ci}
98fd4e5da5Sopenharmony_ci
99fd4e5da5Sopenharmony_ciTEST_F(LocalAccessChainConvertTest, DebugScopeAndLineInfoForNewInstructions) {
100fd4e5da5Sopenharmony_ci  //  #version 140
101fd4e5da5Sopenharmony_ci  //
102fd4e5da5Sopenharmony_ci  //  in vec4 BaseColor;
103fd4e5da5Sopenharmony_ci  //
104fd4e5da5Sopenharmony_ci  //  struct S_t {
105fd4e5da5Sopenharmony_ci  //      vec4 v0;
106fd4e5da5Sopenharmony_ci  //      vec4 v1;
107fd4e5da5Sopenharmony_ci  //  };
108fd4e5da5Sopenharmony_ci  //
109fd4e5da5Sopenharmony_ci  //  void main()
110fd4e5da5Sopenharmony_ci  //  {
111fd4e5da5Sopenharmony_ci  //      S_t s0;
112fd4e5da5Sopenharmony_ci  //      s0.v1 = BaseColor;
113fd4e5da5Sopenharmony_ci  //      gl_FragColor = s0.v1;
114fd4e5da5Sopenharmony_ci  //  }
115fd4e5da5Sopenharmony_ci
116fd4e5da5Sopenharmony_ci  const std::string predefs_before =
117fd4e5da5Sopenharmony_ci      R"(OpCapability Shader
118fd4e5da5Sopenharmony_ci%1 = OpExtInstImport "GLSL.std.450"
119fd4e5da5Sopenharmony_ci%ext = OpExtInstImport "OpenCL.DebugInfo.100"
120fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
121fd4e5da5Sopenharmony_ciOpEntryPoint Fragment %main "main" %BaseColor %gl_FragColor
122fd4e5da5Sopenharmony_ciOpExecutionMode %main OriginUpperLeft
123fd4e5da5Sopenharmony_ciOpSource GLSL 140
124fd4e5da5Sopenharmony_ciOpName %main "main"
125fd4e5da5Sopenharmony_ciOpName %S_t "S_t"
126fd4e5da5Sopenharmony_ciOpMemberName %S_t 0 "v0"
127fd4e5da5Sopenharmony_ciOpMemberName %S_t 1 "v1"
128fd4e5da5Sopenharmony_ciOpName %s0 "s0"
129fd4e5da5Sopenharmony_ciOpName %BaseColor "BaseColor"
130fd4e5da5Sopenharmony_ciOpName %gl_FragColor "gl_FragColor"
131fd4e5da5Sopenharmony_ci%5 = OpString "ps.hlsl"
132fd4e5da5Sopenharmony_ci%6 = OpString "float"
133fd4e5da5Sopenharmony_ci%var_name = OpString "s0"
134fd4e5da5Sopenharmony_ci%main_name = OpString "main"
135fd4e5da5Sopenharmony_ci%void = OpTypeVoid
136fd4e5da5Sopenharmony_ci%8 = OpTypeFunction %void
137fd4e5da5Sopenharmony_ci%float = OpTypeFloat 32
138fd4e5da5Sopenharmony_ci%v4float = OpTypeVector %float 4
139fd4e5da5Sopenharmony_ci%S_t = OpTypeStruct %v4float %v4float
140fd4e5da5Sopenharmony_ci%_ptr_Function_S_t = OpTypePointer Function %S_t
141fd4e5da5Sopenharmony_ci%int = OpTypeInt 32 1
142fd4e5da5Sopenharmony_ci%int_1 = OpConstant %int 1
143fd4e5da5Sopenharmony_ci%int_32 = OpConstant %int 32
144fd4e5da5Sopenharmony_ci%_ptr_Input_v4float = OpTypePointer Input %v4float
145fd4e5da5Sopenharmony_ci%BaseColor = OpVariable %_ptr_Input_v4float Input
146fd4e5da5Sopenharmony_ci%_ptr_Function_v4float = OpTypePointer Function %v4float
147fd4e5da5Sopenharmony_ci%_ptr_Output_v4float = OpTypePointer Output %v4float
148fd4e5da5Sopenharmony_ci%gl_FragColor = OpVariable %_ptr_Output_v4float Output
149fd4e5da5Sopenharmony_ci%20 = OpExtInst %void %ext DebugSource %5
150fd4e5da5Sopenharmony_ci%21 = OpExtInst %void %ext DebugCompilationUnit 1 4 %20 HLSL
151fd4e5da5Sopenharmony_ci%22 = OpExtInst %void %ext DebugTypeBasic %6 %int_32 Float
152fd4e5da5Sopenharmony_ci%23 = OpExtInst %void %ext DebugTypeVector %22 4
153fd4e5da5Sopenharmony_ci%24 = OpExtInst %void %ext DebugTypeFunction FlagIsProtected|FlagIsPrivate %23
154fd4e5da5Sopenharmony_ci%dbg_main = OpExtInst %void %ext DebugFunction %main_name %24 %20 4 1 %21 %main_name FlagIsProtected|FlagIsPrivate 4 %main
155fd4e5da5Sopenharmony_ci%25 = OpExtInst %void %ext DebugLocalVariable %var_name %23 %20 0 0 %dbg_main FlagIsLocal
156fd4e5da5Sopenharmony_ci)";
157fd4e5da5Sopenharmony_ci
158fd4e5da5Sopenharmony_ci  const std::string before =
159fd4e5da5Sopenharmony_ci      R"(
160fd4e5da5Sopenharmony_ci; CHECK: [[st_id:%\w+]] = OpLoad %v4float %BaseColor
161fd4e5da5Sopenharmony_ci; CHECK: OpLine {{%\w+}} 1 0
162fd4e5da5Sopenharmony_ci; CHECK: [[ld1:%\w+]] = OpLoad %S_t %s0
163fd4e5da5Sopenharmony_ci; CHECK: [[ex1:%\w+]] = OpCompositeInsert %S_t [[st_id]] [[ld1]] 1
164fd4e5da5Sopenharmony_ci; CHECK: OpStore %s0 [[ex1]]
165fd4e5da5Sopenharmony_ci; CHECK: OpLine {{%\w+}} 3 0
166fd4e5da5Sopenharmony_ci; CHECK: [[ld2:%\w+]] = OpLoad %S_t %s0
167fd4e5da5Sopenharmony_ci; CHECK: [[ex2:%\w+]] = OpCompositeExtract %v4float [[ld2]] 1
168fd4e5da5Sopenharmony_ci; CHECK: OpLine {{%\w+}} 4 0
169fd4e5da5Sopenharmony_ci; CHECK: OpStore %gl_FragColor [[ex2]]
170fd4e5da5Sopenharmony_ci%main = OpFunction %void None %8
171fd4e5da5Sopenharmony_ci%17 = OpLabel
172fd4e5da5Sopenharmony_ci%26 = OpExtInst %void %ext DebugScope %dbg_main
173fd4e5da5Sopenharmony_ci%s0 = OpVariable %_ptr_Function_S_t Function
174fd4e5da5Sopenharmony_ci%18 = OpLoad %v4float %BaseColor
175fd4e5da5Sopenharmony_ciOpLine %5 0 0
176fd4e5da5Sopenharmony_ci%19 = OpAccessChain %_ptr_Function_v4float %s0 %int_1
177fd4e5da5Sopenharmony_ciOpLine %5 1 0
178fd4e5da5Sopenharmony_ciOpStore %19 %18
179fd4e5da5Sopenharmony_ciOpLine %5 2 0
180fd4e5da5Sopenharmony_ci%27 = OpAccessChain %_ptr_Function_v4float %s0 %int_1
181fd4e5da5Sopenharmony_ciOpLine %5 3 0
182fd4e5da5Sopenharmony_ci%28 = OpLoad %v4float %27
183fd4e5da5Sopenharmony_ciOpLine %5 4 0
184fd4e5da5Sopenharmony_ciOpStore %gl_FragColor %28
185fd4e5da5Sopenharmony_ciOpReturn
186fd4e5da5Sopenharmony_ciOpFunctionEnd
187fd4e5da5Sopenharmony_ci)";
188fd4e5da5Sopenharmony_ci
189fd4e5da5Sopenharmony_ci  SinglePassRunAndMatch<LocalAccessChainConvertPass>(predefs_before + before,
190fd4e5da5Sopenharmony_ci                                                     true);
191fd4e5da5Sopenharmony_ci}
192fd4e5da5Sopenharmony_ci
193fd4e5da5Sopenharmony_ciTEST_F(LocalAccessChainConvertTest, TestTargetsReferencedByDebugValue) {
194fd4e5da5Sopenharmony_ci  //  #version 140
195fd4e5da5Sopenharmony_ci  //
196fd4e5da5Sopenharmony_ci  //  in vec4 BaseColor;
197fd4e5da5Sopenharmony_ci  //
198fd4e5da5Sopenharmony_ci  //  struct S_t {
199fd4e5da5Sopenharmony_ci  //      vec4 v0;
200fd4e5da5Sopenharmony_ci  //      vec4 v1;
201fd4e5da5Sopenharmony_ci  //  };
202fd4e5da5Sopenharmony_ci  //
203fd4e5da5Sopenharmony_ci  //  void main()
204fd4e5da5Sopenharmony_ci  //  {
205fd4e5da5Sopenharmony_ci  //      S_t s0;
206fd4e5da5Sopenharmony_ci  //      s0.v1 = BaseColor;
207fd4e5da5Sopenharmony_ci  //      gl_FragColor = s0.v1;
208fd4e5da5Sopenharmony_ci  //  }
209fd4e5da5Sopenharmony_ci
210fd4e5da5Sopenharmony_ci  const std::string predefs_before =
211fd4e5da5Sopenharmony_ci      R"(OpCapability Shader
212fd4e5da5Sopenharmony_ci%1 = OpExtInstImport "GLSL.std.450"
213fd4e5da5Sopenharmony_ci%ext = OpExtInstImport "OpenCL.DebugInfo.100"
214fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
215fd4e5da5Sopenharmony_ciOpEntryPoint Fragment %main "main" %BaseColor %gl_FragColor
216fd4e5da5Sopenharmony_ciOpExecutionMode %main OriginUpperLeft
217fd4e5da5Sopenharmony_ciOpSource GLSL 140
218fd4e5da5Sopenharmony_ciOpName %main "main"
219fd4e5da5Sopenharmony_ciOpName %S_t "S_t"
220fd4e5da5Sopenharmony_ciOpMemberName %S_t 0 "v0"
221fd4e5da5Sopenharmony_ciOpMemberName %S_t 1 "v1"
222fd4e5da5Sopenharmony_ciOpName %s0 "s0"
223fd4e5da5Sopenharmony_ciOpName %BaseColor "BaseColor"
224fd4e5da5Sopenharmony_ciOpName %gl_FragColor "gl_FragColor"
225fd4e5da5Sopenharmony_ci%5 = OpString "ps.hlsl"
226fd4e5da5Sopenharmony_ci%6 = OpString "float"
227fd4e5da5Sopenharmony_ci%var_name = OpString "s0"
228fd4e5da5Sopenharmony_ci%main_name = OpString "main"
229fd4e5da5Sopenharmony_ci%void = OpTypeVoid
230fd4e5da5Sopenharmony_ci%8 = OpTypeFunction %void
231fd4e5da5Sopenharmony_ci%float = OpTypeFloat 32
232fd4e5da5Sopenharmony_ci%v4float = OpTypeVector %float 4
233fd4e5da5Sopenharmony_ci%S_t = OpTypeStruct %v4float %v4float
234fd4e5da5Sopenharmony_ci%_ptr_Function_S_t = OpTypePointer Function %S_t
235fd4e5da5Sopenharmony_ci%int = OpTypeInt 32 1
236fd4e5da5Sopenharmony_ci%int_1 = OpConstant %int 1
237fd4e5da5Sopenharmony_ci%int_32 = OpConstant %int 32
238fd4e5da5Sopenharmony_ci%_ptr_Input_v4float = OpTypePointer Input %v4float
239fd4e5da5Sopenharmony_ci%BaseColor = OpVariable %_ptr_Input_v4float Input
240fd4e5da5Sopenharmony_ci%_ptr_Function_v4float = OpTypePointer Function %v4float
241fd4e5da5Sopenharmony_ci%_ptr_Output_v4float = OpTypePointer Output %v4float
242fd4e5da5Sopenharmony_ci%gl_FragColor = OpVariable %_ptr_Output_v4float Output
243fd4e5da5Sopenharmony_ci%deref = OpExtInst %void %ext DebugOperation Deref
244fd4e5da5Sopenharmony_ci%deref_expr = OpExtInst %void %ext DebugExpression %deref
245fd4e5da5Sopenharmony_ci%null_expr = OpExtInst %void %ext DebugExpression
246fd4e5da5Sopenharmony_ci%20 = OpExtInst %void %ext DebugSource %5
247fd4e5da5Sopenharmony_ci%21 = OpExtInst %void %ext DebugCompilationUnit 1 4 %20 HLSL
248fd4e5da5Sopenharmony_ci%22 = OpExtInst %void %ext DebugTypeBasic %6 %int_32 Float
249fd4e5da5Sopenharmony_ci%23 = OpExtInst %void %ext DebugTypeVector %22 4
250fd4e5da5Sopenharmony_ci%24 = OpExtInst %void %ext DebugTypeFunction FlagIsProtected|FlagIsPrivate %23
251fd4e5da5Sopenharmony_ci%dbg_main = OpExtInst %void %ext DebugFunction %main_name %24 %20 4 1 %21 %main_name FlagIsProtected|FlagIsPrivate 4 %main
252fd4e5da5Sopenharmony_ci%25 = OpExtInst %void %ext DebugLocalVariable %var_name %23 %20 0 0 %dbg_main FlagIsLocal
253fd4e5da5Sopenharmony_ci)";
254fd4e5da5Sopenharmony_ci
255fd4e5da5Sopenharmony_ci  const std::string before =
256fd4e5da5Sopenharmony_ci      R"(
257fd4e5da5Sopenharmony_ci; CHECK: [[st_id:%\w+]] = OpLoad %v4float %BaseColor
258fd4e5da5Sopenharmony_ci; CHECK: OpLine {{%\w+}} 0 0
259fd4e5da5Sopenharmony_ci; CHECK: [[s0_1_ptr:%\w+]] = OpAccessChain %_ptr_Function_v4float %s0 %int_1
260fd4e5da5Sopenharmony_ci; CHECK: DebugValue [[dbg_s0:%\w+]] [[s0_1_ptr]]
261fd4e5da5Sopenharmony_ci; CHECK: OpLine {{%\w+}} 1 0
262fd4e5da5Sopenharmony_ci; CHECK: [[s0:%\w+]] = OpLoad %S_t %s0
263fd4e5da5Sopenharmony_ci; CHECK: [[comp:%\w+]] = OpCompositeInsert %S_t [[st_id]] [[s0]] 1
264fd4e5da5Sopenharmony_ci; CHECK: OpStore %s0 [[comp]]
265fd4e5da5Sopenharmony_ci; CHECK: OpLine {{%\w+}} 2 0
266fd4e5da5Sopenharmony_ci; CHECK: [[s0_2_ptr:%\w+]] = OpAccessChain %_ptr_Function_v4float %s0 %int_1
267fd4e5da5Sopenharmony_ci; CHECK: OpLine {{%\w+}} 3 0
268fd4e5da5Sopenharmony_ci; CHECK: [[s0:%\w+]] = OpLoad %S_t %s0
269fd4e5da5Sopenharmony_ci; CHECK: [[s0_2_val:%\w+]] = OpCompositeExtract %v4float [[s0]] 1
270fd4e5da5Sopenharmony_ci; CHECK: DebugValue [[dbg_s0]] [[s0_2_val]]
271fd4e5da5Sopenharmony_ci; CHECK: OpLine {{%\w+}} 4 0
272fd4e5da5Sopenharmony_ci; CHECK: OpStore %gl_FragColor [[s0_2_val]]
273fd4e5da5Sopenharmony_ci%main = OpFunction %void None %8
274fd4e5da5Sopenharmony_ci%17 = OpLabel
275fd4e5da5Sopenharmony_ci%26 = OpExtInst %void %ext DebugScope %dbg_main
276fd4e5da5Sopenharmony_ci%s0 = OpVariable %_ptr_Function_S_t Function
277fd4e5da5Sopenharmony_ci%18 = OpLoad %v4float %BaseColor
278fd4e5da5Sopenharmony_ciOpLine %5 0 0
279fd4e5da5Sopenharmony_ci%19 = OpAccessChain %_ptr_Function_v4float %s0 %int_1
280fd4e5da5Sopenharmony_ci%29 = OpExtInst %void %ext DebugValue %25 %19 %deref_expr %int_1
281fd4e5da5Sopenharmony_ciOpLine %5 1 0
282fd4e5da5Sopenharmony_ciOpStore %19 %18
283fd4e5da5Sopenharmony_ciOpLine %5 2 0
284fd4e5da5Sopenharmony_ci%27 = OpAccessChain %_ptr_Function_v4float %s0 %int_1
285fd4e5da5Sopenharmony_ciOpLine %5 3 0
286fd4e5da5Sopenharmony_ci%28 = OpLoad %v4float %27
287fd4e5da5Sopenharmony_ci%30 = OpExtInst %void %ext DebugValue %25 %28 %null_expr %int_1
288fd4e5da5Sopenharmony_ciOpLine %5 4 0
289fd4e5da5Sopenharmony_ciOpStore %gl_FragColor %28
290fd4e5da5Sopenharmony_ciOpReturn
291fd4e5da5Sopenharmony_ciOpFunctionEnd
292fd4e5da5Sopenharmony_ci)";
293fd4e5da5Sopenharmony_ci
294fd4e5da5Sopenharmony_ci  SinglePassRunAndMatch<LocalAccessChainConvertPass>(predefs_before + before,
295fd4e5da5Sopenharmony_ci                                                     true);
296fd4e5da5Sopenharmony_ci}
297fd4e5da5Sopenharmony_ci
298fd4e5da5Sopenharmony_ciTEST_F(LocalAccessChainConvertTest, InBoundsAccessChainsConverted) {
299fd4e5da5Sopenharmony_ci  //  #version 140
300fd4e5da5Sopenharmony_ci  //
301fd4e5da5Sopenharmony_ci  //  in vec4 BaseColor;
302fd4e5da5Sopenharmony_ci  //
303fd4e5da5Sopenharmony_ci  //  struct S_t {
304fd4e5da5Sopenharmony_ci  //      vec4 v0;
305fd4e5da5Sopenharmony_ci  //      vec4 v1;
306fd4e5da5Sopenharmony_ci  //  };
307fd4e5da5Sopenharmony_ci  //
308fd4e5da5Sopenharmony_ci  //  void main()
309fd4e5da5Sopenharmony_ci  //  {
310fd4e5da5Sopenharmony_ci  //      S_t s0;
311fd4e5da5Sopenharmony_ci  //      s0.v1 = BaseColor;
312fd4e5da5Sopenharmony_ci  //      gl_FragColor = s0.v1;
313fd4e5da5Sopenharmony_ci  //  }
314fd4e5da5Sopenharmony_ci
315fd4e5da5Sopenharmony_ci  const std::string predefs_before =
316fd4e5da5Sopenharmony_ci      R"(OpCapability Shader
317fd4e5da5Sopenharmony_ci%1 = OpExtInstImport "GLSL.std.450"
318fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
319fd4e5da5Sopenharmony_ciOpEntryPoint Fragment %main "main" %BaseColor %gl_FragColor
320fd4e5da5Sopenharmony_ciOpExecutionMode %main OriginUpperLeft
321fd4e5da5Sopenharmony_ciOpSource GLSL 140
322fd4e5da5Sopenharmony_ciOpName %main "main"
323fd4e5da5Sopenharmony_ciOpName %S_t "S_t"
324fd4e5da5Sopenharmony_ciOpMemberName %S_t 0 "v0"
325fd4e5da5Sopenharmony_ciOpMemberName %S_t 1 "v1"
326fd4e5da5Sopenharmony_ciOpName %s0 "s0"
327fd4e5da5Sopenharmony_ciOpName %BaseColor "BaseColor"
328fd4e5da5Sopenharmony_ciOpName %gl_FragColor "gl_FragColor"
329fd4e5da5Sopenharmony_ci%void = OpTypeVoid
330fd4e5da5Sopenharmony_ci%8 = OpTypeFunction %void
331fd4e5da5Sopenharmony_ci%float = OpTypeFloat 32
332fd4e5da5Sopenharmony_ci%v4float = OpTypeVector %float 4
333fd4e5da5Sopenharmony_ci%S_t = OpTypeStruct %v4float %v4float
334fd4e5da5Sopenharmony_ci%_ptr_Function_S_t = OpTypePointer Function %S_t
335fd4e5da5Sopenharmony_ci%int = OpTypeInt 32 1
336fd4e5da5Sopenharmony_ci%int_1 = OpConstant %int 1
337fd4e5da5Sopenharmony_ci%_ptr_Input_v4float = OpTypePointer Input %v4float
338fd4e5da5Sopenharmony_ci%BaseColor = OpVariable %_ptr_Input_v4float Input
339fd4e5da5Sopenharmony_ci%_ptr_Function_v4float = OpTypePointer Function %v4float
340fd4e5da5Sopenharmony_ci%_ptr_Output_v4float = OpTypePointer Output %v4float
341fd4e5da5Sopenharmony_ci%gl_FragColor = OpVariable %_ptr_Output_v4float Output
342fd4e5da5Sopenharmony_ci)";
343fd4e5da5Sopenharmony_ci
344fd4e5da5Sopenharmony_ci  const std::string before =
345fd4e5da5Sopenharmony_ci      R"(
346fd4e5da5Sopenharmony_ci; CHECK: [[st_id:%\w+]] = OpLoad %v4float %BaseColor
347fd4e5da5Sopenharmony_ci; CHECK: [[ld1:%\w+]] = OpLoad %S_t %s0
348fd4e5da5Sopenharmony_ci; CHECK: [[ex1:%\w+]] = OpCompositeInsert %S_t [[st_id]] [[ld1]] 1
349fd4e5da5Sopenharmony_ci; CHECK: OpStore %s0 [[ex1]]
350fd4e5da5Sopenharmony_ci; CHECK: [[ld2:%\w+]] = OpLoad %S_t %s0
351fd4e5da5Sopenharmony_ci; CHECK: [[ex2:%\w+]] = OpCompositeExtract %v4float [[ld2]] 1
352fd4e5da5Sopenharmony_ci; CHECK: OpStore %gl_FragColor [[ex2]]
353fd4e5da5Sopenharmony_ci%main = OpFunction %void None %8
354fd4e5da5Sopenharmony_ci%17 = OpLabel
355fd4e5da5Sopenharmony_ci%s0 = OpVariable %_ptr_Function_S_t Function
356fd4e5da5Sopenharmony_ci%18 = OpLoad %v4float %BaseColor
357fd4e5da5Sopenharmony_ci%19 = OpInBoundsAccessChain %_ptr_Function_v4float %s0 %int_1
358fd4e5da5Sopenharmony_ciOpStore %19 %18
359fd4e5da5Sopenharmony_ci%20 = OpInBoundsAccessChain %_ptr_Function_v4float %s0 %int_1
360fd4e5da5Sopenharmony_ci%21 = OpLoad %v4float %20
361fd4e5da5Sopenharmony_ciOpStore %gl_FragColor %21
362fd4e5da5Sopenharmony_ciOpReturn
363fd4e5da5Sopenharmony_ciOpFunctionEnd
364fd4e5da5Sopenharmony_ci)";
365fd4e5da5Sopenharmony_ci
366fd4e5da5Sopenharmony_ci  SinglePassRunAndMatch<LocalAccessChainConvertPass>(predefs_before + before,
367fd4e5da5Sopenharmony_ci                                                     true);
368fd4e5da5Sopenharmony_ci}
369fd4e5da5Sopenharmony_ci
370fd4e5da5Sopenharmony_ciTEST_F(LocalAccessChainConvertTest, TwoUsesofSingleChainConverted) {
371fd4e5da5Sopenharmony_ci  //  #version 140
372fd4e5da5Sopenharmony_ci  //
373fd4e5da5Sopenharmony_ci  //  in vec4 BaseColor;
374fd4e5da5Sopenharmony_ci  //
375fd4e5da5Sopenharmony_ci  //  struct S_t {
376fd4e5da5Sopenharmony_ci  //      vec4 v0;
377fd4e5da5Sopenharmony_ci  //      vec4 v1;
378fd4e5da5Sopenharmony_ci  //  };
379fd4e5da5Sopenharmony_ci  //
380fd4e5da5Sopenharmony_ci  //  void main()
381fd4e5da5Sopenharmony_ci  //  {
382fd4e5da5Sopenharmony_ci  //      S_t s0;
383fd4e5da5Sopenharmony_ci  //      s0.v1 = BaseColor;
384fd4e5da5Sopenharmony_ci  //      gl_FragColor = s0.v1;
385fd4e5da5Sopenharmony_ci  //  }
386fd4e5da5Sopenharmony_ci
387fd4e5da5Sopenharmony_ci  const std::string predefs_before =
388fd4e5da5Sopenharmony_ci      R"(OpCapability Shader
389fd4e5da5Sopenharmony_ci%1 = OpExtInstImport "GLSL.std.450"
390fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
391fd4e5da5Sopenharmony_ciOpEntryPoint Fragment %main "main" %BaseColor %gl_FragColor
392fd4e5da5Sopenharmony_ciOpExecutionMode %main OriginUpperLeft
393fd4e5da5Sopenharmony_ciOpSource GLSL 140
394fd4e5da5Sopenharmony_ciOpName %main "main"
395fd4e5da5Sopenharmony_ciOpName %S_t "S_t"
396fd4e5da5Sopenharmony_ciOpMemberName %S_t 0 "v0"
397fd4e5da5Sopenharmony_ciOpMemberName %S_t 1 "v1"
398fd4e5da5Sopenharmony_ciOpName %s0 "s0"
399fd4e5da5Sopenharmony_ciOpName %BaseColor "BaseColor"
400fd4e5da5Sopenharmony_ciOpName %gl_FragColor "gl_FragColor"
401fd4e5da5Sopenharmony_ci%void = OpTypeVoid
402fd4e5da5Sopenharmony_ci%8 = OpTypeFunction %void
403fd4e5da5Sopenharmony_ci%float = OpTypeFloat 32
404fd4e5da5Sopenharmony_ci%v4float = OpTypeVector %float 4
405fd4e5da5Sopenharmony_ci%S_t = OpTypeStruct %v4float %v4float
406fd4e5da5Sopenharmony_ci%_ptr_Function_S_t = OpTypePointer Function %S_t
407fd4e5da5Sopenharmony_ci%int = OpTypeInt 32 1
408fd4e5da5Sopenharmony_ci%int_1 = OpConstant %int 1
409fd4e5da5Sopenharmony_ci%_ptr_Input_v4float = OpTypePointer Input %v4float
410fd4e5da5Sopenharmony_ci%BaseColor = OpVariable %_ptr_Input_v4float Input
411fd4e5da5Sopenharmony_ci%_ptr_Function_v4float = OpTypePointer Function %v4float
412fd4e5da5Sopenharmony_ci%_ptr_Output_v4float = OpTypePointer Output %v4float
413fd4e5da5Sopenharmony_ci%gl_FragColor = OpVariable %_ptr_Output_v4float Output
414fd4e5da5Sopenharmony_ci)";
415fd4e5da5Sopenharmony_ci
416fd4e5da5Sopenharmony_ci  const std::string before =
417fd4e5da5Sopenharmony_ci      R"(
418fd4e5da5Sopenharmony_ci; CHECK: [[st_id:%\w+]] = OpLoad %v4float %BaseColor
419fd4e5da5Sopenharmony_ci; CHECK: [[ld1:%\w+]] = OpLoad %S_t %s0
420fd4e5da5Sopenharmony_ci; CHECK: [[ex1:%\w+]] = OpCompositeInsert %S_t [[st_id]] [[ld1]] 1
421fd4e5da5Sopenharmony_ci; CHECK: OpStore %s0 [[ex1]]
422fd4e5da5Sopenharmony_ci; CHECK: [[ld2:%\w+]] = OpLoad %S_t %s0
423fd4e5da5Sopenharmony_ci; CHECK: [[ex2:%\w+]] = OpCompositeExtract %v4float [[ld2]] 1
424fd4e5da5Sopenharmony_ci; CHECK: OpStore %gl_FragColor [[ex2]]
425fd4e5da5Sopenharmony_ci%main = OpFunction %void None %8
426fd4e5da5Sopenharmony_ci%17 = OpLabel
427fd4e5da5Sopenharmony_ci%s0 = OpVariable %_ptr_Function_S_t Function
428fd4e5da5Sopenharmony_ci%18 = OpLoad %v4float %BaseColor
429fd4e5da5Sopenharmony_ci%19 = OpAccessChain %_ptr_Function_v4float %s0 %int_1
430fd4e5da5Sopenharmony_ciOpStore %19 %18
431fd4e5da5Sopenharmony_ci%20 = OpLoad %v4float %19
432fd4e5da5Sopenharmony_ciOpStore %gl_FragColor %20
433fd4e5da5Sopenharmony_ciOpReturn
434fd4e5da5Sopenharmony_ciOpFunctionEnd
435fd4e5da5Sopenharmony_ci)";
436fd4e5da5Sopenharmony_ci
437fd4e5da5Sopenharmony_ci  SinglePassRunAndMatch<LocalAccessChainConvertPass>(predefs_before + before,
438fd4e5da5Sopenharmony_ci                                                     true);
439fd4e5da5Sopenharmony_ci}
440fd4e5da5Sopenharmony_ci
441fd4e5da5Sopenharmony_ciTEST_F(LocalAccessChainConvertTest, OpaqueConverted) {
442fd4e5da5Sopenharmony_ci  // SPIR-V not representable in GLSL; not generatable from HLSL
443fd4e5da5Sopenharmony_ci  // at the moment
444fd4e5da5Sopenharmony_ci
445fd4e5da5Sopenharmony_ci  const std::string predefs =
446fd4e5da5Sopenharmony_ci      R"(
447fd4e5da5Sopenharmony_ciOpCapability Shader
448fd4e5da5Sopenharmony_ci%1 = OpExtInstImport "GLSL.std.450"
449fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
450fd4e5da5Sopenharmony_ciOpEntryPoint Fragment %main "main" %outColor %texCoords
451fd4e5da5Sopenharmony_ciOpExecutionMode %main OriginUpperLeft
452fd4e5da5Sopenharmony_ciOpSource GLSL 140
453fd4e5da5Sopenharmony_ciOpName %main "main"
454fd4e5da5Sopenharmony_ciOpName %S_t "S_t"
455fd4e5da5Sopenharmony_ciOpMemberName %S_t 0 "v0"
456fd4e5da5Sopenharmony_ciOpMemberName %S_t 1 "v1"
457fd4e5da5Sopenharmony_ciOpMemberName %S_t 2 "smp"
458fd4e5da5Sopenharmony_ciOpName %foo_struct_S_t_vf2_vf21_ "foo(struct-S_t-vf2-vf21;"
459fd4e5da5Sopenharmony_ciOpName %s "s"
460fd4e5da5Sopenharmony_ciOpName %outColor "outColor"
461fd4e5da5Sopenharmony_ciOpName %sampler15 "sampler15"
462fd4e5da5Sopenharmony_ciOpName %s0 "s0"
463fd4e5da5Sopenharmony_ciOpName %texCoords "texCoords"
464fd4e5da5Sopenharmony_ciOpName %param "param"
465fd4e5da5Sopenharmony_ciOpDecorate %sampler15 DescriptorSet 0
466fd4e5da5Sopenharmony_ci%void = OpTypeVoid
467fd4e5da5Sopenharmony_ci%12 = OpTypeFunction %void
468fd4e5da5Sopenharmony_ci%float = OpTypeFloat 32
469fd4e5da5Sopenharmony_ci%v2float = OpTypeVector %float 2
470fd4e5da5Sopenharmony_ci%v4float = OpTypeVector %float 4
471fd4e5da5Sopenharmony_ci%_ptr_Output_v4float = OpTypePointer Output %v4float
472fd4e5da5Sopenharmony_ci%outColor = OpVariable %_ptr_Output_v4float Output
473fd4e5da5Sopenharmony_ci%17 = OpTypeImage %float 2D 0 0 0 1 Unknown
474fd4e5da5Sopenharmony_ci%18 = OpTypeSampledImage %17
475fd4e5da5Sopenharmony_ci%S_t = OpTypeStruct %v2float %v2float %18
476fd4e5da5Sopenharmony_ci%_ptr_Function_S_t = OpTypePointer Function %S_t
477fd4e5da5Sopenharmony_ci%20 = OpTypeFunction %void %_ptr_Function_S_t
478fd4e5da5Sopenharmony_ci%_ptr_UniformConstant_18 = OpTypePointer UniformConstant %18
479fd4e5da5Sopenharmony_ci%_ptr_Function_18 = OpTypePointer Function %18
480fd4e5da5Sopenharmony_ci%sampler15 = OpVariable %_ptr_UniformConstant_18 UniformConstant
481fd4e5da5Sopenharmony_ci%int = OpTypeInt 32 1
482fd4e5da5Sopenharmony_ci%int_0 = OpConstant %int 0
483fd4e5da5Sopenharmony_ci%int_2 = OpConstant %int 2
484fd4e5da5Sopenharmony_ci%_ptr_Function_v2float = OpTypePointer Function %v2float
485fd4e5da5Sopenharmony_ci%_ptr_Input_v2float = OpTypePointer Input %v2float
486fd4e5da5Sopenharmony_ci%texCoords = OpVariable %_ptr_Input_v2float Input
487fd4e5da5Sopenharmony_ci)";
488fd4e5da5Sopenharmony_ci
489fd4e5da5Sopenharmony_ci  const std::string before =
490fd4e5da5Sopenharmony_ci      R"(
491fd4e5da5Sopenharmony_ci; CHECK: [[l1:%\w+]] = OpLoad %S_t %param
492fd4e5da5Sopenharmony_ci; CHECK: [[e1:%\w+]] = OpCompositeExtract {{%\w+}} [[l1]] 2
493fd4e5da5Sopenharmony_ci; CHECK: [[l2:%\w+]] = OpLoad %S_t %param
494fd4e5da5Sopenharmony_ci; CHECK: [[e2:%\w+]] = OpCompositeExtract {{%\w+}} [[l2]] 0
495fd4e5da5Sopenharmony_ci; CHECK: OpImageSampleImplicitLod {{%\w+}} [[e1]] [[e2]]
496fd4e5da5Sopenharmony_ci%main = OpFunction %void None %12
497fd4e5da5Sopenharmony_ci%28 = OpLabel
498fd4e5da5Sopenharmony_ci%s0 = OpVariable %_ptr_Function_S_t Function
499fd4e5da5Sopenharmony_ci%param = OpVariable %_ptr_Function_S_t Function
500fd4e5da5Sopenharmony_ci%29 = OpLoad %v2float %texCoords
501fd4e5da5Sopenharmony_ci%30 = OpAccessChain %_ptr_Function_v2float %s0 %int_0
502fd4e5da5Sopenharmony_ciOpStore %30 %29
503fd4e5da5Sopenharmony_ci%31 = OpLoad %18 %sampler15
504fd4e5da5Sopenharmony_ci%32 = OpAccessChain %_ptr_Function_18 %s0 %int_2
505fd4e5da5Sopenharmony_ciOpStore %32 %31
506fd4e5da5Sopenharmony_ci%33 = OpLoad %S_t %s0
507fd4e5da5Sopenharmony_ciOpStore %param %33
508fd4e5da5Sopenharmony_ci%34 = OpAccessChain %_ptr_Function_18 %param %int_2
509fd4e5da5Sopenharmony_ci%35 = OpLoad %18 %34
510fd4e5da5Sopenharmony_ci%36 = OpAccessChain %_ptr_Function_v2float %param %int_0
511fd4e5da5Sopenharmony_ci%37 = OpLoad %v2float %36
512fd4e5da5Sopenharmony_ci%38 = OpImageSampleImplicitLod %v4float %35 %37
513fd4e5da5Sopenharmony_ciOpStore %outColor %38
514fd4e5da5Sopenharmony_ciOpReturn
515fd4e5da5Sopenharmony_ciOpFunctionEnd
516fd4e5da5Sopenharmony_ci)";
517fd4e5da5Sopenharmony_ci
518fd4e5da5Sopenharmony_ci  const std::string remain =
519fd4e5da5Sopenharmony_ci      R"(%foo_struct_S_t_vf2_vf21_ = OpFunction %void None %20
520fd4e5da5Sopenharmony_ci%s = OpFunctionParameter %_ptr_Function_S_t
521fd4e5da5Sopenharmony_ci%39 = OpLabel
522fd4e5da5Sopenharmony_ci%40 = OpAccessChain %_ptr_Function_18 %s %int_2
523fd4e5da5Sopenharmony_ci%41 = OpLoad %18 %40
524fd4e5da5Sopenharmony_ci%42 = OpAccessChain %_ptr_Function_v2float %s %int_0
525fd4e5da5Sopenharmony_ci%43 = OpLoad %v2float %42
526fd4e5da5Sopenharmony_ci%44 = OpImageSampleImplicitLod %v4float %41 %43
527fd4e5da5Sopenharmony_ciOpStore %outColor %44
528fd4e5da5Sopenharmony_ciOpReturn
529fd4e5da5Sopenharmony_ciOpFunctionEnd
530fd4e5da5Sopenharmony_ci)";
531fd4e5da5Sopenharmony_ci
532fd4e5da5Sopenharmony_ci  SinglePassRunAndMatch<LocalAccessChainConvertPass>(predefs + before + remain,
533fd4e5da5Sopenharmony_ci                                                     true);
534fd4e5da5Sopenharmony_ci}
535fd4e5da5Sopenharmony_ci
536fd4e5da5Sopenharmony_ciTEST_F(LocalAccessChainConvertTest, NestedStructsConverted) {
537fd4e5da5Sopenharmony_ci  //  #version 140
538fd4e5da5Sopenharmony_ci  //
539fd4e5da5Sopenharmony_ci  //  in vec4 BaseColor;
540fd4e5da5Sopenharmony_ci  //
541fd4e5da5Sopenharmony_ci  //  struct S1_t {
542fd4e5da5Sopenharmony_ci  //      vec4 v1;
543fd4e5da5Sopenharmony_ci  //  };
544fd4e5da5Sopenharmony_ci  //
545fd4e5da5Sopenharmony_ci  //  struct S2_t {
546fd4e5da5Sopenharmony_ci  //      vec4 v2;
547fd4e5da5Sopenharmony_ci  //      S1_t s1;
548fd4e5da5Sopenharmony_ci  //  };
549fd4e5da5Sopenharmony_ci  //
550fd4e5da5Sopenharmony_ci  //  void main()
551fd4e5da5Sopenharmony_ci  //  {
552fd4e5da5Sopenharmony_ci  //      S2_t s2;
553fd4e5da5Sopenharmony_ci  //      s2.s1.v1 = BaseColor;
554fd4e5da5Sopenharmony_ci  //      gl_FragColor = s2.s1.v1;
555fd4e5da5Sopenharmony_ci  //  }
556fd4e5da5Sopenharmony_ci
557fd4e5da5Sopenharmony_ci  const std::string predefs_before =
558fd4e5da5Sopenharmony_ci      R"(OpCapability Shader
559fd4e5da5Sopenharmony_ci%1 = OpExtInstImport "GLSL.std.450"
560fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
561fd4e5da5Sopenharmony_ciOpEntryPoint Fragment %main "main" %BaseColor %gl_FragColor
562fd4e5da5Sopenharmony_ciOpExecutionMode %main OriginUpperLeft
563fd4e5da5Sopenharmony_ciOpSource GLSL 140
564fd4e5da5Sopenharmony_ciOpName %main "main"
565fd4e5da5Sopenharmony_ciOpName %S1_t "S1_t"
566fd4e5da5Sopenharmony_ciOpMemberName %S1_t 0 "v1"
567fd4e5da5Sopenharmony_ciOpName %S2_t "S2_t"
568fd4e5da5Sopenharmony_ciOpMemberName %S2_t 0 "v2"
569fd4e5da5Sopenharmony_ciOpMemberName %S2_t 1 "s1"
570fd4e5da5Sopenharmony_ciOpName %s2 "s2"
571fd4e5da5Sopenharmony_ciOpName %BaseColor "BaseColor"
572fd4e5da5Sopenharmony_ciOpName %gl_FragColor "gl_FragColor"
573fd4e5da5Sopenharmony_ci%void = OpTypeVoid
574fd4e5da5Sopenharmony_ci%9 = OpTypeFunction %void
575fd4e5da5Sopenharmony_ci%float = OpTypeFloat 32
576fd4e5da5Sopenharmony_ci%v4float = OpTypeVector %float 4
577fd4e5da5Sopenharmony_ci%S1_t = OpTypeStruct %v4float
578fd4e5da5Sopenharmony_ci%S2_t = OpTypeStruct %v4float %S1_t
579fd4e5da5Sopenharmony_ci%_ptr_Function_S2_t = OpTypePointer Function %S2_t
580fd4e5da5Sopenharmony_ci%int = OpTypeInt 32 1
581fd4e5da5Sopenharmony_ci%int_1 = OpConstant %int 1
582fd4e5da5Sopenharmony_ci%int_0 = OpConstant %int 0
583fd4e5da5Sopenharmony_ci%_ptr_Input_v4float = OpTypePointer Input %v4float
584fd4e5da5Sopenharmony_ci%BaseColor = OpVariable %_ptr_Input_v4float Input
585fd4e5da5Sopenharmony_ci%_ptr_Function_v4float = OpTypePointer Function %v4float
586fd4e5da5Sopenharmony_ci%_ptr_Output_v4float = OpTypePointer Output %v4float
587fd4e5da5Sopenharmony_ci%gl_FragColor = OpVariable %_ptr_Output_v4float Output
588fd4e5da5Sopenharmony_ci)";
589fd4e5da5Sopenharmony_ci
590fd4e5da5Sopenharmony_ci  const std::string before =
591fd4e5da5Sopenharmony_ci      R"(
592fd4e5da5Sopenharmony_ci; CHECK: [[st_id:%\w+]] = OpLoad %v4float %BaseColor
593fd4e5da5Sopenharmony_ci; CHECK: [[ld1:%\w+]] = OpLoad %S2_t %s2
594fd4e5da5Sopenharmony_ci; CHECK: [[ex1:%\w+]] = OpCompositeInsert %S2_t [[st_id]] [[ld1]] 1 0
595fd4e5da5Sopenharmony_ci; CHECK: OpStore %s2 [[ex1]]
596fd4e5da5Sopenharmony_ci; CHECK: [[ld2:%\w+]] = OpLoad %S2_t %s2
597fd4e5da5Sopenharmony_ci; CHECK: [[ex2:%\w+]] = OpCompositeExtract %v4float [[ld2]] 1 0
598fd4e5da5Sopenharmony_ci; CHECK: OpStore %gl_FragColor [[ex2]]
599fd4e5da5Sopenharmony_ci%main = OpFunction %void None %9
600fd4e5da5Sopenharmony_ci%19 = OpLabel
601fd4e5da5Sopenharmony_ci%s2 = OpVariable %_ptr_Function_S2_t Function
602fd4e5da5Sopenharmony_ci%20 = OpLoad %v4float %BaseColor
603fd4e5da5Sopenharmony_ci%21 = OpAccessChain %_ptr_Function_v4float %s2 %int_1 %int_0
604fd4e5da5Sopenharmony_ciOpStore %21 %20
605fd4e5da5Sopenharmony_ci%22 = OpAccessChain %_ptr_Function_v4float %s2 %int_1 %int_0
606fd4e5da5Sopenharmony_ci%23 = OpLoad %v4float %22
607fd4e5da5Sopenharmony_ciOpStore %gl_FragColor %23
608fd4e5da5Sopenharmony_ciOpReturn
609fd4e5da5Sopenharmony_ciOpFunctionEnd
610fd4e5da5Sopenharmony_ci)";
611fd4e5da5Sopenharmony_ci
612fd4e5da5Sopenharmony_ci  SinglePassRunAndMatch<LocalAccessChainConvertPass>(predefs_before + before,
613fd4e5da5Sopenharmony_ci                                                     true);
614fd4e5da5Sopenharmony_ci}
615fd4e5da5Sopenharmony_ci
616fd4e5da5Sopenharmony_ciTEST_F(LocalAccessChainConvertTest, SomeAccessChainsHaveNoUse) {
617fd4e5da5Sopenharmony_ci  // Based on HLSL source code:
618fd4e5da5Sopenharmony_ci  // struct S {
619fd4e5da5Sopenharmony_ci  //   float f;
620fd4e5da5Sopenharmony_ci  // };
621fd4e5da5Sopenharmony_ci
622fd4e5da5Sopenharmony_ci  // float main(float input : A) : B {
623fd4e5da5Sopenharmony_ci  //   S local = { input };
624fd4e5da5Sopenharmony_ci  //   return local.f;
625fd4e5da5Sopenharmony_ci  // }
626fd4e5da5Sopenharmony_ci
627fd4e5da5Sopenharmony_ci  const std::string predefs = R"(OpCapability Shader
628fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
629fd4e5da5Sopenharmony_ciOpEntryPoint Vertex %main "main" %in_var_A %out_var_B
630fd4e5da5Sopenharmony_ciOpName %main "main"
631fd4e5da5Sopenharmony_ciOpName %in_var_A "in.var.A"
632fd4e5da5Sopenharmony_ciOpName %out_var_B "out.var.B"
633fd4e5da5Sopenharmony_ciOpName %S "S"
634fd4e5da5Sopenharmony_ciOpName %local "local"
635fd4e5da5Sopenharmony_ci%int = OpTypeInt 32 1
636fd4e5da5Sopenharmony_ci%void = OpTypeVoid
637fd4e5da5Sopenharmony_ci%8 = OpTypeFunction %void
638fd4e5da5Sopenharmony_ci%float = OpTypeFloat 32
639fd4e5da5Sopenharmony_ci%_ptr_Function_float = OpTypePointer Function %float
640fd4e5da5Sopenharmony_ci%_ptr_Input_float = OpTypePointer Input %float
641fd4e5da5Sopenharmony_ci%_ptr_Output_float = OpTypePointer Output %float
642fd4e5da5Sopenharmony_ci%S = OpTypeStruct %float
643fd4e5da5Sopenharmony_ci%_ptr_Function_S = OpTypePointer Function %S
644fd4e5da5Sopenharmony_ci%int_0 = OpConstant %int 0
645fd4e5da5Sopenharmony_ci%in_var_A = OpVariable %_ptr_Input_float Input
646fd4e5da5Sopenharmony_ci%out_var_B = OpVariable %_ptr_Output_float Output
647fd4e5da5Sopenharmony_ci%main = OpFunction %void None %8
648fd4e5da5Sopenharmony_ci%15 = OpLabel
649fd4e5da5Sopenharmony_ci%local = OpVariable %_ptr_Function_S Function
650fd4e5da5Sopenharmony_ci%16 = OpLoad %float %in_var_A
651fd4e5da5Sopenharmony_ci%17 = OpCompositeConstruct %S %16
652fd4e5da5Sopenharmony_ciOpStore %local %17
653fd4e5da5Sopenharmony_ci)";
654fd4e5da5Sopenharmony_ci
655fd4e5da5Sopenharmony_ci  const std::string before =
656fd4e5da5Sopenharmony_ci      R"(
657fd4e5da5Sopenharmony_ci; CHECK: [[ld:%\w+]] = OpLoad %S %local
658fd4e5da5Sopenharmony_ci; CHECK: [[ex:%\w+]] = OpCompositeExtract %float [[ld]] 0
659fd4e5da5Sopenharmony_ci; CHECK: OpStore %out_var_B [[ex]]
660fd4e5da5Sopenharmony_ci%18 = OpAccessChain %_ptr_Function_float %local %int_0
661fd4e5da5Sopenharmony_ci%19 = OpAccessChain %_ptr_Function_float %local %int_0
662fd4e5da5Sopenharmony_ci%20 = OpLoad %float %18
663fd4e5da5Sopenharmony_ciOpStore %out_var_B %20
664fd4e5da5Sopenharmony_ciOpReturn
665fd4e5da5Sopenharmony_ciOpFunctionEnd
666fd4e5da5Sopenharmony_ci)";
667fd4e5da5Sopenharmony_ci
668fd4e5da5Sopenharmony_ci  SinglePassRunAndMatch<LocalAccessChainConvertPass>(predefs + before, true);
669fd4e5da5Sopenharmony_ci}
670fd4e5da5Sopenharmony_ci
671fd4e5da5Sopenharmony_ciTEST_F(LocalAccessChainConvertTest,
672fd4e5da5Sopenharmony_ci       StructOfVecsOfFloatConvertedWithDecorationOnLoad) {
673fd4e5da5Sopenharmony_ci  //  #version 140
674fd4e5da5Sopenharmony_ci  //
675fd4e5da5Sopenharmony_ci  //  in vec4 BaseColor;
676fd4e5da5Sopenharmony_ci  //
677fd4e5da5Sopenharmony_ci  //  struct S_t {
678fd4e5da5Sopenharmony_ci  //      vec4 v0;
679fd4e5da5Sopenharmony_ci  //      vec4 v1;
680fd4e5da5Sopenharmony_ci  //  };
681fd4e5da5Sopenharmony_ci  //
682fd4e5da5Sopenharmony_ci  //  void main()
683fd4e5da5Sopenharmony_ci  //  {
684fd4e5da5Sopenharmony_ci  //      S_t s0;
685fd4e5da5Sopenharmony_ci  //      s0.v1 = BaseColor;
686fd4e5da5Sopenharmony_ci  //      gl_FragColor = s0.v1;
687fd4e5da5Sopenharmony_ci  //  }
688fd4e5da5Sopenharmony_ci
689fd4e5da5Sopenharmony_ci  const std::string predefs_before =
690fd4e5da5Sopenharmony_ci      R"(OpCapability Shader
691fd4e5da5Sopenharmony_ci%1 = OpExtInstImport "GLSL.std.450"
692fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
693fd4e5da5Sopenharmony_ciOpEntryPoint Fragment %main "main" %BaseColor %gl_FragColor
694fd4e5da5Sopenharmony_ciOpExecutionMode %main OriginUpperLeft
695fd4e5da5Sopenharmony_ciOpSource GLSL 140
696fd4e5da5Sopenharmony_ciOpName %main "main"
697fd4e5da5Sopenharmony_ciOpName %S_t "S_t"
698fd4e5da5Sopenharmony_ciOpMemberName %S_t 0 "v0"
699fd4e5da5Sopenharmony_ciOpMemberName %S_t 1 "v1"
700fd4e5da5Sopenharmony_ciOpName %s0 "s0"
701fd4e5da5Sopenharmony_ciOpName %BaseColor "BaseColor"
702fd4e5da5Sopenharmony_ciOpName %gl_FragColor "gl_FragColor"
703fd4e5da5Sopenharmony_ciOpDecorate %21 RelaxedPrecision
704fd4e5da5Sopenharmony_ci%void = OpTypeVoid
705fd4e5da5Sopenharmony_ci%8 = OpTypeFunction %void
706fd4e5da5Sopenharmony_ci%float = OpTypeFloat 32
707fd4e5da5Sopenharmony_ci%v4float = OpTypeVector %float 4
708fd4e5da5Sopenharmony_ci%S_t = OpTypeStruct %v4float %v4float
709fd4e5da5Sopenharmony_ci%_ptr_Function_S_t = OpTypePointer Function %S_t
710fd4e5da5Sopenharmony_ci%int = OpTypeInt 32 1
711fd4e5da5Sopenharmony_ci%int_1 = OpConstant %int 1
712fd4e5da5Sopenharmony_ci%_ptr_Input_v4float = OpTypePointer Input %v4float
713fd4e5da5Sopenharmony_ci%BaseColor = OpVariable %_ptr_Input_v4float Input
714fd4e5da5Sopenharmony_ci%_ptr_Function_v4float = OpTypePointer Function %v4float
715fd4e5da5Sopenharmony_ci%_ptr_Output_v4float = OpTypePointer Output %v4float
716fd4e5da5Sopenharmony_ci%gl_FragColor = OpVariable %_ptr_Output_v4float Output
717fd4e5da5Sopenharmony_ci)";
718fd4e5da5Sopenharmony_ci
719fd4e5da5Sopenharmony_ci  const std::string before =
720fd4e5da5Sopenharmony_ci      R"(
721fd4e5da5Sopenharmony_ci; CHECK: OpDecorate
722fd4e5da5Sopenharmony_ci; CHECK: OpDecorate [[ld2:%\w+]] RelaxedPrecision
723fd4e5da5Sopenharmony_ci; CHECK-NOT: OpDecorate
724fd4e5da5Sopenharmony_ci; CHECK: [[st_id:%\w+]] = OpLoad %v4float %BaseColor
725fd4e5da5Sopenharmony_ci; CHECK: [[ld1:%\w+]] = OpLoad %S_t %s0
726fd4e5da5Sopenharmony_ci; CHECK: [[ins:%\w+]] = OpCompositeInsert %S_t [[st_id]] [[ld1]] 1
727fd4e5da5Sopenharmony_ci; CHECK: OpStore %s0 [[ins]]
728fd4e5da5Sopenharmony_ci; CHECK: [[ld2]] = OpLoad %S_t %s0
729fd4e5da5Sopenharmony_ci; CHECK: [[ex2:%\w+]] = OpCompositeExtract %v4float [[ld2]] 1
730fd4e5da5Sopenharmony_ci; CHECK: OpStore %gl_FragColor [[ex2]]
731fd4e5da5Sopenharmony_ci%main = OpFunction %void None %8
732fd4e5da5Sopenharmony_ci%17 = OpLabel
733fd4e5da5Sopenharmony_ci%s0 = OpVariable %_ptr_Function_S_t Function
734fd4e5da5Sopenharmony_ci%18 = OpLoad %v4float %BaseColor
735fd4e5da5Sopenharmony_ci%19 = OpAccessChain %_ptr_Function_v4float %s0 %int_1
736fd4e5da5Sopenharmony_ciOpStore %19 %18
737fd4e5da5Sopenharmony_ci%20 = OpAccessChain %_ptr_Function_v4float %s0 %int_1
738fd4e5da5Sopenharmony_ci%21 = OpLoad %v4float %20
739fd4e5da5Sopenharmony_ciOpStore %gl_FragColor %21
740fd4e5da5Sopenharmony_ciOpReturn
741fd4e5da5Sopenharmony_ciOpFunctionEnd
742fd4e5da5Sopenharmony_ci)";
743fd4e5da5Sopenharmony_ci
744fd4e5da5Sopenharmony_ci  SinglePassRunAndMatch<LocalAccessChainConvertPass>(predefs_before + before,
745fd4e5da5Sopenharmony_ci                                                     true);
746fd4e5da5Sopenharmony_ci}
747fd4e5da5Sopenharmony_ci
748fd4e5da5Sopenharmony_ciTEST_F(LocalAccessChainConvertTest,
749fd4e5da5Sopenharmony_ci       StructOfVecsOfFloatConvertedWithDecorationOnStore) {
750fd4e5da5Sopenharmony_ci  //  #version 140
751fd4e5da5Sopenharmony_ci  //
752fd4e5da5Sopenharmony_ci  //  in vec4 BaseColor;
753fd4e5da5Sopenharmony_ci  //
754fd4e5da5Sopenharmony_ci  //  struct S_t {
755fd4e5da5Sopenharmony_ci  //      vec4 v0;
756fd4e5da5Sopenharmony_ci  //      vec4 v1;
757fd4e5da5Sopenharmony_ci  //  };
758fd4e5da5Sopenharmony_ci  //
759fd4e5da5Sopenharmony_ci  //  void main()
760fd4e5da5Sopenharmony_ci  //  {
761fd4e5da5Sopenharmony_ci  //      S_t s0;
762fd4e5da5Sopenharmony_ci  //      s0.v1 = BaseColor;
763fd4e5da5Sopenharmony_ci  //      gl_FragColor = s0.v1;
764fd4e5da5Sopenharmony_ci  //  }
765fd4e5da5Sopenharmony_ci
766fd4e5da5Sopenharmony_ci  const std::string predefs_before =
767fd4e5da5Sopenharmony_ci      R"(OpCapability Shader
768fd4e5da5Sopenharmony_ci%1 = OpExtInstImport "GLSL.std.450"
769fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
770fd4e5da5Sopenharmony_ciOpEntryPoint Fragment %main "main" %BaseColor %gl_FragColor
771fd4e5da5Sopenharmony_ciOpExecutionMode %main OriginUpperLeft
772fd4e5da5Sopenharmony_ciOpSource GLSL 140
773fd4e5da5Sopenharmony_ciOpName %main "main"
774fd4e5da5Sopenharmony_ciOpName %S_t "S_t"
775fd4e5da5Sopenharmony_ciOpMemberName %S_t 0 "v0"
776fd4e5da5Sopenharmony_ciOpMemberName %S_t 1 "v1"
777fd4e5da5Sopenharmony_ciOpName %s0 "s0"
778fd4e5da5Sopenharmony_ciOpName %BaseColor "BaseColor"
779fd4e5da5Sopenharmony_ciOpName %gl_FragColor "gl_FragColor"
780fd4e5da5Sopenharmony_ciOpDecorate %s0 RelaxedPrecision
781fd4e5da5Sopenharmony_ci%void = OpTypeVoid
782fd4e5da5Sopenharmony_ci%8 = OpTypeFunction %void
783fd4e5da5Sopenharmony_ci%float = OpTypeFloat 32
784fd4e5da5Sopenharmony_ci%v4float = OpTypeVector %float 4
785fd4e5da5Sopenharmony_ci%S_t = OpTypeStruct %v4float %v4float
786fd4e5da5Sopenharmony_ci%_ptr_Function_S_t = OpTypePointer Function %S_t
787fd4e5da5Sopenharmony_ci%int = OpTypeInt 32 1
788fd4e5da5Sopenharmony_ci%int_1 = OpConstant %int 1
789fd4e5da5Sopenharmony_ci%_ptr_Input_v4float = OpTypePointer Input %v4float
790fd4e5da5Sopenharmony_ci%BaseColor = OpVariable %_ptr_Input_v4float Input
791fd4e5da5Sopenharmony_ci%_ptr_Function_v4float = OpTypePointer Function %v4float
792fd4e5da5Sopenharmony_ci%_ptr_Output_v4float = OpTypePointer Output %v4float
793fd4e5da5Sopenharmony_ci%gl_FragColor = OpVariable %_ptr_Output_v4float Output
794fd4e5da5Sopenharmony_ci)";
795fd4e5da5Sopenharmony_ci
796fd4e5da5Sopenharmony_ci  const std::string before =
797fd4e5da5Sopenharmony_ci      R"(
798fd4e5da5Sopenharmony_ci; CHECK: OpDecorate
799fd4e5da5Sopenharmony_ci; CHECK: OpDecorate [[ld1:%\w+]] RelaxedPrecision
800fd4e5da5Sopenharmony_ci; CHECK: OpDecorate [[ins:%\w+]] RelaxedPrecision
801fd4e5da5Sopenharmony_ci; CHECK-NOT: OpDecorate
802fd4e5da5Sopenharmony_ci; CHECK: [[st_id:%\w+]] = OpLoad %v4float %BaseColor
803fd4e5da5Sopenharmony_ci; CHECK: [[ld1]] = OpLoad %S_t %s0
804fd4e5da5Sopenharmony_ci; CHECK: [[ins]] = OpCompositeInsert %S_t [[st_id]] [[ld1]] 1
805fd4e5da5Sopenharmony_ci; CHECK: OpStore %s0 [[ins]]
806fd4e5da5Sopenharmony_ci; CHECK: [[ld2:%\w+]] = OpLoad %S_t %s0
807fd4e5da5Sopenharmony_ci; CHECK: [[ex2:%\w+]] = OpCompositeExtract %v4float [[ld2]] 1
808fd4e5da5Sopenharmony_ci; CHECK: OpStore %gl_FragColor [[ex2]]
809fd4e5da5Sopenharmony_ci%main = OpFunction %void None %8
810fd4e5da5Sopenharmony_ci%17 = OpLabel
811fd4e5da5Sopenharmony_ci%s0 = OpVariable %_ptr_Function_S_t Function
812fd4e5da5Sopenharmony_ci%18 = OpLoad %v4float %BaseColor
813fd4e5da5Sopenharmony_ci%19 = OpAccessChain %_ptr_Function_v4float %s0 %int_1
814fd4e5da5Sopenharmony_ciOpStore %19 %18
815fd4e5da5Sopenharmony_ci%20 = OpAccessChain %_ptr_Function_v4float %s0 %int_1
816fd4e5da5Sopenharmony_ci%21 = OpLoad %v4float %20
817fd4e5da5Sopenharmony_ciOpStore %gl_FragColor %21
818fd4e5da5Sopenharmony_ciOpReturn
819fd4e5da5Sopenharmony_ciOpFunctionEnd
820fd4e5da5Sopenharmony_ci)";
821fd4e5da5Sopenharmony_ci
822fd4e5da5Sopenharmony_ci  SinglePassRunAndMatch<LocalAccessChainConvertPass>(predefs_before + before,
823fd4e5da5Sopenharmony_ci                                                     true);
824fd4e5da5Sopenharmony_ci}
825fd4e5da5Sopenharmony_ci
826fd4e5da5Sopenharmony_ciTEST_F(LocalAccessChainConvertTest, DynamicallyIndexedVarNotConverted) {
827fd4e5da5Sopenharmony_ci  //  #version 140
828fd4e5da5Sopenharmony_ci  //
829fd4e5da5Sopenharmony_ci  //  in vec4 BaseColor;
830fd4e5da5Sopenharmony_ci  //  flat in int Idx;
831fd4e5da5Sopenharmony_ci  //  in float Bi;
832fd4e5da5Sopenharmony_ci  //
833fd4e5da5Sopenharmony_ci  //  struct S_t {
834fd4e5da5Sopenharmony_ci  //      vec4 v0;
835fd4e5da5Sopenharmony_ci  //      vec4 v1;
836fd4e5da5Sopenharmony_ci  //  };
837fd4e5da5Sopenharmony_ci  //
838fd4e5da5Sopenharmony_ci  //  void main()
839fd4e5da5Sopenharmony_ci  //  {
840fd4e5da5Sopenharmony_ci  //      S_t s0;
841fd4e5da5Sopenharmony_ci  //      s0.v1 = BaseColor;
842fd4e5da5Sopenharmony_ci  //      s0.v1[Idx] = Bi;
843fd4e5da5Sopenharmony_ci  //      gl_FragColor = s0.v1;
844fd4e5da5Sopenharmony_ci  //  }
845fd4e5da5Sopenharmony_ci
846fd4e5da5Sopenharmony_ci  const std::string assembly =
847fd4e5da5Sopenharmony_ci      R"(OpCapability Shader
848fd4e5da5Sopenharmony_ci%1 = OpExtInstImport "GLSL.std.450"
849fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
850fd4e5da5Sopenharmony_ciOpEntryPoint Fragment %main "main" %BaseColor %Idx %Bi %gl_FragColor
851fd4e5da5Sopenharmony_ciOpExecutionMode %main OriginUpperLeft
852fd4e5da5Sopenharmony_ciOpSource GLSL 140
853fd4e5da5Sopenharmony_ciOpName %main "main"
854fd4e5da5Sopenharmony_ciOpName %S_t "S_t"
855fd4e5da5Sopenharmony_ciOpMemberName %S_t 0 "v0"
856fd4e5da5Sopenharmony_ciOpMemberName %S_t 1 "v1"
857fd4e5da5Sopenharmony_ciOpName %s0 "s0"
858fd4e5da5Sopenharmony_ciOpName %BaseColor "BaseColor"
859fd4e5da5Sopenharmony_ciOpName %Idx "Idx"
860fd4e5da5Sopenharmony_ciOpName %Bi "Bi"
861fd4e5da5Sopenharmony_ciOpName %gl_FragColor "gl_FragColor"
862fd4e5da5Sopenharmony_ciOpDecorate %Idx Flat
863fd4e5da5Sopenharmony_ci%void = OpTypeVoid
864fd4e5da5Sopenharmony_ci%10 = OpTypeFunction %void
865fd4e5da5Sopenharmony_ci%float = OpTypeFloat 32
866fd4e5da5Sopenharmony_ci%v4float = OpTypeVector %float 4
867fd4e5da5Sopenharmony_ci%S_t = OpTypeStruct %v4float %v4float
868fd4e5da5Sopenharmony_ci%_ptr_Function_S_t = OpTypePointer Function %S_t
869fd4e5da5Sopenharmony_ci%int = OpTypeInt 32 1
870fd4e5da5Sopenharmony_ci%int_1 = OpConstant %int 1
871fd4e5da5Sopenharmony_ci%_ptr_Input_v4float = OpTypePointer Input %v4float
872fd4e5da5Sopenharmony_ci%BaseColor = OpVariable %_ptr_Input_v4float Input
873fd4e5da5Sopenharmony_ci%_ptr_Function_v4float = OpTypePointer Function %v4float
874fd4e5da5Sopenharmony_ci%_ptr_Input_int = OpTypePointer Input %int
875fd4e5da5Sopenharmony_ci%Idx = OpVariable %_ptr_Input_int Input
876fd4e5da5Sopenharmony_ci%_ptr_Input_float = OpTypePointer Input %float
877fd4e5da5Sopenharmony_ci%Bi = OpVariable %_ptr_Input_float Input
878fd4e5da5Sopenharmony_ci%_ptr_Function_float = OpTypePointer Function %float
879fd4e5da5Sopenharmony_ci%_ptr_Output_v4float = OpTypePointer Output %v4float
880fd4e5da5Sopenharmony_ci%gl_FragColor = OpVariable %_ptr_Output_v4float Output
881fd4e5da5Sopenharmony_ci%main = OpFunction %void None %10
882fd4e5da5Sopenharmony_ci%22 = OpLabel
883fd4e5da5Sopenharmony_ci%s0 = OpVariable %_ptr_Function_S_t Function
884fd4e5da5Sopenharmony_ci%23 = OpLoad %v4float %BaseColor
885fd4e5da5Sopenharmony_ci%24 = OpAccessChain %_ptr_Function_v4float %s0 %int_1
886fd4e5da5Sopenharmony_ciOpStore %24 %23
887fd4e5da5Sopenharmony_ci%25 = OpLoad %int %Idx
888fd4e5da5Sopenharmony_ci%26 = OpLoad %float %Bi
889fd4e5da5Sopenharmony_ci%27 = OpAccessChain %_ptr_Function_float %s0 %int_1 %25
890fd4e5da5Sopenharmony_ciOpStore %27 %26
891fd4e5da5Sopenharmony_ci%28 = OpAccessChain %_ptr_Function_v4float %s0 %int_1
892fd4e5da5Sopenharmony_ci%29 = OpLoad %v4float %28
893fd4e5da5Sopenharmony_ciOpStore %gl_FragColor %29
894fd4e5da5Sopenharmony_ciOpReturn
895fd4e5da5Sopenharmony_ciOpFunctionEnd
896fd4e5da5Sopenharmony_ci)";
897fd4e5da5Sopenharmony_ci
898fd4e5da5Sopenharmony_ci  SinglePassRunAndCheck<LocalAccessChainConvertPass>(assembly, assembly, false,
899fd4e5da5Sopenharmony_ci                                                     true);
900fd4e5da5Sopenharmony_ci}
901fd4e5da5Sopenharmony_ci
902fd4e5da5Sopenharmony_ciTEST_F(LocalAccessChainConvertTest, VariablePointersStorageBuffer) {
903fd4e5da5Sopenharmony_ci  // A case with a storage buffer variable pointer.  We should still convert
904fd4e5da5Sopenharmony_ci  // the access chain on the function scope symbol.
905fd4e5da5Sopenharmony_ci  const std::string test =
906fd4e5da5Sopenharmony_ci      R"(
907fd4e5da5Sopenharmony_ci; CHECK: OpFunction
908fd4e5da5Sopenharmony_ci; CHECK: [[var:%\w+]] = OpVariable {{%\w+}} Function
909fd4e5da5Sopenharmony_ci; CHECK: [[ld:%\w+]] = OpLoad {{%\w+}} [[var]]
910fd4e5da5Sopenharmony_ci; CHECK: OpCompositeExtract {{%\w+}} [[ld]] 0 0
911fd4e5da5Sopenharmony_ci               OpCapability Shader
912fd4e5da5Sopenharmony_ci               OpCapability VariablePointersStorageBuffer
913fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
914fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
915fd4e5da5Sopenharmony_ci               OpEntryPoint GLCompute %2 "main"
916fd4e5da5Sopenharmony_ci               OpExecutionMode %2 LocalSize 1 1 1
917fd4e5da5Sopenharmony_ci               OpSource GLSL 450
918fd4e5da5Sopenharmony_ci               OpMemberDecorate %_struct_3 0 Offset 0
919fd4e5da5Sopenharmony_ci               OpDecorate %_struct_3 Block
920fd4e5da5Sopenharmony_ci               OpDecorate %4 DescriptorSet 0
921fd4e5da5Sopenharmony_ci               OpDecorate %4 Binding 0
922fd4e5da5Sopenharmony_ci               OpDecorate %_ptr_StorageBuffer_int ArrayStride 4
923fd4e5da5Sopenharmony_ci               OpDecorate %_arr_int_int_128 ArrayStride 4
924fd4e5da5Sopenharmony_ci       %void = OpTypeVoid
925fd4e5da5Sopenharmony_ci          %8 = OpTypeFunction %void
926fd4e5da5Sopenharmony_ci        %int = OpTypeInt 32 1
927fd4e5da5Sopenharmony_ci    %int_128 = OpConstant %int 128
928fd4e5da5Sopenharmony_ci%_arr_int_int_128 = OpTypeArray %int %int_128
929fd4e5da5Sopenharmony_ci  %_struct_3 = OpTypeStruct %_arr_int_int_128
930fd4e5da5Sopenharmony_ci%_ptr_StorageBuffer__struct_3 = OpTypePointer StorageBuffer %_struct_3
931fd4e5da5Sopenharmony_ci%_ptr_Function__struct_3 = OpTypePointer Function %_struct_3
932fd4e5da5Sopenharmony_ci          %4 = OpVariable %_ptr_StorageBuffer__struct_3 StorageBuffer
933fd4e5da5Sopenharmony_ci       %bool = OpTypeBool
934fd4e5da5Sopenharmony_ci       %true = OpConstantTrue %bool
935fd4e5da5Sopenharmony_ci      %int_0 = OpConstant %int 0
936fd4e5da5Sopenharmony_ci      %int_1 = OpConstant %int 1
937fd4e5da5Sopenharmony_ci%_ptr_StorageBuffer_int = OpTypePointer StorageBuffer %int
938fd4e5da5Sopenharmony_ci%_ptr_Function_int = OpTypePointer Function %int
939fd4e5da5Sopenharmony_ci          %2 = OpFunction %void None %8
940fd4e5da5Sopenharmony_ci         %18 = OpLabel
941fd4e5da5Sopenharmony_ci         %19 = OpVariable %_ptr_Function__struct_3 Function
942fd4e5da5Sopenharmony_ci         %20 = OpAccessChain %_ptr_StorageBuffer_int %4 %int_0 %int_0
943fd4e5da5Sopenharmony_ci               OpBranch %21
944fd4e5da5Sopenharmony_ci         %21 = OpLabel
945fd4e5da5Sopenharmony_ci         %22 = OpPhi %_ptr_StorageBuffer_int %20 %18 %23 %24
946fd4e5da5Sopenharmony_ci               OpLoopMerge %25 %24 None
947fd4e5da5Sopenharmony_ci               OpBranchConditional %true %26 %25
948fd4e5da5Sopenharmony_ci         %26 = OpLabel
949fd4e5da5Sopenharmony_ci               OpStore %22 %int_0
950fd4e5da5Sopenharmony_ci               OpBranch %24
951fd4e5da5Sopenharmony_ci         %24 = OpLabel
952fd4e5da5Sopenharmony_ci         %23 = OpPtrAccessChain %_ptr_StorageBuffer_int %22 %int_1
953fd4e5da5Sopenharmony_ci               OpBranch %21
954fd4e5da5Sopenharmony_ci         %25 = OpLabel
955fd4e5da5Sopenharmony_ci         %27 = OpAccessChain %_ptr_Function_int %19 %int_0 %int_0
956fd4e5da5Sopenharmony_ci         %28 = OpLoad %int %27
957fd4e5da5Sopenharmony_ci               OpReturn
958fd4e5da5Sopenharmony_ci               OpFunctionEnd
959fd4e5da5Sopenharmony_ci)";
960fd4e5da5Sopenharmony_ci
961fd4e5da5Sopenharmony_ci  SinglePassRunAndMatch<LocalAccessChainConvertPass>(test, true);
962fd4e5da5Sopenharmony_ci}
963fd4e5da5Sopenharmony_ci
964fd4e5da5Sopenharmony_ciTEST_F(LocalAccessChainConvertTest, VariablePointers) {
965fd4e5da5Sopenharmony_ci  // A case with variable pointer capability.  We should not convert
966fd4e5da5Sopenharmony_ci  // the access chain on the function scope symbol because the variable pointer
967fd4e5da5Sopenharmony_ci  // could the analysis to miss references to function scope symbols.
968fd4e5da5Sopenharmony_ci  const std::string test =
969fd4e5da5Sopenharmony_ci      R"(OpCapability Shader
970fd4e5da5Sopenharmony_ciOpCapability VariablePointers
971fd4e5da5Sopenharmony_ci%1 = OpExtInstImport "GLSL.std.450"
972fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
973fd4e5da5Sopenharmony_ciOpEntryPoint GLCompute %2 "main"
974fd4e5da5Sopenharmony_ciOpExecutionMode %2 LocalSize 1 1 1
975fd4e5da5Sopenharmony_ciOpSource GLSL 450
976fd4e5da5Sopenharmony_ciOpMemberDecorate %_struct_3 0 Offset 0
977fd4e5da5Sopenharmony_ciOpDecorate %_struct_3 Block
978fd4e5da5Sopenharmony_ciOpDecorate %4 DescriptorSet 0
979fd4e5da5Sopenharmony_ciOpDecorate %4 Binding 0
980fd4e5da5Sopenharmony_ciOpDecorate %_ptr_StorageBuffer_int ArrayStride 4
981fd4e5da5Sopenharmony_ciOpDecorate %_arr_int_int_128 ArrayStride 4
982fd4e5da5Sopenharmony_ci%void = OpTypeVoid
983fd4e5da5Sopenharmony_ci%8 = OpTypeFunction %void
984fd4e5da5Sopenharmony_ci%int = OpTypeInt 32 1
985fd4e5da5Sopenharmony_ci%int_128 = OpConstant %int 128
986fd4e5da5Sopenharmony_ci%_arr_int_int_128 = OpTypeArray %int %int_128
987fd4e5da5Sopenharmony_ci%_struct_3 = OpTypeStruct %_arr_int_int_128
988fd4e5da5Sopenharmony_ci%_ptr_StorageBuffer__struct_3 = OpTypePointer StorageBuffer %_struct_3
989fd4e5da5Sopenharmony_ci%_ptr_Function__struct_3 = OpTypePointer Function %_struct_3
990fd4e5da5Sopenharmony_ci%4 = OpVariable %_ptr_StorageBuffer__struct_3 StorageBuffer
991fd4e5da5Sopenharmony_ci%bool = OpTypeBool
992fd4e5da5Sopenharmony_ci%true = OpConstantTrue %bool
993fd4e5da5Sopenharmony_ci%int_0 = OpConstant %int 0
994fd4e5da5Sopenharmony_ci%int_1 = OpConstant %int 1
995fd4e5da5Sopenharmony_ci%_ptr_StorageBuffer_int = OpTypePointer StorageBuffer %int
996fd4e5da5Sopenharmony_ci%_ptr_Function_int = OpTypePointer Function %int
997fd4e5da5Sopenharmony_ci%2 = OpFunction %void None %8
998fd4e5da5Sopenharmony_ci%18 = OpLabel
999fd4e5da5Sopenharmony_ci%19 = OpVariable %_ptr_Function__struct_3 Function
1000fd4e5da5Sopenharmony_ci%20 = OpAccessChain %_ptr_StorageBuffer_int %4 %int_0 %int_0
1001fd4e5da5Sopenharmony_ciOpBranch %21
1002fd4e5da5Sopenharmony_ci%21 = OpLabel
1003fd4e5da5Sopenharmony_ci%22 = OpPhi %_ptr_StorageBuffer_int %20 %18 %23 %24
1004fd4e5da5Sopenharmony_ciOpLoopMerge %25 %24 None
1005fd4e5da5Sopenharmony_ciOpBranchConditional %true %26 %25
1006fd4e5da5Sopenharmony_ci%26 = OpLabel
1007fd4e5da5Sopenharmony_ciOpStore %22 %int_0
1008fd4e5da5Sopenharmony_ciOpBranch %24
1009fd4e5da5Sopenharmony_ci%24 = OpLabel
1010fd4e5da5Sopenharmony_ci%23 = OpPtrAccessChain %_ptr_StorageBuffer_int %22 %int_1
1011fd4e5da5Sopenharmony_ciOpBranch %21
1012fd4e5da5Sopenharmony_ci%25 = OpLabel
1013fd4e5da5Sopenharmony_ci%27 = OpAccessChain %_ptr_Function_int %19 %int_0 %int_0
1014fd4e5da5Sopenharmony_ci%28 = OpLoad %int %27
1015fd4e5da5Sopenharmony_ciOpReturn
1016fd4e5da5Sopenharmony_ciOpFunctionEnd
1017fd4e5da5Sopenharmony_ci)";
1018fd4e5da5Sopenharmony_ci
1019fd4e5da5Sopenharmony_ci  SinglePassRunAndCheck<LocalAccessChainConvertPass>(test, test, false, true);
1020fd4e5da5Sopenharmony_ci}
1021fd4e5da5Sopenharmony_ci
1022fd4e5da5Sopenharmony_ciTEST_F(LocalAccessChainConvertTest, IdOverflowReplacingLoad) {
1023fd4e5da5Sopenharmony_ci  const std::string text =
1024fd4e5da5Sopenharmony_ci      R"(
1025fd4e5da5Sopenharmony_ci               OpCapability Shader
1026fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
1027fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %4 "PSMain"
1028fd4e5da5Sopenharmony_ci               OpExecutionMode %4 OriginUpperLeft
1029fd4e5da5Sopenharmony_ci               OpDecorate %10 Location 47360
1030fd4e5da5Sopenharmony_ci       %void = OpTypeVoid
1031fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %void
1032fd4e5da5Sopenharmony_ci      %float = OpTypeFloat 32
1033fd4e5da5Sopenharmony_ci    %v4float = OpTypeVector %float 4
1034fd4e5da5Sopenharmony_ci  %_struct_8 = OpTypeStruct %v4float
1035fd4e5da5Sopenharmony_ci%_ptr_Function__struct_8 = OpTypePointer Function %_struct_8
1036fd4e5da5Sopenharmony_ci        %int = OpTypeInt 32 1
1037fd4e5da5Sopenharmony_ci      %int_0 = OpConstant %int 0
1038fd4e5da5Sopenharmony_ci%_ptr_Function_v4float = OpTypePointer Function %v4float
1039fd4e5da5Sopenharmony_ci          %4 = OpFunction %void None %3
1040fd4e5da5Sopenharmony_ci          %5 = OpLabel
1041fd4e5da5Sopenharmony_ci         %10 = OpVariable %_ptr_Function__struct_8 Function
1042fd4e5da5Sopenharmony_ci    %4194301 = OpAccessChain %_ptr_Function_v4float %10 %int_0
1043fd4e5da5Sopenharmony_ci    %4194302 = OpLoad %v4float %4194301
1044fd4e5da5Sopenharmony_ci               OpReturn
1045fd4e5da5Sopenharmony_ci               OpFunctionEnd
1046fd4e5da5Sopenharmony_ci)";
1047fd4e5da5Sopenharmony_ci
1048fd4e5da5Sopenharmony_ci  SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
1049fd4e5da5Sopenharmony_ci
1050fd4e5da5Sopenharmony_ci  std::vector<Message> messages = {
1051fd4e5da5Sopenharmony_ci      {SPV_MSG_ERROR, "", 0, 0, "ID overflow. Try running compact-ids."}};
1052fd4e5da5Sopenharmony_ci  SetMessageConsumer(GetTestMessageConsumer(messages));
1053fd4e5da5Sopenharmony_ci  auto result = SinglePassRunToBinary<LocalAccessChainConvertPass>(text, true);
1054fd4e5da5Sopenharmony_ci  EXPECT_EQ(Pass::Status::Failure, std::get<1>(result));
1055fd4e5da5Sopenharmony_ci}
1056fd4e5da5Sopenharmony_ci
1057fd4e5da5Sopenharmony_ciTEST_F(LocalAccessChainConvertTest, IdOverflowReplacingStore1) {
1058fd4e5da5Sopenharmony_ci  const std::string text =
1059fd4e5da5Sopenharmony_ci      R"(
1060fd4e5da5Sopenharmony_ci               OpCapability Shader
1061fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
1062fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %4 "PSMain"
1063fd4e5da5Sopenharmony_ci               OpExecutionMode %4 OriginUpperLeft
1064fd4e5da5Sopenharmony_ci               OpDecorate %10 Location 47360
1065fd4e5da5Sopenharmony_ci       %void = OpTypeVoid
1066fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %void
1067fd4e5da5Sopenharmony_ci      %float = OpTypeFloat 32
1068fd4e5da5Sopenharmony_ci    %v4float = OpTypeVector %float 4
1069fd4e5da5Sopenharmony_ci  %_struct_7 = OpTypeStruct %v4float
1070fd4e5da5Sopenharmony_ci%_ptr_Function__struct_7 = OpTypePointer Function %_struct_7
1071fd4e5da5Sopenharmony_ci        %int = OpTypeInt 32 1
1072fd4e5da5Sopenharmony_ci      %int_0 = OpConstant %int 0
1073fd4e5da5Sopenharmony_ci%_ptr_Function_v4float = OpTypePointer Function %v4float
1074fd4e5da5Sopenharmony_ci         %13 = OpConstantNull %v4float
1075fd4e5da5Sopenharmony_ci          %4 = OpFunction %void None %3
1076fd4e5da5Sopenharmony_ci          %5 = OpLabel
1077fd4e5da5Sopenharmony_ci         %10 = OpVariable %_ptr_Function__struct_7 Function
1078fd4e5da5Sopenharmony_ci    %4194302 = OpAccessChain %_ptr_Function_v4float %10 %int_0
1079fd4e5da5Sopenharmony_ci               OpStore %4194302 %13
1080fd4e5da5Sopenharmony_ci               OpReturn
1081fd4e5da5Sopenharmony_ci               OpFunctionEnd
1082fd4e5da5Sopenharmony_ci)";
1083fd4e5da5Sopenharmony_ci
1084fd4e5da5Sopenharmony_ci  SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
1085fd4e5da5Sopenharmony_ci
1086fd4e5da5Sopenharmony_ci  std::vector<Message> messages = {
1087fd4e5da5Sopenharmony_ci      {SPV_MSG_ERROR, "", 0, 0, "ID overflow. Try running compact-ids."}};
1088fd4e5da5Sopenharmony_ci  SetMessageConsumer(GetTestMessageConsumer(messages));
1089fd4e5da5Sopenharmony_ci  auto result = SinglePassRunToBinary<LocalAccessChainConvertPass>(text, true);
1090fd4e5da5Sopenharmony_ci  EXPECT_EQ(Pass::Status::Failure, std::get<1>(result));
1091fd4e5da5Sopenharmony_ci}
1092fd4e5da5Sopenharmony_ci
1093fd4e5da5Sopenharmony_ciTEST_F(LocalAccessChainConvertTest, IdOverflowReplacingStore2) {
1094fd4e5da5Sopenharmony_ci  const std::string text =
1095fd4e5da5Sopenharmony_ci      R"(
1096fd4e5da5Sopenharmony_ci               OpCapability Shader
1097fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
1098fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %4 "PSMain"
1099fd4e5da5Sopenharmony_ci               OpExecutionMode %4 OriginUpperLeft
1100fd4e5da5Sopenharmony_ci               OpDecorate %10 Location 47360
1101fd4e5da5Sopenharmony_ci       %void = OpTypeVoid
1102fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %void
1103fd4e5da5Sopenharmony_ci      %float = OpTypeFloat 32
1104fd4e5da5Sopenharmony_ci    %v4float = OpTypeVector %float 4
1105fd4e5da5Sopenharmony_ci  %_struct_7 = OpTypeStruct %v4float
1106fd4e5da5Sopenharmony_ci%_ptr_Function__struct_7 = OpTypePointer Function %_struct_7
1107fd4e5da5Sopenharmony_ci        %int = OpTypeInt 32 1
1108fd4e5da5Sopenharmony_ci      %int_0 = OpConstant %int 0
1109fd4e5da5Sopenharmony_ci%_ptr_Function_v4float = OpTypePointer Function %v4float
1110fd4e5da5Sopenharmony_ci         %13 = OpConstantNull %v4float
1111fd4e5da5Sopenharmony_ci          %4 = OpFunction %void None %3
1112fd4e5da5Sopenharmony_ci          %5 = OpLabel
1113fd4e5da5Sopenharmony_ci         %10 = OpVariable %_ptr_Function__struct_7 Function
1114fd4e5da5Sopenharmony_ci    %4194301 = OpAccessChain %_ptr_Function_v4float %10 %int_0
1115fd4e5da5Sopenharmony_ci               OpStore %4194301 %13
1116fd4e5da5Sopenharmony_ci               OpReturn
1117fd4e5da5Sopenharmony_ci               OpFunctionEnd
1118fd4e5da5Sopenharmony_ci)";
1119fd4e5da5Sopenharmony_ci
1120fd4e5da5Sopenharmony_ci  SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
1121fd4e5da5Sopenharmony_ci
1122fd4e5da5Sopenharmony_ci  std::vector<Message> messages = {
1123fd4e5da5Sopenharmony_ci      {SPV_MSG_ERROR, "", 0, 0, "ID overflow. Try running compact-ids."}};
1124fd4e5da5Sopenharmony_ci  SetMessageConsumer(GetTestMessageConsumer(messages));
1125fd4e5da5Sopenharmony_ci  auto result = SinglePassRunToBinary<LocalAccessChainConvertPass>(text, true);
1126fd4e5da5Sopenharmony_ci  EXPECT_EQ(Pass::Status::Failure, std::get<1>(result));
1127fd4e5da5Sopenharmony_ci}
1128fd4e5da5Sopenharmony_ci
1129fd4e5da5Sopenharmony_ciTEST_F(LocalAccessChainConvertTest, AccessChainWithNoIndex) {
1130fd4e5da5Sopenharmony_ci  const std::string before =
1131fd4e5da5Sopenharmony_ci      R"(
1132fd4e5da5Sopenharmony_ci; CHECK: OpFunction
1133fd4e5da5Sopenharmony_ci; CHECK: [[var:%\w+]] = OpVariable
1134fd4e5da5Sopenharmony_ci; CHECK: OpStore [[var]] %true
1135fd4e5da5Sopenharmony_ci; CHECK: OpLoad %bool [[var]]
1136fd4e5da5Sopenharmony_ci               OpCapability Shader
1137fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
1138fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
1139fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %2 "main"
1140fd4e5da5Sopenharmony_ci               OpExecutionMode %2 OriginUpperLeft
1141fd4e5da5Sopenharmony_ci               OpSource ESSL 310
1142fd4e5da5Sopenharmony_ci       %void = OpTypeVoid
1143fd4e5da5Sopenharmony_ci          %4 = OpTypeFunction %void
1144fd4e5da5Sopenharmony_ci       %bool = OpTypeBool
1145fd4e5da5Sopenharmony_ci       %true = OpConstantTrue %bool
1146fd4e5da5Sopenharmony_ci%_ptr_Function_bool = OpTypePointer Function %bool
1147fd4e5da5Sopenharmony_ci          %2 = OpFunction %void None %4
1148fd4e5da5Sopenharmony_ci          %8 = OpLabel
1149fd4e5da5Sopenharmony_ci          %9 = OpVariable %_ptr_Function_bool Function
1150fd4e5da5Sopenharmony_ci         %10 = OpAccessChain %_ptr_Function_bool %9
1151fd4e5da5Sopenharmony_ci               OpStore %10 %true
1152fd4e5da5Sopenharmony_ci         %11 = OpLoad %bool %10
1153fd4e5da5Sopenharmony_ci               OpReturn
1154fd4e5da5Sopenharmony_ci               OpFunctionEnd
1155fd4e5da5Sopenharmony_ci)";
1156fd4e5da5Sopenharmony_ci
1157fd4e5da5Sopenharmony_ci  SinglePassRunAndMatch<LocalAccessChainConvertPass>(before, true);
1158fd4e5da5Sopenharmony_ci}
1159fd4e5da5Sopenharmony_ciTEST_F(LocalAccessChainConvertTest, AccessChainWithLongIndex) {
1160fd4e5da5Sopenharmony_ci  // The access chain take a value that is larger than 32-bit.  The index cannot
1161fd4e5da5Sopenharmony_ci  // be encoded in an OpCompositeExtract, so nothing should be done.
1162fd4e5da5Sopenharmony_ci  const std::string before =
1163fd4e5da5Sopenharmony_ci      R"(OpCapability Shader
1164fd4e5da5Sopenharmony_ciOpCapability Int64
1165fd4e5da5Sopenharmony_ci%1 = OpExtInstImport "GLSL.std.450"
1166fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
1167fd4e5da5Sopenharmony_ciOpEntryPoint Fragment %2 "main_0004f4d4_85b2f584"
1168fd4e5da5Sopenharmony_ciOpExecutionMode %2 OriginUpperLeft
1169fd4e5da5Sopenharmony_ci%ulong = OpTypeInt 64 0
1170fd4e5da5Sopenharmony_ci%ulong_8589934592 = OpConstant %ulong 8589934592
1171fd4e5da5Sopenharmony_ci%ulong_8589934591 = OpConstant %ulong 8589934591
1172fd4e5da5Sopenharmony_ci%_arr_ulong_ulong_8589934592 = OpTypeArray %ulong %ulong_8589934592
1173fd4e5da5Sopenharmony_ci%_ptr_Function__arr_ulong_ulong_8589934592 = OpTypePointer Function %_arr_ulong_ulong_8589934592
1174fd4e5da5Sopenharmony_ci%_ptr_Function_ulong = OpTypePointer Function %ulong
1175fd4e5da5Sopenharmony_ci%void = OpTypeVoid
1176fd4e5da5Sopenharmony_ci%10 = OpTypeFunction %void
1177fd4e5da5Sopenharmony_ci%2 = OpFunction %void None %10
1178fd4e5da5Sopenharmony_ci%11 = OpLabel
1179fd4e5da5Sopenharmony_ci%12 = OpVariable %_ptr_Function__arr_ulong_ulong_8589934592 Function
1180fd4e5da5Sopenharmony_ci%13 = OpAccessChain %_ptr_Function_ulong %12 %ulong_8589934591
1181fd4e5da5Sopenharmony_ci%14 = OpLoad %ulong %13
1182fd4e5da5Sopenharmony_ciOpReturn
1183fd4e5da5Sopenharmony_ciOpFunctionEnd
1184fd4e5da5Sopenharmony_ci)";
1185fd4e5da5Sopenharmony_ci
1186fd4e5da5Sopenharmony_ci  SinglePassRunAndCheck<LocalAccessChainConvertPass>(before, before, false,
1187fd4e5da5Sopenharmony_ci                                                     true);
1188fd4e5da5Sopenharmony_ci}
1189fd4e5da5Sopenharmony_ci
1190fd4e5da5Sopenharmony_ciTEST_F(LocalAccessChainConvertTest, AccessChainWith32BitIndexInLong) {
1191fd4e5da5Sopenharmony_ci  // The access chain has a value that is 32-bits, but it is stored in a 64-bit
1192fd4e5da5Sopenharmony_ci  // variable.  This access change can be converted to an extract.
1193fd4e5da5Sopenharmony_ci  const std::string before =
1194fd4e5da5Sopenharmony_ci      R"(
1195fd4e5da5Sopenharmony_ci; CHECK: OpFunction
1196fd4e5da5Sopenharmony_ci; CHECK: [[var:%\w+]] = OpVariable
1197fd4e5da5Sopenharmony_ci; CHECK: [[ld:%\w+]] = OpLoad {{%\w+}} [[var]]
1198fd4e5da5Sopenharmony_ci; CHECK: OpCompositeExtract %ulong [[ld]] 3
1199fd4e5da5Sopenharmony_ci               OpCapability Shader
1200fd4e5da5Sopenharmony_ci               OpCapability Int64
1201fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
1202fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
1203fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %2 "main_0004f4d4_85b2f584"
1204fd4e5da5Sopenharmony_ci               OpExecutionMode %2 OriginUpperLeft
1205fd4e5da5Sopenharmony_ci      %ulong = OpTypeInt 64 0
1206fd4e5da5Sopenharmony_ci%ulong_8589934592 = OpConstant %ulong 8589934592
1207fd4e5da5Sopenharmony_ci%ulong_3 = OpConstant %ulong 3
1208fd4e5da5Sopenharmony_ci%_arr_ulong_ulong_8589934592 = OpTypeArray %ulong %ulong_8589934592
1209fd4e5da5Sopenharmony_ci%_ptr_Function__arr_ulong_ulong_8589934592 = OpTypePointer Function %_arr_ulong_ulong_8589934592
1210fd4e5da5Sopenharmony_ci%_ptr_Function_ulong = OpTypePointer Function %ulong
1211fd4e5da5Sopenharmony_ci       %void = OpTypeVoid
1212fd4e5da5Sopenharmony_ci         %10 = OpTypeFunction %void
1213fd4e5da5Sopenharmony_ci          %2 = OpFunction %void None %10
1214fd4e5da5Sopenharmony_ci         %11 = OpLabel
1215fd4e5da5Sopenharmony_ci         %12 = OpVariable %_ptr_Function__arr_ulong_ulong_8589934592 Function
1216fd4e5da5Sopenharmony_ci         %13 = OpAccessChain %_ptr_Function_ulong %12 %ulong_3
1217fd4e5da5Sopenharmony_ci         %14 = OpLoad %ulong %13
1218fd4e5da5Sopenharmony_ci               OpReturn
1219fd4e5da5Sopenharmony_ci               OpFunctionEnd
1220fd4e5da5Sopenharmony_ci)";
1221fd4e5da5Sopenharmony_ci
1222fd4e5da5Sopenharmony_ci  SinglePassRunAndMatch<LocalAccessChainConvertPass>(before, true);
1223fd4e5da5Sopenharmony_ci}
1224fd4e5da5Sopenharmony_ci
1225fd4e5da5Sopenharmony_ciTEST_F(LocalAccessChainConvertTest, AccessChainWithVarIndex) {
1226fd4e5da5Sopenharmony_ci  // The access chain has a value that is not constant, so there should not be
1227fd4e5da5Sopenharmony_ci  // any changes.
1228fd4e5da5Sopenharmony_ci  const std::string before =
1229fd4e5da5Sopenharmony_ci      R"(OpCapability Shader
1230fd4e5da5Sopenharmony_ci%1 = OpExtInstImport "GLSL.std.450"
1231fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
1232fd4e5da5Sopenharmony_ciOpEntryPoint Fragment %2 "main_0004f4d4_85b2f584"
1233fd4e5da5Sopenharmony_ciOpExecutionMode %2 OriginUpperLeft
1234fd4e5da5Sopenharmony_ci%uint = OpTypeInt 32 0
1235fd4e5da5Sopenharmony_ci%uint_5 = OpConstant %uint 5
1236fd4e5da5Sopenharmony_ci%_arr_uint_uint_5 = OpTypeArray %uint %uint_5
1237fd4e5da5Sopenharmony_ci%_ptr_Function__arr_uint_uint_5 = OpTypePointer Function %_arr_uint_uint_5
1238fd4e5da5Sopenharmony_ci%_ptr_Function_uint = OpTypePointer Function %uint
1239fd4e5da5Sopenharmony_ci%8 = OpUndef %uint
1240fd4e5da5Sopenharmony_ci%void = OpTypeVoid
1241fd4e5da5Sopenharmony_ci%10 = OpTypeFunction %void
1242fd4e5da5Sopenharmony_ci%2 = OpFunction %void None %10
1243fd4e5da5Sopenharmony_ci%11 = OpLabel
1244fd4e5da5Sopenharmony_ci%12 = OpVariable %_ptr_Function__arr_uint_uint_5 Function
1245fd4e5da5Sopenharmony_ci%13 = OpAccessChain %_ptr_Function_uint %12 %8
1246fd4e5da5Sopenharmony_ci%14 = OpLoad %uint %13
1247fd4e5da5Sopenharmony_ciOpReturn
1248fd4e5da5Sopenharmony_ciOpFunctionEnd
1249fd4e5da5Sopenharmony_ci)";
1250fd4e5da5Sopenharmony_ci
1251fd4e5da5Sopenharmony_ci  SinglePassRunAndCheck<LocalAccessChainConvertPass>(before, before, false,
1252fd4e5da5Sopenharmony_ci                                                     true);
1253fd4e5da5Sopenharmony_ci}
1254fd4e5da5Sopenharmony_ci
1255fd4e5da5Sopenharmony_ciTEST_F(LocalAccessChainConvertTest, OutOfBoundsAccess) {
1256fd4e5da5Sopenharmony_ci  // The access chain indexes element 12 in an array of size 10.  Nothing should
1257fd4e5da5Sopenharmony_ci  // be done.
1258fd4e5da5Sopenharmony_ci  const std::string assembly =
1259fd4e5da5Sopenharmony_ci      R"(OpCapability Shader
1260fd4e5da5Sopenharmony_ci%1 = OpExtInstImport "GLSL.std.450"
1261fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
1262fd4e5da5Sopenharmony_ciOpEntryPoint Fragment %2 "main" %3
1263fd4e5da5Sopenharmony_ciOpExecutionMode %2 OriginUpperLeft
1264fd4e5da5Sopenharmony_ci%void = OpTypeVoid
1265fd4e5da5Sopenharmony_ci%5 = OpTypeFunction %void
1266fd4e5da5Sopenharmony_ci%int = OpTypeInt 32 1
1267fd4e5da5Sopenharmony_ci%int_10 = OpConstant %int 10
1268fd4e5da5Sopenharmony_ci%_arr_int_int_10 = OpTypeArray %int %int_10
1269fd4e5da5Sopenharmony_ci%_ptr_Function_int = OpTypePointer Function %int
1270fd4e5da5Sopenharmony_ci%int_12 = OpConstant %int 12
1271fd4e5da5Sopenharmony_ci%_ptr_Output_int = OpTypePointer Output %int
1272fd4e5da5Sopenharmony_ci%3 = OpVariable %_ptr_Output_int Output
1273fd4e5da5Sopenharmony_ci%_ptr_Function__arr_int_int_10 = OpTypePointer Function %_arr_int_int_10
1274fd4e5da5Sopenharmony_ci%2 = OpFunction %void None %5
1275fd4e5da5Sopenharmony_ci%13 = OpLabel
1276fd4e5da5Sopenharmony_ci%14 = OpVariable %_ptr_Function__arr_int_int_10 Function
1277fd4e5da5Sopenharmony_ci%15 = OpAccessChain %_ptr_Function_int %14 %int_12
1278fd4e5da5Sopenharmony_ci%16 = OpLoad %int %15
1279fd4e5da5Sopenharmony_ciOpStore %3 %16
1280fd4e5da5Sopenharmony_ciOpReturn
1281fd4e5da5Sopenharmony_ciOpFunctionEnd
1282fd4e5da5Sopenharmony_ci)";
1283fd4e5da5Sopenharmony_ci
1284fd4e5da5Sopenharmony_ci  SinglePassRunAndCheck<LocalAccessChainConvertPass>(assembly, assembly, false,
1285fd4e5da5Sopenharmony_ci                                                     true);
1286fd4e5da5Sopenharmony_ci}
1287fd4e5da5Sopenharmony_ci
1288fd4e5da5Sopenharmony_ciTEST_F(LocalAccessChainConvertTest, OutOfBoundsAccessAtBoundary) {
1289fd4e5da5Sopenharmony_ci  // The access chain indexes element 10 in an array of size 10.  Nothing should
1290fd4e5da5Sopenharmony_ci  // be done.
1291fd4e5da5Sopenharmony_ci  const std::string assembly =
1292fd4e5da5Sopenharmony_ci      R"(OpCapability Shader
1293fd4e5da5Sopenharmony_ci%1 = OpExtInstImport "GLSL.std.450"
1294fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
1295fd4e5da5Sopenharmony_ciOpEntryPoint Fragment %2 "main" %3
1296fd4e5da5Sopenharmony_ciOpExecutionMode %2 OriginUpperLeft
1297fd4e5da5Sopenharmony_ci%void = OpTypeVoid
1298fd4e5da5Sopenharmony_ci%5 = OpTypeFunction %void
1299fd4e5da5Sopenharmony_ci%int = OpTypeInt 32 1
1300fd4e5da5Sopenharmony_ci%int_10 = OpConstant %int 10
1301fd4e5da5Sopenharmony_ci%_arr_int_int_10 = OpTypeArray %int %int_10
1302fd4e5da5Sopenharmony_ci%_ptr_Function_int = OpTypePointer Function %int
1303fd4e5da5Sopenharmony_ci%_ptr_Output_int = OpTypePointer Output %int
1304fd4e5da5Sopenharmony_ci%3 = OpVariable %_ptr_Output_int Output
1305fd4e5da5Sopenharmony_ci%_ptr_Function__arr_int_int_10 = OpTypePointer Function %_arr_int_int_10
1306fd4e5da5Sopenharmony_ci%2 = OpFunction %void None %5
1307fd4e5da5Sopenharmony_ci%12 = OpLabel
1308fd4e5da5Sopenharmony_ci%13 = OpVariable %_ptr_Function__arr_int_int_10 Function
1309fd4e5da5Sopenharmony_ci%14 = OpAccessChain %_ptr_Function_int %13 %int_10
1310fd4e5da5Sopenharmony_ci%15 = OpLoad %int %14
1311fd4e5da5Sopenharmony_ciOpStore %3 %15
1312fd4e5da5Sopenharmony_ciOpReturn
1313fd4e5da5Sopenharmony_ciOpFunctionEnd
1314fd4e5da5Sopenharmony_ci)";
1315fd4e5da5Sopenharmony_ci
1316fd4e5da5Sopenharmony_ci  SinglePassRunAndCheck<LocalAccessChainConvertPass>(assembly, assembly, false,
1317fd4e5da5Sopenharmony_ci                                                     true);
1318fd4e5da5Sopenharmony_ci}
1319fd4e5da5Sopenharmony_ci
1320fd4e5da5Sopenharmony_ciTEST_F(LocalAccessChainConvertTest, NegativeIndex) {
1321fd4e5da5Sopenharmony_ci  // The access chain has a negative index and should not be converted because
1322fd4e5da5Sopenharmony_ci  // the extract instruction cannot hold a negative number.
1323fd4e5da5Sopenharmony_ci  const std::string assembly =
1324fd4e5da5Sopenharmony_ci      R"(OpCapability Shader
1325fd4e5da5Sopenharmony_ci%1 = OpExtInstImport "GLSL.std.450"
1326fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
1327fd4e5da5Sopenharmony_ciOpEntryPoint Fragment %2 "main"
1328fd4e5da5Sopenharmony_ciOpExecutionMode %2 OriginUpperLeft
1329fd4e5da5Sopenharmony_ci%void = OpTypeVoid
1330fd4e5da5Sopenharmony_ci%4 = OpTypeFunction %void
1331fd4e5da5Sopenharmony_ci%int = OpTypeInt 32 1
1332fd4e5da5Sopenharmony_ci%uint = OpTypeInt 32 0
1333fd4e5da5Sopenharmony_ci%uint_3808428041 = OpConstant %uint 3808428041
1334fd4e5da5Sopenharmony_ci%_arr_int_uint_3808428041 = OpTypeArray %int %uint_3808428041
1335fd4e5da5Sopenharmony_ci%_ptr_Function__arr_int_uint_3808428041 = OpTypePointer Function %_arr_int_uint_3808428041
1336fd4e5da5Sopenharmony_ci%_ptr_Function_int = OpTypePointer Function %int
1337fd4e5da5Sopenharmony_ci%int_n1272971256 = OpConstant %int -1272971256
1338fd4e5da5Sopenharmony_ci%2 = OpFunction %void None %4
1339fd4e5da5Sopenharmony_ci%12 = OpLabel
1340fd4e5da5Sopenharmony_ci%13 = OpVariable %_ptr_Function__arr_int_uint_3808428041 Function
1341fd4e5da5Sopenharmony_ci%14 = OpAccessChain %_ptr_Function_int %13 %int_n1272971256
1342fd4e5da5Sopenharmony_ci%15 = OpLoad %int %14
1343fd4e5da5Sopenharmony_ciOpReturn
1344fd4e5da5Sopenharmony_ciOpFunctionEnd
1345fd4e5da5Sopenharmony_ci)";
1346fd4e5da5Sopenharmony_ci
1347fd4e5da5Sopenharmony_ci  SinglePassRunAndCheck<LocalAccessChainConvertPass>(assembly, assembly, false,
1348fd4e5da5Sopenharmony_ci                                                     true);
1349fd4e5da5Sopenharmony_ci}
1350fd4e5da5Sopenharmony_ci
1351fd4e5da5Sopenharmony_ciTEST_F(LocalAccessChainConvertTest, VkMemoryModelTest) {
1352fd4e5da5Sopenharmony_ci  const std::string text =
1353fd4e5da5Sopenharmony_ci      R"(
1354fd4e5da5Sopenharmony_ci; CHECK: OpCapability Shader
1355fd4e5da5Sopenharmony_ci; CHECK: OpCapability VulkanMemoryModel
1356fd4e5da5Sopenharmony_ci; CHECK: OpExtension "SPV_KHR_vulkan_memory_model"
1357fd4e5da5Sopenharmony_ci               OpCapability Shader
1358fd4e5da5Sopenharmony_ci               OpCapability VulkanMemoryModel
1359fd4e5da5Sopenharmony_ci               OpExtension "SPV_KHR_vulkan_memory_model"
1360fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
1361fd4e5da5Sopenharmony_ci               OpMemoryModel Logical Vulkan
1362fd4e5da5Sopenharmony_ci               OpEntryPoint GLCompute %main "main"
1363fd4e5da5Sopenharmony_ci               OpExecutionMode %main LocalSize 1 1 1
1364fd4e5da5Sopenharmony_ci               OpSource GLSL 450
1365fd4e5da5Sopenharmony_ci               OpSourceExtension "GL_GOOGLE_cpp_style_line_directive"
1366fd4e5da5Sopenharmony_ci               OpSourceExtension "GL_GOOGLE_include_directive"
1367fd4e5da5Sopenharmony_ci               OpName %main "main"
1368fd4e5da5Sopenharmony_ci               OpName %a "a"
1369fd4e5da5Sopenharmony_ci       %void = OpTypeVoid
1370fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %void
1371fd4e5da5Sopenharmony_ci      %float = OpTypeFloat 32
1372fd4e5da5Sopenharmony_ci    %v4float = OpTypeVector %float 4
1373fd4e5da5Sopenharmony_ci%_ptr_Function_v4float = OpTypePointer Function %v4float
1374fd4e5da5Sopenharmony_ci       %uint = OpTypeInt 32 0
1375fd4e5da5Sopenharmony_ci     %uint_0 = OpConstant %uint 0
1376fd4e5da5Sopenharmony_ci%_ptr_Function_float = OpTypePointer Function %float
1377fd4e5da5Sopenharmony_ci    %float_1 = OpConstant %float 1
1378fd4e5da5Sopenharmony_ci; CHECK: OpFunction
1379fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpLabel
1380fd4e5da5Sopenharmony_ci; CHECK-NEXT: [[a:%\w+]] = OpVariable
1381fd4e5da5Sopenharmony_ci; Make sure the access chains were removed.
1382fd4e5da5Sopenharmony_ci; CHECK: [[ld:%\w+]] = OpLoad {{%\w+}} [[a]]
1383fd4e5da5Sopenharmony_ci; CHECK: [[ex:%\w+]] = OpCompositeExtract {{%\w+}} [[ld]] 0
1384fd4e5da5Sopenharmony_ci; CHECK: [[ld2:%\w+]] = OpLoad {{%\w+}} [[a]]
1385fd4e5da5Sopenharmony_ci; CHECK: [[v:%\w+]] = OpCompositeInsert {{%\w+}} [[ex]] [[ld2]] 0
1386fd4e5da5Sopenharmony_ci; CHECK: OpStore [[a]] [[v]]
1387fd4e5da5Sopenharmony_ci       %main = OpFunction %void None %3
1388fd4e5da5Sopenharmony_ci          %5 = OpLabel
1389fd4e5da5Sopenharmony_ci          %a = OpVariable %_ptr_Function_v4float Function
1390fd4e5da5Sopenharmony_ci         %13 = OpAccessChain %_ptr_Function_float %a %uint_0
1391fd4e5da5Sopenharmony_ci         %14 = OpLoad %float %13
1392fd4e5da5Sopenharmony_ci         %17 = OpAccessChain %_ptr_Function_float %a %uint_0
1393fd4e5da5Sopenharmony_ci               OpStore %17 %14
1394fd4e5da5Sopenharmony_ci               OpReturn
1395fd4e5da5Sopenharmony_ci               OpFunctionEnd
1396fd4e5da5Sopenharmony_ci)";
1397fd4e5da5Sopenharmony_ci
1398fd4e5da5Sopenharmony_ci  SinglePassRunAndMatch<LocalAccessChainConvertPass>(text, false);
1399fd4e5da5Sopenharmony_ci}
1400fd4e5da5Sopenharmony_ci
1401fd4e5da5Sopenharmony_ci// TODO(greg-lunarg): Add tests to verify handling of these cases:
1402fd4e5da5Sopenharmony_ci//
1403fd4e5da5Sopenharmony_ci//    Assorted vector and matrix types
1404fd4e5da5Sopenharmony_ci//    Assorted struct array types
1405fd4e5da5Sopenharmony_ci//    Assorted scalar types
1406fd4e5da5Sopenharmony_ci//    Assorted non-target types
1407fd4e5da5Sopenharmony_ci//    OpInBoundsAccessChain
1408fd4e5da5Sopenharmony_ci//    Others?
1409fd4e5da5Sopenharmony_ci
1410fd4e5da5Sopenharmony_ci}  // namespace
1411fd4e5da5Sopenharmony_ci}  // namespace opt
1412fd4e5da5Sopenharmony_ci}  // namespace spvtools
1413