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