1fd4e5da5Sopenharmony_ci// Copyright (c) 2021 Alastair F. Donaldson
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/structured_construct_to_block_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(StructuredConstructToBlockReductionPassTest, SimpleTest) {
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 320
33fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
34fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
35fd4e5da5Sopenharmony_ci          %6 = OpTypeInt 32 1
36fd4e5da5Sopenharmony_ci          %7 = OpTypePointer Function %6
37fd4e5da5Sopenharmony_ci          %9 = OpConstant %6 0
38fd4e5da5Sopenharmony_ci         %10 = OpTypeBool
39fd4e5da5Sopenharmony_ci         %11 = OpConstantTrue %10
40fd4e5da5Sopenharmony_ci         %19 = OpConstant %6 3
41fd4e5da5Sopenharmony_ci         %29 = OpConstant %6 1
42fd4e5da5Sopenharmony_ci         %31 = OpConstant %6 2
43fd4e5da5Sopenharmony_ci          %4 = OpFunction %2 None %3
44fd4e5da5Sopenharmony_ci          %5 = OpLabel
45fd4e5da5Sopenharmony_ci          %8 = OpVariable %7 Function
46fd4e5da5Sopenharmony_ci               OpStore %8 %9
47fd4e5da5Sopenharmony_ci               OpSelectionMerge %13 None
48fd4e5da5Sopenharmony_ci               OpBranchConditional %11 %12 %13
49fd4e5da5Sopenharmony_ci         %12 = OpLabel
50fd4e5da5Sopenharmony_ci               OpBranch %13
51fd4e5da5Sopenharmony_ci         %13 = OpLabel
52fd4e5da5Sopenharmony_ci               OpBranch %14
53fd4e5da5Sopenharmony_ci         %14 = OpLabel
54fd4e5da5Sopenharmony_ci               OpLoopMerge %16 %17 None
55fd4e5da5Sopenharmony_ci               OpBranch %15
56fd4e5da5Sopenharmony_ci         %15 = OpLabel
57fd4e5da5Sopenharmony_ci         %18 = OpLoad %6 %8
58fd4e5da5Sopenharmony_ci         %20 = OpSGreaterThan %10 %18 %19
59fd4e5da5Sopenharmony_ci               OpSelectionMerge %22 None
60fd4e5da5Sopenharmony_ci               OpBranchConditional %20 %21 %22
61fd4e5da5Sopenharmony_ci         %21 = OpLabel
62fd4e5da5Sopenharmony_ci               OpBranch %16
63fd4e5da5Sopenharmony_ci         %22 = OpLabel
64fd4e5da5Sopenharmony_ci               OpBranch %17
65fd4e5da5Sopenharmony_ci         %17 = OpLabel
66fd4e5da5Sopenharmony_ci               OpBranch %14
67fd4e5da5Sopenharmony_ci         %16 = OpLabel
68fd4e5da5Sopenharmony_ci         %24 = OpLoad %6 %8
69fd4e5da5Sopenharmony_ci               OpSelectionMerge %28 None
70fd4e5da5Sopenharmony_ci               OpSwitch %24 %27 1 %25 2 %26
71fd4e5da5Sopenharmony_ci         %27 = OpLabel
72fd4e5da5Sopenharmony_ci               OpStore %8 %19
73fd4e5da5Sopenharmony_ci               OpBranch %28
74fd4e5da5Sopenharmony_ci         %25 = OpLabel
75fd4e5da5Sopenharmony_ci               OpStore %8 %29
76fd4e5da5Sopenharmony_ci               OpBranch %28
77fd4e5da5Sopenharmony_ci         %26 = OpLabel
78fd4e5da5Sopenharmony_ci               OpStore %8 %31
79fd4e5da5Sopenharmony_ci               OpBranch %28
80fd4e5da5Sopenharmony_ci         %28 = OpLabel
81fd4e5da5Sopenharmony_ci               OpReturn
82fd4e5da5Sopenharmony_ci               OpFunctionEnd
83fd4e5da5Sopenharmony_ci  )";
84fd4e5da5Sopenharmony_ci
85fd4e5da5Sopenharmony_ci  const auto env = SPV_ENV_UNIVERSAL_1_3;
86fd4e5da5Sopenharmony_ci  const auto context = BuildModule(env, nullptr, shader, kReduceAssembleOption);
87fd4e5da5Sopenharmony_ci  const auto ops = StructuredConstructToBlockReductionOpportunityFinder()
88fd4e5da5Sopenharmony_ci                       .GetAvailableOpportunities(context.get(), 0);
89fd4e5da5Sopenharmony_ci  ASSERT_EQ(3, ops.size());
90fd4e5da5Sopenharmony_ci
91fd4e5da5Sopenharmony_ci  ASSERT_TRUE(ops[0]->PreconditionHolds());
92fd4e5da5Sopenharmony_ci  ops[0]->TryToApply();
93fd4e5da5Sopenharmony_ci  CheckValid(env, context.get());
94fd4e5da5Sopenharmony_ci
95fd4e5da5Sopenharmony_ci  ASSERT_TRUE(ops[1]->PreconditionHolds());
96fd4e5da5Sopenharmony_ci  ops[1]->TryToApply();
97fd4e5da5Sopenharmony_ci  CheckValid(env, context.get());
98fd4e5da5Sopenharmony_ci
99fd4e5da5Sopenharmony_ci  ASSERT_TRUE(ops[2]->PreconditionHolds());
100fd4e5da5Sopenharmony_ci  ops[2]->TryToApply();
101fd4e5da5Sopenharmony_ci  CheckValid(env, context.get());
102fd4e5da5Sopenharmony_ci
103fd4e5da5Sopenharmony_ci  std::string expected = R"(
104fd4e5da5Sopenharmony_ci               OpCapability Shader
105fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
106fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
107fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %4 "main"
108fd4e5da5Sopenharmony_ci               OpExecutionMode %4 OriginUpperLeft
109fd4e5da5Sopenharmony_ci               OpSource ESSL 320
110fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
111fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
112fd4e5da5Sopenharmony_ci          %6 = OpTypeInt 32 1
113fd4e5da5Sopenharmony_ci          %7 = OpTypePointer Function %6
114fd4e5da5Sopenharmony_ci          %9 = OpConstant %6 0
115fd4e5da5Sopenharmony_ci         %10 = OpTypeBool
116fd4e5da5Sopenharmony_ci         %11 = OpConstantTrue %10
117fd4e5da5Sopenharmony_ci         %19 = OpConstant %6 3
118fd4e5da5Sopenharmony_ci         %29 = OpConstant %6 1
119fd4e5da5Sopenharmony_ci         %31 = OpConstant %6 2
120fd4e5da5Sopenharmony_ci          %4 = OpFunction %2 None %3
121fd4e5da5Sopenharmony_ci          %5 = OpLabel
122fd4e5da5Sopenharmony_ci          %8 = OpVariable %7 Function
123fd4e5da5Sopenharmony_ci               OpStore %8 %9
124fd4e5da5Sopenharmony_ci               OpBranch %13
125fd4e5da5Sopenharmony_ci         %13 = OpLabel
126fd4e5da5Sopenharmony_ci               OpBranch %14
127fd4e5da5Sopenharmony_ci         %14 = OpLabel
128fd4e5da5Sopenharmony_ci               OpBranch %16
129fd4e5da5Sopenharmony_ci         %16 = OpLabel
130fd4e5da5Sopenharmony_ci         %24 = OpLoad %6 %8
131fd4e5da5Sopenharmony_ci               OpBranch %28
132fd4e5da5Sopenharmony_ci         %28 = OpLabel
133fd4e5da5Sopenharmony_ci               OpReturn
134fd4e5da5Sopenharmony_ci               OpFunctionEnd
135fd4e5da5Sopenharmony_ci  )";
136fd4e5da5Sopenharmony_ci  CheckEqual(env, expected, context.get());
137fd4e5da5Sopenharmony_ci}
138fd4e5da5Sopenharmony_ci
139fd4e5da5Sopenharmony_ciTEST(StructuredConstructToBlockReductionPassTest, CannotBeRemovedDueToUses) {
140fd4e5da5Sopenharmony_ci  std::string shader = R"(
141fd4e5da5Sopenharmony_ci               OpCapability Shader
142fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
143fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
144fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %4 "main"
145fd4e5da5Sopenharmony_ci               OpExecutionMode %4 OriginUpperLeft
146fd4e5da5Sopenharmony_ci               OpSource ESSL 320
147fd4e5da5Sopenharmony_ci               OpName %100 "temp"
148fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
149fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
150fd4e5da5Sopenharmony_ci          %6 = OpTypeInt 32 1
151fd4e5da5Sopenharmony_ci          %7 = OpTypePointer Function %6
152fd4e5da5Sopenharmony_ci          %9 = OpConstant %6 0
153fd4e5da5Sopenharmony_ci         %10 = OpTypeBool
154fd4e5da5Sopenharmony_ci         %11 = OpConstantTrue %10
155fd4e5da5Sopenharmony_ci         %19 = OpConstant %6 3
156fd4e5da5Sopenharmony_ci         %29 = OpConstant %6 1
157fd4e5da5Sopenharmony_ci         %31 = OpConstant %6 2
158fd4e5da5Sopenharmony_ci          %4 = OpFunction %2 None %3
159fd4e5da5Sopenharmony_ci          %5 = OpLabel
160fd4e5da5Sopenharmony_ci          %8 = OpVariable %7 Function
161fd4e5da5Sopenharmony_ci               OpStore %8 %9
162fd4e5da5Sopenharmony_ci               OpSelectionMerge %13 None
163fd4e5da5Sopenharmony_ci               OpBranchConditional %11 %12 %13
164fd4e5da5Sopenharmony_ci         %12 = OpLabel
165fd4e5da5Sopenharmony_ci        %100 = OpCopyObject %10 %11
166fd4e5da5Sopenharmony_ci               OpBranch %13
167fd4e5da5Sopenharmony_ci         %13 = OpLabel
168fd4e5da5Sopenharmony_ci               OpBranch %14
169fd4e5da5Sopenharmony_ci         %14 = OpLabel
170fd4e5da5Sopenharmony_ci               OpLoopMerge %16 %17 None
171fd4e5da5Sopenharmony_ci               OpBranch %15
172fd4e5da5Sopenharmony_ci         %15 = OpLabel
173fd4e5da5Sopenharmony_ci         %18 = OpLoad %6 %8
174fd4e5da5Sopenharmony_ci         %20 = OpSGreaterThan %10 %18 %19
175fd4e5da5Sopenharmony_ci               OpSelectionMerge %22 None
176fd4e5da5Sopenharmony_ci               OpBranchConditional %20 %21 %22
177fd4e5da5Sopenharmony_ci         %21 = OpLabel
178fd4e5da5Sopenharmony_ci               OpBranch %16
179fd4e5da5Sopenharmony_ci         %22 = OpLabel
180fd4e5da5Sopenharmony_ci               OpBranch %17
181fd4e5da5Sopenharmony_ci         %17 = OpLabel
182fd4e5da5Sopenharmony_ci               OpBranch %14
183fd4e5da5Sopenharmony_ci         %16 = OpLabel
184fd4e5da5Sopenharmony_ci        %101 = OpCopyObject %6 %18
185fd4e5da5Sopenharmony_ci         %24 = OpLoad %6 %8
186fd4e5da5Sopenharmony_ci               OpSelectionMerge %28 None
187fd4e5da5Sopenharmony_ci               OpSwitch %24 %27 1 %25 2 %26
188fd4e5da5Sopenharmony_ci         %27 = OpLabel
189fd4e5da5Sopenharmony_ci               OpStore %8 %19
190fd4e5da5Sopenharmony_ci        %102 = OpCopyObject %10 %11
191fd4e5da5Sopenharmony_ci               OpBranch %28
192fd4e5da5Sopenharmony_ci         %25 = OpLabel
193fd4e5da5Sopenharmony_ci               OpStore %8 %29
194fd4e5da5Sopenharmony_ci               OpBranch %28
195fd4e5da5Sopenharmony_ci         %26 = OpLabel
196fd4e5da5Sopenharmony_ci               OpStore %8 %31
197fd4e5da5Sopenharmony_ci               OpBranch %28
198fd4e5da5Sopenharmony_ci         %28 = OpLabel
199fd4e5da5Sopenharmony_ci        %103 = OpPhi %10 %102 %27 %11 %25 %11 %26
200fd4e5da5Sopenharmony_ci               OpReturn
201fd4e5da5Sopenharmony_ci               OpFunctionEnd
202fd4e5da5Sopenharmony_ci  )";
203fd4e5da5Sopenharmony_ci
204fd4e5da5Sopenharmony_ci  const auto env = SPV_ENV_UNIVERSAL_1_3;
205fd4e5da5Sopenharmony_ci  const auto context = BuildModule(env, nullptr, shader, kReduceAssembleOption);
206fd4e5da5Sopenharmony_ci  const auto ops = StructuredConstructToBlockReductionOpportunityFinder()
207fd4e5da5Sopenharmony_ci                       .GetAvailableOpportunities(context.get(), 0);
208fd4e5da5Sopenharmony_ci  ASSERT_TRUE(ops.empty());
209fd4e5da5Sopenharmony_ci}
210fd4e5da5Sopenharmony_ci
211fd4e5da5Sopenharmony_ciTEST(StructuredConstructToBlockReductionPassTest,
212fd4e5da5Sopenharmony_ci     CannotBeRemovedDueToOpPhiAtMerge) {
213fd4e5da5Sopenharmony_ci  std::string shader = R"(
214fd4e5da5Sopenharmony_ci               OpCapability Shader
215fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
216fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
217fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %4 "main"
218fd4e5da5Sopenharmony_ci               OpExecutionMode %4 OriginUpperLeft
219fd4e5da5Sopenharmony_ci               OpSource ESSL 320
220fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
221fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
222fd4e5da5Sopenharmony_ci         %10 = OpTypeBool
223fd4e5da5Sopenharmony_ci         %11 = OpConstantTrue %10
224fd4e5da5Sopenharmony_ci          %4 = OpFunction %2 None %3
225fd4e5da5Sopenharmony_ci          %5 = OpLabel
226fd4e5da5Sopenharmony_ci               OpSelectionMerge %13 None
227fd4e5da5Sopenharmony_ci               OpBranchConditional %11 %12 %13
228fd4e5da5Sopenharmony_ci         %12 = OpLabel
229fd4e5da5Sopenharmony_ci               OpBranch %13
230fd4e5da5Sopenharmony_ci         %13 = OpLabel
231fd4e5da5Sopenharmony_ci        %101 = OpPhi %10 %11 %5 %11 %12
232fd4e5da5Sopenharmony_ci               OpReturn
233fd4e5da5Sopenharmony_ci               OpFunctionEnd
234fd4e5da5Sopenharmony_ci  )";
235fd4e5da5Sopenharmony_ci
236fd4e5da5Sopenharmony_ci  const auto env = SPV_ENV_UNIVERSAL_1_3;
237fd4e5da5Sopenharmony_ci  const auto context = BuildModule(env, nullptr, shader, kReduceAssembleOption);
238fd4e5da5Sopenharmony_ci  const auto ops = StructuredConstructToBlockReductionOpportunityFinder()
239fd4e5da5Sopenharmony_ci                       .GetAvailableOpportunities(context.get(), 0);
240fd4e5da5Sopenharmony_ci  ASSERT_TRUE(ops.empty());
241fd4e5da5Sopenharmony_ci}
242fd4e5da5Sopenharmony_ci
243fd4e5da5Sopenharmony_ci}  // namespace
244fd4e5da5Sopenharmony_ci}  // namespace reduce
245fd4e5da5Sopenharmony_ci}  // namespace spvtools
246