• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_vector_shuffle.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(TransformationVectorShuffleTest,BasicTest)26 TEST(TransformationVectorShuffleTest, BasicTest) {
27   std::string shader = R"(
28                OpCapability Shader
29           %1 = OpExtInstImport "GLSL.std.450"
30                OpMemoryModel Logical GLSL450
31                OpEntryPoint Fragment %4 "main"
32                OpExecutionMode %4 OriginUpperLeft
33                OpSource ESSL 310
34           %2 = OpTypeVoid
35           %3 = OpTypeFunction %2
36           %6 = OpTypeBool
37           %7 = OpTypeVector %6 2
38          %10 = OpConstantTrue %6
39          %11 = OpConstantFalse %6
40          %12 = OpConstantComposite %7 %10 %11
41         %112 = OpUndef %7
42          %13 = OpTypeVector %6 3
43          %16 = OpConstantComposite %13 %10 %11 %10
44          %17 = OpTypeVector %6 4
45          %20 = OpConstantComposite %17 %10 %11 %10 %11
46          %21 = OpTypeInt 32 1
47          %22 = OpTypeVector %21 2
48          %25 = OpConstant %21 1
49          %26 = OpConstant %21 0
50          %27 = OpConstantComposite %22 %25 %26
51          %28 = OpTypeVector %21 3
52          %31 = OpConstantComposite %28 %25 %26 %25
53          %32 = OpTypeVector %21 4
54          %33 = OpTypePointer Function %32
55          %35 = OpConstantComposite %32 %25 %26 %25 %26
56          %36 = OpTypeInt 32 0
57          %37 = OpTypeVector %36 2
58          %40 = OpConstant %36 1
59          %41 = OpConstant %36 0
60          %42 = OpConstantComposite %37 %40 %41
61          %43 = OpTypeVector %36 3
62          %46 = OpConstantComposite %43 %40 %41 %40
63          %47 = OpTypeVector %36 4
64          %50 = OpConstantComposite %47 %40 %41 %40 %41
65          %51 = OpTypeFloat 32
66          %55 = OpConstant %51 1
67          %56 = OpConstant %51 0
68          %58 = OpTypeVector %51 3
69          %61 = OpConstantComposite %58 %55 %56 %55
70          %62 = OpTypeVector %51 4
71          %65 = OpConstantComposite %62 %55 %56 %55 %56
72           %4 = OpFunction %2 None %3
73           %5 = OpLabel
74                OpSelectionMerge %100 None
75                OpBranchConditional %10 %101 %102
76         %101 = OpLabel
77         %103 = OpCompositeConstruct %62 %55 %55 %55 %56
78                OpBranch %100
79         %102 = OpLabel
80                OpBranch %100
81         %100 = OpLabel
82                OpReturn
83                OpFunctionEnd
84   )";
85 
86   const auto env = SPV_ENV_UNIVERSAL_1_4;
87   const auto consumer = nullptr;
88   const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
89   spvtools::ValidatorOptions validator_options;
90   ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
91                                                kConsoleMessageConsumer));
92   TransformationContext transformation_context(
93       MakeUnique<FactManager>(context.get()), validator_options);
94   transformation_context.GetFactManager()->AddFactDataSynonym(
95       MakeDataDescriptor(10, {}), MakeDataDescriptor(12, {0}));
96   transformation_context.GetFactManager()->AddFactDataSynonym(
97       MakeDataDescriptor(11, {}), MakeDataDescriptor(12, {1}));
98 
99   transformation_context.GetFactManager()->AddFactDataSynonym(
100       MakeDataDescriptor(10, {}), MakeDataDescriptor(16, {0}));
101   transformation_context.GetFactManager()->AddFactDataSynonym(
102       MakeDataDescriptor(11, {}), MakeDataDescriptor(16, {1}));
103   transformation_context.GetFactManager()->AddFactDataSynonym(
104       MakeDataDescriptor(10, {}), MakeDataDescriptor(16, {2}));
105 
106   transformation_context.GetFactManager()->AddFactDataSynonym(
107       MakeDataDescriptor(10, {}), MakeDataDescriptor(20, {0}));
108   transformation_context.GetFactManager()->AddFactDataSynonym(
109       MakeDataDescriptor(11, {}), MakeDataDescriptor(20, {1}));
110   transformation_context.GetFactManager()->AddFactDataSynonym(
111       MakeDataDescriptor(10, {}), MakeDataDescriptor(20, {2}));
112   transformation_context.GetFactManager()->AddFactDataSynonym(
113       MakeDataDescriptor(11, {}), MakeDataDescriptor(20, {3}));
114 
115   transformation_context.GetFactManager()->AddFactDataSynonym(
116       MakeDataDescriptor(25, {}), MakeDataDescriptor(27, {0}));
117   transformation_context.GetFactManager()->AddFactDataSynonym(
118       MakeDataDescriptor(26, {}), MakeDataDescriptor(27, {1}));
119 
120   transformation_context.GetFactManager()->AddFactDataSynonym(
121       MakeDataDescriptor(25, {}), MakeDataDescriptor(31, {0}));
122   transformation_context.GetFactManager()->AddFactDataSynonym(
123       MakeDataDescriptor(26, {}), MakeDataDescriptor(31, {1}));
124   transformation_context.GetFactManager()->AddFactDataSynonym(
125       MakeDataDescriptor(25, {}), MakeDataDescriptor(31, {2}));
126 
127   transformation_context.GetFactManager()->AddFactDataSynonym(
128       MakeDataDescriptor(25, {}), MakeDataDescriptor(35, {0}));
129   transformation_context.GetFactManager()->AddFactDataSynonym(
130       MakeDataDescriptor(26, {}), MakeDataDescriptor(35, {1}));
131   transformation_context.GetFactManager()->AddFactDataSynonym(
132       MakeDataDescriptor(25, {}), MakeDataDescriptor(35, {2}));
133   transformation_context.GetFactManager()->AddFactDataSynonym(
134       MakeDataDescriptor(26, {}), MakeDataDescriptor(35, {3}));
135 
136   transformation_context.GetFactManager()->AddFactDataSynonym(
137       MakeDataDescriptor(40, {}), MakeDataDescriptor(42, {0}));
138   transformation_context.GetFactManager()->AddFactDataSynonym(
139       MakeDataDescriptor(41, {}), MakeDataDescriptor(42, {1}));
140 
141   transformation_context.GetFactManager()->AddFactDataSynonym(
142       MakeDataDescriptor(40, {}), MakeDataDescriptor(46, {0}));
143   transformation_context.GetFactManager()->AddFactDataSynonym(
144       MakeDataDescriptor(41, {}), MakeDataDescriptor(46, {1}));
145   transformation_context.GetFactManager()->AddFactDataSynonym(
146       MakeDataDescriptor(40, {}), MakeDataDescriptor(46, {2}));
147 
148   transformation_context.GetFactManager()->AddFactDataSynonym(
149       MakeDataDescriptor(40, {}), MakeDataDescriptor(50, {0}));
150   transformation_context.GetFactManager()->AddFactDataSynonym(
151       MakeDataDescriptor(41, {}), MakeDataDescriptor(50, {1}));
152   transformation_context.GetFactManager()->AddFactDataSynonym(
153       MakeDataDescriptor(40, {}), MakeDataDescriptor(50, {2}));
154   transformation_context.GetFactManager()->AddFactDataSynonym(
155       MakeDataDescriptor(41, {}), MakeDataDescriptor(50, {3}));
156 
157   transformation_context.GetFactManager()->AddFactDataSynonym(
158       MakeDataDescriptor(55, {}), MakeDataDescriptor(61, {0}));
159   transformation_context.GetFactManager()->AddFactDataSynonym(
160       MakeDataDescriptor(56, {}), MakeDataDescriptor(61, {1}));
161   transformation_context.GetFactManager()->AddFactDataSynonym(
162       MakeDataDescriptor(55, {}), MakeDataDescriptor(61, {2}));
163 
164   transformation_context.GetFactManager()->AddFactDataSynonym(
165       MakeDataDescriptor(55, {}), MakeDataDescriptor(65, {0}));
166   transformation_context.GetFactManager()->AddFactDataSynonym(
167       MakeDataDescriptor(56, {}), MakeDataDescriptor(65, {1}));
168   transformation_context.GetFactManager()->AddFactDataSynonym(
169       MakeDataDescriptor(55, {}), MakeDataDescriptor(65, {2}));
170   transformation_context.GetFactManager()->AddFactDataSynonym(
171       MakeDataDescriptor(56, {}), MakeDataDescriptor(65, {3}));
172 
173   // %103 does not dominate the return instruction.
174   ASSERT_FALSE(TransformationVectorShuffle(
175                    MakeInstructionDescriptor(100, SpvOpReturn, 0), 200, 103, 65,
176                    {3, 5, 7})
177                    .IsApplicable(context.get(), transformation_context));
178 
179   // Illegal to shuffle a bvec2 and a vec3
180   ASSERT_FALSE(TransformationVectorShuffle(
181                    MakeInstructionDescriptor(100, SpvOpReturn, 0), 200, 112, 61,
182                    {0, 2, 4})
183                    .IsApplicable(context.get(), transformation_context));
184 
185   // Illegal to shuffle an ivec2 and a uvec4
186   ASSERT_FALSE(TransformationVectorShuffle(
187                    MakeInstructionDescriptor(100, SpvOpReturn, 0), 200, 27, 50,
188                    {1, 3, 5})
189                    .IsApplicable(context.get(), transformation_context));
190 
191   // Vector 1 does not exist
192   ASSERT_FALSE(TransformationVectorShuffle(
193                    MakeInstructionDescriptor(100, SpvOpReturn, 0), 200, 300, 50,
194                    {1, 3, 5})
195                    .IsApplicable(context.get(), transformation_context));
196 
197   // Vector 2 does not exist
198   ASSERT_FALSE(TransformationVectorShuffle(
199                    MakeInstructionDescriptor(100, SpvOpReturn, 0), 200, 27, 300,
200                    {1, 3, 5})
201                    .IsApplicable(context.get(), transformation_context));
202 
203   // Index out of range
204   ASSERT_FALSE(
205       TransformationVectorShuffle(
206           MakeInstructionDescriptor(100, SpvOpReturn, 0), 200, 12, 112, {0, 20})
207           .IsApplicable(context.get(), transformation_context));
208 
209   // Too many indices
210   ASSERT_FALSE(TransformationVectorShuffle(
211                    MakeInstructionDescriptor(100, SpvOpReturn, 0), 200, 12, 112,
212                    {0, 1, 0, 1, 0, 1, 0, 1})
213                    .IsApplicable(context.get(), transformation_context));
214 
215   // Too few indices
216   ASSERT_FALSE(
217       TransformationVectorShuffle(
218           MakeInstructionDescriptor(100, SpvOpReturn, 0), 200, 12, 112, {})
219           .IsApplicable(context.get(), transformation_context));
220 
221   // Too few indices again
222   ASSERT_FALSE(
223       TransformationVectorShuffle(
224           MakeInstructionDescriptor(100, SpvOpReturn, 0), 200, 12, 112, {0})
225           .IsApplicable(context.get(), transformation_context));
226 
227   // Indices define unknown type: we do not have vec2
228   ASSERT_FALSE(
229       TransformationVectorShuffle(
230           MakeInstructionDescriptor(100, SpvOpReturn, 0), 200, 65, 65, {0, 1})
231           .IsApplicable(context.get(), transformation_context));
232 
233   // The instruction to insert before does not exist
234   ASSERT_FALSE(TransformationVectorShuffle(
235                    MakeInstructionDescriptor(100, SpvOpCompositeConstruct, 1),
236                    201, 20, 12, {0xFFFFFFFF, 3, 5})
237                    .IsApplicable(context.get(), transformation_context));
238 
239   // The 'fresh' id is already in use
240   ASSERT_FALSE(
241       TransformationVectorShuffle(
242           MakeInstructionDescriptor(100, SpvOpReturn, 0), 12, 12, 112, {})
243           .IsApplicable(context.get(), transformation_context));
244 
245   protobufs::DataDescriptor temp_dd;
246 
247   TransformationVectorShuffle transformation1(
248       MakeInstructionDescriptor(100, SpvOpReturn, 0), 200, 12, 112, {1, 0});
249   ASSERT_TRUE(
250       transformation1.IsApplicable(context.get(), transformation_context));
251   ApplyAndCheckFreshIds(transformation1, context.get(),
252                         &transformation_context);
253   temp_dd = MakeDataDescriptor(200, {0});
254   ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
255       MakeDataDescriptor(11, {}), temp_dd));
256   temp_dd = MakeDataDescriptor(200, {1});
257   ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
258       MakeDataDescriptor(10, {}), temp_dd));
259 
260   TransformationVectorShuffle transformation2(
261       MakeInstructionDescriptor(100, SpvOpReturn, 0), 201, 20, 12,
262       {0xFFFFFFFF, 3, 5});
263   ASSERT_TRUE(
264       transformation2.IsApplicable(context.get(), transformation_context));
265   ApplyAndCheckFreshIds(transformation2, context.get(),
266                         &transformation_context);
267   temp_dd = MakeDataDescriptor(201, {1});
268   ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
269       MakeDataDescriptor(11, {}), temp_dd));
270   temp_dd = MakeDataDescriptor(201, {2});
271   ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
272       MakeDataDescriptor(11, {}), temp_dd));
273 
274   TransformationVectorShuffle transformation3(
275       MakeInstructionDescriptor(100, SpvOpReturn, 0), 202, 27, 35, {5, 4, 1});
276   ASSERT_TRUE(
277       transformation3.IsApplicable(context.get(), transformation_context));
278   ApplyAndCheckFreshIds(transformation3, context.get(),
279                         &transformation_context);
280   temp_dd = MakeDataDescriptor(202, {0});
281   ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
282       MakeDataDescriptor(26, {}), temp_dd));
283   temp_dd = MakeDataDescriptor(202, {1});
284   ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
285       MakeDataDescriptor(25, {}), temp_dd));
286   temp_dd = MakeDataDescriptor(202, {2});
287   ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
288       MakeDataDescriptor(26, {}), temp_dd));
289 
290   TransformationVectorShuffle transformation4(
291       MakeInstructionDescriptor(100, SpvOpReturn, 0), 203, 42, 46, {0, 1});
292   ASSERT_TRUE(
293       transformation4.IsApplicable(context.get(), transformation_context));
294   ApplyAndCheckFreshIds(transformation4, context.get(),
295                         &transformation_context);
296   temp_dd = MakeDataDescriptor(203, {0});
297   ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
298       MakeDataDescriptor(40, {}), temp_dd));
299   temp_dd = MakeDataDescriptor(203, {1});
300   ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
301       MakeDataDescriptor(41, {}), temp_dd));
302 
303   TransformationVectorShuffle transformation5(
304       MakeInstructionDescriptor(100, SpvOpReturn, 0), 204, 42, 46, {2, 3, 4});
305   ASSERT_TRUE(
306       transformation5.IsApplicable(context.get(), transformation_context));
307   ApplyAndCheckFreshIds(transformation5, context.get(),
308                         &transformation_context);
309   temp_dd = MakeDataDescriptor(204, {0});
310   ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
311       MakeDataDescriptor(40, {}), temp_dd));
312   temp_dd = MakeDataDescriptor(204, {1});
313   ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
314       MakeDataDescriptor(41, {}), temp_dd));
315   temp_dd = MakeDataDescriptor(204, {2});
316   ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
317       MakeDataDescriptor(40, {}), temp_dd));
318 
319   TransformationVectorShuffle transformation6(
320       MakeInstructionDescriptor(100, SpvOpReturn, 0), 205, 42, 42,
321       {0, 1, 2, 3});
322   ASSERT_TRUE(
323       transformation6.IsApplicable(context.get(), transformation_context));
324   ApplyAndCheckFreshIds(transformation6, context.get(),
325                         &transformation_context);
326   temp_dd = MakeDataDescriptor(205, {0});
327   ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
328       MakeDataDescriptor(40, {}), temp_dd));
329   temp_dd = MakeDataDescriptor(205, {1});
330   ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
331       MakeDataDescriptor(41, {}), temp_dd));
332   temp_dd = MakeDataDescriptor(205, {2});
333   ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
334       MakeDataDescriptor(40, {}), temp_dd));
335   temp_dd = MakeDataDescriptor(205, {3});
336   ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
337       MakeDataDescriptor(41, {}), temp_dd));
338 
339   // swizzle vec4 from vec4 and vec4 using some undefs
340   TransformationVectorShuffle transformation7(
341       MakeInstructionDescriptor(100, SpvOpReturn, 0), 206, 65, 65,
342       {0xFFFFFFFF, 3, 6, 0xFFFFFFFF});
343   ASSERT_TRUE(
344       transformation7.IsApplicable(context.get(), transformation_context));
345   ApplyAndCheckFreshIds(transformation7, context.get(),
346                         &transformation_context);
347   temp_dd = MakeDataDescriptor(206, {1});
348   ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
349       MakeDataDescriptor(56, {}), temp_dd));
350 
351   std::string after_transformation = R"(
352                OpCapability Shader
353           %1 = OpExtInstImport "GLSL.std.450"
354                OpMemoryModel Logical GLSL450
355                OpEntryPoint Fragment %4 "main"
356                OpExecutionMode %4 OriginUpperLeft
357                OpSource ESSL 310
358           %2 = OpTypeVoid
359           %3 = OpTypeFunction %2
360           %6 = OpTypeBool
361           %7 = OpTypeVector %6 2
362          %10 = OpConstantTrue %6
363          %11 = OpConstantFalse %6
364          %12 = OpConstantComposite %7 %10 %11
365         %112 = OpUndef %7
366          %13 = OpTypeVector %6 3
367          %16 = OpConstantComposite %13 %10 %11 %10
368          %17 = OpTypeVector %6 4
369          %20 = OpConstantComposite %17 %10 %11 %10 %11
370          %21 = OpTypeInt 32 1
371          %22 = OpTypeVector %21 2
372          %25 = OpConstant %21 1
373          %26 = OpConstant %21 0
374          %27 = OpConstantComposite %22 %25 %26
375          %28 = OpTypeVector %21 3
376          %31 = OpConstantComposite %28 %25 %26 %25
377          %32 = OpTypeVector %21 4
378          %33 = OpTypePointer Function %32
379          %35 = OpConstantComposite %32 %25 %26 %25 %26
380          %36 = OpTypeInt 32 0
381          %37 = OpTypeVector %36 2
382          %40 = OpConstant %36 1
383          %41 = OpConstant %36 0
384          %42 = OpConstantComposite %37 %40 %41
385          %43 = OpTypeVector %36 3
386          %46 = OpConstantComposite %43 %40 %41 %40
387          %47 = OpTypeVector %36 4
388          %50 = OpConstantComposite %47 %40 %41 %40 %41
389          %51 = OpTypeFloat 32
390          %55 = OpConstant %51 1
391          %56 = OpConstant %51 0
392          %58 = OpTypeVector %51 3
393          %61 = OpConstantComposite %58 %55 %56 %55
394          %62 = OpTypeVector %51 4
395          %65 = OpConstantComposite %62 %55 %56 %55 %56
396           %4 = OpFunction %2 None %3
397           %5 = OpLabel
398                OpSelectionMerge %100 None
399                OpBranchConditional %10 %101 %102
400         %101 = OpLabel
401         %103 = OpCompositeConstruct %62 %55 %55 %55 %56
402                OpBranch %100
403         %102 = OpLabel
404                OpBranch %100
405         %100 = OpLabel
406         %200 = OpVectorShuffle %7 %12 %112 1 0
407         %201 = OpVectorShuffle %13 %20 %12 0xFFFFFFFF 3 5
408         %202 = OpVectorShuffle %28 %27 %35 5 4 1
409         %203 = OpVectorShuffle %37 %42 %46 0 1
410         %204 = OpVectorShuffle %43 %42 %46 2 3 4
411         %205 = OpVectorShuffle %47 %42 %42 0 1 2 3
412         %206 = OpVectorShuffle %62 %65 %65 0xFFFFFFFF 3 6 0xFFFFFFFF
413                OpReturn
414                OpFunctionEnd
415   )";
416   ASSERT_TRUE(IsEqual(env, after_transformation, context.get()));
417 }
418 
TEST(TransformationVectorShuffleTest,IllegalInsertionPoints)419 TEST(TransformationVectorShuffleTest, IllegalInsertionPoints) {
420   std::string shader = R"(
421                OpCapability Shader
422           %1 = OpExtInstImport "GLSL.std.450"
423                OpMemoryModel Logical GLSL450
424                OpEntryPoint Fragment %4 "main" %51 %27
425                OpExecutionMode %4 OriginUpperLeft
426                OpSource ESSL 310
427                OpName %4 "main"
428                OpName %25 "buf"
429                OpMemberName %25 0 "value"
430                OpName %27 ""
431                OpName %51 "color"
432                OpMemberDecorate %25 0 Offset 0
433                OpDecorate %25 Block
434                OpDecorate %27 DescriptorSet 0
435                OpDecorate %27 Binding 0
436                OpDecorate %51 Location 0
437           %2 = OpTypeVoid
438           %3 = OpTypeFunction %2
439           %6 = OpTypeFloat 32
440           %7 = OpTypeVector %6 4
441         %150 = OpTypeVector %6 2
442          %10 = OpConstant %6 0.300000012
443          %11 = OpConstant %6 0.400000006
444          %12 = OpConstant %6 0.5
445          %13 = OpConstant %6 1
446          %14 = OpConstantComposite %7 %10 %11 %12 %13
447          %15 = OpTypeInt 32 1
448          %18 = OpConstant %15 0
449          %25 = OpTypeStruct %6
450          %26 = OpTypePointer Uniform %25
451          %27 = OpVariable %26 Uniform
452          %28 = OpTypePointer Uniform %6
453          %32 = OpTypeBool
454         %103 = OpConstantTrue %32
455          %34 = OpConstant %6 0.100000001
456          %48 = OpConstant %15 1
457          %50 = OpTypePointer Output %7
458          %51 = OpVariable %50 Output
459         %100 = OpTypePointer Function %6
460           %4 = OpFunction %2 None %3
461           %5 = OpLabel
462         %101 = OpVariable %100 Function
463         %102 = OpVariable %100 Function
464                OpBranch %19
465          %19 = OpLabel
466          %60 = OpPhi %7 %14 %5 %58 %20
467          %59 = OpPhi %15 %18 %5 %49 %20
468          %29 = OpAccessChain %28 %27 %18
469          %30 = OpLoad %6 %29
470          %31 = OpConvertFToS %15 %30
471          %33 = OpSLessThan %32 %59 %31
472                OpLoopMerge %21 %20 None
473                OpBranchConditional %33 %20 %21
474          %20 = OpLabel
475          %39 = OpCompositeExtract %6 %60 0
476          %40 = OpFAdd %6 %39 %34
477          %55 = OpCompositeInsert %7 %40 %60 0
478          %44 = OpCompositeExtract %6 %60 1
479          %45 = OpFSub %6 %44 %34
480          %58 = OpCompositeInsert %7 %45 %55 1
481          %49 = OpIAdd %15 %59 %48
482                OpBranch %19
483          %21 = OpLabel
484                OpStore %51 %60
485                OpSelectionMerge %105 None
486                OpBranchConditional %103 %104 %105
487         %104 = OpLabel
488                OpBranch %105
489         %105 = OpLabel
490                OpReturn
491                OpFunctionEnd
492   )";
493 
494   const auto env = SPV_ENV_UNIVERSAL_1_4;
495   const auto consumer = nullptr;
496   const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
497   spvtools::ValidatorOptions validator_options;
498   ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
499                                                kConsoleMessageConsumer));
500   TransformationContext transformation_context(
501       MakeUnique<FactManager>(context.get()), validator_options);
502   // Cannot insert before the OpVariables of a function.
503   ASSERT_FALSE(
504       TransformationVectorShuffle(
505           MakeInstructionDescriptor(101, SpvOpVariable, 0), 200, 14, 14, {0, 1})
506           .IsApplicable(context.get(), transformation_context));
507   ASSERT_FALSE(
508       TransformationVectorShuffle(
509           MakeInstructionDescriptor(101, SpvOpVariable, 1), 200, 14, 14, {1, 2})
510           .IsApplicable(context.get(), transformation_context));
511   ASSERT_FALSE(
512       TransformationVectorShuffle(
513           MakeInstructionDescriptor(102, SpvOpVariable, 0), 200, 14, 14, {1, 2})
514           .IsApplicable(context.get(), transformation_context));
515   // OK to insert right after the OpVariables.
516   ASSERT_FALSE(
517       TransformationVectorShuffle(
518           MakeInstructionDescriptor(102, SpvOpBranch, 1), 200, 14, 14, {1, 1})
519           .IsApplicable(context.get(), transformation_context));
520 
521   // Cannot insert before the OpPhis of a block.
522   ASSERT_FALSE(
523       TransformationVectorShuffle(MakeInstructionDescriptor(60, SpvOpPhi, 0),
524                                   200, 14, 14, {2, 0})
525           .IsApplicable(context.get(), transformation_context));
526   ASSERT_FALSE(
527       TransformationVectorShuffle(MakeInstructionDescriptor(59, SpvOpPhi, 0),
528                                   200, 14, 14, {3, 0})
529           .IsApplicable(context.get(), transformation_context));
530   // OK to insert after the OpPhis.
531   ASSERT_TRUE(TransformationVectorShuffle(
532                   MakeInstructionDescriptor(59, SpvOpAccessChain, 0), 200, 14,
533                   14, {3, 4})
534                   .IsApplicable(context.get(), transformation_context));
535 
536   // Cannot insert before OpLoopMerge
537   ASSERT_FALSE(TransformationVectorShuffle(
538                    MakeInstructionDescriptor(33, SpvOpBranchConditional, 0),
539                    200, 14, 14, {3})
540                    .IsApplicable(context.get(), transformation_context));
541 
542   // Cannot insert before OpSelectionMerge
543   ASSERT_FALSE(TransformationVectorShuffle(
544                    MakeInstructionDescriptor(21, SpvOpBranchConditional, 0),
545                    200, 14, 14, {2})
546                    .IsApplicable(context.get(), transformation_context));
547 }
548 
TEST(TransformationVectorShuffleTest,HandlesIrrelevantIds1)549 TEST(TransformationVectorShuffleTest, HandlesIrrelevantIds1) {
550   std::string shader = R"(
551                OpCapability Shader
552           %1 = OpExtInstImport "GLSL.std.450"
553                OpMemoryModel Logical GLSL450
554                OpEntryPoint Fragment %4 "main"
555                OpExecutionMode %4 OriginUpperLeft
556                OpSource ESSL 310
557           %2 = OpTypeVoid
558           %3 = OpTypeFunction %2
559           %6 = OpTypeBool
560           %7 = OpTypeVector %6 2
561          %10 = OpConstantTrue %6
562          %11 = OpConstantFalse %6
563          %12 = OpConstantComposite %7 %10 %11
564         %112 = OpConstantComposite %7 %11 %10
565          %13 = OpTypeVector %6 3
566          %16 = OpConstantComposite %13 %10 %11 %10
567          %17 = OpTypeVector %6 4
568          %20 = OpConstantComposite %17 %10 %11 %10 %11
569          %21 = OpTypeInt 32 1
570          %22 = OpTypeVector %21 2
571          %25 = OpConstant %21 1
572          %26 = OpConstant %21 0
573          %27 = OpConstantComposite %22 %25 %26
574          %28 = OpTypeVector %21 3
575          %31 = OpConstantComposite %28 %25 %26 %25
576          %32 = OpTypeVector %21 4
577          %33 = OpTypePointer Function %32
578          %35 = OpConstantComposite %32 %25 %26 %25 %26
579          %36 = OpTypeInt 32 0
580          %37 = OpTypeVector %36 2
581          %40 = OpConstant %36 1
582          %41 = OpConstant %36 0
583          %42 = OpConstantComposite %37 %40 %41
584          %43 = OpTypeVector %36 3
585          %46 = OpConstantComposite %43 %40 %41 %40
586          %47 = OpTypeVector %36 4
587          %50 = OpConstantComposite %47 %40 %41 %40 %41
588          %51 = OpTypeFloat 32
589          %55 = OpConstant %51 1
590          %56 = OpConstant %51 0
591          %58 = OpTypeVector %51 3
592          %61 = OpConstantComposite %58 %55 %56 %55
593          %62 = OpTypeVector %51 4
594          %65 = OpConstantComposite %62 %55 %56 %55 %56
595           %4 = OpFunction %2 None %3
596           %5 = OpLabel
597                OpSelectionMerge %100 None
598                OpBranchConditional %10 %101 %102
599         %101 = OpLabel
600         %103 = OpCompositeConstruct %62 %55 %55 %55 %56
601                OpBranch %100
602         %102 = OpLabel
603                OpBranch %100
604         %100 = OpLabel
605                OpReturn
606                OpFunctionEnd
607   )";
608 
609   const auto env = SPV_ENV_UNIVERSAL_1_4;
610   const auto consumer = nullptr;
611   const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
612   spvtools::ValidatorOptions validator_options;
613   ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
614                                                kConsoleMessageConsumer));
615   TransformationContext transformation_context(
616       MakeUnique<FactManager>(context.get()), validator_options);
617   TransformationVectorShuffle transformation(
618       MakeInstructionDescriptor(100, SpvOpReturn, 0), 200, 12, 112, {2, 0});
619   ASSERT_TRUE(
620       transformation.IsApplicable(context.get(), transformation_context));
621   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
622   ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
623                                                kConsoleMessageConsumer));
624   ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
625       MakeDataDescriptor(12, {0}), MakeDataDescriptor(200, {1})));
626   ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
627       MakeDataDescriptor(112, {0}), MakeDataDescriptor(200, {0})));
628 }
629 
TEST(TransformationVectorShuffleTest,HandlesIrrelevantIds2)630 TEST(TransformationVectorShuffleTest, HandlesIrrelevantIds2) {
631   std::string shader = R"(
632                OpCapability Shader
633           %1 = OpExtInstImport "GLSL.std.450"
634                OpMemoryModel Logical GLSL450
635                OpEntryPoint Fragment %4 "main"
636                OpExecutionMode %4 OriginUpperLeft
637                OpSource ESSL 310
638           %2 = OpTypeVoid
639           %3 = OpTypeFunction %2
640           %6 = OpTypeBool
641           %7 = OpTypeVector %6 2
642          %10 = OpConstantTrue %6
643          %11 = OpConstantFalse %6
644          %12 = OpConstantComposite %7 %10 %11
645         %112 = OpConstantComposite %7 %11 %10
646          %13 = OpTypeVector %6 3
647          %16 = OpConstantComposite %13 %10 %11 %10
648          %17 = OpTypeVector %6 4
649          %20 = OpConstantComposite %17 %10 %11 %10 %11
650          %21 = OpTypeInt 32 1
651          %22 = OpTypeVector %21 2
652          %25 = OpConstant %21 1
653          %26 = OpConstant %21 0
654          %27 = OpConstantComposite %22 %25 %26
655          %28 = OpTypeVector %21 3
656          %31 = OpConstantComposite %28 %25 %26 %25
657          %32 = OpTypeVector %21 4
658          %33 = OpTypePointer Function %32
659          %35 = OpConstantComposite %32 %25 %26 %25 %26
660          %36 = OpTypeInt 32 0
661          %37 = OpTypeVector %36 2
662          %40 = OpConstant %36 1
663          %41 = OpConstant %36 0
664          %42 = OpConstantComposite %37 %40 %41
665          %43 = OpTypeVector %36 3
666          %46 = OpConstantComposite %43 %40 %41 %40
667          %47 = OpTypeVector %36 4
668          %50 = OpConstantComposite %47 %40 %41 %40 %41
669          %51 = OpTypeFloat 32
670          %55 = OpConstant %51 1
671          %56 = OpConstant %51 0
672          %58 = OpTypeVector %51 3
673          %61 = OpConstantComposite %58 %55 %56 %55
674          %62 = OpTypeVector %51 4
675          %65 = OpConstantComposite %62 %55 %56 %55 %56
676           %4 = OpFunction %2 None %3
677           %5 = OpLabel
678                OpSelectionMerge %100 None
679                OpBranchConditional %10 %101 %102
680         %101 = OpLabel
681         %103 = OpCompositeConstruct %62 %55 %55 %55 %56
682                OpBranch %100
683         %102 = OpLabel
684                OpBranch %100
685         %100 = OpLabel
686                OpReturn
687                OpFunctionEnd
688   )";
689 
690   const auto env = SPV_ENV_UNIVERSAL_1_4;
691   const auto consumer = nullptr;
692   const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
693   spvtools::ValidatorOptions validator_options;
694   ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
695                                                kConsoleMessageConsumer));
696   TransformationContext transformation_context(
697       MakeUnique<FactManager>(context.get()), validator_options);
698   transformation_context.GetFactManager()->AddFactIdIsIrrelevant(112);
699   TransformationVectorShuffle transformation(
700       MakeInstructionDescriptor(100, SpvOpReturn, 0), 200, 12, 112, {2, 0});
701   ASSERT_TRUE(
702       transformation.IsApplicable(context.get(), transformation_context));
703   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
704   ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
705                                                kConsoleMessageConsumer));
706   // Because %12 is not irrelevant, we get a synonym between it and %200[1].
707   ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
708       MakeDataDescriptor(12, {0}), MakeDataDescriptor(200, {1})));
709   // Because %112 is irrelevant, we do not get a synonym between it and %200[0].
710   ASSERT_FALSE(transformation_context.GetFactManager()->IsSynonymous(
711       MakeDataDescriptor(112, {0}), MakeDataDescriptor(200, {0})));
712 }
713 
TEST(TransformationVectorShuffleTest,HandlesIrrelevantIds3)714 TEST(TransformationVectorShuffleTest, HandlesIrrelevantIds3) {
715   std::string shader = R"(
716                OpCapability Shader
717           %1 = OpExtInstImport "GLSL.std.450"
718                OpMemoryModel Logical GLSL450
719                OpEntryPoint Fragment %4 "main"
720                OpExecutionMode %4 OriginUpperLeft
721                OpSource ESSL 320
722           %2 = OpTypeVoid
723           %3 = OpTypeFunction %2
724           %6 = OpTypeInt 32 1
725           %7 = OpTypeVector %6 2
726           %8 = OpTypePointer Function %7
727          %10 = OpConstant %6 0
728          %11 = OpConstant %6 1
729          %12 = OpConstantComposite %7 %10 %11
730          %40 = OpConstantComposite %7 %10 %11
731          %13 = OpTypeBool
732          %14 = OpConstantFalse %13
733           %4 = OpFunction %2 None %3
734           %5 = OpLabel
735           %9 = OpVariable %8 Function
736                OpStore %9 %12
737                OpSelectionMerge %16 None
738                OpBranchConditional %14 %15 %16
739          %15 = OpLabel
740                OpBranch %16
741          %16 = OpLabel
742                OpReturn
743                OpFunctionEnd
744   )";
745 
746   const auto env = SPV_ENV_UNIVERSAL_1_4;
747   const auto consumer = nullptr;
748   const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
749   spvtools::ValidatorOptions validator_options;
750   ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
751                                                kConsoleMessageConsumer));
752   TransformationContext transformation_context(
753       MakeUnique<FactManager>(context.get()), validator_options);
754   transformation_context.GetFactManager()->AddFactIdIsIrrelevant(40);
755   transformation_context.GetFactManager()->AddFactBlockIsDead(15);
756 
757   TransformationVectorShuffle transformation1(
758       MakeInstructionDescriptor(15, SpvOpBranch, 0), 200, 12, 12, {0, 3});
759   ASSERT_TRUE(
760       transformation1.IsApplicable(context.get(), transformation_context));
761   ApplyAndCheckFreshIds(transformation1, context.get(),
762                         &transformation_context);
763   ASSERT_FALSE(transformation_context.GetFactManager()->IsSynonymous(
764       MakeDataDescriptor(200, {0}), MakeDataDescriptor(12, {0})));
765   ASSERT_FALSE(transformation_context.GetFactManager()->IsSynonymous(
766       MakeDataDescriptor(200, {1}), MakeDataDescriptor(12, {1})));
767 
768   TransformationVectorShuffle transformation2(
769       MakeInstructionDescriptor(16, SpvOpReturn, 0), 201, 12, 40, {0, 1});
770   ASSERT_TRUE(
771       transformation2.IsApplicable(context.get(), transformation_context));
772   ApplyAndCheckFreshIds(transformation2, context.get(),
773                         &transformation_context);
774   ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
775       MakeDataDescriptor(201, {0}), MakeDataDescriptor(12, {0})));
776   ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
777       MakeDataDescriptor(201, {1}), MakeDataDescriptor(12, {1})));
778 
779   TransformationVectorShuffle transformation3(
780       MakeInstructionDescriptor(16, SpvOpReturn, 0), 202, 40, 12, {2, 3});
781   ASSERT_TRUE(
782       transformation3.IsApplicable(context.get(), transformation_context));
783   ApplyAndCheckFreshIds(transformation3, context.get(),
784                         &transformation_context);
785   ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
786       MakeDataDescriptor(202, {0}), MakeDataDescriptor(12, {0})));
787   ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
788       MakeDataDescriptor(202, {1}), MakeDataDescriptor(12, {1})));
789 
790   TransformationVectorShuffle transformation4(
791       MakeInstructionDescriptor(16, SpvOpReturn, 0), 203, 40, 12, {0, 3});
792   ASSERT_TRUE(
793       transformation4.IsApplicable(context.get(), transformation_context));
794   ApplyAndCheckFreshIds(transformation4, context.get(),
795                         &transformation_context);
796   // Because %40 is irrelevant we do not get a synonym between it and %203[0].
797   ASSERT_FALSE(transformation_context.GetFactManager()->IsSynonymous(
798       MakeDataDescriptor(203, {0}), MakeDataDescriptor(40, {0})));
799   // Because %12 is *not* irrelevant we do get a synonym between it and %203[1].
800   ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
801       MakeDataDescriptor(203, {1}), MakeDataDescriptor(12, {1})));
802 }
803 
804 }  // namespace
805 }  // namespace fuzz
806 }  // namespace spvtools
807