1 // Copyright (c) 2017 Google Inc.
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 <memory>
16 #include <string>
17 #include <vector>
18
19 #include "gmock/gmock.h"
20 #include "source/opt/dominator_analysis.h"
21 #include "source/opt/pass.h"
22 #include "test/opt/assembly_builder.h"
23 #include "test/opt/function_utils.h"
24 #include "test/opt/pass_fixture.h"
25 #include "test/opt/pass_utils.h"
26
27 namespace spvtools {
28 namespace opt {
29 namespace {
30
31 using ::testing::UnorderedElementsAre;
32 using PassClassTest = PassTest<::testing::Test>;
33
34 /*
35 Generated from the following GLSL
36 #version 440 core
37 layout(location = 0) out vec4 v;
38 layout(location = 1) in vec4 in_val;
39 void main() {
40 for (int i = 0; i < in_val.x; ++i) {
41 for (int j = 0; j < in_val.y; j++) {
42 }
43 }
44 for (int i = 0; i < in_val.x; ++i) {
45 for (int j = 0; j < in_val.y; j++) {
46 }
47 if (in_val.z == in_val.w) {
48 break;
49 }
50 }
51 int i = 0;
52 while (i < in_val.x) {
53 ++i;
54 for (int j = 0; j < 1; j++) {
55 for (int k = 0; k < 1; k++) {
56 }
57 }
58 }
59 i = 0;
60 while (i < in_val.x) {
61 ++i;
62 if (in_val.z == in_val.w) {
63 continue;
64 }
65 for (int j = 0; j < 1; j++) {
66 for (int k = 0; k < 1; k++) {
67 }
68 if (in_val.z == in_val.w) {
69 break;
70 }
71 }
72 }
73 v = vec4(1,1,1,1);
74 }
75 */
TEST_F(PassClassTest,BasicVisitFromEntryPoint)76 TEST_F(PassClassTest, BasicVisitFromEntryPoint) {
77 const std::string text = R"(
78 OpCapability Shader
79 %1 = OpExtInstImport "GLSL.std.450"
80 OpMemoryModel Logical GLSL450
81 OpEntryPoint Fragment %4 "main" %20 %163
82 OpExecutionMode %4 OriginUpperLeft
83 OpSource GLSL 440
84 OpName %4 "main"
85 OpName %8 "i"
86 OpName %20 "in_val"
87 OpName %28 "j"
88 OpName %45 "i"
89 OpName %56 "j"
90 OpName %81 "i"
91 OpName %94 "j"
92 OpName %102 "k"
93 OpName %134 "j"
94 OpName %142 "k"
95 OpName %163 "v"
96 OpDecorate %20 Location 1
97 OpDecorate %163 Location 0
98 %2 = OpTypeVoid
99 %3 = OpTypeFunction %2
100 %6 = OpTypeInt 32 1
101 %7 = OpTypePointer Function %6
102 %9 = OpConstant %6 0
103 %16 = OpTypeFloat 32
104 %18 = OpTypeVector %16 4
105 %19 = OpTypePointer Input %18
106 %20 = OpVariable %19 Input
107 %21 = OpTypeInt 32 0
108 %22 = OpConstant %21 0
109 %23 = OpTypePointer Input %16
110 %26 = OpTypeBool
111 %36 = OpConstant %21 1
112 %41 = OpConstant %6 1
113 %69 = OpConstant %21 2
114 %72 = OpConstant %21 3
115 %162 = OpTypePointer Output %18
116 %163 = OpVariable %162 Output
117 %164 = OpConstant %16 1
118 %165 = OpConstantComposite %18 %164 %164 %164 %164
119 %4 = OpFunction %2 None %3
120 %5 = OpLabel
121 %8 = OpVariable %7 Function
122 %28 = OpVariable %7 Function
123 %45 = OpVariable %7 Function
124 %56 = OpVariable %7 Function
125 %81 = OpVariable %7 Function
126 %94 = OpVariable %7 Function
127 %102 = OpVariable %7 Function
128 %134 = OpVariable %7 Function
129 %142 = OpVariable %7 Function
130 OpStore %8 %9
131 OpBranch %10
132 %10 = OpLabel
133 OpLoopMerge %12 %13 None
134 OpBranch %14
135 %14 = OpLabel
136 %15 = OpLoad %6 %8
137 %17 = OpConvertSToF %16 %15
138 %24 = OpAccessChain %23 %20 %22
139 %25 = OpLoad %16 %24
140 %27 = OpFOrdLessThan %26 %17 %25
141 OpBranchConditional %27 %11 %12
142 %11 = OpLabel
143 OpStore %28 %9
144 OpBranch %29
145 %29 = OpLabel
146 OpLoopMerge %31 %32 None
147 OpBranch %33
148 %33 = OpLabel
149 %34 = OpLoad %6 %28
150 %35 = OpConvertSToF %16 %34
151 %37 = OpAccessChain %23 %20 %36
152 %38 = OpLoad %16 %37
153 %39 = OpFOrdLessThan %26 %35 %38
154 OpBranchConditional %39 %30 %31
155 %30 = OpLabel
156 OpBranch %32
157 %32 = OpLabel
158 %40 = OpLoad %6 %28
159 %42 = OpIAdd %6 %40 %41
160 OpStore %28 %42
161 OpBranch %29
162 %31 = OpLabel
163 OpBranch %13
164 %13 = OpLabel
165 %43 = OpLoad %6 %8
166 %44 = OpIAdd %6 %43 %41
167 OpStore %8 %44
168 OpBranch %10
169 %12 = OpLabel
170 OpStore %45 %9
171 OpBranch %46
172 %46 = OpLabel
173 OpLoopMerge %48 %49 None
174 OpBranch %50
175 %50 = OpLabel
176 %51 = OpLoad %6 %45
177 %52 = OpConvertSToF %16 %51
178 %53 = OpAccessChain %23 %20 %22
179 %54 = OpLoad %16 %53
180 %55 = OpFOrdLessThan %26 %52 %54
181 OpBranchConditional %55 %47 %48
182 %47 = OpLabel
183 OpStore %56 %9
184 OpBranch %57
185 %57 = OpLabel
186 OpLoopMerge %59 %60 None
187 OpBranch %61
188 %61 = OpLabel
189 %62 = OpLoad %6 %56
190 %63 = OpConvertSToF %16 %62
191 %64 = OpAccessChain %23 %20 %36
192 %65 = OpLoad %16 %64
193 %66 = OpFOrdLessThan %26 %63 %65
194 OpBranchConditional %66 %58 %59
195 %58 = OpLabel
196 OpBranch %60
197 %60 = OpLabel
198 %67 = OpLoad %6 %56
199 %68 = OpIAdd %6 %67 %41
200 OpStore %56 %68
201 OpBranch %57
202 %59 = OpLabel
203 %70 = OpAccessChain %23 %20 %69
204 %71 = OpLoad %16 %70
205 %73 = OpAccessChain %23 %20 %72
206 %74 = OpLoad %16 %73
207 %75 = OpFOrdEqual %26 %71 %74
208 OpSelectionMerge %77 None
209 OpBranchConditional %75 %76 %77
210 %76 = OpLabel
211 OpBranch %48
212 %77 = OpLabel
213 OpBranch %49
214 %49 = OpLabel
215 %79 = OpLoad %6 %45
216 %80 = OpIAdd %6 %79 %41
217 OpStore %45 %80
218 OpBranch %46
219 %48 = OpLabel
220 OpStore %81 %9
221 OpBranch %82
222 %82 = OpLabel
223 OpLoopMerge %84 %85 None
224 OpBranch %86
225 %86 = OpLabel
226 %87 = OpLoad %6 %81
227 %88 = OpConvertSToF %16 %87
228 %89 = OpAccessChain %23 %20 %22
229 %90 = OpLoad %16 %89
230 %91 = OpFOrdLessThan %26 %88 %90
231 OpBranchConditional %91 %83 %84
232 %83 = OpLabel
233 %92 = OpLoad %6 %81
234 %93 = OpIAdd %6 %92 %41
235 OpStore %81 %93
236 OpStore %94 %9
237 OpBranch %95
238 %95 = OpLabel
239 OpLoopMerge %97 %98 None
240 OpBranch %99
241 %99 = OpLabel
242 %100 = OpLoad %6 %94
243 %101 = OpSLessThan %26 %100 %41
244 OpBranchConditional %101 %96 %97
245 %96 = OpLabel
246 OpStore %102 %9
247 OpBranch %103
248 %103 = OpLabel
249 OpLoopMerge %105 %106 None
250 OpBranch %107
251 %107 = OpLabel
252 %108 = OpLoad %6 %102
253 %109 = OpSLessThan %26 %108 %41
254 OpBranchConditional %109 %104 %105
255 %104 = OpLabel
256 OpBranch %106
257 %106 = OpLabel
258 %110 = OpLoad %6 %102
259 %111 = OpIAdd %6 %110 %41
260 OpStore %102 %111
261 OpBranch %103
262 %105 = OpLabel
263 OpBranch %98
264 %98 = OpLabel
265 %112 = OpLoad %6 %94
266 %113 = OpIAdd %6 %112 %41
267 OpStore %94 %113
268 OpBranch %95
269 %97 = OpLabel
270 OpBranch %85
271 %85 = OpLabel
272 OpBranch %82
273 %84 = OpLabel
274 OpStore %81 %9
275 OpBranch %114
276 %114 = OpLabel
277 OpLoopMerge %116 %117 None
278 OpBranch %118
279 %118 = OpLabel
280 %119 = OpLoad %6 %81
281 %120 = OpConvertSToF %16 %119
282 %121 = OpAccessChain %23 %20 %22
283 %122 = OpLoad %16 %121
284 %123 = OpFOrdLessThan %26 %120 %122
285 OpBranchConditional %123 %115 %116
286 %115 = OpLabel
287 %124 = OpLoad %6 %81
288 %125 = OpIAdd %6 %124 %41
289 OpStore %81 %125
290 %126 = OpAccessChain %23 %20 %69
291 %127 = OpLoad %16 %126
292 %128 = OpAccessChain %23 %20 %72
293 %129 = OpLoad %16 %128
294 %130 = OpFOrdEqual %26 %127 %129
295 OpSelectionMerge %132 None
296 OpBranchConditional %130 %131 %132
297 %131 = OpLabel
298 OpBranch %117
299 %132 = OpLabel
300 OpStore %134 %9
301 OpBranch %135
302 %135 = OpLabel
303 OpLoopMerge %137 %138 None
304 OpBranch %139
305 %139 = OpLabel
306 %140 = OpLoad %6 %134
307 %141 = OpSLessThan %26 %140 %41
308 OpBranchConditional %141 %136 %137
309 %136 = OpLabel
310 OpStore %142 %9
311 OpBranch %143
312 %143 = OpLabel
313 OpLoopMerge %145 %146 None
314 OpBranch %147
315 %147 = OpLabel
316 %148 = OpLoad %6 %142
317 %149 = OpSLessThan %26 %148 %41
318 OpBranchConditional %149 %144 %145
319 %144 = OpLabel
320 OpBranch %146
321 %146 = OpLabel
322 %150 = OpLoad %6 %142
323 %151 = OpIAdd %6 %150 %41
324 OpStore %142 %151
325 OpBranch %143
326 %145 = OpLabel
327 %152 = OpAccessChain %23 %20 %69
328 %153 = OpLoad %16 %152
329 %154 = OpAccessChain %23 %20 %72
330 %155 = OpLoad %16 %154
331 %156 = OpFOrdEqual %26 %153 %155
332 OpSelectionMerge %158 None
333 OpBranchConditional %156 %157 %158
334 %157 = OpLabel
335 OpBranch %137
336 %158 = OpLabel
337 OpBranch %138
338 %138 = OpLabel
339 %160 = OpLoad %6 %134
340 %161 = OpIAdd %6 %160 %41
341 OpStore %134 %161
342 OpBranch %135
343 %137 = OpLabel
344 OpBranch %117
345 %117 = OpLabel
346 OpBranch %114
347 %116 = OpLabel
348 OpStore %163 %165
349 OpReturn
350 OpFunctionEnd
351 )";
352 // clang-format on
353 std::unique_ptr<IRContext> context =
354 BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text,
355 SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
356 Module* module = context->module();
357 EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n"
358 << text << std::endl;
359
360 const Function* f = spvtest::GetFunction(module, 4);
361 DominatorAnalysis* analysis = context->GetDominatorAnalysis(f);
362
363 EXPECT_TRUE(analysis->Dominates(5, 10));
364 EXPECT_TRUE(analysis->Dominates(5, 46));
365 EXPECT_TRUE(analysis->Dominates(5, 82));
366 EXPECT_TRUE(analysis->Dominates(5, 114));
367 EXPECT_TRUE(analysis->Dominates(5, 116));
368
369 EXPECT_TRUE(analysis->Dominates(10, 14));
370 EXPECT_TRUE(analysis->Dominates(10, 11));
371 EXPECT_TRUE(analysis->Dominates(10, 29));
372 EXPECT_TRUE(analysis->Dominates(10, 33));
373 EXPECT_TRUE(analysis->Dominates(10, 30));
374 EXPECT_TRUE(analysis->Dominates(10, 32));
375 EXPECT_TRUE(analysis->Dominates(10, 31));
376 EXPECT_TRUE(analysis->Dominates(10, 13));
377 EXPECT_TRUE(analysis->Dominates(10, 12));
378
379 EXPECT_TRUE(analysis->Dominates(12, 46));
380
381 EXPECT_TRUE(analysis->Dominates(46, 50));
382 EXPECT_TRUE(analysis->Dominates(46, 47));
383 EXPECT_TRUE(analysis->Dominates(46, 57));
384 EXPECT_TRUE(analysis->Dominates(46, 61));
385 EXPECT_TRUE(analysis->Dominates(46, 58));
386 EXPECT_TRUE(analysis->Dominates(46, 60));
387 EXPECT_TRUE(analysis->Dominates(46, 59));
388 EXPECT_TRUE(analysis->Dominates(46, 77));
389 EXPECT_TRUE(analysis->Dominates(46, 49));
390 EXPECT_TRUE(analysis->Dominates(46, 76));
391 EXPECT_TRUE(analysis->Dominates(46, 48));
392
393 EXPECT_TRUE(analysis->Dominates(48, 82));
394
395 EXPECT_TRUE(analysis->Dominates(82, 86));
396 EXPECT_TRUE(analysis->Dominates(82, 83));
397 EXPECT_TRUE(analysis->Dominates(82, 95));
398 EXPECT_TRUE(analysis->Dominates(82, 99));
399 EXPECT_TRUE(analysis->Dominates(82, 96));
400 EXPECT_TRUE(analysis->Dominates(82, 103));
401 EXPECT_TRUE(analysis->Dominates(82, 107));
402 EXPECT_TRUE(analysis->Dominates(82, 104));
403 EXPECT_TRUE(analysis->Dominates(82, 106));
404 EXPECT_TRUE(analysis->Dominates(82, 105));
405 EXPECT_TRUE(analysis->Dominates(82, 98));
406 EXPECT_TRUE(analysis->Dominates(82, 97));
407 EXPECT_TRUE(analysis->Dominates(82, 85));
408 EXPECT_TRUE(analysis->Dominates(82, 84));
409
410 EXPECT_TRUE(analysis->Dominates(84, 114));
411
412 EXPECT_TRUE(analysis->Dominates(114, 118));
413 EXPECT_TRUE(analysis->Dominates(114, 116));
414 EXPECT_TRUE(analysis->Dominates(114, 115));
415 EXPECT_TRUE(analysis->Dominates(114, 132));
416 EXPECT_TRUE(analysis->Dominates(114, 135));
417 EXPECT_TRUE(analysis->Dominates(114, 139));
418 EXPECT_TRUE(analysis->Dominates(114, 136));
419 EXPECT_TRUE(analysis->Dominates(114, 143));
420 EXPECT_TRUE(analysis->Dominates(114, 147));
421 EXPECT_TRUE(analysis->Dominates(114, 144));
422 EXPECT_TRUE(analysis->Dominates(114, 146));
423 EXPECT_TRUE(analysis->Dominates(114, 145));
424 EXPECT_TRUE(analysis->Dominates(114, 158));
425 EXPECT_TRUE(analysis->Dominates(114, 138));
426 EXPECT_TRUE(analysis->Dominates(114, 137));
427 EXPECT_TRUE(analysis->Dominates(114, 131));
428 EXPECT_TRUE(analysis->Dominates(114, 117));
429 }
430
431 } // namespace
432 } // namespace opt
433 } // namespace spvtools
434