1 // Copyright (c) 2019 Google LLC
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include "source/fuzz/transformation_set_loop_control.h"
16
17 #include "gtest/gtest.h"
18 #include "source/fuzz/fuzzer_util.h"
19 #include "test/fuzz/fuzz_test_util.h"
20
21 namespace spvtools {
22 namespace fuzz {
23 namespace {
24
TEST(TransformationSetLoopControlTest,VariousScenarios)25 TEST(TransformationSetLoopControlTest, VariousScenarios) {
26 // This test features loops with various different controls, and goes through
27 // a number of acceptable and unacceptable transformations to those controls.
28
29 std::string shader = R"(
30 OpCapability Shader
31 %1 = OpExtInstImport "GLSL.std.450"
32 OpMemoryModel Logical GLSL450
33 OpEntryPoint Fragment %4 "main"
34 OpExecutionMode %4 OriginUpperLeft
35 OpSource ESSL 310
36 OpName %4 "main"
37 %2 = OpTypeVoid
38 %3 = OpTypeFunction %2
39 %6 = OpTypeInt 32 1
40 %7 = OpTypePointer Function %6
41 %9 = OpConstant %6 0
42 %16 = OpConstant %6 100
43 %17 = OpTypeBool
44 %20 = OpConstant %6 1
45 %4 = OpFunction %2 None %3
46 %5 = OpLabel
47 %8 = OpVariable %7 Function
48 %22 = OpVariable %7 Function
49 %32 = OpVariable %7 Function
50 %42 = OpVariable %7 Function
51 %52 = OpVariable %7 Function
52 %62 = OpVariable %7 Function
53 %72 = OpVariable %7 Function
54 %82 = OpVariable %7 Function
55 %92 = OpVariable %7 Function
56 %102 = OpVariable %7 Function
57 %112 = OpVariable %7 Function
58 %122 = OpVariable %7 Function
59 OpStore %8 %9
60 OpBranch %10
61 %10 = OpLabel
62 %132 = OpPhi %6 %9 %5 %21 %13
63 OpLoopMerge %12 %13 None
64 OpBranch %14
65 %14 = OpLabel
66 %18 = OpSLessThan %17 %132 %16
67 OpBranchConditional %18 %11 %12
68 %11 = OpLabel
69 OpBranch %13
70 %13 = OpLabel
71 %21 = OpIAdd %6 %132 %20
72 OpStore %8 %21
73 OpBranch %10
74 %12 = OpLabel
75 OpStore %22 %9
76 OpBranch %23
77 %23 = OpLabel
78 %133 = OpPhi %6 %9 %12 %31 %26
79 OpLoopMerge %25 %26 Unroll
80 OpBranch %27
81 %27 = OpLabel
82 %29 = OpSLessThan %17 %133 %16
83 OpBranchConditional %29 %24 %25
84 %24 = OpLabel
85 OpBranch %26
86 %26 = OpLabel
87 %31 = OpIAdd %6 %133 %20
88 OpStore %22 %31
89 OpBranch %23
90 %25 = OpLabel
91 OpStore %32 %9
92 OpBranch %33
93 %33 = OpLabel
94 %134 = OpPhi %6 %9 %25 %41 %36
95 OpLoopMerge %35 %36 DontUnroll
96 OpBranch %37
97 %37 = OpLabel
98 %39 = OpSLessThan %17 %134 %16
99 OpBranchConditional %39 %34 %35
100 %34 = OpLabel
101 OpBranch %36
102 %36 = OpLabel
103 %41 = OpIAdd %6 %134 %20
104 OpStore %32 %41
105 OpBranch %33
106 %35 = OpLabel
107 OpStore %42 %9
108 OpBranch %43
109 %43 = OpLabel
110 %135 = OpPhi %6 %9 %35 %51 %46
111 OpLoopMerge %45 %46 DependencyInfinite
112 OpBranch %47
113 %47 = OpLabel
114 %49 = OpSLessThan %17 %135 %16
115 OpBranchConditional %49 %44 %45
116 %44 = OpLabel
117 OpBranch %46
118 %46 = OpLabel
119 %51 = OpIAdd %6 %135 %20
120 OpStore %42 %51
121 OpBranch %43
122 %45 = OpLabel
123 OpStore %52 %9
124 OpBranch %53
125 %53 = OpLabel
126 %136 = OpPhi %6 %9 %45 %61 %56
127 OpLoopMerge %55 %56 DependencyLength 3
128 OpBranch %57
129 %57 = OpLabel
130 %59 = OpSLessThan %17 %136 %16
131 OpBranchConditional %59 %54 %55
132 %54 = OpLabel
133 OpBranch %56
134 %56 = OpLabel
135 %61 = OpIAdd %6 %136 %20
136 OpStore %52 %61
137 OpBranch %53
138 %55 = OpLabel
139 OpStore %62 %9
140 OpBranch %63
141 %63 = OpLabel
142 %137 = OpPhi %6 %9 %55 %71 %66
143 OpLoopMerge %65 %66 MinIterations 10
144 OpBranch %67
145 %67 = OpLabel
146 %69 = OpSLessThan %17 %137 %16
147 OpBranchConditional %69 %64 %65
148 %64 = OpLabel
149 OpBranch %66
150 %66 = OpLabel
151 %71 = OpIAdd %6 %137 %20
152 OpStore %62 %71
153 OpBranch %63
154 %65 = OpLabel
155 OpStore %72 %9
156 OpBranch %73
157 %73 = OpLabel
158 %138 = OpPhi %6 %9 %65 %81 %76
159 OpLoopMerge %75 %76 MaxIterations 50
160 OpBranch %77
161 %77 = OpLabel
162 %79 = OpSLessThan %17 %138 %16
163 OpBranchConditional %79 %74 %75
164 %74 = OpLabel
165 OpBranch %76
166 %76 = OpLabel
167 %81 = OpIAdd %6 %138 %20
168 OpStore %72 %81
169 OpBranch %73
170 %75 = OpLabel
171 OpStore %82 %9
172 OpBranch %83
173 %83 = OpLabel
174 %139 = OpPhi %6 %9 %75 %91 %86
175 OpLoopMerge %85 %86 IterationMultiple 4
176 OpBranch %87
177 %87 = OpLabel
178 %89 = OpSLessThan %17 %139 %16
179 OpBranchConditional %89 %84 %85
180 %84 = OpLabel
181 OpBranch %86
182 %86 = OpLabel
183 %91 = OpIAdd %6 %139 %20
184 OpStore %82 %91
185 OpBranch %83
186 %85 = OpLabel
187 OpStore %92 %9
188 OpBranch %93
189 %93 = OpLabel
190 %140 = OpPhi %6 %9 %85 %101 %96
191 OpLoopMerge %95 %96 PeelCount 2
192 OpBranch %97
193 %97 = OpLabel
194 %99 = OpSLessThan %17 %140 %16
195 OpBranchConditional %99 %94 %95
196 %94 = OpLabel
197 OpBranch %96
198 %96 = OpLabel
199 %101 = OpIAdd %6 %140 %20
200 OpStore %92 %101
201 OpBranch %93
202 %95 = OpLabel
203 OpStore %102 %9
204 OpBranch %103
205 %103 = OpLabel
206 %141 = OpPhi %6 %9 %95 %111 %106
207 OpLoopMerge %105 %106 PartialCount 3
208 OpBranch %107
209 %107 = OpLabel
210 %109 = OpSLessThan %17 %141 %16
211 OpBranchConditional %109 %104 %105
212 %104 = OpLabel
213 OpBranch %106
214 %106 = OpLabel
215 %111 = OpIAdd %6 %141 %20
216 OpStore %102 %111
217 OpBranch %103
218 %105 = OpLabel
219 OpStore %112 %9
220 OpBranch %113
221 %113 = OpLabel
222 %142 = OpPhi %6 %9 %105 %121 %116
223 OpLoopMerge %115 %116 Unroll|PeelCount|PartialCount 3 4
224 OpBranch %117
225 %117 = OpLabel
226 %119 = OpSLessThan %17 %142 %16
227 OpBranchConditional %119 %114 %115
228 %114 = OpLabel
229 OpBranch %116
230 %116 = OpLabel
231 %121 = OpIAdd %6 %142 %20
232 OpStore %112 %121
233 OpBranch %113
234 %115 = OpLabel
235 OpStore %122 %9
236 OpBranch %123
237 %123 = OpLabel
238 %143 = OpPhi %6 %9 %115 %131 %126
239 OpLoopMerge %125 %126 DependencyLength|MinIterations|MaxIterations|IterationMultiple|PeelCount|PartialCount 2 5 90 4 7 14
240 OpBranch %127
241 %127 = OpLabel
242 %129 = OpSLessThan %17 %143 %16
243 OpBranchConditional %129 %124 %125
244 %124 = OpLabel
245 OpBranch %126
246 %126 = OpLabel
247 %131 = OpIAdd %6 %143 %20
248 OpStore %122 %131
249 OpBranch %123
250 %125 = OpLabel
251 OpReturn
252 OpFunctionEnd
253 )";
254
255 const auto env = SPV_ENV_UNIVERSAL_1_4;
256 const auto consumer = nullptr;
257 const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
258
259 spvtools::ValidatorOptions validator_options;
260 ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
261 kConsoleMessageConsumer));
262 TransformationContext transformation_context(
263 MakeUnique<FactManager>(context.get()), validator_options);
264 // These are the loop headers together with the selection controls of their
265 // merge instructions:
266 // %10 None
267 // %23 Unroll
268 // %33 DontUnroll
269 // %43 DependencyInfinite
270 // %53 DependencyLength 3
271 // %63 MinIterations 10
272 // %73 MaxIterations 50
273 // %83 IterationMultiple 4
274 // %93 PeelCount 2
275 // %103 PartialCount 3
276 // %113 Unroll|PeelCount|PartialCount 3 4
277 // %123
278 // DependencyLength|MinIterations|MaxIterations|IterationMultiple|PeelCount|PartialCount
279 // 2 5 90 4 7 14
280
281 ASSERT_TRUE(TransformationSetLoopControl(10, SpvLoopControlMaskNone, 0, 0)
282 .IsApplicable(context.get(), transformation_context));
283 ASSERT_TRUE(TransformationSetLoopControl(10, SpvLoopControlUnrollMask, 0, 0)
284 .IsApplicable(context.get(), transformation_context));
285 ASSERT_TRUE(
286 TransformationSetLoopControl(10, SpvLoopControlDontUnrollMask, 0, 0)
287 .IsApplicable(context.get(), transformation_context));
288 ASSERT_FALSE(TransformationSetLoopControl(
289 10, SpvLoopControlDependencyInfiniteMask, 0, 0)
290 .IsApplicable(context.get(), transformation_context));
291 ASSERT_FALSE(
292 TransformationSetLoopControl(10, SpvLoopControlDependencyLengthMask, 0, 0)
293 .IsApplicable(context.get(), transformation_context));
294 ASSERT_FALSE(
295 TransformationSetLoopControl(10, SpvLoopControlMinIterationsMask, 0, 0)
296 .IsApplicable(context.get(), transformation_context));
297 ASSERT_FALSE(
298 TransformationSetLoopControl(10, SpvLoopControlMaxIterationsMask, 0, 0)
299 .IsApplicable(context.get(), transformation_context));
300 ASSERT_FALSE(TransformationSetLoopControl(
301 10, SpvLoopControlIterationMultipleMask, 0, 0)
302 .IsApplicable(context.get(), transformation_context));
303 ASSERT_TRUE(
304 TransformationSetLoopControl(10, SpvLoopControlPeelCountMask, 3, 0)
305 .IsApplicable(context.get(), transformation_context));
306 ASSERT_FALSE(
307 TransformationSetLoopControl(10, SpvLoopControlPeelCountMask, 3, 3)
308 .IsApplicable(context.get(), transformation_context));
309 ASSERT_TRUE(
310 TransformationSetLoopControl(10, SpvLoopControlPartialCountMask, 0, 3)
311 .IsApplicable(context.get(), transformation_context));
312 ASSERT_FALSE(
313 TransformationSetLoopControl(10, SpvLoopControlPartialCountMask, 3, 3)
314 .IsApplicable(context.get(), transformation_context));
315 ASSERT_TRUE(TransformationSetLoopControl(
316 10,
317 SpvLoopControlPeelCountMask | SpvLoopControlPartialCountMask,
318 3, 3)
319 .IsApplicable(context.get(), transformation_context));
320 ASSERT_TRUE(TransformationSetLoopControl(10,
321 SpvLoopControlUnrollMask |
322 SpvLoopControlPeelCountMask |
323 SpvLoopControlPartialCountMask,
324 3, 3)
325 .IsApplicable(context.get(), transformation_context));
326 ASSERT_FALSE(TransformationSetLoopControl(10,
327 SpvLoopControlDontUnrollMask |
328 SpvLoopControlPeelCountMask |
329 SpvLoopControlPartialCountMask,
330 3, 3)
331 .IsApplicable(context.get(), transformation_context));
332
333 ASSERT_TRUE(TransformationSetLoopControl(23, SpvLoopControlMaskNone, 0, 0)
334 .IsApplicable(context.get(), transformation_context));
335 ASSERT_TRUE(TransformationSetLoopControl(23, SpvLoopControlUnrollMask, 0, 0)
336 .IsApplicable(context.get(), transformation_context));
337 ASSERT_TRUE(
338 TransformationSetLoopControl(23, SpvLoopControlDontUnrollMask, 0, 0)
339 .IsApplicable(context.get(), transformation_context));
340 ASSERT_TRUE(TransformationSetLoopControl(
341 23,
342 SpvLoopControlPeelCountMask | SpvLoopControlPartialCountMask,
343 3, 3)
344 .IsApplicable(context.get(), transformation_context));
345 ASSERT_FALSE(
346 TransformationSetLoopControl(23, SpvLoopControlMaxIterationsMask, 2, 3)
347 .IsApplicable(context.get(), transformation_context));
348
349 ASSERT_TRUE(TransformationSetLoopControl(33, SpvLoopControlMaskNone, 0, 0)
350 .IsApplicable(context.get(), transformation_context));
351 ASSERT_TRUE(TransformationSetLoopControl(33, SpvLoopControlUnrollMask, 0, 0)
352 .IsApplicable(context.get(), transformation_context));
353 ASSERT_TRUE(
354 TransformationSetLoopControl(33, SpvLoopControlDontUnrollMask, 0, 0)
355 .IsApplicable(context.get(), transformation_context));
356 ASSERT_FALSE(
357 TransformationSetLoopControl(33, SpvLoopControlMinIterationsMask, 0, 0)
358 .IsApplicable(context.get(), transformation_context));
359 ASSERT_TRUE(
360 TransformationSetLoopControl(
361 33, SpvLoopControlUnrollMask | SpvLoopControlPeelCountMask, 5, 0)
362 .IsApplicable(context.get(), transformation_context));
363 ASSERT_FALSE(TransformationSetLoopControl(33,
364 SpvLoopControlDontUnrollMask |
365 SpvLoopControlPartialCountMask,
366 0, 10)
367 .IsApplicable(context.get(), transformation_context));
368
369 ASSERT_TRUE(TransformationSetLoopControl(43, SpvLoopControlMaskNone, 0, 0)
370 .IsApplicable(context.get(), transformation_context));
371 ASSERT_TRUE(TransformationSetLoopControl(43, SpvLoopControlUnrollMask, 0, 0)
372 .IsApplicable(context.get(), transformation_context));
373 ASSERT_TRUE(
374 TransformationSetLoopControl(43, SpvLoopControlDontUnrollMask, 0, 0)
375 .IsApplicable(context.get(), transformation_context));
376 ASSERT_TRUE(TransformationSetLoopControl(
377 43,
378 SpvLoopControlMaskNone | SpvLoopControlDependencyInfiniteMask,
379 0, 0)
380 .IsApplicable(context.get(), transformation_context));
381 ASSERT_TRUE(
382 TransformationSetLoopControl(
383 43, SpvLoopControlUnrollMask | SpvLoopControlDependencyInfiniteMask,
384 0, 0)
385 .IsApplicable(context.get(), transformation_context));
386 ASSERT_TRUE(
387 TransformationSetLoopControl(
388 43,
389 SpvLoopControlDontUnrollMask | SpvLoopControlDependencyInfiniteMask,
390 0, 0)
391 .IsApplicable(context.get(), transformation_context));
392 ASSERT_FALSE(
393 TransformationSetLoopControl(43,
394 SpvLoopControlDependencyInfiniteMask |
395 SpvLoopControlDependencyLengthMask,
396 0, 0)
397 .IsApplicable(context.get(), transformation_context));
398 ASSERT_TRUE(
399 TransformationSetLoopControl(
400 43, SpvLoopControlUnrollMask | SpvLoopControlPeelCountMask, 5, 0)
401 .IsApplicable(context.get(), transformation_context));
402
403 ASSERT_TRUE(TransformationSetLoopControl(53, SpvLoopControlMaskNone, 0, 0)
404 .IsApplicable(context.get(), transformation_context));
405 ASSERT_TRUE(TransformationSetLoopControl(53, SpvLoopControlUnrollMask, 0, 0)
406 .IsApplicable(context.get(), transformation_context));
407 ASSERT_TRUE(
408 TransformationSetLoopControl(53, SpvLoopControlDontUnrollMask, 0, 0)
409 .IsApplicable(context.get(), transformation_context));
410 ASSERT_FALSE(
411 TransformationSetLoopControl(53, SpvLoopControlMaxIterationsMask, 0, 0)
412 .IsApplicable(context.get(), transformation_context));
413 ASSERT_TRUE(
414 TransformationSetLoopControl(
415 53, SpvLoopControlMaskNone | SpvLoopControlDependencyLengthMask, 0, 0)
416 .IsApplicable(context.get(), transformation_context));
417 ASSERT_FALSE(
418 TransformationSetLoopControl(
419 53, SpvLoopControlUnrollMask | SpvLoopControlDependencyInfiniteMask,
420 0, 0)
421 .IsApplicable(context.get(), transformation_context));
422 ASSERT_TRUE(
423 TransformationSetLoopControl(
424 53, SpvLoopControlDontUnrollMask | SpvLoopControlDependencyLengthMask,
425 0, 0)
426 .IsApplicable(context.get(), transformation_context));
427 ASSERT_FALSE(
428 TransformationSetLoopControl(53,
429 SpvLoopControlDependencyInfiniteMask |
430 SpvLoopControlDependencyLengthMask,
431 0, 0)
432 .IsApplicable(context.get(), transformation_context));
433 ASSERT_TRUE(
434 TransformationSetLoopControl(
435 53,
436 SpvLoopControlUnrollMask | SpvLoopControlDependencyLengthMask |
437 SpvLoopControlPeelCountMask | SpvLoopControlPartialCountMask,
438 5, 3)
439 .IsApplicable(context.get(), transformation_context));
440
441 ASSERT_TRUE(TransformationSetLoopControl(63, SpvLoopControlMaskNone, 0, 0)
442 .IsApplicable(context.get(), transformation_context));
443 ASSERT_TRUE(TransformationSetLoopControl(63, SpvLoopControlUnrollMask, 0, 0)
444 .IsApplicable(context.get(), transformation_context));
445 ASSERT_TRUE(
446 TransformationSetLoopControl(63, SpvLoopControlDontUnrollMask, 0, 0)
447 .IsApplicable(context.get(), transformation_context));
448 ASSERT_TRUE(TransformationSetLoopControl(63,
449 SpvLoopControlUnrollMask |
450 SpvLoopControlMinIterationsMask |
451 SpvLoopControlPeelCountMask |
452 SpvLoopControlPartialCountMask,
453 5, 3)
454 .IsApplicable(context.get(), transformation_context));
455 ASSERT_TRUE(TransformationSetLoopControl(63,
456 SpvLoopControlUnrollMask |
457 SpvLoopControlMinIterationsMask |
458 SpvLoopControlPeelCountMask,
459 23, 0)
460 .IsApplicable(context.get(), transformation_context));
461 ASSERT_FALSE(TransformationSetLoopControl(
462 63,
463 SpvLoopControlUnrollMask | SpvLoopControlMinIterationsMask |
464 SpvLoopControlPeelCountMask,
465 2, 23)
466 .IsApplicable(context.get(), transformation_context));
467
468 ASSERT_TRUE(TransformationSetLoopControl(73, SpvLoopControlMaskNone, 0, 0)
469 .IsApplicable(context.get(), transformation_context));
470 ASSERT_TRUE(TransformationSetLoopControl(73, SpvLoopControlUnrollMask, 0, 0)
471 .IsApplicable(context.get(), transformation_context));
472 ASSERT_TRUE(
473 TransformationSetLoopControl(73, SpvLoopControlDontUnrollMask, 0, 0)
474 .IsApplicable(context.get(), transformation_context));
475 ASSERT_FALSE(TransformationSetLoopControl(
476 73,
477 SpvLoopControlUnrollMask | SpvLoopControlMinIterationsMask |
478 SpvLoopControlPeelCountMask |
479 SpvLoopControlPartialCountMask,
480 5, 3)
481 .IsApplicable(context.get(), transformation_context));
482 ASSERT_TRUE(TransformationSetLoopControl(73,
483 SpvLoopControlUnrollMask |
484 SpvLoopControlMaxIterationsMask |
485 SpvLoopControlPeelCountMask,
486 23, 0)
487 .IsApplicable(context.get(), transformation_context));
488 ASSERT_FALSE(TransformationSetLoopControl(
489 73,
490 SpvLoopControlUnrollMask | SpvLoopControlMaxIterationsMask |
491 SpvLoopControlPeelCountMask,
492 2, 23)
493 .IsApplicable(context.get(), transformation_context));
494
495 ASSERT_TRUE(TransformationSetLoopControl(83, SpvLoopControlMaskNone, 0, 0)
496 .IsApplicable(context.get(), transformation_context));
497 ASSERT_TRUE(TransformationSetLoopControl(83, SpvLoopControlUnrollMask, 0, 0)
498 .IsApplicable(context.get(), transformation_context));
499 ASSERT_TRUE(
500 TransformationSetLoopControl(83, SpvLoopControlDontUnrollMask, 0, 0)
501 .IsApplicable(context.get(), transformation_context));
502 ASSERT_FALSE(TransformationSetLoopControl(
503 83,
504 SpvLoopControlUnrollMask | SpvLoopControlMinIterationsMask |
505 SpvLoopControlPeelCountMask |
506 SpvLoopControlPartialCountMask,
507 5, 3)
508 .IsApplicable(context.get(), transformation_context));
509 ASSERT_TRUE(
510 TransformationSetLoopControl(83,
511 SpvLoopControlUnrollMask |
512 SpvLoopControlIterationMultipleMask |
513 SpvLoopControlPeelCountMask,
514 23, 0)
515 .IsApplicable(context.get(), transformation_context));
516 ASSERT_FALSE(
517 TransformationSetLoopControl(83,
518 SpvLoopControlUnrollMask |
519 SpvLoopControlIterationMultipleMask |
520 SpvLoopControlPeelCountMask,
521 2, 23)
522 .IsApplicable(context.get(), transformation_context));
523
524 ASSERT_TRUE(TransformationSetLoopControl(93, SpvLoopControlMaskNone, 0, 0)
525 .IsApplicable(context.get(), transformation_context));
526 ASSERT_TRUE(TransformationSetLoopControl(93, SpvLoopControlUnrollMask, 0, 0)
527 .IsApplicable(context.get(), transformation_context));
528 ASSERT_TRUE(
529 TransformationSetLoopControl(93, SpvLoopControlDontUnrollMask, 0, 0)
530 .IsApplicable(context.get(), transformation_context));
531 ASSERT_TRUE(
532 TransformationSetLoopControl(93, SpvLoopControlPeelCountMask, 8, 0)
533 .IsApplicable(context.get(), transformation_context));
534 ASSERT_FALSE(
535 TransformationSetLoopControl(93, SpvLoopControlPeelCountMask, 8, 8)
536 .IsApplicable(context.get(), transformation_context));
537 ASSERT_TRUE(
538 TransformationSetLoopControl(93, SpvLoopControlPartialCountMask, 0, 8)
539 .IsApplicable(context.get(), transformation_context));
540 ASSERT_TRUE(TransformationSetLoopControl(
541 93,
542 SpvLoopControlPeelCountMask | SpvLoopControlPartialCountMask,
543 16, 8)
544 .IsApplicable(context.get(), transformation_context));
545
546 ASSERT_TRUE(TransformationSetLoopControl(103, SpvLoopControlMaskNone, 0, 0)
547 .IsApplicable(context.get(), transformation_context));
548 ASSERT_TRUE(TransformationSetLoopControl(103, SpvLoopControlUnrollMask, 0, 0)
549 .IsApplicable(context.get(), transformation_context));
550 ASSERT_TRUE(
551 TransformationSetLoopControl(103, SpvLoopControlDontUnrollMask, 0, 0)
552 .IsApplicable(context.get(), transformation_context));
553 ASSERT_TRUE(
554 TransformationSetLoopControl(103, SpvLoopControlPartialCountMask, 0, 60)
555 .IsApplicable(context.get(), transformation_context));
556 ASSERT_FALSE(TransformationSetLoopControl(103,
557 SpvLoopControlDontUnrollMask |
558 SpvLoopControlPartialCountMask,
559 0, 60)
560 .IsApplicable(context.get(), transformation_context));
561
562 ASSERT_TRUE(TransformationSetLoopControl(113, SpvLoopControlMaskNone, 0, 0)
563 .IsApplicable(context.get(), transformation_context));
564 ASSERT_TRUE(TransformationSetLoopControl(113, SpvLoopControlUnrollMask, 0, 0)
565 .IsApplicable(context.get(), transformation_context));
566 ASSERT_TRUE(
567 TransformationSetLoopControl(113, SpvLoopControlDontUnrollMask, 0, 0)
568 .IsApplicable(context.get(), transformation_context));
569 ASSERT_TRUE(
570 TransformationSetLoopControl(113, SpvLoopControlPeelCountMask, 12, 0)
571 .IsApplicable(context.get(), transformation_context));
572 ASSERT_FALSE(
573 TransformationSetLoopControl(
574 113,
575 SpvLoopControlIterationMultipleMask | SpvLoopControlPeelCountMask, 12,
576 0)
577 .IsApplicable(context.get(), transformation_context));
578
579 ASSERT_TRUE(TransformationSetLoopControl(123, SpvLoopControlMaskNone, 0, 0)
580 .IsApplicable(context.get(), transformation_context));
581 ASSERT_TRUE(TransformationSetLoopControl(123, SpvLoopControlUnrollMask, 0, 0)
582 .IsApplicable(context.get(), transformation_context));
583 ASSERT_TRUE(
584 TransformationSetLoopControl(123, SpvLoopControlDontUnrollMask, 0, 0)
585 .IsApplicable(context.get(), transformation_context));
586 ASSERT_TRUE(
587 TransformationSetLoopControl(
588 123,
589 SpvLoopControlMinIterationsMask | SpvLoopControlMaxIterationsMask |
590 SpvLoopControlIterationMultipleMask |
591 SpvLoopControlPeelCountMask | SpvLoopControlPartialCountMask,
592 7, 8)
593 .IsApplicable(context.get(), transformation_context));
594 ASSERT_TRUE(TransformationSetLoopControl(123,
595 SpvLoopControlUnrollMask |
596 SpvLoopControlMinIterationsMask |
597 SpvLoopControlMaxIterationsMask |
598 SpvLoopControlPartialCountMask,
599 0, 9)
600 .IsApplicable(context.get(), transformation_context));
601 ASSERT_FALSE(TransformationSetLoopControl(
602 123,
603 SpvLoopControlUnrollMask | SpvLoopControlMinIterationsMask |
604 SpvLoopControlMaxIterationsMask |
605 SpvLoopControlPartialCountMask,
606 7, 9)
607 .IsApplicable(context.get(), transformation_context));
608 ASSERT_FALSE(
609 TransformationSetLoopControl(
610 123,
611 SpvLoopControlDontUnrollMask | SpvLoopControlMinIterationsMask |
612 SpvLoopControlMaxIterationsMask | SpvLoopControlPartialCountMask,
613 7, 9)
614 .IsApplicable(context.get(), transformation_context));
615
616 ApplyAndCheckFreshIds(
617 TransformationSetLoopControl(10,
618 SpvLoopControlUnrollMask |
619 SpvLoopControlPeelCountMask |
620 SpvLoopControlPartialCountMask,
621 3, 3),
622 context.get(), &transformation_context);
623 ApplyAndCheckFreshIds(
624 TransformationSetLoopControl(23, SpvLoopControlDontUnrollMask, 0, 0),
625 context.get(), &transformation_context);
626 ApplyAndCheckFreshIds(
627 TransformationSetLoopControl(33, SpvLoopControlUnrollMask, 0, 0),
628 context.get(), &transformation_context);
629 ApplyAndCheckFreshIds(
630 TransformationSetLoopControl(
631 43,
632 SpvLoopControlDontUnrollMask | SpvLoopControlDependencyInfiniteMask,
633 0, 0),
634 context.get(), &transformation_context);
635 ApplyAndCheckFreshIds(
636 TransformationSetLoopControl(53, SpvLoopControlMaskNone, 0, 0),
637 context.get(), &transformation_context);
638 ApplyAndCheckFreshIds(
639 TransformationSetLoopControl(63,
640 SpvLoopControlUnrollMask |
641 SpvLoopControlMinIterationsMask |
642 SpvLoopControlPeelCountMask,
643 23, 0),
644 context.get(), &transformation_context);
645 ApplyAndCheckFreshIds(
646 TransformationSetLoopControl(73,
647 SpvLoopControlUnrollMask |
648 SpvLoopControlMaxIterationsMask |
649 SpvLoopControlPeelCountMask,
650 23, 0),
651 context.get(), &transformation_context);
652 ApplyAndCheckFreshIds(
653 TransformationSetLoopControl(83, SpvLoopControlDontUnrollMask, 0, 0),
654 context.get(), &transformation_context);
655 ApplyAndCheckFreshIds(
656 TransformationSetLoopControl(
657 93, SpvLoopControlPeelCountMask | SpvLoopControlPartialCountMask, 16,
658 8),
659 context.get(), &transformation_context);
660 ApplyAndCheckFreshIds(
661 TransformationSetLoopControl(103, SpvLoopControlPartialCountMask, 0, 60),
662 context.get(), &transformation_context);
663 ApplyAndCheckFreshIds(
664 TransformationSetLoopControl(113, SpvLoopControlPeelCountMask, 12, 0),
665 context.get(), &transformation_context);
666 ApplyAndCheckFreshIds(
667 TransformationSetLoopControl(
668 123,
669 SpvLoopControlUnrollMask | SpvLoopControlMinIterationsMask |
670 SpvLoopControlMaxIterationsMask | SpvLoopControlPartialCountMask,
671 0, 9),
672 context.get(), &transformation_context);
673
674 std::string after_transformation = R"(
675 OpCapability Shader
676 %1 = OpExtInstImport "GLSL.std.450"
677 OpMemoryModel Logical GLSL450
678 OpEntryPoint Fragment %4 "main"
679 OpExecutionMode %4 OriginUpperLeft
680 OpSource ESSL 310
681 OpName %4 "main"
682 %2 = OpTypeVoid
683 %3 = OpTypeFunction %2
684 %6 = OpTypeInt 32 1
685 %7 = OpTypePointer Function %6
686 %9 = OpConstant %6 0
687 %16 = OpConstant %6 100
688 %17 = OpTypeBool
689 %20 = OpConstant %6 1
690 %4 = OpFunction %2 None %3
691 %5 = OpLabel
692 %8 = OpVariable %7 Function
693 %22 = OpVariable %7 Function
694 %32 = OpVariable %7 Function
695 %42 = OpVariable %7 Function
696 %52 = OpVariable %7 Function
697 %62 = OpVariable %7 Function
698 %72 = OpVariable %7 Function
699 %82 = OpVariable %7 Function
700 %92 = OpVariable %7 Function
701 %102 = OpVariable %7 Function
702 %112 = OpVariable %7 Function
703 %122 = OpVariable %7 Function
704 OpStore %8 %9
705 OpBranch %10
706 %10 = OpLabel
707 %132 = OpPhi %6 %9 %5 %21 %13
708 OpLoopMerge %12 %13 Unroll|PeelCount|PartialCount 3 3
709 OpBranch %14
710 %14 = OpLabel
711 %18 = OpSLessThan %17 %132 %16
712 OpBranchConditional %18 %11 %12
713 %11 = OpLabel
714 OpBranch %13
715 %13 = OpLabel
716 %21 = OpIAdd %6 %132 %20
717 OpStore %8 %21
718 OpBranch %10
719 %12 = OpLabel
720 OpStore %22 %9
721 OpBranch %23
722 %23 = OpLabel
723 %133 = OpPhi %6 %9 %12 %31 %26
724 OpLoopMerge %25 %26 DontUnroll
725 OpBranch %27
726 %27 = OpLabel
727 %29 = OpSLessThan %17 %133 %16
728 OpBranchConditional %29 %24 %25
729 %24 = OpLabel
730 OpBranch %26
731 %26 = OpLabel
732 %31 = OpIAdd %6 %133 %20
733 OpStore %22 %31
734 OpBranch %23
735 %25 = OpLabel
736 OpStore %32 %9
737 OpBranch %33
738 %33 = OpLabel
739 %134 = OpPhi %6 %9 %25 %41 %36
740 OpLoopMerge %35 %36 Unroll
741 OpBranch %37
742 %37 = OpLabel
743 %39 = OpSLessThan %17 %134 %16
744 OpBranchConditional %39 %34 %35
745 %34 = OpLabel
746 OpBranch %36
747 %36 = OpLabel
748 %41 = OpIAdd %6 %134 %20
749 OpStore %32 %41
750 OpBranch %33
751 %35 = OpLabel
752 OpStore %42 %9
753 OpBranch %43
754 %43 = OpLabel
755 %135 = OpPhi %6 %9 %35 %51 %46
756 OpLoopMerge %45 %46 DontUnroll|DependencyInfinite
757 OpBranch %47
758 %47 = OpLabel
759 %49 = OpSLessThan %17 %135 %16
760 OpBranchConditional %49 %44 %45
761 %44 = OpLabel
762 OpBranch %46
763 %46 = OpLabel
764 %51 = OpIAdd %6 %135 %20
765 OpStore %42 %51
766 OpBranch %43
767 %45 = OpLabel
768 OpStore %52 %9
769 OpBranch %53
770 %53 = OpLabel
771 %136 = OpPhi %6 %9 %45 %61 %56
772 OpLoopMerge %55 %56 None
773 OpBranch %57
774 %57 = OpLabel
775 %59 = OpSLessThan %17 %136 %16
776 OpBranchConditional %59 %54 %55
777 %54 = OpLabel
778 OpBranch %56
779 %56 = OpLabel
780 %61 = OpIAdd %6 %136 %20
781 OpStore %52 %61
782 OpBranch %53
783 %55 = OpLabel
784 OpStore %62 %9
785 OpBranch %63
786 %63 = OpLabel
787 %137 = OpPhi %6 %9 %55 %71 %66
788 OpLoopMerge %65 %66 Unroll|MinIterations|PeelCount 10 23
789 OpBranch %67
790 %67 = OpLabel
791 %69 = OpSLessThan %17 %137 %16
792 OpBranchConditional %69 %64 %65
793 %64 = OpLabel
794 OpBranch %66
795 %66 = OpLabel
796 %71 = OpIAdd %6 %137 %20
797 OpStore %62 %71
798 OpBranch %63
799 %65 = OpLabel
800 OpStore %72 %9
801 OpBranch %73
802 %73 = OpLabel
803 %138 = OpPhi %6 %9 %65 %81 %76
804 OpLoopMerge %75 %76 Unroll|MaxIterations|PeelCount 50 23
805 OpBranch %77
806 %77 = OpLabel
807 %79 = OpSLessThan %17 %138 %16
808 OpBranchConditional %79 %74 %75
809 %74 = OpLabel
810 OpBranch %76
811 %76 = OpLabel
812 %81 = OpIAdd %6 %138 %20
813 OpStore %72 %81
814 OpBranch %73
815 %75 = OpLabel
816 OpStore %82 %9
817 OpBranch %83
818 %83 = OpLabel
819 %139 = OpPhi %6 %9 %75 %91 %86
820 OpLoopMerge %85 %86 DontUnroll
821 OpBranch %87
822 %87 = OpLabel
823 %89 = OpSLessThan %17 %139 %16
824 OpBranchConditional %89 %84 %85
825 %84 = OpLabel
826 OpBranch %86
827 %86 = OpLabel
828 %91 = OpIAdd %6 %139 %20
829 OpStore %82 %91
830 OpBranch %83
831 %85 = OpLabel
832 OpStore %92 %9
833 OpBranch %93
834 %93 = OpLabel
835 %140 = OpPhi %6 %9 %85 %101 %96
836 OpLoopMerge %95 %96 PeelCount|PartialCount 16 8
837 OpBranch %97
838 %97 = OpLabel
839 %99 = OpSLessThan %17 %140 %16
840 OpBranchConditional %99 %94 %95
841 %94 = OpLabel
842 OpBranch %96
843 %96 = OpLabel
844 %101 = OpIAdd %6 %140 %20
845 OpStore %92 %101
846 OpBranch %93
847 %95 = OpLabel
848 OpStore %102 %9
849 OpBranch %103
850 %103 = OpLabel
851 %141 = OpPhi %6 %9 %95 %111 %106
852 OpLoopMerge %105 %106 PartialCount 60
853 OpBranch %107
854 %107 = OpLabel
855 %109 = OpSLessThan %17 %141 %16
856 OpBranchConditional %109 %104 %105
857 %104 = OpLabel
858 OpBranch %106
859 %106 = OpLabel
860 %111 = OpIAdd %6 %141 %20
861 OpStore %102 %111
862 OpBranch %103
863 %105 = OpLabel
864 OpStore %112 %9
865 OpBranch %113
866 %113 = OpLabel
867 %142 = OpPhi %6 %9 %105 %121 %116
868 OpLoopMerge %115 %116 PeelCount 12
869 OpBranch %117
870 %117 = OpLabel
871 %119 = OpSLessThan %17 %142 %16
872 OpBranchConditional %119 %114 %115
873 %114 = OpLabel
874 OpBranch %116
875 %116 = OpLabel
876 %121 = OpIAdd %6 %142 %20
877 OpStore %112 %121
878 OpBranch %113
879 %115 = OpLabel
880 OpStore %122 %9
881 OpBranch %123
882 %123 = OpLabel
883 %143 = OpPhi %6 %9 %115 %131 %126
884 OpLoopMerge %125 %126 Unroll|MinIterations|MaxIterations|PartialCount 5 90 9
885 OpBranch %127
886 %127 = OpLabel
887 %129 = OpSLessThan %17 %143 %16
888 OpBranchConditional %129 %124 %125
889 %124 = OpLabel
890 OpBranch %126
891 %126 = OpLabel
892 %131 = OpIAdd %6 %143 %20
893 OpStore %122 %131
894 OpBranch %123
895 %125 = OpLabel
896 OpReturn
897 OpFunctionEnd
898 )";
899 ASSERT_TRUE(IsEqual(env, after_transformation, context.get()));
900 }
901
TEST(TransformationSetLoopControlTest,CheckSPIRVVersionsRespected)902 TEST(TransformationSetLoopControlTest, CheckSPIRVVersionsRespected) {
903 // This test checks that we do not allow introducing PeelCount and
904 // PartialCount loop controls if the SPIR-V version being used does not
905 // support them.
906
907 std::string shader = R"(
908 OpCapability Shader
909 %1 = OpExtInstImport "GLSL.std.450"
910 OpMemoryModel Logical GLSL450
911 OpEntryPoint Fragment %4 "main"
912 OpExecutionMode %4 OriginUpperLeft
913 OpSource ESSL 310
914 OpName %4 "main"
915 OpName %8 "i"
916 %2 = OpTypeVoid
917 %3 = OpTypeFunction %2
918 %6 = OpTypeInt 32 1
919 %7 = OpTypePointer Function %6
920 %9 = OpConstant %6 0
921 %16 = OpConstant %6 10
922 %17 = OpTypeBool
923 %20 = OpConstant %6 1
924 %4 = OpFunction %2 None %3
925 %5 = OpLabel
926 %8 = OpVariable %7 Function
927 OpStore %8 %9
928 OpBranch %10
929 %10 = OpLabel
930 OpLoopMerge %12 %13 None
931 OpBranch %14
932 %14 = OpLabel
933 %15 = OpLoad %6 %8
934 %18 = OpSLessThan %17 %15 %16
935 OpBranchConditional %18 %11 %12
936 %11 = OpLabel
937 OpBranch %13
938 %13 = OpLabel
939 %19 = OpLoad %6 %8
940 %21 = OpIAdd %6 %19 %20
941 OpStore %8 %21
942 OpBranch %10
943 %12 = OpLabel
944 OpReturn
945 OpFunctionEnd
946 )";
947
948 for (auto env :
949 {SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1, SPV_ENV_UNIVERSAL_1_2,
950 SPV_ENV_UNIVERSAL_1_3, SPV_ENV_UNIVERSAL_1_4, SPV_ENV_UNIVERSAL_1_5}) {
951 const auto consumer = nullptr;
952 const auto context =
953 BuildModule(env, consumer, shader, kFuzzAssembleOption);
954 spvtools::ValidatorOptions validator_options;
955 ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(
956 context.get(), validator_options, kConsoleMessageConsumer));
957 TransformationContext transformation_context(
958 MakeUnique<FactManager>(context.get()), validator_options);
959 TransformationSetLoopControl transformation(
960 10, SpvLoopControlPeelCountMask | SpvLoopControlPartialCountMask, 4, 4);
961
962 switch (env) {
963 case SPV_ENV_UNIVERSAL_1_0:
964 case SPV_ENV_UNIVERSAL_1_1:
965 case SPV_ENV_UNIVERSAL_1_2:
966 case SPV_ENV_UNIVERSAL_1_3:
967 // PeelCount and PartialCount were introduced in SPIRV 1.4, so are not
968 // valid in the context of older versions.
969 ASSERT_FALSE(
970 transformation.IsApplicable(context.get(), transformation_context));
971 break;
972 case SPV_ENV_UNIVERSAL_1_4:
973 case SPV_ENV_UNIVERSAL_1_5:
974 ASSERT_TRUE(
975 transformation.IsApplicable(context.get(), transformation_context));
976 break;
977 default:
978 assert(false && "Unhandled environment");
979 break;
980 }
981 }
982 }
983
984 } // namespace
985 } // namespace fuzz
986 } // namespace spvtools
987