1fd4e5da5Sopenharmony_ci// Copyright (c) 2020 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 "source/reduce/remove_unused_struct_member_reduction_opportunity_finder.h"
16fd4e5da5Sopenharmony_ci
17fd4e5da5Sopenharmony_ci#include "source/opt/build_module.h"
18fd4e5da5Sopenharmony_ci#include "source/reduce/reduction_opportunity.h"
19fd4e5da5Sopenharmony_ci#include "test/reduce/reduce_test_util.h"
20fd4e5da5Sopenharmony_ci
21fd4e5da5Sopenharmony_cinamespace spvtools {
22fd4e5da5Sopenharmony_cinamespace reduce {
23fd4e5da5Sopenharmony_cinamespace {
24fd4e5da5Sopenharmony_ci
25fd4e5da5Sopenharmony_ciTEST(RemoveUnusedStructMemberTest, RemoveOneMember) {
26fd4e5da5Sopenharmony_ci  std::string shader = R"(
27fd4e5da5Sopenharmony_ci               OpCapability Shader
28fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
29fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
30fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %4 "main"
31fd4e5da5Sopenharmony_ci               OpExecutionMode %4 OriginUpperLeft
32fd4e5da5Sopenharmony_ci               OpSource ESSL 310
33fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
34fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
35fd4e5da5Sopenharmony_ci          %6 = OpTypeInt 32 1
36fd4e5da5Sopenharmony_ci          %7 = OpTypeStruct %6 %6
37fd4e5da5Sopenharmony_ci          %8 = OpTypePointer Function %7
38fd4e5da5Sopenharmony_ci         %50 = OpConstant %6 0
39fd4e5da5Sopenharmony_ci         %10 = OpConstant %6 1
40fd4e5da5Sopenharmony_ci         %11 = OpConstant %6 2
41fd4e5da5Sopenharmony_ci         %12 = OpConstantComposite %7 %10 %11
42fd4e5da5Sopenharmony_ci         %13 = OpConstant %6 4
43fd4e5da5Sopenharmony_ci         %14 = OpTypePointer Function %6
44fd4e5da5Sopenharmony_ci          %4 = OpFunction %2 None %3
45fd4e5da5Sopenharmony_ci          %5 = OpLabel
46fd4e5da5Sopenharmony_ci          %9 = OpVariable %8 Function
47fd4e5da5Sopenharmony_ci               OpStore %9 %12
48fd4e5da5Sopenharmony_ci         %15 = OpAccessChain %14 %9 %10
49fd4e5da5Sopenharmony_ci         %22 = OpInBoundsAccessChain %14 %9 %10
50fd4e5da5Sopenharmony_ci         %20 = OpLoad %7 %9
51fd4e5da5Sopenharmony_ci         %21 = OpCompositeExtract %6 %20 1
52fd4e5da5Sopenharmony_ci         %23 = OpCompositeInsert %7 %10 %20 1
53fd4e5da5Sopenharmony_ci               OpStore %15 %13
54fd4e5da5Sopenharmony_ci               OpReturn
55fd4e5da5Sopenharmony_ci               OpFunctionEnd
56fd4e5da5Sopenharmony_ci  )";
57fd4e5da5Sopenharmony_ci
58fd4e5da5Sopenharmony_ci  const auto env = SPV_ENV_UNIVERSAL_1_3;
59fd4e5da5Sopenharmony_ci  const auto consumer = nullptr;
60fd4e5da5Sopenharmony_ci  const auto context =
61fd4e5da5Sopenharmony_ci      BuildModule(env, consumer, shader, kReduceAssembleOption);
62fd4e5da5Sopenharmony_ci
63fd4e5da5Sopenharmony_ci  auto ops = RemoveUnusedStructMemberReductionOpportunityFinder()
64fd4e5da5Sopenharmony_ci                 .GetAvailableOpportunities(context.get(), 0);
65fd4e5da5Sopenharmony_ci  ASSERT_EQ(1, ops.size());
66fd4e5da5Sopenharmony_ci  ASSERT_TRUE(ops[0]->PreconditionHolds());
67fd4e5da5Sopenharmony_ci  ops[0]->TryToApply();
68fd4e5da5Sopenharmony_ci
69fd4e5da5Sopenharmony_ci  CheckValid(env, context.get());
70fd4e5da5Sopenharmony_ci
71fd4e5da5Sopenharmony_ci  std::string expected = R"(
72fd4e5da5Sopenharmony_ci               OpCapability Shader
73fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
74fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
75fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %4 "main"
76fd4e5da5Sopenharmony_ci               OpExecutionMode %4 OriginUpperLeft
77fd4e5da5Sopenharmony_ci               OpSource ESSL 310
78fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
79fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
80fd4e5da5Sopenharmony_ci          %6 = OpTypeInt 32 1
81fd4e5da5Sopenharmony_ci          %7 = OpTypeStruct %6
82fd4e5da5Sopenharmony_ci          %8 = OpTypePointer Function %7
83fd4e5da5Sopenharmony_ci         %50 = OpConstant %6 0
84fd4e5da5Sopenharmony_ci         %10 = OpConstant %6 1
85fd4e5da5Sopenharmony_ci         %11 = OpConstant %6 2
86fd4e5da5Sopenharmony_ci         %12 = OpConstantComposite %7 %11
87fd4e5da5Sopenharmony_ci         %13 = OpConstant %6 4
88fd4e5da5Sopenharmony_ci         %14 = OpTypePointer Function %6
89fd4e5da5Sopenharmony_ci          %4 = OpFunction %2 None %3
90fd4e5da5Sopenharmony_ci          %5 = OpLabel
91fd4e5da5Sopenharmony_ci          %9 = OpVariable %8 Function
92fd4e5da5Sopenharmony_ci               OpStore %9 %12
93fd4e5da5Sopenharmony_ci         %15 = OpAccessChain %14 %9 %50
94fd4e5da5Sopenharmony_ci         %22 = OpInBoundsAccessChain %14 %9 %50
95fd4e5da5Sopenharmony_ci         %20 = OpLoad %7 %9
96fd4e5da5Sopenharmony_ci         %21 = OpCompositeExtract %6 %20 0
97fd4e5da5Sopenharmony_ci         %23 = OpCompositeInsert %7 %10 %20 0
98fd4e5da5Sopenharmony_ci               OpStore %15 %13
99fd4e5da5Sopenharmony_ci               OpReturn
100fd4e5da5Sopenharmony_ci               OpFunctionEnd
101fd4e5da5Sopenharmony_ci  )";
102fd4e5da5Sopenharmony_ci
103fd4e5da5Sopenharmony_ci  CheckEqual(env, expected, context.get());
104fd4e5da5Sopenharmony_ci}
105fd4e5da5Sopenharmony_ci
106fd4e5da5Sopenharmony_ciTEST(RemoveUnusedStructMemberTest, RemoveUniformBufferMember) {
107fd4e5da5Sopenharmony_ci  std::string shader = R"(
108fd4e5da5Sopenharmony_ci               OpCapability Shader
109fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
110fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
111fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %4 "main"
112fd4e5da5Sopenharmony_ci               OpExecutionMode %4 OriginUpperLeft
113fd4e5da5Sopenharmony_ci               OpSource ESSL 310
114fd4e5da5Sopenharmony_ci               OpMemberDecorate %10 0 Offset 0
115fd4e5da5Sopenharmony_ci               OpMemberDecorate %10 1 Offset 4
116fd4e5da5Sopenharmony_ci               OpDecorate %10 Block
117fd4e5da5Sopenharmony_ci               OpDecorate %12 DescriptorSet 0
118fd4e5da5Sopenharmony_ci               OpDecorate %12 Binding 0
119fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
120fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
121fd4e5da5Sopenharmony_ci          %6 = OpTypeFloat 32
122fd4e5da5Sopenharmony_ci          %7 = OpTypePointer Function %6
123fd4e5da5Sopenharmony_ci          %9 = OpTypeInt 32 1
124fd4e5da5Sopenharmony_ci         %10 = OpTypeStruct %9 %6
125fd4e5da5Sopenharmony_ci         %11 = OpTypePointer Uniform %10
126fd4e5da5Sopenharmony_ci         %12 = OpVariable %11 Uniform
127fd4e5da5Sopenharmony_ci         %13 = OpConstant %9 1
128fd4e5da5Sopenharmony_ci         %20 = OpConstant %9 0
129fd4e5da5Sopenharmony_ci         %14 = OpTypePointer Uniform %6
130fd4e5da5Sopenharmony_ci          %4 = OpFunction %2 None %3
131fd4e5da5Sopenharmony_ci          %5 = OpLabel
132fd4e5da5Sopenharmony_ci          %8 = OpVariable %7 Function
133fd4e5da5Sopenharmony_ci         %15 = OpAccessChain %14 %12 %13
134fd4e5da5Sopenharmony_ci         %16 = OpLoad %6 %15
135fd4e5da5Sopenharmony_ci               OpStore %8 %16
136fd4e5da5Sopenharmony_ci               OpReturn
137fd4e5da5Sopenharmony_ci               OpFunctionEnd
138fd4e5da5Sopenharmony_ci  )";
139fd4e5da5Sopenharmony_ci
140fd4e5da5Sopenharmony_ci  const auto env = SPV_ENV_UNIVERSAL_1_3;
141fd4e5da5Sopenharmony_ci  const auto consumer = nullptr;
142fd4e5da5Sopenharmony_ci  const auto context =
143fd4e5da5Sopenharmony_ci      BuildModule(env, consumer, shader, kReduceAssembleOption);
144fd4e5da5Sopenharmony_ci
145fd4e5da5Sopenharmony_ci  auto ops = RemoveUnusedStructMemberReductionOpportunityFinder()
146fd4e5da5Sopenharmony_ci                 .GetAvailableOpportunities(context.get(), 0);
147fd4e5da5Sopenharmony_ci  ASSERT_EQ(1, ops.size());
148fd4e5da5Sopenharmony_ci  ASSERT_TRUE(ops[0]->PreconditionHolds());
149fd4e5da5Sopenharmony_ci  ops[0]->TryToApply();
150fd4e5da5Sopenharmony_ci
151fd4e5da5Sopenharmony_ci  CheckValid(env, context.get());
152fd4e5da5Sopenharmony_ci
153fd4e5da5Sopenharmony_ci  std::string expected = R"(
154fd4e5da5Sopenharmony_ci               OpCapability Shader
155fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
156fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
157fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %4 "main"
158fd4e5da5Sopenharmony_ci               OpExecutionMode %4 OriginUpperLeft
159fd4e5da5Sopenharmony_ci               OpSource ESSL 310
160fd4e5da5Sopenharmony_ci               OpMemberDecorate %10 0 Offset 4
161fd4e5da5Sopenharmony_ci               OpDecorate %10 Block
162fd4e5da5Sopenharmony_ci               OpDecorate %12 DescriptorSet 0
163fd4e5da5Sopenharmony_ci               OpDecorate %12 Binding 0
164fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
165fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
166fd4e5da5Sopenharmony_ci          %6 = OpTypeFloat 32
167fd4e5da5Sopenharmony_ci          %7 = OpTypePointer Function %6
168fd4e5da5Sopenharmony_ci          %9 = OpTypeInt 32 1
169fd4e5da5Sopenharmony_ci         %10 = OpTypeStruct %6
170fd4e5da5Sopenharmony_ci         %11 = OpTypePointer Uniform %10
171fd4e5da5Sopenharmony_ci         %12 = OpVariable %11 Uniform
172fd4e5da5Sopenharmony_ci         %13 = OpConstant %9 1
173fd4e5da5Sopenharmony_ci         %20 = OpConstant %9 0
174fd4e5da5Sopenharmony_ci         %14 = OpTypePointer Uniform %6
175fd4e5da5Sopenharmony_ci          %4 = OpFunction %2 None %3
176fd4e5da5Sopenharmony_ci          %5 = OpLabel
177fd4e5da5Sopenharmony_ci          %8 = OpVariable %7 Function
178fd4e5da5Sopenharmony_ci         %15 = OpAccessChain %14 %12 %20
179fd4e5da5Sopenharmony_ci         %16 = OpLoad %6 %15
180fd4e5da5Sopenharmony_ci               OpStore %8 %16
181fd4e5da5Sopenharmony_ci               OpReturn
182fd4e5da5Sopenharmony_ci               OpFunctionEnd
183fd4e5da5Sopenharmony_ci  )";
184fd4e5da5Sopenharmony_ci
185fd4e5da5Sopenharmony_ci  CheckEqual(env, expected, context.get());
186fd4e5da5Sopenharmony_ci}
187fd4e5da5Sopenharmony_ci
188fd4e5da5Sopenharmony_ciTEST(RemoveUnusedStructMemberTest, DoNotRemoveNamedMemberRemoveOneMember) {
189fd4e5da5Sopenharmony_ci  // This illustrates that naming a member is enough to prevent its removal.
190fd4e5da5Sopenharmony_ci  // Removal of names is done by a different pass.
191fd4e5da5Sopenharmony_ci
192fd4e5da5Sopenharmony_ci  std::string shader = R"(
193fd4e5da5Sopenharmony_ci               OpCapability Shader
194fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
195fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
196fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %4 "main"
197fd4e5da5Sopenharmony_ci               OpExecutionMode %4 OriginUpperLeft
198fd4e5da5Sopenharmony_ci               OpSource ESSL 310
199fd4e5da5Sopenharmony_ci               OpMemberName %7 0 "someName"
200fd4e5da5Sopenharmony_ci               OpMemberName %7 1 "someOtherName"
201fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
202fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
203fd4e5da5Sopenharmony_ci          %6 = OpTypeInt 32 1
204fd4e5da5Sopenharmony_ci          %7 = OpTypeStruct %6 %6
205fd4e5da5Sopenharmony_ci          %8 = OpTypePointer Function %7
206fd4e5da5Sopenharmony_ci         %50 = OpConstant %6 0
207fd4e5da5Sopenharmony_ci         %10 = OpConstant %6 1
208fd4e5da5Sopenharmony_ci         %11 = OpConstant %6 2
209fd4e5da5Sopenharmony_ci         %12 = OpConstantComposite %7 %10 %11
210fd4e5da5Sopenharmony_ci         %13 = OpConstant %6 4
211fd4e5da5Sopenharmony_ci         %14 = OpTypePointer Function %6
212fd4e5da5Sopenharmony_ci          %4 = OpFunction %2 None %3
213fd4e5da5Sopenharmony_ci          %5 = OpLabel
214fd4e5da5Sopenharmony_ci          %9 = OpVariable %8 Function
215fd4e5da5Sopenharmony_ci               OpStore %9 %12
216fd4e5da5Sopenharmony_ci         %15 = OpAccessChain %14 %9 %10
217fd4e5da5Sopenharmony_ci         %22 = OpInBoundsAccessChain %14 %9 %10
218fd4e5da5Sopenharmony_ci         %20 = OpLoad %7 %9
219fd4e5da5Sopenharmony_ci         %21 = OpCompositeExtract %6 %20 1
220fd4e5da5Sopenharmony_ci         %23 = OpCompositeInsert %7 %10 %20 1
221fd4e5da5Sopenharmony_ci               OpStore %15 %13
222fd4e5da5Sopenharmony_ci               OpReturn
223fd4e5da5Sopenharmony_ci               OpFunctionEnd
224fd4e5da5Sopenharmony_ci  )";
225fd4e5da5Sopenharmony_ci
226fd4e5da5Sopenharmony_ci  const auto env = SPV_ENV_UNIVERSAL_1_3;
227fd4e5da5Sopenharmony_ci  const auto consumer = nullptr;
228fd4e5da5Sopenharmony_ci  const auto context =
229fd4e5da5Sopenharmony_ci      BuildModule(env, consumer, shader, kReduceAssembleOption);
230fd4e5da5Sopenharmony_ci
231fd4e5da5Sopenharmony_ci  auto ops = RemoveUnusedStructMemberReductionOpportunityFinder()
232fd4e5da5Sopenharmony_ci                 .GetAvailableOpportunities(context.get(), 0);
233fd4e5da5Sopenharmony_ci  ASSERT_EQ(0, ops.size());
234fd4e5da5Sopenharmony_ci}
235fd4e5da5Sopenharmony_ci
236fd4e5da5Sopenharmony_ci}  // namespace
237fd4e5da5Sopenharmony_ci}  // namespace reduce
238fd4e5da5Sopenharmony_ci}  // namespace spvtools
239