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 #include "source/fuzz/instruction_descriptor.h"
17 #include "test/fuzz/fuzz_test_util.h"
18
19 namespace spvtools {
20 namespace fuzz {
21 namespace {
22
TEST(TransformationVectorShuffle,BasicTest)23 TEST(TransformationVectorShuffle, BasicTest) {
24 std::string shader = R"(
25 OpCapability Shader
26 %1 = OpExtInstImport "GLSL.std.450"
27 OpMemoryModel Logical GLSL450
28 OpEntryPoint Fragment %4 "main"
29 OpExecutionMode %4 OriginUpperLeft
30 OpSource ESSL 310
31 %2 = OpTypeVoid
32 %3 = OpTypeFunction %2
33 %6 = OpTypeBool
34 %7 = OpTypeVector %6 2
35 %10 = OpConstantTrue %6
36 %11 = OpConstantFalse %6
37 %12 = OpConstantComposite %7 %10 %11
38 %112 = OpUndef %7
39 %13 = OpTypeVector %6 3
40 %16 = OpConstantComposite %13 %10 %11 %10
41 %17 = OpTypeVector %6 4
42 %20 = OpConstantComposite %17 %10 %11 %10 %11
43 %21 = OpTypeInt 32 1
44 %22 = OpTypeVector %21 2
45 %25 = OpConstant %21 1
46 %26 = OpConstant %21 0
47 %27 = OpConstantComposite %22 %25 %26
48 %28 = OpTypeVector %21 3
49 %31 = OpConstantComposite %28 %25 %26 %25
50 %32 = OpTypeVector %21 4
51 %33 = OpTypePointer Function %32
52 %35 = OpConstantComposite %32 %25 %26 %25 %26
53 %36 = OpTypeInt 32 0
54 %37 = OpTypeVector %36 2
55 %40 = OpConstant %36 1
56 %41 = OpConstant %36 0
57 %42 = OpConstantComposite %37 %40 %41
58 %43 = OpTypeVector %36 3
59 %46 = OpConstantComposite %43 %40 %41 %40
60 %47 = OpTypeVector %36 4
61 %50 = OpConstantComposite %47 %40 %41 %40 %41
62 %51 = OpTypeFloat 32
63 %55 = OpConstant %51 1
64 %56 = OpConstant %51 0
65 %58 = OpTypeVector %51 3
66 %61 = OpConstantComposite %58 %55 %56 %55
67 %62 = OpTypeVector %51 4
68 %65 = OpConstantComposite %62 %55 %56 %55 %56
69 %4 = OpFunction %2 None %3
70 %5 = OpLabel
71 OpSelectionMerge %100 None
72 OpBranchConditional %10 %101 %102
73 %101 = OpLabel
74 %103 = OpCompositeConstruct %62 %55 %55 %55 %56
75 OpBranch %100
76 %102 = OpLabel
77 OpBranch %100
78 %100 = OpLabel
79 OpReturn
80 OpFunctionEnd
81 )";
82
83 const auto env = SPV_ENV_UNIVERSAL_1_4;
84 const auto consumer = nullptr;
85 const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
86 ASSERT_TRUE(IsValid(env, context.get()));
87
88 FactManager fact_manager;
89 spvtools::ValidatorOptions validator_options;
90 TransformationContext transformation_context(&fact_manager,
91 validator_options);
92
93 transformation_context.GetFactManager()->AddFactDataSynonym(
94 MakeDataDescriptor(10, {}), MakeDataDescriptor(12, {0}), context.get());
95 transformation_context.GetFactManager()->AddFactDataSynonym(
96 MakeDataDescriptor(11, {}), MakeDataDescriptor(12, {1}), context.get());
97
98 transformation_context.GetFactManager()->AddFactDataSynonym(
99 MakeDataDescriptor(10, {}), MakeDataDescriptor(16, {0}), context.get());
100 transformation_context.GetFactManager()->AddFactDataSynonym(
101 MakeDataDescriptor(11, {}), MakeDataDescriptor(16, {1}), context.get());
102 transformation_context.GetFactManager()->AddFactDataSynonym(
103 MakeDataDescriptor(10, {}), MakeDataDescriptor(16, {2}), context.get());
104
105 transformation_context.GetFactManager()->AddFactDataSynonym(
106 MakeDataDescriptor(10, {}), MakeDataDescriptor(20, {0}), context.get());
107 transformation_context.GetFactManager()->AddFactDataSynonym(
108 MakeDataDescriptor(11, {}), MakeDataDescriptor(20, {1}), context.get());
109 transformation_context.GetFactManager()->AddFactDataSynonym(
110 MakeDataDescriptor(10, {}), MakeDataDescriptor(20, {2}), context.get());
111 transformation_context.GetFactManager()->AddFactDataSynonym(
112 MakeDataDescriptor(11, {}), MakeDataDescriptor(20, {3}), context.get());
113
114 transformation_context.GetFactManager()->AddFactDataSynonym(
115 MakeDataDescriptor(25, {}), MakeDataDescriptor(27, {0}), context.get());
116 transformation_context.GetFactManager()->AddFactDataSynonym(
117 MakeDataDescriptor(26, {}), MakeDataDescriptor(27, {1}), context.get());
118
119 transformation_context.GetFactManager()->AddFactDataSynonym(
120 MakeDataDescriptor(25, {}), MakeDataDescriptor(31, {0}), context.get());
121 transformation_context.GetFactManager()->AddFactDataSynonym(
122 MakeDataDescriptor(26, {}), MakeDataDescriptor(31, {1}), context.get());
123 transformation_context.GetFactManager()->AddFactDataSynonym(
124 MakeDataDescriptor(25, {}), MakeDataDescriptor(31, {2}), context.get());
125
126 transformation_context.GetFactManager()->AddFactDataSynonym(
127 MakeDataDescriptor(25, {}), MakeDataDescriptor(35, {0}), context.get());
128 transformation_context.GetFactManager()->AddFactDataSynonym(
129 MakeDataDescriptor(26, {}), MakeDataDescriptor(35, {1}), context.get());
130 transformation_context.GetFactManager()->AddFactDataSynonym(
131 MakeDataDescriptor(25, {}), MakeDataDescriptor(35, {2}), context.get());
132 transformation_context.GetFactManager()->AddFactDataSynonym(
133 MakeDataDescriptor(26, {}), MakeDataDescriptor(35, {3}), context.get());
134
135 transformation_context.GetFactManager()->AddFactDataSynonym(
136 MakeDataDescriptor(40, {}), MakeDataDescriptor(42, {0}), context.get());
137 transformation_context.GetFactManager()->AddFactDataSynonym(
138 MakeDataDescriptor(41, {}), MakeDataDescriptor(42, {1}), context.get());
139
140 transformation_context.GetFactManager()->AddFactDataSynonym(
141 MakeDataDescriptor(40, {}), MakeDataDescriptor(46, {0}), context.get());
142 transformation_context.GetFactManager()->AddFactDataSynonym(
143 MakeDataDescriptor(41, {}), MakeDataDescriptor(46, {1}), context.get());
144 transformation_context.GetFactManager()->AddFactDataSynonym(
145 MakeDataDescriptor(40, {}), MakeDataDescriptor(46, {2}), context.get());
146
147 transformation_context.GetFactManager()->AddFactDataSynonym(
148 MakeDataDescriptor(40, {}), MakeDataDescriptor(50, {0}), context.get());
149 transformation_context.GetFactManager()->AddFactDataSynonym(
150 MakeDataDescriptor(41, {}), MakeDataDescriptor(50, {1}), context.get());
151 transformation_context.GetFactManager()->AddFactDataSynonym(
152 MakeDataDescriptor(40, {}), MakeDataDescriptor(50, {2}), context.get());
153 transformation_context.GetFactManager()->AddFactDataSynonym(
154 MakeDataDescriptor(41, {}), MakeDataDescriptor(50, {3}), context.get());
155
156 transformation_context.GetFactManager()->AddFactDataSynonym(
157 MakeDataDescriptor(55, {}), MakeDataDescriptor(61, {0}), context.get());
158 transformation_context.GetFactManager()->AddFactDataSynonym(
159 MakeDataDescriptor(56, {}), MakeDataDescriptor(61, {1}), context.get());
160 transformation_context.GetFactManager()->AddFactDataSynonym(
161 MakeDataDescriptor(55, {}), MakeDataDescriptor(61, {2}), context.get());
162
163 transformation_context.GetFactManager()->AddFactDataSynonym(
164 MakeDataDescriptor(55, {}), MakeDataDescriptor(65, {0}), context.get());
165 transformation_context.GetFactManager()->AddFactDataSynonym(
166 MakeDataDescriptor(56, {}), MakeDataDescriptor(65, {1}), context.get());
167 transformation_context.GetFactManager()->AddFactDataSynonym(
168 MakeDataDescriptor(55, {}), MakeDataDescriptor(65, {2}), context.get());
169 transformation_context.GetFactManager()->AddFactDataSynonym(
170 MakeDataDescriptor(56, {}), MakeDataDescriptor(65, {3}), context.get());
171
172 // %103 does not dominate the return instruction.
173 ASSERT_FALSE(TransformationVectorShuffle(
174 MakeInstructionDescriptor(100, SpvOpReturn, 0), 200, 103, 65,
175 {3, 5, 7})
176 .IsApplicable(context.get(), transformation_context));
177
178 // Illegal to shuffle a bvec2 and a vec3
179 ASSERT_FALSE(TransformationVectorShuffle(
180 MakeInstructionDescriptor(100, SpvOpReturn, 0), 200, 112, 61,
181 {0, 2, 4})
182 .IsApplicable(context.get(), transformation_context));
183
184 // Illegal to shuffle an ivec2 and a uvec4
185 ASSERT_FALSE(TransformationVectorShuffle(
186 MakeInstructionDescriptor(100, SpvOpReturn, 0), 200, 27, 50,
187 {1, 3, 5})
188 .IsApplicable(context.get(), transformation_context));
189
190 // Vector 1 does not exist
191 ASSERT_FALSE(TransformationVectorShuffle(
192 MakeInstructionDescriptor(100, SpvOpReturn, 0), 200, 300, 50,
193 {1, 3, 5})
194 .IsApplicable(context.get(), transformation_context));
195
196 // Vector 2 does not exist
197 ASSERT_FALSE(TransformationVectorShuffle(
198 MakeInstructionDescriptor(100, SpvOpReturn, 0), 200, 27, 300,
199 {1, 3, 5})
200 .IsApplicable(context.get(), transformation_context));
201
202 // Index out of range
203 ASSERT_FALSE(
204 TransformationVectorShuffle(
205 MakeInstructionDescriptor(100, SpvOpReturn, 0), 200, 12, 112, {0, 20})
206 .IsApplicable(context.get(), transformation_context));
207
208 // Too many indices
209 ASSERT_FALSE(TransformationVectorShuffle(
210 MakeInstructionDescriptor(100, SpvOpReturn, 0), 200, 12, 112,
211 {0, 1, 0, 1, 0, 1, 0, 1})
212 .IsApplicable(context.get(), transformation_context));
213
214 // Too few indices
215 ASSERT_FALSE(
216 TransformationVectorShuffle(
217 MakeInstructionDescriptor(100, SpvOpReturn, 0), 200, 12, 112, {})
218 .IsApplicable(context.get(), transformation_context));
219
220 // Too few indices again
221 ASSERT_FALSE(
222 TransformationVectorShuffle(
223 MakeInstructionDescriptor(100, SpvOpReturn, 0), 200, 12, 112, {0})
224 .IsApplicable(context.get(), transformation_context));
225
226 // Indices define unknown type: we do not have vec2
227 ASSERT_FALSE(
228 TransformationVectorShuffle(
229 MakeInstructionDescriptor(100, SpvOpReturn, 0), 200, 65, 65, {0, 1})
230 .IsApplicable(context.get(), transformation_context));
231
232 // The instruction to insert before does not exist
233 ASSERT_FALSE(TransformationVectorShuffle(
234 MakeInstructionDescriptor(100, SpvOpCompositeConstruct, 1),
235 201, 20, 12, {0xFFFFFFFF, 3, 5})
236 .IsApplicable(context.get(), transformation_context));
237
238 // The 'fresh' id is already in use
239 ASSERT_FALSE(
240 TransformationVectorShuffle(
241 MakeInstructionDescriptor(100, SpvOpReturn, 0), 12, 12, 112, {})
242 .IsApplicable(context.get(), transformation_context));
243
244 protobufs::DataDescriptor temp_dd;
245
246 TransformationVectorShuffle transformation1(
247 MakeInstructionDescriptor(100, SpvOpReturn, 0), 200, 12, 112, {1, 0});
248 ASSERT_TRUE(
249 transformation1.IsApplicable(context.get(), transformation_context));
250 transformation1.Apply(context.get(), &transformation_context);
251 temp_dd = MakeDataDescriptor(200, {0});
252 ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
253 MakeDataDescriptor(11, {}), temp_dd, context.get()));
254 temp_dd = MakeDataDescriptor(200, {1});
255 ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
256 MakeDataDescriptor(10, {}), temp_dd, context.get()));
257
258 TransformationVectorShuffle transformation2(
259 MakeInstructionDescriptor(100, SpvOpReturn, 0), 201, 20, 12,
260 {0xFFFFFFFF, 3, 5});
261 ASSERT_TRUE(
262 transformation2.IsApplicable(context.get(), transformation_context));
263 transformation2.Apply(context.get(), &transformation_context);
264 temp_dd = MakeDataDescriptor(201, {1});
265 ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
266 MakeDataDescriptor(11, {}), temp_dd, context.get()));
267 temp_dd = MakeDataDescriptor(201, {2});
268 ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
269 MakeDataDescriptor(11, {}), temp_dd, context.get()));
270
271 TransformationVectorShuffle transformation3(
272 MakeInstructionDescriptor(100, SpvOpReturn, 0), 202, 27, 35, {5, 4, 1});
273 ASSERT_TRUE(
274 transformation3.IsApplicable(context.get(), transformation_context));
275 transformation3.Apply(context.get(), &transformation_context);
276 temp_dd = MakeDataDescriptor(202, {0});
277 ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
278 MakeDataDescriptor(26, {}), temp_dd, context.get()));
279 temp_dd = MakeDataDescriptor(202, {1});
280 ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
281 MakeDataDescriptor(25, {}), temp_dd, context.get()));
282 temp_dd = MakeDataDescriptor(202, {2});
283 ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
284 MakeDataDescriptor(26, {}), temp_dd, context.get()));
285
286 TransformationVectorShuffle transformation4(
287 MakeInstructionDescriptor(100, SpvOpReturn, 0), 203, 42, 46, {0, 1});
288 ASSERT_TRUE(
289 transformation4.IsApplicable(context.get(), transformation_context));
290 transformation4.Apply(context.get(), &transformation_context);
291 temp_dd = MakeDataDescriptor(203, {0});
292 ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
293 MakeDataDescriptor(40, {}), temp_dd, context.get()));
294 temp_dd = MakeDataDescriptor(203, {1});
295 ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
296 MakeDataDescriptor(41, {}), temp_dd, context.get()));
297
298 TransformationVectorShuffle transformation5(
299 MakeInstructionDescriptor(100, SpvOpReturn, 0), 204, 42, 46, {2, 3, 4});
300 ASSERT_TRUE(
301 transformation5.IsApplicable(context.get(), transformation_context));
302 transformation5.Apply(context.get(), &transformation_context);
303 temp_dd = MakeDataDescriptor(204, {0});
304 ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
305 MakeDataDescriptor(40, {}), temp_dd, context.get()));
306 temp_dd = MakeDataDescriptor(204, {1});
307 ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
308 MakeDataDescriptor(41, {}), temp_dd, context.get()));
309 temp_dd = MakeDataDescriptor(204, {2});
310 ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
311 MakeDataDescriptor(40, {}), temp_dd, context.get()));
312
313 TransformationVectorShuffle transformation6(
314 MakeInstructionDescriptor(100, SpvOpReturn, 0), 205, 42, 42,
315 {0, 1, 2, 3});
316 ASSERT_TRUE(
317 transformation6.IsApplicable(context.get(), transformation_context));
318 transformation6.Apply(context.get(), &transformation_context);
319 temp_dd = MakeDataDescriptor(205, {0});
320 ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
321 MakeDataDescriptor(40, {}), temp_dd, context.get()));
322 temp_dd = MakeDataDescriptor(205, {1});
323 ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
324 MakeDataDescriptor(41, {}), temp_dd, context.get()));
325 temp_dd = MakeDataDescriptor(205, {2});
326 ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
327 MakeDataDescriptor(40, {}), temp_dd, context.get()));
328 temp_dd = MakeDataDescriptor(205, {3});
329 ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
330 MakeDataDescriptor(41, {}), temp_dd, context.get()));
331
332 // swizzle vec4 from vec4 and vec4 using some undefs
333 TransformationVectorShuffle transformation7(
334 MakeInstructionDescriptor(100, SpvOpReturn, 0), 206, 65, 65,
335 {0xFFFFFFFF, 3, 6, 0xFFFFFFFF});
336 ASSERT_TRUE(
337 transformation7.IsApplicable(context.get(), transformation_context));
338 transformation7.Apply(context.get(), &transformation_context);
339 temp_dd = MakeDataDescriptor(206, {1});
340 ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
341 MakeDataDescriptor(56, {}), temp_dd, context.get()));
342
343 std::string after_transformation = R"(
344 OpCapability Shader
345 %1 = OpExtInstImport "GLSL.std.450"
346 OpMemoryModel Logical GLSL450
347 OpEntryPoint Fragment %4 "main"
348 OpExecutionMode %4 OriginUpperLeft
349 OpSource ESSL 310
350 %2 = OpTypeVoid
351 %3 = OpTypeFunction %2
352 %6 = OpTypeBool
353 %7 = OpTypeVector %6 2
354 %10 = OpConstantTrue %6
355 %11 = OpConstantFalse %6
356 %12 = OpConstantComposite %7 %10 %11
357 %112 = OpUndef %7
358 %13 = OpTypeVector %6 3
359 %16 = OpConstantComposite %13 %10 %11 %10
360 %17 = OpTypeVector %6 4
361 %20 = OpConstantComposite %17 %10 %11 %10 %11
362 %21 = OpTypeInt 32 1
363 %22 = OpTypeVector %21 2
364 %25 = OpConstant %21 1
365 %26 = OpConstant %21 0
366 %27 = OpConstantComposite %22 %25 %26
367 %28 = OpTypeVector %21 3
368 %31 = OpConstantComposite %28 %25 %26 %25
369 %32 = OpTypeVector %21 4
370 %33 = OpTypePointer Function %32
371 %35 = OpConstantComposite %32 %25 %26 %25 %26
372 %36 = OpTypeInt 32 0
373 %37 = OpTypeVector %36 2
374 %40 = OpConstant %36 1
375 %41 = OpConstant %36 0
376 %42 = OpConstantComposite %37 %40 %41
377 %43 = OpTypeVector %36 3
378 %46 = OpConstantComposite %43 %40 %41 %40
379 %47 = OpTypeVector %36 4
380 %50 = OpConstantComposite %47 %40 %41 %40 %41
381 %51 = OpTypeFloat 32
382 %55 = OpConstant %51 1
383 %56 = OpConstant %51 0
384 %58 = OpTypeVector %51 3
385 %61 = OpConstantComposite %58 %55 %56 %55
386 %62 = OpTypeVector %51 4
387 %65 = OpConstantComposite %62 %55 %56 %55 %56
388 %4 = OpFunction %2 None %3
389 %5 = OpLabel
390 OpSelectionMerge %100 None
391 OpBranchConditional %10 %101 %102
392 %101 = OpLabel
393 %103 = OpCompositeConstruct %62 %55 %55 %55 %56
394 OpBranch %100
395 %102 = OpLabel
396 OpBranch %100
397 %100 = OpLabel
398 %200 = OpVectorShuffle %7 %12 %112 1 0
399 %201 = OpVectorShuffle %13 %20 %12 0xFFFFFFFF 3 5
400 %202 = OpVectorShuffle %28 %27 %35 5 4 1
401 %203 = OpVectorShuffle %37 %42 %46 0 1
402 %204 = OpVectorShuffle %43 %42 %46 2 3 4
403 %205 = OpVectorShuffle %47 %42 %42 0 1 2 3
404 %206 = OpVectorShuffle %62 %65 %65 0xFFFFFFFF 3 6 0xFFFFFFFF
405 OpReturn
406 OpFunctionEnd
407 )";
408 ASSERT_TRUE(IsEqual(env, after_transformation, context.get()));
409 }
410
TEST(TransformationVectorShuffleTest,IllegalInsertionPoints)411 TEST(TransformationVectorShuffleTest, IllegalInsertionPoints) {
412 std::string shader = R"(
413 OpCapability Shader
414 %1 = OpExtInstImport "GLSL.std.450"
415 OpMemoryModel Logical GLSL450
416 OpEntryPoint Fragment %4 "main" %51 %27
417 OpExecutionMode %4 OriginUpperLeft
418 OpSource ESSL 310
419 OpName %4 "main"
420 OpName %25 "buf"
421 OpMemberName %25 0 "value"
422 OpName %27 ""
423 OpName %51 "color"
424 OpMemberDecorate %25 0 Offset 0
425 OpDecorate %25 Block
426 OpDecorate %27 DescriptorSet 0
427 OpDecorate %27 Binding 0
428 OpDecorate %51 Location 0
429 %2 = OpTypeVoid
430 %3 = OpTypeFunction %2
431 %6 = OpTypeFloat 32
432 %7 = OpTypeVector %6 4
433 %150 = OpTypeVector %6 2
434 %10 = OpConstant %6 0.300000012
435 %11 = OpConstant %6 0.400000006
436 %12 = OpConstant %6 0.5
437 %13 = OpConstant %6 1
438 %14 = OpConstantComposite %7 %10 %11 %12 %13
439 %15 = OpTypeInt 32 1
440 %18 = OpConstant %15 0
441 %25 = OpTypeStruct %6
442 %26 = OpTypePointer Uniform %25
443 %27 = OpVariable %26 Uniform
444 %28 = OpTypePointer Uniform %6
445 %32 = OpTypeBool
446 %103 = OpConstantTrue %32
447 %34 = OpConstant %6 0.100000001
448 %48 = OpConstant %15 1
449 %50 = OpTypePointer Output %7
450 %51 = OpVariable %50 Output
451 %100 = OpTypePointer Function %6
452 %4 = OpFunction %2 None %3
453 %5 = OpLabel
454 %101 = OpVariable %100 Function
455 %102 = OpVariable %100 Function
456 OpBranch %19
457 %19 = OpLabel
458 %60 = OpPhi %7 %14 %5 %58 %20
459 %59 = OpPhi %15 %18 %5 %49 %20
460 %29 = OpAccessChain %28 %27 %18
461 %30 = OpLoad %6 %29
462 %31 = OpConvertFToS %15 %30
463 %33 = OpSLessThan %32 %59 %31
464 OpLoopMerge %21 %20 None
465 OpBranchConditional %33 %20 %21
466 %20 = OpLabel
467 %39 = OpCompositeExtract %6 %60 0
468 %40 = OpFAdd %6 %39 %34
469 %55 = OpCompositeInsert %7 %40 %60 0
470 %44 = OpCompositeExtract %6 %60 1
471 %45 = OpFSub %6 %44 %34
472 %58 = OpCompositeInsert %7 %45 %55 1
473 %49 = OpIAdd %15 %59 %48
474 OpBranch %19
475 %21 = OpLabel
476 OpStore %51 %60
477 OpSelectionMerge %105 None
478 OpBranchConditional %103 %104 %105
479 %104 = OpLabel
480 OpBranch %105
481 %105 = OpLabel
482 OpReturn
483 OpFunctionEnd
484 )";
485
486 const auto env = SPV_ENV_UNIVERSAL_1_4;
487 const auto consumer = nullptr;
488 const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
489 ASSERT_TRUE(IsValid(env, context.get()));
490
491 FactManager fact_manager;
492 spvtools::ValidatorOptions validator_options;
493 TransformationContext transformation_context(&fact_manager,
494 validator_options);
495
496 // Cannot insert before the OpVariables of a function.
497 ASSERT_FALSE(
498 TransformationVectorShuffle(
499 MakeInstructionDescriptor(101, SpvOpVariable, 0), 200, 14, 14, {0, 1})
500 .IsApplicable(context.get(), transformation_context));
501 ASSERT_FALSE(
502 TransformationVectorShuffle(
503 MakeInstructionDescriptor(101, SpvOpVariable, 1), 200, 14, 14, {1, 2})
504 .IsApplicable(context.get(), transformation_context));
505 ASSERT_FALSE(
506 TransformationVectorShuffle(
507 MakeInstructionDescriptor(102, SpvOpVariable, 0), 200, 14, 14, {1, 2})
508 .IsApplicable(context.get(), transformation_context));
509 // OK to insert right after the OpVariables.
510 ASSERT_FALSE(
511 TransformationVectorShuffle(
512 MakeInstructionDescriptor(102, SpvOpBranch, 1), 200, 14, 14, {1, 1})
513 .IsApplicable(context.get(), transformation_context));
514
515 // Cannot insert before the OpPhis of a block.
516 ASSERT_FALSE(
517 TransformationVectorShuffle(MakeInstructionDescriptor(60, SpvOpPhi, 0),
518 200, 14, 14, {2, 0})
519 .IsApplicable(context.get(), transformation_context));
520 ASSERT_FALSE(
521 TransformationVectorShuffle(MakeInstructionDescriptor(59, SpvOpPhi, 0),
522 200, 14, 14, {3, 0})
523 .IsApplicable(context.get(), transformation_context));
524 // OK to insert after the OpPhis.
525 ASSERT_TRUE(TransformationVectorShuffle(
526 MakeInstructionDescriptor(59, SpvOpAccessChain, 0), 200, 14,
527 14, {3, 4})
528 .IsApplicable(context.get(), transformation_context));
529
530 // Cannot insert before OpLoopMerge
531 ASSERT_FALSE(TransformationVectorShuffle(
532 MakeInstructionDescriptor(33, SpvOpBranchConditional, 0),
533 200, 14, 14, {3})
534 .IsApplicable(context.get(), transformation_context));
535
536 // Cannot insert before OpSelectionMerge
537 ASSERT_FALSE(TransformationVectorShuffle(
538 MakeInstructionDescriptor(21, SpvOpBranchConditional, 0),
539 200, 14, 14, {2})
540 .IsApplicable(context.get(), transformation_context));
541 }
542
543 } // namespace
544 } // namespace fuzz
545 } // namespace spvtools
546