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
26namespace spvtools {
27namespace opt {
28namespace {
29
30using ::testing::UnorderedElementsAre;
31using PassClassTest = PassTest<::testing::Test>;
32
33/*
34  Generated from the following GLSL
35#version 440 core
36layout(location = 0) out vec4 v;
37layout(location = 1) in vec4 in_val;
38void 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*/
75TEST_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