• 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_composite_extract.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(TransformationCompositeExtractTest,BasicTest)26 TEST(TransformationCompositeExtractTest, 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                OpName %4 "main"
35                OpName %8 "a"
36                OpName %10 "b"
37                OpName %17 "FunnyPoint"
38                OpMemberName %17 0 "x"
39                OpMemberName %17 1 "y"
40                OpMemberName %17 2 "z"
41                OpName %19 "p"
42           %2 = OpTypeVoid
43           %3 = OpTypeFunction %2
44           %6 = OpTypeInt 32 1
45           %7 = OpTypePointer Function %6
46          %12 = OpTypeBool
47          %16 = OpTypeFloat 32
48          %17 = OpTypeStruct %16 %16 %6
49          %81 = OpTypeStruct %17 %16
50          %18 = OpTypePointer Function %17
51          %20 = OpConstant %6 0
52          %23 = OpTypePointer Function %16
53          %26 = OpConstant %6 1
54          %30 = OpConstant %6 2
55          %80 = OpUndef %16
56           %4 = OpFunction %2 None %3
57           %5 = OpLabel
58           %8 = OpVariable %7 Function
59          %10 = OpVariable %7 Function
60          %19 = OpVariable %18 Function
61           %9 = OpLoad %6 %8
62          %11 = OpLoad %6 %10
63         %100 = OpCompositeConstruct %17 %80 %80 %26
64         %104 = OpCompositeConstruct %81 %100 %80
65          %13 = OpIEqual %12 %9 %11
66                OpSelectionMerge %15 None
67                OpBranchConditional %13 %14 %25
68          %14 = OpLabel
69          %21 = OpLoad %6 %8
70          %22 = OpConvertSToF %16 %21
71         %101 = OpCompositeConstruct %17 %22 %80 %30
72          %24 = OpAccessChain %23 %19 %20
73                OpStore %24 %22
74                OpBranch %15
75          %25 = OpLabel
76          %27 = OpLoad %6 %10
77          %28 = OpConvertSToF %16 %27
78         %102 = OpCompositeConstruct %17 %80 %28 %27
79          %29 = OpAccessChain %23 %19 %26
80                OpStore %29 %28
81                OpBranch %15
82          %15 = OpLabel
83          %31 = OpAccessChain %23 %19 %20
84          %32 = OpLoad %16 %31
85          %33 = OpAccessChain %23 %19 %26
86          %34 = OpLoad %16 %33
87         %103 = OpCompositeConstruct %17 %34 %32 %9
88          %35 = OpFAdd %16 %32 %34
89          %36 = OpConvertFToS %6 %35
90          %37 = OpAccessChain %7 %19 %30
91                OpStore %37 %36
92                OpReturn
93                OpFunctionEnd
94   )";
95 
96   const auto env = SPV_ENV_UNIVERSAL_1_4;
97   const auto consumer = nullptr;
98   const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
99   spvtools::ValidatorOptions validator_options;
100   ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
101                                                kConsoleMessageConsumer));
102   TransformationContext transformation_context(
103       MakeUnique<FactManager>(context.get()), validator_options);
104   // Instruction does not exist.
105   ASSERT_FALSE(TransformationCompositeExtract(
106                    MakeInstructionDescriptor(36, SpvOpIAdd, 0), 200, 101, {0})
107                    .IsApplicable(context.get(), transformation_context));
108 
109   // Id for composite is not a composite.
110   ASSERT_FALSE(
111       TransformationCompositeExtract(
112           MakeInstructionDescriptor(37, SpvOpAccessChain, 0), 200, 32, {})
113           .IsApplicable(context.get(), transformation_context));
114 
115   // Composite does not dominate instruction being inserted before.
116   ASSERT_FALSE(
117       TransformationCompositeExtract(
118           MakeInstructionDescriptor(37, SpvOpAccessChain, 0), 200, 101, {0})
119           .IsApplicable(context.get(), transformation_context));
120 
121   // Too many indices for extraction from struct composite.
122   ASSERT_FALSE(
123       TransformationCompositeExtract(
124           MakeInstructionDescriptor(24, SpvOpAccessChain, 0), 200, 101, {0, 0})
125           .IsApplicable(context.get(), transformation_context));
126 
127   // Too many indices for extraction from struct composite.
128   ASSERT_FALSE(
129       TransformationCompositeExtract(
130           MakeInstructionDescriptor(13, SpvOpIEqual, 0), 200, 104, {0, 0, 0})
131           .IsApplicable(context.get(), transformation_context));
132 
133   // Out of bounds index for extraction from struct composite.
134   ASSERT_FALSE(
135       TransformationCompositeExtract(
136           MakeInstructionDescriptor(13, SpvOpIEqual, 0), 200, 104, {0, 3})
137           .IsApplicable(context.get(), transformation_context));
138 
139   // Result id already used.
140   ASSERT_FALSE(TransformationCompositeExtract(
141                    MakeInstructionDescriptor(35, SpvOpFAdd, 0), 80, 103, {0})
142                    .IsApplicable(context.get(), transformation_context));
143 
144   TransformationCompositeExtract transformation_1(
145       MakeInstructionDescriptor(36, SpvOpConvertFToS, 0), 201, 100, {2});
146   ASSERT_EQ(nullptr, context->get_def_use_mgr()->GetDef(201));
147   ASSERT_EQ(nullptr, context->get_instr_block(201));
148   uint32_t num_uses_of_100_before = context->get_def_use_mgr()->NumUses(100);
149   ASSERT_TRUE(
150       transformation_1.IsApplicable(context.get(), transformation_context));
151   ApplyAndCheckFreshIds(transformation_1, context.get(),
152                         &transformation_context);
153   ASSERT_EQ(SpvOpCompositeExtract,
154             context->get_def_use_mgr()->GetDef(201)->opcode());
155   ASSERT_EQ(15, context->get_instr_block(201)->id());
156   ASSERT_EQ(num_uses_of_100_before + 1,
157             context->get_def_use_mgr()->NumUses(100));
158   ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
159                                                kConsoleMessageConsumer));
160 
161   TransformationCompositeExtract transformation_2(
162       MakeInstructionDescriptor(37, SpvOpAccessChain, 0), 202, 104, {0, 2});
163   ASSERT_TRUE(
164       transformation_2.IsApplicable(context.get(), transformation_context));
165   ApplyAndCheckFreshIds(transformation_2, context.get(),
166                         &transformation_context);
167   ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
168                                                kConsoleMessageConsumer));
169 
170   TransformationCompositeExtract transformation_3(
171       MakeInstructionDescriptor(29, SpvOpAccessChain, 0), 203, 104, {0});
172   ASSERT_TRUE(
173       transformation_3.IsApplicable(context.get(), transformation_context));
174   ApplyAndCheckFreshIds(transformation_3, context.get(),
175                         &transformation_context);
176   ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
177                                                kConsoleMessageConsumer));
178 
179   TransformationCompositeExtract transformation_4(
180       MakeInstructionDescriptor(24, SpvOpStore, 0), 204, 101, {0});
181   ASSERT_TRUE(
182       transformation_4.IsApplicable(context.get(), transformation_context));
183   ApplyAndCheckFreshIds(transformation_4, context.get(),
184                         &transformation_context);
185   ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
186                                                kConsoleMessageConsumer));
187 
188   TransformationCompositeExtract transformation_5(
189       MakeInstructionDescriptor(29, SpvOpBranch, 0), 205, 102, {2});
190   ASSERT_TRUE(
191       transformation_5.IsApplicable(context.get(), transformation_context));
192   ApplyAndCheckFreshIds(transformation_5, context.get(),
193                         &transformation_context);
194   ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
195                                                kConsoleMessageConsumer));
196 
197   TransformationCompositeExtract transformation_6(
198       MakeInstructionDescriptor(37, SpvOpReturn, 0), 206, 103, {1});
199   ASSERT_TRUE(
200       transformation_6.IsApplicable(context.get(), transformation_context));
201   ApplyAndCheckFreshIds(transformation_6, context.get(),
202                         &transformation_context);
203   ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
204                                                kConsoleMessageConsumer));
205 
206   ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
207       MakeDataDescriptor(201, {}), MakeDataDescriptor(100, {2})));
208   ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
209       MakeDataDescriptor(202, {}), MakeDataDescriptor(104, {0, 2})));
210   ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
211       MakeDataDescriptor(203, {}), MakeDataDescriptor(104, {0})));
212   ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
213       MakeDataDescriptor(204, {}), MakeDataDescriptor(101, {0})));
214   ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
215       MakeDataDescriptor(205, {}), MakeDataDescriptor(102, {2})));
216   ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
217       MakeDataDescriptor(206, {}), MakeDataDescriptor(103, {1})));
218 
219   std::string after_transformation = R"(
220                OpCapability Shader
221           %1 = OpExtInstImport "GLSL.std.450"
222                OpMemoryModel Logical GLSL450
223                OpEntryPoint Fragment %4 "main"
224                OpExecutionMode %4 OriginUpperLeft
225                OpSource ESSL 310
226                OpName %4 "main"
227                OpName %8 "a"
228                OpName %10 "b"
229                OpName %17 "FunnyPoint"
230                OpMemberName %17 0 "x"
231                OpMemberName %17 1 "y"
232                OpMemberName %17 2 "z"
233                OpName %19 "p"
234           %2 = OpTypeVoid
235           %3 = OpTypeFunction %2
236           %6 = OpTypeInt 32 1
237           %7 = OpTypePointer Function %6
238          %12 = OpTypeBool
239          %16 = OpTypeFloat 32
240          %17 = OpTypeStruct %16 %16 %6
241          %81 = OpTypeStruct %17 %16
242          %18 = OpTypePointer Function %17
243          %20 = OpConstant %6 0
244          %23 = OpTypePointer Function %16
245          %26 = OpConstant %6 1
246          %30 = OpConstant %6 2
247          %80 = OpUndef %16
248           %4 = OpFunction %2 None %3
249           %5 = OpLabel
250           %8 = OpVariable %7 Function
251          %10 = OpVariable %7 Function
252          %19 = OpVariable %18 Function
253           %9 = OpLoad %6 %8
254          %11 = OpLoad %6 %10
255         %100 = OpCompositeConstruct %17 %80 %80 %26
256         %104 = OpCompositeConstruct %81 %100 %80
257          %13 = OpIEqual %12 %9 %11
258                OpSelectionMerge %15 None
259                OpBranchConditional %13 %14 %25
260          %14 = OpLabel
261          %21 = OpLoad %6 %8
262          %22 = OpConvertSToF %16 %21
263         %101 = OpCompositeConstruct %17 %22 %80 %30
264          %24 = OpAccessChain %23 %19 %20
265         %204 = OpCompositeExtract %16 %101 0
266                OpStore %24 %22
267                OpBranch %15
268          %25 = OpLabel
269          %27 = OpLoad %6 %10
270          %28 = OpConvertSToF %16 %27
271         %102 = OpCompositeConstruct %17 %80 %28 %27
272         %203 = OpCompositeExtract %17 %104 0
273          %29 = OpAccessChain %23 %19 %26
274                OpStore %29 %28
275         %205 = OpCompositeExtract %6 %102 2
276                OpBranch %15
277          %15 = OpLabel
278          %31 = OpAccessChain %23 %19 %20
279          %32 = OpLoad %16 %31
280          %33 = OpAccessChain %23 %19 %26
281          %34 = OpLoad %16 %33
282         %103 = OpCompositeConstruct %17 %34 %32 %9
283          %35 = OpFAdd %16 %32 %34
284         %201 = OpCompositeExtract %6 %100 2
285          %36 = OpConvertFToS %6 %35
286         %202 = OpCompositeExtract %6 %104 0 2
287          %37 = OpAccessChain %7 %19 %30
288                OpStore %37 %36
289         %206 = OpCompositeExtract %16 %103 1
290                OpReturn
291                OpFunctionEnd
292   )";
293   ASSERT_TRUE(IsEqual(env, after_transformation, context.get()));
294 }
295 
TEST(TransformationCompositeExtractTest,IllegalInsertionPoints)296 TEST(TransformationCompositeExtractTest, IllegalInsertionPoints) {
297   std::string shader = R"(
298                OpCapability Shader
299           %1 = OpExtInstImport "GLSL.std.450"
300                OpMemoryModel Logical GLSL450
301                OpEntryPoint Fragment %4 "main" %51 %27
302                OpExecutionMode %4 OriginUpperLeft
303                OpSource ESSL 310
304                OpName %4 "main"
305                OpName %25 "buf"
306                OpMemberName %25 0 "value"
307                OpName %27 ""
308                OpName %51 "color"
309                OpMemberDecorate %25 0 Offset 0
310                OpDecorate %25 Block
311                OpDecorate %27 DescriptorSet 0
312                OpDecorate %27 Binding 0
313                OpDecorate %51 Location 0
314           %2 = OpTypeVoid
315           %3 = OpTypeFunction %2
316           %6 = OpTypeFloat 32
317           %7 = OpTypeVector %6 4
318          %10 = OpConstant %6 0.300000012
319          %11 = OpConstant %6 0.400000006
320          %12 = OpConstant %6 0.5
321          %13 = OpConstant %6 1
322          %14 = OpConstantComposite %7 %10 %11 %12 %13
323          %15 = OpTypeInt 32 1
324          %18 = OpConstant %15 0
325          %25 = OpTypeStruct %6
326          %26 = OpTypePointer Uniform %25
327          %27 = OpVariable %26 Uniform
328          %28 = OpTypePointer Uniform %6
329          %32 = OpTypeBool
330         %103 = OpConstantTrue %32
331          %34 = OpConstant %6 0.100000001
332          %48 = OpConstant %15 1
333          %50 = OpTypePointer Output %7
334          %51 = OpVariable %50 Output
335         %100 = OpTypePointer Function %6
336           %4 = OpFunction %2 None %3
337           %5 = OpLabel
338         %101 = OpVariable %100 Function
339         %102 = OpVariable %100 Function
340                OpBranch %19
341          %19 = OpLabel
342          %60 = OpPhi %7 %14 %5 %58 %20
343          %59 = OpPhi %15 %18 %5 %49 %20
344          %29 = OpAccessChain %28 %27 %18
345          %30 = OpLoad %6 %29
346          %31 = OpConvertFToS %15 %30
347          %33 = OpSLessThan %32 %59 %31
348                OpLoopMerge %21 %20 None
349                OpBranchConditional %33 %20 %21
350          %20 = OpLabel
351          %39 = OpCompositeExtract %6 %60 0
352          %40 = OpFAdd %6 %39 %34
353          %55 = OpCompositeInsert %7 %40 %60 0
354          %44 = OpCompositeExtract %6 %60 1
355          %45 = OpFSub %6 %44 %34
356          %58 = OpCompositeInsert %7 %45 %55 1
357          %49 = OpIAdd %15 %59 %48
358                OpBranch %19
359          %21 = OpLabel
360                OpStore %51 %60
361                OpSelectionMerge %105 None
362                OpBranchConditional %103 %104 %105
363         %104 = OpLabel
364                OpBranch %105
365         %105 = OpLabel
366                OpReturn
367                OpFunctionEnd
368   )";
369 
370   const auto env = SPV_ENV_UNIVERSAL_1_4;
371   const auto consumer = nullptr;
372   const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
373   spvtools::ValidatorOptions validator_options;
374   ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
375                                                kConsoleMessageConsumer));
376   TransformationContext transformation_context(
377       MakeUnique<FactManager>(context.get()), validator_options);
378   // Cannot insert before the OpVariables of a function.
379   ASSERT_FALSE(
380       TransformationCompositeExtract(
381           MakeInstructionDescriptor(101, SpvOpVariable, 0), 200, 14, {0})
382           .IsApplicable(context.get(), transformation_context));
383   ASSERT_FALSE(
384       TransformationCompositeExtract(
385           MakeInstructionDescriptor(101, SpvOpVariable, 1), 200, 14, {1})
386           .IsApplicable(context.get(), transformation_context));
387   ASSERT_FALSE(
388       TransformationCompositeExtract(
389           MakeInstructionDescriptor(102, SpvOpVariable, 0), 200, 14, {1})
390           .IsApplicable(context.get(), transformation_context));
391   // OK to insert right after the OpVariables.
392   ASSERT_FALSE(TransformationCompositeExtract(
393                    MakeInstructionDescriptor(102, SpvOpBranch, 1), 200, 14, {1})
394                    .IsApplicable(context.get(), transformation_context));
395 
396   // Cannot insert before the OpPhis of a block.
397   ASSERT_FALSE(TransformationCompositeExtract(
398                    MakeInstructionDescriptor(60, SpvOpPhi, 0), 200, 14, {2})
399                    .IsApplicable(context.get(), transformation_context));
400   ASSERT_FALSE(TransformationCompositeExtract(
401                    MakeInstructionDescriptor(59, SpvOpPhi, 0), 200, 14, {3})
402                    .IsApplicable(context.get(), transformation_context));
403   // OK to insert after the OpPhis.
404   ASSERT_TRUE(
405       TransformationCompositeExtract(
406           MakeInstructionDescriptor(59, SpvOpAccessChain, 0), 200, 14, {3})
407           .IsApplicable(context.get(), transformation_context));
408 
409   // Cannot insert before OpLoopMerge
410   ASSERT_FALSE(TransformationCompositeExtract(
411                    MakeInstructionDescriptor(33, SpvOpBranchConditional, 0),
412                    200, 14, {3})
413                    .IsApplicable(context.get(), transformation_context));
414 
415   // Cannot insert before OpSelectionMerge
416   ASSERT_FALSE(TransformationCompositeExtract(
417                    MakeInstructionDescriptor(21, SpvOpBranchConditional, 0),
418                    200, 14, {2})
419                    .IsApplicable(context.get(), transformation_context));
420 }
421 
TEST(TransformationCompositeExtractTest,AddSynonymsForRelevantIds)422 TEST(TransformationCompositeExtractTest, AddSynonymsForRelevantIds) {
423   std::string shader = R"(
424                OpCapability Shader
425           %1 = OpExtInstImport "GLSL.std.450"
426                OpMemoryModel Logical GLSL450
427                OpEntryPoint Fragment %4 "main"
428                OpExecutionMode %4 OriginUpperLeft
429                OpSource ESSL 310
430                OpName %4 "main"
431                OpName %8 "a"
432                OpName %10 "b"
433                OpName %17 "FunnyPoint"
434                OpMemberName %17 0 "x"
435                OpMemberName %17 1 "y"
436                OpMemberName %17 2 "z"
437                OpName %19 "p"
438           %2 = OpTypeVoid
439           %3 = OpTypeFunction %2
440           %6 = OpTypeInt 32 1
441           %7 = OpTypePointer Function %6
442          %12 = OpTypeBool
443          %16 = OpTypeFloat 32
444          %17 = OpTypeStruct %16 %16 %6
445          %81 = OpTypeStruct %17 %16
446          %18 = OpTypePointer Function %17
447          %20 = OpConstant %6 0
448          %23 = OpTypePointer Function %16
449          %26 = OpConstant %6 1
450          %30 = OpConstant %6 2
451          %80 = OpUndef %16
452           %4 = OpFunction %2 None %3
453           %5 = OpLabel
454           %8 = OpVariable %7 Function
455          %10 = OpVariable %7 Function
456          %19 = OpVariable %18 Function
457           %9 = OpLoad %6 %8
458          %11 = OpLoad %6 %10
459         %100 = OpCompositeConstruct %17 %80 %80 %26
460         %104 = OpCompositeConstruct %81 %100 %80
461          %13 = OpIEqual %12 %9 %11
462                OpSelectionMerge %15 None
463                OpBranchConditional %13 %14 %25
464          %14 = OpLabel
465          %21 = OpLoad %6 %8
466          %22 = OpConvertSToF %16 %21
467         %101 = OpCompositeConstruct %17 %22 %80 %30
468          %24 = OpAccessChain %23 %19 %20
469                OpStore %24 %22
470                OpBranch %15
471          %25 = OpLabel
472          %27 = OpLoad %6 %10
473          %28 = OpConvertSToF %16 %27
474         %102 = OpCompositeConstruct %17 %80 %28 %27
475          %29 = OpAccessChain %23 %19 %26
476                OpStore %29 %28
477                OpBranch %15
478          %15 = OpLabel
479          %31 = OpAccessChain %23 %19 %20
480          %32 = OpLoad %16 %31
481          %33 = OpAccessChain %23 %19 %26
482          %34 = OpLoad %16 %33
483         %103 = OpCompositeConstruct %17 %34 %32 %9
484          %35 = OpFAdd %16 %32 %34
485          %36 = OpConvertFToS %6 %35
486          %37 = OpAccessChain %7 %19 %30
487                OpStore %37 %36
488                OpReturn
489                OpFunctionEnd
490   )";
491 
492   const auto env = SPV_ENV_UNIVERSAL_1_4;
493   const auto consumer = nullptr;
494   const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
495   spvtools::ValidatorOptions validator_options;
496   ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
497                                                kConsoleMessageConsumer));
498   TransformationContext transformation_context(
499       MakeUnique<FactManager>(context.get()), validator_options);
500   TransformationCompositeExtract transformation(
501       MakeInstructionDescriptor(36, SpvOpConvertFToS, 0), 201, 100, {2});
502   ASSERT_TRUE(
503       transformation.IsApplicable(context.get(), transformation_context));
504   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
505   ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
506       MakeDataDescriptor(201, {}), MakeDataDescriptor(100, {2})));
507 }
508 
TEST(TransformationCompositeExtractTest,DontAddSynonymsForIrrelevantIds)509 TEST(TransformationCompositeExtractTest, DontAddSynonymsForIrrelevantIds) {
510   std::string shader = R"(
511                OpCapability Shader
512           %1 = OpExtInstImport "GLSL.std.450"
513                OpMemoryModel Logical GLSL450
514                OpEntryPoint Fragment %4 "main"
515                OpExecutionMode %4 OriginUpperLeft
516                OpSource ESSL 310
517                OpName %4 "main"
518                OpName %8 "a"
519                OpName %10 "b"
520                OpName %17 "FunnyPoint"
521                OpMemberName %17 0 "x"
522                OpMemberName %17 1 "y"
523                OpMemberName %17 2 "z"
524                OpName %19 "p"
525           %2 = OpTypeVoid
526           %3 = OpTypeFunction %2
527           %6 = OpTypeInt 32 1
528           %7 = OpTypePointer Function %6
529          %12 = OpTypeBool
530          %16 = OpTypeFloat 32
531          %17 = OpTypeStruct %16 %16 %6
532          %81 = OpTypeStruct %17 %16
533          %18 = OpTypePointer Function %17
534          %20 = OpConstant %6 0
535          %23 = OpTypePointer Function %16
536          %26 = OpConstant %6 1
537          %30 = OpConstant %6 2
538          %80 = OpUndef %16
539           %4 = OpFunction %2 None %3
540           %5 = OpLabel
541           %8 = OpVariable %7 Function
542          %10 = OpVariable %7 Function
543          %19 = OpVariable %18 Function
544           %9 = OpLoad %6 %8
545          %11 = OpLoad %6 %10
546         %100 = OpCompositeConstruct %17 %80 %80 %26
547         %104 = OpCompositeConstruct %81 %100 %80
548          %13 = OpIEqual %12 %9 %11
549                OpSelectionMerge %15 None
550                OpBranchConditional %13 %14 %25
551          %14 = OpLabel
552          %21 = OpLoad %6 %8
553          %22 = OpConvertSToF %16 %21
554         %101 = OpCompositeConstruct %17 %22 %80 %30
555          %24 = OpAccessChain %23 %19 %20
556                OpStore %24 %22
557                OpBranch %15
558          %25 = OpLabel
559          %27 = OpLoad %6 %10
560          %28 = OpConvertSToF %16 %27
561         %102 = OpCompositeConstruct %17 %80 %28 %27
562          %29 = OpAccessChain %23 %19 %26
563                OpStore %29 %28
564                OpBranch %15
565          %15 = OpLabel
566          %31 = OpAccessChain %23 %19 %20
567          %32 = OpLoad %16 %31
568          %33 = OpAccessChain %23 %19 %26
569          %34 = OpLoad %16 %33
570         %103 = OpCompositeConstruct %17 %34 %32 %9
571          %35 = OpFAdd %16 %32 %34
572          %36 = OpConvertFToS %6 %35
573          %37 = OpAccessChain %7 %19 %30
574                OpStore %37 %36
575                OpReturn
576                OpFunctionEnd
577   )";
578 
579   const auto env = SPV_ENV_UNIVERSAL_1_4;
580   const auto consumer = nullptr;
581   const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
582   spvtools::ValidatorOptions validator_options;
583   ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
584                                                kConsoleMessageConsumer));
585   TransformationContext transformation_context(
586       MakeUnique<FactManager>(context.get()), validator_options);
587   transformation_context.GetFactManager()->AddFactIdIsIrrelevant(100);
588   TransformationCompositeExtract transformation(
589       MakeInstructionDescriptor(36, SpvOpConvertFToS, 0), 201, 100, {2});
590   ASSERT_TRUE(
591       transformation.IsApplicable(context.get(), transformation_context));
592   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
593   ASSERT_FALSE(transformation_context.GetFactManager()->IsSynonymous(
594       MakeDataDescriptor(201, {}), MakeDataDescriptor(100, {2})));
595 }
596 
TEST(TransformationCompositeExtractTest,DontAddSynonymInDeadBlock)597 TEST(TransformationCompositeExtractTest, DontAddSynonymInDeadBlock) {
598   std::string shader = R"(
599                OpCapability Shader
600           %1 = OpExtInstImport "GLSL.std.450"
601                OpMemoryModel Logical GLSL450
602                OpEntryPoint Fragment %4 "main"
603                OpExecutionMode %4 OriginUpperLeft
604                OpSource ESSL 320
605           %2 = OpTypeVoid
606           %3 = OpTypeFunction %2
607           %6 = OpTypeInt 32 1
608           %7 = OpTypeVector %6 2
609           %8 = OpTypePointer Function %7
610          %10 = OpConstant %6 0
611          %11 = OpConstant %6 1
612          %12 = OpConstantComposite %7 %10 %11
613          %13 = OpTypeBool
614          %14 = OpConstantFalse %13
615           %4 = OpFunction %2 None %3
616           %5 = OpLabel
617           %9 = OpVariable %8 Function
618                OpStore %9 %12
619                OpSelectionMerge %16 None
620                OpBranchConditional %14 %15 %16
621          %15 = OpLabel
622                OpBranch %16
623          %16 = OpLabel
624                OpReturn
625                OpFunctionEnd
626   )";
627 
628   const auto env = SPV_ENV_UNIVERSAL_1_4;
629   const auto consumer = nullptr;
630   const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
631   spvtools::ValidatorOptions validator_options;
632   ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
633                                                kConsoleMessageConsumer));
634   TransformationContext transformation_context(
635       MakeUnique<FactManager>(context.get()), validator_options);
636   transformation_context.GetFactManager()->AddFactBlockIsDead(15);
637   TransformationCompositeExtract transformation(
638       MakeInstructionDescriptor(15, SpvOpBranch, 0), 100, 12, {0});
639   ASSERT_TRUE(
640       transformation.IsApplicable(context.get(), transformation_context));
641   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
642   ASSERT_FALSE(transformation_context.GetFactManager()->IsSynonymous(
643       MakeDataDescriptor(100, {}), MakeDataDescriptor(12, {0})));
644 }
645 
646 }  // namespace
647 }  // namespace fuzz
648 }  // namespace spvtools
649