• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2019 Google LLC
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include <limits>
16 
17 #include "source/fuzz/fact_manager.h"
18 #include "source/fuzz/uniform_buffer_element_descriptor.h"
19 #include "test/fuzz/fuzz_test_util.h"
20 
21 namespace spvtools {
22 namespace fuzz {
23 namespace {
24 
25 using opt::analysis::BoolConstant;
26 using opt::analysis::FloatConstant;
27 using opt::analysis::IntConstant;
28 using opt::analysis::ScalarConstant;
29 
30 using opt::analysis::Bool;
31 using opt::analysis::Float;
32 using opt::analysis::Integer;
33 using opt::analysis::Type;
34 
AddFactHelper(FactManager * fact_manager,opt::IRContext * context,std::vector<uint32_t> && words,const protobufs::UniformBufferElementDescriptor & descriptor)35 bool AddFactHelper(
36     FactManager* fact_manager, opt::IRContext* context,
37     std::vector<uint32_t>&& words,
38     const protobufs::UniformBufferElementDescriptor& descriptor) {
39   protobufs::FactConstantUniform constant_uniform_fact;
40   for (auto word : words) {
41     constant_uniform_fact.add_constant_word(word);
42   }
43   *constant_uniform_fact.mutable_uniform_buffer_element_descriptor() =
44       descriptor;
45   protobufs::Fact fact;
46   *fact.mutable_constant_uniform_fact() = constant_uniform_fact;
47   return fact_manager->AddFact(fact, context);
48 }
49 
TEST(FactManagerTest,ConstantsAvailableViaUniforms)50 TEST(FactManagerTest, ConstantsAvailableViaUniforms) {
51   std::string shader = R"(
52                OpCapability Shader
53                OpCapability Int64
54                OpCapability Float64
55           %1 = OpExtInstImport "GLSL.std.450"
56                OpMemoryModel Logical GLSL450
57                OpEntryPoint Fragment %4 "main"
58                OpExecutionMode %4 OriginUpperLeft
59                OpSource GLSL 450
60                OpName %4 "main"
61                OpDecorate %100 DescriptorSet 0
62                OpDecorate %100 Binding 0
63                OpDecorate %200 DescriptorSet 0
64                OpDecorate %200 Binding 1
65                OpDecorate %300 DescriptorSet 0
66                OpDecorate %300 Binding 2
67                OpDecorate %400 DescriptorSet 0
68                OpDecorate %400 Binding 3
69                OpDecorate %500 DescriptorSet 0
70                OpDecorate %500 Binding 4
71                OpDecorate %600 DescriptorSet 0
72                OpDecorate %600 Binding 5
73                OpDecorate %700 DescriptorSet 0
74                OpDecorate %700 Binding 6
75                OpDecorate %800 DescriptorSet 1
76                OpDecorate %800 Binding 0
77                OpDecorate %900 DescriptorSet 1
78                OpDecorate %900 Binding 1
79                OpDecorate %1000 DescriptorSet 1
80                OpDecorate %1000 Binding 2
81                OpDecorate %1100 DescriptorSet 1
82                OpDecorate %1100 Binding 3
83                OpDecorate %1200 DescriptorSet 1
84                OpDecorate %1200 Binding 4
85                OpDecorate %1300 DescriptorSet 1
86                OpDecorate %1300 Binding 5
87                OpDecorate %1400 DescriptorSet 1
88                OpDecorate %1400 Binding 6
89                OpDecorate %1500 DescriptorSet 2
90                OpDecorate %1500 Binding 0
91                OpDecorate %1600 DescriptorSet 2
92                OpDecorate %1600 Binding 1
93                OpDecorate %1700 DescriptorSet 2
94                OpDecorate %1700 Binding 2
95                OpDecorate %1800 DescriptorSet 2
96                OpDecorate %1800 Binding 3
97                OpDecorate %1900 DescriptorSet 2
98                OpDecorate %1900 Binding 4
99           %2 = OpTypeVoid
100           %3 = OpTypeFunction %2
101          %10 = OpTypeInt 32 0
102          %11 = OpTypeInt 32 1
103          %12 = OpTypeInt 64 0
104          %13 = OpTypeInt 64 1
105          %15 = OpTypeFloat 32
106          %16 = OpTypeFloat 64
107          %17 = OpConstant %11 5
108          %18 = OpConstant %11 20
109          %19 = OpTypeVector %10 4
110          %20 = OpConstant %11 6
111          %21 = OpTypeVector %12 4
112          %22 = OpConstant %11 10
113          %23 = OpTypeVector %11 4
114 
115         %102 = OpTypeStruct %10 %10 %23
116         %101 = OpTypePointer Uniform %102
117         %100 = OpVariable %101 Uniform
118 
119         %203 = OpTypeArray %23 %17
120         %202 = OpTypeArray %203 %18
121         %201 = OpTypePointer Uniform %202
122         %200 = OpVariable %201 Uniform
123 
124         %305 = OpTypeStruct %16 %16 %16 %11 %16
125         %304 = OpTypeStruct %16 %16 %305
126         %303 = OpTypeStruct %304
127         %302 = OpTypeStruct %10 %303
128         %301 = OpTypePointer Uniform %302
129         %300 = OpVariable %301 Uniform
130 
131         %400 = OpVariable %101 Uniform
132 
133         %500 = OpVariable %201 Uniform
134 
135         %604 = OpTypeArray %13 %20
136         %603 = OpTypeArray %604 %20
137         %602 = OpTypeArray %603 %20
138         %601 = OpTypePointer Uniform %602
139         %600 = OpVariable %601 Uniform
140 
141         %703 = OpTypeArray %13 %20
142         %702 = OpTypeArray %703 %20
143         %701 = OpTypePointer Uniform %702
144         %700 = OpVariable %701 Uniform
145 
146         %802 = OpTypeStruct %702 %602 %19 %202 %302
147         %801 = OpTypePointer Uniform %802
148         %800 = OpVariable %801 Uniform
149 
150         %902 = OpTypeStruct %702 %802 %19 %202 %302
151         %901 = OpTypePointer Uniform %902
152         %900 = OpVariable %901 Uniform
153 
154        %1003 = OpTypeStruct %802
155        %1002 = OpTypeArray %1003 %20
156        %1001 = OpTypePointer Uniform %1002
157        %1000 = OpVariable %1001 Uniform
158 
159        %1101 = OpTypePointer Uniform %21
160        %1100 = OpVariable %1101 Uniform
161 
162        %1202 = OpTypeArray %21 %20
163        %1201 = OpTypePointer Uniform %1202
164        %1200 = OpVariable %1201 Uniform
165 
166        %1302 = OpTypeArray %21 %20
167        %1301 = OpTypePointer Uniform %1302
168        %1300 = OpVariable %1301 Uniform
169 
170        %1402 = OpTypeArray %15 %22
171        %1401 = OpTypePointer Uniform %1402
172        %1400 = OpVariable %1401 Uniform
173 
174        %1501 = OpTypePointer Uniform %1402
175        %1500 = OpVariable %1501 Uniform
176 
177        %1602 = OpTypeArray %1402 %22
178        %1601 = OpTypePointer Uniform %1602
179        %1600 = OpVariable %1601 Uniform
180 
181        %1704 = OpTypeStruct %16 %16 %16
182        %1703 = OpTypeArray %1704 %22
183        %1702 = OpTypeArray %1703 %22
184        %1701 = OpTypePointer Uniform %1702
185        %1700 = OpVariable %1701 Uniform
186 
187        %1800 = OpVariable %1701 Uniform
188 
189        %1906 = OpTypeStruct %16
190        %1905 = OpTypeStruct %1906
191        %1904 = OpTypeStruct %1905
192        %1903 = OpTypeStruct %1904
193        %1902 = OpTypeStruct %1903
194        %1901 = OpTypePointer Uniform %1902
195        %1900 = OpVariable %1901 Uniform
196 
197           %4 = OpFunction %2 None %3
198           %5 = OpLabel
199                OpReturn
200                OpFunctionEnd
201   )";
202 
203   const auto env = SPV_ENV_UNIVERSAL_1_3;
204   const auto consumer = nullptr;
205   const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
206   ASSERT_TRUE(IsValid(env, context.get()));
207 
208   uint32_t buffer_int32_min[1];
209   uint32_t buffer_int64_1[2];
210   uint32_t buffer_int64_max[2];
211   uint32_t buffer_uint64_1[2];
212   uint32_t buffer_uint64_max[2];
213   uint32_t buffer_float_10[1];
214   uint32_t buffer_double_10[2];
215   uint32_t buffer_double_20[2];
216 
217   {
218     int32_t temp = std::numeric_limits<int32_t>::min();
219     std::memcpy(&buffer_int32_min, &temp, sizeof(temp));
220   }
221 
222   {
223     int64_t temp = 1;
224     std::memcpy(&buffer_int64_1, &temp, sizeof(temp));
225   }
226 
227   {
228     int64_t temp = std::numeric_limits<int64_t>::max();
229     std::memcpy(&buffer_int64_max, &temp, sizeof(temp));
230   }
231 
232   {
233     uint64_t temp = 1;
234     std::memcpy(&buffer_uint64_1, &temp, sizeof(temp));
235   }
236 
237   {
238     uint64_t temp = std::numeric_limits<uint64_t>::max();
239     std::memcpy(&buffer_uint64_max, &temp, sizeof(temp));
240   }
241 
242   {
243     float temp = 10.0f;
244     std::memcpy(&buffer_float_10, &temp, sizeof(float));
245   }
246 
247   {
248     double temp = 10.0;
249     std::memcpy(&buffer_double_10, &temp, sizeof(temp));
250   }
251 
252   {
253     double temp = 20.0;
254     std::memcpy(&buffer_double_20, &temp, sizeof(temp));
255   }
256 
257   FactManager fact_manager;
258 
259   uint32_t type_int32_id = 11;
260   uint32_t type_int64_id = 13;
261   uint32_t type_uint32_id = 10;
262   uint32_t type_uint64_id = 12;
263   uint32_t type_float_id = 15;
264   uint32_t type_double_id = 16;
265 
266   // Initially there should be no facts about uniforms.
267   ASSERT_TRUE(fact_manager
268                   .GetConstantsAvailableFromUniformsForType(context.get(),
269                                                             type_uint32_id)
270                   .empty());
271 
272   // In the comments that follow we write v[...][...] to refer to uniform
273   // variable v indexed with some given indices, when in practice v is
274   // identified via a (descriptor set, binding) pair.
275 
276   // 100[2][3] == int(1)
277   ASSERT_TRUE(AddFactHelper(&fact_manager, context.get(), {1},
278                             MakeUniformBufferElementDescriptor(0, 0, {2, 3})));
279 
280   // 200[1][2][3] == int(1)
281   ASSERT_TRUE(
282       AddFactHelper(&fact_manager, context.get(), {1},
283                     MakeUniformBufferElementDescriptor(0, 1, {1, 2, 3})));
284 
285   // 300[1][0][2][3] == int(1)
286   ASSERT_TRUE(
287       AddFactHelper(&fact_manager, context.get(), {1},
288                     MakeUniformBufferElementDescriptor(0, 2, {1, 0, 2, 3})));
289 
290   // 400[2][3] = int32_min
291   ASSERT_TRUE(AddFactHelper(&fact_manager, context.get(), {buffer_int32_min[0]},
292                             MakeUniformBufferElementDescriptor(0, 3, {2, 3})));
293 
294   // 500[1][2][3] = int32_min
295   ASSERT_TRUE(
296       AddFactHelper(&fact_manager, context.get(), {buffer_int32_min[0]},
297                     MakeUniformBufferElementDescriptor(0, 4, {1, 2, 3})));
298 
299   // 600[1][2][3] = int64_max
300   ASSERT_TRUE(AddFactHelper(
301       &fact_manager, context.get(), {buffer_int64_max[0], buffer_int64_max[1]},
302       MakeUniformBufferElementDescriptor(0, 5, {1, 2, 3})));
303 
304   // 700[1][1] = int64_max
305   ASSERT_TRUE(AddFactHelper(&fact_manager, context.get(),
306                             {buffer_int64_max[0], buffer_int64_max[1]},
307                             MakeUniformBufferElementDescriptor(0, 6, {1, 1})));
308 
309   // 800[2][3] = uint(1)
310   ASSERT_TRUE(AddFactHelper(&fact_manager, context.get(), {1},
311                             MakeUniformBufferElementDescriptor(1, 0, {2, 3})));
312 
313   // 900[1][2][3] = uint(1)
314   ASSERT_TRUE(
315       AddFactHelper(&fact_manager, context.get(), {1},
316                     MakeUniformBufferElementDescriptor(1, 1, {1, 2, 3})));
317 
318   // 1000[1][0][2][3] = uint(1)
319   ASSERT_TRUE(
320       AddFactHelper(&fact_manager, context.get(), {1},
321                     MakeUniformBufferElementDescriptor(1, 2, {1, 0, 2, 3})));
322 
323   // 1100[0] = uint64(1)
324   ASSERT_TRUE(AddFactHelper(&fact_manager, context.get(),
325                             {buffer_uint64_1[0], buffer_uint64_1[1]},
326                             MakeUniformBufferElementDescriptor(1, 3, {0})));
327 
328   // 1200[0][0] = uint64_max
329   ASSERT_TRUE(AddFactHelper(&fact_manager, context.get(),
330                             {buffer_uint64_max[0], buffer_uint64_max[1]},
331                             MakeUniformBufferElementDescriptor(1, 4, {0, 0})));
332 
333   // 1300[1][0] = uint64_max
334   ASSERT_TRUE(AddFactHelper(&fact_manager, context.get(),
335                             {buffer_uint64_max[0], buffer_uint64_max[1]},
336                             MakeUniformBufferElementDescriptor(1, 5, {1, 0})));
337 
338   // 1400[6] = float(10.0)
339   ASSERT_TRUE(AddFactHelper(&fact_manager, context.get(), {buffer_float_10[0]},
340                             MakeUniformBufferElementDescriptor(1, 6, {6})));
341 
342   // 1500[7] = float(10.0)
343   ASSERT_TRUE(AddFactHelper(&fact_manager, context.get(), {buffer_float_10[0]},
344                             MakeUniformBufferElementDescriptor(2, 0, {7})));
345 
346   // 1600[9][9] = float(10.0)
347   ASSERT_TRUE(AddFactHelper(&fact_manager, context.get(), {buffer_float_10[0]},
348                             MakeUniformBufferElementDescriptor(2, 1, {9, 9})));
349 
350   // 1700[9][9][1] = double(10.0)
351   ASSERT_TRUE(AddFactHelper(
352       &fact_manager, context.get(), {buffer_double_10[0], buffer_double_10[1]},
353       MakeUniformBufferElementDescriptor(2, 2, {9, 9, 1})));
354 
355   // 1800[9][9][2] = double(10.0)
356   ASSERT_TRUE(AddFactHelper(
357       &fact_manager, context.get(), {buffer_double_10[0], buffer_double_10[1]},
358       MakeUniformBufferElementDescriptor(2, 3, {9, 9, 2})));
359 
360   // 1900[0][0][0][0][0] = double(20.0)
361   ASSERT_TRUE(AddFactHelper(
362       &fact_manager, context.get(), {buffer_double_20[0], buffer_double_20[1]},
363       MakeUniformBufferElementDescriptor(2, 4, {0, 0, 0, 0, 0})));
364 
365   opt::Instruction::OperandList operands = {
366       {SPV_OPERAND_TYPE_LITERAL_INTEGER, {1}}};
367   context->module()->AddGlobalValue(MakeUnique<opt::Instruction>(
368       context.get(), SpvOpConstant, type_int32_id, 50, operands));
369   operands = {{SPV_OPERAND_TYPE_LITERAL_INTEGER, {buffer_int32_min[0]}}};
370   context->module()->AddGlobalValue(MakeUnique<opt::Instruction>(
371       context.get(), SpvOpConstant, type_int32_id, 51, operands));
372   operands = {{SPV_OPERAND_TYPE_LITERAL_INTEGER, {buffer_int64_max[0]}},
373               {SPV_OPERAND_TYPE_LITERAL_INTEGER, {buffer_int64_max[1]}}};
374   context->module()->AddGlobalValue(MakeUnique<opt::Instruction>(
375       context.get(), SpvOpConstant, type_int64_id, 52, operands));
376   operands = {{SPV_OPERAND_TYPE_LITERAL_INTEGER, {1}}};
377   context->module()->AddGlobalValue(MakeUnique<opt::Instruction>(
378       context.get(), SpvOpConstant, type_uint32_id, 53, operands));
379   operands = {{SPV_OPERAND_TYPE_LITERAL_INTEGER, {buffer_uint64_1[0]}},
380               {SPV_OPERAND_TYPE_LITERAL_INTEGER, {buffer_uint64_1[1]}}};
381   context->module()->AddGlobalValue(MakeUnique<opt::Instruction>(
382       context.get(), SpvOpConstant, type_uint64_id, 54, operands));
383   operands = {{SPV_OPERAND_TYPE_LITERAL_INTEGER, {buffer_uint64_max[0]}},
384               {SPV_OPERAND_TYPE_LITERAL_INTEGER, {buffer_uint64_max[1]}}};
385   context->module()->AddGlobalValue(MakeUnique<opt::Instruction>(
386       context.get(), SpvOpConstant, type_uint64_id, 55, operands));
387   operands = {{SPV_OPERAND_TYPE_LITERAL_INTEGER, {buffer_float_10[0]}}};
388   context->module()->AddGlobalValue(MakeUnique<opt::Instruction>(
389       context.get(), SpvOpConstant, type_float_id, 56, operands));
390   operands = {{SPV_OPERAND_TYPE_LITERAL_INTEGER, {buffer_double_10[0]}},
391               {SPV_OPERAND_TYPE_LITERAL_INTEGER, {buffer_double_10[1]}}};
392   context->module()->AddGlobalValue(MakeUnique<opt::Instruction>(
393       context.get(), SpvOpConstant, type_double_id, 57, operands));
394   operands = {{SPV_OPERAND_TYPE_LITERAL_INTEGER, {buffer_double_20[0]}},
395               {SPV_OPERAND_TYPE_LITERAL_INTEGER, {buffer_double_20[1]}}};
396   context->module()->AddGlobalValue(MakeUnique<opt::Instruction>(
397       context.get(), SpvOpConstant, type_double_id, 58, operands));
398 
399   // A duplicate of the constant with id 59.
400   operands = {{SPV_OPERAND_TYPE_LITERAL_INTEGER, {1}}};
401   context->module()->AddGlobalValue(MakeUnique<opt::Instruction>(
402       context.get(), SpvOpConstant, type_int32_id, 59, operands));
403 
404   context->InvalidateAnalysesExceptFor(opt::IRContext::Analysis::kAnalysisNone);
405 
406   // Constants 1 and int32_min are available.
407   ASSERT_EQ(2, fact_manager
408                    .GetConstantsAvailableFromUniformsForType(context.get(),
409                                                              type_int32_id)
410                    .size());
411   // Constant int64_max is available.
412   ASSERT_EQ(1, fact_manager
413                    .GetConstantsAvailableFromUniformsForType(context.get(),
414                                                              type_int64_id)
415                    .size());
416   // Constant 1u is available.
417   ASSERT_EQ(1, fact_manager
418                    .GetConstantsAvailableFromUniformsForType(context.get(),
419                                                              type_uint32_id)
420                    .size());
421   // Constants 1u and uint64_max are available.
422   ASSERT_EQ(2, fact_manager
423                    .GetConstantsAvailableFromUniformsForType(context.get(),
424                                                              type_uint64_id)
425                    .size());
426   // Constant 10.0 is available.
427   ASSERT_EQ(1, fact_manager
428                    .GetConstantsAvailableFromUniformsForType(context.get(),
429                                                              type_float_id)
430                    .size());
431   // Constants 10.0 and 20.0 are available.
432   ASSERT_EQ(2, fact_manager
433                    .GetConstantsAvailableFromUniformsForType(context.get(),
434                                                              type_double_id)
435                    .size());
436 
437   ASSERT_EQ(std::numeric_limits<int64_t>::max(),
438             context->get_constant_mgr()
439                 ->FindDeclaredConstant(
440                     fact_manager.GetConstantsAvailableFromUniformsForType(
441                         context.get(), type_int64_id)[0])
442                 ->AsIntConstant()
443                 ->GetS64());
444   ASSERT_EQ(1, context->get_constant_mgr()
445                    ->FindDeclaredConstant(
446                        fact_manager.GetConstantsAvailableFromUniformsForType(
447                            context.get(), type_uint32_id)[0])
448                    ->AsIntConstant()
449                    ->GetU32());
450   ASSERT_EQ(10.0f,
451             context->get_constant_mgr()
452                 ->FindDeclaredConstant(
453                     fact_manager.GetConstantsAvailableFromUniformsForType(
454                         context.get(), type_float_id)[0])
455                 ->AsFloatConstant()
456                 ->GetFloat());
457   const std::vector<uint32_t>& double_constant_ids =
458       fact_manager.GetConstantsAvailableFromUniformsForType(context.get(),
459                                                             type_double_id);
460   ASSERT_EQ(10.0, context->get_constant_mgr()
461                       ->FindDeclaredConstant(double_constant_ids[0])
462                       ->AsFloatConstant()
463                       ->GetDouble());
464   ASSERT_EQ(20.0, context->get_constant_mgr()
465                       ->FindDeclaredConstant(double_constant_ids[1])
466                       ->AsFloatConstant()
467                       ->GetDouble());
468 
469   const std::vector<protobufs::UniformBufferElementDescriptor>
470       descriptors_for_double_10 = fact_manager.GetUniformDescriptorsForConstant(
471           context.get(), double_constant_ids[0]);
472   ASSERT_EQ(2, descriptors_for_double_10.size());
473   {
474     auto temp = MakeUniformBufferElementDescriptor(2, 2, {9, 9, 1});
475     ASSERT_TRUE(UniformBufferElementDescriptorEquals()(
476         &temp, &descriptors_for_double_10[0]));
477   }
478   {
479     auto temp = MakeUniformBufferElementDescriptor(2, 3, {9, 9, 2});
480     ASSERT_TRUE(UniformBufferElementDescriptorEquals()(
481         &temp, &descriptors_for_double_10[1]));
482   }
483   const std::vector<protobufs::UniformBufferElementDescriptor>
484       descriptors_for_double_20 = fact_manager.GetUniformDescriptorsForConstant(
485           context.get(), double_constant_ids[1]);
486   ASSERT_EQ(1, descriptors_for_double_20.size());
487   {
488     auto temp = MakeUniformBufferElementDescriptor(2, 4, {0, 0, 0, 0, 0});
489     ASSERT_TRUE(UniformBufferElementDescriptorEquals()(
490         &temp, &descriptors_for_double_20[0]));
491   }
492 
493   auto constant_1_id = fact_manager.GetConstantFromUniformDescriptor(
494       context.get(), MakeUniformBufferElementDescriptor(2, 3, {9, 9, 2}));
495   ASSERT_TRUE(constant_1_id);
496 
497   auto constant_2_id = fact_manager.GetConstantFromUniformDescriptor(
498       context.get(), MakeUniformBufferElementDescriptor(2, 4, {0, 0, 0, 0, 0}));
499   ASSERT_TRUE(constant_2_id);
500 
501   ASSERT_EQ(double_constant_ids[0], constant_1_id);
502 
503   ASSERT_EQ(double_constant_ids[1], constant_2_id);
504 }
505 
TEST(FactManagerTest,TwoConstantsWithSameValue)506 TEST(FactManagerTest, TwoConstantsWithSameValue) {
507   std::string shader = R"(
508                OpCapability Shader
509           %1 = OpExtInstImport "GLSL.std.450"
510                OpMemoryModel Logical GLSL450
511                OpEntryPoint Fragment %4 "main"
512                OpExecutionMode %4 OriginUpperLeft
513                OpSource ESSL 310
514                OpName %4 "main"
515                OpName %8 "x"
516                OpName %10 "buf"
517                OpMemberName %10 0 "a"
518                OpName %12 ""
519                OpDecorate %8 RelaxedPrecision
520                OpMemberDecorate %10 0 RelaxedPrecision
521                OpMemberDecorate %10 0 Offset 0
522                OpDecorate %10 Block
523                OpDecorate %12 DescriptorSet 0
524                OpDecorate %12 Binding 0
525           %2 = OpTypeVoid
526           %3 = OpTypeFunction %2
527           %6 = OpTypeInt 32 1
528           %7 = OpTypePointer Function %6
529           %9 = OpConstant %6 1
530          %20 = OpConstant %6 1
531          %10 = OpTypeStruct %6
532          %11 = OpTypePointer Uniform %10
533          %12 = OpVariable %11 Uniform
534           %4 = OpFunction %2 None %3
535           %5 = OpLabel
536           %8 = OpVariable %7 Function
537                OpStore %8 %9
538                OpReturn
539                OpFunctionEnd
540   )";
541 
542   const auto env = SPV_ENV_UNIVERSAL_1_3;
543   const auto consumer = nullptr;
544   const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
545   ASSERT_TRUE(IsValid(env, context.get()));
546 
547   FactManager fact_manager;
548 
549   auto uniform_buffer_element_descriptor =
550       MakeUniformBufferElementDescriptor(0, 0, {0});
551 
552   // (0, 0, [0]) = int(1)
553   ASSERT_TRUE(AddFactHelper(&fact_manager, context.get(), {1},
554                             uniform_buffer_element_descriptor));
555   auto constants =
556       fact_manager.GetConstantsAvailableFromUniformsForType(context.get(), 6);
557   ASSERT_EQ(1, constants.size());
558   ASSERT_TRUE(constants[0] == 9 || constants[0] == 20);
559 
560   auto constant = fact_manager.GetConstantFromUniformDescriptor(
561       context.get(), uniform_buffer_element_descriptor);
562   ASSERT_TRUE(constant == 9 || constant == 20);
563 
564   // Because the constants with ids 9 and 20 are equal, we should get the same
565   // single uniform buffer element descriptor when we look up the descriptors
566   // for either one of them.
567   for (auto constant_id : {9u, 20u}) {
568     auto descriptors = fact_manager.GetUniformDescriptorsForConstant(
569         context.get(), constant_id);
570     ASSERT_EQ(1, descriptors.size());
571     ASSERT_TRUE(UniformBufferElementDescriptorEquals()(
572         &uniform_buffer_element_descriptor, &descriptors[0]));
573   }
574 }
575 
TEST(FactManagerTest,NonFiniteFactsAreNotValid)576 TEST(FactManagerTest, NonFiniteFactsAreNotValid) {
577   std::string shader = R"(
578                OpCapability Shader
579                OpCapability Float64
580           %1 = OpExtInstImport "GLSL.std.450"
581                OpMemoryModel Logical GLSL450
582                OpEntryPoint Fragment %4 "main"
583                OpExecutionMode %4 OriginUpperLeft
584                OpSource ESSL 310
585                OpName %4 "main"
586                OpName %7 "buf"
587                OpMemberName %7 0 "f"
588                OpMemberName %7 1 "d"
589                OpName %9 ""
590                OpMemberDecorate %7 0 Offset 0
591                OpMemberDecorate %7 1 Offset 8
592                OpDecorate %7 Block
593                OpDecorate %9 DescriptorSet 0
594                OpDecorate %9 Binding 0
595           %2 = OpTypeVoid
596           %3 = OpTypeFunction %2
597           %6 = OpTypeFloat 32
598          %10 = OpTypeFloat 64
599           %7 = OpTypeStruct %6 %10
600           %8 = OpTypePointer Uniform %7
601           %9 = OpVariable %8 Uniform
602           %4 = OpFunction %2 None %3
603           %5 = OpLabel
604                OpReturn
605                OpFunctionEnd
606   )";
607 
608   const auto env = SPV_ENV_UNIVERSAL_1_3;
609   const auto consumer = nullptr;
610   const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
611   ASSERT_TRUE(IsValid(env, context.get()));
612 
613   FactManager fact_manager;
614   auto uniform_buffer_element_descriptor_f =
615       MakeUniformBufferElementDescriptor(0, 0, {0});
616 
617   auto uniform_buffer_element_descriptor_d =
618       MakeUniformBufferElementDescriptor(0, 0, {1});
619 
620   if (std::numeric_limits<float>::has_infinity) {
621     // f == +inf
622     float positive_infinity_float = std::numeric_limits<float>::infinity();
623     uint32_t words[1];
624     memcpy(words, &positive_infinity_float, sizeof(float));
625     ASSERT_FALSE(AddFactHelper(&fact_manager, context.get(), {words[0]},
626                                uniform_buffer_element_descriptor_f));
627     // f == -inf
628     float negative_infinity_float = std::numeric_limits<float>::infinity();
629     memcpy(words, &negative_infinity_float, sizeof(float));
630     ASSERT_FALSE(AddFactHelper(&fact_manager, context.get(), {words[0]},
631                                uniform_buffer_element_descriptor_f));
632   }
633 
634   if (std::numeric_limits<float>::has_quiet_NaN) {
635     // f == NaN
636     float quiet_nan_float = std::numeric_limits<float>::quiet_NaN();
637     uint32_t words[1];
638     memcpy(words, &quiet_nan_float, sizeof(float));
639     ASSERT_FALSE(AddFactHelper(&fact_manager, context.get(), {words[0]},
640                                uniform_buffer_element_descriptor_f));
641   }
642 
643   if (std::numeric_limits<double>::has_infinity) {
644     // d == +inf
645     double positive_infinity_double = std::numeric_limits<double>::infinity();
646     uint32_t words[2];
647     memcpy(words, &positive_infinity_double, sizeof(double));
648     ASSERT_FALSE(AddFactHelper(&fact_manager, context.get(),
649                                {words[0], words[1]},
650                                uniform_buffer_element_descriptor_d));
651     // d == -inf
652     double negative_infinity_double = -std::numeric_limits<double>::infinity();
653     memcpy(words, &negative_infinity_double, sizeof(double));
654     ASSERT_FALSE(AddFactHelper(&fact_manager, context.get(),
655                                {words[0], words[1]},
656                                uniform_buffer_element_descriptor_d));
657   }
658 
659   if (std::numeric_limits<double>::has_quiet_NaN) {
660     // d == NaN
661     double quiet_nan_double = std::numeric_limits<double>::quiet_NaN();
662     uint32_t words[2];
663     memcpy(words, &quiet_nan_double, sizeof(double));
664     ASSERT_FALSE(AddFactHelper(&fact_manager, context.get(),
665                                {words[0], words[1]},
666                                uniform_buffer_element_descriptor_d));
667   }
668 }
669 
TEST(FactManagerTest,AmbiguousFact)670 TEST(FactManagerTest, AmbiguousFact) {
671   //  This test came from the following GLSL:
672   //
673   // #version 310 es
674   //
675   // precision highp float;
676   //
677   // layout(set = 0, binding = 0) uniform buf {
678   //   float f;
679   // };
680   //
681   // layout(set = 0, binding = 0) uniform buf2 {
682   //   float g;
683   // };
684   //
685   // void main() {
686   //
687   // }
688 
689   std::string shader = R"(
690                OpCapability Shader
691           %1 = OpExtInstImport "GLSL.std.450"
692                OpMemoryModel Logical GLSL450
693                OpEntryPoint Fragment %4 "main"
694                OpExecutionMode %4 OriginUpperLeft
695                OpSource ESSL 310
696                OpName %4 "main"
697                OpName %7 "buf"
698                OpMemberName %7 0 "f"
699                OpName %9 ""
700                OpName %10 "buf2"
701                OpMemberName %10 0 "g"
702                OpName %12 ""
703                OpMemberDecorate %7 0 Offset 0
704                OpDecorate %7 Block
705                OpDecorate %9 DescriptorSet 0
706                OpDecorate %9 Binding 0
707                OpMemberDecorate %10 0 Offset 0
708                OpDecorate %10 Block
709                OpDecorate %12 DescriptorSet 0
710                OpDecorate %12 Binding 0
711           %2 = OpTypeVoid
712           %3 = OpTypeFunction %2
713           %6 = OpTypeFloat 32
714           %7 = OpTypeStruct %6
715           %8 = OpTypePointer Uniform %7
716           %9 = OpVariable %8 Uniform
717          %10 = OpTypeStruct %6
718          %11 = OpTypePointer Uniform %10
719          %12 = OpVariable %11 Uniform
720           %4 = OpFunction %2 None %3
721           %5 = OpLabel
722                OpReturn
723                OpFunctionEnd
724   )";
725 
726   const auto env = SPV_ENV_UNIVERSAL_1_3;
727   const auto consumer = nullptr;
728   const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
729   ASSERT_TRUE(IsValid(env, context.get()));
730 
731   FactManager fact_manager;
732   auto uniform_buffer_element_descriptor =
733       MakeUniformBufferElementDescriptor(0, 0, {0});
734 
735   // The fact cannot be added because it is ambiguous: there are two uniforms
736   // with descriptor set 0 and binding 0.
737   ASSERT_FALSE(AddFactHelper(&fact_manager, context.get(), {1},
738                              uniform_buffer_element_descriptor));
739 }
740 
TEST(FactManagerTest,DataSynonymFacts)741 TEST(FactManagerTest, DataSynonymFacts) {
742   // The SPIR-V types and constants come from the following code.  The body of
743   // the SPIR-V function then constructs a composite that is synonymous with
744   // myT.
745   //
746   // #version 310 es
747   //
748   // precision highp float;
749   //
750   // struct S {
751   //   int a;
752   //   uvec2 b;
753   // };
754   //
755   // struct T {
756   //   bool c[5];
757   //   mat4x2 d;
758   //   S e;
759   // };
760   //
761   // void main() {
762   //   T myT = T(bool[5](true, false, true, false, true),
763   //             mat4x2(vec2(1.0, 2.0), vec2(3.0, 4.0),
764   // 	           vec2(5.0, 6.0), vec2(7.0, 8.0)),
765   //             S(10, uvec2(100u, 200u)));
766   // }
767 
768   std::string shader = R"(
769                OpCapability Shader
770           %1 = OpExtInstImport "GLSL.std.450"
771                OpMemoryModel Logical GLSL450
772                OpEntryPoint Fragment %4 "main"
773                OpExecutionMode %4 OriginUpperLeft
774                OpSource ESSL 310
775                OpName %4 "main"
776                OpName %15 "S"
777                OpMemberName %15 0 "a"
778                OpMemberName %15 1 "b"
779                OpName %16 "T"
780                OpMemberName %16 0 "c"
781                OpMemberName %16 1 "d"
782                OpMemberName %16 2 "e"
783                OpName %18 "myT"
784                OpMemberDecorate %15 0 RelaxedPrecision
785                OpMemberDecorate %15 1 RelaxedPrecision
786           %2 = OpTypeVoid
787           %3 = OpTypeFunction %2
788           %6 = OpTypeBool
789           %7 = OpTypeInt 32 0
790           %8 = OpConstant %7 5
791           %9 = OpTypeArray %6 %8
792          %10 = OpTypeFloat 32
793          %11 = OpTypeVector %10 2
794          %12 = OpTypeMatrix %11 4
795          %13 = OpTypeInt 32 1
796          %14 = OpTypeVector %7 2
797          %15 = OpTypeStruct %13 %14
798          %16 = OpTypeStruct %9 %12 %15
799          %17 = OpTypePointer Function %16
800          %19 = OpConstantTrue %6
801          %20 = OpConstantFalse %6
802          %21 = OpConstantComposite %9 %19 %20 %19 %20 %19
803          %22 = OpConstant %10 1
804          %23 = OpConstant %10 2
805          %24 = OpConstantComposite %11 %22 %23
806          %25 = OpConstant %10 3
807          %26 = OpConstant %10 4
808          %27 = OpConstantComposite %11 %25 %26
809          %28 = OpConstant %10 5
810          %29 = OpConstant %10 6
811          %30 = OpConstantComposite %11 %28 %29
812          %31 = OpConstant %10 7
813          %32 = OpConstant %10 8
814          %33 = OpConstantComposite %11 %31 %32
815          %34 = OpConstantComposite %12 %24 %27 %30 %33
816          %35 = OpConstant %13 10
817          %36 = OpConstant %7 100
818          %37 = OpConstant %7 200
819          %38 = OpConstantComposite %14 %36 %37
820          %39 = OpConstantComposite %15 %35 %38
821          %40 = OpConstantComposite %16 %21 %34 %39
822           %4 = OpFunction %2 None %3
823           %5 = OpLabel
824          %18 = OpVariable %17 Function
825                OpStore %18 %40
826         %100 = OpCompositeConstruct %9 %19 %20 %19 %20 %19
827         %101 = OpCompositeConstruct %11 %22 %23
828         %102 = OpCompositeConstruct %11 %25 %26
829         %103 = OpCompositeConstruct %11 %28 %29
830         %104 = OpCompositeConstruct %11 %31 %32
831         %105 = OpCompositeConstruct %12 %101 %102 %103 %104
832         %106 = OpCompositeConstruct %14 %36 %37
833         %107 = OpCompositeConstruct %15 %35 %106
834         %108 = OpCompositeConstruct %16 %100 %105 %107
835                OpReturn
836                OpFunctionEnd
837   )";
838 
839   const auto env = SPV_ENV_UNIVERSAL_1_3;
840   const auto consumer = nullptr;
841   const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
842   ASSERT_TRUE(IsValid(env, context.get()));
843 
844   FactManager fact_manager;
845 
846   ASSERT_FALSE(fact_manager.IsSynonymous(
847       MakeDataDescriptor(24, {}), MakeDataDescriptor(101, {}), context.get()));
848   ASSERT_FALSE(fact_manager.IsSynonymous(MakeDataDescriptor(24, {0}),
849                                          MakeDataDescriptor(101, {0}),
850                                          context.get()));
851   ASSERT_FALSE(fact_manager.IsSynonymous(MakeDataDescriptor(24, {1}),
852                                          MakeDataDescriptor(101, {1}),
853                                          context.get()));
854   ASSERT_FALSE(fact_manager.IsSynonymous(MakeDataDescriptor(24, {0}),
855                                          MakeDataDescriptor(101, {1}),
856                                          context.get()));
857 
858   fact_manager.AddFactDataSynonym(MakeDataDescriptor(24, {}),
859                                   MakeDataDescriptor(101, {}), context.get());
860   ASSERT_TRUE(fact_manager.IsSynonymous(
861       MakeDataDescriptor(24, {}), MakeDataDescriptor(101, {}), context.get()));
862   ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(24, {0}),
863                                         MakeDataDescriptor(101, {0}),
864                                         context.get()));
865   ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(24, {1}),
866                                         MakeDataDescriptor(101, {1}),
867                                         context.get()));
868   ASSERT_FALSE(fact_manager.IsSynonymous(MakeDataDescriptor(24, {0}),
869                                          MakeDataDescriptor(101, {1}),
870                                          context.get()));
871 
872   ASSERT_FALSE(fact_manager.IsSynonymous(
873       MakeDataDescriptor(27, {}), MakeDataDescriptor(102, {}), context.get()));
874   ASSERT_FALSE(fact_manager.IsSynonymous(MakeDataDescriptor(27, {0}),
875                                          MakeDataDescriptor(102, {0}),
876                                          context.get()));
877   ASSERT_FALSE(fact_manager.IsSynonymous(MakeDataDescriptor(27, {1}),
878                                          MakeDataDescriptor(102, {1}),
879                                          context.get()));
880   fact_manager.AddFactDataSynonym(MakeDataDescriptor(27, {0}),
881                                   MakeDataDescriptor(102, {0}), context.get());
882   ASSERT_FALSE(fact_manager.IsSynonymous(
883       MakeDataDescriptor(27, {}), MakeDataDescriptor(102, {}), context.get()));
884   ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(27, {0}),
885                                         MakeDataDescriptor(102, {0}),
886                                         context.get()));
887   ASSERT_FALSE(fact_manager.IsSynonymous(MakeDataDescriptor(27, {1}),
888                                          MakeDataDescriptor(102, {1}),
889                                          context.get()));
890   fact_manager.AddFactDataSynonym(MakeDataDescriptor(27, {1}),
891                                   MakeDataDescriptor(102, {1}), context.get());
892   ASSERT_TRUE(fact_manager.IsSynonymous(
893       MakeDataDescriptor(27, {}), MakeDataDescriptor(102, {}), context.get()));
894   ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(27, {0}),
895                                         MakeDataDescriptor(102, {0}),
896                                         context.get()));
897   ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(27, {1}),
898                                         MakeDataDescriptor(102, {1}),
899                                         context.get()));
900 
901   ASSERT_FALSE(fact_manager.IsSynonymous(
902       MakeDataDescriptor(30, {}), MakeDataDescriptor(103, {}), context.get()));
903   ASSERT_FALSE(fact_manager.IsSynonymous(MakeDataDescriptor(30, {0}),
904                                          MakeDataDescriptor(103, {0}),
905                                          context.get()));
906   ASSERT_FALSE(fact_manager.IsSynonymous(MakeDataDescriptor(30, {1}),
907                                          MakeDataDescriptor(103, {1}),
908                                          context.get()));
909   ASSERT_FALSE(fact_manager.IsSynonymous(
910       MakeDataDescriptor(33, {}), MakeDataDescriptor(104, {}), context.get()));
911   ASSERT_FALSE(fact_manager.IsSynonymous(MakeDataDescriptor(33, {0}),
912                                          MakeDataDescriptor(104, {0}),
913                                          context.get()));
914   ASSERT_FALSE(fact_manager.IsSynonymous(MakeDataDescriptor(33, {1}),
915                                          MakeDataDescriptor(104, {1}),
916                                          context.get()));
917   ASSERT_FALSE(fact_manager.IsSynonymous(
918       MakeDataDescriptor(34, {}), MakeDataDescriptor(105, {}), context.get()));
919   ASSERT_FALSE(fact_manager.IsSynonymous(MakeDataDescriptor(34, {0}),
920                                          MakeDataDescriptor(105, {0}),
921                                          context.get()));
922   ASSERT_FALSE(fact_manager.IsSynonymous(MakeDataDescriptor(34, {1}),
923                                          MakeDataDescriptor(105, {1}),
924                                          context.get()));
925   ASSERT_FALSE(fact_manager.IsSynonymous(MakeDataDescriptor(34, {2}),
926                                          MakeDataDescriptor(105, {2}),
927                                          context.get()));
928   ASSERT_FALSE(fact_manager.IsSynonymous(MakeDataDescriptor(34, {3}),
929                                          MakeDataDescriptor(105, {3}),
930                                          context.get()));
931   fact_manager.AddFactDataSynonym(MakeDataDescriptor(30, {}),
932                                   MakeDataDescriptor(103, {}), context.get());
933   fact_manager.AddFactDataSynonym(MakeDataDescriptor(33, {}),
934                                   MakeDataDescriptor(104, {}), context.get());
935   fact_manager.AddFactDataSynonym(MakeDataDescriptor(34, {0}),
936                                   MakeDataDescriptor(105, {0}), context.get());
937   fact_manager.AddFactDataSynonym(MakeDataDescriptor(34, {1}),
938                                   MakeDataDescriptor(105, {1}), context.get());
939   fact_manager.AddFactDataSynonym(MakeDataDescriptor(34, {2}),
940                                   MakeDataDescriptor(105, {2}), context.get());
941   ASSERT_TRUE(fact_manager.IsSynonymous(
942       MakeDataDescriptor(30, {}), MakeDataDescriptor(103, {}), context.get()));
943   ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(30, {0}),
944                                         MakeDataDescriptor(103, {0}),
945                                         context.get()));
946   ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(30, {1}),
947                                         MakeDataDescriptor(103, {1}),
948                                         context.get()));
949   ASSERT_TRUE(fact_manager.IsSynonymous(
950       MakeDataDescriptor(33, {}), MakeDataDescriptor(104, {}), context.get()));
951   ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(33, {0}),
952                                         MakeDataDescriptor(104, {0}),
953                                         context.get()));
954   ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(33, {1}),
955                                         MakeDataDescriptor(104, {1}),
956                                         context.get()));
957   ASSERT_FALSE(fact_manager.IsSynonymous(
958       MakeDataDescriptor(34, {}), MakeDataDescriptor(105, {}), context.get()));
959   ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(34, {0}),
960                                         MakeDataDescriptor(105, {0}),
961                                         context.get()));
962   ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(34, {1}),
963                                         MakeDataDescriptor(105, {1}),
964                                         context.get()));
965   ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(34, {2}),
966                                         MakeDataDescriptor(105, {2}),
967                                         context.get()));
968   ASSERT_FALSE(fact_manager.IsSynonymous(MakeDataDescriptor(34, {3}),
969                                          MakeDataDescriptor(105, {3}),
970                                          context.get()));
971 
972   fact_manager.AddFactDataSynonym(MakeDataDescriptor(34, {3}),
973                                   MakeDataDescriptor(105, {3}), context.get());
974   ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(33, {0}),
975                                         MakeDataDescriptor(104, {0}),
976                                         context.get()));
977   ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(34, {3}),
978                                         MakeDataDescriptor(105, {3}),
979                                         context.get()));
980 
981   ASSERT_FALSE(fact_manager.IsSynonymous(
982       MakeDataDescriptor(21, {}), MakeDataDescriptor(100, {}), context.get()));
983   fact_manager.AddFactDataSynonym(MakeDataDescriptor(21, {0}),
984                                   MakeDataDescriptor(100, {0}), context.get());
985   fact_manager.AddFactDataSynonym(MakeDataDescriptor(21, {1}),
986                                   MakeDataDescriptor(100, {1}), context.get());
987   fact_manager.AddFactDataSynonym(MakeDataDescriptor(21, {2}),
988                                   MakeDataDescriptor(100, {2}), context.get());
989   fact_manager.AddFactDataSynonym(MakeDataDescriptor(21, {3}),
990                                   MakeDataDescriptor(100, {3}), context.get());
991   fact_manager.AddFactDataSynonym(MakeDataDescriptor(21, {4}),
992                                   MakeDataDescriptor(100, {4}), context.get());
993   ASSERT_TRUE(fact_manager.IsSynonymous(
994       MakeDataDescriptor(21, {}), MakeDataDescriptor(100, {}), context.get()));
995 
996   ASSERT_FALSE(fact_manager.IsSynonymous(MakeDataDescriptor(39, {0}),
997                                          MakeDataDescriptor(107, {0}),
998                                          context.get()));
999   ASSERT_FALSE(fact_manager.IsSynonymous(
1000       MakeDataDescriptor(35, {}), MakeDataDescriptor(39, {0}), context.get()));
1001   fact_manager.AddFactDataSynonym(MakeDataDescriptor(39, {0}),
1002                                   MakeDataDescriptor(35, {}), context.get());
1003   ASSERT_FALSE(fact_manager.IsSynonymous(MakeDataDescriptor(39, {0}),
1004                                          MakeDataDescriptor(107, {0}),
1005                                          context.get()));
1006   ASSERT_TRUE(fact_manager.IsSynonymous(
1007       MakeDataDescriptor(35, {}), MakeDataDescriptor(39, {0}), context.get()));
1008 
1009   ASSERT_FALSE(fact_manager.IsSynonymous(
1010       MakeDataDescriptor(38, {0}), MakeDataDescriptor(36, {}), context.get()));
1011   ASSERT_FALSE(fact_manager.IsSynonymous(
1012       MakeDataDescriptor(38, {1}), MakeDataDescriptor(37, {}), context.get()));
1013   ASSERT_FALSE(fact_manager.IsSynonymous(
1014       MakeDataDescriptor(106, {0}), MakeDataDescriptor(36, {}), context.get()));
1015   ASSERT_FALSE(fact_manager.IsSynonymous(
1016       MakeDataDescriptor(106, {1}), MakeDataDescriptor(37, {}), context.get()));
1017   ASSERT_FALSE(fact_manager.IsSynonymous(
1018       MakeDataDescriptor(38, {}), MakeDataDescriptor(106, {}), context.get()));
1019   fact_manager.AddFactDataSynonym(MakeDataDescriptor(38, {0}),
1020                                   MakeDataDescriptor(36, {}), context.get());
1021   fact_manager.AddFactDataSynonym(MakeDataDescriptor(106, {0}),
1022                                   MakeDataDescriptor(36, {}), context.get());
1023   fact_manager.AddFactDataSynonym(MakeDataDescriptor(38, {1}),
1024                                   MakeDataDescriptor(37, {}), context.get());
1025   fact_manager.AddFactDataSynonym(MakeDataDescriptor(106, {1}),
1026                                   MakeDataDescriptor(37, {}), context.get());
1027   ASSERT_TRUE(fact_manager.IsSynonymous(
1028       MakeDataDescriptor(38, {0}), MakeDataDescriptor(36, {}), context.get()));
1029   ASSERT_TRUE(fact_manager.IsSynonymous(
1030       MakeDataDescriptor(38, {1}), MakeDataDescriptor(37, {}), context.get()));
1031   ASSERT_TRUE(fact_manager.IsSynonymous(
1032       MakeDataDescriptor(106, {0}), MakeDataDescriptor(36, {}), context.get()));
1033   ASSERT_TRUE(fact_manager.IsSynonymous(
1034       MakeDataDescriptor(106, {1}), MakeDataDescriptor(37, {}), context.get()));
1035   ASSERT_TRUE(fact_manager.IsSynonymous(
1036       MakeDataDescriptor(38, {}), MakeDataDescriptor(106, {}), context.get()));
1037 
1038   ASSERT_FALSE(fact_manager.IsSynonymous(
1039       MakeDataDescriptor(40, {}), MakeDataDescriptor(108, {}), context.get()));
1040   fact_manager.AddFactDataSynonym(MakeDataDescriptor(107, {0}),
1041                                   MakeDataDescriptor(35, {}), context.get());
1042   fact_manager.AddFactDataSynonym(MakeDataDescriptor(40, {0}),
1043                                   MakeDataDescriptor(108, {0}), context.get());
1044   fact_manager.AddFactDataSynonym(MakeDataDescriptor(40, {1}),
1045                                   MakeDataDescriptor(108, {1}), context.get());
1046   fact_manager.AddFactDataSynonym(MakeDataDescriptor(40, {2}),
1047                                   MakeDataDescriptor(108, {2}), context.get());
1048   ASSERT_TRUE(fact_manager.IsSynonymous(
1049       MakeDataDescriptor(40, {}), MakeDataDescriptor(108, {}), context.get()));
1050   ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(40, {0}),
1051                                         MakeDataDescriptor(108, {0}),
1052                                         context.get()));
1053   ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(40, {1}),
1054                                         MakeDataDescriptor(108, {1}),
1055                                         context.get()));
1056   ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(40, {2}),
1057                                         MakeDataDescriptor(108, {2}),
1058                                         context.get()));
1059   ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(40, {0, 0}),
1060                                         MakeDataDescriptor(108, {0, 0}),
1061                                         context.get()));
1062   ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(40, {0, 1}),
1063                                         MakeDataDescriptor(108, {0, 1}),
1064                                         context.get()));
1065   ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(40, {0, 2}),
1066                                         MakeDataDescriptor(108, {0, 2}),
1067                                         context.get()));
1068   ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(40, {0, 3}),
1069                                         MakeDataDescriptor(108, {0, 3}),
1070                                         context.get()));
1071   ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(40, {0, 4}),
1072                                         MakeDataDescriptor(108, {0, 4}),
1073                                         context.get()));
1074   ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(40, {1, 0}),
1075                                         MakeDataDescriptor(108, {1, 0}),
1076                                         context.get()));
1077   ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(40, {1, 1}),
1078                                         MakeDataDescriptor(108, {1, 1}),
1079                                         context.get()));
1080   ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(40, {1, 2}),
1081                                         MakeDataDescriptor(108, {1, 2}),
1082                                         context.get()));
1083   ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(40, {1, 3}),
1084                                         MakeDataDescriptor(108, {1, 3}),
1085                                         context.get()));
1086   ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(40, {1, 0, 0}),
1087                                         MakeDataDescriptor(108, {1, 0, 0}),
1088                                         context.get()));
1089   ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(40, {1, 1, 0}),
1090                                         MakeDataDescriptor(108, {1, 1, 0}),
1091                                         context.get()));
1092   ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(40, {1, 2, 0}),
1093                                         MakeDataDescriptor(108, {1, 2, 0}),
1094                                         context.get()));
1095   ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(40, {1, 3, 0}),
1096                                         MakeDataDescriptor(108, {1, 3, 0}),
1097                                         context.get()));
1098   ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(40, {1, 0, 1}),
1099                                         MakeDataDescriptor(108, {1, 0, 1}),
1100                                         context.get()));
1101   ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(40, {1, 1, 1}),
1102                                         MakeDataDescriptor(108, {1, 1, 1}),
1103                                         context.get()));
1104   ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(40, {1, 2, 1}),
1105                                         MakeDataDescriptor(108, {1, 2, 1}),
1106                                         context.get()));
1107   ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(40, {1, 3, 1}),
1108                                         MakeDataDescriptor(108, {1, 3, 1}),
1109                                         context.get()));
1110 
1111   ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(40, {2, 0}),
1112                                         MakeDataDescriptor(108, {2, 0}),
1113                                         context.get()));
1114 
1115   ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(40, {2, 1}),
1116                                         MakeDataDescriptor(108, {2, 1}),
1117                                         context.get()));
1118 
1119   ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(40, {2, 1, 0}),
1120                                         MakeDataDescriptor(108, {2, 1, 0}),
1121                                         context.get()));
1122 
1123   ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(40, {2, 1, 1}),
1124                                         MakeDataDescriptor(108, {2, 1, 1}),
1125                                         context.get()));
1126 }
1127 
TEST(FactManagerTest,RecursiveAdditionOfFacts)1128 TEST(FactManagerTest, RecursiveAdditionOfFacts) {
1129   std::string shader = R"(
1130                OpCapability Shader
1131           %1 = OpExtInstImport "GLSL.std.450"
1132                OpMemoryModel Logical GLSL450
1133                OpEntryPoint Fragment %12 "main"
1134                OpExecutionMode %12 OriginUpperLeft
1135                OpSource ESSL 310
1136           %2 = OpTypeVoid
1137           %3 = OpTypeFunction %2
1138           %6 = OpTypeFloat 32
1139           %7 = OpTypeVector %6 4
1140           %8 = OpTypeMatrix %7 4
1141           %9 = OpConstant %6 0
1142          %10 = OpConstantComposite %7 %9 %9 %9 %9
1143          %11 = OpConstantComposite %8 %10 %10 %10 %10
1144          %12 = OpFunction %2 None %3
1145          %13 = OpLabel
1146                OpReturn
1147                OpFunctionEnd
1148   )";
1149 
1150   const auto env = SPV_ENV_UNIVERSAL_1_3;
1151   const auto consumer = nullptr;
1152   const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
1153   ASSERT_TRUE(IsValid(env, context.get()));
1154 
1155   FactManager fact_manager;
1156 
1157   fact_manager.AddFactDataSynonym(MakeDataDescriptor(10, {}),
1158                                   MakeDataDescriptor(11, {2}), context.get());
1159 
1160   ASSERT_TRUE(fact_manager.IsSynonymous(
1161       MakeDataDescriptor(10, {}), MakeDataDescriptor(11, {2}), context.get()));
1162   ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(10, {0}),
1163                                         MakeDataDescriptor(11, {2, 0}),
1164                                         context.get()));
1165   ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(10, {1}),
1166                                         MakeDataDescriptor(11, {2, 1}),
1167                                         context.get()));
1168   ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(10, {2}),
1169                                         MakeDataDescriptor(11, {2, 2}),
1170                                         context.get()));
1171   ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(10, {3}),
1172                                         MakeDataDescriptor(11, {2, 3}),
1173                                         context.get()));
1174 }
1175 
TEST(FactManagerTest,LogicalNotEquationFacts)1176 TEST(FactManagerTest, LogicalNotEquationFacts) {
1177   std::string shader = R"(
1178                OpCapability Shader
1179           %1 = OpExtInstImport "GLSL.std.450"
1180                OpMemoryModel Logical GLSL450
1181                OpEntryPoint Fragment %12 "main"
1182                OpExecutionMode %12 OriginUpperLeft
1183                OpSource ESSL 310
1184           %2 = OpTypeVoid
1185           %3 = OpTypeFunction %2
1186           %6 = OpTypeBool
1187           %7 = OpConstantTrue %6
1188          %12 = OpFunction %2 None %3
1189          %13 = OpLabel
1190          %14 = OpLogicalNot %6 %7
1191          %15 = OpCopyObject %6 %7
1192          %16 = OpCopyObject %6 %14
1193          %17 = OpLogicalNot %6 %16
1194                OpReturn
1195                OpFunctionEnd
1196   )";
1197 
1198   const auto env = SPV_ENV_UNIVERSAL_1_3;
1199   const auto consumer = nullptr;
1200   const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
1201   ASSERT_TRUE(IsValid(env, context.get()));
1202 
1203   FactManager fact_manager;
1204 
1205   fact_manager.AddFactDataSynonym(MakeDataDescriptor(15, {}),
1206                                   MakeDataDescriptor(7, {}), context.get());
1207   fact_manager.AddFactDataSynonym(MakeDataDescriptor(16, {}),
1208                                   MakeDataDescriptor(14, {}), context.get());
1209   fact_manager.AddFactIdEquation(14, SpvOpLogicalNot, {7}, context.get());
1210   fact_manager.AddFactIdEquation(17, SpvOpLogicalNot, {16}, context.get());
1211 
1212   ASSERT_TRUE(fact_manager.IsSynonymous(
1213       MakeDataDescriptor(15, {}), MakeDataDescriptor(7, {}), context.get()));
1214   ASSERT_TRUE(fact_manager.IsSynonymous(
1215       MakeDataDescriptor(17, {}), MakeDataDescriptor(7, {}), context.get()));
1216   ASSERT_TRUE(fact_manager.IsSynonymous(
1217       MakeDataDescriptor(15, {}), MakeDataDescriptor(17, {}), context.get()));
1218   ASSERT_TRUE(fact_manager.IsSynonymous(
1219       MakeDataDescriptor(16, {}), MakeDataDescriptor(14, {}), context.get()));
1220 }
1221 
TEST(FactManagerTest,SignedNegateEquationFacts)1222 TEST(FactManagerTest, SignedNegateEquationFacts) {
1223   std::string shader = R"(
1224                OpCapability Shader
1225           %1 = OpExtInstImport "GLSL.std.450"
1226                OpMemoryModel Logical GLSL450
1227                OpEntryPoint Fragment %12 "main"
1228                OpExecutionMode %12 OriginUpperLeft
1229                OpSource ESSL 310
1230           %2 = OpTypeVoid
1231           %3 = OpTypeFunction %2
1232           %6 = OpTypeInt 32 1
1233           %7 = OpConstant %6 24
1234          %12 = OpFunction %2 None %3
1235          %13 = OpLabel
1236          %14 = OpSNegate %6 %7
1237          %15 = OpSNegate %6 %14
1238                OpReturn
1239                OpFunctionEnd
1240   )";
1241 
1242   const auto env = SPV_ENV_UNIVERSAL_1_3;
1243   const auto consumer = nullptr;
1244   const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
1245   ASSERT_TRUE(IsValid(env, context.get()));
1246 
1247   FactManager fact_manager;
1248 
1249   fact_manager.AddFactIdEquation(14, SpvOpSNegate, {7}, context.get());
1250   fact_manager.AddFactIdEquation(15, SpvOpSNegate, {14}, context.get());
1251 
1252   ASSERT_TRUE(fact_manager.IsSynonymous(
1253       MakeDataDescriptor(7, {}), MakeDataDescriptor(15, {}), context.get()));
1254 }
1255 
TEST(FactManagerTest,AddSubNegateFacts1)1256 TEST(FactManagerTest, AddSubNegateFacts1) {
1257   std::string shader = R"(
1258                OpCapability Shader
1259           %1 = OpExtInstImport "GLSL.std.450"
1260                OpMemoryModel Logical GLSL450
1261                OpEntryPoint Fragment %12 "main"
1262                OpExecutionMode %12 OriginUpperLeft
1263                OpSource ESSL 310
1264           %2 = OpTypeVoid
1265           %3 = OpTypeFunction %2
1266           %6 = OpTypeInt 32 1
1267          %15 = OpConstant %6 24
1268          %16 = OpConstant %6 37
1269          %12 = OpFunction %2 None %3
1270          %13 = OpLabel
1271          %14 = OpIAdd %6 %15 %16
1272          %17 = OpCopyObject %6 %15
1273          %18 = OpCopyObject %6 %16
1274          %19 = OpISub %6 %14 %18 ; ==> synonymous(%19, %15)
1275          %20 = OpISub %6 %14 %17 ; ==> synonymous(%20, %16)
1276          %21 = OpCopyObject %6 %14
1277          %22 = OpISub %6 %16 %21
1278          %23 = OpCopyObject %6 %22
1279          %24 = OpSNegate %6 %23 ; ==> synonymous(%24, %15)
1280                OpReturn
1281                OpFunctionEnd
1282   )";
1283 
1284   const auto env = SPV_ENV_UNIVERSAL_1_3;
1285   const auto consumer = nullptr;
1286   const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
1287   ASSERT_TRUE(IsValid(env, context.get()));
1288 
1289   FactManager fact_manager;
1290 
1291   fact_manager.AddFactIdEquation(14, SpvOpIAdd, {15, 16}, context.get());
1292   fact_manager.AddFactDataSynonym(MakeDataDescriptor(17, {}),
1293                                   MakeDataDescriptor(15, {}), context.get());
1294   fact_manager.AddFactDataSynonym(MakeDataDescriptor(18, {}),
1295                                   MakeDataDescriptor(16, {}), context.get());
1296   fact_manager.AddFactIdEquation(19, SpvOpISub, {14, 18}, context.get());
1297   fact_manager.AddFactIdEquation(20, SpvOpISub, {14, 17}, context.get());
1298   fact_manager.AddFactDataSynonym(MakeDataDescriptor(21, {}),
1299                                   MakeDataDescriptor(14, {}), context.get());
1300   fact_manager.AddFactIdEquation(22, SpvOpISub, {16, 21}, context.get());
1301   fact_manager.AddFactDataSynonym(MakeDataDescriptor(23, {}),
1302                                   MakeDataDescriptor(22, {}), context.get());
1303   fact_manager.AddFactIdEquation(24, SpvOpSNegate, {23}, context.get());
1304 
1305   ASSERT_TRUE(fact_manager.IsSynonymous(
1306       MakeDataDescriptor(19, {}), MakeDataDescriptor(15, {}), context.get()));
1307   ASSERT_TRUE(fact_manager.IsSynonymous(
1308       MakeDataDescriptor(20, {}), MakeDataDescriptor(16, {}), context.get()));
1309   ASSERT_TRUE(fact_manager.IsSynonymous(
1310       MakeDataDescriptor(24, {}), MakeDataDescriptor(15, {}), context.get()));
1311 }
1312 
TEST(FactManagerTest,AddSubNegateFacts2)1313 TEST(FactManagerTest, AddSubNegateFacts2) {
1314   std::string shader = R"(
1315                OpCapability Shader
1316           %1 = OpExtInstImport "GLSL.std.450"
1317                OpMemoryModel Logical GLSL450
1318                OpEntryPoint Fragment %12 "main"
1319                OpExecutionMode %12 OriginUpperLeft
1320                OpSource ESSL 310
1321           %2 = OpTypeVoid
1322           %3 = OpTypeFunction %2
1323           %6 = OpTypeInt 32 1
1324          %15 = OpConstant %6 24
1325          %16 = OpConstant %6 37
1326          %12 = OpFunction %2 None %3
1327          %13 = OpLabel
1328          %14 = OpISub %6 %15 %16
1329          %17 = OpIAdd %6 %14 %16 ; ==> synonymous(%17, %15)
1330          %18 = OpIAdd %6 %16 %14 ; ==> synonymous(%17, %18, %15)
1331          %19 = OpISub %6 %14 %15
1332          %20 = OpSNegate %6 %19 ; ==> synonymous(%20, %16)
1333          %21 = OpISub %6 %14 %19 ; ==> synonymous(%21, %15)
1334          %22 = OpISub %6 %14 %18
1335          %23 = OpSNegate %6 %22 ; ==> synonymous(%23, %16)
1336                OpReturn
1337                OpFunctionEnd
1338   )";
1339 
1340   const auto env = SPV_ENV_UNIVERSAL_1_3;
1341   const auto consumer = nullptr;
1342   const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
1343   ASSERT_TRUE(IsValid(env, context.get()));
1344 
1345   FactManager fact_manager;
1346 
1347   fact_manager.AddFactIdEquation(14, SpvOpISub, {15, 16}, context.get());
1348   fact_manager.AddFactIdEquation(17, SpvOpIAdd, {14, 16}, context.get());
1349 
1350   ASSERT_TRUE(fact_manager.IsSynonymous(
1351       MakeDataDescriptor(17, {}), MakeDataDescriptor(15, {}), context.get()));
1352 
1353   fact_manager.AddFactIdEquation(18, SpvOpIAdd, {16, 14}, context.get());
1354 
1355   ASSERT_TRUE(fact_manager.IsSynonymous(
1356       MakeDataDescriptor(18, {}), MakeDataDescriptor(15, {}), context.get()));
1357   ASSERT_TRUE(fact_manager.IsSynonymous(
1358       MakeDataDescriptor(17, {}), MakeDataDescriptor(18, {}), context.get()));
1359 
1360   fact_manager.AddFactIdEquation(19, SpvOpISub, {14, 15}, context.get());
1361   fact_manager.AddFactIdEquation(20, SpvOpSNegate, {19}, context.get());
1362 
1363   ASSERT_TRUE(fact_manager.IsSynonymous(
1364       MakeDataDescriptor(20, {}), MakeDataDescriptor(16, {}), context.get()));
1365 
1366   fact_manager.AddFactIdEquation(21, SpvOpISub, {14, 19}, context.get());
1367   ASSERT_TRUE(fact_manager.IsSynonymous(
1368       MakeDataDescriptor(21, {}), MakeDataDescriptor(15, {}), context.get()));
1369 
1370   fact_manager.AddFactIdEquation(22, SpvOpISub, {14, 18}, context.get());
1371   fact_manager.AddFactIdEquation(23, SpvOpSNegate, {22}, context.get());
1372   ASSERT_TRUE(fact_manager.IsSynonymous(
1373       MakeDataDescriptor(23, {}), MakeDataDescriptor(16, {}), context.get()));
1374 }
1375 
TEST(FactManagerTest,EquationAndEquivalenceFacts)1376 TEST(FactManagerTest, EquationAndEquivalenceFacts) {
1377   std::string shader = R"(
1378                OpCapability Shader
1379           %1 = OpExtInstImport "GLSL.std.450"
1380                OpMemoryModel Logical GLSL450
1381                OpEntryPoint Fragment %12 "main"
1382                OpExecutionMode %12 OriginUpperLeft
1383                OpSource ESSL 310
1384           %2 = OpTypeVoid
1385           %3 = OpTypeFunction %2
1386           %6 = OpTypeInt 32 1
1387          %15 = OpConstant %6 24
1388          %16 = OpConstant %6 37
1389          %12 = OpFunction %2 None %3
1390          %13 = OpLabel
1391          %14 = OpISub %6 %15 %16
1392         %114 = OpCopyObject %6 %14
1393          %17 = OpIAdd %6 %114 %16 ; ==> synonymous(%17, %15)
1394          %18 = OpIAdd %6 %16 %114 ; ==> synonymous(%17, %18, %15)
1395          %19 = OpISub %6 %114 %15
1396         %119 = OpCopyObject %6 %19
1397          %20 = OpSNegate %6 %119 ; ==> synonymous(%20, %16)
1398          %21 = OpISub %6 %14 %19 ; ==> synonymous(%21, %15)
1399          %22 = OpISub %6 %14 %18
1400         %220 = OpCopyObject %6 %22
1401          %23 = OpSNegate %6 %220 ; ==> synonymous(%23, %16)
1402                OpReturn
1403                OpFunctionEnd
1404   )";
1405 
1406   const auto env = SPV_ENV_UNIVERSAL_1_3;
1407   const auto consumer = nullptr;
1408   const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
1409   ASSERT_TRUE(IsValid(env, context.get()));
1410 
1411   FactManager fact_manager;
1412 
1413   fact_manager.AddFactIdEquation(14, SpvOpISub, {15, 16}, context.get());
1414   fact_manager.AddFactDataSynonym(MakeDataDescriptor(114, {}),
1415                                   MakeDataDescriptor(14, {}), context.get());
1416   fact_manager.AddFactIdEquation(17, SpvOpIAdd, {114, 16}, context.get());
1417 
1418   ASSERT_TRUE(fact_manager.IsSynonymous(
1419       MakeDataDescriptor(17, {}), MakeDataDescriptor(15, {}), context.get()));
1420 
1421   fact_manager.AddFactIdEquation(18, SpvOpIAdd, {16, 114}, context.get());
1422 
1423   ASSERT_TRUE(fact_manager.IsSynonymous(
1424       MakeDataDescriptor(18, {}), MakeDataDescriptor(15, {}), context.get()));
1425   ASSERT_TRUE(fact_manager.IsSynonymous(
1426       MakeDataDescriptor(17, {}), MakeDataDescriptor(18, {}), context.get()));
1427 
1428   fact_manager.AddFactIdEquation(19, SpvOpISub, {14, 15}, context.get());
1429   fact_manager.AddFactDataSynonym(MakeDataDescriptor(119, {}),
1430                                   MakeDataDescriptor(19, {}), context.get());
1431   fact_manager.AddFactIdEquation(20, SpvOpSNegate, {119}, context.get());
1432 
1433   ASSERT_TRUE(fact_manager.IsSynonymous(
1434       MakeDataDescriptor(20, {}), MakeDataDescriptor(16, {}), context.get()));
1435 
1436   fact_manager.AddFactIdEquation(21, SpvOpISub, {14, 19}, context.get());
1437   ASSERT_TRUE(fact_manager.IsSynonymous(
1438       MakeDataDescriptor(21, {}), MakeDataDescriptor(15, {}), context.get()));
1439 
1440   fact_manager.AddFactIdEquation(22, SpvOpISub, {14, 18}, context.get());
1441   fact_manager.AddFactDataSynonym(MakeDataDescriptor(22, {}),
1442                                   MakeDataDescriptor(220, {}), context.get());
1443   fact_manager.AddFactIdEquation(23, SpvOpSNegate, {220}, context.get());
1444   ASSERT_TRUE(fact_manager.IsSynonymous(
1445       MakeDataDescriptor(23, {}), MakeDataDescriptor(16, {}), context.get()));
1446 }
1447 
1448 }  // namespace
1449 }  // namespace fuzz
1450 }  // namespace spvtools
1451