1 // Copyright (c) 2020 André Perez Maselco
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_expand_vector_reduction.h"
16
17 #include "gtest/gtest.h"
18 #include "source/fuzz/fuzzer_util.h"
19 #include "source/fuzz/instruction_descriptor.h"
20 #include "test/fuzz/fuzz_test_util.h"
21
22 namespace spvtools {
23 namespace fuzz {
24 namespace {
25
TEST(TransformationExpandVectorReductionTest,IsApplicable)26 TEST(TransformationExpandVectorReductionTest, IsApplicable) {
27 std::string reference_shader = R"(
28 OpCapability Shader
29 %1 = OpExtInstImport "GLSL.std.450"
30 OpMemoryModel Logical GLSL450
31 OpEntryPoint Vertex %9 "main"
32
33 ; Types
34 %2 = OpTypeBool
35 %3 = OpTypeVector %2 2
36 %4 = OpTypeVoid
37 %5 = OpTypeFunction %4
38
39 ; Constants
40 %6 = OpConstantTrue %2
41 %7 = OpConstantFalse %2
42 %8 = OpConstantComposite %3 %6 %7
43
44 ; main function
45 %9 = OpFunction %4 None %5
46 %10 = OpLabel
47 %11 = OpAny %2 %8
48 %12 = OpAll %2 %8
49 OpReturn
50 OpFunctionEnd
51 )";
52
53 const auto env = SPV_ENV_UNIVERSAL_1_5;
54 const auto consumer = nullptr;
55 const auto context =
56 BuildModule(env, consumer, reference_shader, kFuzzAssembleOption);
57
58 spvtools::ValidatorOptions validator_options;
59 TransformationContext transformation_context(
60 MakeUnique<FactManager>(context.get()), validator_options);
61 ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
62 kConsoleMessageConsumer));
63
64 // Tests undefined instruction.
65 auto transformation = TransformationExpandVectorReduction(13, {14, 15, 16});
66 ASSERT_FALSE(
67 transformation.IsApplicable(context.get(), transformation_context));
68
69 // Tests non OpAny or OpAll instruction.
70 transformation = TransformationExpandVectorReduction(10, {13, 14, 15});
71 ASSERT_FALSE(
72 transformation.IsApplicable(context.get(), transformation_context));
73
74 // Tests the number of fresh ids being different than the necessary.
75 transformation = TransformationExpandVectorReduction(11, {13, 14});
76 ASSERT_FALSE(
77 transformation.IsApplicable(context.get(), transformation_context));
78
79 transformation = TransformationExpandVectorReduction(12, {13, 14, 15, 16});
80 ASSERT_FALSE(
81 transformation.IsApplicable(context.get(), transformation_context));
82
83 // Tests non-fresh ids.
84 transformation = TransformationExpandVectorReduction(11, {12, 13, 14});
85 ASSERT_FALSE(
86 transformation.IsApplicable(context.get(), transformation_context));
87
88 // Tests duplicated fresh ids.
89 transformation = TransformationExpandVectorReduction(11, {13, 13, 14});
90 ASSERT_FALSE(
91 transformation.IsApplicable(context.get(), transformation_context));
92
93 // Tests applicable transformations.
94 transformation = TransformationExpandVectorReduction(11, {13, 14, 15});
95 ASSERT_TRUE(
96 transformation.IsApplicable(context.get(), transformation_context));
97
98 transformation = TransformationExpandVectorReduction(12, {13, 14, 15});
99 ASSERT_TRUE(
100 transformation.IsApplicable(context.get(), transformation_context));
101 }
102
TEST(TransformationExpandVectorReductionTest,Apply)103 TEST(TransformationExpandVectorReductionTest, Apply) {
104 std::string reference_shader = R"(
105 OpCapability Shader
106 %1 = OpExtInstImport "GLSL.std.450"
107 OpMemoryModel Logical GLSL450
108 OpEntryPoint Vertex %13 "main"
109
110 ; Types
111 %2 = OpTypeBool
112 %3 = OpTypeVector %2 2
113 %4 = OpTypeVector %2 3
114 %5 = OpTypeVector %2 4
115 %6 = OpTypeVoid
116 %7 = OpTypeFunction %6
117
118 ; Constants
119 %8 = OpConstantTrue %2
120 %9 = OpConstantFalse %2
121 %10 = OpConstantComposite %3 %8 %9
122 %11 = OpConstantComposite %4 %8 %9 %8
123 %12 = OpConstantComposite %5 %8 %9 %8 %9
124
125 ; main function
126 %13 = OpFunction %6 None %7
127 %14 = OpLabel
128
129 ; OpAny for 2-dimensional vector
130 %15 = OpAny %2 %10
131
132 ; OpAny for 3-dimensional vector
133 %16 = OpAny %2 %11
134
135 ; OpAny for 4-dimensional vector
136 %17 = OpAny %2 %12
137
138 ; OpAll for 2-dimensional vector
139 %18 = OpAll %2 %10
140
141 ; OpAll for 3-dimensional vector
142 %19 = OpAll %2 %11
143
144 ; OpAll for 4-dimensional vector
145 %20 = OpAll %2 %12
146 OpReturn
147 OpFunctionEnd
148 )";
149
150 const auto env = SPV_ENV_UNIVERSAL_1_5;
151 const auto consumer = nullptr;
152 const auto context =
153 BuildModule(env, consumer, reference_shader, kFuzzAssembleOption);
154
155 spvtools::ValidatorOptions validator_options;
156 TransformationContext transformation_context(
157 MakeUnique<FactManager>(context.get()), validator_options);
158 ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
159 kConsoleMessageConsumer));
160
161 // Adds OpAny synonym for 2-dimensional vector.
162 auto transformation = TransformationExpandVectorReduction(15, {21, 22, 23});
163 ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
164 ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
165 MakeDataDescriptor(23, {}), MakeDataDescriptor(15, {})));
166
167 // Adds OpAny synonym for 3-dimensional vector.
168 transformation =
169 TransformationExpandVectorReduction(16, {24, 25, 26, 27, 28});
170 ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
171 ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
172 MakeDataDescriptor(28, {}), MakeDataDescriptor(16, {})));
173
174 // Adds OpAny synonym for 4-dimensional vector.
175 transformation =
176 TransformationExpandVectorReduction(17, {29, 30, 31, 32, 33, 34, 35});
177 ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
178 ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
179 MakeDataDescriptor(35, {}), MakeDataDescriptor(17, {})));
180
181 // Adds OpAll synonym for 2-dimensional vector.
182 transformation = TransformationExpandVectorReduction(18, {36, 37, 38});
183 ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
184 ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
185 MakeDataDescriptor(38, {}), MakeDataDescriptor(18, {})));
186
187 // Adds OpAll synonym for 3-dimensional vector.
188 transformation =
189 TransformationExpandVectorReduction(19, {39, 40, 41, 42, 43});
190 ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
191 ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
192 MakeDataDescriptor(43, {}), MakeDataDescriptor(19, {})));
193
194 // Adds OpAll synonym for 4-dimensional vector.
195 transformation =
196 TransformationExpandVectorReduction(20, {44, 45, 46, 47, 48, 49, 50});
197 ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
198 ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
199 MakeDataDescriptor(50, {}), MakeDataDescriptor(20, {})));
200
201 std::string variant_shader = R"(
202 OpCapability Shader
203 %1 = OpExtInstImport "GLSL.std.450"
204 OpMemoryModel Logical GLSL450
205 OpEntryPoint Vertex %13 "main"
206
207 ; Types
208 %2 = OpTypeBool
209 %3 = OpTypeVector %2 2
210 %4 = OpTypeVector %2 3
211 %5 = OpTypeVector %2 4
212 %6 = OpTypeVoid
213 %7 = OpTypeFunction %6
214
215 ; Constants
216 %8 = OpConstantTrue %2
217 %9 = OpConstantFalse %2
218 %10 = OpConstantComposite %3 %8 %9
219 %11 = OpConstantComposite %4 %8 %9 %8
220 %12 = OpConstantComposite %5 %8 %9 %8 %9
221
222 ; main function
223 %13 = OpFunction %6 None %7
224 %14 = OpLabel
225
226 ; Add OpAny synonym for 2-dimensional vector
227 %21 = OpCompositeExtract %2 %10 0
228 %22 = OpCompositeExtract %2 %10 1
229 %23 = OpLogicalOr %2 %21 %22
230 %15 = OpAny %2 %10
231
232 ; Add OpAny synonym for 3-dimensional vector
233 %24 = OpCompositeExtract %2 %11 0
234 %25 = OpCompositeExtract %2 %11 1
235 %26 = OpCompositeExtract %2 %11 2
236 %27 = OpLogicalOr %2 %24 %25
237 %28 = OpLogicalOr %2 %26 %27
238 %16 = OpAny %2 %11
239
240 ; Add OpAny synonym for 4-dimensional vector
241 %29 = OpCompositeExtract %2 %12 0
242 %30 = OpCompositeExtract %2 %12 1
243 %31 = OpCompositeExtract %2 %12 2
244 %32 = OpCompositeExtract %2 %12 3
245 %33 = OpLogicalOr %2 %29 %30
246 %34 = OpLogicalOr %2 %31 %33
247 %35 = OpLogicalOr %2 %32 %34
248 %17 = OpAny %2 %12
249
250 ; Add OpAll synonym for 2-dimensional vector
251 %36 = OpCompositeExtract %2 %10 0
252 %37 = OpCompositeExtract %2 %10 1
253 %38 = OpLogicalAnd %2 %36 %37
254 %18 = OpAll %2 %10
255
256 ; Add OpAll synonym for 3-dimensional vector
257 %39 = OpCompositeExtract %2 %11 0
258 %40 = OpCompositeExtract %2 %11 1
259 %41 = OpCompositeExtract %2 %11 2
260 %42 = OpLogicalAnd %2 %39 %40
261 %43 = OpLogicalAnd %2 %41 %42
262 %19 = OpAll %2 %11
263
264 ; Add OpAll synonym for 4-dimensional vector
265 %44 = OpCompositeExtract %2 %12 0
266 %45 = OpCompositeExtract %2 %12 1
267 %46 = OpCompositeExtract %2 %12 2
268 %47 = OpCompositeExtract %2 %12 3
269 %48 = OpLogicalAnd %2 %44 %45
270 %49 = OpLogicalAnd %2 %46 %48
271 %50 = OpLogicalAnd %2 %47 %49
272 %20 = OpAll %2 %12
273 OpReturn
274 OpFunctionEnd
275 )";
276
277 ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
278 kConsoleMessageConsumer));
279 ASSERT_TRUE(IsEqual(env, variant_shader, context.get()));
280 }
281
282 } // namespace
283 } // namespace fuzz
284 } // namespace spvtools
285