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