1fd4e5da5Sopenharmony_ci// Copyright (c) 2022 Google LLC
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 <iostream>
16fd4e5da5Sopenharmony_ci
17fd4e5da5Sopenharmony_ci#include "test/opt/pass_fixture.h"
18fd4e5da5Sopenharmony_ci#include "test/opt/pass_utils.h"
19fd4e5da5Sopenharmony_ci
20fd4e5da5Sopenharmony_cinamespace spvtools {
21fd4e5da5Sopenharmony_cinamespace opt {
22fd4e5da5Sopenharmony_cinamespace {
23fd4e5da5Sopenharmony_ci
24fd4e5da5Sopenharmony_ciusing InterfaceVariableScalarReplacementTest = PassTest<::testing::Test>;
25fd4e5da5Sopenharmony_ci
26fd4e5da5Sopenharmony_ciTEST_F(InterfaceVariableScalarReplacementTest,
27fd4e5da5Sopenharmony_ci       ReplaceInterfaceVarsWithScalars) {
28fd4e5da5Sopenharmony_ci  const std::string spirv = R"(
29fd4e5da5Sopenharmony_ci               OpCapability Shader
30fd4e5da5Sopenharmony_ci               OpCapability Tessellation
31fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
32fd4e5da5Sopenharmony_ci               OpEntryPoint TessellationControl %func "shader" %x %y %z %w %u %v
33fd4e5da5Sopenharmony_ci
34fd4e5da5Sopenharmony_ci; CHECK:     OpName [[x:%\w+]] "x"
35fd4e5da5Sopenharmony_ci; CHECK-NOT: OpName {{%\w+}} "x"
36fd4e5da5Sopenharmony_ci; CHECK:     OpName [[y:%\w+]] "y"
37fd4e5da5Sopenharmony_ci; CHECK-NOT: OpName {{%\w+}} "y"
38fd4e5da5Sopenharmony_ci; CHECK:     OpName [[z0:%\w+]] "z"
39fd4e5da5Sopenharmony_ci; CHECK:     OpName [[z1:%\w+]] "z"
40fd4e5da5Sopenharmony_ci; CHECK:     OpName [[w0:%\w+]] "w"
41fd4e5da5Sopenharmony_ci; CHECK:     OpName [[w1:%\w+]] "w"
42fd4e5da5Sopenharmony_ci; CHECK:     OpName [[u0:%\w+]] "u"
43fd4e5da5Sopenharmony_ci; CHECK:     OpName [[u1:%\w+]] "u"
44fd4e5da5Sopenharmony_ci; CHECK:     OpName [[v0:%\w+]] "v"
45fd4e5da5Sopenharmony_ci; CHECK:     OpName [[v1:%\w+]] "v"
46fd4e5da5Sopenharmony_ci; CHECK:     OpName [[v2:%\w+]] "v"
47fd4e5da5Sopenharmony_ci; CHECK:     OpName [[v3:%\w+]] "v"
48fd4e5da5Sopenharmony_ci; CHECK:     OpName [[v4:%\w+]] "v"
49fd4e5da5Sopenharmony_ci; CHECK:     OpName [[v5:%\w+]] "v"
50fd4e5da5Sopenharmony_ci               OpName %x "x"
51fd4e5da5Sopenharmony_ci               OpName %y "y"
52fd4e5da5Sopenharmony_ci               OpName %z "z"
53fd4e5da5Sopenharmony_ci               OpName %w "w"
54fd4e5da5Sopenharmony_ci               OpName %u "u"
55fd4e5da5Sopenharmony_ci               OpName %v "v"
56fd4e5da5Sopenharmony_ci
57fd4e5da5Sopenharmony_ci; CHECK-DAG: OpDecorate [[x]] Location 2
58fd4e5da5Sopenharmony_ci; CHECK-DAG: OpDecorate [[y]] Location 0
59fd4e5da5Sopenharmony_ci; CHECK-DAG: OpDecorate [[z0]] Location 0
60fd4e5da5Sopenharmony_ci; CHECK-DAG: OpDecorate [[z0]] Component 0
61fd4e5da5Sopenharmony_ci; CHECK-DAG: OpDecorate [[z1]] Location 1
62fd4e5da5Sopenharmony_ci; CHECK-DAG: OpDecorate [[z1]] Component 0
63fd4e5da5Sopenharmony_ci; CHECK-DAG: OpDecorate [[z0]] Patch
64fd4e5da5Sopenharmony_ci; CHECK-DAG: OpDecorate [[z1]] Patch
65fd4e5da5Sopenharmony_ci; CHECK-DAG: OpDecorate [[w0]] Location 2
66fd4e5da5Sopenharmony_ci; CHECK-DAG: OpDecorate [[w0]] Component 0
67fd4e5da5Sopenharmony_ci; CHECK-DAG: OpDecorate [[w1]] Location 3
68fd4e5da5Sopenharmony_ci; CHECK-DAG: OpDecorate [[w1]] Component 0
69fd4e5da5Sopenharmony_ci; CHECK-DAG: OpDecorate [[w0]] Patch
70fd4e5da5Sopenharmony_ci; CHECK-DAG: OpDecorate [[w1]] Patch
71fd4e5da5Sopenharmony_ci; CHECK-DAG: OpDecorate [[u0]] Location 3
72fd4e5da5Sopenharmony_ci; CHECK-DAG: OpDecorate [[u0]] Component 2
73fd4e5da5Sopenharmony_ci; CHECK-DAG: OpDecorate [[u1]] Location 4
74fd4e5da5Sopenharmony_ci; CHECK-DAG: OpDecorate [[u1]] Component 2
75fd4e5da5Sopenharmony_ci; CHECK-DAG: OpDecorate [[v0]] Location 3
76fd4e5da5Sopenharmony_ci; CHECK-DAG: OpDecorate [[v0]] Component 3
77fd4e5da5Sopenharmony_ci; CHECK-DAG: OpDecorate [[v1]] Location 4
78fd4e5da5Sopenharmony_ci; CHECK-DAG: OpDecorate [[v1]] Component 3
79fd4e5da5Sopenharmony_ci; CHECK-DAG: OpDecorate [[v2]] Location 5
80fd4e5da5Sopenharmony_ci; CHECK-DAG: OpDecorate [[v2]] Component 3
81fd4e5da5Sopenharmony_ci; CHECK-DAG: OpDecorate [[v3]] Location 6
82fd4e5da5Sopenharmony_ci; CHECK-DAG: OpDecorate [[v3]] Component 3
83fd4e5da5Sopenharmony_ci; CHECK-DAG: OpDecorate [[v4]] Location 7
84fd4e5da5Sopenharmony_ci; CHECK-DAG: OpDecorate [[v4]] Component 3
85fd4e5da5Sopenharmony_ci; CHECK-DAG: OpDecorate [[v5]] Location 8
86fd4e5da5Sopenharmony_ci; CHECK-DAG: OpDecorate [[v5]] Component 3
87fd4e5da5Sopenharmony_ci               OpDecorate %z Patch
88fd4e5da5Sopenharmony_ci               OpDecorate %w Patch
89fd4e5da5Sopenharmony_ci               OpDecorate %z Location 0
90fd4e5da5Sopenharmony_ci               OpDecorate %x Location 2
91fd4e5da5Sopenharmony_ci               OpDecorate %v Location 3
92fd4e5da5Sopenharmony_ci               OpDecorate %v Component 3
93fd4e5da5Sopenharmony_ci               OpDecorate %y Location 0
94fd4e5da5Sopenharmony_ci               OpDecorate %w Location 2
95fd4e5da5Sopenharmony_ci               OpDecorate %u Location 3
96fd4e5da5Sopenharmony_ci               OpDecorate %u Component 2
97fd4e5da5Sopenharmony_ci
98fd4e5da5Sopenharmony_ci       %uint = OpTypeInt 32 0
99fd4e5da5Sopenharmony_ci     %uint_1 = OpConstant %uint 1
100fd4e5da5Sopenharmony_ci     %uint_2 = OpConstant %uint 2
101fd4e5da5Sopenharmony_ci     %uint_3 = OpConstant %uint 3
102fd4e5da5Sopenharmony_ci     %uint_4 = OpConstant %uint 4
103fd4e5da5Sopenharmony_ci%_arr_uint_uint_2 = OpTypeArray %uint %uint_2
104fd4e5da5Sopenharmony_ci%_ptr_Output__arr_uint_uint_2 = OpTypePointer Output %_arr_uint_uint_2
105fd4e5da5Sopenharmony_ci%_ptr_Input__arr_uint_uint_2 = OpTypePointer Input %_arr_uint_uint_2
106fd4e5da5Sopenharmony_ci%_ptr_Input_uint = OpTypePointer Input %uint
107fd4e5da5Sopenharmony_ci%_ptr_Output_uint = OpTypePointer Output %uint
108fd4e5da5Sopenharmony_ci%_arr_arr_uint_uint_2_3 = OpTypeArray %_arr_uint_uint_2 %uint_3
109fd4e5da5Sopenharmony_ci%_ptr_Input__arr_arr_uint_uint_2_3 = OpTypePointer Input %_arr_arr_uint_uint_2_3
110fd4e5da5Sopenharmony_ci%_arr_arr_arr_uint_uint_2_3_4 = OpTypeArray %_arr_arr_uint_uint_2_3 %uint_4
111fd4e5da5Sopenharmony_ci%_ptr_Output__arr_arr_arr_uint_uint_2_3_4 = OpTypePointer Output %_arr_arr_arr_uint_uint_2_3_4
112fd4e5da5Sopenharmony_ci%_ptr_Output__arr_arr_uint_uint_2_3 = OpTypePointer Output %_arr_arr_uint_uint_2_3
113fd4e5da5Sopenharmony_ci          %z = OpVariable %_ptr_Output__arr_uint_uint_2 Output
114fd4e5da5Sopenharmony_ci          %x = OpVariable %_ptr_Output__arr_uint_uint_2 Output
115fd4e5da5Sopenharmony_ci          %y = OpVariable %_ptr_Input__arr_uint_uint_2 Input
116fd4e5da5Sopenharmony_ci          %w = OpVariable %_ptr_Input__arr_uint_uint_2 Input
117fd4e5da5Sopenharmony_ci          %u = OpVariable %_ptr_Input__arr_arr_uint_uint_2_3 Input
118fd4e5da5Sopenharmony_ci          %v = OpVariable %_ptr_Output__arr_arr_arr_uint_uint_2_3_4 Output
119fd4e5da5Sopenharmony_ci
120fd4e5da5Sopenharmony_ci; CHECK-DAG:  [[x]] = OpVariable %_ptr_Output__arr_uint_uint_2 Output
121fd4e5da5Sopenharmony_ci; CHECK-DAG:  [[y]] = OpVariable %_ptr_Input__arr_uint_uint_2 Input
122fd4e5da5Sopenharmony_ci; CHECK-DAG: [[z0]] = OpVariable %_ptr_Output_uint Output
123fd4e5da5Sopenharmony_ci; CHECK-DAG: [[z1]] = OpVariable %_ptr_Output_uint Output
124fd4e5da5Sopenharmony_ci; CHECK-DAG: [[w0]] = OpVariable %_ptr_Input_uint Input
125fd4e5da5Sopenharmony_ci; CHECK-DAG: [[w1]] = OpVariable %_ptr_Input_uint Input
126fd4e5da5Sopenharmony_ci; CHECK-DAG: [[u0]] = OpVariable %_ptr_Input__arr_uint_uint_3 Input
127fd4e5da5Sopenharmony_ci; CHECK-DAG: [[u1]] = OpVariable %_ptr_Input__arr_uint_uint_3 Input
128fd4e5da5Sopenharmony_ci; CHECK-DAG: [[v0]] = OpVariable %_ptr_Output__arr_uint_uint_4 Output
129fd4e5da5Sopenharmony_ci; CHECK-DAG: [[v1]] = OpVariable %_ptr_Output__arr_uint_uint_4 Output
130fd4e5da5Sopenharmony_ci; CHECK-DAG: [[v2]] = OpVariable %_ptr_Output__arr_uint_uint_4 Output
131fd4e5da5Sopenharmony_ci; CHECK-DAG: [[v3]] = OpVariable %_ptr_Output__arr_uint_uint_4 Output
132fd4e5da5Sopenharmony_ci; CHECK-DAG: [[v4]] = OpVariable %_ptr_Output__arr_uint_uint_4 Output
133fd4e5da5Sopenharmony_ci; CHECK-DAG: [[v5]] = OpVariable %_ptr_Output__arr_uint_uint_4 Output
134fd4e5da5Sopenharmony_ci
135fd4e5da5Sopenharmony_ci     %void   = OpTypeVoid
136fd4e5da5Sopenharmony_ci     %void_f = OpTypeFunction %void
137fd4e5da5Sopenharmony_ci     %func   = OpFunction %void None %void_f
138fd4e5da5Sopenharmony_ci     %label  = OpLabel
139fd4e5da5Sopenharmony_ci
140fd4e5da5Sopenharmony_ci; CHECK: [[w0_value:%\w+]] = OpLoad %uint [[w0]]
141fd4e5da5Sopenharmony_ci; CHECK: [[w1_value:%\w+]] = OpLoad %uint [[w1]]
142fd4e5da5Sopenharmony_ci; CHECK:  [[w_value:%\w+]] = OpCompositeConstruct %_arr_uint_uint_2 [[w0_value]] [[w1_value]]
143fd4e5da5Sopenharmony_ci; CHECK:       [[w0:%\w+]] = OpCompositeExtract %uint [[w_value]] 0
144fd4e5da5Sopenharmony_ci; CHECK:                     OpStore [[z0]] [[w0]]
145fd4e5da5Sopenharmony_ci; CHECK:       [[w1:%\w+]] = OpCompositeExtract %uint [[w_value]] 1
146fd4e5da5Sopenharmony_ci; CHECK:                     OpStore [[z1]] [[w1]]
147fd4e5da5Sopenharmony_ci    %w_value = OpLoad %_arr_uint_uint_2 %w
148fd4e5da5Sopenharmony_ci               OpStore %z %w_value
149fd4e5da5Sopenharmony_ci
150fd4e5da5Sopenharmony_ci; CHECK: [[u00_ptr:%\w+]] = OpAccessChain %_ptr_Input_uint [[u0]] %uint_0
151fd4e5da5Sopenharmony_ci; CHECK:     [[u00:%\w+]] = OpLoad %uint [[u00_ptr]]
152fd4e5da5Sopenharmony_ci; CHECK: [[u10_ptr:%\w+]] = OpAccessChain %_ptr_Input_uint [[u1]] %uint_0
153fd4e5da5Sopenharmony_ci; CHECK:     [[u10:%\w+]] = OpLoad %uint [[u10_ptr]]
154fd4e5da5Sopenharmony_ci; CHECK: [[u01_ptr:%\w+]] = OpAccessChain %_ptr_Input_uint [[u0]] %uint_1
155fd4e5da5Sopenharmony_ci; CHECK:     [[u01:%\w+]] = OpLoad %uint [[u01_ptr]]
156fd4e5da5Sopenharmony_ci; CHECK: [[u11_ptr:%\w+]] = OpAccessChain %_ptr_Input_uint [[u1]] %uint_1
157fd4e5da5Sopenharmony_ci; CHECK:     [[u11:%\w+]] = OpLoad %uint [[u11_ptr]]
158fd4e5da5Sopenharmony_ci; CHECK: [[u02_ptr:%\w+]] = OpAccessChain %_ptr_Input_uint [[u0]] %uint_2
159fd4e5da5Sopenharmony_ci; CHECK:     [[u02:%\w+]] = OpLoad %uint [[u02_ptr]]
160fd4e5da5Sopenharmony_ci; CHECK: [[u12_ptr:%\w+]] = OpAccessChain %_ptr_Input_uint [[u1]] %uint_2
161fd4e5da5Sopenharmony_ci; CHECK:     [[u12:%\w+]] = OpLoad %uint [[u12_ptr]]
162fd4e5da5Sopenharmony_ci
163fd4e5da5Sopenharmony_ci; CHECK-DAG: [[u0_val:%\w+]] = OpCompositeConstruct %_arr_uint_uint_2 [[u00]] [[u10]]
164fd4e5da5Sopenharmony_ci; CHECK-DAG: [[u1_val:%\w+]] = OpCompositeConstruct %_arr_uint_uint_2 [[u01]] [[u11]]
165fd4e5da5Sopenharmony_ci; CHECK-DAG: [[u2_val:%\w+]] = OpCompositeConstruct %_arr_uint_uint_2 [[u02]] [[u12]]
166fd4e5da5Sopenharmony_ci
167fd4e5da5Sopenharmony_ci; CHECK: [[u_val:%\w+]] = OpCompositeConstruct %_arr__arr_uint_uint_2_uint_3 [[u0_val]] [[u1_val]] [[u2_val]]
168fd4e5da5Sopenharmony_ci
169fd4e5da5Sopenharmony_ci; CHECK: [[ptr:%\w+]] = OpAccessChain %_ptr_Output_uint [[v0]] %uint_1
170fd4e5da5Sopenharmony_ci; CHECK: [[val:%\w+]] = OpCompositeExtract %uint [[u_val]] 0 0
171fd4e5da5Sopenharmony_ci; CHECK:                OpStore [[ptr]] [[val]]
172fd4e5da5Sopenharmony_ci; CHECK: [[ptr:%\w+]] = OpAccessChain %_ptr_Output_uint [[v1]] %uint_1
173fd4e5da5Sopenharmony_ci; CHECK: [[val:%\w+]] = OpCompositeExtract %uint [[u_val]] 0 1
174fd4e5da5Sopenharmony_ci; CHECK:                OpStore [[ptr]] [[val]]
175fd4e5da5Sopenharmony_ci; CHECK: [[ptr:%\w+]] = OpAccessChain %_ptr_Output_uint [[v2]] %uint_1
176fd4e5da5Sopenharmony_ci; CHECK: [[val:%\w+]] = OpCompositeExtract %uint [[u_val]] 1 0
177fd4e5da5Sopenharmony_ci; CHECK:                OpStore [[ptr]] [[val]]
178fd4e5da5Sopenharmony_ci; CHECK: [[ptr:%\w+]] = OpAccessChain %_ptr_Output_uint [[v3]] %uint_1
179fd4e5da5Sopenharmony_ci; CHECK: [[val:%\w+]] = OpCompositeExtract %uint [[u_val]] 1 1
180fd4e5da5Sopenharmony_ci; CHECK:                OpStore [[ptr]] [[val]]
181fd4e5da5Sopenharmony_ci; CHECK: [[ptr:%\w+]] = OpAccessChain %_ptr_Output_uint [[v4]] %uint_1
182fd4e5da5Sopenharmony_ci; CHECK: [[val:%\w+]] = OpCompositeExtract %uint [[u_val]] 2 0
183fd4e5da5Sopenharmony_ci; CHECK:                OpStore [[ptr]] [[val]]
184fd4e5da5Sopenharmony_ci; CHECK: [[ptr:%\w+]] = OpAccessChain %_ptr_Output_uint [[v5]] %uint_1
185fd4e5da5Sopenharmony_ci; CHECK: [[val:%\w+]] = OpCompositeExtract %uint [[u_val]] 2 1
186fd4e5da5Sopenharmony_ci; CHECK:                OpStore [[ptr]] [[val]]
187fd4e5da5Sopenharmony_ci     %v_ptr  = OpAccessChain %_ptr_Output__arr_arr_uint_uint_2_3 %v %uint_1
188fd4e5da5Sopenharmony_ci     %u_val  = OpLoad %_arr_arr_uint_uint_2_3 %u
189fd4e5da5Sopenharmony_ci               OpStore %v_ptr %u_val
190fd4e5da5Sopenharmony_ci
191fd4e5da5Sopenharmony_ci               OpReturn
192fd4e5da5Sopenharmony_ci               OpFunctionEnd
193fd4e5da5Sopenharmony_ci  )";
194fd4e5da5Sopenharmony_ci
195fd4e5da5Sopenharmony_ci  SinglePassRunAndMatch<InterfaceVariableScalarReplacement>(spirv, true);
196fd4e5da5Sopenharmony_ci}
197fd4e5da5Sopenharmony_ci
198fd4e5da5Sopenharmony_ciTEST_F(InterfaceVariableScalarReplacementTest,
199fd4e5da5Sopenharmony_ci       CheckPatchDecorationPreservation) {
200fd4e5da5Sopenharmony_ci  // Make sure scalars for the variables with the extra arrayness have the extra
201fd4e5da5Sopenharmony_ci  // arrayness after running the pass while others do not have it.
202fd4e5da5Sopenharmony_ci  // Only "y" does not have the extra arrayness in the following SPIR-V.
203fd4e5da5Sopenharmony_ci  const std::string spirv = R"(
204fd4e5da5Sopenharmony_ci               OpCapability Shader
205fd4e5da5Sopenharmony_ci               OpCapability Tessellation
206fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
207fd4e5da5Sopenharmony_ci               OpEntryPoint TessellationEvaluation %func "shader" %x %y %z %w
208fd4e5da5Sopenharmony_ci               OpDecorate %z Patch
209fd4e5da5Sopenharmony_ci               OpDecorate %w Patch
210fd4e5da5Sopenharmony_ci               OpDecorate %z Location 0
211fd4e5da5Sopenharmony_ci               OpDecorate %x Location 2
212fd4e5da5Sopenharmony_ci               OpDecorate %y Location 0
213fd4e5da5Sopenharmony_ci               OpDecorate %w Location 1
214fd4e5da5Sopenharmony_ci               OpName %x "x"
215fd4e5da5Sopenharmony_ci               OpName %y "y"
216fd4e5da5Sopenharmony_ci               OpName %z "z"
217fd4e5da5Sopenharmony_ci               OpName %w "w"
218fd4e5da5Sopenharmony_ci
219fd4e5da5Sopenharmony_ci  ; CHECK:     OpName [[y:%\w+]] "y"
220fd4e5da5Sopenharmony_ci  ; CHECK-NOT: OpName {{%\w+}} "y"
221fd4e5da5Sopenharmony_ci  ; CHECK-DAG: OpName [[z0:%\w+]] "z"
222fd4e5da5Sopenharmony_ci  ; CHECK-DAG: OpName [[z1:%\w+]] "z"
223fd4e5da5Sopenharmony_ci  ; CHECK-DAG: OpName [[w0:%\w+]] "w"
224fd4e5da5Sopenharmony_ci  ; CHECK-DAG: OpName [[w1:%\w+]] "w"
225fd4e5da5Sopenharmony_ci  ; CHECK-DAG: OpName [[x0:%\w+]] "x"
226fd4e5da5Sopenharmony_ci  ; CHECK-DAG: OpName [[x1:%\w+]] "x"
227fd4e5da5Sopenharmony_ci
228fd4e5da5Sopenharmony_ci       %uint = OpTypeInt 32 0
229fd4e5da5Sopenharmony_ci     %uint_2 = OpConstant %uint 2
230fd4e5da5Sopenharmony_ci%_arr_uint_uint_2 = OpTypeArray %uint %uint_2
231fd4e5da5Sopenharmony_ci%_ptr_Output__arr_uint_uint_2 = OpTypePointer Output %_arr_uint_uint_2
232fd4e5da5Sopenharmony_ci%_ptr_Input__arr_uint_uint_2 = OpTypePointer Input %_arr_uint_uint_2
233fd4e5da5Sopenharmony_ci          %z = OpVariable %_ptr_Output__arr_uint_uint_2 Output
234fd4e5da5Sopenharmony_ci          %x = OpVariable %_ptr_Output__arr_uint_uint_2 Output
235fd4e5da5Sopenharmony_ci          %y = OpVariable %_ptr_Input__arr_uint_uint_2 Input
236fd4e5da5Sopenharmony_ci          %w = OpVariable %_ptr_Input__arr_uint_uint_2 Input
237fd4e5da5Sopenharmony_ci
238fd4e5da5Sopenharmony_ci  ; CHECK-DAG: [[y]] = OpVariable %_ptr_Input__arr_uint_uint_2 Input
239fd4e5da5Sopenharmony_ci  ; CHECK-DAG: [[z0]] = OpVariable %_ptr_Output_uint Output
240fd4e5da5Sopenharmony_ci  ; CHECK-DAG: [[z1]] = OpVariable %_ptr_Output_uint Output
241fd4e5da5Sopenharmony_ci  ; CHECK-DAG: [[w0]] = OpVariable %_ptr_Input_uint Input
242fd4e5da5Sopenharmony_ci  ; CHECK-DAG: [[w1]] = OpVariable %_ptr_Input_uint Input
243fd4e5da5Sopenharmony_ci  ; CHECK-DAG: [[x0]] = OpVariable %_ptr_Output_uint Output
244fd4e5da5Sopenharmony_ci  ; CHECK-DAG: [[x1]] = OpVariable %_ptr_Output_uint Output
245fd4e5da5Sopenharmony_ci
246fd4e5da5Sopenharmony_ci     %void   = OpTypeVoid
247fd4e5da5Sopenharmony_ci     %void_f = OpTypeFunction %void
248fd4e5da5Sopenharmony_ci     %func   = OpFunction %void None %void_f
249fd4e5da5Sopenharmony_ci     %label  = OpLabel
250fd4e5da5Sopenharmony_ci               OpReturn
251fd4e5da5Sopenharmony_ci               OpFunctionEnd
252fd4e5da5Sopenharmony_ci  )";
253fd4e5da5Sopenharmony_ci
254fd4e5da5Sopenharmony_ci  SinglePassRunAndMatch<InterfaceVariableScalarReplacement>(spirv, true);
255fd4e5da5Sopenharmony_ci}
256fd4e5da5Sopenharmony_ci
257fd4e5da5Sopenharmony_ciTEST_F(InterfaceVariableScalarReplacementTest,
258fd4e5da5Sopenharmony_ci       CheckEntryPointInterfaceOperands) {
259fd4e5da5Sopenharmony_ci  const std::string spirv = R"(
260fd4e5da5Sopenharmony_ci               OpCapability Shader
261fd4e5da5Sopenharmony_ci               OpCapability Tessellation
262fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
263fd4e5da5Sopenharmony_ci               OpEntryPoint TessellationEvaluation %tess "tess" %x %y
264fd4e5da5Sopenharmony_ci               OpEntryPoint Vertex %vert "vert" %w
265fd4e5da5Sopenharmony_ci               OpDecorate %z Location 0
266fd4e5da5Sopenharmony_ci               OpDecorate %x Location 2
267fd4e5da5Sopenharmony_ci               OpDecorate %y Location 0
268fd4e5da5Sopenharmony_ci               OpDecorate %w Location 1
269fd4e5da5Sopenharmony_ci               OpName %x "x"
270fd4e5da5Sopenharmony_ci               OpName %y "y"
271fd4e5da5Sopenharmony_ci               OpName %z "z"
272fd4e5da5Sopenharmony_ci               OpName %w "w"
273fd4e5da5Sopenharmony_ci
274fd4e5da5Sopenharmony_ci  ; CHECK:     OpName [[y:%\w+]] "y"
275fd4e5da5Sopenharmony_ci  ; CHECK-NOT: OpName {{%\w+}} "y"
276fd4e5da5Sopenharmony_ci  ; CHECK-DAG: OpName [[x0:%\w+]] "x"
277fd4e5da5Sopenharmony_ci  ; CHECK-DAG: OpName [[x1:%\w+]] "x"
278fd4e5da5Sopenharmony_ci  ; CHECK-DAG: OpName [[w0:%\w+]] "w"
279fd4e5da5Sopenharmony_ci  ; CHECK-DAG: OpName [[w1:%\w+]] "w"
280fd4e5da5Sopenharmony_ci  ; CHECK-DAG: OpName [[z:%\w+]] "z"
281fd4e5da5Sopenharmony_ci  ; CHECK-NOT: OpName {{%\w+}} "z"
282fd4e5da5Sopenharmony_ci
283fd4e5da5Sopenharmony_ci       %uint = OpTypeInt 32 0
284fd4e5da5Sopenharmony_ci     %uint_2 = OpConstant %uint 2
285fd4e5da5Sopenharmony_ci%_arr_uint_uint_2 = OpTypeArray %uint %uint_2
286fd4e5da5Sopenharmony_ci%_ptr_Output__arr_uint_uint_2 = OpTypePointer Output %_arr_uint_uint_2
287fd4e5da5Sopenharmony_ci%_ptr_Input__arr_uint_uint_2 = OpTypePointer Input %_arr_uint_uint_2
288fd4e5da5Sopenharmony_ci          %z = OpVariable %_ptr_Output__arr_uint_uint_2 Output
289fd4e5da5Sopenharmony_ci          %x = OpVariable %_ptr_Output__arr_uint_uint_2 Output
290fd4e5da5Sopenharmony_ci          %y = OpVariable %_ptr_Input__arr_uint_uint_2 Input
291fd4e5da5Sopenharmony_ci          %w = OpVariable %_ptr_Input__arr_uint_uint_2 Input
292fd4e5da5Sopenharmony_ci
293fd4e5da5Sopenharmony_ci  ; CHECK-DAG: [[y]] = OpVariable %_ptr_Input__arr_uint_uint_2 Input
294fd4e5da5Sopenharmony_ci  ; CHECK-DAG: [[z]] = OpVariable %_ptr_Output__arr_uint_uint_2 Output
295fd4e5da5Sopenharmony_ci  ; CHECK-DAG: [[w0]] = OpVariable %_ptr_Input_uint Input
296fd4e5da5Sopenharmony_ci  ; CHECK-DAG: [[w1]] = OpVariable %_ptr_Input_uint Input
297fd4e5da5Sopenharmony_ci  ; CHECK-DAG: [[x0]] = OpVariable %_ptr_Output_uint Output
298fd4e5da5Sopenharmony_ci  ; CHECK-DAG: [[x1]] = OpVariable %_ptr_Output_uint Output
299fd4e5da5Sopenharmony_ci
300fd4e5da5Sopenharmony_ci     %void   = OpTypeVoid
301fd4e5da5Sopenharmony_ci     %void_f = OpTypeFunction %void
302fd4e5da5Sopenharmony_ci     %tess   = OpFunction %void None %void_f
303fd4e5da5Sopenharmony_ci     %bb0    = OpLabel
304fd4e5da5Sopenharmony_ci               OpReturn
305fd4e5da5Sopenharmony_ci               OpFunctionEnd
306fd4e5da5Sopenharmony_ci     %vert   = OpFunction %void None %void_f
307fd4e5da5Sopenharmony_ci     %bb1    = OpLabel
308fd4e5da5Sopenharmony_ci               OpReturn
309fd4e5da5Sopenharmony_ci               OpFunctionEnd
310fd4e5da5Sopenharmony_ci  )";
311fd4e5da5Sopenharmony_ci
312fd4e5da5Sopenharmony_ci  SinglePassRunAndMatch<InterfaceVariableScalarReplacement>(spirv, true);
313fd4e5da5Sopenharmony_ci}
314fd4e5da5Sopenharmony_ci
315fd4e5da5Sopenharmony_ciclass InterfaceVarSROAErrorTest : public PassTest<::testing::Test> {
316fd4e5da5Sopenharmony_ci public:
317fd4e5da5Sopenharmony_ci  InterfaceVarSROAErrorTest()
318fd4e5da5Sopenharmony_ci      : consumer_([this](spv_message_level_t level, const char*,
319fd4e5da5Sopenharmony_ci                         const spv_position_t& position, const char* message) {
320fd4e5da5Sopenharmony_ci          if (!error_message_.empty()) error_message_ += "\n";
321fd4e5da5Sopenharmony_ci          switch (level) {
322fd4e5da5Sopenharmony_ci            case SPV_MSG_FATAL:
323fd4e5da5Sopenharmony_ci            case SPV_MSG_INTERNAL_ERROR:
324fd4e5da5Sopenharmony_ci            case SPV_MSG_ERROR:
325fd4e5da5Sopenharmony_ci              error_message_ += "ERROR";
326fd4e5da5Sopenharmony_ci              break;
327fd4e5da5Sopenharmony_ci            case SPV_MSG_WARNING:
328fd4e5da5Sopenharmony_ci              error_message_ += "WARNING";
329fd4e5da5Sopenharmony_ci              break;
330fd4e5da5Sopenharmony_ci            case SPV_MSG_INFO:
331fd4e5da5Sopenharmony_ci              error_message_ += "INFO";
332fd4e5da5Sopenharmony_ci              break;
333fd4e5da5Sopenharmony_ci            case SPV_MSG_DEBUG:
334fd4e5da5Sopenharmony_ci              error_message_ += "DEBUG";
335fd4e5da5Sopenharmony_ci              break;
336fd4e5da5Sopenharmony_ci          }
337fd4e5da5Sopenharmony_ci          error_message_ +=
338fd4e5da5Sopenharmony_ci              ": " + std::to_string(position.index) + ": " + message;
339fd4e5da5Sopenharmony_ci        }) {}
340fd4e5da5Sopenharmony_ci
341fd4e5da5Sopenharmony_ci  Pass::Status RunPass(const std::string& text) {
342fd4e5da5Sopenharmony_ci    std::unique_ptr<IRContext> context_ =
343fd4e5da5Sopenharmony_ci        spvtools::BuildModule(SPV_ENV_UNIVERSAL_1_2, consumer_, text);
344fd4e5da5Sopenharmony_ci    if (!context_.get()) return Pass::Status::Failure;
345fd4e5da5Sopenharmony_ci
346fd4e5da5Sopenharmony_ci    PassManager manager;
347fd4e5da5Sopenharmony_ci    manager.SetMessageConsumer(consumer_);
348fd4e5da5Sopenharmony_ci    manager.AddPass<InterfaceVariableScalarReplacement>();
349fd4e5da5Sopenharmony_ci
350fd4e5da5Sopenharmony_ci    return manager.Run(context_.get());
351fd4e5da5Sopenharmony_ci  }
352fd4e5da5Sopenharmony_ci
353fd4e5da5Sopenharmony_ci  std::string GetErrorMessage() const { return error_message_; }
354fd4e5da5Sopenharmony_ci
355fd4e5da5Sopenharmony_ci  void TearDown() override { error_message_.clear(); }
356fd4e5da5Sopenharmony_ci
357fd4e5da5Sopenharmony_ci private:
358fd4e5da5Sopenharmony_ci  spvtools::MessageConsumer consumer_;
359fd4e5da5Sopenharmony_ci  std::string error_message_;
360fd4e5da5Sopenharmony_ci};
361fd4e5da5Sopenharmony_ci
362fd4e5da5Sopenharmony_ciTEST_F(InterfaceVarSROAErrorTest, CheckConflictOfExtraArraynessBetweenEntries) {
363fd4e5da5Sopenharmony_ci  const std::string spirv = R"(
364fd4e5da5Sopenharmony_ci               OpCapability Shader
365fd4e5da5Sopenharmony_ci               OpCapability Tessellation
366fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
367fd4e5da5Sopenharmony_ci               OpEntryPoint TessellationControl %tess "tess" %x %y %z
368fd4e5da5Sopenharmony_ci               OpEntryPoint Vertex %vert "vert" %z %w
369fd4e5da5Sopenharmony_ci               OpDecorate %z Location 0
370fd4e5da5Sopenharmony_ci               OpDecorate %x Location 2
371fd4e5da5Sopenharmony_ci               OpDecorate %y Location 0
372fd4e5da5Sopenharmony_ci               OpDecorate %w Location 1
373fd4e5da5Sopenharmony_ci               OpName %x "x"
374fd4e5da5Sopenharmony_ci               OpName %y "y"
375fd4e5da5Sopenharmony_ci               OpName %z "z"
376fd4e5da5Sopenharmony_ci               OpName %w "w"
377fd4e5da5Sopenharmony_ci       %uint = OpTypeInt 32 0
378fd4e5da5Sopenharmony_ci     %uint_2 = OpConstant %uint 2
379fd4e5da5Sopenharmony_ci%_arr_uint_uint_2 = OpTypeArray %uint %uint_2
380fd4e5da5Sopenharmony_ci%_ptr_Output__arr_uint_uint_2 = OpTypePointer Output %_arr_uint_uint_2
381fd4e5da5Sopenharmony_ci%_ptr_Input__arr_uint_uint_2 = OpTypePointer Input %_arr_uint_uint_2
382fd4e5da5Sopenharmony_ci          %z = OpVariable %_ptr_Output__arr_uint_uint_2 Output
383fd4e5da5Sopenharmony_ci          %x = OpVariable %_ptr_Output__arr_uint_uint_2 Output
384fd4e5da5Sopenharmony_ci          %y = OpVariable %_ptr_Input__arr_uint_uint_2 Input
385fd4e5da5Sopenharmony_ci          %w = OpVariable %_ptr_Input__arr_uint_uint_2 Input
386fd4e5da5Sopenharmony_ci     %void   = OpTypeVoid
387fd4e5da5Sopenharmony_ci     %void_f = OpTypeFunction %void
388fd4e5da5Sopenharmony_ci     %tess   = OpFunction %void None %void_f
389fd4e5da5Sopenharmony_ci     %bb0    = OpLabel
390fd4e5da5Sopenharmony_ci               OpReturn
391fd4e5da5Sopenharmony_ci               OpFunctionEnd
392fd4e5da5Sopenharmony_ci     %vert   = OpFunction %void None %void_f
393fd4e5da5Sopenharmony_ci     %bb1    = OpLabel
394fd4e5da5Sopenharmony_ci               OpReturn
395fd4e5da5Sopenharmony_ci               OpFunctionEnd
396fd4e5da5Sopenharmony_ci  )";
397fd4e5da5Sopenharmony_ci
398fd4e5da5Sopenharmony_ci  EXPECT_EQ(RunPass(spirv), Pass::Status::Failure);
399fd4e5da5Sopenharmony_ci  const char expected_error[] =
400fd4e5da5Sopenharmony_ci      "ERROR: 0: A variable is arrayed for an entry point but it is not "
401fd4e5da5Sopenharmony_ci      "arrayed for another entry point\n"
402fd4e5da5Sopenharmony_ci      "  %z = OpVariable %_ptr_Output__arr_uint_uint_2 Output";
403fd4e5da5Sopenharmony_ci  EXPECT_STREQ(GetErrorMessage().c_str(), expected_error);
404fd4e5da5Sopenharmony_ci}
405fd4e5da5Sopenharmony_ci
406fd4e5da5Sopenharmony_ci}  // namespace
407fd4e5da5Sopenharmony_ci}  // namespace opt
408fd4e5da5Sopenharmony_ci}  // namespace spvtools
409