1 // Copyright (c) 2019 Google LLC
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 "source/fuzz/transformation_set_selection_control.h"
16 
17 #include "gtest/gtest.h"
18 #include "source/fuzz/fuzzer_util.h"
19 #include "test/fuzz/fuzz_test_util.h"
20 
21 namespace spvtools {
22 namespace fuzz {
23 namespace {
24 
TEST(TransformationSetSelectionControlTest, VariousScenarios)25 TEST(TransformationSetSelectionControlTest, VariousScenarios) {
26   // This is a simple transformation; this test captures the important things
27   // to check for.
28 
29   std::string shader = R"(
30                OpCapability Shader
31           %1 = OpExtInstImport "GLSL.std.450"
32                OpMemoryModel Logical GLSL450
33                OpEntryPoint Fragment %4 "main"
34                OpExecutionMode %4 OriginUpperLeft
35                OpSource ESSL 310
36                OpName %4 "main"
37                OpName %8 "i"
38           %2 = OpTypeVoid
39           %3 = OpTypeFunction %2
40           %6 = OpTypeInt 32 1
41           %7 = OpTypePointer Function %6
42           %9 = OpConstant %6 0
43          %16 = OpConstant %6 10
44          %17 = OpTypeBool
45          %20 = OpConstant %6 3
46          %25 = OpConstant %6 1
47          %28 = OpConstant %6 2
48          %38 = OpConstant %6 4
49           %4 = OpFunction %2 None %3
50           %5 = OpLabel
51           %8 = OpVariable %7 Function
52                OpStore %8 %9
53                OpBranch %10
54          %10 = OpLabel
55                OpLoopMerge %12 %13 None
56                OpBranch %14
57          %14 = OpLabel
58          %15 = OpLoad %6 %8
59          %18 = OpSLessThan %17 %15 %16
60                OpBranchConditional %18 %11 %12
61          %11 = OpLabel
62          %19 = OpLoad %6 %8
63          %21 = OpSGreaterThan %17 %19 %20
64                OpSelectionMerge %23 Flatten
65                OpBranchConditional %21 %22 %23
66          %22 = OpLabel
67          %24 = OpLoad %6 %8
68          %26 = OpIAdd %6 %24 %25
69                OpStore %8 %26
70                OpBranch %23
71          %23 = OpLabel
72          %27 = OpLoad %6 %8
73          %29 = OpSLessThan %17 %27 %28
74                OpSelectionMerge %31 DontFlatten
75                OpBranchConditional %29 %30 %31
76          %30 = OpLabel
77          %32 = OpLoad %6 %8
78          %33 = OpISub %6 %32 %25
79                OpStore %8 %33
80                OpBranch %31
81          %31 = OpLabel
82          %34 = OpLoad %6 %8
83                OpSelectionMerge %37 None
84                OpSwitch %34 %36 0 %35
85          %36 = OpLabel
86                OpBranch %37
87          %35 = OpLabel
88          %39 = OpLoad %6 %8
89          %40 = OpIAdd %6 %39 %38
90                OpStore %8 %40
91                OpBranch %36
92          %37 = OpLabel
93                OpBranch %13
94          %13 = OpLabel
95          %43 = OpLoad %6 %8
96          %44 = OpIAdd %6 %43 %25
97                OpStore %8 %44
98                OpBranch %10
99          %12 = OpLabel
100                OpReturn
101                OpFunctionEnd
102   )";
103 
104   const auto env = SPV_ENV_UNIVERSAL_1_3;
105   const auto consumer = nullptr;
106   const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
107 
108   spvtools::ValidatorOptions validator_options;
109   TransformationContext transformation_context(
110       MakeUnique<FactManager>(context.get()), validator_options);
111   // %44 is not a block
112   ASSERT_FALSE(TransformationSetSelectionControl(
113                    44, uint32_t(spv::SelectionControlMask::Flatten))
114                    .IsApplicable(context.get(), transformation_context));
115   // %13 does not end with OpSelectionMerge
116   ASSERT_FALSE(TransformationSetSelectionControl(
117                    13, uint32_t(spv::SelectionControlMask::MaskNone))
118                    .IsApplicable(context.get(), transformation_context));
119   // %10 ends in OpLoopMerge, not OpSelectionMerge
120   ASSERT_FALSE(TransformationSetSelectionControl(
121                    10, uint32_t(spv::SelectionControlMask::MaskNone))
122                    .IsApplicable(context.get(), transformation_context));
123 
124   TransformationSetSelectionControl transformation1(
125       11, uint32_t(spv::SelectionControlMask::DontFlatten));
126   ASSERT_TRUE(
127       transformation1.IsApplicable(context.get(), transformation_context));
128   ApplyAndCheckFreshIds(transformation1, context.get(),
129                         &transformation_context);
130 
131   TransformationSetSelectionControl transformation2(
132       23, uint32_t(spv::SelectionControlMask::Flatten));
133   ASSERT_TRUE(
134       transformation2.IsApplicable(context.get(), transformation_context));
135   ApplyAndCheckFreshIds(transformation2, context.get(),
136                         &transformation_context);
137 
138   TransformationSetSelectionControl transformation3(
139       31, uint32_t(spv::SelectionControlMask::MaskNone));
140   ASSERT_TRUE(
141       transformation3.IsApplicable(context.get(), transformation_context));
142   ApplyAndCheckFreshIds(transformation3, context.get(),
143                         &transformation_context);
144 
145   TransformationSetSelectionControl transformation4(
146       31, uint32_t(spv::SelectionControlMask::Flatten));
147   ASSERT_TRUE(
148       transformation4.IsApplicable(context.get(), transformation_context));
149   ApplyAndCheckFreshIds(transformation4, context.get(),
150                         &transformation_context);
151 
152   std::string after_transformation = R"(
153                OpCapability Shader
154           %1 = OpExtInstImport "GLSL.std.450"
155                OpMemoryModel Logical GLSL450
156                OpEntryPoint Fragment %4 "main"
157                OpExecutionMode %4 OriginUpperLeft
158                OpSource ESSL 310
159                OpName %4 "main"
160                OpName %8 "i"
161           %2 = OpTypeVoid
162           %3 = OpTypeFunction %2
163           %6 = OpTypeInt 32 1
164           %7 = OpTypePointer Function %6
165           %9 = OpConstant %6 0
166          %16 = OpConstant %6 10
167          %17 = OpTypeBool
168          %20 = OpConstant %6 3
169          %25 = OpConstant %6 1
170          %28 = OpConstant %6 2
171          %38 = OpConstant %6 4
172           %4 = OpFunction %2 None %3
173           %5 = OpLabel
174           %8 = OpVariable %7 Function
175                OpStore %8 %9
176                OpBranch %10
177          %10 = OpLabel
178                OpLoopMerge %12 %13 None
179                OpBranch %14
180          %14 = OpLabel
181          %15 = OpLoad %6 %8
182          %18 = OpSLessThan %17 %15 %16
183                OpBranchConditional %18 %11 %12
184          %11 = OpLabel
185          %19 = OpLoad %6 %8
186          %21 = OpSGreaterThan %17 %19 %20
187                OpSelectionMerge %23 DontFlatten
188                OpBranchConditional %21 %22 %23
189          %22 = OpLabel
190          %24 = OpLoad %6 %8
191          %26 = OpIAdd %6 %24 %25
192                OpStore %8 %26
193                OpBranch %23
194          %23 = OpLabel
195          %27 = OpLoad %6 %8
196          %29 = OpSLessThan %17 %27 %28
197                OpSelectionMerge %31 Flatten
198                OpBranchConditional %29 %30 %31
199          %30 = OpLabel
200          %32 = OpLoad %6 %8
201          %33 = OpISub %6 %32 %25
202                OpStore %8 %33
203                OpBranch %31
204          %31 = OpLabel
205          %34 = OpLoad %6 %8
206                OpSelectionMerge %37 Flatten
207                OpSwitch %34 %36 0 %35
208          %36 = OpLabel
209                OpBranch %37
210          %35 = OpLabel
211          %39 = OpLoad %6 %8
212          %40 = OpIAdd %6 %39 %38
213                OpStore %8 %40
214                OpBranch %36
215          %37 = OpLabel
216                OpBranch %13
217          %13 = OpLabel
218          %43 = OpLoad %6 %8
219          %44 = OpIAdd %6 %43 %25
220                OpStore %8 %44
221                OpBranch %10
222          %12 = OpLabel
223                OpReturn
224                OpFunctionEnd
225   )";
226   ASSERT_TRUE(IsEqual(env, after_transformation, context.get()));
227 }
228 
229 }  // namespace
230 }  // namespace fuzz
231 }  // namespace spvtools
232