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