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 330 core
36layout(location = 0) out vec4 v;
37void main(){
38  if (true) {
39    if (true) {
40      v = vec4(1,1,1,1);
41    } else {
42      v = vec4(2,2,2,2);
43    }
44  } else {
45    if (true) {
46      v = vec4(3,3,3,3);
47    } else {
48      v = vec4(4,4,4,4);
49    }
50  }
51}
52*/
53TEST_F(PassClassTest, UnreachableNestedIfs) {
54  const std::string text = R"(
55        OpCapability Shader
56        %1 = OpExtInstImport "GLSL.std.450"
57             OpMemoryModel Logical GLSL450
58             OpEntryPoint Fragment %4 "main" %15
59             OpExecutionMode %4 OriginUpperLeft
60             OpSource GLSL 330
61             OpName %4 "main"
62             OpName %15 "v"
63             OpDecorate %15 Location 0
64        %2 = OpTypeVoid
65        %3 = OpTypeFunction %2
66        %6 = OpTypeBool
67        %7 = OpConstantTrue %6
68       %12 = OpTypeFloat 32
69       %13 = OpTypeVector %12 4
70       %14 = OpTypePointer Output %13
71       %15 = OpVariable %14 Output
72       %16 = OpConstant %12 1
73       %17 = OpConstantComposite %13 %16 %16 %16 %16
74       %19 = OpConstant %12 2
75       %20 = OpConstantComposite %13 %19 %19 %19 %19
76       %24 = OpConstant %12 3
77       %25 = OpConstantComposite %13 %24 %24 %24 %24
78       %27 = OpConstant %12 4
79       %28 = OpConstantComposite %13 %27 %27 %27 %27
80        %4 = OpFunction %2 None %3
81        %5 = OpLabel
82             OpSelectionMerge %9 None
83             OpBranchConditional %7 %8 %21
84        %8 = OpLabel
85             OpSelectionMerge %11 None
86             OpBranchConditional %7 %10 %18
87       %10 = OpLabel
88             OpStore %15 %17
89             OpBranch %11
90       %18 = OpLabel
91             OpStore %15 %20
92             OpBranch %11
93       %11 = OpLabel
94             OpBranch %9
95       %21 = OpLabel
96             OpSelectionMerge %23 None
97             OpBranchConditional %7 %22 %26
98       %22 = OpLabel
99             OpStore %15 %25
100             OpBranch %23
101       %26 = OpLabel
102             OpStore %15 %28
103             OpBranch %23
104       %23 = OpLabel
105             OpBranch %9
106        %9 = OpLabel
107             OpReturn
108             OpFunctionEnd
109)";
110  // clang-format on
111  std::unique_ptr<IRContext> context =
112      BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text,
113                  SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
114  Module* module = context->module();
115  EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n"
116                             << text << std::endl;
117
118  const Function* f = spvtest::GetFunction(module, 4);
119
120  DominatorAnalysis* analysis = context->GetDominatorAnalysis(f);
121
122  EXPECT_TRUE(analysis->Dominates(5, 8));
123  EXPECT_TRUE(analysis->Dominates(5, 9));
124  EXPECT_TRUE(analysis->Dominates(5, 21));
125  EXPECT_TRUE(analysis->Dominates(5, 18));
126  EXPECT_TRUE(analysis->Dominates(5, 10));
127  EXPECT_TRUE(analysis->Dominates(5, 11));
128  EXPECT_TRUE(analysis->Dominates(5, 23));
129  EXPECT_TRUE(analysis->Dominates(5, 22));
130  EXPECT_TRUE(analysis->Dominates(5, 26));
131  EXPECT_TRUE(analysis->Dominates(8, 18));
132  EXPECT_TRUE(analysis->Dominates(8, 10));
133  EXPECT_TRUE(analysis->Dominates(8, 11));
134  EXPECT_TRUE(analysis->Dominates(21, 23));
135  EXPECT_TRUE(analysis->Dominates(21, 22));
136  EXPECT_TRUE(analysis->Dominates(21, 26));
137
138  EXPECT_TRUE(analysis->StrictlyDominates(5, 8));
139  EXPECT_TRUE(analysis->StrictlyDominates(5, 9));
140  EXPECT_TRUE(analysis->StrictlyDominates(5, 21));
141  EXPECT_TRUE(analysis->StrictlyDominates(8, 18));
142  EXPECT_TRUE(analysis->StrictlyDominates(8, 10));
143  EXPECT_TRUE(analysis->StrictlyDominates(8, 11));
144  EXPECT_TRUE(analysis->StrictlyDominates(21, 23));
145  EXPECT_TRUE(analysis->StrictlyDominates(21, 22));
146  EXPECT_TRUE(analysis->StrictlyDominates(21, 26));
147}
148
149}  // namespace
150}  // namespace opt
151}  // namespace spvtools
152