1fd4e5da5Sopenharmony_ci// Copyright (c) 2017 Google Inc.
2fd4e5da5Sopenharmony_ci//
3fd4e5da5Sopenharmony_ci// Licensed under the Apache License, Version 2.0 (the "License");
4fd4e5da5Sopenharmony_ci// you may not use this file except in compliance with the License.
5fd4e5da5Sopenharmony_ci// You may obtain a copy of the License at
6fd4e5da5Sopenharmony_ci//
7fd4e5da5Sopenharmony_ci//     http://www.apache.org/licenses/LICENSE-2.0
8fd4e5da5Sopenharmony_ci//
9fd4e5da5Sopenharmony_ci// Unless required by applicable law or agreed to in writing, software
10fd4e5da5Sopenharmony_ci// distributed under the License is distributed on an "AS IS" BASIS,
11fd4e5da5Sopenharmony_ci// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12fd4e5da5Sopenharmony_ci// See the License for the specific language governing permissions and
13fd4e5da5Sopenharmony_ci// limitations under the License.
14fd4e5da5Sopenharmony_ci
15fd4e5da5Sopenharmony_ci#include <string>
16fd4e5da5Sopenharmony_ci
17fd4e5da5Sopenharmony_ci#include "gmock/gmock.h"
18fd4e5da5Sopenharmony_ci#include "source/opt/value_number_table.h"
19fd4e5da5Sopenharmony_ci#include "test/opt/assembly_builder.h"
20fd4e5da5Sopenharmony_ci#include "test/opt/pass_fixture.h"
21fd4e5da5Sopenharmony_ci#include "test/opt/pass_utils.h"
22fd4e5da5Sopenharmony_ci
23fd4e5da5Sopenharmony_cinamespace spvtools {
24fd4e5da5Sopenharmony_cinamespace opt {
25fd4e5da5Sopenharmony_cinamespace {
26fd4e5da5Sopenharmony_ci
27fd4e5da5Sopenharmony_ciusing ::testing::HasSubstr;
28fd4e5da5Sopenharmony_ciusing ::testing::MatchesRegex;
29fd4e5da5Sopenharmony_ciusing PrivateToLocalTest = PassTest<::testing::Test>;
30fd4e5da5Sopenharmony_ci
31fd4e5da5Sopenharmony_ciTEST_F(PrivateToLocalTest, ChangeToLocal) {
32fd4e5da5Sopenharmony_ci  // Change the private variable to a local, and change the types accordingly.
33fd4e5da5Sopenharmony_ci  const std::string text = R"(
34fd4e5da5Sopenharmony_ci               OpCapability Shader
35fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
36fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
37fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %2 "main"
38fd4e5da5Sopenharmony_ci               OpExecutionMode %2 OriginUpperLeft
39fd4e5da5Sopenharmony_ci               OpSource GLSL 430
40fd4e5da5Sopenharmony_ci          %3 = OpTypeVoid
41fd4e5da5Sopenharmony_ci          %4 = OpTypeFunction %3
42fd4e5da5Sopenharmony_ci; CHECK: [[float:%[a-zA-Z_\d]+]] = OpTypeFloat 32
43fd4e5da5Sopenharmony_ci          %5 = OpTypeFloat 32
44fd4e5da5Sopenharmony_ci; CHECK: [[newtype:%[a-zA-Z_\d]+]] = OpTypePointer Function [[float]]
45fd4e5da5Sopenharmony_ci          %6 = OpTypePointer Private %5
46fd4e5da5Sopenharmony_ci; CHECK-NOT: OpVariable [[.+]] Private
47fd4e5da5Sopenharmony_ci          %8 = OpVariable %6 Private
48fd4e5da5Sopenharmony_ci; CHECK: OpFunction
49fd4e5da5Sopenharmony_ci          %2 = OpFunction %3 None %4
50fd4e5da5Sopenharmony_ci; CHECK: OpLabel
51fd4e5da5Sopenharmony_ci          %7 = OpLabel
52fd4e5da5Sopenharmony_ci; CHECK-NEXT: [[newvar:%[a-zA-Z_\d]+]] = OpVariable [[newtype]] Function
53fd4e5da5Sopenharmony_ci; CHECK: OpLoad [[float]] [[newvar]]
54fd4e5da5Sopenharmony_ci          %9 = OpLoad %5 %8
55fd4e5da5Sopenharmony_ci               OpReturn
56fd4e5da5Sopenharmony_ci               OpFunctionEnd
57fd4e5da5Sopenharmony_ci  )";
58fd4e5da5Sopenharmony_ci  SinglePassRunAndMatch<PrivateToLocalPass>(text, false);
59fd4e5da5Sopenharmony_ci}
60fd4e5da5Sopenharmony_ci
61fd4e5da5Sopenharmony_ciTEST_F(PrivateToLocalTest, ReuseExistingType) {
62fd4e5da5Sopenharmony_ci  // Change the private variable to a local, and change the types accordingly.
63fd4e5da5Sopenharmony_ci  const std::string text = R"(
64fd4e5da5Sopenharmony_ci               OpCapability Shader
65fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
66fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
67fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %2 "main"
68fd4e5da5Sopenharmony_ci               OpExecutionMode %2 OriginUpperLeft
69fd4e5da5Sopenharmony_ci               OpSource GLSL 430
70fd4e5da5Sopenharmony_ci          %3 = OpTypeVoid
71fd4e5da5Sopenharmony_ci          %4 = OpTypeFunction %3
72fd4e5da5Sopenharmony_ci; CHECK: [[float:%[a-zA-Z_\d]+]] = OpTypeFloat 32
73fd4e5da5Sopenharmony_ci          %5 = OpTypeFloat 32
74fd4e5da5Sopenharmony_ci        %func_ptr = OpTypePointer Function %5
75fd4e5da5Sopenharmony_ci; CHECK: [[newtype:%[a-zA-Z_\d]+]] = OpTypePointer Function [[float]]
76fd4e5da5Sopenharmony_ci; CHECK-NOT: [[%[a-zA-Z_\d]+]] = OpTypePointer Function [[float]]
77fd4e5da5Sopenharmony_ci          %6 = OpTypePointer Private %5
78fd4e5da5Sopenharmony_ci; CHECK-NOT: OpVariable [[.+]] Private
79fd4e5da5Sopenharmony_ci          %8 = OpVariable %6 Private
80fd4e5da5Sopenharmony_ci; CHECK: OpFunction
81fd4e5da5Sopenharmony_ci          %2 = OpFunction %3 None %4
82fd4e5da5Sopenharmony_ci; CHECK: OpLabel
83fd4e5da5Sopenharmony_ci          %7 = OpLabel
84fd4e5da5Sopenharmony_ci; CHECK-NEXT: [[newvar:%[a-zA-Z_\d]+]] = OpVariable [[newtype]] Function
85fd4e5da5Sopenharmony_ci; CHECK: OpLoad [[float]] [[newvar]]
86fd4e5da5Sopenharmony_ci          %9 = OpLoad %5 %8
87fd4e5da5Sopenharmony_ci               OpReturn
88fd4e5da5Sopenharmony_ci               OpFunctionEnd
89fd4e5da5Sopenharmony_ci  )";
90fd4e5da5Sopenharmony_ci  SinglePassRunAndMatch<PrivateToLocalPass>(text, false);
91fd4e5da5Sopenharmony_ci}
92fd4e5da5Sopenharmony_ci
93fd4e5da5Sopenharmony_ciTEST_F(PrivateToLocalTest, UpdateAccessChain) {
94fd4e5da5Sopenharmony_ci  // Change the private variable to a local, and change the AccessChain.
95fd4e5da5Sopenharmony_ci  const std::string text = R"(
96fd4e5da5Sopenharmony_ci               OpCapability Shader
97fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
98fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
99fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %2 "main"
100fd4e5da5Sopenharmony_ci               OpExecutionMode %2 OriginUpperLeft
101fd4e5da5Sopenharmony_ci               OpSource GLSL 430
102fd4e5da5Sopenharmony_ci       %uint = OpTypeInt 32 0
103fd4e5da5Sopenharmony_ci     %uint_0 = OpConstant %uint 0
104fd4e5da5Sopenharmony_ci       %void = OpTypeVoid
105fd4e5da5Sopenharmony_ci          %6 = OpTypeFunction %void
106fd4e5da5Sopenharmony_ci; CHECK: [[float:%[a-zA-Z_\d]+]] = OpTypeFloat
107fd4e5da5Sopenharmony_ci      %float = OpTypeFloat 32
108fd4e5da5Sopenharmony_ci; CHECK: [[struct:%[a-zA-Z_\d]+]] = OpTypeStruct
109fd4e5da5Sopenharmony_ci  %_struct_8 = OpTypeStruct %float
110fd4e5da5Sopenharmony_ci%_ptr_Private_float = OpTypePointer Private %float
111fd4e5da5Sopenharmony_ci; CHECK: [[new_struct_type:%[a-zA-Z_\d]+]] = OpTypePointer Function [[struct]]
112fd4e5da5Sopenharmony_ci; CHECK: [[new_float_type:%[a-zA-Z_\d]+]] = OpTypePointer Function [[float]]
113fd4e5da5Sopenharmony_ci%_ptr_Private__struct_8 = OpTypePointer Private %_struct_8
114fd4e5da5Sopenharmony_ci; CHECK-NOT: OpVariable [[.+]] Private
115fd4e5da5Sopenharmony_ci         %11 = OpVariable %_ptr_Private__struct_8 Private
116fd4e5da5Sopenharmony_ci; CHECK: OpFunction
117fd4e5da5Sopenharmony_ci          %2 = OpFunction %void None %6
118fd4e5da5Sopenharmony_ci; CHECK: OpLabel
119fd4e5da5Sopenharmony_ci         %12 = OpLabel
120fd4e5da5Sopenharmony_ci; CHECK-NEXT: [[newvar:%[a-zA-Z_\d]+]] = OpVariable [[new_struct_type]] Function
121fd4e5da5Sopenharmony_ci; CHECK: [[member:%[a-zA-Z_\d]+]] = OpAccessChain [[new_float_type]] [[newvar]]
122fd4e5da5Sopenharmony_ci         %13 = OpAccessChain %_ptr_Private_float %11 %uint_0
123fd4e5da5Sopenharmony_ci; CHECK: OpLoad [[float]] [[member]]
124fd4e5da5Sopenharmony_ci         %14 = OpLoad %float %13
125fd4e5da5Sopenharmony_ci               OpReturn
126fd4e5da5Sopenharmony_ci               OpFunctionEnd
127fd4e5da5Sopenharmony_ci  )";
128fd4e5da5Sopenharmony_ci  SinglePassRunAndMatch<PrivateToLocalPass>(text, false);
129fd4e5da5Sopenharmony_ci}
130fd4e5da5Sopenharmony_ci
131fd4e5da5Sopenharmony_ciTEST_F(PrivateToLocalTest, UseTexelPointer) {
132fd4e5da5Sopenharmony_ci  // Change the private variable to a local, and change the OpImageTexelPointer.
133fd4e5da5Sopenharmony_ci  const std::string text = R"(
134fd4e5da5Sopenharmony_ciOpCapability SampledBuffer
135fd4e5da5Sopenharmony_ci               OpCapability StorageImageExtendedFormats
136fd4e5da5Sopenharmony_ci               OpCapability ImageBuffer
137fd4e5da5Sopenharmony_ci               OpCapability Shader
138fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
139fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
140fd4e5da5Sopenharmony_ci               OpEntryPoint GLCompute %2 "min" %gl_GlobalInvocationID
141fd4e5da5Sopenharmony_ci               OpExecutionMode %2 LocalSize 64 1 1
142fd4e5da5Sopenharmony_ci               OpSource HLSL 600
143fd4e5da5Sopenharmony_ci               OpDecorate %gl_GlobalInvocationID BuiltIn GlobalInvocationId
144fd4e5da5Sopenharmony_ci               OpDecorate %4 DescriptorSet 4
145fd4e5da5Sopenharmony_ci               OpDecorate %4 Binding 70
146fd4e5da5Sopenharmony_ci       %uint = OpTypeInt 32 0
147fd4e5da5Sopenharmony_ci          %6 = OpTypeImage %uint Buffer 0 0 0 2 R32ui
148fd4e5da5Sopenharmony_ci%_ptr_UniformConstant_6 = OpTypePointer UniformConstant %6
149fd4e5da5Sopenharmony_ci%_ptr_Private_6 = OpTypePointer Private %6
150fd4e5da5Sopenharmony_ci       %void = OpTypeVoid
151fd4e5da5Sopenharmony_ci         %10 = OpTypeFunction %void
152fd4e5da5Sopenharmony_ci     %uint_0 = OpConstant %uint 0
153fd4e5da5Sopenharmony_ci     %uint_1 = OpConstant %uint 1
154fd4e5da5Sopenharmony_ci     %v3uint = OpTypeVector %uint 3
155fd4e5da5Sopenharmony_ci%_ptr_Input_v3uint = OpTypePointer Input %v3uint
156fd4e5da5Sopenharmony_ci%_ptr_Image_uint = OpTypePointer Image %uint
157fd4e5da5Sopenharmony_ci          %4 = OpVariable %_ptr_UniformConstant_6 UniformConstant
158fd4e5da5Sopenharmony_ci         %16 = OpVariable %_ptr_Private_6 Private
159fd4e5da5Sopenharmony_ci%gl_GlobalInvocationID = OpVariable %_ptr_Input_v3uint Input
160fd4e5da5Sopenharmony_ci          %2 = OpFunction %void None %10
161fd4e5da5Sopenharmony_ci         %17 = OpLabel
162fd4e5da5Sopenharmony_ci; Make sure the variable was moved.
163fd4e5da5Sopenharmony_ci; CHECK: OpFunction
164fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpLabel
165fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpVariable %_ptr_Function_6 Function
166fd4e5da5Sopenharmony_ci         %18 = OpLoad %6 %4
167fd4e5da5Sopenharmony_ci               OpStore %16 %18
168fd4e5da5Sopenharmony_ci         %19 = OpImageTexelPointer %_ptr_Image_uint %16 %uint_0 %uint_0
169fd4e5da5Sopenharmony_ci         %20 = OpAtomicIAdd %uint %19 %uint_1 %uint_0 %uint_1
170fd4e5da5Sopenharmony_ci               OpReturn
171fd4e5da5Sopenharmony_ci               OpFunctionEnd
172fd4e5da5Sopenharmony_ci  )";
173fd4e5da5Sopenharmony_ci  SinglePassRunAndMatch<PrivateToLocalPass>(text, false);
174fd4e5da5Sopenharmony_ci}
175fd4e5da5Sopenharmony_ci
176fd4e5da5Sopenharmony_ciTEST_F(PrivateToLocalTest, UsedInTwoFunctions) {
177fd4e5da5Sopenharmony_ci  // Should not change because it is used in multiple functions.
178fd4e5da5Sopenharmony_ci  const std::string text = R"(
179fd4e5da5Sopenharmony_ci               OpCapability Shader
180fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
181fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
182fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %2 "main"
183fd4e5da5Sopenharmony_ci               OpExecutionMode %2 OriginUpperLeft
184fd4e5da5Sopenharmony_ci               OpSource GLSL 430
185fd4e5da5Sopenharmony_ci          %3 = OpTypeVoid
186fd4e5da5Sopenharmony_ci          %4 = OpTypeFunction %3
187fd4e5da5Sopenharmony_ci          %5 = OpTypeFloat 32
188fd4e5da5Sopenharmony_ci          %6 = OpTypePointer Private %5
189fd4e5da5Sopenharmony_ci          %8 = OpVariable %6 Private
190fd4e5da5Sopenharmony_ci          %2 = OpFunction %3 None %4
191fd4e5da5Sopenharmony_ci          %7 = OpLabel
192fd4e5da5Sopenharmony_ci          %9 = OpLoad %5 %8
193fd4e5da5Sopenharmony_ci               OpReturn
194fd4e5da5Sopenharmony_ci               OpFunctionEnd
195fd4e5da5Sopenharmony_ci         %10 = OpFunction %3 None %4
196fd4e5da5Sopenharmony_ci         %11 = OpLabel
197fd4e5da5Sopenharmony_ci         %12 = OpLoad %5 %8
198fd4e5da5Sopenharmony_ci               OpReturn
199fd4e5da5Sopenharmony_ci               OpFunctionEnd
200fd4e5da5Sopenharmony_ci  )";
201fd4e5da5Sopenharmony_ci  auto result = SinglePassRunAndDisassemble<StrengthReductionPass>(
202fd4e5da5Sopenharmony_ci      text, /* skip_nop = */ true, /* do_validation = */ false);
203fd4e5da5Sopenharmony_ci  EXPECT_EQ(Pass::Status::SuccessWithoutChange, std::get<1>(result));
204fd4e5da5Sopenharmony_ci}
205fd4e5da5Sopenharmony_ci
206fd4e5da5Sopenharmony_ciTEST_F(PrivateToLocalTest, UsedInFunctionCall) {
207fd4e5da5Sopenharmony_ci  // Should not change because it is used in a function call.  Changing the
208fd4e5da5Sopenharmony_ci  // signature of the function would require cloning the function, which is not
209fd4e5da5Sopenharmony_ci  // worth it.
210fd4e5da5Sopenharmony_ci  const std::string text = R"(
211fd4e5da5Sopenharmony_ci               OpCapability Shader
212fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
213fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
214fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %2 "main"
215fd4e5da5Sopenharmony_ci               OpExecutionMode %2 OriginUpperLeft
216fd4e5da5Sopenharmony_ci               OpSource GLSL 430
217fd4e5da5Sopenharmony_ci       %void = OpTypeVoid
218fd4e5da5Sopenharmony_ci          %4 = OpTypeFunction %void
219fd4e5da5Sopenharmony_ci      %float = OpTypeFloat 32
220fd4e5da5Sopenharmony_ci%_ptr_Private_float = OpTypePointer Private %float
221fd4e5da5Sopenharmony_ci          %7 = OpTypeFunction %void %_ptr_Private_float
222fd4e5da5Sopenharmony_ci          %8 = OpVariable %_ptr_Private_float Private
223fd4e5da5Sopenharmony_ci          %2 = OpFunction %void None %4
224fd4e5da5Sopenharmony_ci          %9 = OpLabel
225fd4e5da5Sopenharmony_ci         %10 = OpFunctionCall %void %11 %8
226fd4e5da5Sopenharmony_ci               OpReturn
227fd4e5da5Sopenharmony_ci               OpFunctionEnd
228fd4e5da5Sopenharmony_ci         %11 = OpFunction %void None %7
229fd4e5da5Sopenharmony_ci         %12 = OpFunctionParameter %_ptr_Private_float
230fd4e5da5Sopenharmony_ci         %13 = OpLabel
231fd4e5da5Sopenharmony_ci         %14 = OpLoad %float %12
232fd4e5da5Sopenharmony_ci               OpReturn
233fd4e5da5Sopenharmony_ci               OpFunctionEnd
234fd4e5da5Sopenharmony_ci  )";
235fd4e5da5Sopenharmony_ci  auto result = SinglePassRunAndDisassemble<StrengthReductionPass>(
236fd4e5da5Sopenharmony_ci      text, /* skip_nop = */ true, /* do_validation = */ false);
237fd4e5da5Sopenharmony_ci  EXPECT_EQ(Pass::Status::SuccessWithoutChange, std::get<1>(result));
238fd4e5da5Sopenharmony_ci}
239fd4e5da5Sopenharmony_ci
240fd4e5da5Sopenharmony_ciTEST_F(PrivateToLocalTest, CreatePointerToAmbiguousStruct1) {
241fd4e5da5Sopenharmony_ci  // Test that the correct pointer type is picked up.
242fd4e5da5Sopenharmony_ci  const std::string text = R"(
243fd4e5da5Sopenharmony_ci; CHECK: [[struct1:%[a-zA-Z_\d]+]] = OpTypeStruct
244fd4e5da5Sopenharmony_ci; CHECK: [[struct2:%[a-zA-Z_\d]+]] = OpTypeStruct
245fd4e5da5Sopenharmony_ci; CHECK: [[priv_ptr:%[\w]+]] = OpTypePointer Private [[struct1]]
246fd4e5da5Sopenharmony_ci; CHECK: [[fuct_ptr2:%[\w]+]] = OpTypePointer Function [[struct2]]
247fd4e5da5Sopenharmony_ci; CHECK: [[fuct_ptr1:%[\w]+]] = OpTypePointer Function [[struct1]]
248fd4e5da5Sopenharmony_ci; CHECK: OpFunction
249fd4e5da5Sopenharmony_ci; CHECK: OpLabel
250fd4e5da5Sopenharmony_ci; CHECK-NEXT: [[newvar:%[a-zA-Z_\d]+]] = OpVariable [[fuct_ptr1]] Function
251fd4e5da5Sopenharmony_ci; CHECK: OpLoad [[struct1]] [[newvar]]
252fd4e5da5Sopenharmony_ci               OpCapability Shader
253fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
254fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
255fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %2 "main"
256fd4e5da5Sopenharmony_ci               OpExecutionMode %2 OriginUpperLeft
257fd4e5da5Sopenharmony_ci               OpSource GLSL 430
258fd4e5da5Sopenharmony_ci          %3 = OpTypeVoid
259fd4e5da5Sopenharmony_ci          %4 = OpTypeFunction %3
260fd4e5da5Sopenharmony_ci          %5 = OpTypeFloat 32
261fd4e5da5Sopenharmony_ci    %struct1 = OpTypeStruct %5
262fd4e5da5Sopenharmony_ci    %struct2 = OpTypeStruct %5
263fd4e5da5Sopenharmony_ci          %6 = OpTypePointer Private %struct1
264fd4e5da5Sopenharmony_ci  %func_ptr2 = OpTypePointer Function %struct2
265fd4e5da5Sopenharmony_ci          %8 = OpVariable %6 Private
266fd4e5da5Sopenharmony_ci          %2 = OpFunction %3 None %4
267fd4e5da5Sopenharmony_ci          %7 = OpLabel
268fd4e5da5Sopenharmony_ci          %9 = OpLoad %struct1 %8
269fd4e5da5Sopenharmony_ci               OpReturn
270fd4e5da5Sopenharmony_ci               OpFunctionEnd
271fd4e5da5Sopenharmony_ci  )";
272fd4e5da5Sopenharmony_ci  SinglePassRunAndMatch<PrivateToLocalPass>(text, false);
273fd4e5da5Sopenharmony_ci}
274fd4e5da5Sopenharmony_ci
275fd4e5da5Sopenharmony_ciTEST_F(PrivateToLocalTest, CreatePointerToAmbiguousStruct2) {
276fd4e5da5Sopenharmony_ci  // Test that the correct pointer type is picked up.
277fd4e5da5Sopenharmony_ci  const std::string text = R"(
278fd4e5da5Sopenharmony_ci; CHECK: [[struct1:%[a-zA-Z_\d]+]] = OpTypeStruct
279fd4e5da5Sopenharmony_ci; CHECK: [[struct2:%[a-zA-Z_\d]+]] = OpTypeStruct
280fd4e5da5Sopenharmony_ci; CHECK: [[priv_ptr:%[\w]+]] = OpTypePointer Private [[struct2]]
281fd4e5da5Sopenharmony_ci; CHECK: [[fuct_ptr1:%[\w]+]] = OpTypePointer Function [[struct1]]
282fd4e5da5Sopenharmony_ci; CHECK: [[fuct_ptr2:%[\w]+]] = OpTypePointer Function [[struct2]]
283fd4e5da5Sopenharmony_ci; CHECK: OpFunction
284fd4e5da5Sopenharmony_ci; CHECK: OpLabel
285fd4e5da5Sopenharmony_ci; CHECK-NEXT: [[newvar:%[a-zA-Z_\d]+]] = OpVariable [[fuct_ptr2]] Function
286fd4e5da5Sopenharmony_ci; CHECK: OpLoad [[struct2]] [[newvar]]
287fd4e5da5Sopenharmony_ci               OpCapability Shader
288fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
289fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
290fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %2 "main"
291fd4e5da5Sopenharmony_ci               OpExecutionMode %2 OriginUpperLeft
292fd4e5da5Sopenharmony_ci               OpSource GLSL 430
293fd4e5da5Sopenharmony_ci          %3 = OpTypeVoid
294fd4e5da5Sopenharmony_ci          %4 = OpTypeFunction %3
295fd4e5da5Sopenharmony_ci          %5 = OpTypeFloat 32
296fd4e5da5Sopenharmony_ci    %struct1 = OpTypeStruct %5
297fd4e5da5Sopenharmony_ci    %struct2 = OpTypeStruct %5
298fd4e5da5Sopenharmony_ci          %6 = OpTypePointer Private %struct2
299fd4e5da5Sopenharmony_ci  %func_ptr2 = OpTypePointer Function %struct1
300fd4e5da5Sopenharmony_ci          %8 = OpVariable %6 Private
301fd4e5da5Sopenharmony_ci          %2 = OpFunction %3 None %4
302fd4e5da5Sopenharmony_ci          %7 = OpLabel
303fd4e5da5Sopenharmony_ci          %9 = OpLoad %struct2 %8
304fd4e5da5Sopenharmony_ci               OpReturn
305fd4e5da5Sopenharmony_ci               OpFunctionEnd
306fd4e5da5Sopenharmony_ci  )";
307fd4e5da5Sopenharmony_ci  SinglePassRunAndMatch<PrivateToLocalPass>(text, false);
308fd4e5da5Sopenharmony_ci}
309fd4e5da5Sopenharmony_ci
310fd4e5da5Sopenharmony_ciTEST_F(PrivateToLocalTest, SPV14RemoveFromInterface) {
311fd4e5da5Sopenharmony_ci  const std::string text = R"(
312fd4e5da5Sopenharmony_ci; CHECK-NOT: OpEntryPoint GLCompute %foo "foo" %in %priv
313fd4e5da5Sopenharmony_ci; CHECK: OpEntryPoint GLCompute %foo "foo" %in
314fd4e5da5Sopenharmony_ci; CHECK: %priv = OpVariable {{%\w+}} Function
315fd4e5da5Sopenharmony_ciOpCapability Shader
316fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
317fd4e5da5Sopenharmony_ciOpEntryPoint GLCompute %foo "foo" %in %priv
318fd4e5da5Sopenharmony_ciOpExecutionMode %foo LocalSize 1 1 1
319fd4e5da5Sopenharmony_ciOpName %foo "foo"
320fd4e5da5Sopenharmony_ciOpName %in "in"
321fd4e5da5Sopenharmony_ciOpName %priv "priv"
322fd4e5da5Sopenharmony_ci%void = OpTypeVoid
323fd4e5da5Sopenharmony_ci%int = OpTypeInt 32 0
324fd4e5da5Sopenharmony_ci%ptr_ssbo_int = OpTypePointer StorageBuffer %int
325fd4e5da5Sopenharmony_ci%ptr_private_int = OpTypePointer Private %int
326fd4e5da5Sopenharmony_ci%in = OpVariable %ptr_ssbo_int StorageBuffer
327fd4e5da5Sopenharmony_ci%priv = OpVariable %ptr_private_int Private
328fd4e5da5Sopenharmony_ci%void_fn = OpTypeFunction %void
329fd4e5da5Sopenharmony_ci%foo = OpFunction %void None %void_fn
330fd4e5da5Sopenharmony_ci%entry = OpLabel
331fd4e5da5Sopenharmony_ci%ld = OpLoad %int %in
332fd4e5da5Sopenharmony_ciOpStore %priv %ld
333fd4e5da5Sopenharmony_ciOpReturn
334fd4e5da5Sopenharmony_ciOpFunctionEnd
335fd4e5da5Sopenharmony_ci)";
336fd4e5da5Sopenharmony_ci
337fd4e5da5Sopenharmony_ci  SetTargetEnv(SPV_ENV_UNIVERSAL_1_4);
338fd4e5da5Sopenharmony_ci  SinglePassRunAndMatch<PrivateToLocalPass>(text, true);
339fd4e5da5Sopenharmony_ci}
340fd4e5da5Sopenharmony_ci
341fd4e5da5Sopenharmony_ciTEST_F(PrivateToLocalTest, SPV14RemoveFromInterfaceMultipleEntryPoints) {
342fd4e5da5Sopenharmony_ci  const std::string text = R"(
343fd4e5da5Sopenharmony_ci; CHECK-NOT: OpEntryPoint GLCompute %foo "foo" %in %priv
344fd4e5da5Sopenharmony_ci; CHECK-NOT: OpEntryPoint GLCompute %foo "bar" %in %priv
345fd4e5da5Sopenharmony_ci; CHECK: OpEntryPoint GLCompute %foo "foo" %in
346fd4e5da5Sopenharmony_ci; CHECK: OpEntryPoint GLCompute %foo "bar" %in
347fd4e5da5Sopenharmony_ci; CHECK: %priv = OpVariable {{%\w+}} Function
348fd4e5da5Sopenharmony_ciOpCapability Shader
349fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
350fd4e5da5Sopenharmony_ciOpEntryPoint GLCompute %foo "foo" %in %priv
351fd4e5da5Sopenharmony_ciOpEntryPoint GLCompute %foo "bar" %in %priv
352fd4e5da5Sopenharmony_ciOpExecutionMode %foo LocalSize 1 1 1
353fd4e5da5Sopenharmony_ciOpName %foo "foo"
354fd4e5da5Sopenharmony_ciOpName %in "in"
355fd4e5da5Sopenharmony_ciOpName %priv "priv"
356fd4e5da5Sopenharmony_ci%void = OpTypeVoid
357fd4e5da5Sopenharmony_ci%int = OpTypeInt 32 0
358fd4e5da5Sopenharmony_ci%ptr_ssbo_int = OpTypePointer StorageBuffer %int
359fd4e5da5Sopenharmony_ci%ptr_private_int = OpTypePointer Private %int
360fd4e5da5Sopenharmony_ci%in = OpVariable %ptr_ssbo_int StorageBuffer
361fd4e5da5Sopenharmony_ci%priv = OpVariable %ptr_private_int Private
362fd4e5da5Sopenharmony_ci%void_fn = OpTypeFunction %void
363fd4e5da5Sopenharmony_ci%foo = OpFunction %void None %void_fn
364fd4e5da5Sopenharmony_ci%entry = OpLabel
365fd4e5da5Sopenharmony_ci%ld = OpLoad %int %in
366fd4e5da5Sopenharmony_ciOpStore %priv %ld
367fd4e5da5Sopenharmony_ciOpReturn
368fd4e5da5Sopenharmony_ciOpFunctionEnd
369fd4e5da5Sopenharmony_ci)";
370fd4e5da5Sopenharmony_ci
371fd4e5da5Sopenharmony_ci  SetTargetEnv(SPV_ENV_UNIVERSAL_1_4);
372fd4e5da5Sopenharmony_ci  SinglePassRunAndMatch<PrivateToLocalPass>(text, true);
373fd4e5da5Sopenharmony_ci}
374fd4e5da5Sopenharmony_ci
375fd4e5da5Sopenharmony_ciTEST_F(PrivateToLocalTest, SPV14RemoveFromInterfaceMultipleVariables) {
376fd4e5da5Sopenharmony_ci  const std::string text = R"(
377fd4e5da5Sopenharmony_ci; CHECK-NOT: OpEntryPoint GLCompute %foo "foo" %in %priv1 %priv2
378fd4e5da5Sopenharmony_ci; CHECK: OpEntryPoint GLCompute %foo "foo" %in
379fd4e5da5Sopenharmony_ci; CHECK: %priv1 = OpVariable {{%\w+}} Function
380fd4e5da5Sopenharmony_ci; CHECK: %priv2 = OpVariable {{%\w+}} Function
381fd4e5da5Sopenharmony_ciOpCapability Shader
382fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
383fd4e5da5Sopenharmony_ciOpEntryPoint GLCompute %foo "foo" %in %priv1 %priv2
384fd4e5da5Sopenharmony_ciOpExecutionMode %foo LocalSize 1 1 1
385fd4e5da5Sopenharmony_ciOpName %foo "foo"
386fd4e5da5Sopenharmony_ciOpName %in "in"
387fd4e5da5Sopenharmony_ciOpName %priv1 "priv1"
388fd4e5da5Sopenharmony_ciOpName %priv2 "priv2"
389fd4e5da5Sopenharmony_ci%void = OpTypeVoid
390fd4e5da5Sopenharmony_ci%int = OpTypeInt 32 0
391fd4e5da5Sopenharmony_ci%ptr_ssbo_int = OpTypePointer StorageBuffer %int
392fd4e5da5Sopenharmony_ci%ptr_private_int = OpTypePointer Private %int
393fd4e5da5Sopenharmony_ci%in = OpVariable %ptr_ssbo_int StorageBuffer
394fd4e5da5Sopenharmony_ci%priv1 = OpVariable %ptr_private_int Private
395fd4e5da5Sopenharmony_ci%priv2 = OpVariable %ptr_private_int Private
396fd4e5da5Sopenharmony_ci%void_fn = OpTypeFunction %void
397fd4e5da5Sopenharmony_ci%foo = OpFunction %void None %void_fn
398fd4e5da5Sopenharmony_ci%entry = OpLabel
399fd4e5da5Sopenharmony_ci%1 = OpFunctionCall %void %bar1
400fd4e5da5Sopenharmony_ci%2 = OpFunctionCall %void %bar2
401fd4e5da5Sopenharmony_ciOpReturn
402fd4e5da5Sopenharmony_ciOpFunctionEnd
403fd4e5da5Sopenharmony_ci%bar1 = OpFunction %void None %void_fn
404fd4e5da5Sopenharmony_ci%3 = OpLabel
405fd4e5da5Sopenharmony_ci%ld1 = OpLoad %int %in
406fd4e5da5Sopenharmony_ciOpStore %priv1 %ld1
407fd4e5da5Sopenharmony_ciOpReturn
408fd4e5da5Sopenharmony_ciOpFunctionEnd
409fd4e5da5Sopenharmony_ci%bar2 = OpFunction %void None %void_fn
410fd4e5da5Sopenharmony_ci%4 = OpLabel
411fd4e5da5Sopenharmony_ci%ld2 = OpLoad %int %in
412fd4e5da5Sopenharmony_ciOpStore %priv2 %ld2
413fd4e5da5Sopenharmony_ciOpReturn
414fd4e5da5Sopenharmony_ciOpFunctionEnd
415fd4e5da5Sopenharmony_ci)";
416fd4e5da5Sopenharmony_ci
417fd4e5da5Sopenharmony_ci  SetTargetEnv(SPV_ENV_UNIVERSAL_1_4);
418fd4e5da5Sopenharmony_ci  SinglePassRunAndMatch<PrivateToLocalPass>(text, true);
419fd4e5da5Sopenharmony_ci}
420fd4e5da5Sopenharmony_ci
421fd4e5da5Sopenharmony_ciTEST_F(PrivateToLocalTest, IdBoundOverflow1) {
422fd4e5da5Sopenharmony_ci  const std::string text = R"(
423fd4e5da5Sopenharmony_ci               OpCapability Shader
424fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
425fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %4 "main"
426fd4e5da5Sopenharmony_ci               OpExecutionMode %4 OriginLowerLeft
427fd4e5da5Sopenharmony_ci               OpSource HLSL 84
428fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
429fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
430fd4e5da5Sopenharmony_ci          %6 = OpTypeFloat 32
431fd4e5da5Sopenharmony_ci          %7 = OpTypeVector %6 4
432fd4e5da5Sopenharmony_ci          %8 = OpTypeStruct %7
433fd4e5da5Sopenharmony_ci    %4194302 = OpTypeStruct %8 %8
434fd4e5da5Sopenharmony_ci          %9 = OpTypeStruct %8 %8
435fd4e5da5Sopenharmony_ci         %11 = OpTypePointer Private %7
436fd4e5da5Sopenharmony_ci         %18 = OpTypeStruct %6 %9
437fd4e5da5Sopenharmony_ci         %12 = OpVariable %11 Private
438fd4e5da5Sopenharmony_ci          %4 = OpFunction %2 None %3
439fd4e5da5Sopenharmony_ci          %5 = OpLabel
440fd4e5da5Sopenharmony_ci         %13 = OpLoad %7 %12
441fd4e5da5Sopenharmony_ci               OpReturn
442fd4e5da5Sopenharmony_ci               OpFunctionEnd
443fd4e5da5Sopenharmony_ci  )";
444fd4e5da5Sopenharmony_ci
445fd4e5da5Sopenharmony_ci  SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
446fd4e5da5Sopenharmony_ci
447fd4e5da5Sopenharmony_ci  std::vector<Message> messages = {
448fd4e5da5Sopenharmony_ci      {SPV_MSG_ERROR, "", 0, 0, "ID overflow. Try running compact-ids."}};
449fd4e5da5Sopenharmony_ci  SetMessageConsumer(GetTestMessageConsumer(messages));
450fd4e5da5Sopenharmony_ci  auto result = SinglePassRunToBinary<PrivateToLocalPass>(text, true);
451fd4e5da5Sopenharmony_ci  EXPECT_EQ(Pass::Status::Failure, std::get<1>(result));
452fd4e5da5Sopenharmony_ci}
453fd4e5da5Sopenharmony_ci
454fd4e5da5Sopenharmony_ciTEST_F(PrivateToLocalTest, DebugPrivateToLocal) {
455fd4e5da5Sopenharmony_ci  // Debug instructions must not have any impact on changing the private
456fd4e5da5Sopenharmony_ci  // variable to a local.
457fd4e5da5Sopenharmony_ci  const std::string text = R"(
458fd4e5da5Sopenharmony_ci               OpCapability Shader
459fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
460fd4e5da5Sopenharmony_ci         %10 = OpExtInstImport "OpenCL.DebugInfo.100"
461fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
462fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %2 "main"
463fd4e5da5Sopenharmony_ci               OpExecutionMode %2 OriginUpperLeft
464fd4e5da5Sopenharmony_ci         %11 = OpString "test"
465fd4e5da5Sopenharmony_ci               OpSource GLSL 430
466fd4e5da5Sopenharmony_ci         %13 = OpTypeInt 32 0
467fd4e5da5Sopenharmony_ci         %14 = OpConstant %13 32
468fd4e5da5Sopenharmony_ci          %3 = OpTypeVoid
469fd4e5da5Sopenharmony_ci          %4 = OpTypeFunction %3
470fd4e5da5Sopenharmony_ci; CHECK: [[float:%[a-zA-Z_\d]+]] = OpTypeFloat 32
471fd4e5da5Sopenharmony_ci          %5 = OpTypeFloat 32
472fd4e5da5Sopenharmony_ci; CHECK: [[newtype:%[a-zA-Z_\d]+]] = OpTypePointer Function [[float]]
473fd4e5da5Sopenharmony_ci          %6 = OpTypePointer Private %5
474fd4e5da5Sopenharmony_ci; CHECK-NOT: OpVariable [[.+]] Private
475fd4e5da5Sopenharmony_ci          %8 = OpVariable %6 Private
476fd4e5da5Sopenharmony_ci
477fd4e5da5Sopenharmony_ci         %12 = OpExtInst %3 %10 DebugTypeBasic %11 %14 Float
478fd4e5da5Sopenharmony_ci         %15 = OpExtInst %3 %10 DebugSource %11
479fd4e5da5Sopenharmony_ci         %16 = OpExtInst %3 %10 DebugCompilationUnit 1 4 %15 GLSL
480fd4e5da5Sopenharmony_ci; CHECK-NOT: DebugGlobalVariable
481fd4e5da5Sopenharmony_ci; CHECK: [[dbg_newvar:%[a-zA-Z_\d]+]] = OpExtInst {{%\w+}} {{%\w+}} DebugLocalVariable
482fd4e5da5Sopenharmony_ci         %17 = OpExtInst %3 %10 DebugGlobalVariable %11 %12 %15 0 0 %16 %11 %8 FlagIsDefinition
483fd4e5da5Sopenharmony_ci
484fd4e5da5Sopenharmony_ci; CHECK: OpFunction
485fd4e5da5Sopenharmony_ci          %2 = OpFunction %3 None %4
486fd4e5da5Sopenharmony_ci; CHECK: OpLabel
487fd4e5da5Sopenharmony_ci          %7 = OpLabel
488fd4e5da5Sopenharmony_ci; CHECK-NEXT: [[newvar:%[a-zA-Z_\d]+]] = OpVariable [[newtype]] Function
489fd4e5da5Sopenharmony_ci; CHECK-NEXT: DebugDeclare [[dbg_newvar]] [[newvar]]
490fd4e5da5Sopenharmony_ci; CHECK: OpLoad [[float]] [[newvar]]
491fd4e5da5Sopenharmony_ci          %9 = OpLoad %5 %8
492fd4e5da5Sopenharmony_ci               OpReturn
493fd4e5da5Sopenharmony_ci               OpFunctionEnd
494fd4e5da5Sopenharmony_ci  )";
495fd4e5da5Sopenharmony_ci  SinglePassRunAndMatch<PrivateToLocalPass>(text, true);
496fd4e5da5Sopenharmony_ci}
497fd4e5da5Sopenharmony_ci
498fd4e5da5Sopenharmony_ci}  // namespace
499fd4e5da5Sopenharmony_ci}  // namespace opt
500fd4e5da5Sopenharmony_ci}  // namespace spvtools
501