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/*
34Generated from the following GLSL
35#version 440 core
36layout(location = 0) out vec4 c;
37layout(location = 1)in vec4 in_val;
38void main(){
39  if ( in_val.x < 10) {
40    int z = 0;
41    int i = 0;
42    for (i = 0; i < in_val.y; ++i) {
43        z += i;
44    }
45    c = vec4(i,i,i,i);
46  } else {
47        c = vec4(1,1,1,1);
48  }
49}
50*/
51TEST_F(PassClassTest, BasicVisitFromEntryPoint) {
52  const std::string text = R"(
53               OpCapability Shader
54          %1 = OpExtInstImport "GLSL.std.450"
55               OpMemoryModel Logical GLSL450
56               OpEntryPoint Fragment %4 "main" %9 %43
57               OpExecutionMode %4 OriginUpperLeft
58               OpSource GLSL 440
59               OpName %4 "main"
60               OpName %9 "in_val"
61               OpName %22 "z"
62               OpName %24 "i"
63               OpName %43 "c"
64               OpDecorate %9 Location 1
65               OpDecorate %43 Location 0
66          %2 = OpTypeVoid
67          %3 = OpTypeFunction %2
68          %6 = OpTypeFloat 32
69          %7 = OpTypeVector %6 4
70          %8 = OpTypePointer Input %7
71          %9 = OpVariable %8 Input
72         %10 = OpTypeInt 32 0
73         %11 = OpConstant %10 0
74         %12 = OpTypePointer Input %6
75         %15 = OpConstant %6 10
76         %16 = OpTypeBool
77         %20 = OpTypeInt 32 1
78         %21 = OpTypePointer Function %20
79         %23 = OpConstant %20 0
80         %32 = OpConstant %10 1
81         %40 = OpConstant %20 1
82         %42 = OpTypePointer Output %7
83         %43 = OpVariable %42 Output
84         %54 = OpConstant %6 1
85         %55 = OpConstantComposite %7 %54 %54 %54 %54
86          %4 = OpFunction %2 None %3
87          %5 = OpLabel
88         %22 = OpVariable %21 Function
89         %24 = OpVariable %21 Function
90         %13 = OpAccessChain %12 %9 %11
91         %14 = OpLoad %6 %13
92         %17 = OpFOrdLessThan %16 %14 %15
93               OpSelectionMerge %19 None
94               OpBranchConditional %17 %18 %53
95         %18 = OpLabel
96               OpStore %22 %23
97               OpStore %24 %23
98               OpStore %24 %23
99               OpBranch %25
100         %25 = OpLabel
101               OpLoopMerge %27 %28 None
102               OpBranch %29
103         %29 = OpLabel
104         %30 = OpLoad %20 %24
105         %31 = OpConvertSToF %6 %30
106         %33 = OpAccessChain %12 %9 %32
107         %34 = OpLoad %6 %33
108         %35 = OpFOrdLessThan %16 %31 %34
109               OpBranchConditional %35 %26 %27
110         %26 = OpLabel
111         %36 = OpLoad %20 %24
112         %37 = OpLoad %20 %22
113         %38 = OpIAdd %20 %37 %36
114               OpStore %22 %38
115               OpBranch %28
116         %28 = OpLabel
117         %39 = OpLoad %20 %24
118         %41 = OpIAdd %20 %39 %40
119               OpStore %24 %41
120               OpBranch %25
121         %27 = OpLabel
122         %44 = OpLoad %20 %24
123         %45 = OpConvertSToF %6 %44
124         %46 = OpLoad %20 %24
125         %47 = OpConvertSToF %6 %46
126         %48 = OpLoad %20 %24
127         %49 = OpConvertSToF %6 %48
128         %50 = OpLoad %20 %24
129         %51 = OpConvertSToF %6 %50
130         %52 = OpCompositeConstruct %7 %45 %47 %49 %51
131               OpStore %43 %52
132               OpBranch %19
133         %53 = OpLabel
134               OpStore %43 %55
135               OpBranch %19
136         %19 = OpLabel
137               OpReturn
138               OpFunctionEnd
139)";
140  // clang-format on
141  std::unique_ptr<IRContext> context =
142      BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text,
143                  SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
144  Module* module = context->module();
145  EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n"
146                             << text << std::endl;
147  const Function* f = spvtest::GetFunction(module, 4);
148
149  DominatorAnalysis* analysis = context->GetDominatorAnalysis(f);
150  const CFG& cfg = *context->cfg();
151
152  DominatorTree& tree = analysis->GetDomTree();
153
154  EXPECT_EQ(tree.GetRoot()->bb_, cfg.pseudo_entry_block());
155  EXPECT_TRUE(analysis->Dominates(5, 18));
156  EXPECT_TRUE(analysis->Dominates(5, 53));
157  EXPECT_TRUE(analysis->Dominates(5, 19));
158  EXPECT_TRUE(analysis->Dominates(5, 25));
159  EXPECT_TRUE(analysis->Dominates(5, 29));
160  EXPECT_TRUE(analysis->Dominates(5, 27));
161  EXPECT_TRUE(analysis->Dominates(5, 26));
162  EXPECT_TRUE(analysis->Dominates(5, 28));
163
164  EXPECT_TRUE(analysis->StrictlyDominates(5, 18));
165  EXPECT_TRUE(analysis->StrictlyDominates(5, 53));
166  EXPECT_TRUE(analysis->StrictlyDominates(5, 19));
167  EXPECT_TRUE(analysis->StrictlyDominates(5, 25));
168  EXPECT_TRUE(analysis->StrictlyDominates(5, 29));
169  EXPECT_TRUE(analysis->StrictlyDominates(5, 27));
170  EXPECT_TRUE(analysis->StrictlyDominates(5, 26));
171  EXPECT_TRUE(analysis->StrictlyDominates(5, 28));
172}
173
174}  // namespace
175}  // namespace opt
176}  // namespace spvtools
177