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