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