1 // Copyright (c) 2020 André Perez Maselco
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_replace_linear_algebra_instruction.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(TransformationReplaceLinearAlgebraInstructionTest, IsApplicable)26 TEST(TransformationReplaceLinearAlgebraInstructionTest, IsApplicable) {
27   std::string shader = R"(
28                OpCapability Shader
29           %1 = OpExtInstImport "GLSL.std.450"
30                OpMemoryModel Logical GLSL450
31                OpEntryPoint Fragment %22 "main"
32                OpExecutionMode %22 OriginUpperLeft
33                OpSource ESSL 310
34                OpName %22 "main"
35           %2 = OpTypeVoid
36           %3 = OpTypeFunction %2
37           %4 = OpTypeFloat 32
38           %5 = OpTypeVector %4 2
39           %6 = OpTypeVector %4 3
40           %7 = OpTypeVector %4 4
41           %8 = OpConstant %4 1
42           %9 = OpConstant %4 2
43          %10 = OpConstant %4 3
44          %11 = OpConstant %4 4
45          %12 = OpConstant %4 5
46          %13 = OpConstant %4 6
47          %14 = OpConstant %4 7
48          %15 = OpConstant %4 8
49          %16 = OpConstantComposite %5 %8 %9
50          %17 = OpConstantComposite %5 %10 %11
51          %18 = OpConstantComposite %6 %8 %9 %10
52          %19 = OpConstantComposite %6 %11 %12 %13
53          %20 = OpConstantComposite %7 %8 %9 %10 %11
54          %21 = OpConstantComposite %7 %12 %13 %14 %15
55          %22 = OpFunction %2 None %3
56          %23 = OpLabel
57          %24 = OpDot %4 %16 %17
58          %25 = OpDot %4 %18 %19
59          %26 = OpDot %4 %20 %21
60          %27 = OpVectorTimesScalar %5 %16 %8
61          %28 = OpVectorTimesScalar %6 %18 %9
62          %29 = OpVectorTimesScalar %7 %20 %10
63          %30 = OpCopyObject %4 %24
64          %31 = OpFAdd %4 %8 %9
65          %32 = OpFMul %4 %10 %11
66                OpReturn
67                OpFunctionEnd
68   )";
69 
70   const auto env = SPV_ENV_UNIVERSAL_1_5;
71   const auto consumer = nullptr;
72   const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
73   spvtools::ValidatorOptions validator_options;
74   ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
75                                                kConsoleMessageConsumer));
76   TransformationContext transformation_context(
77       MakeUnique<FactManager>(context.get()), validator_options);
78   // Tests linear algebra instructions.
79   auto instruction_descriptor =
80       MakeInstructionDescriptor(24, spv::Op::OpDot, 0);
81   auto transformation = TransformationReplaceLinearAlgebraInstruction(
82       {33, 34, 35, 36, 37, 38}, instruction_descriptor);
83   ASSERT_TRUE(
84       transformation.IsApplicable(context.get(), transformation_context));
85 
86   instruction_descriptor =
87       MakeInstructionDescriptor(27, spv::Op::OpVectorTimesScalar, 0);
88   transformation = TransformationReplaceLinearAlgebraInstruction(
89       {33, 34, 35, 36}, instruction_descriptor);
90   ASSERT_TRUE(
91       transformation.IsApplicable(context.get(), transformation_context));
92 
93   // Tests non-linear algebra instructions.
94   instruction_descriptor =
95       MakeInstructionDescriptor(30, spv::Op::OpCopyObject, 0);
96   transformation = TransformationReplaceLinearAlgebraInstruction(
97       {33, 34, 35, 36, 37, 38}, instruction_descriptor);
98   ASSERT_FALSE(
99       transformation.IsApplicable(context.get(), transformation_context));
100 
101   instruction_descriptor = MakeInstructionDescriptor(31, spv::Op::OpFAdd, 0);
102   transformation = TransformationReplaceLinearAlgebraInstruction(
103       {33, 34, 35, 36, 37}, instruction_descriptor);
104   ASSERT_FALSE(
105       transformation.IsApplicable(context.get(), transformation_context));
106 
107   instruction_descriptor = MakeInstructionDescriptor(32, spv::Op::OpFMul, 0);
108   transformation = TransformationReplaceLinearAlgebraInstruction(
109       {33, 34, 35, 36}, instruction_descriptor);
110   ASSERT_FALSE(
111       transformation.IsApplicable(context.get(), transformation_context));
112 
113   // Tests number of fresh ids is different than necessary.
114   instruction_descriptor = MakeInstructionDescriptor(25, spv::Op::OpDot, 0);
115   transformation = TransformationReplaceLinearAlgebraInstruction(
116       {33, 34, 35, 36}, instruction_descriptor);
117   ASSERT_FALSE(
118       transformation.IsApplicable(context.get(), transformation_context));
119 
120   instruction_descriptor =
121       MakeInstructionDescriptor(28, spv::Op::OpVectorTimesScalar, 0);
122   transformation = TransformationReplaceLinearAlgebraInstruction(
123       {33, 34, 35, 36, 37, 38, 39}, instruction_descriptor);
124   ASSERT_FALSE(
125       transformation.IsApplicable(context.get(), transformation_context));
126 
127   // Tests non-fresh ids.
128   instruction_descriptor = MakeInstructionDescriptor(26, spv::Op::OpDot, 0);
129   transformation = TransformationReplaceLinearAlgebraInstruction(
130       {33, 34, 5, 36, 37, 8, 39, 40, 1, 42, 3, 44, 45, 46},
131       instruction_descriptor);
132   ASSERT_FALSE(
133       transformation.IsApplicable(context.get(), transformation_context));
134 
135   instruction_descriptor =
136       MakeInstructionDescriptor(29, spv::Op::OpVectorTimesScalar, 0);
137   transformation = TransformationReplaceLinearAlgebraInstruction(
138       {33, 34, 35, 36, 7, 38, 9, 40}, instruction_descriptor);
139   ASSERT_FALSE(
140       transformation.IsApplicable(context.get(), transformation_context));
141 }
142 
TEST(TransformationReplaceLinearAlgebraInstructionTest, ReplaceOpTranspose)143 TEST(TransformationReplaceLinearAlgebraInstructionTest, ReplaceOpTranspose) {
144   std::string reference_shader = R"(
145                OpCapability Shader
146           %1 = OpExtInstImport "GLSL.std.450"
147                OpMemoryModel Logical GLSL450
148                OpEntryPoint Vertex %54 "main"
149 
150 ; Types
151           %2 = OpTypeVoid
152           %3 = OpTypeFunction %2
153           %4 = OpTypeFloat 32
154           %5 = OpTypeVector %4 2
155           %6 = OpTypeVector %4 3
156           %7 = OpTypeVector %4 4
157           %8 = OpTypeMatrix %5 2
158           %9 = OpTypeMatrix %5 3
159          %10 = OpTypeMatrix %5 4
160          %11 = OpTypeMatrix %6 2
161          %12 = OpTypeMatrix %6 3
162          %13 = OpTypeMatrix %6 4
163          %14 = OpTypeMatrix %7 2
164          %15 = OpTypeMatrix %7 3
165          %16 = OpTypeMatrix %7 4
166 
167 ; Constant scalars
168          %17 = OpConstant %4 1
169          %18 = OpConstant %4 2
170          %19 = OpConstant %4 3
171          %20 = OpConstant %4 4
172          %21 = OpConstant %4 5
173          %22 = OpConstant %4 6
174          %23 = OpConstant %4 7
175          %24 = OpConstant %4 8
176          %25 = OpConstant %4 9
177          %26 = OpConstant %4 10
178          %27 = OpConstant %4 11
179          %28 = OpConstant %4 12
180          %29 = OpConstant %4 13
181          %30 = OpConstant %4 14
182          %31 = OpConstant %4 15
183          %32 = OpConstant %4 16
184 
185 ; Constant vectors
186          %33 = OpConstantComposite %5 %17 %18
187          %34 = OpConstantComposite %5 %19 %20
188          %35 = OpConstantComposite %5 %21 %22
189          %36 = OpConstantComposite %5 %23 %24
190          %37 = OpConstantComposite %6 %17 %18 %19
191          %38 = OpConstantComposite %6 %20 %21 %22
192          %39 = OpConstantComposite %6 %23 %24 %25
193          %40 = OpConstantComposite %6 %26 %27 %28
194          %41 = OpConstantComposite %7 %17 %18 %19 %20
195          %42 = OpConstantComposite %7 %21 %22 %23 %24
196          %43 = OpConstantComposite %7 %25 %26 %27 %28
197          %44 = OpConstantComposite %7 %29 %30 %31 %32
198 
199 ; Constant matrices
200          %45 = OpConstantComposite %8 %33 %34
201          %46 = OpConstantComposite %9 %33 %34 %35
202          %47 = OpConstantComposite %10 %33 %34 %35 %36
203          %48 = OpConstantComposite %11 %37 %38
204          %49 = OpConstantComposite %12 %37 %38 %39
205          %50 = OpConstantComposite %13 %37 %38 %39 %40
206          %51 = OpConstantComposite %14 %41 %42
207          %52 = OpConstantComposite %15 %41 %42 %43
208          %53 = OpConstantComposite %16 %41 %42 %43 %44
209 
210 ; main function
211          %54 = OpFunction %2 None %3
212          %55 = OpLabel
213 
214 ; Transposing a 2x2 matrix
215          %56 = OpTranspose %8 %45
216 
217 ; Transposing a 2x3 matrix
218          %57 = OpTranspose %11 %46
219 
220 ; Transposing a 2x4 matrix
221          %58 = OpTranspose %14 %47
222 
223 ; Transposing a 3x2 matrix
224          %59 = OpTranspose %9 %48
225 
226 ; Transposing a 3x3 matrix
227          %60 = OpTranspose %12 %49
228 
229 ; Transposing a 3x4 matrix
230          %61 = OpTranspose %15 %50
231 
232 ; Transposing a 4x2 matrix
233          %62 = OpTranspose %10 %51
234 
235 ; Transposing a 4x3 matrix
236          %63 = OpTranspose %13 %52
237 
238 ; Transposing a 4x4 matrix
239          %64 = OpTranspose %16 %53
240                OpReturn
241                OpFunctionEnd
242   )";
243 
244   const auto env = SPV_ENV_UNIVERSAL_1_5;
245   const auto consumer = nullptr;
246   const auto context =
247       BuildModule(env, consumer, reference_shader, kFuzzAssembleOption);
248   spvtools::ValidatorOptions validator_options;
249   ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
250                                                kConsoleMessageConsumer));
251   TransformationContext transformation_context(
252       MakeUnique<FactManager>(context.get()), validator_options);
253   auto instruction_descriptor =
254       MakeInstructionDescriptor(56, spv::Op::OpTranspose, 0);
255   auto transformation = TransformationReplaceLinearAlgebraInstruction(
256       {65, 66, 67, 68, 69, 70, 71, 72, 73, 74}, instruction_descriptor);
257   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
258 
259   instruction_descriptor =
260       MakeInstructionDescriptor(57, spv::Op::OpTranspose, 0);
261   transformation = TransformationReplaceLinearAlgebraInstruction(
262       {75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88},
263       instruction_descriptor);
264   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
265 
266   instruction_descriptor =
267       MakeInstructionDescriptor(58, spv::Op::OpTranspose, 0);
268   transformation = TransformationReplaceLinearAlgebraInstruction(
269       {89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105,
270        106},
271       instruction_descriptor);
272   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
273 
274   instruction_descriptor =
275       MakeInstructionDescriptor(59, spv::Op::OpTranspose, 0);
276   transformation = TransformationReplaceLinearAlgebraInstruction(
277       {107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120,
278        121},
279       instruction_descriptor);
280   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
281 
282   instruction_descriptor =
283       MakeInstructionDescriptor(60, spv::Op::OpTranspose, 0);
284   transformation = TransformationReplaceLinearAlgebraInstruction(
285       {122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132,
286        133, 134, 135, 136, 137, 138, 139, 140, 141, 142},
287       instruction_descriptor);
288   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
289 
290   std::string variant_shader = R"(
291                OpCapability Shader
292           %1 = OpExtInstImport "GLSL.std.450"
293                OpMemoryModel Logical GLSL450
294                OpEntryPoint Vertex %54 "main"
295 
296 ; Types
297           %2 = OpTypeVoid
298           %3 = OpTypeFunction %2
299           %4 = OpTypeFloat 32
300           %5 = OpTypeVector %4 2
301           %6 = OpTypeVector %4 3
302           %7 = OpTypeVector %4 4
303           %8 = OpTypeMatrix %5 2
304           %9 = OpTypeMatrix %5 3
305          %10 = OpTypeMatrix %5 4
306          %11 = OpTypeMatrix %6 2
307          %12 = OpTypeMatrix %6 3
308          %13 = OpTypeMatrix %6 4
309          %14 = OpTypeMatrix %7 2
310          %15 = OpTypeMatrix %7 3
311          %16 = OpTypeMatrix %7 4
312 
313 ; Constant scalars
314          %17 = OpConstant %4 1
315          %18 = OpConstant %4 2
316          %19 = OpConstant %4 3
317          %20 = OpConstant %4 4
318          %21 = OpConstant %4 5
319          %22 = OpConstant %4 6
320          %23 = OpConstant %4 7
321          %24 = OpConstant %4 8
322          %25 = OpConstant %4 9
323          %26 = OpConstant %4 10
324          %27 = OpConstant %4 11
325          %28 = OpConstant %4 12
326          %29 = OpConstant %4 13
327          %30 = OpConstant %4 14
328          %31 = OpConstant %4 15
329          %32 = OpConstant %4 16
330 
331 ; Constant vectors
332          %33 = OpConstantComposite %5 %17 %18
333          %34 = OpConstantComposite %5 %19 %20
334          %35 = OpConstantComposite %5 %21 %22
335          %36 = OpConstantComposite %5 %23 %24
336          %37 = OpConstantComposite %6 %17 %18 %19
337          %38 = OpConstantComposite %6 %20 %21 %22
338          %39 = OpConstantComposite %6 %23 %24 %25
339          %40 = OpConstantComposite %6 %26 %27 %28
340          %41 = OpConstantComposite %7 %17 %18 %19 %20
341          %42 = OpConstantComposite %7 %21 %22 %23 %24
342          %43 = OpConstantComposite %7 %25 %26 %27 %28
343          %44 = OpConstantComposite %7 %29 %30 %31 %32
344 
345 ; Constant matrices
346          %45 = OpConstantComposite %8 %33 %34
347          %46 = OpConstantComposite %9 %33 %34 %35
348          %47 = OpConstantComposite %10 %33 %34 %35 %36
349          %48 = OpConstantComposite %11 %37 %38
350          %49 = OpConstantComposite %12 %37 %38 %39
351          %50 = OpConstantComposite %13 %37 %38 %39 %40
352          %51 = OpConstantComposite %14 %41 %42
353          %52 = OpConstantComposite %15 %41 %42 %43
354          %53 = OpConstantComposite %16 %41 %42 %43 %44
355 
356 ; main function
357          %54 = OpFunction %2 None %3
358          %55 = OpLabel
359 
360 ; Transposing a 2x2 matrix
361          %65 = OpCompositeExtract %5 %45 0
362          %66 = OpCompositeExtract %4 %65 0
363          %67 = OpCompositeExtract %5 %45 1
364          %68 = OpCompositeExtract %4 %67 0
365          %69 = OpCompositeConstruct %5 %66 %68
366          %70 = OpCompositeExtract %5 %45 0
367          %71 = OpCompositeExtract %4 %70 1
368          %72 = OpCompositeExtract %5 %45 1
369          %73 = OpCompositeExtract %4 %72 1
370          %74 = OpCompositeConstruct %5 %71 %73
371          %56 = OpCompositeConstruct %8 %69 %74
372 
373 ; Transposing a 2x3 matrix
374          %75 = OpCompositeExtract %5 %46 0
375          %76 = OpCompositeExtract %4 %75 0
376          %77 = OpCompositeExtract %5 %46 1
377          %78 = OpCompositeExtract %4 %77 0
378          %79 = OpCompositeExtract %5 %46 2
379          %80 = OpCompositeExtract %4 %79 0
380          %81 = OpCompositeConstruct %6 %76 %78 %80
381          %82 = OpCompositeExtract %5 %46 0
382          %83 = OpCompositeExtract %4 %82 1
383          %84 = OpCompositeExtract %5 %46 1
384          %85 = OpCompositeExtract %4 %84 1
385          %86 = OpCompositeExtract %5 %46 2
386          %87 = OpCompositeExtract %4 %86 1
387          %88 = OpCompositeConstruct %6 %83 %85 %87
388          %57 = OpCompositeConstruct %11 %81 %88
389 
390 ; Transposing a 2x4 matrix
391          %89 = OpCompositeExtract %5 %47 0
392          %90 = OpCompositeExtract %4 %89 0
393          %91 = OpCompositeExtract %5 %47 1
394          %92 = OpCompositeExtract %4 %91 0
395          %93 = OpCompositeExtract %5 %47 2
396          %94 = OpCompositeExtract %4 %93 0
397          %95 = OpCompositeExtract %5 %47 3
398          %96 = OpCompositeExtract %4 %95 0
399          %97 = OpCompositeConstruct %7 %90 %92 %94 %96
400          %98 = OpCompositeExtract %5 %47 0
401          %99 = OpCompositeExtract %4 %98 1
402         %100 = OpCompositeExtract %5 %47 1
403         %101 = OpCompositeExtract %4 %100 1
404         %102 = OpCompositeExtract %5 %47 2
405         %103 = OpCompositeExtract %4 %102 1
406         %104 = OpCompositeExtract %5 %47 3
407         %105 = OpCompositeExtract %4 %104 1
408         %106 = OpCompositeConstruct %7 %99 %101 %103 %105
409          %58 = OpCompositeConstruct %14 %97 %106
410 
411 ; Transposing a 3x2 matrix
412         %107 = OpCompositeExtract %6 %48 0
413         %108 = OpCompositeExtract %4 %107 0
414         %109 = OpCompositeExtract %6 %48 1
415         %110 = OpCompositeExtract %4 %109 0
416         %111 = OpCompositeConstruct %5 %108 %110
417         %112 = OpCompositeExtract %6 %48 0
418         %113 = OpCompositeExtract %4 %112 1
419         %114 = OpCompositeExtract %6 %48 1
420         %115 = OpCompositeExtract %4 %114 1
421         %116 = OpCompositeConstruct %5 %113 %115
422         %117 = OpCompositeExtract %6 %48 0
423         %118 = OpCompositeExtract %4 %117 2
424         %119 = OpCompositeExtract %6 %48 1
425         %120 = OpCompositeExtract %4 %119 2
426         %121 = OpCompositeConstruct %5 %118 %120
427          %59 = OpCompositeConstruct %9 %111 %116 %121
428 
429 ; Transposing a 3x3 matrix
430         %122 = OpCompositeExtract %6 %49 0
431         %123 = OpCompositeExtract %4 %122 0
432         %124 = OpCompositeExtract %6 %49 1
433         %125 = OpCompositeExtract %4 %124 0
434         %126 = OpCompositeExtract %6 %49 2
435         %127 = OpCompositeExtract %4 %126 0
436         %128 = OpCompositeConstruct %6 %123 %125 %127
437         %129 = OpCompositeExtract %6 %49 0
438         %130 = OpCompositeExtract %4 %129 1
439         %131 = OpCompositeExtract %6 %49 1
440         %132 = OpCompositeExtract %4 %131 1
441         %133 = OpCompositeExtract %6 %49 2
442         %134 = OpCompositeExtract %4 %133 1
443         %135 = OpCompositeConstruct %6 %130 %132 %134
444         %136 = OpCompositeExtract %6 %49 0
445         %137 = OpCompositeExtract %4 %136 2
446         %138 = OpCompositeExtract %6 %49 1
447         %139 = OpCompositeExtract %4 %138 2
448         %140 = OpCompositeExtract %6 %49 2
449         %141 = OpCompositeExtract %4 %140 2
450         %142 = OpCompositeConstruct %6 %137 %139 %141
451          %60 = OpCompositeConstruct %12 %128 %135 %142
452 
453 ; Transposing a 3x4 matrix
454          %61 = OpTranspose %15 %50
455 
456 ; Transposing a 4x2 matrix
457          %62 = OpTranspose %10 %51
458 
459 ; Transposing a 4x3 matrix
460          %63 = OpTranspose %13 %52
461 
462 ; Transposing a 4x4 matrix
463          %64 = OpTranspose %16 %53
464                OpReturn
465                OpFunctionEnd
466   )";
467 
468   ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
469                                                kConsoleMessageConsumer));
470   ASSERT_TRUE(IsEqual(env, variant_shader, context.get()));
471 }
472 
TEST(TransformationReplaceLinearAlgebraInstructionTest, ReplaceOpVectorTimesScalar)473 TEST(TransformationReplaceLinearAlgebraInstructionTest,
474      ReplaceOpVectorTimesScalar) {
475   std::string reference_shader = R"(
476                OpCapability Shader
477           %1 = OpExtInstImport "GLSL.std.450"
478                OpMemoryModel Logical GLSL450
479                OpEntryPoint Fragment %15 "main"
480                OpExecutionMode %15 OriginUpperLeft
481                OpSource ESSL 310
482                OpName %15 "main"
483           %2 = OpTypeVoid
484           %3 = OpTypeFunction %2
485           %4 = OpTypeFloat 32
486           %5 = OpTypeVector %4 2
487           %6 = OpTypeVector %4 3
488           %7 = OpTypeVector %4 4
489           %8 = OpConstant %4 1
490           %9 = OpConstant %4 2
491          %10 = OpConstant %4 3
492          %11 = OpConstant %4 4
493          %12 = OpConstantComposite %5 %8 %9
494          %13 = OpConstantComposite %6 %8 %9 %10
495          %14 = OpConstantComposite %7 %8 %9 %10 %11
496          %15 = OpFunction %2 None %3
497          %16 = OpLabel
498          %17 = OpVectorTimesScalar %5 %12 %8
499          %18 = OpVectorTimesScalar %6 %13 %9
500          %19 = OpVectorTimesScalar %7 %14 %10
501                OpReturn
502                OpFunctionEnd
503   )";
504 
505   const auto env = SPV_ENV_UNIVERSAL_1_5;
506   const auto consumer = nullptr;
507   const auto context =
508       BuildModule(env, consumer, reference_shader, kFuzzAssembleOption);
509   spvtools::ValidatorOptions validator_options;
510   ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
511                                                kConsoleMessageConsumer));
512   TransformationContext transformation_context(
513       MakeUnique<FactManager>(context.get()), validator_options);
514   auto instruction_descriptor =
515       MakeInstructionDescriptor(17, spv::Op::OpVectorTimesScalar, 0);
516   auto transformation = TransformationReplaceLinearAlgebraInstruction(
517       {20, 21, 22, 23}, instruction_descriptor);
518   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
519 
520   instruction_descriptor =
521       MakeInstructionDescriptor(18, spv::Op::OpVectorTimesScalar, 0);
522   transformation = TransformationReplaceLinearAlgebraInstruction(
523       {24, 25, 26, 27, 28, 29}, instruction_descriptor);
524   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
525 
526   instruction_descriptor =
527       MakeInstructionDescriptor(19, spv::Op::OpVectorTimesScalar, 0);
528   transformation = TransformationReplaceLinearAlgebraInstruction(
529       {30, 31, 32, 33, 34, 35, 36, 37}, instruction_descriptor);
530   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
531 
532   std::string variant_shader = R"(
533                OpCapability Shader
534           %1 = OpExtInstImport "GLSL.std.450"
535                OpMemoryModel Logical GLSL450
536                OpEntryPoint Fragment %15 "main"
537                OpExecutionMode %15 OriginUpperLeft
538                OpSource ESSL 310
539                OpName %15 "main"
540           %2 = OpTypeVoid
541           %3 = OpTypeFunction %2
542           %4 = OpTypeFloat 32
543           %5 = OpTypeVector %4 2
544           %6 = OpTypeVector %4 3
545           %7 = OpTypeVector %4 4
546           %8 = OpConstant %4 1
547           %9 = OpConstant %4 2
548          %10 = OpConstant %4 3
549          %11 = OpConstant %4 4
550          %12 = OpConstantComposite %5 %8 %9
551          %13 = OpConstantComposite %6 %8 %9 %10
552          %14 = OpConstantComposite %7 %8 %9 %10 %11
553          %15 = OpFunction %2 None %3
554          %16 = OpLabel
555          %20 = OpCompositeExtract %4 %12 0
556          %21 = OpFMul %4 %20 %8
557          %22 = OpCompositeExtract %4 %12 1
558          %23 = OpFMul %4 %22 %8
559          %17 = OpCompositeConstruct %5 %21 %23
560          %24 = OpCompositeExtract %4 %13 0
561          %25 = OpFMul %4 %24 %9
562          %26 = OpCompositeExtract %4 %13 1
563          %27 = OpFMul %4 %26 %9
564          %28 = OpCompositeExtract %4 %13 2
565          %29 = OpFMul %4 %28 %9
566          %18 = OpCompositeConstruct %6 %25 %27 %29
567          %30 = OpCompositeExtract %4 %14 0
568          %31 = OpFMul %4 %30 %10
569          %32 = OpCompositeExtract %4 %14 1
570          %33 = OpFMul %4 %32 %10
571          %34 = OpCompositeExtract %4 %14 2
572          %35 = OpFMul %4 %34 %10
573          %36 = OpCompositeExtract %4 %14 3
574          %37 = OpFMul %4 %36 %10
575          %19 = OpCompositeConstruct %7 %31 %33 %35 %37
576                OpReturn
577                OpFunctionEnd
578   )";
579 
580   ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
581                                                kConsoleMessageConsumer));
582   ASSERT_TRUE(IsEqual(env, variant_shader, context.get()));
583 }
584 
TEST(TransformationReplaceLinearAlgebraInstructionTest, ReplaceOpMatrixTimesScalar)585 TEST(TransformationReplaceLinearAlgebraInstructionTest,
586      ReplaceOpMatrixTimesScalar) {
587   std::string reference_shader = R"(
588                OpCapability Shader
589           %1 = OpExtInstImport "GLSL.std.450"
590                OpMemoryModel Logical GLSL450
591                OpEntryPoint Fragment %54 "main"
592                OpExecutionMode %54 OriginUpperLeft
593 
594 ; Types
595           %2 = OpTypeVoid
596           %3 = OpTypeFunction %2
597           %4 = OpTypeFloat 32
598           %5 = OpTypeVector %4 2
599           %6 = OpTypeVector %4 3
600           %7 = OpTypeVector %4 4
601           %8 = OpTypeMatrix %5 2
602           %9 = OpTypeMatrix %5 3
603          %10 = OpTypeMatrix %5 4
604          %11 = OpTypeMatrix %6 2
605          %12 = OpTypeMatrix %6 3
606          %13 = OpTypeMatrix %6 4
607          %14 = OpTypeMatrix %7 2
608          %15 = OpTypeMatrix %7 3
609          %16 = OpTypeMatrix %7 4
610 
611 ; Constant scalars
612          %17 = OpConstant %4 1
613          %18 = OpConstant %4 2
614          %19 = OpConstant %4 3
615          %20 = OpConstant %4 4
616          %21 = OpConstant %4 5
617          %22 = OpConstant %4 6
618          %23 = OpConstant %4 7
619          %24 = OpConstant %4 8
620          %25 = OpConstant %4 9
621          %26 = OpConstant %4 10
622          %27 = OpConstant %4 11
623          %28 = OpConstant %4 12
624          %29 = OpConstant %4 13
625          %30 = OpConstant %4 14
626          %31 = OpConstant %4 15
627          %32 = OpConstant %4 16
628 
629 ; Constant vectors
630          %33 = OpConstantComposite %5 %17 %18
631          %34 = OpConstantComposite %5 %19 %20
632          %35 = OpConstantComposite %5 %21 %22
633          %36 = OpConstantComposite %5 %23 %24
634          %37 = OpConstantComposite %6 %17 %18 %19
635          %38 = OpConstantComposite %6 %20 %21 %22
636          %39 = OpConstantComposite %6 %23 %24 %25
637          %40 = OpConstantComposite %6 %26 %27 %28
638          %41 = OpConstantComposite %7 %17 %18 %19 %20
639          %42 = OpConstantComposite %7 %21 %22 %23 %24
640          %43 = OpConstantComposite %7 %25 %26 %27 %28
641          %44 = OpConstantComposite %7 %29 %30 %31 %32
642 
643 ; Constant matrices
644          %45 = OpConstantComposite %8 %33 %34
645          %46 = OpConstantComposite %9 %33 %34 %35
646          %47 = OpConstantComposite %10 %33 %34 %35 %36
647          %48 = OpConstantComposite %11 %37 %38
648          %49 = OpConstantComposite %12 %37 %38 %39
649          %50 = OpConstantComposite %13 %37 %38 %39 %40
650          %51 = OpConstantComposite %14 %41 %42
651          %52 = OpConstantComposite %15 %41 %42 %43
652          %53 = OpConstantComposite %16 %41 %42 %43 %44
653 
654 ; main function
655          %54 = OpFunction %2 None %3
656          %55 = OpLabel
657 
658 ; Multiplying 2-row matrices by scalar
659          %56 = OpMatrixTimesScalar %8 %45 %17
660          %57 = OpMatrixTimesScalar %9 %46 %18
661          %58 = OpMatrixTimesScalar %10 %47 %19
662 
663 ; Multiplying 3-row matrices by scalar
664          %59 = OpMatrixTimesScalar %11 %48 %21
665          %60 = OpMatrixTimesScalar %12 %49 %22
666          %61 = OpMatrixTimesScalar %13 %50 %23
667 
668 ; Multiplying 4-row matrices by scalar
669          %62 = OpMatrixTimesScalar %14 %51 %24
670          %63 = OpMatrixTimesScalar %15 %52 %25
671          %64 = OpMatrixTimesScalar %16 %53 %26
672                OpReturn
673                OpFunctionEnd
674   )";
675 
676   const auto env = SPV_ENV_UNIVERSAL_1_5;
677   const auto consumer = nullptr;
678   const auto context =
679       BuildModule(env, consumer, reference_shader, kFuzzAssembleOption);
680   spvtools::ValidatorOptions validator_options;
681   ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
682                                                kConsoleMessageConsumer));
683   TransformationContext transformation_context(
684       MakeUnique<FactManager>(context.get()), validator_options);
685   auto instruction_descriptor =
686       MakeInstructionDescriptor(56, spv::Op::OpMatrixTimesScalar, 0);
687   auto transformation = TransformationReplaceLinearAlgebraInstruction(
688       {65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76}, instruction_descriptor);
689   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
690 
691   instruction_descriptor =
692       MakeInstructionDescriptor(57, spv::Op::OpMatrixTimesScalar, 0);
693   transformation = TransformationReplaceLinearAlgebraInstruction(
694       {77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94},
695       instruction_descriptor);
696   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
697 
698   instruction_descriptor =
699       MakeInstructionDescriptor(58, spv::Op::OpMatrixTimesScalar, 0);
700   transformation = TransformationReplaceLinearAlgebraInstruction(
701       {95,  96,  97,  98,  99,  100, 101, 102, 103, 104, 105, 106,
702        107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118},
703       instruction_descriptor);
704   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
705 
706   std::string variant_shader = R"(
707                OpCapability Shader
708           %1 = OpExtInstImport "GLSL.std.450"
709                OpMemoryModel Logical GLSL450
710                OpEntryPoint Fragment %54 "main"
711                OpExecutionMode %54 OriginUpperLeft
712 
713 ; Types
714           %2 = OpTypeVoid
715           %3 = OpTypeFunction %2
716           %4 = OpTypeFloat 32
717           %5 = OpTypeVector %4 2
718           %6 = OpTypeVector %4 3
719           %7 = OpTypeVector %4 4
720           %8 = OpTypeMatrix %5 2
721           %9 = OpTypeMatrix %5 3
722          %10 = OpTypeMatrix %5 4
723          %11 = OpTypeMatrix %6 2
724          %12 = OpTypeMatrix %6 3
725          %13 = OpTypeMatrix %6 4
726          %14 = OpTypeMatrix %7 2
727          %15 = OpTypeMatrix %7 3
728          %16 = OpTypeMatrix %7 4
729 
730 ; Constant scalars
731          %17 = OpConstant %4 1
732          %18 = OpConstant %4 2
733          %19 = OpConstant %4 3
734          %20 = OpConstant %4 4
735          %21 = OpConstant %4 5
736          %22 = OpConstant %4 6
737          %23 = OpConstant %4 7
738          %24 = OpConstant %4 8
739          %25 = OpConstant %4 9
740          %26 = OpConstant %4 10
741          %27 = OpConstant %4 11
742          %28 = OpConstant %4 12
743          %29 = OpConstant %4 13
744          %30 = OpConstant %4 14
745          %31 = OpConstant %4 15
746          %32 = OpConstant %4 16
747 
748 ; Constant vectors
749          %33 = OpConstantComposite %5 %17 %18
750          %34 = OpConstantComposite %5 %19 %20
751          %35 = OpConstantComposite %5 %21 %22
752          %36 = OpConstantComposite %5 %23 %24
753          %37 = OpConstantComposite %6 %17 %18 %19
754          %38 = OpConstantComposite %6 %20 %21 %22
755          %39 = OpConstantComposite %6 %23 %24 %25
756          %40 = OpConstantComposite %6 %26 %27 %28
757          %41 = OpConstantComposite %7 %17 %18 %19 %20
758          %42 = OpConstantComposite %7 %21 %22 %23 %24
759          %43 = OpConstantComposite %7 %25 %26 %27 %28
760          %44 = OpConstantComposite %7 %29 %30 %31 %32
761 
762 ; Constant matrices
763          %45 = OpConstantComposite %8 %33 %34
764          %46 = OpConstantComposite %9 %33 %34 %35
765          %47 = OpConstantComposite %10 %33 %34 %35 %36
766          %48 = OpConstantComposite %11 %37 %38
767          %49 = OpConstantComposite %12 %37 %38 %39
768          %50 = OpConstantComposite %13 %37 %38 %39 %40
769          %51 = OpConstantComposite %14 %41 %42
770          %52 = OpConstantComposite %15 %41 %42 %43
771          %53 = OpConstantComposite %16 %41 %42 %43 %44
772 
773 ; main function
774          %54 = OpFunction %2 None %3
775          %55 = OpLabel
776 
777 ; Multiplying 2x2 matrix by scalar
778          %65 = OpCompositeExtract %5 %45 0
779          %66 = OpCompositeExtract %4 %65 0
780          %67 = OpFMul %4 %66 %17
781          %68 = OpCompositeExtract %4 %65 1
782          %69 = OpFMul %4 %68 %17
783          %70 = OpCompositeConstruct %5 %67 %69
784          %71 = OpCompositeExtract %5 %45 1
785          %72 = OpCompositeExtract %4 %71 0
786          %73 = OpFMul %4 %72 %17
787          %74 = OpCompositeExtract %4 %71 1
788          %75 = OpFMul %4 %74 %17
789          %76 = OpCompositeConstruct %5 %73 %75
790          %56 = OpCompositeConstruct %8 %70 %76
791 
792 ; Multiplying 2x3 matrix by scalar
793          %77 = OpCompositeExtract %5 %46 0
794          %78 = OpCompositeExtract %4 %77 0
795          %79 = OpFMul %4 %78 %18
796          %80 = OpCompositeExtract %4 %77 1
797          %81 = OpFMul %4 %80 %18
798          %82 = OpCompositeConstruct %5 %79 %81
799          %83 = OpCompositeExtract %5 %46 1
800          %84 = OpCompositeExtract %4 %83 0
801          %85 = OpFMul %4 %84 %18
802          %86 = OpCompositeExtract %4 %83 1
803          %87 = OpFMul %4 %86 %18
804          %88 = OpCompositeConstruct %5 %85 %87
805          %89 = OpCompositeExtract %5 %46 2
806          %90 = OpCompositeExtract %4 %89 0
807          %91 = OpFMul %4 %90 %18
808          %92 = OpCompositeExtract %4 %89 1
809          %93 = OpFMul %4 %92 %18
810          %94 = OpCompositeConstruct %5 %91 %93
811          %57 = OpCompositeConstruct %9 %82 %88 %94
812 
813 ; Multiplying 2x4 matrix by scalar
814          %95 = OpCompositeExtract %5 %47 0
815          %96 = OpCompositeExtract %4 %95 0
816          %97 = OpFMul %4 %96 %19
817          %98 = OpCompositeExtract %4 %95 1
818          %99 = OpFMul %4 %98 %19
819         %100 = OpCompositeConstruct %5 %97 %99
820         %101 = OpCompositeExtract %5 %47 1
821         %102 = OpCompositeExtract %4 %101 0
822         %103 = OpFMul %4 %102 %19
823         %104 = OpCompositeExtract %4 %101 1
824         %105 = OpFMul %4 %104 %19
825         %106 = OpCompositeConstruct %5 %103 %105
826         %107 = OpCompositeExtract %5 %47 2
827         %108 = OpCompositeExtract %4 %107 0
828         %109 = OpFMul %4 %108 %19
829         %110 = OpCompositeExtract %4 %107 1
830         %111 = OpFMul %4 %110 %19
831         %112 = OpCompositeConstruct %5 %109 %111
832         %113 = OpCompositeExtract %5 %47 3
833         %114 = OpCompositeExtract %4 %113 0
834         %115 = OpFMul %4 %114 %19
835         %116 = OpCompositeExtract %4 %113 1
836         %117 = OpFMul %4 %116 %19
837         %118 = OpCompositeConstruct %5 %115 %117
838          %58 = OpCompositeConstruct %10 %100 %106 %112 %118
839 
840 ; Multiplying 3-row matrices by scalar
841          %59 = OpMatrixTimesScalar %11 %48 %21
842          %60 = OpMatrixTimesScalar %12 %49 %22
843          %61 = OpMatrixTimesScalar %13 %50 %23
844 
845 ; Multiplying 4-row matrices by scalar
846          %62 = OpMatrixTimesScalar %14 %51 %24
847          %63 = OpMatrixTimesScalar %15 %52 %25
848          %64 = OpMatrixTimesScalar %16 %53 %26
849                OpReturn
850                OpFunctionEnd
851   )";
852 
853   ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
854                                                kConsoleMessageConsumer));
855   ASSERT_TRUE(IsEqual(env, variant_shader, context.get()));
856 }
857 
TEST(TransformationReplaceLinearAlgebraInstructionTest, ReplaceOpVectorTimesMatrix)858 TEST(TransformationReplaceLinearAlgebraInstructionTest,
859      ReplaceOpVectorTimesMatrix) {
860   std::string reference_shader = R"(
861                OpCapability Shader
862           %1 = OpExtInstImport "GLSL.std.450"
863                OpMemoryModel Logical GLSL450
864                OpEntryPoint Fragment %54 "main"
865                OpExecutionMode %54 OriginUpperLeft
866                OpSource ESSL 310
867                OpName %54 "main"
868 
869 ; Types
870           %2 = OpTypeVoid
871           %3 = OpTypeFunction %2
872           %4 = OpTypeFloat 32
873           %5 = OpTypeVector %4 2
874           %6 = OpTypeVector %4 3
875           %7 = OpTypeVector %4 4
876           %8 = OpTypeMatrix %5 2
877           %9 = OpTypeMatrix %5 3
878          %10 = OpTypeMatrix %5 4
879          %11 = OpTypeMatrix %6 2
880          %12 = OpTypeMatrix %6 3
881          %13 = OpTypeMatrix %6 4
882          %14 = OpTypeMatrix %7 2
883          %15 = OpTypeMatrix %7 3
884          %16 = OpTypeMatrix %7 4
885 
886 ; Constant scalars
887          %17 = OpConstant %4 1
888          %18 = OpConstant %4 2
889          %19 = OpConstant %4 3
890          %20 = OpConstant %4 4
891          %21 = OpConstant %4 5
892          %22 = OpConstant %4 6
893          %23 = OpConstant %4 7
894          %24 = OpConstant %4 8
895          %25 = OpConstant %4 9
896          %26 = OpConstant %4 10
897          %27 = OpConstant %4 11
898          %28 = OpConstant %4 12
899          %29 = OpConstant %4 13
900          %30 = OpConstant %4 14
901          %31 = OpConstant %4 15
902          %32 = OpConstant %4 16
903 
904 ; Constant vectors
905          %33 = OpConstantComposite %5 %17 %18
906          %34 = OpConstantComposite %5 %19 %20
907          %35 = OpConstantComposite %5 %21 %22
908          %36 = OpConstantComposite %5 %23 %24
909          %37 = OpConstantComposite %6 %17 %18 %19
910          %38 = OpConstantComposite %6 %20 %21 %22
911          %39 = OpConstantComposite %6 %23 %24 %25
912          %40 = OpConstantComposite %6 %26 %27 %28
913          %41 = OpConstantComposite %7 %17 %18 %19 %20
914          %42 = OpConstantComposite %7 %21 %22 %23 %24
915          %43 = OpConstantComposite %7 %25 %26 %27 %28
916          %44 = OpConstantComposite %7 %29 %30 %31 %32
917 
918 ; Constant matrices
919          %45 = OpConstantComposite %8 %33 %34
920          %46 = OpConstantComposite %9 %33 %34 %35
921          %47 = OpConstantComposite %10 %33 %34 %35 %36
922          %48 = OpConstantComposite %11 %37 %38
923          %49 = OpConstantComposite %12 %37 %38 %39
924          %50 = OpConstantComposite %13 %37 %38 %39 %40
925          %51 = OpConstantComposite %14 %41 %42
926          %52 = OpConstantComposite %15 %41 %42 %43
927          %53 = OpConstantComposite %16 %41 %42 %43 %44
928 
929 ; main function
930          %54 = OpFunction %2 None %3
931          %55 = OpLabel
932 
933 ; Multiplying 2-dimensional vector by 2x2 matrix
934          %56 = OpVectorTimesMatrix %5 %33 %45
935 
936 ; Multiplying 2-dimensional vector by 2x3 matrix
937          %57 = OpVectorTimesMatrix %6 %34 %46
938 
939 ; Multiplying 2-dimensional vector by 2x4 matrix
940          %58 = OpVectorTimesMatrix %7 %35 %47
941 
942 ; Multiplying 3-dimensional vector by 3x2 matrix
943          %59 = OpVectorTimesMatrix %5 %37 %48
944 
945 ; Multiplying 3-dimensional vector by 3x3 matrix
946          %60 = OpVectorTimesMatrix %6 %38 %49
947 
948 ; Multiplying 3-dimensional vector by 3x4 matrix
949          %61 = OpVectorTimesMatrix %7 %39 %50
950 
951 ; Multiplying 4-dimensional vector by 4x2 matrix
952          %62 = OpVectorTimesMatrix %5 %41 %51
953 
954 ; Multiplying 4-dimensional vector by 4x3 matrix
955          %63 = OpVectorTimesMatrix %6 %42 %52
956 
957 ; Multiplying 4-dimensional vector by 4x4 matrix
958          %64 = OpVectorTimesMatrix %7 %43 %53
959                OpReturn
960                OpFunctionEnd
961   )";
962 
963   const auto env = SPV_ENV_UNIVERSAL_1_5;
964   const auto consumer = nullptr;
965   const auto context =
966       BuildModule(env, consumer, reference_shader, kFuzzAssembleOption);
967   spvtools::ValidatorOptions validator_options;
968   ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
969                                                kConsoleMessageConsumer));
970   TransformationContext transformation_context(
971       MakeUnique<FactManager>(context.get()), validator_options);
972   auto instruction_descriptor =
973       MakeInstructionDescriptor(56, spv::Op::OpVectorTimesMatrix, 0);
974   auto transformation = TransformationReplaceLinearAlgebraInstruction(
975       {65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78},
976       instruction_descriptor);
977   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
978 
979   instruction_descriptor =
980       MakeInstructionDescriptor(57, spv::Op::OpVectorTimesMatrix, 0);
981   transformation = TransformationReplaceLinearAlgebraInstruction(
982       {79, 80, 81, 82, 83, 84, 85, 86, 87, 88,
983        89, 90, 91, 92, 93, 94, 95, 96, 97, 98},
984       instruction_descriptor);
985   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
986 
987   instruction_descriptor =
988       MakeInstructionDescriptor(58, spv::Op::OpVectorTimesMatrix, 0);
989   transformation = TransformationReplaceLinearAlgebraInstruction(
990       {99,  100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
991        112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124},
992       instruction_descriptor);
993   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
994 
995   instruction_descriptor =
996       MakeInstructionDescriptor(59, spv::Op::OpVectorTimesMatrix, 0);
997   transformation = TransformationReplaceLinearAlgebraInstruction(
998       {125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135,
999        136, 137, 138, 139, 140, 141, 142, 143, 144, 145},
1000       instruction_descriptor);
1001   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
1002 
1003   std::string variant_shader = R"(
1004                OpCapability Shader
1005           %1 = OpExtInstImport "GLSL.std.450"
1006                OpMemoryModel Logical GLSL450
1007                OpEntryPoint Fragment %54 "main"
1008                OpExecutionMode %54 OriginUpperLeft
1009                OpSource ESSL 310
1010                OpName %54 "main"
1011 
1012 ; Types
1013           %2 = OpTypeVoid
1014           %3 = OpTypeFunction %2
1015           %4 = OpTypeFloat 32
1016           %5 = OpTypeVector %4 2
1017           %6 = OpTypeVector %4 3
1018           %7 = OpTypeVector %4 4
1019           %8 = OpTypeMatrix %5 2
1020           %9 = OpTypeMatrix %5 3
1021          %10 = OpTypeMatrix %5 4
1022          %11 = OpTypeMatrix %6 2
1023          %12 = OpTypeMatrix %6 3
1024          %13 = OpTypeMatrix %6 4
1025          %14 = OpTypeMatrix %7 2
1026          %15 = OpTypeMatrix %7 3
1027          %16 = OpTypeMatrix %7 4
1028 
1029 ; Constant scalars
1030          %17 = OpConstant %4 1
1031          %18 = OpConstant %4 2
1032          %19 = OpConstant %4 3
1033          %20 = OpConstant %4 4
1034          %21 = OpConstant %4 5
1035          %22 = OpConstant %4 6
1036          %23 = OpConstant %4 7
1037          %24 = OpConstant %4 8
1038          %25 = OpConstant %4 9
1039          %26 = OpConstant %4 10
1040          %27 = OpConstant %4 11
1041          %28 = OpConstant %4 12
1042          %29 = OpConstant %4 13
1043          %30 = OpConstant %4 14
1044          %31 = OpConstant %4 15
1045          %32 = OpConstant %4 16
1046 
1047 ; Constant vectors
1048          %33 = OpConstantComposite %5 %17 %18
1049          %34 = OpConstantComposite %5 %19 %20
1050          %35 = OpConstantComposite %5 %21 %22
1051          %36 = OpConstantComposite %5 %23 %24
1052          %37 = OpConstantComposite %6 %17 %18 %19
1053          %38 = OpConstantComposite %6 %20 %21 %22
1054          %39 = OpConstantComposite %6 %23 %24 %25
1055          %40 = OpConstantComposite %6 %26 %27 %28
1056          %41 = OpConstantComposite %7 %17 %18 %19 %20
1057          %42 = OpConstantComposite %7 %21 %22 %23 %24
1058          %43 = OpConstantComposite %7 %25 %26 %27 %28
1059          %44 = OpConstantComposite %7 %29 %30 %31 %32
1060 
1061 ; Constant matrices
1062          %45 = OpConstantComposite %8 %33 %34
1063          %46 = OpConstantComposite %9 %33 %34 %35
1064          %47 = OpConstantComposite %10 %33 %34 %35 %36
1065          %48 = OpConstantComposite %11 %37 %38
1066          %49 = OpConstantComposite %12 %37 %38 %39
1067          %50 = OpConstantComposite %13 %37 %38 %39 %40
1068          %51 = OpConstantComposite %14 %41 %42
1069          %52 = OpConstantComposite %15 %41 %42 %43
1070          %53 = OpConstantComposite %16 %41 %42 %43 %44
1071 
1072 ; main function
1073          %54 = OpFunction %2 None %3
1074          %55 = OpLabel
1075 
1076 ; Multiplying 2-dimensional vector by 2x2 matrix
1077          %65 = OpCompositeExtract %4 %33 0
1078          %66 = OpCompositeExtract %4 %33 1
1079          %67 = OpCompositeExtract %5 %45 0
1080          %68 = OpCompositeExtract %4 %67 0
1081          %69 = OpFMul %4 %65 %68
1082          %70 = OpCompositeExtract %4 %67 1
1083          %71 = OpFMul %4 %66 %70
1084          %72 = OpFAdd %4 %69 %71
1085          %73 = OpCompositeExtract %5 %45 1
1086          %74 = OpCompositeExtract %4 %73 0
1087          %75 = OpFMul %4 %65 %74
1088          %76 = OpCompositeExtract %4 %73 1
1089          %77 = OpFMul %4 %66 %76
1090          %78 = OpFAdd %4 %75 %77
1091          %56 = OpCompositeConstruct %5 %72 %78
1092 
1093 ; Multiplying 2-dimensional vector by 2x3 matrix
1094          %79 = OpCompositeExtract %4 %34 0
1095          %80 = OpCompositeExtract %4 %34 1
1096          %81 = OpCompositeExtract %5 %46 0
1097          %82 = OpCompositeExtract %4 %81 0
1098          %83 = OpFMul %4 %79 %82
1099          %84 = OpCompositeExtract %4 %81 1
1100          %85 = OpFMul %4 %80 %84
1101          %86 = OpFAdd %4 %83 %85
1102          %87 = OpCompositeExtract %5 %46 1
1103          %88 = OpCompositeExtract %4 %87 0
1104          %89 = OpFMul %4 %79 %88
1105          %90 = OpCompositeExtract %4 %87 1
1106          %91 = OpFMul %4 %80 %90
1107          %92 = OpFAdd %4 %89 %91
1108          %93 = OpCompositeExtract %5 %46 2
1109          %94 = OpCompositeExtract %4 %93 0
1110          %95 = OpFMul %4 %79 %94
1111          %96 = OpCompositeExtract %4 %93 1
1112          %97 = OpFMul %4 %80 %96
1113          %98 = OpFAdd %4 %95 %97
1114          %57 = OpCompositeConstruct %6 %86 %92 %98
1115 
1116 ; Multiplying 2-dimensional vector by 2x4 matrix
1117          %99 = OpCompositeExtract %4 %35 0
1118         %100 = OpCompositeExtract %4 %35 1
1119         %101 = OpCompositeExtract %5 %47 0
1120         %102 = OpCompositeExtract %4 %101 0
1121         %103 = OpFMul %4 %99 %102
1122         %104 = OpCompositeExtract %4 %101 1
1123         %105 = OpFMul %4 %100 %104
1124         %106 = OpFAdd %4 %103 %105
1125         %107 = OpCompositeExtract %5 %47 1
1126         %108 = OpCompositeExtract %4 %107 0
1127         %109 = OpFMul %4 %99 %108
1128         %110 = OpCompositeExtract %4 %107 1
1129         %111 = OpFMul %4 %100 %110
1130         %112 = OpFAdd %4 %109 %111
1131         %113 = OpCompositeExtract %5 %47 2
1132         %114 = OpCompositeExtract %4 %113 0
1133         %115 = OpFMul %4 %99 %114
1134         %116 = OpCompositeExtract %4 %113 1
1135         %117 = OpFMul %4 %100 %116
1136         %118 = OpFAdd %4 %115 %117
1137         %119 = OpCompositeExtract %5 %47 3
1138         %120 = OpCompositeExtract %4 %119 0
1139         %121 = OpFMul %4 %99 %120
1140         %122 = OpCompositeExtract %4 %119 1
1141         %123 = OpFMul %4 %100 %122
1142         %124 = OpFAdd %4 %121 %123
1143          %58 = OpCompositeConstruct %7 %106 %112 %118 %124
1144 
1145 ; Multiplying 3-dimensional vector by 3x2 matrix
1146         %125 = OpCompositeExtract %4 %37 0
1147         %126 = OpCompositeExtract %4 %37 1
1148         %127 = OpCompositeExtract %4 %37 2
1149         %128 = OpCompositeExtract %6 %48 0
1150         %129 = OpCompositeExtract %4 %128 0
1151         %130 = OpFMul %4 %125 %129
1152         %131 = OpCompositeExtract %4 %128 1
1153         %132 = OpFMul %4 %126 %131
1154         %133 = OpCompositeExtract %4 %128 2
1155         %134 = OpFMul %4 %127 %133
1156         %135 = OpFAdd %4 %130 %132
1157         %136 = OpFAdd %4 %134 %135
1158         %137 = OpCompositeExtract %6 %48 1
1159         %138 = OpCompositeExtract %4 %137 0
1160         %139 = OpFMul %4 %125 %138
1161         %140 = OpCompositeExtract %4 %137 1
1162         %141 = OpFMul %4 %126 %140
1163         %142 = OpCompositeExtract %4 %137 2
1164         %143 = OpFMul %4 %127 %142
1165         %144 = OpFAdd %4 %139 %141
1166         %145 = OpFAdd %4 %143 %144
1167          %59 = OpCompositeConstruct %5 %136 %145
1168 
1169 ; Multiplying 3-dimensional vector by 3x3 matrix
1170          %60 = OpVectorTimesMatrix %6 %38 %49
1171 
1172 ; Multiplying 3-dimensional vector by 3x4 matrix
1173          %61 = OpVectorTimesMatrix %7 %39 %50
1174 
1175 ; Multiplying 4-dimensional vector by 4x2 matrix
1176          %62 = OpVectorTimesMatrix %5 %41 %51
1177 
1178 ; Multiplying 4-dimensional vector by 4x3 matrix
1179          %63 = OpVectorTimesMatrix %6 %42 %52
1180 
1181 ; Multiplying 4-dimensional vector by 4x4 matrix
1182          %64 = OpVectorTimesMatrix %7 %43 %53
1183                OpReturn
1184                OpFunctionEnd
1185   )";
1186 
1187   ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
1188                                                kConsoleMessageConsumer));
1189   ASSERT_TRUE(IsEqual(env, variant_shader, context.get()));
1190 }
1191 
TEST(TransformationReplaceLinearAlgebraInstructionTest, ReplaceOpMatrixTimesVector)1192 TEST(TransformationReplaceLinearAlgebraInstructionTest,
1193      ReplaceOpMatrixTimesVector) {
1194   std::string reference_shader = R"(
1195                OpCapability Shader
1196           %1 = OpExtInstImport "GLSL.std.450"
1197                OpMemoryModel Logical GLSL450
1198                OpEntryPoint Fragment %54 "main"
1199                OpExecutionMode %54 OriginUpperLeft
1200                OpSource ESSL 310
1201                OpName %54 "main"
1202 
1203 ; Types
1204           %2 = OpTypeVoid
1205           %3 = OpTypeFunction %2
1206           %4 = OpTypeFloat 32
1207           %5 = OpTypeVector %4 2
1208           %6 = OpTypeVector %4 3
1209           %7 = OpTypeVector %4 4
1210           %8 = OpTypeMatrix %5 2
1211           %9 = OpTypeMatrix %5 3
1212          %10 = OpTypeMatrix %5 4
1213          %11 = OpTypeMatrix %6 2
1214          %12 = OpTypeMatrix %6 3
1215          %13 = OpTypeMatrix %6 4
1216          %14 = OpTypeMatrix %7 2
1217          %15 = OpTypeMatrix %7 3
1218          %16 = OpTypeMatrix %7 4
1219 
1220 ; Constant scalars
1221          %17 = OpConstant %4 1
1222          %18 = OpConstant %4 2
1223          %19 = OpConstant %4 3
1224          %20 = OpConstant %4 4
1225          %21 = OpConstant %4 5
1226          %22 = OpConstant %4 6
1227          %23 = OpConstant %4 7
1228          %24 = OpConstant %4 8
1229          %25 = OpConstant %4 9
1230          %26 = OpConstant %4 10
1231          %27 = OpConstant %4 11
1232          %28 = OpConstant %4 12
1233          %29 = OpConstant %4 13
1234          %30 = OpConstant %4 14
1235          %31 = OpConstant %4 15
1236          %32 = OpConstant %4 16
1237 
1238 ; Constant vectors
1239          %33 = OpConstantComposite %5 %17 %18
1240          %34 = OpConstantComposite %5 %19 %20
1241          %35 = OpConstantComposite %5 %21 %22
1242          %36 = OpConstantComposite %5 %23 %24
1243          %37 = OpConstantComposite %6 %17 %18 %19
1244          %38 = OpConstantComposite %6 %20 %21 %22
1245          %39 = OpConstantComposite %6 %23 %24 %25
1246          %40 = OpConstantComposite %6 %26 %27 %28
1247          %41 = OpConstantComposite %7 %17 %18 %19 %20
1248          %42 = OpConstantComposite %7 %21 %22 %23 %24
1249          %43 = OpConstantComposite %7 %25 %26 %27 %28
1250          %44 = OpConstantComposite %7 %29 %30 %31 %32
1251 
1252 ; Constant matrices
1253          %45 = OpConstantComposite %8 %33 %34
1254          %46 = OpConstantComposite %9 %33 %34 %35
1255          %47 = OpConstantComposite %10 %33 %34 %35 %36
1256          %48 = OpConstantComposite %11 %37 %38
1257          %49 = OpConstantComposite %12 %37 %38 %39
1258          %50 = OpConstantComposite %13 %37 %38 %39 %40
1259          %51 = OpConstantComposite %14 %41 %42
1260          %52 = OpConstantComposite %15 %41 %42 %43
1261          %53 = OpConstantComposite %16 %41 %42 %43 %44
1262 
1263 ; main function
1264          %54 = OpFunction %2 None %3
1265          %55 = OpLabel
1266 
1267 ; Multiplying 2x2 matrix by 2-dimensional vector
1268          %56 = OpMatrixTimesVector %5 %45 %33
1269 
1270 ; Multiplying 3x2 matrix by 2-dimensional vector
1271          %57 = OpMatrixTimesVector %6 %48 %34
1272 
1273 ; Multiplying 4x2 matrix by 2-dimensional vector
1274          %58 = OpMatrixTimesVector %7 %51 %35
1275 
1276 ; Multiplying 2x3 matrix by 3-dimensional vector
1277          %59 = OpMatrixTimesVector %5 %46 %37
1278 
1279 ; Multiplying 3x3 matrix by 3-dimensional vector
1280          %60 = OpMatrixTimesVector %6 %49 %38
1281 
1282 ; Multiplying 4x3 matrix by 3-dimensional vector
1283          %61 = OpMatrixTimesVector %7 %52 %39
1284 
1285 ; Multiplying 2x4 matrix by 4-dimensional vector
1286          %62 = OpMatrixTimesVector %5 %47 %41
1287 
1288 ; Multiplying 3x4 matrix by 4-dimensional vector
1289          %63 = OpMatrixTimesVector %6 %50 %42
1290 
1291 ; Multiplying 4x4 matrix by 4-dimensional vector
1292          %64 = OpMatrixTimesVector %7 %53 %43
1293                OpReturn
1294                OpFunctionEnd
1295   )";
1296 
1297   const auto env = SPV_ENV_UNIVERSAL_1_5;
1298   const auto consumer = nullptr;
1299   const auto context =
1300       BuildModule(env, consumer, reference_shader, kFuzzAssembleOption);
1301   spvtools::ValidatorOptions validator_options;
1302   ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
1303                                                kConsoleMessageConsumer));
1304   TransformationContext transformation_context(
1305       MakeUnique<FactManager>(context.get()), validator_options);
1306   auto instruction_descriptor =
1307       MakeInstructionDescriptor(56, spv::Op::OpMatrixTimesVector, 0);
1308   auto transformation = TransformationReplaceLinearAlgebraInstruction(
1309       {65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78},
1310       instruction_descriptor);
1311   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
1312 
1313   instruction_descriptor =
1314       MakeInstructionDescriptor(57, spv::Op::OpMatrixTimesVector, 0);
1315   transformation = TransformationReplaceLinearAlgebraInstruction(
1316       {79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96,
1317        97},
1318       instruction_descriptor);
1319   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
1320 
1321   instruction_descriptor =
1322       MakeInstructionDescriptor(58, spv::Op::OpMatrixTimesVector, 0);
1323   transformation = TransformationReplaceLinearAlgebraInstruction(
1324       {98,  99,  100, 101, 102, 103, 104, 105, 106, 107, 108, 109,
1325        110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121},
1326       instruction_descriptor);
1327   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
1328 
1329   instruction_descriptor =
1330       MakeInstructionDescriptor(59, spv::Op::OpMatrixTimesVector, 0);
1331   transformation = TransformationReplaceLinearAlgebraInstruction(
1332       {122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132,
1333        133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143},
1334       instruction_descriptor);
1335   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
1336 
1337   std::string variant_shader = R"(
1338                OpCapability Shader
1339           %1 = OpExtInstImport "GLSL.std.450"
1340                OpMemoryModel Logical GLSL450
1341                OpEntryPoint Fragment %54 "main"
1342                OpExecutionMode %54 OriginUpperLeft
1343                OpSource ESSL 310
1344                OpName %54 "main"
1345 
1346 ; Types
1347           %2 = OpTypeVoid
1348           %3 = OpTypeFunction %2
1349           %4 = OpTypeFloat 32
1350           %5 = OpTypeVector %4 2
1351           %6 = OpTypeVector %4 3
1352           %7 = OpTypeVector %4 4
1353           %8 = OpTypeMatrix %5 2
1354           %9 = OpTypeMatrix %5 3
1355          %10 = OpTypeMatrix %5 4
1356          %11 = OpTypeMatrix %6 2
1357          %12 = OpTypeMatrix %6 3
1358          %13 = OpTypeMatrix %6 4
1359          %14 = OpTypeMatrix %7 2
1360          %15 = OpTypeMatrix %7 3
1361          %16 = OpTypeMatrix %7 4
1362 
1363 ; Constant scalars
1364          %17 = OpConstant %4 1
1365          %18 = OpConstant %4 2
1366          %19 = OpConstant %4 3
1367          %20 = OpConstant %4 4
1368          %21 = OpConstant %4 5
1369          %22 = OpConstant %4 6
1370          %23 = OpConstant %4 7
1371          %24 = OpConstant %4 8
1372          %25 = OpConstant %4 9
1373          %26 = OpConstant %4 10
1374          %27 = OpConstant %4 11
1375          %28 = OpConstant %4 12
1376          %29 = OpConstant %4 13
1377          %30 = OpConstant %4 14
1378          %31 = OpConstant %4 15
1379          %32 = OpConstant %4 16
1380 
1381 ; Constant vectors
1382          %33 = OpConstantComposite %5 %17 %18
1383          %34 = OpConstantComposite %5 %19 %20
1384          %35 = OpConstantComposite %5 %21 %22
1385          %36 = OpConstantComposite %5 %23 %24
1386          %37 = OpConstantComposite %6 %17 %18 %19
1387          %38 = OpConstantComposite %6 %20 %21 %22
1388          %39 = OpConstantComposite %6 %23 %24 %25
1389          %40 = OpConstantComposite %6 %26 %27 %28
1390          %41 = OpConstantComposite %7 %17 %18 %19 %20
1391          %42 = OpConstantComposite %7 %21 %22 %23 %24
1392          %43 = OpConstantComposite %7 %25 %26 %27 %28
1393          %44 = OpConstantComposite %7 %29 %30 %31 %32
1394 
1395 ; Constant matrices
1396          %45 = OpConstantComposite %8 %33 %34
1397          %46 = OpConstantComposite %9 %33 %34 %35
1398          %47 = OpConstantComposite %10 %33 %34 %35 %36
1399          %48 = OpConstantComposite %11 %37 %38
1400          %49 = OpConstantComposite %12 %37 %38 %39
1401          %50 = OpConstantComposite %13 %37 %38 %39 %40
1402          %51 = OpConstantComposite %14 %41 %42
1403          %52 = OpConstantComposite %15 %41 %42 %43
1404          %53 = OpConstantComposite %16 %41 %42 %43 %44
1405 
1406 ; main function
1407          %54 = OpFunction %2 None %3
1408          %55 = OpLabel
1409 
1410 ; Multiplying 2x2 matrix by 2-dimensional vector
1411          %65 = OpCompositeExtract %5 %45 0
1412          %66 = OpCompositeExtract %5 %45 1
1413          %67 = OpCompositeExtract %4 %33 0
1414          %68 = OpCompositeExtract %4 %33 1
1415          %69 = OpCompositeExtract %4 %65 0
1416          %70 = OpFMul %4 %69 %67
1417          %71 = OpCompositeExtract %4 %66 0
1418          %72 = OpFMul %4 %71 %68
1419          %73 = OpFAdd %4 %70 %72
1420          %74 = OpCompositeExtract %4 %65 1
1421          %75 = OpFMul %4 %74 %67
1422          %76 = OpCompositeExtract %4 %66 1
1423          %77 = OpFMul %4 %76 %68
1424          %78 = OpFAdd %4 %75 %77
1425          %56 = OpCompositeConstruct %5 %73 %78
1426 
1427 ; Multiplying 3x2 matrix by 2-dimensional vector
1428          %79 = OpCompositeExtract %6 %48 0
1429          %80 = OpCompositeExtract %6 %48 1
1430          %81 = OpCompositeExtract %4 %34 0
1431          %82 = OpCompositeExtract %4 %34 1
1432          %83 = OpCompositeExtract %4 %79 0
1433          %84 = OpFMul %4 %83 %81
1434          %85 = OpCompositeExtract %4 %80 0
1435          %86 = OpFMul %4 %85 %82
1436          %87 = OpFAdd %4 %84 %86
1437          %88 = OpCompositeExtract %4 %79 1
1438          %89 = OpFMul %4 %88 %81
1439          %90 = OpCompositeExtract %4 %80 1
1440          %91 = OpFMul %4 %90 %82
1441          %92 = OpFAdd %4 %89 %91
1442          %93 = OpCompositeExtract %4 %79 2
1443          %94 = OpFMul %4 %93 %81
1444          %95 = OpCompositeExtract %4 %80 2
1445          %96 = OpFMul %4 %95 %82
1446          %97 = OpFAdd %4 %94 %96
1447          %57 = OpCompositeConstruct %6 %87 %92 %97
1448 
1449 ; Multiplying 4x2 matrix by 2-dimensional vector
1450          %98 = OpCompositeExtract %7 %51 0
1451          %99 = OpCompositeExtract %7 %51 1
1452         %100 = OpCompositeExtract %4 %35 0
1453         %101 = OpCompositeExtract %4 %35 1
1454         %102 = OpCompositeExtract %4 %98 0
1455         %103 = OpFMul %4 %102 %100
1456         %104 = OpCompositeExtract %4 %99 0
1457         %105 = OpFMul %4 %104 %101
1458         %106 = OpFAdd %4 %103 %105
1459         %107 = OpCompositeExtract %4 %98 1
1460         %108 = OpFMul %4 %107 %100
1461         %109 = OpCompositeExtract %4 %99 1
1462         %110 = OpFMul %4 %109 %101
1463         %111 = OpFAdd %4 %108 %110
1464         %112 = OpCompositeExtract %4 %98 2
1465         %113 = OpFMul %4 %112 %100
1466         %114 = OpCompositeExtract %4 %99 2
1467         %115 = OpFMul %4 %114 %101
1468         %116 = OpFAdd %4 %113 %115
1469         %117 = OpCompositeExtract %4 %98 3
1470         %118 = OpFMul %4 %117 %100
1471         %119 = OpCompositeExtract %4 %99 3
1472         %120 = OpFMul %4 %119 %101
1473         %121 = OpFAdd %4 %118 %120
1474          %58 = OpCompositeConstruct %7 %106 %111 %116 %121
1475 
1476 ; Multiplying 2x3 matrix by 3-dimensional vector
1477         %122 = OpCompositeExtract %5 %46 0
1478         %123 = OpCompositeExtract %5 %46 1
1479         %124 = OpCompositeExtract %5 %46 2
1480         %125 = OpCompositeExtract %4 %37 0
1481         %126 = OpCompositeExtract %4 %37 1
1482         %127 = OpCompositeExtract %4 %37 2
1483         %128 = OpCompositeExtract %4 %122 0
1484         %129 = OpFMul %4 %128 %125
1485         %130 = OpCompositeExtract %4 %123 0
1486         %131 = OpFMul %4 %130 %126
1487         %132 = OpCompositeExtract %4 %124 0
1488         %133 = OpFMul %4 %132 %127
1489         %134 = OpFAdd %4 %129 %131
1490         %135 = OpFAdd %4 %133 %134
1491         %136 = OpCompositeExtract %4 %122 1
1492         %137 = OpFMul %4 %136 %125
1493         %138 = OpCompositeExtract %4 %123 1
1494         %139 = OpFMul %4 %138 %126
1495         %140 = OpCompositeExtract %4 %124 1
1496         %141 = OpFMul %4 %140 %127
1497         %142 = OpFAdd %4 %137 %139
1498         %143 = OpFAdd %4 %141 %142
1499          %59 = OpCompositeConstruct %5 %135 %143
1500 
1501 ; Multiplying 3x3 matrix by 3-dimensional vector
1502          %60 = OpMatrixTimesVector %6 %49 %38
1503 
1504 ; Multiplying 4x3 matrix by 3-dimensional vector
1505          %61 = OpMatrixTimesVector %7 %52 %39
1506 
1507 ; Multiplying 2x4 matrix by 4-dimensional vector
1508          %62 = OpMatrixTimesVector %5 %47 %41
1509 
1510 ; Multiplying 3x4 matrix by 4-dimensional vector
1511          %63 = OpMatrixTimesVector %6 %50 %42
1512 
1513 ; Multiplying 4x4 matrix by 4-dimensional vector
1514          %64 = OpMatrixTimesVector %7 %53 %43
1515                OpReturn
1516                OpFunctionEnd
1517   )";
1518 
1519   ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
1520                                                kConsoleMessageConsumer));
1521   ASSERT_TRUE(IsEqual(env, variant_shader, context.get()));
1522 }
1523 
TEST(TransformationReplaceLinearAlgebraInstructionTest, ReplaceOpMatrixTimesMatrix)1524 TEST(TransformationReplaceLinearAlgebraInstructionTest,
1525      ReplaceOpMatrixTimesMatrix) {
1526   std::string reference_shader = R"(
1527                OpCapability Shader
1528           %1 = OpExtInstImport "GLSL.std.450"
1529                OpMemoryModel Logical GLSL450
1530                OpEntryPoint Fragment %54 "main"
1531                OpExecutionMode %54 OriginUpperLeft
1532                OpSource ESSL 310
1533                OpName %54 "main"
1534 
1535 ; Types
1536           %2 = OpTypeVoid
1537           %3 = OpTypeFunction %2
1538           %4 = OpTypeFloat 32
1539           %5 = OpTypeVector %4 2
1540           %6 = OpTypeVector %4 3
1541           %7 = OpTypeVector %4 4
1542           %8 = OpTypeMatrix %5 2
1543           %9 = OpTypeMatrix %5 3
1544          %10 = OpTypeMatrix %5 4
1545          %11 = OpTypeMatrix %6 2
1546          %12 = OpTypeMatrix %6 3
1547          %13 = OpTypeMatrix %6 4
1548          %14 = OpTypeMatrix %7 2
1549          %15 = OpTypeMatrix %7 3
1550          %16 = OpTypeMatrix %7 4
1551 
1552 ; Constant scalars
1553          %17 = OpConstant %4 1
1554          %18 = OpConstant %4 2
1555          %19 = OpConstant %4 3
1556          %20 = OpConstant %4 4
1557          %21 = OpConstant %4 5
1558          %22 = OpConstant %4 6
1559          %23 = OpConstant %4 7
1560          %24 = OpConstant %4 8
1561          %25 = OpConstant %4 9
1562          %26 = OpConstant %4 10
1563          %27 = OpConstant %4 11
1564          %28 = OpConstant %4 12
1565          %29 = OpConstant %4 13
1566          %30 = OpConstant %4 14
1567          %31 = OpConstant %4 15
1568          %32 = OpConstant %4 16
1569 
1570 ; Constant vectors
1571          %33 = OpConstantComposite %5 %17 %18
1572          %34 = OpConstantComposite %5 %19 %20
1573          %35 = OpConstantComposite %5 %21 %22
1574          %36 = OpConstantComposite %5 %23 %24
1575          %37 = OpConstantComposite %6 %17 %18 %19
1576          %38 = OpConstantComposite %6 %20 %21 %22
1577          %39 = OpConstantComposite %6 %23 %24 %25
1578          %40 = OpConstantComposite %6 %26 %27 %28
1579          %41 = OpConstantComposite %7 %17 %18 %19 %20
1580          %42 = OpConstantComposite %7 %21 %22 %23 %24
1581          %43 = OpConstantComposite %7 %25 %26 %27 %28
1582          %44 = OpConstantComposite %7 %29 %30 %31 %32
1583 
1584 ; Constant matrices
1585          %45 = OpConstantComposite %8 %33 %34
1586          %46 = OpConstantComposite %9 %33 %34 %35
1587          %47 = OpConstantComposite %10 %33 %34 %35 %36
1588          %48 = OpConstantComposite %11 %37 %38
1589          %49 = OpConstantComposite %12 %37 %38 %39
1590          %50 = OpConstantComposite %13 %37 %38 %39 %40
1591          %51 = OpConstantComposite %14 %41 %42
1592          %52 = OpConstantComposite %15 %41 %42 %43
1593          %53 = OpConstantComposite %16 %41 %42 %43 %44
1594 
1595 ; main function
1596          %54 = OpFunction %2 None %3
1597          %55 = OpLabel
1598 
1599 ; Multiplying 2x2 matrix by 2x2 matrix
1600          %56 = OpMatrixTimesMatrix %8 %45 %45
1601 
1602 ; Multiplying 2x2 matrix by 2x3 matrix
1603          %57 = OpMatrixTimesMatrix %9 %45 %46
1604 
1605 ; Multiplying 2x2 matrix by 2x4 matrix
1606          %58 = OpMatrixTimesMatrix %10 %45 %47
1607 
1608 ; Multiplying 2x3 matrix by 3x2 matrix
1609          %59 = OpMatrixTimesMatrix %8 %46 %48
1610 
1611 ; Multiplying 2x3 matrix by 3x3 matrix
1612          %60 = OpMatrixTimesMatrix %9 %46 %49
1613 
1614 ; Multiplying 2x3 matrix by 3x4 matrix
1615          %61 = OpMatrixTimesMatrix %10 %46 %50
1616 
1617 ; Multiplying 2x4 matrix by 4x2 matrix
1618          %62 = OpMatrixTimesMatrix %8 %47 %51
1619 
1620 ; Multiplying 2x4 matrix by 4x3 matrix
1621          %63 = OpMatrixTimesMatrix %9 %47 %52
1622 
1623 ; Multiplying 2x4 matrix by 4x4 matrix
1624          %64 = OpMatrixTimesMatrix %10 %47 %53
1625 
1626 ; Multiplying 3x2 matrix by 2x2 matrix
1627          %65 = OpMatrixTimesMatrix %11 %48 %45
1628 
1629 ; Multiplying 3x2 matrix by 2x3 matrix
1630          %66 = OpMatrixTimesMatrix %12 %48 %46
1631 
1632 ; Multiplying 3x2 matrix by 2x4 matrix
1633          %67 = OpMatrixTimesMatrix %13 %48 %47
1634 
1635 ; Multiplying 3x3 matrix by 3x2 matrix
1636          %68 = OpMatrixTimesMatrix %11 %49 %48
1637 
1638 ; Multiplying 3x3 matrix by 3x3 matrix
1639          %69 = OpMatrixTimesMatrix %12 %49 %49
1640 
1641 ; Multiplying 3x3 matrix by 3x4 matrix
1642          %70 = OpMatrixTimesMatrix %13 %49 %50
1643 
1644 ; Multiplying 3x4 matrix by 4x2 matrix
1645          %71 = OpMatrixTimesMatrix %11 %50 %51
1646 
1647 ; Multiplying 3x4 matrix by 4x3 matrix
1648          %72 = OpMatrixTimesMatrix %12 %50 %52
1649 
1650 ; Multiplying 3x4 matrix by 4x4 matrix
1651          %73 = OpMatrixTimesMatrix %13 %50 %53
1652 
1653 ; Multiplying 4x2 matrix by 2x2 matrix
1654          %74 = OpMatrixTimesMatrix %14 %51 %45
1655 
1656 ; Multiplying 4x2 matrix by 2x3 matrix
1657          %75 = OpMatrixTimesMatrix %15 %51 %46
1658 
1659 ; Multiplying 4x2 matrix by 2x4 matrix
1660          %76 = OpMatrixTimesMatrix %16 %51 %47
1661 
1662 ; Multiplying 4x3 matrix by 3x2 matrix
1663          %77 = OpMatrixTimesMatrix %14 %52 %48
1664 
1665 ; Multiplying 4x3 matrix by 3x3 matrix
1666          %78 = OpMatrixTimesMatrix %15 %52 %49
1667 
1668 ; Multiplying 4x3 matrix by 3x4 matrix
1669          %79 = OpMatrixTimesMatrix %16 %52 %50
1670 
1671 ; Multiplying 4x4 matrix by 4x2 matrix
1672          %80 = OpMatrixTimesMatrix %14 %53 %51
1673 
1674 ; Multiplying 4x4 matrix by 4x3 matrix
1675          %81 = OpMatrixTimesMatrix %15 %53 %52
1676 
1677 ; Multiplying 4x4 matrix by 4x4 matrix
1678          %82 = OpMatrixTimesMatrix %16 %53 %53
1679                OpReturn
1680                OpFunctionEnd
1681   )";
1682 
1683   const auto env = SPV_ENV_UNIVERSAL_1_5;
1684   const auto consumer = nullptr;
1685   const auto context =
1686       BuildModule(env, consumer, reference_shader, kFuzzAssembleOption);
1687   spvtools::ValidatorOptions validator_options;
1688   ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
1689                                                kConsoleMessageConsumer));
1690   TransformationContext transformation_context(
1691       MakeUnique<FactManager>(context.get()), validator_options);
1692   auto instruction_descriptor =
1693       MakeInstructionDescriptor(56, spv::Op::OpMatrixTimesMatrix, 0);
1694   auto transformation = TransformationReplaceLinearAlgebraInstruction(
1695       {83,  84,  85,  86,  87,  88,  89,  90,  91,  92,  93,  94,  95,  96,
1696        97,  98,  99,  100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110,
1697        111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122},
1698       instruction_descriptor);
1699   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
1700 
1701   instruction_descriptor =
1702       MakeInstructionDescriptor(57, spv::Op::OpMatrixTimesMatrix, 0);
1703   transformation = TransformationReplaceLinearAlgebraInstruction(
1704       {123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134,
1705        135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146,
1706        147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158,
1707        159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170,
1708        171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182},
1709       instruction_descriptor);
1710   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
1711 
1712   instruction_descriptor =
1713       MakeInstructionDescriptor(58, spv::Op::OpMatrixTimesMatrix, 0);
1714   transformation = TransformationReplaceLinearAlgebraInstruction(
1715       {183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196,
1716        197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210,
1717        211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224,
1718        225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238,
1719        239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252,
1720        253, 254, 255, 256, 257, 258, 259, 260, 261, 262},
1721       instruction_descriptor);
1722   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
1723 
1724   std::string variant_shader = R"(
1725                OpCapability Shader
1726           %1 = OpExtInstImport "GLSL.std.450"
1727                OpMemoryModel Logical GLSL450
1728                OpEntryPoint Fragment %54 "main"
1729                OpExecutionMode %54 OriginUpperLeft
1730                OpSource ESSL 310
1731                OpName %54 "main"
1732 
1733 ; Types
1734           %2 = OpTypeVoid
1735           %3 = OpTypeFunction %2
1736           %4 = OpTypeFloat 32
1737           %5 = OpTypeVector %4 2
1738           %6 = OpTypeVector %4 3
1739           %7 = OpTypeVector %4 4
1740           %8 = OpTypeMatrix %5 2
1741           %9 = OpTypeMatrix %5 3
1742          %10 = OpTypeMatrix %5 4
1743          %11 = OpTypeMatrix %6 2
1744          %12 = OpTypeMatrix %6 3
1745          %13 = OpTypeMatrix %6 4
1746          %14 = OpTypeMatrix %7 2
1747          %15 = OpTypeMatrix %7 3
1748          %16 = OpTypeMatrix %7 4
1749 
1750 ; Constant scalars
1751          %17 = OpConstant %4 1
1752          %18 = OpConstant %4 2
1753          %19 = OpConstant %4 3
1754          %20 = OpConstant %4 4
1755          %21 = OpConstant %4 5
1756          %22 = OpConstant %4 6
1757          %23 = OpConstant %4 7
1758          %24 = OpConstant %4 8
1759          %25 = OpConstant %4 9
1760          %26 = OpConstant %4 10
1761          %27 = OpConstant %4 11
1762          %28 = OpConstant %4 12
1763          %29 = OpConstant %4 13
1764          %30 = OpConstant %4 14
1765          %31 = OpConstant %4 15
1766          %32 = OpConstant %4 16
1767 
1768 ; Constant vectors
1769          %33 = OpConstantComposite %5 %17 %18
1770          %34 = OpConstantComposite %5 %19 %20
1771          %35 = OpConstantComposite %5 %21 %22
1772          %36 = OpConstantComposite %5 %23 %24
1773          %37 = OpConstantComposite %6 %17 %18 %19
1774          %38 = OpConstantComposite %6 %20 %21 %22
1775          %39 = OpConstantComposite %6 %23 %24 %25
1776          %40 = OpConstantComposite %6 %26 %27 %28
1777          %41 = OpConstantComposite %7 %17 %18 %19 %20
1778          %42 = OpConstantComposite %7 %21 %22 %23 %24
1779          %43 = OpConstantComposite %7 %25 %26 %27 %28
1780          %44 = OpConstantComposite %7 %29 %30 %31 %32
1781 
1782 ; Constant matrices
1783          %45 = OpConstantComposite %8 %33 %34
1784          %46 = OpConstantComposite %9 %33 %34 %35
1785          %47 = OpConstantComposite %10 %33 %34 %35 %36
1786          %48 = OpConstantComposite %11 %37 %38
1787          %49 = OpConstantComposite %12 %37 %38 %39
1788          %50 = OpConstantComposite %13 %37 %38 %39 %40
1789          %51 = OpConstantComposite %14 %41 %42
1790          %52 = OpConstantComposite %15 %41 %42 %43
1791          %53 = OpConstantComposite %16 %41 %42 %43 %44
1792 
1793 ; main function
1794          %54 = OpFunction %2 None %3
1795          %55 = OpLabel
1796 
1797 ; Multiplying 2x2 matrix by 2x2 matrix
1798          %83 = OpCompositeExtract %5 %45 0 ; matrix 2 column 0
1799          %84 = OpCompositeExtract %5 %45 0 ; matrix 1 column 0
1800          %85 = OpCompositeExtract %4 %84 0 ; matrix 1 row 0 column 0
1801          %86 = OpCompositeExtract %4 %83 0 ; matrix 2 row 0 column 0
1802          %87 = OpFMul %4 %85 %86
1803          %88 = OpCompositeExtract %5 %45 1 ; matrix 1 column 1
1804          %89 = OpCompositeExtract %4 %88 0 ; matrix 1 row 0 column 1
1805          %90 = OpCompositeExtract %4 %83 1 ; matrix 2 row 1 column 0
1806          %91 = OpFMul %4 %89 %90
1807          %92 = OpFAdd %4 %87 %91
1808          %93 = OpCompositeExtract %5 %45 0 ; matrix 1 column 0
1809          %94 = OpCompositeExtract %4 %93 1 ; matrix 1 row 1 column 0
1810          %95 = OpCompositeExtract %4 %83 0 ; matrix 2 row 0 column 0
1811          %96 = OpFMul %4 %94 %95
1812          %97 = OpCompositeExtract %5 %45 1 ; matrix 1 column 1
1813          %98 = OpCompositeExtract %4 %97 1 ; matrix 1 row 1 column 1
1814          %99 = OpCompositeExtract %4 %83 1 ; matrix 2 row 1 column 0
1815         %100 = OpFMul %4 %98 %99
1816         %101 = OpFAdd %4 %96 %100
1817         %102 = OpCompositeConstruct %5 %92 %101 ; resulting matrix column 0
1818         %103 = OpCompositeExtract %5 %45 1 ; matrix 2 column 1
1819         %104 = OpCompositeExtract %5 %45 0 ; matrix 1 column 0
1820         %105 = OpCompositeExtract %4 %104 0 ; matrix 1 row 0 column 0
1821         %106 = OpCompositeExtract %4 %103 0 ; matrix 2 row 0 column 1
1822         %107 = OpFMul %4 %105 %106
1823         %108 = OpCompositeExtract %5 %45 1 ; matrix 1 column 1
1824         %109 = OpCompositeExtract %4 %108 0 ; matrix 1 row 0 column 1
1825         %110 = OpCompositeExtract %4 %103 1 ; matrix 2 row 1 column 1
1826         %111 = OpFMul %4 %109 %110
1827         %112 = OpFAdd %4 %107 %111
1828         %113 = OpCompositeExtract %5 %45 0 ; matrix 1 column 0
1829         %114 = OpCompositeExtract %4 %113 1 ; matrix 1 row 1 column 0
1830         %115 = OpCompositeExtract %4 %103 0 ; matrix 2 row 0 column 1
1831         %116 = OpFMul %4 %114 %115
1832         %117 = OpCompositeExtract %5 %45 1 ; matrix 1 column 1
1833         %118 = OpCompositeExtract %4 %117 1 ; matrix 1 row 1 column 1
1834         %119 = OpCompositeExtract %4 %103 1 ; matrix 2 row 1 column 1
1835         %120 = OpFMul %4 %118 %119
1836         %121 = OpFAdd %4 %116 %120
1837         %122 = OpCompositeConstruct %5 %112 %121 ; resulting matrix column 1
1838          %56 = OpCompositeConstruct %8 %102 %122 ; resulting matrix
1839 
1840 ; Multiplying 2x2 matrix by 2x3 matrix
1841         %123 = OpCompositeExtract %5 %46 0 ; matrix 2 column 0
1842         %124 = OpCompositeExtract %5 %45 0 ; matrix 1 column 0
1843         %125 = OpCompositeExtract %4 %124 0 ; matrix 1 row 0 column 0
1844         %126 = OpCompositeExtract %4 %123 0 ; matrix 2 row 0 column 0
1845         %127 = OpFMul %4 %125 %126
1846         %128 = OpCompositeExtract %5 %45 1 ; matrix 1 column 1
1847         %129 = OpCompositeExtract %4 %128 0 ; matrix 1 row 0 column 1
1848         %130 = OpCompositeExtract %4 %123 1 ; matrix 2 row 1 column 0
1849         %131 = OpFMul %4 %129 %130
1850         %132 = OpFAdd %4 %127 %131
1851         %133 = OpCompositeExtract %5 %45 0 ; matrix 1 column 0
1852         %134 = OpCompositeExtract %4 %133 1 ; matrix 1 row 1 column 0
1853         %135 = OpCompositeExtract %4 %123 0 ; matrix 2 row 0 column 0
1854         %136 = OpFMul %4 %134 %135
1855         %137 = OpCompositeExtract %5 %45 1 ; matrix 1 column 1
1856         %138 = OpCompositeExtract %4 %137 1 ; matrix 1 row 1 column 1
1857         %139 = OpCompositeExtract %4 %123 1 ; matrix 2 row 1 column 0
1858         %140 = OpFMul %4 %138 %139
1859         %141 = OpFAdd %4 %136 %140
1860         %142 = OpCompositeConstruct %5 %132 %141 ; resulting matrix column 0
1861         %143 = OpCompositeExtract %5 %46 1 ; matrix 2 column 1
1862         %144 = OpCompositeExtract %5 %45 0 ; matrix 1 column 0
1863         %145 = OpCompositeExtract %4 %144 0 ; matrix 1 row 0 column 0
1864         %146 = OpCompositeExtract %4 %143 0 ; matrix 2 row 0 column 1
1865         %147 = OpFMul %4 %145 %146
1866         %148 = OpCompositeExtract %5 %45 1 ; matrix 1 column 1
1867         %149 = OpCompositeExtract %4 %148 0 ; matrix 1 row 0 column 1
1868         %150 = OpCompositeExtract %4 %143 1 ; matrix 2 row 1 column 1
1869         %151 = OpFMul %4 %149 %150
1870         %152 = OpFAdd %4 %147 %151
1871         %153 = OpCompositeExtract %5 %45 0 ; matrix 1 column 0
1872         %154 = OpCompositeExtract %4 %153 1 ; matrix 1 row 1 column 0
1873         %155 = OpCompositeExtract %4 %143 0 ; matrix 2 row 0 column 1
1874         %156 = OpFMul %4 %154 %155
1875         %157 = OpCompositeExtract %5 %45 1 ; matrix 1 column 1
1876         %158 = OpCompositeExtract %4 %157 1 ; matrix 1 row 1 column 1
1877         %159 = OpCompositeExtract %4 %143 1 ; matrix 2 row 1 column 1
1878         %160 = OpFMul %4 %158 %159
1879         %161 = OpFAdd %4 %156 %160
1880         %162 = OpCompositeConstruct %5 %152 %161 ; resulting matrix column 1
1881         %163 = OpCompositeExtract %5 %46 2 ; matrix 2 column 2
1882         %164 = OpCompositeExtract %5 %45 0 ; matrix 1 column 0
1883         %165 = OpCompositeExtract %4 %164 0 ; matrix 1 row 0 column 0
1884         %166 = OpCompositeExtract %4 %163 0 ; matrix 2 row 0 column 2
1885         %167 = OpFMul %4 %165 %166
1886         %168 = OpCompositeExtract %5 %45 1 ; matrix 1 column 1
1887         %169 = OpCompositeExtract %4 %168 0 ; matrix 1 row 0 column 1
1888         %170 = OpCompositeExtract %4 %163 1 ; matrix 2 row 1 column 2
1889         %171 = OpFMul %4 %169 %170
1890         %172 = OpFAdd %4 %167 %171
1891         %173 = OpCompositeExtract %5 %45 0 ; matrix 1 column 0
1892         %174 = OpCompositeExtract %4 %173 1 ; matrix 1 row 1 column 0
1893         %175 = OpCompositeExtract %4 %163 0 ; matrix 2 row 0 column 2
1894         %176 = OpFMul %4 %174 %175
1895         %177 = OpCompositeExtract %5 %45 1 ; matrix 1 column 1
1896         %178 = OpCompositeExtract %4 %177 1 ; matrix 1 row 1 column 1
1897         %179 = OpCompositeExtract %4 %163 1 ; matrix 2 row 1 column 2
1898         %180 = OpFMul %4 %178 %179
1899         %181 = OpFAdd %4 %176 %180
1900         %182 = OpCompositeConstruct %5 %172 %181 ; resulting matrix column 2
1901          %57 = OpCompositeConstruct %9 %142 %162 %182
1902 
1903 ; Multiplying 2x2 matrix by 2x4 matrix
1904         %183 = OpCompositeExtract %5 %47 0 ; matrix 2 column 0
1905         %184 = OpCompositeExtract %5 %45 0 ; matrix 1 column 0
1906         %185 = OpCompositeExtract %4 %184 0 ; matrix 1 row 0 column 0
1907         %186 = OpCompositeExtract %4 %183 0 ; matrix 2 row 0 column 0
1908         %187 = OpFMul %4 %185 %186
1909         %188 = OpCompositeExtract %5 %45 1 ; matrix 1 column 1
1910         %189 = OpCompositeExtract %4 %188 0 ; matrix 1 row 0 column 1
1911         %190 = OpCompositeExtract %4 %183 1 ; matrix 2 row 1 column 0
1912         %191 = OpFMul %4 %189 %190
1913         %192 = OpFAdd %4 %187 %191
1914         %193 = OpCompositeExtract %5 %45 0 ; matrix 1 column 0
1915         %194 = OpCompositeExtract %4 %193 1 ; matrix 1 row 1 column 0
1916         %195 = OpCompositeExtract %4 %183 0 ; matrix 2 row 0 column 0
1917         %196 = OpFMul %4 %194 %195
1918         %197 = OpCompositeExtract %5 %45 1 ; matrix 1 column 1
1919         %198 = OpCompositeExtract %4 %197 1 ; matrix 1 row 1 column 1
1920         %199 = OpCompositeExtract %4 %183 1 ; matrix 2 row 1 column 0
1921         %200 = OpFMul %4 %198 %199
1922         %201 = OpFAdd %4 %196 %200
1923         %202 = OpCompositeConstruct %5 %192 %201 ; resulting matrix column 0
1924         %203 = OpCompositeExtract %5 %47 1 ; matrix 2 column 1
1925         %204 = OpCompositeExtract %5 %45 0 ; matrix 1 column 0
1926         %205 = OpCompositeExtract %4 %204 0 ; matrix 1 row 0 column 0
1927         %206 = OpCompositeExtract %4 %203 0 ; matrix 2 row 0 column 1
1928         %207 = OpFMul %4 %205 %206
1929         %208 = OpCompositeExtract %5 %45 1 ; matrix 1 column 1
1930         %209 = OpCompositeExtract %4 %208 0 ; matrix 1 row 0 column 1
1931         %210 = OpCompositeExtract %4 %203 1 ; matrix 2 row 1 column 1
1932         %211 = OpFMul %4 %209 %210
1933         %212 = OpFAdd %4 %207 %211
1934         %213 = OpCompositeExtract %5 %45 0 ; matrix 1 column 0
1935         %214 = OpCompositeExtract %4 %213 1 ; matrix 1 row 1 column 0
1936         %215 = OpCompositeExtract %4 %203 0 ; matrix 2 row 0 column 1
1937         %216 = OpFMul %4 %214 %215
1938         %217 = OpCompositeExtract %5 %45 1 ; matrix 1 column 1
1939         %218 = OpCompositeExtract %4 %217 1 ; matrix 1 row 1 column 1
1940         %219 = OpCompositeExtract %4 %203 1 ; matrix 2 row 1 column 1
1941         %220 = OpFMul %4 %218 %219
1942         %221 = OpFAdd %4 %216 %220
1943         %222 = OpCompositeConstruct %5 %212 %221 ; resulting matrix column 1
1944         %223 = OpCompositeExtract %5 %47 2 ; matrix 2 column 2
1945         %224 = OpCompositeExtract %5 %45 0 ; matrix 1 column 0
1946         %225 = OpCompositeExtract %4 %224 0 ; matrix 1 row 0 column 0
1947         %226 = OpCompositeExtract %4 %223 0 ; matrix 2 row 0 column 2
1948         %227 = OpFMul %4 %225 %226
1949         %228 = OpCompositeExtract %5 %45 1 ; matrix 1 column 1
1950         %229 = OpCompositeExtract %4 %228 0 ; matrix 1 row 0 column 1
1951         %230 = OpCompositeExtract %4 %223 1 ; matrix 2 row 1 column 2
1952         %231 = OpFMul %4 %229 %230
1953         %232 = OpFAdd %4 %227 %231
1954         %233 = OpCompositeExtract %5 %45 0 ; matrix 1 column 0
1955         %234 = OpCompositeExtract %4 %233 1 ; matrix 1 row 1 column 0
1956         %235 = OpCompositeExtract %4 %223 0 ; matrix 2 row 0 column 2
1957         %236 = OpFMul %4 %234 %235
1958         %237 = OpCompositeExtract %5 %45 1 ; matrix 1 column 1
1959         %238 = OpCompositeExtract %4 %237 1 ; matrix 1 row 1 column 1
1960         %239 = OpCompositeExtract %4 %223 1 ; matrix 2 row 1 column 2
1961         %240 = OpFMul %4 %238 %239
1962         %241 = OpFAdd %4 %236 %240
1963         %242 = OpCompositeConstruct %5 %232 %241 ; resulting matrix column 2
1964         %243 = OpCompositeExtract %5 %47 3 ; matrix 2 column 3
1965         %244 = OpCompositeExtract %5 %45 0 ; matrix 1 column 0
1966         %245 = OpCompositeExtract %4 %244 0 ; matrix 1 row 0 column 0
1967         %246 = OpCompositeExtract %4 %243 0 ; matrix 2 row 0 column 3
1968         %247 = OpFMul %4 %245 %246
1969         %248 = OpCompositeExtract %5 %45 1 ; matrix 1 column 1
1970         %249 = OpCompositeExtract %4 %248 0 ; matrix 1 row 0 column 1
1971         %250 = OpCompositeExtract %4 %243 1 ; matrix 2 row 1 column 3
1972         %251 = OpFMul %4 %249 %250
1973         %252 = OpFAdd %4 %247 %251
1974         %253 = OpCompositeExtract %5 %45 0 ; matrix 1 column 0
1975         %254 = OpCompositeExtract %4 %253 1 ; matrix 1 row 1 column 0
1976         %255 = OpCompositeExtract %4 %243 0 ; matrix 2 row 0 column 3
1977         %256 = OpFMul %4 %254 %255
1978         %257 = OpCompositeExtract %5 %45 1 ; matrix 1 column 1
1979         %258 = OpCompositeExtract %4 %257 1 ; matrix 1 row 1 column 1
1980         %259 = OpCompositeExtract %4 %243 1 ; matrix 2 row 1 column 3
1981         %260 = OpFMul %4 %258 %259
1982         %261 = OpFAdd %4 %256 %260
1983         %262 = OpCompositeConstruct %5 %252 %261 ; resulting matrix column 3
1984          %58 = OpCompositeConstruct %10 %202 %222 %242 %262
1985 
1986 ; Multiplying 2x3 matrix by 3x2 matrix
1987          %59 = OpMatrixTimesMatrix %8 %46 %48
1988 
1989 ; Multiplying 2x3 matrix by 3x3 matrix
1990          %60 = OpMatrixTimesMatrix %9 %46 %49
1991 
1992 ; Multiplying 2x3 matrix by 3x4 matrix
1993          %61 = OpMatrixTimesMatrix %10 %46 %50
1994 
1995 ; Multiplying 2x4 matrix by 4x2 matrix
1996          %62 = OpMatrixTimesMatrix %8 %47 %51
1997 
1998 ; Multiplying 2x4 matrix by 4x3 matrix
1999          %63 = OpMatrixTimesMatrix %9 %47 %52
2000 
2001 ; Multiplying 2x4 matrix by 4x4 matrix
2002          %64 = OpMatrixTimesMatrix %10 %47 %53
2003 
2004 ; Multiplying 3x2 matrix by 2x2 matrix
2005          %65 = OpMatrixTimesMatrix %11 %48 %45
2006 
2007 ; Multiplying 3x2 matrix by 2x3 matrix
2008          %66 = OpMatrixTimesMatrix %12 %48 %46
2009 
2010 ; Multiplying 3x2 matrix by 2x4 matrix
2011          %67 = OpMatrixTimesMatrix %13 %48 %47
2012 
2013 ; Multiplying 3x3 matrix by 3x2 matrix
2014          %68 = OpMatrixTimesMatrix %11 %49 %48
2015 
2016 ; Multiplying 3x3 matrix by 3x3 matrix
2017          %69 = OpMatrixTimesMatrix %12 %49 %49
2018 
2019 ; Multiplying 3x3 matrix by 3x4 matrix
2020          %70 = OpMatrixTimesMatrix %13 %49 %50
2021 
2022 ; Multiplying 3x4 matrix by 4x2 matrix
2023          %71 = OpMatrixTimesMatrix %11 %50 %51
2024 
2025 ; Multiplying 3x4 matrix by 4x3 matrix
2026          %72 = OpMatrixTimesMatrix %12 %50 %52
2027 
2028 ; Multiplying 3x4 matrix by 4x4 matrix
2029          %73 = OpMatrixTimesMatrix %13 %50 %53
2030 
2031 ; Multiplying 4x2 matrix by 2x2 matrix
2032          %74 = OpMatrixTimesMatrix %14 %51 %45
2033 
2034 ; Multiplying 4x2 matrix by 2x3 matrix
2035          %75 = OpMatrixTimesMatrix %15 %51 %46
2036 
2037 ; Multiplying 4x2 matrix by 2x4 matrix
2038          %76 = OpMatrixTimesMatrix %16 %51 %47
2039 
2040 ; Multiplying 4x3 matrix by 3x2 matrix
2041          %77 = OpMatrixTimesMatrix %14 %52 %48
2042 
2043 ; Multiplying 4x3 matrix by 3x3 matrix
2044          %78 = OpMatrixTimesMatrix %15 %52 %49
2045 
2046 ; Multiplying 4x3 matrix by 3x4 matrix
2047          %79 = OpMatrixTimesMatrix %16 %52 %50
2048 
2049 ; Multiplying 4x4 matrix by 4x2 matrix
2050          %80 = OpMatrixTimesMatrix %14 %53 %51
2051 
2052 ; Multiplying 4x4 matrix by 4x3 matrix
2053          %81 = OpMatrixTimesMatrix %15 %53 %52
2054 
2055 ; Multiplying 4x4 matrix by 4x4 matrix
2056          %82 = OpMatrixTimesMatrix %16 %53 %53
2057                OpReturn
2058                OpFunctionEnd
2059   )";
2060 
2061   ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
2062                                                kConsoleMessageConsumer));
2063   ASSERT_TRUE(IsEqual(env, variant_shader, context.get()));
2064 }
2065 
TEST(TransformationReplaceLinearAlgebraInstructionTest, ReplaceOpOuterProduct)2066 TEST(TransformationReplaceLinearAlgebraInstructionTest, ReplaceOpOuterProduct) {
2067   std::string reference_shader = R"(
2068                OpCapability Shader
2069           %1 = OpExtInstImport "GLSL.std.450"
2070                OpMemoryModel Logical GLSL450
2071                OpEntryPoint Vertex %45 "main"
2072 
2073 ; Types
2074           %2 = OpTypeVoid
2075           %3 = OpTypeFunction %2
2076           %4 = OpTypeFloat 32
2077           %5 = OpTypeVector %4 2
2078           %6 = OpTypeVector %4 3
2079           %7 = OpTypeVector %4 4
2080           %8 = OpTypeMatrix %5 2
2081           %9 = OpTypeMatrix %5 3
2082          %10 = OpTypeMatrix %5 4
2083          %11 = OpTypeMatrix %6 2
2084          %12 = OpTypeMatrix %6 3
2085          %13 = OpTypeMatrix %6 4
2086          %14 = OpTypeMatrix %7 2
2087          %15 = OpTypeMatrix %7 3
2088          %16 = OpTypeMatrix %7 4
2089 
2090 ; Constant scalars
2091          %17 = OpConstant %4 1
2092          %18 = OpConstant %4 2
2093          %19 = OpConstant %4 3
2094          %20 = OpConstant %4 4
2095          %21 = OpConstant %4 5
2096          %22 = OpConstant %4 6
2097          %23 = OpConstant %4 7
2098          %24 = OpConstant %4 8
2099          %25 = OpConstant %4 9
2100          %26 = OpConstant %4 10
2101          %27 = OpConstant %4 11
2102          %28 = OpConstant %4 12
2103          %29 = OpConstant %4 13
2104          %30 = OpConstant %4 14
2105          %31 = OpConstant %4 15
2106          %32 = OpConstant %4 16
2107 
2108 ; Constant vectors
2109          %33 = OpConstantComposite %5 %17 %18
2110          %34 = OpConstantComposite %5 %19 %20
2111          %35 = OpConstantComposite %5 %21 %22
2112          %36 = OpConstantComposite %5 %23 %24
2113          %37 = OpConstantComposite %6 %17 %18 %19
2114          %38 = OpConstantComposite %6 %20 %21 %22
2115          %39 = OpConstantComposite %6 %23 %24 %25
2116          %40 = OpConstantComposite %6 %26 %27 %28
2117          %41 = OpConstantComposite %7 %17 %18 %19 %20
2118          %42 = OpConstantComposite %7 %21 %22 %23 %24
2119          %43 = OpConstantComposite %7 %25 %26 %27 %28
2120          %44 = OpConstantComposite %7 %29 %30 %31 %32
2121 
2122 ; main function
2123          %45 = OpFunction %2 None %3
2124          %46 = OpLabel
2125 
2126 ; Multiplying 2-dimensional vector by 2-dimensional vector
2127          %47 = OpOuterProduct %8 %33 %34
2128 
2129 ; Multiplying 2-dimensional vector by 3-dimensional vector
2130          %48 = OpOuterProduct %9 %35 %37
2131 
2132 ; Multiplying 2-dimensional vector by 4-dimensional vector
2133          %49 = OpOuterProduct %10 %36 %41
2134 
2135 ; Multiplying 3-dimensional vector by 2-dimensional vector
2136          %50 = OpOuterProduct %11 %37 %33
2137 
2138 ; Multiplying 3-dimensional vector by 3-dimensional vector
2139          %51 = OpOuterProduct %12 %38 %39
2140 
2141 ; Multiplying 3-dimensional vector by 4-dimensional vector
2142          %52 = OpOuterProduct %13 %40 %41
2143 
2144 ; Multiplying 4-dimensional vector by 2-dimensional vector
2145          %53 = OpOuterProduct %14 %41 %33
2146 
2147 ; Multiplying 4-dimensional vector by 3-dimensional vector
2148          %54 = OpOuterProduct %15 %42 %37
2149 
2150 ; Multiplying 4-dimensional vector by 4-dimensional vector
2151          %55 = OpOuterProduct %16 %43 %44
2152                OpReturn
2153                OpFunctionEnd
2154   )";
2155 
2156   const auto env = SPV_ENV_UNIVERSAL_1_5;
2157   const auto consumer = nullptr;
2158   const auto context =
2159       BuildModule(env, consumer, reference_shader, kFuzzAssembleOption);
2160   spvtools::ValidatorOptions validator_options;
2161   ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
2162                                                kConsoleMessageConsumer));
2163   TransformationContext transformation_context(
2164       MakeUnique<FactManager>(context.get()), validator_options);
2165   auto instruction_descriptor =
2166       MakeInstructionDescriptor(47, spv::Op::OpOuterProduct, 0);
2167   auto transformation = TransformationReplaceLinearAlgebraInstruction(
2168       {56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67}, instruction_descriptor);
2169   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
2170 
2171   instruction_descriptor =
2172       MakeInstructionDescriptor(48, spv::Op::OpOuterProduct, 0);
2173   transformation = TransformationReplaceLinearAlgebraInstruction(
2174       {68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85},
2175       instruction_descriptor);
2176   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
2177 
2178   instruction_descriptor =
2179       MakeInstructionDescriptor(49, spv::Op::OpOuterProduct, 0);
2180   transformation = TransformationReplaceLinearAlgebraInstruction(
2181       {86, 87, 88,  89,  90,  91,  92,  93,  94,  95,  96,  97,
2182        98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109},
2183       instruction_descriptor);
2184   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
2185 
2186   instruction_descriptor =
2187       MakeInstructionDescriptor(50, spv::Op::OpOuterProduct, 0);
2188   transformation = TransformationReplaceLinearAlgebraInstruction(
2189       {110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123,
2190        124, 125},
2191       instruction_descriptor);
2192   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
2193 
2194   std::string variant_shader = R"(
2195                OpCapability Shader
2196           %1 = OpExtInstImport "GLSL.std.450"
2197                OpMemoryModel Logical GLSL450
2198                OpEntryPoint Vertex %45 "main"
2199 
2200 ; Types
2201           %2 = OpTypeVoid
2202           %3 = OpTypeFunction %2
2203           %4 = OpTypeFloat 32
2204           %5 = OpTypeVector %4 2
2205           %6 = OpTypeVector %4 3
2206           %7 = OpTypeVector %4 4
2207           %8 = OpTypeMatrix %5 2
2208           %9 = OpTypeMatrix %5 3
2209          %10 = OpTypeMatrix %5 4
2210          %11 = OpTypeMatrix %6 2
2211          %12 = OpTypeMatrix %6 3
2212          %13 = OpTypeMatrix %6 4
2213          %14 = OpTypeMatrix %7 2
2214          %15 = OpTypeMatrix %7 3
2215          %16 = OpTypeMatrix %7 4
2216 
2217 ; Constant scalars
2218          %17 = OpConstant %4 1
2219          %18 = OpConstant %4 2
2220          %19 = OpConstant %4 3
2221          %20 = OpConstant %4 4
2222          %21 = OpConstant %4 5
2223          %22 = OpConstant %4 6
2224          %23 = OpConstant %4 7
2225          %24 = OpConstant %4 8
2226          %25 = OpConstant %4 9
2227          %26 = OpConstant %4 10
2228          %27 = OpConstant %4 11
2229          %28 = OpConstant %4 12
2230          %29 = OpConstant %4 13
2231          %30 = OpConstant %4 14
2232          %31 = OpConstant %4 15
2233          %32 = OpConstant %4 16
2234 
2235 ; Constant vectors
2236          %33 = OpConstantComposite %5 %17 %18
2237          %34 = OpConstantComposite %5 %19 %20
2238          %35 = OpConstantComposite %5 %21 %22
2239          %36 = OpConstantComposite %5 %23 %24
2240          %37 = OpConstantComposite %6 %17 %18 %19
2241          %38 = OpConstantComposite %6 %20 %21 %22
2242          %39 = OpConstantComposite %6 %23 %24 %25
2243          %40 = OpConstantComposite %6 %26 %27 %28
2244          %41 = OpConstantComposite %7 %17 %18 %19 %20
2245          %42 = OpConstantComposite %7 %21 %22 %23 %24
2246          %43 = OpConstantComposite %7 %25 %26 %27 %28
2247          %44 = OpConstantComposite %7 %29 %30 %31 %32
2248 
2249 ; main function
2250          %45 = OpFunction %2 None %3
2251          %46 = OpLabel
2252 
2253 ; Multiplying 2-dimensional vector by 2-dimensional vector
2254          %56 = OpCompositeExtract %4 %34 0
2255          %57 = OpCompositeExtract %4 %33 0
2256          %58 = OpFMul %4 %56 %57
2257          %59 = OpCompositeExtract %4 %33 1
2258          %60 = OpFMul %4 %56 %59
2259          %61 = OpCompositeConstruct %5 %58 %60
2260          %62 = OpCompositeExtract %4 %34 1
2261          %63 = OpCompositeExtract %4 %33 0
2262          %64 = OpFMul %4 %62 %63
2263          %65 = OpCompositeExtract %4 %33 1
2264          %66 = OpFMul %4 %62 %65
2265          %67 = OpCompositeConstruct %5 %64 %66
2266          %47 = OpCompositeConstruct %8 %61 %67
2267 
2268 ; Multiplying 2-dimensional vector by 3-dimensional vector
2269          %68 = OpCompositeExtract %4 %37 0
2270          %69 = OpCompositeExtract %4 %35 0
2271          %70 = OpFMul %4 %68 %69
2272          %71 = OpCompositeExtract %4 %35 1
2273          %72 = OpFMul %4 %68 %71
2274          %73 = OpCompositeConstruct %5 %70 %72
2275          %74 = OpCompositeExtract %4 %37 1
2276          %75 = OpCompositeExtract %4 %35 0
2277          %76 = OpFMul %4 %74 %75
2278          %77 = OpCompositeExtract %4 %35 1
2279          %78 = OpFMul %4 %74 %77
2280          %79 = OpCompositeConstruct %5 %76 %78
2281          %80 = OpCompositeExtract %4 %37 2
2282          %81 = OpCompositeExtract %4 %35 0
2283          %82 = OpFMul %4 %80 %81
2284          %83 = OpCompositeExtract %4 %35 1
2285          %84 = OpFMul %4 %80 %83
2286          %85 = OpCompositeConstruct %5 %82 %84
2287          %48 = OpCompositeConstruct %9 %73 %79 %85
2288 
2289 ; Multiplying 2-dimensional vector by 4-dimensional vector
2290          %86 = OpCompositeExtract %4 %41 0
2291          %87 = OpCompositeExtract %4 %36 0
2292          %88 = OpFMul %4 %86 %87
2293          %89 = OpCompositeExtract %4 %36 1
2294          %90 = OpFMul %4 %86 %89
2295          %91 = OpCompositeConstruct %5 %88 %90
2296          %92 = OpCompositeExtract %4 %41 1
2297          %93 = OpCompositeExtract %4 %36 0
2298          %94 = OpFMul %4 %92 %93
2299          %95 = OpCompositeExtract %4 %36 1
2300          %96 = OpFMul %4 %92 %95
2301          %97 = OpCompositeConstruct %5 %94 %96
2302          %98 = OpCompositeExtract %4 %41 2
2303          %99 = OpCompositeExtract %4 %36 0
2304         %100 = OpFMul %4 %98 %99
2305         %101 = OpCompositeExtract %4 %36 1
2306         %102 = OpFMul %4 %98 %101
2307         %103 = OpCompositeConstruct %5 %100 %102
2308         %104 = OpCompositeExtract %4 %41 3
2309         %105 = OpCompositeExtract %4 %36 0
2310         %106 = OpFMul %4 %104 %105
2311         %107 = OpCompositeExtract %4 %36 1
2312         %108 = OpFMul %4 %104 %107
2313         %109 = OpCompositeConstruct %5 %106 %108
2314          %49 = OpCompositeConstruct %10 %91 %97 %103 %109
2315 
2316 ; Multiplying 3-dimensional vector by 2-dimensional vector
2317         %110 = OpCompositeExtract %4 %33 0
2318         %111 = OpCompositeExtract %4 %37 0
2319         %112 = OpFMul %4 %110 %111
2320         %113 = OpCompositeExtract %4 %37 1
2321         %114 = OpFMul %4 %110 %113
2322         %115 = OpCompositeExtract %4 %37 2
2323         %116 = OpFMul %4 %110 %115
2324         %117 = OpCompositeConstruct %6 %112 %114 %116
2325         %118 = OpCompositeExtract %4 %33 1
2326         %119 = OpCompositeExtract %4 %37 0
2327         %120 = OpFMul %4 %118 %119
2328         %121 = OpCompositeExtract %4 %37 1
2329         %122 = OpFMul %4 %118 %121
2330         %123 = OpCompositeExtract %4 %37 2
2331         %124 = OpFMul %4 %118 %123
2332         %125 = OpCompositeConstruct %6 %120 %122 %124
2333          %50 = OpCompositeConstruct %11 %117 %125
2334 
2335 ; Multiplying 3-dimensional vector by 3-dimensional vector
2336          %51 = OpOuterProduct %12 %38 %39
2337 
2338 ; Multiplying 3-dimensional vector by 4-dimensional vector
2339          %52 = OpOuterProduct %13 %40 %41
2340 
2341 ; Multiplying 4-dimensional vector by 2-dimensional vector
2342          %53 = OpOuterProduct %14 %41 %33
2343 
2344 ; Multiplying 4-dimensional vector by 3-dimensional vector
2345          %54 = OpOuterProduct %15 %42 %37
2346 
2347 ; Multiplying 4-dimensional vector by 4-dimensional vector
2348          %55 = OpOuterProduct %16 %43 %44
2349                OpReturn
2350                OpFunctionEnd
2351   )";
2352 
2353   ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
2354                                                kConsoleMessageConsumer));
2355   ASSERT_TRUE(IsEqual(env, variant_shader, context.get()));
2356 }
2357 
TEST(TransformationReplaceLinearAlgebraInstructionTest, ReplaceOpDot)2358 TEST(TransformationReplaceLinearAlgebraInstructionTest, ReplaceOpDot) {
2359   std::string reference_shader = R"(
2360                OpCapability Shader
2361           %1 = OpExtInstImport "GLSL.std.450"
2362                OpMemoryModel Logical GLSL450
2363                OpEntryPoint Fragment %22 "main"
2364                OpExecutionMode %22 OriginUpperLeft
2365                OpSource ESSL 310
2366                OpName %22 "main"
2367           %2 = OpTypeVoid
2368           %3 = OpTypeFunction %2
2369           %4 = OpTypeFloat 32
2370           %5 = OpTypeVector %4 2
2371           %6 = OpTypeVector %4 3
2372           %7 = OpTypeVector %4 4
2373           %8 = OpConstant %4 1
2374           %9 = OpConstant %4 2
2375          %10 = OpConstant %4 3
2376          %11 = OpConstant %4 4
2377          %12 = OpConstant %4 5
2378          %13 = OpConstant %4 6
2379          %14 = OpConstant %4 7
2380          %15 = OpConstant %4 8
2381          %16 = OpConstantComposite %5 %8 %9
2382          %17 = OpConstantComposite %5 %10 %11
2383          %18 = OpConstantComposite %6 %8 %9 %10
2384          %19 = OpConstantComposite %6 %11 %12 %13
2385          %20 = OpConstantComposite %7 %8 %9 %10 %11
2386          %21 = OpConstantComposite %7 %12 %13 %14 %15
2387          %22 = OpFunction %2 None %3
2388          %23 = OpLabel
2389          %24 = OpDot %4 %16 %17
2390          %25 = OpDot %4 %18 %19
2391          %26 = OpDot %4 %20 %21
2392                OpReturn
2393                OpFunctionEnd
2394   )";
2395 
2396   const auto env = SPV_ENV_UNIVERSAL_1_5;
2397   const auto consumer = nullptr;
2398   const auto context =
2399       BuildModule(env, consumer, reference_shader, kFuzzAssembleOption);
2400   spvtools::ValidatorOptions validator_options;
2401   ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
2402                                                kConsoleMessageConsumer));
2403   TransformationContext transformation_context(
2404       MakeUnique<FactManager>(context.get()), validator_options);
2405   auto instruction_descriptor =
2406       MakeInstructionDescriptor(24, spv::Op::OpDot, 0);
2407   auto transformation = TransformationReplaceLinearAlgebraInstruction(
2408       {27, 28, 29, 30, 31, 32}, instruction_descriptor);
2409   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
2410 
2411   instruction_descriptor = MakeInstructionDescriptor(25, spv::Op::OpDot, 0);
2412   transformation = TransformationReplaceLinearAlgebraInstruction(
2413       {33, 34, 35, 36, 37, 38, 39, 40, 41, 42}, instruction_descriptor);
2414   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
2415 
2416   instruction_descriptor = MakeInstructionDescriptor(26, spv::Op::OpDot, 0);
2417   transformation = TransformationReplaceLinearAlgebraInstruction(
2418       {43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56},
2419       instruction_descriptor);
2420   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
2421 
2422   std::string variant_shader = R"(
2423                OpCapability Shader
2424           %1 = OpExtInstImport "GLSL.std.450"
2425                OpMemoryModel Logical GLSL450
2426                OpEntryPoint Fragment %22 "main"
2427                OpExecutionMode %22 OriginUpperLeft
2428                OpSource ESSL 310
2429                OpName %22 "main"
2430           %2 = OpTypeVoid
2431           %3 = OpTypeFunction %2
2432           %4 = OpTypeFloat 32
2433           %5 = OpTypeVector %4 2
2434           %6 = OpTypeVector %4 3
2435           %7 = OpTypeVector %4 4
2436           %8 = OpConstant %4 1
2437           %9 = OpConstant %4 2
2438          %10 = OpConstant %4 3
2439          %11 = OpConstant %4 4
2440          %12 = OpConstant %4 5
2441          %13 = OpConstant %4 6
2442          %14 = OpConstant %4 7
2443          %15 = OpConstant %4 8
2444          %16 = OpConstantComposite %5 %8 %9
2445          %17 = OpConstantComposite %5 %10 %11
2446          %18 = OpConstantComposite %6 %8 %9 %10
2447          %19 = OpConstantComposite %6 %11 %12 %13
2448          %20 = OpConstantComposite %7 %8 %9 %10 %11
2449          %21 = OpConstantComposite %7 %12 %13 %14 %15
2450          %22 = OpFunction %2 None %3
2451          %23 = OpLabel
2452          %27 = OpCompositeExtract %4 %16 0
2453          %28 = OpCompositeExtract %4 %17 0
2454          %29 = OpFMul %4 %27 %28
2455          %30 = OpCompositeExtract %4 %16 1
2456          %31 = OpCompositeExtract %4 %17 1
2457          %32 = OpFMul %4 %30 %31
2458          %24 = OpFAdd %4 %29 %32
2459          %33 = OpCompositeExtract %4 %18 0
2460          %34 = OpCompositeExtract %4 %19 0
2461          %35 = OpFMul %4 %33 %34
2462          %36 = OpCompositeExtract %4 %18 1
2463          %37 = OpCompositeExtract %4 %19 1
2464          %38 = OpFMul %4 %36 %37
2465          %39 = OpCompositeExtract %4 %18 2
2466          %40 = OpCompositeExtract %4 %19 2
2467          %41 = OpFMul %4 %39 %40
2468          %42 = OpFAdd %4 %35 %38
2469          %25 = OpFAdd %4 %41 %42
2470          %43 = OpCompositeExtract %4 %20 0
2471          %44 = OpCompositeExtract %4 %21 0
2472          %45 = OpFMul %4 %43 %44
2473          %46 = OpCompositeExtract %4 %20 1
2474          %47 = OpCompositeExtract %4 %21 1
2475          %48 = OpFMul %4 %46 %47
2476          %49 = OpCompositeExtract %4 %20 2
2477          %50 = OpCompositeExtract %4 %21 2
2478          %51 = OpFMul %4 %49 %50
2479          %52 = OpCompositeExtract %4 %20 3
2480          %53 = OpCompositeExtract %4 %21 3
2481          %54 = OpFMul %4 %52 %53
2482          %55 = OpFAdd %4 %45 %48
2483          %56 = OpFAdd %4 %51 %55
2484          %26 = OpFAdd %4 %54 %56
2485                OpReturn
2486                OpFunctionEnd
2487   )";
2488 
2489   ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
2490                                                kConsoleMessageConsumer));
2491   ASSERT_TRUE(IsEqual(env, variant_shader, context.get()));
2492 }
2493 
2494 }  // namespace
2495 }  // namespace fuzz
2496 }  // namespace spvtools
2497