1 // Copyright (c) 2021 Shiyu Liu
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_wrap_vector_synonym.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(TransformationWrapVectorSynonym, BasicTest)26 TEST(TransformationWrapVectorSynonym, BasicTest) {
27 std::string shader = R"(
28 OpCapability Shader
29 %1 = OpExtInstImport "GLSL.std.450"
30 OpMemoryModel Logical GLSL450
31 OpEntryPoint Fragment %4 "main" %97
32 OpExecutionMode %4 OriginUpperLeft
33 OpSource ESSL 310
34 OpName %4 "main"
35 %2 = OpTypeVoid
36 %3 = OpTypeFunction %2
37 %6 = OpTypeInt 32 1
38 %7 = OpTypePointer Function %6
39 %9 = OpConstant %6 10
40 %11 = OpConstant %6 -5
41 %12 = OpTypeVector %6 2
42 %13 = OpTypePointer Function %12
43 %18 = OpTypeInt 32 0
44 %19 = OpTypePointer Function %18
45 %21 = OpConstant %18 8
46 %23 = OpConstant %18 2
47 %24 = OpTypeVector %18 3
48 %25 = OpTypePointer Function %24
49 %31 = OpTypeFloat 32
50 %32 = OpTypePointer Function %31
51 %34 = OpConstant %31 3.29999995
52 %36 = OpConstant %31 1.10000002
53 %37 = OpTypeVector %31 4
54 %38 = OpTypePointer Function %37
55 %96 = OpTypePointer Input %31
56 %97 = OpVariable %96 Input
57 %4 = OpFunction %2 None %3
58 %5 = OpLabel
59 %8 = OpVariable %7 Function
60 %10 = OpVariable %7 Function
61 %14 = OpVariable %13 Function
62 %20 = OpVariable %19 Function
63 %22 = OpVariable %19 Function
64 %26 = OpVariable %25 Function
65 %33 = OpVariable %32 Function
66 %35 = OpVariable %32 Function
67 %39 = OpVariable %38 Function
68 %47 = OpVariable %7 Function
69 %51 = OpVariable %7 Function
70 %55 = OpVariable %7 Function
71 %59 = OpVariable %7 Function
72 %63 = OpVariable %19 Function
73 %67 = OpVariable %19 Function
74 %71 = OpVariable %19 Function
75 %75 = OpVariable %19 Function
76 %79 = OpVariable %32 Function
77 %83 = OpVariable %32 Function
78 %87 = OpVariable %32 Function
79 %91 = OpVariable %32 Function
80 OpStore %8 %9
81 OpStore %10 %11
82 %15 = OpLoad %6 %8
83 %16 = OpLoad %6 %10
84 %17 = OpCompositeConstruct %12 %15 %16
85 OpStore %14 %17
86 OpStore %20 %21
87 OpStore %22 %23
88 %27 = OpLoad %18 %20
89 %28 = OpLoad %18 %20
90 %29 = OpLoad %18 %22
91 %30 = OpCompositeConstruct %24 %27 %28 %29
92 OpStore %26 %30
93 OpStore %33 %34
94 OpStore %35 %36
95 %40 = OpLoad %31 %33
96 %41 = OpLoad %31 %33
97 %42 = OpLoad %31 %35
98 %43 = OpLoad %31 %35
99 %44 = OpCompositeConstruct %37 %40 %41 %42 %43
100 %45 = OpLoad %37 %39
101 %46 = OpVectorShuffle %37 %45 %44 5 6 7 4
102 OpStore %39 %46
103 %48 = OpLoad %6 %8
104 %49 = OpLoad %6 %10
105 %100 = OpCompositeConstruct %12 %48 %48
106 %101 = OpCompositeConstruct %12 %49 %49
107 %50 = OpIAdd %6 %48 %49
108 OpStore %47 %50
109 %52 = OpLoad %6 %8
110 %53 = OpLoad %6 %10
111 %54 = OpISub %6 %52 %53
112 OpStore %51 %54
113 %56 = OpLoad %6 %8
114 %57 = OpLoad %6 %10
115 %58 = OpIMul %6 %56 %57
116 OpStore %55 %58
117 %60 = OpLoad %6 %8
118 %61 = OpLoad %6 %10
119 %62 = OpSDiv %6 %60 %61
120 OpStore %59 %62
121 %64 = OpLoad %18 %20
122 %65 = OpLoad %18 %22
123 %66 = OpIAdd %18 %64 %65
124 OpStore %63 %66
125 %68 = OpLoad %18 %20
126 %69 = OpLoad %18 %22
127 %70 = OpISub %18 %68 %69
128 OpStore %67 %70
129 %72 = OpLoad %18 %20
130 %73 = OpLoad %18 %22
131 %74 = OpIMul %18 %72 %73
132 OpStore %71 %74
133 %76 = OpLoad %18 %20
134 %77 = OpLoad %18 %22
135 %78 = OpUDiv %18 %76 %77
136 OpStore %75 %78
137 %80 = OpLoad %31 %33
138 %81 = OpLoad %31 %35
139 %82 = OpFAdd %31 %80 %81
140 OpStore %79 %82
141 %84 = OpLoad %31 %33
142 %85 = OpLoad %31 %35
143 %86 = OpFSub %31 %84 %85
144 OpStore %83 %86
145 %88 = OpLoad %31 %33
146 %89 = OpLoad %31 %35
147 %90 = OpFMul %31 %88 %89
148 OpStore %87 %90
149 %92 = OpLoad %31 %33
150 %93 = OpLoad %31 %35
151 %94 = OpFDiv %31 %92 %93
152 OpStore %91 %94
153 OpReturn
154 OpFunctionEnd
155 )";
156 const auto env = SPV_ENV_UNIVERSAL_1_3;
157 const auto consumer = nullptr;
158 const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
159 spvtools::ValidatorOptions validator_options;
160
161 // Check context validity.
162 ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
163 kConsoleMessageConsumer));
164
165 TransformationContext transformation_context(
166 MakeUnique<FactManager>(context.get()), validator_options);
167
168 // Vec Type Id | Vector Type | Element Type id | Element Type |
169 // ------------+----------------+------------------+-----------------+
170 // 12 | vec2 | 6 | int32 |
171 // 24 | vec3 | 18 | uint32 |
172 // 37 | vec4 | 31 | float |
173
174 // Instruction Id | Opcode | Type Id | constant id 1 | constant id 2 |
175 // ---------------+---------+---------+---------------+---------------+
176 // 50 | OpIAdd | 6 | 48 | 49 |
177 // 54 | OpISub | 6 | 52 | 53 |
178 // 58 | OpIMul | 6 | 56 | 57 |
179 // 62 | OpSDiv | 6 | 60 | 61 |
180 // 66 | OpIAdd | 18 | 64 | 65 |
181 // 70 | OpISub | 18 | 68 | 69 |
182 // 74 | OpIMul | 18 | 72 | 73 |
183 // 78 | OpUDiv | 18 | 76 | 77 |
184 // 82 | OpFAdd | 31 | 80 | 81 |
185 // 86 | OpFSub | 31 | 84 | 85 |
186 // 90 | OpFMul | 31 | 88 | 89 |
187 // 94 | OpFDiv | 31 | 92 | 93 |
188
189 // Assert that the target scalar instruction result id is relevant.
190 ASSERT_FALSE(transformation_context.GetFactManager()->IdIsIrrelevant(50));
191 transformation_context.GetFactManager()->AddFactDataSynonym(
192 MakeDataDescriptor(100, {1}), MakeDataDescriptor(48, {}));
193 transformation_context.GetFactManager()->AddFactDataSynonym(
194 MakeDataDescriptor(101, {1}), MakeDataDescriptor(49, {}));
195
196 // The following are all invalid use.
197 {
198 // Bad: Instruction id does not exist.
199 TransformationWrapVectorSynonym wrap_add_int_bad1(103, 100, 101, 102, 1);
200 ASSERT_FALSE(
201 wrap_add_int_bad1.IsApplicable(context.get(), transformation_context));
202
203 // Bad: Instruction id given is not of a valid arithmetic operation typed
204 // instruction.
205 TransformationWrapVectorSynonym wrap_add_int_bad2(80, 100, 101, 102, 1);
206 ASSERT_FALSE(
207 wrap_add_int_bad1.IsApplicable(context.get(), transformation_context));
208
209 // Bad: the id for the first vector does not exist.
210 TransformationWrapVectorSynonym wrap_add_int_bad3(50, 105, 101, 102, 1);
211 ASSERT_FALSE(
212 wrap_add_int_bad3.IsApplicable(context.get(), transformation_context));
213
214 // Bad: the id for the second vector does not exist.
215 TransformationWrapVectorSynonym wrap_add_int_bad4(50, 100, 105, 102, 1);
216 ASSERT_FALSE(
217 wrap_add_int_bad4.IsApplicable(context.get(), transformation_context));
218
219 // Bad: vector id is not fresh.
220 TransformationWrapVectorSynonym wrap_add_int_bad6(50, 100, 101, 94, 1);
221 ASSERT_FALSE(
222 wrap_add_int_bad6.IsApplicable(context.get(), transformation_context));
223
224 // Bad: The position goes out of bound for the given vector type.
225 TransformationWrapVectorSynonym wrap_add_int_bad8(50, 100, 101, 102, 2);
226 ASSERT_FALSE(
227 wrap_add_int_bad8.IsApplicable(context.get(), transformation_context));
228
229 // Bad: The original instruction is not a valid scalar operation
230 // instruction.
231 TransformationWrapVectorSynonym wrap_add_int(27, 100, 101, 102, 1);
232 ASSERT_FALSE(
233 wrap_add_int.IsApplicable(context.get(), transformation_context));
234 }
235
236 // Good: The following transformation should be applicable.
237 TransformationWrapVectorSynonym wrap_add_int(50, 100, 101, 102, 1);
238 ASSERT_TRUE(wrap_add_int.IsApplicable(context.get(), transformation_context));
239 // Insert an arithmetic instruction of the same type to add two vectors.
240 ApplyAndCheckFreshIds(wrap_add_int, context.get(), &transformation_context);
241
242 // |instruction_id| and id at |scalar_position of the result vector should be
243 // synonyms.
244 ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
245 MakeDataDescriptor(102, {1}), MakeDataDescriptor(50, {})));
246
247 // After applying transformations, the instruction:
248 //
249 // %102 = OpIAdd %12 %100 %101
250 //
251 // should be added before:
252 //
253 // %50 = OpIAdd %6 %48 %49
254 std::string after_transformation = R"(
255 OpCapability Shader
256 %1 = OpExtInstImport "GLSL.std.450"
257 OpMemoryModel Logical GLSL450
258 OpEntryPoint Fragment %4 "main" %97
259 OpExecutionMode %4 OriginUpperLeft
260 OpSource ESSL 310
261 OpName %4 "main"
262 %2 = OpTypeVoid
263 %3 = OpTypeFunction %2
264 %6 = OpTypeInt 32 1
265 %7 = OpTypePointer Function %6
266 %9 = OpConstant %6 10
267 %11 = OpConstant %6 -5
268 %12 = OpTypeVector %6 2
269 %13 = OpTypePointer Function %12
270 %18 = OpTypeInt 32 0
271 %19 = OpTypePointer Function %18
272 %21 = OpConstant %18 8
273 %23 = OpConstant %18 2
274 %24 = OpTypeVector %18 3
275 %25 = OpTypePointer Function %24
276 %31 = OpTypeFloat 32
277 %32 = OpTypePointer Function %31
278 %34 = OpConstant %31 3.29999995
279 %36 = OpConstant %31 1.10000002
280 %37 = OpTypeVector %31 4
281 %38 = OpTypePointer Function %37
282 %96 = OpTypePointer Input %31
283 %97 = OpVariable %96 Input
284 %4 = OpFunction %2 None %3
285 %5 = OpLabel
286 %8 = OpVariable %7 Function
287 %10 = OpVariable %7 Function
288 %14 = OpVariable %13 Function
289 %20 = OpVariable %19 Function
290 %22 = OpVariable %19 Function
291 %26 = OpVariable %25 Function
292 %33 = OpVariable %32 Function
293 %35 = OpVariable %32 Function
294 %39 = OpVariable %38 Function
295 %47 = OpVariable %7 Function
296 %51 = OpVariable %7 Function
297 %55 = OpVariable %7 Function
298 %59 = OpVariable %7 Function
299 %63 = OpVariable %19 Function
300 %67 = OpVariable %19 Function
301 %71 = OpVariable %19 Function
302 %75 = OpVariable %19 Function
303 %79 = OpVariable %32 Function
304 %83 = OpVariable %32 Function
305 %87 = OpVariable %32 Function
306 %91 = OpVariable %32 Function
307 OpStore %8 %9
308 OpStore %10 %11
309 %15 = OpLoad %6 %8
310 %16 = OpLoad %6 %10
311 %17 = OpCompositeConstruct %12 %15 %16
312 OpStore %14 %17
313 OpStore %20 %21
314 OpStore %22 %23
315 %27 = OpLoad %18 %20
316 %28 = OpLoad %18 %20
317 %29 = OpLoad %18 %22
318 %30 = OpCompositeConstruct %24 %27 %28 %29
319 OpStore %26 %30
320 OpStore %33 %34
321 OpStore %35 %36
322 %40 = OpLoad %31 %33
323 %41 = OpLoad %31 %33
324 %42 = OpLoad %31 %35
325 %43 = OpLoad %31 %35
326 %44 = OpCompositeConstruct %37 %40 %41 %42 %43
327 %45 = OpLoad %37 %39
328 %46 = OpVectorShuffle %37 %45 %44 5 6 7 4
329 OpStore %39 %46
330 %48 = OpLoad %6 %8
331 %49 = OpLoad %6 %10
332 %100 = OpCompositeConstruct %12 %48 %48
333 %101 = OpCompositeConstruct %12 %49 %49
334 %102 = OpIAdd %12 %100 %101
335 %50 = OpIAdd %6 %48 %49
336 OpStore %47 %50
337 %52 = OpLoad %6 %8
338 %53 = OpLoad %6 %10
339 %54 = OpISub %6 %52 %53
340 OpStore %51 %54
341 %56 = OpLoad %6 %8
342 %57 = OpLoad %6 %10
343 %58 = OpIMul %6 %56 %57
344 OpStore %55 %58
345 %60 = OpLoad %6 %8
346 %61 = OpLoad %6 %10
347 %62 = OpSDiv %6 %60 %61
348 OpStore %59 %62
349 %64 = OpLoad %18 %20
350 %65 = OpLoad %18 %22
351 %66 = OpIAdd %18 %64 %65
352 OpStore %63 %66
353 %68 = OpLoad %18 %20
354 %69 = OpLoad %18 %22
355 %70 = OpISub %18 %68 %69
356 OpStore %67 %70
357 %72 = OpLoad %18 %20
358 %73 = OpLoad %18 %22
359 %74 = OpIMul %18 %72 %73
360 OpStore %71 %74
361 %76 = OpLoad %18 %20
362 %77 = OpLoad %18 %22
363 %78 = OpUDiv %18 %76 %77
364 OpStore %75 %78
365 %80 = OpLoad %31 %33
366 %81 = OpLoad %31 %35
367 %82 = OpFAdd %31 %80 %81
368 OpStore %79 %82
369 %84 = OpLoad %31 %33
370 %85 = OpLoad %31 %35
371 %86 = OpFSub %31 %84 %85
372 OpStore %83 %86
373 %88 = OpLoad %31 %33
374 %89 = OpLoad %31 %35
375 %90 = OpFMul %31 %88 %89
376 OpStore %87 %90
377 %92 = OpLoad %31 %33
378 %93 = OpLoad %31 %35
379 %94 = OpFDiv %31 %92 %93
380 OpStore %91 %94
381 OpReturn
382 OpFunctionEnd
383 )";
384 ASSERT_TRUE(IsEqual(env, after_transformation, context.get()));
385 }
386
TEST(TransformationWrapVectorSynonym, OperationSupportTest)387 TEST(TransformationWrapVectorSynonym, OperationSupportTest) {
388 std::string shader = R"(
389 OpCapability Shader
390 %1 = OpExtInstImport "GLSL.std.450"
391 OpMemoryModel Logical GLSL450
392 OpEntryPoint Fragment %4 "main" %97
393 OpExecutionMode %4 OriginUpperLeft
394 OpSource ESSL 310
395 OpName %4 "main"
396 %2 = OpTypeVoid
397 %3 = OpTypeFunction %2
398 %6 = OpTypeInt 32 1
399 %7 = OpTypePointer Function %6
400 %9 = OpConstant %6 10
401 %11 = OpConstant %6 -5
402 %12 = OpTypeVector %6 2
403 %13 = OpTypePointer Function %12
404 %18 = OpTypeInt 32 0
405 %19 = OpTypePointer Function %18
406 %21 = OpConstant %18 8
407 %23 = OpConstant %18 2
408 %24 = OpTypeVector %18 3
409 %25 = OpTypePointer Function %24
410 %31 = OpTypeFloat 32
411 %32 = OpTypePointer Function %31
412 %34 = OpConstant %31 3.29999995
413 %36 = OpConstant %31 1.10000002
414 %37 = OpTypeVector %31 4
415 %38 = OpTypePointer Function %37
416 %96 = OpTypePointer Input %31
417 %97 = OpVariable %96 Input
418 %4 = OpFunction %2 None %3
419 %5 = OpLabel
420 %8 = OpVariable %7 Function
421 %10 = OpVariable %7 Function
422 %14 = OpVariable %13 Function
423 %20 = OpVariable %19 Function
424 %22 = OpVariable %19 Function
425 %26 = OpVariable %25 Function
426 %33 = OpVariable %32 Function
427 %35 = OpVariable %32 Function
428 %39 = OpVariable %38 Function
429 %47 = OpVariable %7 Function
430 %51 = OpVariable %7 Function
431 %55 = OpVariable %7 Function
432 %59 = OpVariable %7 Function
433 %63 = OpVariable %19 Function
434 %67 = OpVariable %19 Function
435 %71 = OpVariable %19 Function
436 %75 = OpVariable %19 Function
437 %79 = OpVariable %32 Function
438 %83 = OpVariable %32 Function
439 %87 = OpVariable %32 Function
440 %91 = OpVariable %32 Function
441 OpStore %8 %9
442 OpStore %10 %11
443 %15 = OpLoad %6 %8
444 %16 = OpLoad %6 %10
445 %17 = OpCompositeConstruct %12 %15 %16
446 OpStore %14 %17
447 OpStore %20 %21
448 OpStore %22 %23
449 %27 = OpLoad %18 %20
450 %28 = OpLoad %18 %20
451 %29 = OpLoad %18 %22
452 %30 = OpCompositeConstruct %24 %27 %28 %29
453 OpStore %26 %30
454 OpStore %33 %34
455 OpStore %35 %36
456 %40 = OpLoad %31 %33
457 %41 = OpLoad %31 %33
458 %42 = OpLoad %31 %35
459 %43 = OpLoad %31 %35
460 %44 = OpCompositeConstruct %37 %40 %41 %42 %43
461 %45 = OpLoad %37 %39
462 %46 = OpVectorShuffle %37 %45 %44 5 6 7 4
463 OpStore %39 %46
464 %48 = OpLoad %6 %8
465 %49 = OpLoad %6 %10
466 %50 = OpIAdd %6 %48 %49
467 OpStore %47 %50
468 %52 = OpLoad %6 %8
469 %53 = OpLoad %6 %10
470 %100 = OpCompositeConstruct %12 %52 %52
471 %101 = OpCompositeConstruct %12 %53 %53
472 %54 = OpISub %6 %52 %53
473 OpStore %51 %54
474 %56 = OpLoad %6 %8
475 %57 = OpLoad %6 %10
476 %103 = OpCompositeConstruct %12 %56 %56
477 %104 = OpCompositeConstruct %12 %57 %57
478 %58 = OpIMul %6 %56 %57
479 OpStore %55 %58
480 %60 = OpLoad %6 %8
481 %61 = OpLoad %6 %10
482 %62 = OpSDiv %6 %60 %61
483 OpStore %59 %62
484 %64 = OpLoad %18 %20
485 %65 = OpLoad %18 %22
486 %106 = OpCompositeConstruct %24 %64 %64 %64
487 %107 = OpCompositeConstruct %24 %65 %65 %65
488 %66 = OpIAdd %18 %64 %65
489 OpStore %63 %66
490 %68 = OpLoad %18 %20
491 %69 = OpLoad %18 %22
492 %109 = OpCompositeConstruct %24 %68 %68 %68
493 %110 = OpCompositeConstruct %24 %69 %69 %69
494 %70 = OpISub %18 %68 %69
495 OpStore %67 %70
496 %72 = OpLoad %18 %20
497 %73 = OpLoad %18 %22
498 %112 = OpCompositeConstruct %24 %72 %72 %72
499 %113 = OpCompositeConstruct %24 %73 %73 %73
500 %74 = OpIMul %18 %72 %73
501 OpStore %71 %74
502 %76 = OpLoad %18 %20
503 %77 = OpLoad %18 %22
504 %78 = OpUDiv %18 %76 %77
505 OpStore %75 %78
506 %80 = OpLoad %31 %33
507 %81 = OpLoad %31 %35
508 %115 = OpCompositeConstruct %37 %80 %80 %80 %80
509 %116 = OpCompositeConstruct %37 %81 %81 %81 %81
510 %82 = OpFAdd %31 %80 %81
511 OpStore %79 %82
512 %84 = OpLoad %31 %33
513 %85 = OpLoad %31 %35
514 %118 = OpCompositeConstruct %37 %84 %84 %84 %84
515 %119 = OpCompositeConstruct %37 %85 %85 %85 %85
516 %86 = OpFSub %31 %84 %85
517 OpStore %83 %86
518 %88 = OpLoad %31 %33
519 %89 = OpLoad %31 %35
520 %121 = OpCompositeConstruct %37 %88 %88 %88 %88
521 %122 = OpCompositeConstruct %37 %89 %89 %89 %89
522 %90 = OpFMul %31 %88 %89
523 OpStore %87 %90
524 %92 = OpLoad %31 %33
525 %93 = OpLoad %31 %35
526 %94 = OpFDiv %31 %92 %93
527 OpStore %91 %94
528 OpReturn
529 OpFunctionEnd
530 )";
531 const auto env = SPV_ENV_UNIVERSAL_1_3;
532 const auto consumer = nullptr;
533 const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
534 spvtools::ValidatorOptions validator_options;
535
536 ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
537 kConsoleMessageConsumer));
538
539 TransformationContext transformation_context(
540 MakeUnique<FactManager>(context.get()), validator_options);
541
542 {
543 // Add synonym facts between the vector operands at pos and the operands to
544 // the scalar instruction.
545 transformation_context.GetFactManager()->AddFactDataSynonym(
546 MakeDataDescriptor(100, {1}), MakeDataDescriptor(52, {}));
547 transformation_context.GetFactManager()->AddFactDataSynonym(
548 MakeDataDescriptor(101, {1}), MakeDataDescriptor(53, {}));
549
550 transformation_context.GetFactManager()->AddFactDataSynonym(
551 MakeDataDescriptor(103, {0}), MakeDataDescriptor(56, {}));
552 transformation_context.GetFactManager()->AddFactDataSynonym(
553 MakeDataDescriptor(104, {0}), MakeDataDescriptor(57, {}));
554
555 transformation_context.GetFactManager()->AddFactDataSynonym(
556 MakeDataDescriptor(106, {2}), MakeDataDescriptor(64, {}));
557 transformation_context.GetFactManager()->AddFactDataSynonym(
558 MakeDataDescriptor(107, {2}), MakeDataDescriptor(65, {}));
559
560 transformation_context.GetFactManager()->AddFactDataSynonym(
561 MakeDataDescriptor(109, {2}), MakeDataDescriptor(68, {}));
562 transformation_context.GetFactManager()->AddFactDataSynonym(
563 MakeDataDescriptor(110, {2}), MakeDataDescriptor(69, {}));
564
565 transformation_context.GetFactManager()->AddFactDataSynonym(
566 MakeDataDescriptor(112, {1}), MakeDataDescriptor(72, {}));
567 transformation_context.GetFactManager()->AddFactDataSynonym(
568 MakeDataDescriptor(113, {1}), MakeDataDescriptor(73, {}));
569
570 transformation_context.GetFactManager()->AddFactDataSynonym(
571 MakeDataDescriptor(115, {2}), MakeDataDescriptor(80, {}));
572 transformation_context.GetFactManager()->AddFactDataSynonym(
573 MakeDataDescriptor(116, {2}), MakeDataDescriptor(81, {}));
574
575 transformation_context.GetFactManager()->AddFactDataSynonym(
576 MakeDataDescriptor(118, {3}), MakeDataDescriptor(84, {}));
577 transformation_context.GetFactManager()->AddFactDataSynonym(
578 MakeDataDescriptor(119, {3}), MakeDataDescriptor(85, {}));
579
580 transformation_context.GetFactManager()->AddFactDataSynonym(
581 MakeDataDescriptor(121, {1}), MakeDataDescriptor(88, {}));
582 transformation_context.GetFactManager()->AddFactDataSynonym(
583 MakeDataDescriptor(122, {1}), MakeDataDescriptor(89, {}));
584 }
585
586 // Test OpISub for signed integer.
587 {
588 // Good: The following transformation should be applicable.
589 TransformationWrapVectorSynonym wrap_sub_int(54, 100, 101, 102, 1);
590 ASSERT_TRUE(
591 wrap_sub_int.IsApplicable(context.get(), transformation_context));
592 ApplyAndCheckFreshIds(wrap_sub_int, context.get(), &transformation_context);
593
594 // |instruction_id| and id at |scalar_position of the result vector should
595 // be synonyms.
596 ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
597 MakeDataDescriptor(102, {1}), MakeDataDescriptor(54, {})));
598 }
599
600 // Test OpIMul for signed integer.
601 {
602 // Good: The following transformation should be applicable.
603 TransformationWrapVectorSynonym wrap_mul_int(58, 103, 104, 105, 0);
604 ASSERT_TRUE(
605 wrap_mul_int.IsApplicable(context.get(), transformation_context));
606 ApplyAndCheckFreshIds(wrap_mul_int, context.get(), &transformation_context);
607
608 // |instruction_id| and id at |scalar_position of the result vector should
609 // be synonyms.
610 ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
611 MakeDataDescriptor(105, {0}), MakeDataDescriptor(58, {})));
612 }
613
614 // Test OpIAdd for unsigned integer.
615 {
616 // Good: The following transformation should be applicable.
617 TransformationWrapVectorSynonym wrap_add_uint(66, 106, 107, 108, 2);
618 ASSERT_TRUE(
619 wrap_add_uint.IsApplicable(context.get(), transformation_context));
620 ApplyAndCheckFreshIds(wrap_add_uint, context.get(),
621 &transformation_context);
622
623 // |instruction_id| and id at |scalar_position of the result vector should
624 // be synonyms.
625 ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
626 MakeDataDescriptor(108, {2}), MakeDataDescriptor(66, {})));
627 }
628
629 // Test OpISub for signed integer.
630 {
631 // Good: The following transformation should be applicable.
632 TransformationWrapVectorSynonym wrap_sub_uint(70, 109, 110, 111, 2);
633 ASSERT_TRUE(
634 wrap_sub_uint.IsApplicable(context.get(), transformation_context));
635 ApplyAndCheckFreshIds(wrap_sub_uint, context.get(),
636 &transformation_context);
637
638 // |instruction_id| and id at |scalar_position of the result vector should
639 // be synonyms.
640 ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
641 MakeDataDescriptor(111, {2}), MakeDataDescriptor(70, {})));
642 }
643
644 // Test OpIMul for signed integer.
645 {
646 // Good: The following transformation should be applicable.
647 TransformationWrapVectorSynonym wrap_mul_uint(74, 112, 113, 114, 1);
648 ASSERT_TRUE(
649 wrap_mul_uint.IsApplicable(context.get(), transformation_context));
650 ApplyAndCheckFreshIds(wrap_mul_uint, context.get(),
651 &transformation_context);
652
653 // |instruction_id| and id at |scalar_position of the result vector should
654 // be synonyms.
655 ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
656 MakeDataDescriptor(114, {1}), MakeDataDescriptor(74, {})));
657 }
658
659 // Test OpFAdd for float.
660 {
661 // Good: The following transformation should be applicable.
662 TransformationWrapVectorSynonym wrap_add_float(82, 115, 116, 117, 2);
663 ASSERT_TRUE(
664 wrap_add_float.IsApplicable(context.get(), transformation_context));
665 ApplyAndCheckFreshIds(wrap_add_float, context.get(),
666 &transformation_context);
667
668 // |instruction_id| and id at |scalar_position of the result vector should
669 // be synonyms.
670 ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
671 MakeDataDescriptor(117, {2}), MakeDataDescriptor(82, {})));
672 }
673
674 // Test OpFSub for float.
675 {
676 // Good: The following transformation should be applicable.
677 TransformationWrapVectorSynonym wrap_add_float(86, 118, 119, 120, 3);
678 ASSERT_TRUE(
679 wrap_add_float.IsApplicable(context.get(), transformation_context));
680 ApplyAndCheckFreshIds(wrap_add_float, context.get(),
681 &transformation_context);
682
683 // |instruction_id| and id at |scalar_position of the result vector should
684 // be synonyms.
685 ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
686 MakeDataDescriptor(120, {3}), MakeDataDescriptor(86, {})));
687 }
688
689 // Test OpFMul for float.
690 {
691 // Good: The following transformation should be applicable.
692 TransformationWrapVectorSynonym wrap_mul_float(90, 121, 122, 123, 1);
693 ASSERT_TRUE(
694 wrap_mul_float.IsApplicable(context.get(), transformation_context));
695 ApplyAndCheckFreshIds(wrap_mul_float, context.get(),
696 &transformation_context);
697
698 // |instruction_id| and id at |scalar_position of the result vector should
699 // be synonyms.
700 ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
701 MakeDataDescriptor(123, {1}), MakeDataDescriptor(90, {})));
702 }
703
704 std::string after_transformation = R"(
705 OpCapability Shader
706 %1 = OpExtInstImport "GLSL.std.450"
707 OpMemoryModel Logical GLSL450
708 OpEntryPoint Fragment %4 "main" %97
709 OpExecutionMode %4 OriginUpperLeft
710 OpSource ESSL 310
711 OpName %4 "main"
712 %2 = OpTypeVoid
713 %3 = OpTypeFunction %2
714 %6 = OpTypeInt 32 1
715 %7 = OpTypePointer Function %6
716 %9 = OpConstant %6 10
717 %11 = OpConstant %6 -5
718 %12 = OpTypeVector %6 2
719 %13 = OpTypePointer Function %12
720 %18 = OpTypeInt 32 0
721 %19 = OpTypePointer Function %18
722 %21 = OpConstant %18 8
723 %23 = OpConstant %18 2
724 %24 = OpTypeVector %18 3
725 %25 = OpTypePointer Function %24
726 %31 = OpTypeFloat 32
727 %32 = OpTypePointer Function %31
728 %34 = OpConstant %31 3.29999995
729 %36 = OpConstant %31 1.10000002
730 %37 = OpTypeVector %31 4
731 %38 = OpTypePointer Function %37
732 %96 = OpTypePointer Input %31
733 %97 = OpVariable %96 Input
734 %4 = OpFunction %2 None %3
735 %5 = OpLabel
736 %8 = OpVariable %7 Function
737 %10 = OpVariable %7 Function
738 %14 = OpVariable %13 Function
739 %20 = OpVariable %19 Function
740 %22 = OpVariable %19 Function
741 %26 = OpVariable %25 Function
742 %33 = OpVariable %32 Function
743 %35 = OpVariable %32 Function
744 %39 = OpVariable %38 Function
745 %47 = OpVariable %7 Function
746 %51 = OpVariable %7 Function
747 %55 = OpVariable %7 Function
748 %59 = OpVariable %7 Function
749 %63 = OpVariable %19 Function
750 %67 = OpVariable %19 Function
751 %71 = OpVariable %19 Function
752 %75 = OpVariable %19 Function
753 %79 = OpVariable %32 Function
754 %83 = OpVariable %32 Function
755 %87 = OpVariable %32 Function
756 %91 = OpVariable %32 Function
757 OpStore %8 %9
758 OpStore %10 %11
759 %15 = OpLoad %6 %8
760 %16 = OpLoad %6 %10
761 %17 = OpCompositeConstruct %12 %15 %16
762 OpStore %14 %17
763 OpStore %20 %21
764 OpStore %22 %23
765 %27 = OpLoad %18 %20
766 %28 = OpLoad %18 %20
767 %29 = OpLoad %18 %22
768 %30 = OpCompositeConstruct %24 %27 %28 %29
769 OpStore %26 %30
770 OpStore %33 %34
771 OpStore %35 %36
772 %40 = OpLoad %31 %33
773 %41 = OpLoad %31 %33
774 %42 = OpLoad %31 %35
775 %43 = OpLoad %31 %35
776 %44 = OpCompositeConstruct %37 %40 %41 %42 %43
777 %45 = OpLoad %37 %39
778 %46 = OpVectorShuffle %37 %45 %44 5 6 7 4
779 OpStore %39 %46
780 %48 = OpLoad %6 %8
781 %49 = OpLoad %6 %10
782 %50 = OpIAdd %6 %48 %49
783 OpStore %47 %50
784 %52 = OpLoad %6 %8
785 %53 = OpLoad %6 %10
786 %100 = OpCompositeConstruct %12 %52 %52
787 %101 = OpCompositeConstruct %12 %53 %53
788 %102 = OpISub %12 %100 %101
789 %54 = OpISub %6 %52 %53
790 OpStore %51 %54
791 %56 = OpLoad %6 %8
792 %57 = OpLoad %6 %10
793 %103 = OpCompositeConstruct %12 %56 %56
794 %104 = OpCompositeConstruct %12 %57 %57
795 %105 = OpIMul %12 %103 %104
796 %58 = OpIMul %6 %56 %57
797 OpStore %55 %58
798 %60 = OpLoad %6 %8
799 %61 = OpLoad %6 %10
800 %62 = OpSDiv %6 %60 %61
801 OpStore %59 %62
802 %64 = OpLoad %18 %20
803 %65 = OpLoad %18 %22
804 %106 = OpCompositeConstruct %24 %64 %64 %64
805 %107 = OpCompositeConstruct %24 %65 %65 %65
806 %108 = OpIAdd %24 %106 %107
807 %66 = OpIAdd %18 %64 %65
808 OpStore %63 %66
809 %68 = OpLoad %18 %20
810 %69 = OpLoad %18 %22
811 %109 = OpCompositeConstruct %24 %68 %68 %68
812 %110 = OpCompositeConstruct %24 %69 %69 %69
813 %111 = OpISub %24 %109 %110
814 %70 = OpISub %18 %68 %69
815 OpStore %67 %70
816 %72 = OpLoad %18 %20
817 %73 = OpLoad %18 %22
818 %112 = OpCompositeConstruct %24 %72 %72 %72
819 %113 = OpCompositeConstruct %24 %73 %73 %73
820 %114 = OpIMul %24 %112 %113
821 %74 = OpIMul %18 %72 %73
822 OpStore %71 %74
823 %76 = OpLoad %18 %20
824 %77 = OpLoad %18 %22
825 %78 = OpUDiv %18 %76 %77
826 OpStore %75 %78
827 %80 = OpLoad %31 %33
828 %81 = OpLoad %31 %35
829 %115 = OpCompositeConstruct %37 %80 %80 %80 %80
830 %116 = OpCompositeConstruct %37 %81 %81 %81 %81
831 %117 = OpFAdd %37 %115 %116
832 %82 = OpFAdd %31 %80 %81
833 OpStore %79 %82
834 %84 = OpLoad %31 %33
835 %85 = OpLoad %31 %35
836 %118 = OpCompositeConstruct %37 %84 %84 %84 %84
837 %119 = OpCompositeConstruct %37 %85 %85 %85 %85
838 %120 = OpFSub %37 %118 %119
839 %86 = OpFSub %31 %84 %85
840 OpStore %83 %86
841 %88 = OpLoad %31 %33
842 %89 = OpLoad %31 %35
843 %121 = OpCompositeConstruct %37 %88 %88 %88 %88
844 %122 = OpCompositeConstruct %37 %89 %89 %89 %89
845 %123 = OpFMul %37 %121 %122
846 %90 = OpFMul %31 %88 %89
847 OpStore %87 %90
848 %92 = OpLoad %31 %33
849 %93 = OpLoad %31 %35
850 %94 = OpFDiv %31 %92 %93
851 OpStore %91 %94
852 OpReturn
853 OpFunctionEnd
854 )";
855 ASSERT_TRUE(IsEqual(env, after_transformation, context.get()));
856 }
857
TEST(TransformationWrapVectorSynonym, DivSupportTest)858 TEST(TransformationWrapVectorSynonym, DivSupportTest) {
859 std::string shader = R"(
860 OpCapability Shader
861 %1 = OpExtInstImport "GLSL.std.450"
862 OpMemoryModel Logical GLSL450
863 OpEntryPoint Fragment %4 "main" %97
864 OpExecutionMode %4 OriginUpperLeft
865 OpSource ESSL 310
866 OpName %4 "main"
867 %2 = OpTypeVoid
868 %3 = OpTypeFunction %2
869 %6 = OpTypeInt 32 1
870 %7 = OpTypePointer Function %6
871 %9 = OpConstant %6 10
872 %11 = OpConstant %6 -5
873 %12 = OpTypeVector %6 2
874 %13 = OpTypePointer Function %12
875 %18 = OpTypeInt 32 0
876 %19 = OpTypePointer Function %18
877 %21 = OpConstant %18 8
878 %23 = OpConstant %18 2
879 %24 = OpTypeVector %18 3
880 %25 = OpTypePointer Function %24
881 %31 = OpTypeFloat 32
882 %32 = OpTypePointer Function %31
883 %34 = OpConstant %31 3.29999995
884 %36 = OpConstant %31 1.10000002
885 %37 = OpTypeVector %31 4
886 %38 = OpTypePointer Function %37
887 %96 = OpTypePointer Input %31
888 %97 = OpVariable %96 Input
889 %4 = OpFunction %2 None %3
890 %5 = OpLabel
891 %8 = OpVariable %7 Function
892 %10 = OpVariable %7 Function
893 %14 = OpVariable %13 Function
894 %20 = OpVariable %19 Function
895 %22 = OpVariable %19 Function
896 %26 = OpVariable %25 Function
897 %33 = OpVariable %32 Function
898 %35 = OpVariable %32 Function
899 %39 = OpVariable %38 Function
900 %47 = OpVariable %7 Function
901 %51 = OpVariable %7 Function
902 %55 = OpVariable %7 Function
903 %59 = OpVariable %7 Function
904 %63 = OpVariable %19 Function
905 %67 = OpVariable %19 Function
906 %71 = OpVariable %19 Function
907 %75 = OpVariable %19 Function
908 %79 = OpVariable %32 Function
909 %83 = OpVariable %32 Function
910 %87 = OpVariable %32 Function
911 %91 = OpVariable %32 Function
912 OpStore %8 %9
913 OpStore %10 %11
914 %15 = OpLoad %6 %8
915 %16 = OpLoad %6 %10
916 %17 = OpCompositeConstruct %12 %15 %16
917 OpStore %14 %17
918 OpStore %20 %21
919 OpStore %22 %23
920 %27 = OpLoad %18 %20
921 %28 = OpLoad %18 %20
922 %29 = OpLoad %18 %22
923 %30 = OpCompositeConstruct %24 %27 %28 %29
924 OpStore %26 %30
925 OpStore %33 %34
926 OpStore %35 %36
927 %40 = OpLoad %31 %33
928 %41 = OpLoad %31 %33
929 %42 = OpLoad %31 %35
930 %43 = OpLoad %31 %35
931 %44 = OpCompositeConstruct %37 %40 %41 %42 %43
932 %45 = OpLoad %37 %39
933 %46 = OpVectorShuffle %37 %45 %44 5 6 7 4
934 OpStore %39 %46
935 %48 = OpLoad %6 %8
936 %49 = OpLoad %6 %10
937 %50 = OpIAdd %6 %48 %49
938 OpStore %47 %50
939 %52 = OpLoad %6 %8
940 %53 = OpLoad %6 %10
941 %54 = OpISub %6 %52 %53
942 OpStore %51 %54
943 %56 = OpLoad %6 %8
944 %57 = OpLoad %6 %10
945 %58 = OpIMul %6 %56 %57
946 OpStore %55 %58
947 %60 = OpLoad %6 %8
948 %61 = OpLoad %6 %10
949 %100 = OpCompositeConstruct %12 %60 %60
950 %101 = OpCompositeConstruct %12 %61 %61
951 %62 = OpSDiv %6 %60 %61
952 OpStore %59 %62
953 %64 = OpLoad %18 %20
954 %65 = OpLoad %18 %22
955 %66 = OpIAdd %18 %64 %65
956 OpStore %63 %66
957 %68 = OpLoad %18 %20
958 %69 = OpLoad %18 %22
959 %70 = OpISub %18 %68 %69
960 OpStore %67 %70
961 %72 = OpLoad %18 %20
962 %73 = OpLoad %18 %22
963 %74 = OpIMul %18 %72 %73
964 OpStore %71 %74
965 %76 = OpLoad %18 %20
966 %77 = OpLoad %18 %22
967 %102 = OpCompositeConstruct %24 %76 %76 %76
968 %103 = OpCompositeConstruct %24 %77 %77 %77
969 %78 = OpUDiv %18 %76 %77
970 OpStore %75 %78
971 %80 = OpLoad %31 %33
972 %81 = OpLoad %31 %35
973 %82 = OpFAdd %31 %80 %81
974 OpStore %79 %82
975 %84 = OpLoad %31 %33
976 %85 = OpLoad %31 %35
977 %86 = OpFSub %31 %84 %85
978 OpStore %83 %86
979 %88 = OpLoad %31 %33
980 %89 = OpLoad %31 %35
981 %90 = OpFMul %31 %88 %89
982 OpStore %87 %90
983 %92 = OpLoad %31 %33
984 %93 = OpLoad %31 %35
985 %104 = OpCompositeConstruct %37 %92 %92 %92 %92
986 %105 = OpCompositeConstruct %37 %93 %93 %93 %93
987 %94 = OpFDiv %31 %92 %93
988 OpStore %91 %94
989 OpReturn
990 OpFunctionEnd
991 )";
992 const auto env = SPV_ENV_UNIVERSAL_1_3;
993 const auto consumer = nullptr;
994 const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
995 spvtools::ValidatorOptions validator_options;
996
997 ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
998 kConsoleMessageConsumer));
999
1000 TransformationContext transformation_context(
1001 MakeUnique<FactManager>(context.get()), validator_options);
1002
1003 transformation_context.GetFactManager()->AddFactDataSynonym(
1004 MakeDataDescriptor(100, {1}), MakeDataDescriptor(60, {}));
1005 transformation_context.GetFactManager()->AddFactDataSynonym(
1006 MakeDataDescriptor(101, {1}), MakeDataDescriptor(61, {}));
1007
1008 transformation_context.GetFactManager()->AddFactDataSynonym(
1009 MakeDataDescriptor(102, {1}), MakeDataDescriptor(76, {}));
1010 transformation_context.GetFactManager()->AddFactDataSynonym(
1011 MakeDataDescriptor(103, {1}), MakeDataDescriptor(77, {}));
1012
1013 transformation_context.GetFactManager()->AddFactDataSynonym(
1014 MakeDataDescriptor(104, {1}), MakeDataDescriptor(92, {}));
1015 transformation_context.GetFactManager()->AddFactDataSynonym(
1016 MakeDataDescriptor(105, {1}), MakeDataDescriptor(93, {}));
1017
1018 // Div operations are not currently supported.
1019 {
1020 TransformationWrapVectorSynonym wrap_div_bad1(62, 100, 101, 106, 1);
1021 ASSERT_FALSE(
1022 wrap_div_bad1.IsApplicable(context.get(), transformation_context));
1023
1024 TransformationWrapVectorSynonym wrap_div_bad2(78, 102, 103, 106, 1);
1025 ASSERT_FALSE(
1026 wrap_div_bad2.IsApplicable(context.get(), transformation_context));
1027
1028 TransformationWrapVectorSynonym wrap_div_bad3(94, 104, 105, 106, 1);
1029 ASSERT_FALSE(
1030 wrap_div_bad3.IsApplicable(context.get(), transformation_context));
1031 }
1032 }
1033
TEST(TransformationWrapVectorSynonym, AdditionalWidthSupportTest)1034 TEST(TransformationWrapVectorSynonym, AdditionalWidthSupportTest) {
1035 std::string shader = R"(
1036 OpCapability Shader
1037 OpCapability Int64
1038 OpCapability Float64
1039 %1 = OpExtInstImport "GLSL.std.450"
1040 OpMemoryModel Logical GLSL450
1041 OpEntryPoint Fragment %4 "main" %97
1042 OpExecutionMode %4 OriginUpperLeft
1043 OpSource ESSL 310
1044 OpName %4 "main"
1045 %2 = OpTypeVoid
1046 %3 = OpTypeFunction %2
1047 %6 = OpTypeInt 64 1
1048 %7 = OpTypePointer Function %6
1049 %9 = OpConstant %6 10
1050 %11 = OpConstant %6 -5
1051 %12 = OpTypeVector %6 2
1052 %13 = OpTypePointer Function %12
1053 %18 = OpTypeInt 64 0
1054 %19 = OpTypePointer Function %18
1055 %21 = OpConstant %18 8
1056 %23 = OpConstant %18 2
1057 %24 = OpTypeVector %18 3
1058 %25 = OpTypePointer Function %24
1059 %31 = OpTypeFloat 64
1060 %32 = OpTypePointer Function %31
1061 %34 = OpConstant %31 3.29999995
1062 %36 = OpConstant %31 1.10000002
1063 %37 = OpTypeVector %31 4
1064 %38 = OpTypePointer Function %37
1065 %96 = OpTypePointer Input %31
1066 %97 = OpVariable %96 Input
1067 %4 = OpFunction %2 None %3
1068 %5 = OpLabel
1069 %8 = OpVariable %7 Function
1070 %10 = OpVariable %7 Function
1071 %14 = OpVariable %13 Function
1072 %20 = OpVariable %19 Function
1073 %22 = OpVariable %19 Function
1074 %26 = OpVariable %25 Function
1075 %33 = OpVariable %32 Function
1076 %35 = OpVariable %32 Function
1077 %39 = OpVariable %38 Function
1078 %47 = OpVariable %7 Function
1079 %51 = OpVariable %7 Function
1080 %55 = OpVariable %7 Function
1081 %59 = OpVariable %7 Function
1082 %63 = OpVariable %19 Function
1083 %67 = OpVariable %19 Function
1084 %71 = OpVariable %19 Function
1085 %75 = OpVariable %19 Function
1086 %79 = OpVariable %32 Function
1087 %83 = OpVariable %32 Function
1088 %87 = OpVariable %32 Function
1089 %91 = OpVariable %32 Function
1090 OpStore %8 %9
1091 OpStore %10 %11
1092 %15 = OpLoad %6 %8
1093 %16 = OpLoad %6 %10
1094 %17 = OpCompositeConstruct %12 %15 %16
1095 OpStore %14 %17
1096 OpStore %20 %21
1097 OpStore %22 %23
1098 %27 = OpLoad %18 %20
1099 %28 = OpLoad %18 %20
1100 %29 = OpLoad %18 %22
1101 %30 = OpCompositeConstruct %24 %27 %28 %29
1102 OpStore %26 %30
1103 OpStore %33 %34
1104 OpStore %35 %36
1105 %40 = OpLoad %31 %33
1106 %41 = OpLoad %31 %33
1107 %42 = OpLoad %31 %35
1108 %43 = OpLoad %31 %35
1109 %44 = OpCompositeConstruct %37 %40 %41 %42 %43
1110 %45 = OpLoad %37 %39
1111 %46 = OpVectorShuffle %37 %45 %44 5 6 7 4
1112 OpStore %39 %46
1113 %48 = OpLoad %6 %8
1114 %49 = OpLoad %6 %10
1115 %100 = OpCompositeConstruct %12 %48 %48
1116 %101 = OpCompositeConstruct %12 %49 %49
1117 %50 = OpIAdd %6 %48 %49
1118 OpStore %47 %50
1119 %52 = OpLoad %6 %8
1120 %53 = OpLoad %6 %10
1121 %54 = OpISub %6 %52 %53
1122 OpStore %51 %54
1123 %56 = OpLoad %6 %8
1124 %57 = OpLoad %6 %10
1125 %58 = OpIMul %6 %56 %57
1126 OpStore %55 %58
1127 %60 = OpLoad %6 %8
1128 %61 = OpLoad %6 %10
1129 %62 = OpSDiv %6 %60 %61
1130 OpStore %59 %62
1131 %64 = OpLoad %18 %20
1132 %65 = OpLoad %18 %22
1133 %66 = OpIAdd %18 %64 %65
1134 OpStore %63 %66
1135 %68 = OpLoad %18 %20
1136 %69 = OpLoad %18 %22
1137 %103 = OpCompositeConstruct %24 %68 %68 %68
1138 %104 = OpCompositeConstruct %24 %69 %69 %69
1139 %70 = OpISub %18 %68 %69
1140 OpStore %67 %70
1141 %72 = OpLoad %18 %20
1142 %73 = OpLoad %18 %22
1143 %74 = OpIMul %18 %72 %73
1144 OpStore %71 %74
1145 %76 = OpLoad %18 %20
1146 %77 = OpLoad %18 %22
1147 %78 = OpUDiv %18 %76 %77
1148 OpStore %75 %78
1149 %80 = OpLoad %31 %33
1150 %81 = OpLoad %31 %35
1151 %82 = OpFAdd %31 %80 %81
1152 OpStore %79 %82
1153 %84 = OpLoad %31 %33
1154 %85 = OpLoad %31 %35
1155 %86 = OpFSub %31 %84 %85
1156 OpStore %83 %86
1157 %88 = OpLoad %31 %33
1158 %89 = OpLoad %31 %35
1159 %106 = OpCompositeConstruct %37 %88 %88 %88 %88
1160 %107 = OpCompositeConstruct %37 %89 %89 %89 %89
1161 %90 = OpFMul %31 %88 %89
1162 OpStore %87 %90
1163 %92 = OpLoad %31 %33
1164 %93 = OpLoad %31 %35
1165 %94 = OpFDiv %31 %92 %93
1166 OpStore %91 %94
1167 OpReturn
1168 OpFunctionEnd
1169 )";
1170 const auto env = SPV_ENV_UNIVERSAL_1_3;
1171 const auto consumer = nullptr;
1172 const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
1173 spvtools::ValidatorOptions validator_options;
1174
1175 // Check context validity.
1176 ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
1177 kConsoleMessageConsumer));
1178
1179 TransformationContext transformation_context(
1180 MakeUnique<FactManager>(context.get()), validator_options);
1181
1182 // Vec Type Id | Vector Type | Element Type id | Element Type |
1183 // ------------+----------------+------------------+-----------------+
1184 // 12 | vec2 | 6 | int64 |
1185 // 24 | vec3 | 18 | uint64 |
1186 // 37 | vec4 | 31 | float64 |
1187
1188 // Test support for 64-bit signed int.
1189 {
1190 // Assert that the target scalar instruction result id is relevant.
1191 ASSERT_FALSE(transformation_context.GetFactManager()->IdIsIrrelevant(50));
1192 transformation_context.GetFactManager()->AddFactDataSynonym(
1193 MakeDataDescriptor(100, {1}), MakeDataDescriptor(48, {}));
1194 transformation_context.GetFactManager()->AddFactDataSynonym(
1195 MakeDataDescriptor(101, {1}), MakeDataDescriptor(49, {}));
1196
1197 // Good: The following transformation should be applicable.
1198 TransformationWrapVectorSynonym wrap_add_int64(50, 100, 101, 102, 1);
1199 ASSERT_TRUE(
1200 wrap_add_int64.IsApplicable(context.get(), transformation_context));
1201 // Insert an arithmetic instruction of the same type to add two vectors.
1202 ApplyAndCheckFreshIds(wrap_add_int64, context.get(),
1203 &transformation_context);
1204
1205 // |instruction_id| and id at |scalar_position of the result vector should
1206 // be synonyms.
1207 ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
1208 MakeDataDescriptor(102, {1}), MakeDataDescriptor(50, {})));
1209 }
1210
1211 // Test support for 64-bit unsigned int.
1212 {
1213 ASSERT_FALSE(transformation_context.GetFactManager()->IdIsIrrelevant(70));
1214 transformation_context.GetFactManager()->AddFactDataSynonym(
1215 MakeDataDescriptor(103, {2}), MakeDataDescriptor(68, {}));
1216 transformation_context.GetFactManager()->AddFactDataSynonym(
1217 MakeDataDescriptor(104, {2}), MakeDataDescriptor(69, {}));
1218
1219 // Good: The following transformation should be applicable.
1220 TransformationWrapVectorSynonym wrap_sub_uint64(70, 103, 104, 105, 2);
1221 ASSERT_TRUE(
1222 wrap_sub_uint64.IsApplicable(context.get(), transformation_context));
1223
1224 ApplyAndCheckFreshIds(wrap_sub_uint64, context.get(),
1225 &transformation_context);
1226
1227 ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
1228 MakeDataDescriptor(105, {2}), MakeDataDescriptor(70, {})));
1229 }
1230
1231 // Test support for 64-bit float.
1232 {
1233 ASSERT_FALSE(transformation_context.GetFactManager()->IdIsIrrelevant(90));
1234 transformation_context.GetFactManager()->AddFactDataSynonym(
1235 MakeDataDescriptor(106, {3}), MakeDataDescriptor(88, {}));
1236 transformation_context.GetFactManager()->AddFactDataSynonym(
1237 MakeDataDescriptor(107, {3}), MakeDataDescriptor(89, {}));
1238
1239 // Good: The following transformation should be applicable.
1240 TransformationWrapVectorSynonym wrap_mul_float64(90, 106, 107, 108, 3);
1241 ASSERT_TRUE(
1242 wrap_mul_float64.IsApplicable(context.get(), transformation_context));
1243
1244 ApplyAndCheckFreshIds(wrap_mul_float64, context.get(),
1245 &transformation_context);
1246
1247 ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
1248 MakeDataDescriptor(108, {3}), MakeDataDescriptor(90, {})));
1249 }
1250
1251 std::string after_transformation = R"(
1252 OpCapability Shader
1253 OpCapability Int64
1254 OpCapability Float64
1255 %1 = OpExtInstImport "GLSL.std.450"
1256 OpMemoryModel Logical GLSL450
1257 OpEntryPoint Fragment %4 "main" %97
1258 OpExecutionMode %4 OriginUpperLeft
1259 OpSource ESSL 310
1260 OpName %4 "main"
1261 %2 = OpTypeVoid
1262 %3 = OpTypeFunction %2
1263 %6 = OpTypeInt 64 1
1264 %7 = OpTypePointer Function %6
1265 %9 = OpConstant %6 10
1266 %11 = OpConstant %6 -5
1267 %12 = OpTypeVector %6 2
1268 %13 = OpTypePointer Function %12
1269 %18 = OpTypeInt 64 0
1270 %19 = OpTypePointer Function %18
1271 %21 = OpConstant %18 8
1272 %23 = OpConstant %18 2
1273 %24 = OpTypeVector %18 3
1274 %25 = OpTypePointer Function %24
1275 %31 = OpTypeFloat 64
1276 %32 = OpTypePointer Function %31
1277 %34 = OpConstant %31 3.29999995
1278 %36 = OpConstant %31 1.10000002
1279 %37 = OpTypeVector %31 4
1280 %38 = OpTypePointer Function %37
1281 %96 = OpTypePointer Input %31
1282 %97 = OpVariable %96 Input
1283 %4 = OpFunction %2 None %3
1284 %5 = OpLabel
1285 %8 = OpVariable %7 Function
1286 %10 = OpVariable %7 Function
1287 %14 = OpVariable %13 Function
1288 %20 = OpVariable %19 Function
1289 %22 = OpVariable %19 Function
1290 %26 = OpVariable %25 Function
1291 %33 = OpVariable %32 Function
1292 %35 = OpVariable %32 Function
1293 %39 = OpVariable %38 Function
1294 %47 = OpVariable %7 Function
1295 %51 = OpVariable %7 Function
1296 %55 = OpVariable %7 Function
1297 %59 = OpVariable %7 Function
1298 %63 = OpVariable %19 Function
1299 %67 = OpVariable %19 Function
1300 %71 = OpVariable %19 Function
1301 %75 = OpVariable %19 Function
1302 %79 = OpVariable %32 Function
1303 %83 = OpVariable %32 Function
1304 %87 = OpVariable %32 Function
1305 %91 = OpVariable %32 Function
1306 OpStore %8 %9
1307 OpStore %10 %11
1308 %15 = OpLoad %6 %8
1309 %16 = OpLoad %6 %10
1310 %17 = OpCompositeConstruct %12 %15 %16
1311 OpStore %14 %17
1312 OpStore %20 %21
1313 OpStore %22 %23
1314 %27 = OpLoad %18 %20
1315 %28 = OpLoad %18 %20
1316 %29 = OpLoad %18 %22
1317 %30 = OpCompositeConstruct %24 %27 %28 %29
1318 OpStore %26 %30
1319 OpStore %33 %34
1320 OpStore %35 %36
1321 %40 = OpLoad %31 %33
1322 %41 = OpLoad %31 %33
1323 %42 = OpLoad %31 %35
1324 %43 = OpLoad %31 %35
1325 %44 = OpCompositeConstruct %37 %40 %41 %42 %43
1326 %45 = OpLoad %37 %39
1327 %46 = OpVectorShuffle %37 %45 %44 5 6 7 4
1328 OpStore %39 %46
1329 %48 = OpLoad %6 %8
1330 %49 = OpLoad %6 %10
1331 %100 = OpCompositeConstruct %12 %48 %48
1332 %101 = OpCompositeConstruct %12 %49 %49
1333 %102 = OpIAdd %12 %100 %101
1334 %50 = OpIAdd %6 %48 %49
1335 OpStore %47 %50
1336 %52 = OpLoad %6 %8
1337 %53 = OpLoad %6 %10
1338 %54 = OpISub %6 %52 %53
1339 OpStore %51 %54
1340 %56 = OpLoad %6 %8
1341 %57 = OpLoad %6 %10
1342 %58 = OpIMul %6 %56 %57
1343 OpStore %55 %58
1344 %60 = OpLoad %6 %8
1345 %61 = OpLoad %6 %10
1346 %62 = OpSDiv %6 %60 %61
1347 OpStore %59 %62
1348 %64 = OpLoad %18 %20
1349 %65 = OpLoad %18 %22
1350 %66 = OpIAdd %18 %64 %65
1351 OpStore %63 %66
1352 %68 = OpLoad %18 %20
1353 %69 = OpLoad %18 %22
1354 %103 = OpCompositeConstruct %24 %68 %68 %68
1355 %104 = OpCompositeConstruct %24 %69 %69 %69
1356 %105 = OpISub %24 %103 %104
1357 %70 = OpISub %18 %68 %69
1358 OpStore %67 %70
1359 %72 = OpLoad %18 %20
1360 %73 = OpLoad %18 %22
1361 %74 = OpIMul %18 %72 %73
1362 OpStore %71 %74
1363 %76 = OpLoad %18 %20
1364 %77 = OpLoad %18 %22
1365 %78 = OpUDiv %18 %76 %77
1366 OpStore %75 %78
1367 %80 = OpLoad %31 %33
1368 %81 = OpLoad %31 %35
1369 %82 = OpFAdd %31 %80 %81
1370 OpStore %79 %82
1371 %84 = OpLoad %31 %33
1372 %85 = OpLoad %31 %35
1373 %86 = OpFSub %31 %84 %85
1374 OpStore %83 %86
1375 %88 = OpLoad %31 %33
1376 %89 = OpLoad %31 %35
1377 %106 = OpCompositeConstruct %37 %88 %88 %88 %88
1378 %107 = OpCompositeConstruct %37 %89 %89 %89 %89
1379 %108 = OpFMul %37 %106 %107
1380 %90 = OpFMul %31 %88 %89
1381 OpStore %87 %90
1382 %92 = OpLoad %31 %33
1383 %93 = OpLoad %31 %35
1384 %94 = OpFDiv %31 %92 %93
1385 OpStore %91 %94
1386 OpReturn
1387 OpFunctionEnd
1388 )";
1389 ASSERT_TRUE(IsEqual(env, after_transformation, context.get()));
1390 }
1391
TEST(TransformationWrapVectorSynonym, DifferentVectorSignedness)1392 TEST(TransformationWrapVectorSynonym, DifferentVectorSignedness) {
1393 std::string shader = R"(
1394 OpCapability Shader
1395 %1 = OpExtInstImport "GLSL.std.450"
1396 OpMemoryModel Logical GLSL450
1397 OpEntryPoint Fragment %4 "main"
1398 OpExecutionMode %4 OriginUpperLeft
1399 OpSource ESSL 320
1400 %2 = OpTypeVoid
1401 %3 = OpTypeFunction %2
1402 %6 = OpTypeInt 32 1
1403 %7 = OpTypeVector %6 2
1404 %8 = OpTypePointer Function %7
1405 %10 = OpConstant %6 1
1406 %11 = OpConstant %6 0
1407 %12 = OpConstantComposite %7 %10 %11
1408 %14 = OpTypeInt 32 0
1409 %15 = OpTypeVector %14 2
1410 %18 = OpConstant %14 3
1411 %19 = OpConstant %14 0
1412 %20 = OpConstantComposite %15 %18 %19
1413 %21 = OpConstantComposite %15 %19 %18
1414 %4 = OpFunction %2 None %3
1415 %5 = OpLabel
1416 %100 = OpIAdd %14 %10 %18
1417 %101 = OpIAdd %6 %10 %18
1418 %102 = OpIAdd %6 %18 %19
1419 OpReturn
1420 OpFunctionEnd
1421 )";
1422 const auto env = SPV_ENV_UNIVERSAL_1_3;
1423 const auto consumer = nullptr;
1424 const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
1425 spvtools::ValidatorOptions validator_options;
1426
1427 // Check context validity.
1428 ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
1429 kConsoleMessageConsumer));
1430
1431 TransformationContext transformation_context(
1432 MakeUnique<FactManager>(context.get()), validator_options);
1433
1434 transformation_context.GetFactManager()->AddFactDataSynonym(
1435 MakeDataDescriptor(10, {}), MakeDataDescriptor(12, {0}));
1436 transformation_context.GetFactManager()->AddFactDataSynonym(
1437 MakeDataDescriptor(18, {}), MakeDataDescriptor(20, {0}));
1438 transformation_context.GetFactManager()->AddFactDataSynonym(
1439 MakeDataDescriptor(19, {}), MakeDataDescriptor(21, {0}));
1440
1441 {
1442 TransformationWrapVectorSynonym transformation1(100, 12, 20, 200, 0);
1443 ASSERT_TRUE(
1444 transformation1.IsApplicable(context.get(), transformation_context));
1445 ApplyAndCheckFreshIds(transformation1, context.get(),
1446 &transformation_context);
1447 ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
1448 MakeDataDescriptor(200, {0}), MakeDataDescriptor(100, {})));
1449 }
1450
1451 {
1452 TransformationWrapVectorSynonym transformation2(101, 12, 20, 201, 0);
1453 ASSERT_TRUE(
1454 transformation2.IsApplicable(context.get(), transformation_context));
1455 ApplyAndCheckFreshIds(transformation2, context.get(),
1456 &transformation_context);
1457 ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
1458 MakeDataDescriptor(201, {0}), MakeDataDescriptor(101, {})));
1459 }
1460
1461 {
1462 TransformationWrapVectorSynonym transformation3(102, 20, 21, 202, 0);
1463 ASSERT_TRUE(
1464 transformation3.IsApplicable(context.get(), transformation_context));
1465 ApplyAndCheckFreshIds(transformation3, context.get(),
1466 &transformation_context);
1467 ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
1468 MakeDataDescriptor(202, {0}), MakeDataDescriptor(102, {})));
1469 }
1470
1471 std::string after_transformation = R"(
1472 OpCapability Shader
1473 %1 = OpExtInstImport "GLSL.std.450"
1474 OpMemoryModel Logical GLSL450
1475 OpEntryPoint Fragment %4 "main"
1476 OpExecutionMode %4 OriginUpperLeft
1477 OpSource ESSL 320
1478 %2 = OpTypeVoid
1479 %3 = OpTypeFunction %2
1480 %6 = OpTypeInt 32 1
1481 %7 = OpTypeVector %6 2
1482 %8 = OpTypePointer Function %7
1483 %10 = OpConstant %6 1
1484 %11 = OpConstant %6 0
1485 %12 = OpConstantComposite %7 %10 %11
1486 %14 = OpTypeInt 32 0
1487 %15 = OpTypeVector %14 2
1488 %18 = OpConstant %14 3
1489 %19 = OpConstant %14 0
1490 %20 = OpConstantComposite %15 %18 %19
1491 %21 = OpConstantComposite %15 %19 %18
1492 %4 = OpFunction %2 None %3
1493 %5 = OpLabel
1494 %200 = OpIAdd %15 %12 %20
1495 %100 = OpIAdd %14 %10 %18
1496 %201 = OpIAdd %7 %12 %20
1497 %101 = OpIAdd %6 %10 %18
1498 %202 = OpIAdd %7 %20 %21
1499 %102 = OpIAdd %6 %18 %19
1500 OpReturn
1501 OpFunctionEnd
1502 )";
1503 ASSERT_TRUE(IsEqual(env, after_transformation, context.get()));
1504 }
1505
TEST(TransformationWrapVectorSynonym, SignednessDoesNotMatchResultType)1506 TEST(TransformationWrapVectorSynonym, SignednessDoesNotMatchResultType) {
1507 std::string shader = R"(
1508 OpCapability Shader
1509 %1 = OpExtInstImport "GLSL.std.450"
1510 OpMemoryModel Logical GLSL450
1511 OpEntryPoint Fragment %4 "main"
1512 OpExecutionMode %4 OriginUpperLeft
1513 OpSource ESSL 320
1514 %2 = OpTypeVoid
1515 %3 = OpTypeFunction %2
1516 %6 = OpTypeInt 32 1
1517 %7 = OpTypeVector %6 2
1518 %8 = OpTypePointer Function %7
1519 %10 = OpConstant %6 1
1520 %11 = OpConstant %6 0
1521 %12 = OpConstantComposite %7 %10 %11
1522 %13 = OpConstantComposite %7 %11 %10
1523 %14 = OpTypeInt 32 0
1524 %4 = OpFunction %2 None %3
1525 %5 = OpLabel
1526 %100 = OpIAdd %14 %10 %11
1527 OpReturn
1528 OpFunctionEnd
1529 )";
1530 const auto env = SPV_ENV_UNIVERSAL_1_3;
1531 const auto consumer = nullptr;
1532 const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
1533 spvtools::ValidatorOptions validator_options;
1534
1535 // Check context validity.
1536 ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
1537 kConsoleMessageConsumer));
1538
1539 TransformationContext transformation_context(
1540 MakeUnique<FactManager>(context.get()), validator_options);
1541
1542 transformation_context.GetFactManager()->AddFactDataSynonym(
1543 MakeDataDescriptor(10, {}), MakeDataDescriptor(12, {0}));
1544 transformation_context.GetFactManager()->AddFactDataSynonym(
1545 MakeDataDescriptor(11, {}), MakeDataDescriptor(13, {0}));
1546
1547 ASSERT_FALSE(TransformationWrapVectorSynonym(100, 12, 13, 200, 0)
1548 .IsApplicable(context.get(), transformation_context));
1549 }
1550
1551 } // namespace
1552 } // namespace fuzz
1553 } // namespace spvtools
1554