1fd4e5da5Sopenharmony_ci// Copyright (c) 2018 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_instruction_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 "source/util/make_unique.h"
20fd4e5da5Sopenharmony_ci#include "test/reduce/reduce_test_util.h"
21fd4e5da5Sopenharmony_ci
22fd4e5da5Sopenharmony_cinamespace spvtools {
23fd4e5da5Sopenharmony_cinamespace reduce {
24fd4e5da5Sopenharmony_cinamespace {
25fd4e5da5Sopenharmony_ci
26fd4e5da5Sopenharmony_ciconst spv_target_env kEnv = SPV_ENV_UNIVERSAL_1_3;
27fd4e5da5Sopenharmony_ci
28fd4e5da5Sopenharmony_ciTEST(RemoveUnusedInstructionReductionPassTest, RemoveStores) {
29fd4e5da5Sopenharmony_ci  // A module with some unused instructions, including some unused OpStore
30fd4e5da5Sopenharmony_ci  // instructions.
31fd4e5da5Sopenharmony_ci
32fd4e5da5Sopenharmony_ci  RemoveUnusedInstructionReductionOpportunityFinder finder(true);
33fd4e5da5Sopenharmony_ci
34fd4e5da5Sopenharmony_ci  const std::string original = R"(
35fd4e5da5Sopenharmony_ci               OpCapability Shader
36fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
37fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
38fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %4 "main"
39fd4e5da5Sopenharmony_ci               OpExecutionMode %4 OriginUpperLeft
40fd4e5da5Sopenharmony_ci               OpSource ESSL 310  ; 0
41fd4e5da5Sopenharmony_ci               OpName %4 "main"   ; 1
42fd4e5da5Sopenharmony_ci               OpName %8 "a"      ; 2
43fd4e5da5Sopenharmony_ci               OpName %10 "b"     ; 3
44fd4e5da5Sopenharmony_ci               OpName %12 "c"     ; 4
45fd4e5da5Sopenharmony_ci               OpName %14 "d"     ; 5
46fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
47fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
48fd4e5da5Sopenharmony_ci          %6 = OpTypeInt 32 1
49fd4e5da5Sopenharmony_ci          %7 = OpTypePointer Function %6
50fd4e5da5Sopenharmony_ci          %9 = OpConstant %6 10
51fd4e5da5Sopenharmony_ci         %11 = OpConstant %6 20
52fd4e5da5Sopenharmony_ci         %13 = OpConstant %6 30
53fd4e5da5Sopenharmony_ci          %4 = OpFunction %2 None %3
54fd4e5da5Sopenharmony_ci          %5 = OpLabel
55fd4e5da5Sopenharmony_ci          %8 = OpVariable %7 Function
56fd4e5da5Sopenharmony_ci         %10 = OpVariable %7 Function
57fd4e5da5Sopenharmony_ci         %12 = OpVariable %7 Function
58fd4e5da5Sopenharmony_ci         %14 = OpVariable %7 Function
59fd4e5da5Sopenharmony_ci               OpStore %8 %9           ; 6
60fd4e5da5Sopenharmony_ci               OpStore %10 %11         ; 7
61fd4e5da5Sopenharmony_ci               OpStore %12 %13         ; 8
62fd4e5da5Sopenharmony_ci         %15 = OpLoad %6 %8
63fd4e5da5Sopenharmony_ci               OpStore %14 %15         ; 9
64fd4e5da5Sopenharmony_ci               OpReturn
65fd4e5da5Sopenharmony_ci               OpFunctionEnd
66fd4e5da5Sopenharmony_ci
67fd4e5da5Sopenharmony_ci  )";
68fd4e5da5Sopenharmony_ci
69fd4e5da5Sopenharmony_ci  const MessageConsumer consumer = nullptr;
70fd4e5da5Sopenharmony_ci  const auto context =
71fd4e5da5Sopenharmony_ci      BuildModule(kEnv, consumer, original, kReduceAssembleOption);
72fd4e5da5Sopenharmony_ci
73fd4e5da5Sopenharmony_ci  CheckValid(kEnv, context.get());
74fd4e5da5Sopenharmony_ci
75fd4e5da5Sopenharmony_ci  auto ops = finder.GetAvailableOpportunities(context.get(), 0);
76fd4e5da5Sopenharmony_ci
77fd4e5da5Sopenharmony_ci  ASSERT_EQ(10, ops.size());
78fd4e5da5Sopenharmony_ci
79fd4e5da5Sopenharmony_ci  for (auto& op : ops) {
80fd4e5da5Sopenharmony_ci    ASSERT_TRUE(op->PreconditionHolds());
81fd4e5da5Sopenharmony_ci    op->TryToApply();
82fd4e5da5Sopenharmony_ci    CheckValid(kEnv, context.get());
83fd4e5da5Sopenharmony_ci  }
84fd4e5da5Sopenharmony_ci
85fd4e5da5Sopenharmony_ci  const std::string step_2 = R"(
86fd4e5da5Sopenharmony_ci               OpCapability Shader
87fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
88fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
89fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %4 "main"
90fd4e5da5Sopenharmony_ci               OpExecutionMode %4 OriginUpperLeft
91fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
92fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
93fd4e5da5Sopenharmony_ci          %6 = OpTypeInt 32 1
94fd4e5da5Sopenharmony_ci          %7 = OpTypePointer Function %6
95fd4e5da5Sopenharmony_ci          %9 = OpConstant %6 10       ; 0
96fd4e5da5Sopenharmony_ci         %11 = OpConstant %6 20       ; 1
97fd4e5da5Sopenharmony_ci         %13 = OpConstant %6 30       ; 2
98fd4e5da5Sopenharmony_ci          %4 = OpFunction %2 None %3
99fd4e5da5Sopenharmony_ci          %5 = OpLabel
100fd4e5da5Sopenharmony_ci          %8 = OpVariable %7 Function
101fd4e5da5Sopenharmony_ci         %10 = OpVariable %7 Function ; 3
102fd4e5da5Sopenharmony_ci         %12 = OpVariable %7 Function ; 4
103fd4e5da5Sopenharmony_ci         %14 = OpVariable %7 Function ; 5
104fd4e5da5Sopenharmony_ci         %15 = OpLoad %6 %8           ; 6
105fd4e5da5Sopenharmony_ci               OpReturn
106fd4e5da5Sopenharmony_ci               OpFunctionEnd
107fd4e5da5Sopenharmony_ci  )";
108fd4e5da5Sopenharmony_ci
109fd4e5da5Sopenharmony_ci  CheckEqual(kEnv, step_2, context.get());
110fd4e5da5Sopenharmony_ci
111fd4e5da5Sopenharmony_ci  ops = finder.GetAvailableOpportunities(context.get(), 0);
112fd4e5da5Sopenharmony_ci
113fd4e5da5Sopenharmony_ci  ASSERT_EQ(7, ops.size());
114fd4e5da5Sopenharmony_ci
115fd4e5da5Sopenharmony_ci  for (auto& op : ops) {
116fd4e5da5Sopenharmony_ci    ASSERT_TRUE(op->PreconditionHolds());
117fd4e5da5Sopenharmony_ci    op->TryToApply();
118fd4e5da5Sopenharmony_ci    CheckValid(kEnv, context.get());
119fd4e5da5Sopenharmony_ci  }
120fd4e5da5Sopenharmony_ci
121fd4e5da5Sopenharmony_ci  const std::string step_3 = R"(
122fd4e5da5Sopenharmony_ci               OpCapability Shader
123fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
124fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
125fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %4 "main"
126fd4e5da5Sopenharmony_ci               OpExecutionMode %4 OriginUpperLeft
127fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
128fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
129fd4e5da5Sopenharmony_ci          %6 = OpTypeInt 32 1
130fd4e5da5Sopenharmony_ci          %7 = OpTypePointer Function %6
131fd4e5da5Sopenharmony_ci          %4 = OpFunction %2 None %3
132fd4e5da5Sopenharmony_ci          %5 = OpLabel
133fd4e5da5Sopenharmony_ci          %8 = OpVariable %7 Function   ; 0
134fd4e5da5Sopenharmony_ci               OpReturn
135fd4e5da5Sopenharmony_ci               OpFunctionEnd
136fd4e5da5Sopenharmony_ci  )";
137fd4e5da5Sopenharmony_ci
138fd4e5da5Sopenharmony_ci  CheckEqual(kEnv, step_3, context.get());
139fd4e5da5Sopenharmony_ci
140fd4e5da5Sopenharmony_ci  ops = finder.GetAvailableOpportunities(context.get(), 0);
141fd4e5da5Sopenharmony_ci
142fd4e5da5Sopenharmony_ci  ASSERT_EQ(1, ops.size());
143fd4e5da5Sopenharmony_ci
144fd4e5da5Sopenharmony_ci  for (auto& op : ops) {
145fd4e5da5Sopenharmony_ci    ASSERT_TRUE(op->PreconditionHolds());
146fd4e5da5Sopenharmony_ci    op->TryToApply();
147fd4e5da5Sopenharmony_ci    CheckValid(kEnv, context.get());
148fd4e5da5Sopenharmony_ci  }
149fd4e5da5Sopenharmony_ci
150fd4e5da5Sopenharmony_ci  const std::string step_4 = R"(
151fd4e5da5Sopenharmony_ci               OpCapability Shader
152fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
153fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
154fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %4 "main"
155fd4e5da5Sopenharmony_ci               OpExecutionMode %4 OriginUpperLeft
156fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
157fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
158fd4e5da5Sopenharmony_ci          %6 = OpTypeInt 32 1
159fd4e5da5Sopenharmony_ci          %7 = OpTypePointer Function %6  ; 0
160fd4e5da5Sopenharmony_ci          %4 = OpFunction %2 None %3
161fd4e5da5Sopenharmony_ci          %5 = OpLabel
162fd4e5da5Sopenharmony_ci               OpReturn
163fd4e5da5Sopenharmony_ci               OpFunctionEnd
164fd4e5da5Sopenharmony_ci  )";
165fd4e5da5Sopenharmony_ci
166fd4e5da5Sopenharmony_ci  CheckEqual(kEnv, step_4, context.get());
167fd4e5da5Sopenharmony_ci
168fd4e5da5Sopenharmony_ci  ops = finder.GetAvailableOpportunities(context.get(), 0);
169fd4e5da5Sopenharmony_ci
170fd4e5da5Sopenharmony_ci  ASSERT_EQ(1, ops.size());
171fd4e5da5Sopenharmony_ci
172fd4e5da5Sopenharmony_ci  for (auto& op : ops) {
173fd4e5da5Sopenharmony_ci    ASSERT_TRUE(op->PreconditionHolds());
174fd4e5da5Sopenharmony_ci    op->TryToApply();
175fd4e5da5Sopenharmony_ci    CheckValid(kEnv, context.get());
176fd4e5da5Sopenharmony_ci  }
177fd4e5da5Sopenharmony_ci
178fd4e5da5Sopenharmony_ci  const std::string step_5 = R"(
179fd4e5da5Sopenharmony_ci               OpCapability Shader
180fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
181fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
182fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %4 "main"
183fd4e5da5Sopenharmony_ci               OpExecutionMode %4 OriginUpperLeft
184fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
185fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
186fd4e5da5Sopenharmony_ci          %6 = OpTypeInt 32 1        ; 0
187fd4e5da5Sopenharmony_ci          %4 = OpFunction %2 None %3
188fd4e5da5Sopenharmony_ci          %5 = OpLabel
189fd4e5da5Sopenharmony_ci               OpReturn
190fd4e5da5Sopenharmony_ci               OpFunctionEnd
191fd4e5da5Sopenharmony_ci  )";
192fd4e5da5Sopenharmony_ci
193fd4e5da5Sopenharmony_ci  CheckEqual(kEnv, step_5, context.get());
194fd4e5da5Sopenharmony_ci
195fd4e5da5Sopenharmony_ci  ops = finder.GetAvailableOpportunities(context.get(), 0);
196fd4e5da5Sopenharmony_ci
197fd4e5da5Sopenharmony_ci  ASSERT_EQ(1, ops.size());
198fd4e5da5Sopenharmony_ci
199fd4e5da5Sopenharmony_ci  for (auto& op : ops) {
200fd4e5da5Sopenharmony_ci    ASSERT_TRUE(op->PreconditionHolds());
201fd4e5da5Sopenharmony_ci    op->TryToApply();
202fd4e5da5Sopenharmony_ci    CheckValid(kEnv, context.get());
203fd4e5da5Sopenharmony_ci  }
204fd4e5da5Sopenharmony_ci
205fd4e5da5Sopenharmony_ci  const std::string step_6 = R"(
206fd4e5da5Sopenharmony_ci               OpCapability Shader
207fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
208fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
209fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %4 "main"
210fd4e5da5Sopenharmony_ci               OpExecutionMode %4 OriginUpperLeft
211fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
212fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
213fd4e5da5Sopenharmony_ci          %4 = OpFunction %2 None %3
214fd4e5da5Sopenharmony_ci          %5 = OpLabel
215fd4e5da5Sopenharmony_ci               OpReturn
216fd4e5da5Sopenharmony_ci               OpFunctionEnd
217fd4e5da5Sopenharmony_ci  )";
218fd4e5da5Sopenharmony_ci
219fd4e5da5Sopenharmony_ci  CheckEqual(kEnv, step_6, context.get());
220fd4e5da5Sopenharmony_ci
221fd4e5da5Sopenharmony_ci  ops = finder.GetAvailableOpportunities(context.get(), 0);
222fd4e5da5Sopenharmony_ci
223fd4e5da5Sopenharmony_ci  ASSERT_EQ(0, ops.size());
224fd4e5da5Sopenharmony_ci}
225fd4e5da5Sopenharmony_ci
226fd4e5da5Sopenharmony_ciTEST(RemoveUnusedInstructionReductionPassTest, Referenced) {
227fd4e5da5Sopenharmony_ci  // A module with some unused global variables, constants, and types. Some will
228fd4e5da5Sopenharmony_ci  // not be removed initially because of the OpDecorate instructions.
229fd4e5da5Sopenharmony_ci
230fd4e5da5Sopenharmony_ci  RemoveUnusedInstructionReductionOpportunityFinder finder(true);
231fd4e5da5Sopenharmony_ci
232fd4e5da5Sopenharmony_ci  const std::string shader = R"(
233fd4e5da5Sopenharmony_ci               OpCapability Shader
234fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
235fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
236fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %4 "main"
237fd4e5da5Sopenharmony_ci               OpExecutionMode %4 OriginUpperLeft
238fd4e5da5Sopenharmony_ci               OpSource ESSL 310                 ; 1
239fd4e5da5Sopenharmony_ci               OpName %4 "main"                  ; 2
240fd4e5da5Sopenharmony_ci               OpName %12 "a"                    ; 3
241fd4e5da5Sopenharmony_ci               OpDecorate %12 RelaxedPrecision   ; 4
242fd4e5da5Sopenharmony_ci               OpDecorate %13 RelaxedPrecision   ; 5
243fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
244fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
245fd4e5da5Sopenharmony_ci          %6 = OpTypeBool
246fd4e5da5Sopenharmony_ci          %7 = OpConstantTrue %6                 ; 6
247fd4e5da5Sopenharmony_ci         %10 = OpTypeInt 32 1
248fd4e5da5Sopenharmony_ci         %11 = OpTypePointer Private %10
249fd4e5da5Sopenharmony_ci         %12 = OpVariable %11 Private
250fd4e5da5Sopenharmony_ci         %13 = OpConstant %10 1
251fd4e5da5Sopenharmony_ci          %4 = OpFunction %2 None %3
252fd4e5da5Sopenharmony_ci          %5 = OpLabel
253fd4e5da5Sopenharmony_ci               OpReturn
254fd4e5da5Sopenharmony_ci               OpFunctionEnd
255fd4e5da5Sopenharmony_ci  )";
256fd4e5da5Sopenharmony_ci
257fd4e5da5Sopenharmony_ci  auto context = BuildModule(kEnv, nullptr, shader, kReduceAssembleOption);
258fd4e5da5Sopenharmony_ci
259fd4e5da5Sopenharmony_ci  CheckValid(kEnv, context.get());
260fd4e5da5Sopenharmony_ci
261fd4e5da5Sopenharmony_ci  auto ops = finder.GetAvailableOpportunities(context.get(), 0);
262fd4e5da5Sopenharmony_ci
263fd4e5da5Sopenharmony_ci  ASSERT_EQ(6, ops.size());
264fd4e5da5Sopenharmony_ci
265fd4e5da5Sopenharmony_ci  for (auto& op : ops) {
266fd4e5da5Sopenharmony_ci    ASSERT_TRUE(op->PreconditionHolds());
267fd4e5da5Sopenharmony_ci    op->TryToApply();
268fd4e5da5Sopenharmony_ci    CheckValid(kEnv, context.get());
269fd4e5da5Sopenharmony_ci  }
270fd4e5da5Sopenharmony_ci
271fd4e5da5Sopenharmony_ci  std::string after = R"(
272fd4e5da5Sopenharmony_ci               OpCapability Shader
273fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
274fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
275fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %4 "main"
276fd4e5da5Sopenharmony_ci               OpExecutionMode %4 OriginUpperLeft
277fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
278fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
279fd4e5da5Sopenharmony_ci          %6 = OpTypeBool                 ; 1
280fd4e5da5Sopenharmony_ci         %10 = OpTypeInt 32 1
281fd4e5da5Sopenharmony_ci         %11 = OpTypePointer Private %10
282fd4e5da5Sopenharmony_ci         %12 = OpVariable %11 Private     ; 2
283fd4e5da5Sopenharmony_ci         %13 = OpConstant %10 1           ; 3
284fd4e5da5Sopenharmony_ci          %4 = OpFunction %2 None %3
285fd4e5da5Sopenharmony_ci          %5 = OpLabel
286fd4e5da5Sopenharmony_ci               OpReturn
287fd4e5da5Sopenharmony_ci               OpFunctionEnd
288fd4e5da5Sopenharmony_ci    )";
289fd4e5da5Sopenharmony_ci
290fd4e5da5Sopenharmony_ci  CheckEqual(kEnv, after, context.get());
291fd4e5da5Sopenharmony_ci
292fd4e5da5Sopenharmony_ci  ops = finder.GetAvailableOpportunities(context.get(), 0);
293fd4e5da5Sopenharmony_ci
294fd4e5da5Sopenharmony_ci  ASSERT_EQ(3, ops.size());
295fd4e5da5Sopenharmony_ci
296fd4e5da5Sopenharmony_ci  for (auto& op : ops) {
297fd4e5da5Sopenharmony_ci    ASSERT_TRUE(op->PreconditionHolds());
298fd4e5da5Sopenharmony_ci    op->TryToApply();
299fd4e5da5Sopenharmony_ci    CheckValid(kEnv, context.get());
300fd4e5da5Sopenharmony_ci  }
301fd4e5da5Sopenharmony_ci
302fd4e5da5Sopenharmony_ci  std::string after_2 = R"(
303fd4e5da5Sopenharmony_ci               OpCapability Shader
304fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
305fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
306fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %4 "main"
307fd4e5da5Sopenharmony_ci               OpExecutionMode %4 OriginUpperLeft
308fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
309fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
310fd4e5da5Sopenharmony_ci         %10 = OpTypeInt 32 1
311fd4e5da5Sopenharmony_ci         %11 = OpTypePointer Private %10   ; 1
312fd4e5da5Sopenharmony_ci          %4 = OpFunction %2 None %3
313fd4e5da5Sopenharmony_ci          %5 = OpLabel
314fd4e5da5Sopenharmony_ci               OpReturn
315fd4e5da5Sopenharmony_ci               OpFunctionEnd
316fd4e5da5Sopenharmony_ci    )";
317fd4e5da5Sopenharmony_ci
318fd4e5da5Sopenharmony_ci  CheckEqual(kEnv, after_2, context.get());
319fd4e5da5Sopenharmony_ci
320fd4e5da5Sopenharmony_ci  ops = finder.GetAvailableOpportunities(context.get(), 0);
321fd4e5da5Sopenharmony_ci
322fd4e5da5Sopenharmony_ci  ASSERT_EQ(1, ops.size());
323fd4e5da5Sopenharmony_ci
324fd4e5da5Sopenharmony_ci  for (auto& op : ops) {
325fd4e5da5Sopenharmony_ci    ASSERT_TRUE(op->PreconditionHolds());
326fd4e5da5Sopenharmony_ci    op->TryToApply();
327fd4e5da5Sopenharmony_ci    CheckValid(kEnv, context.get());
328fd4e5da5Sopenharmony_ci  }
329fd4e5da5Sopenharmony_ci
330fd4e5da5Sopenharmony_ci  std::string after_3 = R"(
331fd4e5da5Sopenharmony_ci               OpCapability Shader
332fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
333fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
334fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %4 "main"
335fd4e5da5Sopenharmony_ci               OpExecutionMode %4 OriginUpperLeft
336fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
337fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
338fd4e5da5Sopenharmony_ci         %10 = OpTypeInt 32 1          ; 1
339fd4e5da5Sopenharmony_ci          %4 = OpFunction %2 None %3
340fd4e5da5Sopenharmony_ci          %5 = OpLabel
341fd4e5da5Sopenharmony_ci               OpReturn
342fd4e5da5Sopenharmony_ci               OpFunctionEnd
343fd4e5da5Sopenharmony_ci    )";
344fd4e5da5Sopenharmony_ci
345fd4e5da5Sopenharmony_ci  CheckEqual(kEnv, after_3, context.get());
346fd4e5da5Sopenharmony_ci
347fd4e5da5Sopenharmony_ci  ops = finder.GetAvailableOpportunities(context.get(), 0);
348fd4e5da5Sopenharmony_ci
349fd4e5da5Sopenharmony_ci  ASSERT_EQ(1, ops.size());
350fd4e5da5Sopenharmony_ci
351fd4e5da5Sopenharmony_ci  for (auto& op : ops) {
352fd4e5da5Sopenharmony_ci    ASSERT_TRUE(op->PreconditionHolds());
353fd4e5da5Sopenharmony_ci    op->TryToApply();
354fd4e5da5Sopenharmony_ci    CheckValid(kEnv, context.get());
355fd4e5da5Sopenharmony_ci  }
356fd4e5da5Sopenharmony_ci
357fd4e5da5Sopenharmony_ci  std::string after_4 = R"(
358fd4e5da5Sopenharmony_ci               OpCapability Shader
359fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
360fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
361fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %4 "main"
362fd4e5da5Sopenharmony_ci               OpExecutionMode %4 OriginUpperLeft
363fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
364fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
365fd4e5da5Sopenharmony_ci          %4 = OpFunction %2 None %3
366fd4e5da5Sopenharmony_ci          %5 = OpLabel
367fd4e5da5Sopenharmony_ci               OpReturn
368fd4e5da5Sopenharmony_ci               OpFunctionEnd
369fd4e5da5Sopenharmony_ci    )";
370fd4e5da5Sopenharmony_ci
371fd4e5da5Sopenharmony_ci  CheckEqual(kEnv, after_4, context.get());
372fd4e5da5Sopenharmony_ci
373fd4e5da5Sopenharmony_ci  ops = finder.GetAvailableOpportunities(context.get(), 0);
374fd4e5da5Sopenharmony_ci
375fd4e5da5Sopenharmony_ci  ASSERT_EQ(0, ops.size());
376fd4e5da5Sopenharmony_ci}
377fd4e5da5Sopenharmony_ci
378fd4e5da5Sopenharmony_ciTEST(RemoveUnusedResourceVariableTest, RemoveUnusedResourceVariables) {
379fd4e5da5Sopenharmony_ci  std::string shader = R"(
380fd4e5da5Sopenharmony_ci               OpCapability Shader
381fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
382fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
383fd4e5da5Sopenharmony_ci               OpEntryPoint GLCompute %4 "main"
384fd4e5da5Sopenharmony_ci               OpExecutionMode %4 LocalSize 1 1 1
385fd4e5da5Sopenharmony_ci               OpMemberDecorate %9 0 Offset 0
386fd4e5da5Sopenharmony_ci               OpDecorate %9 Block
387fd4e5da5Sopenharmony_ci               OpDecorate %11 DescriptorSet 0
388fd4e5da5Sopenharmony_ci               OpDecorate %11 Binding 1
389fd4e5da5Sopenharmony_ci               OpMemberDecorate %16 0 Offset 0
390fd4e5da5Sopenharmony_ci               OpMemberDecorate %16 1 Offset 4
391fd4e5da5Sopenharmony_ci               OpDecorate %16 Block
392fd4e5da5Sopenharmony_ci               OpDecorate %18 DescriptorSet 0
393fd4e5da5Sopenharmony_ci               OpDecorate %18 Binding 0
394fd4e5da5Sopenharmony_ci               OpMemberDecorate %19 0 Offset 0
395fd4e5da5Sopenharmony_ci               OpDecorate %19 BufferBlock
396fd4e5da5Sopenharmony_ci               OpDecorate %21 DescriptorSet 1
397fd4e5da5Sopenharmony_ci               OpDecorate %21 Binding 0
398fd4e5da5Sopenharmony_ci               OpMemberDecorate %22 0 Offset 0
399fd4e5da5Sopenharmony_ci               OpDecorate %22 Block
400fd4e5da5Sopenharmony_ci               OpDecorate %29 DescriptorSet 1
401fd4e5da5Sopenharmony_ci               OpDecorate %29 Binding 1
402fd4e5da5Sopenharmony_ci               OpDecorate %32 DescriptorSet 1
403fd4e5da5Sopenharmony_ci               OpDecorate %32 Binding 2
404fd4e5da5Sopenharmony_ci               OpDecorate %32 NonReadable
405fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
406fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
407fd4e5da5Sopenharmony_ci          %6 = OpTypeInt 32 1
408fd4e5da5Sopenharmony_ci          %9 = OpTypeStruct %6
409fd4e5da5Sopenharmony_ci         %10 = OpTypePointer Uniform %9
410fd4e5da5Sopenharmony_ci         %11 = OpVariable %10 Uniform
411fd4e5da5Sopenharmony_ci         %13 = OpTypePointer Uniform %6
412fd4e5da5Sopenharmony_ci         %16 = OpTypeStruct %6 %6
413fd4e5da5Sopenharmony_ci         %17 = OpTypePointer Uniform %16
414fd4e5da5Sopenharmony_ci         %18 = OpVariable %17 Uniform
415fd4e5da5Sopenharmony_ci         %19 = OpTypeStruct %6
416fd4e5da5Sopenharmony_ci         %20 = OpTypePointer Uniform %19
417fd4e5da5Sopenharmony_ci         %21 = OpVariable %20 Uniform
418fd4e5da5Sopenharmony_ci         %22 = OpTypeStruct %6
419fd4e5da5Sopenharmony_ci         %23 = OpTypePointer PushConstant %22
420fd4e5da5Sopenharmony_ci         %24 = OpVariable %23 PushConstant
421fd4e5da5Sopenharmony_ci         %25 = OpTypeFloat 32
422fd4e5da5Sopenharmony_ci         %26 = OpTypeImage %25 2D 0 0 0 1 Unknown
423fd4e5da5Sopenharmony_ci         %27 = OpTypeSampledImage %26
424fd4e5da5Sopenharmony_ci         %28 = OpTypePointer UniformConstant %27
425fd4e5da5Sopenharmony_ci         %29 = OpVariable %28 UniformConstant
426fd4e5da5Sopenharmony_ci         %30 = OpTypeImage %25 2D 0 0 0 2 Unknown
427fd4e5da5Sopenharmony_ci         %31 = OpTypePointer UniformConstant %30
428fd4e5da5Sopenharmony_ci         %32 = OpVariable %31 UniformConstant
429fd4e5da5Sopenharmony_ci          %4 = OpFunction %2 None %3
430fd4e5da5Sopenharmony_ci          %5 = OpLabel
431fd4e5da5Sopenharmony_ci               OpReturn
432fd4e5da5Sopenharmony_ci               OpFunctionEnd
433fd4e5da5Sopenharmony_ci  )";
434fd4e5da5Sopenharmony_ci
435fd4e5da5Sopenharmony_ci  const auto env = SPV_ENV_UNIVERSAL_1_3;
436fd4e5da5Sopenharmony_ci  const auto consumer = nullptr;
437fd4e5da5Sopenharmony_ci  const auto context =
438fd4e5da5Sopenharmony_ci      BuildModule(env, consumer, shader, kReduceAssembleOption);
439fd4e5da5Sopenharmony_ci
440fd4e5da5Sopenharmony_ci  auto ops = RemoveUnusedInstructionReductionOpportunityFinder(true)
441fd4e5da5Sopenharmony_ci                 .GetAvailableOpportunities(context.get(), 0);
442fd4e5da5Sopenharmony_ci  ASSERT_EQ(7, ops.size());
443fd4e5da5Sopenharmony_ci
444fd4e5da5Sopenharmony_ci  for (auto& op : ops) {
445fd4e5da5Sopenharmony_ci    ASSERT_TRUE(op->PreconditionHolds());
446fd4e5da5Sopenharmony_ci    op->TryToApply();
447fd4e5da5Sopenharmony_ci  }
448fd4e5da5Sopenharmony_ci
449fd4e5da5Sopenharmony_ci  std::string expected_1 = R"(
450fd4e5da5Sopenharmony_ci               OpCapability Shader
451fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
452fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
453fd4e5da5Sopenharmony_ci               OpEntryPoint GLCompute %4 "main"
454fd4e5da5Sopenharmony_ci               OpExecutionMode %4 LocalSize 1 1 1
455fd4e5da5Sopenharmony_ci               OpMemberDecorate %9 0 Offset 0
456fd4e5da5Sopenharmony_ci               OpDecorate %9 Block
457fd4e5da5Sopenharmony_ci               OpMemberDecorate %16 0 Offset 0
458fd4e5da5Sopenharmony_ci               OpMemberDecorate %16 1 Offset 4
459fd4e5da5Sopenharmony_ci               OpDecorate %16 Block
460fd4e5da5Sopenharmony_ci               OpMemberDecorate %19 0 Offset 0
461fd4e5da5Sopenharmony_ci               OpDecorate %19 BufferBlock
462fd4e5da5Sopenharmony_ci               OpMemberDecorate %22 0 Offset 0
463fd4e5da5Sopenharmony_ci               OpDecorate %22 Block
464fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
465fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
466fd4e5da5Sopenharmony_ci          %6 = OpTypeInt 32 1
467fd4e5da5Sopenharmony_ci          %9 = OpTypeStruct %6
468fd4e5da5Sopenharmony_ci         %10 = OpTypePointer Uniform %9
469fd4e5da5Sopenharmony_ci         %16 = OpTypeStruct %6 %6
470fd4e5da5Sopenharmony_ci         %17 = OpTypePointer Uniform %16
471fd4e5da5Sopenharmony_ci         %19 = OpTypeStruct %6
472fd4e5da5Sopenharmony_ci         %20 = OpTypePointer Uniform %19
473fd4e5da5Sopenharmony_ci         %22 = OpTypeStruct %6
474fd4e5da5Sopenharmony_ci         %23 = OpTypePointer PushConstant %22
475fd4e5da5Sopenharmony_ci         %25 = OpTypeFloat 32
476fd4e5da5Sopenharmony_ci         %26 = OpTypeImage %25 2D 0 0 0 1 Unknown
477fd4e5da5Sopenharmony_ci         %27 = OpTypeSampledImage %26
478fd4e5da5Sopenharmony_ci         %28 = OpTypePointer UniformConstant %27
479fd4e5da5Sopenharmony_ci         %30 = OpTypeImage %25 2D 0 0 0 2 Unknown
480fd4e5da5Sopenharmony_ci         %31 = OpTypePointer UniformConstant %30
481fd4e5da5Sopenharmony_ci          %4 = OpFunction %2 None %3
482fd4e5da5Sopenharmony_ci          %5 = OpLabel
483fd4e5da5Sopenharmony_ci               OpReturn
484fd4e5da5Sopenharmony_ci               OpFunctionEnd
485fd4e5da5Sopenharmony_ci  )";
486fd4e5da5Sopenharmony_ci
487fd4e5da5Sopenharmony_ci  CheckEqual(env, expected_1, context.get());
488fd4e5da5Sopenharmony_ci
489fd4e5da5Sopenharmony_ci  ops = RemoveUnusedInstructionReductionOpportunityFinder(true)
490fd4e5da5Sopenharmony_ci            .GetAvailableOpportunities(context.get(), 0);
491fd4e5da5Sopenharmony_ci  ASSERT_EQ(6, ops.size());
492fd4e5da5Sopenharmony_ci
493fd4e5da5Sopenharmony_ci  for (auto& op : ops) {
494fd4e5da5Sopenharmony_ci    ASSERT_TRUE(op->PreconditionHolds());
495fd4e5da5Sopenharmony_ci    op->TryToApply();
496fd4e5da5Sopenharmony_ci  }
497fd4e5da5Sopenharmony_ci
498fd4e5da5Sopenharmony_ci  std::string expected_2 = R"(
499fd4e5da5Sopenharmony_ci               OpCapability Shader
500fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
501fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
502fd4e5da5Sopenharmony_ci               OpEntryPoint GLCompute %4 "main"
503fd4e5da5Sopenharmony_ci               OpExecutionMode %4 LocalSize 1 1 1
504fd4e5da5Sopenharmony_ci               OpMemberDecorate %9 0 Offset 0
505fd4e5da5Sopenharmony_ci               OpDecorate %9 Block
506fd4e5da5Sopenharmony_ci               OpMemberDecorate %16 0 Offset 0
507fd4e5da5Sopenharmony_ci               OpMemberDecorate %16 1 Offset 4
508fd4e5da5Sopenharmony_ci               OpDecorate %16 Block
509fd4e5da5Sopenharmony_ci               OpMemberDecorate %19 0 Offset 0
510fd4e5da5Sopenharmony_ci               OpDecorate %19 BufferBlock
511fd4e5da5Sopenharmony_ci               OpMemberDecorate %22 0 Offset 0
512fd4e5da5Sopenharmony_ci               OpDecorate %22 Block
513fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
514fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
515fd4e5da5Sopenharmony_ci          %6 = OpTypeInt 32 1
516fd4e5da5Sopenharmony_ci          %9 = OpTypeStruct %6
517fd4e5da5Sopenharmony_ci         %16 = OpTypeStruct %6 %6
518fd4e5da5Sopenharmony_ci         %19 = OpTypeStruct %6
519fd4e5da5Sopenharmony_ci         %22 = OpTypeStruct %6
520fd4e5da5Sopenharmony_ci         %25 = OpTypeFloat 32
521fd4e5da5Sopenharmony_ci         %26 = OpTypeImage %25 2D 0 0 0 1 Unknown
522fd4e5da5Sopenharmony_ci         %27 = OpTypeSampledImage %26
523fd4e5da5Sopenharmony_ci         %30 = OpTypeImage %25 2D 0 0 0 2 Unknown
524fd4e5da5Sopenharmony_ci          %4 = OpFunction %2 None %3
525fd4e5da5Sopenharmony_ci          %5 = OpLabel
526fd4e5da5Sopenharmony_ci               OpReturn
527fd4e5da5Sopenharmony_ci               OpFunctionEnd
528fd4e5da5Sopenharmony_ci  )";
529fd4e5da5Sopenharmony_ci
530fd4e5da5Sopenharmony_ci  CheckEqual(env, expected_2, context.get());
531fd4e5da5Sopenharmony_ci
532fd4e5da5Sopenharmony_ci  ops = RemoveUnusedInstructionReductionOpportunityFinder(true)
533fd4e5da5Sopenharmony_ci            .GetAvailableOpportunities(context.get(), 0);
534fd4e5da5Sopenharmony_ci  ASSERT_EQ(6, ops.size());
535fd4e5da5Sopenharmony_ci
536fd4e5da5Sopenharmony_ci  for (auto& op : ops) {
537fd4e5da5Sopenharmony_ci    ASSERT_TRUE(op->PreconditionHolds());
538fd4e5da5Sopenharmony_ci    op->TryToApply();
539fd4e5da5Sopenharmony_ci  }
540fd4e5da5Sopenharmony_ci
541fd4e5da5Sopenharmony_ci  std::string expected_3 = R"(
542fd4e5da5Sopenharmony_ci               OpCapability Shader
543fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
544fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
545fd4e5da5Sopenharmony_ci               OpEntryPoint GLCompute %4 "main"
546fd4e5da5Sopenharmony_ci               OpExecutionMode %4 LocalSize 1 1 1
547fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
548fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
549fd4e5da5Sopenharmony_ci          %6 = OpTypeInt 32 1
550fd4e5da5Sopenharmony_ci         %25 = OpTypeFloat 32
551fd4e5da5Sopenharmony_ci         %26 = OpTypeImage %25 2D 0 0 0 1 Unknown
552fd4e5da5Sopenharmony_ci          %4 = OpFunction %2 None %3
553fd4e5da5Sopenharmony_ci          %5 = OpLabel
554fd4e5da5Sopenharmony_ci               OpReturn
555fd4e5da5Sopenharmony_ci               OpFunctionEnd
556fd4e5da5Sopenharmony_ci  )";
557fd4e5da5Sopenharmony_ci
558fd4e5da5Sopenharmony_ci  CheckEqual(env, expected_3, context.get());
559fd4e5da5Sopenharmony_ci}
560fd4e5da5Sopenharmony_ci
561fd4e5da5Sopenharmony_ci}  // namespace
562fd4e5da5Sopenharmony_ci}  // namespace reduce
563fd4e5da5Sopenharmony_ci}  // namespace spvtools
564