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