• 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,RecursiveAdditionOfFacts)741 TEST(FactManagerTest, RecursiveAdditionOfFacts) {
742   std::string shader = R"(
743                OpCapability Shader
744           %1 = OpExtInstImport "GLSL.std.450"
745                OpMemoryModel Logical GLSL450
746                OpEntryPoint Fragment %12 "main"
747                OpExecutionMode %12 OriginUpperLeft
748                OpSource ESSL 310
749           %2 = OpTypeVoid
750           %3 = OpTypeFunction %2
751           %6 = OpTypeFloat 32
752           %7 = OpTypeVector %6 4
753           %8 = OpTypeMatrix %7 4
754           %9 = OpConstant %6 0
755          %10 = OpConstantComposite %7 %9 %9 %9 %9
756          %11 = OpConstantComposite %8 %10 %10 %10 %10
757          %12 = OpFunction %2 None %3
758          %13 = OpLabel
759                OpReturn
760                OpFunctionEnd
761   )";
762 
763   const auto env = SPV_ENV_UNIVERSAL_1_3;
764   const auto consumer = nullptr;
765   const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
766   ASSERT_TRUE(IsValid(env, context.get()));
767 
768   FactManager fact_manager;
769 
770   fact_manager.AddFactDataSynonym(MakeDataDescriptor(10, {}),
771                                   MakeDataDescriptor(11, {2}), context.get());
772 
773   ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(10, {}),
774                                         MakeDataDescriptor(11, {2})));
775   ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(10, {0}),
776                                         MakeDataDescriptor(11, {2, 0})));
777   ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(10, {1}),
778                                         MakeDataDescriptor(11, {2, 1})));
779   ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(10, {2}),
780                                         MakeDataDescriptor(11, {2, 2})));
781   ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(10, {3}),
782                                         MakeDataDescriptor(11, {2, 3})));
783 }
784 
TEST(FactManagerTest,LogicalNotEquationFacts)785 TEST(FactManagerTest, LogicalNotEquationFacts) {
786   std::string shader = R"(
787                OpCapability Shader
788           %1 = OpExtInstImport "GLSL.std.450"
789                OpMemoryModel Logical GLSL450
790                OpEntryPoint Fragment %12 "main"
791                OpExecutionMode %12 OriginUpperLeft
792                OpSource ESSL 310
793           %2 = OpTypeVoid
794           %3 = OpTypeFunction %2
795           %6 = OpTypeBool
796           %7 = OpConstantTrue %6
797          %12 = OpFunction %2 None %3
798          %13 = OpLabel
799          %14 = OpLogicalNot %6 %7
800          %15 = OpCopyObject %6 %7
801          %16 = OpCopyObject %6 %14
802          %17 = OpLogicalNot %6 %16
803                OpReturn
804                OpFunctionEnd
805   )";
806 
807   const auto env = SPV_ENV_UNIVERSAL_1_3;
808   const auto consumer = nullptr;
809   const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
810   ASSERT_TRUE(IsValid(env, context.get()));
811 
812   FactManager fact_manager;
813 
814   fact_manager.AddFactDataSynonym(MakeDataDescriptor(15, {}),
815                                   MakeDataDescriptor(7, {}), context.get());
816   fact_manager.AddFactDataSynonym(MakeDataDescriptor(16, {}),
817                                   MakeDataDescriptor(14, {}), context.get());
818   fact_manager.AddFactIdEquation(14, SpvOpLogicalNot, {7}, context.get());
819   fact_manager.AddFactIdEquation(17, SpvOpLogicalNot, {16}, context.get());
820 
821   ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(15, {}),
822                                         MakeDataDescriptor(7, {})));
823   ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(17, {}),
824                                         MakeDataDescriptor(7, {})));
825   ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(15, {}),
826                                         MakeDataDescriptor(17, {})));
827   ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(16, {}),
828                                         MakeDataDescriptor(14, {})));
829 }
830 
TEST(FactManagerTest,SignedNegateEquationFacts)831 TEST(FactManagerTest, SignedNegateEquationFacts) {
832   std::string shader = R"(
833                OpCapability Shader
834           %1 = OpExtInstImport "GLSL.std.450"
835                OpMemoryModel Logical GLSL450
836                OpEntryPoint Fragment %12 "main"
837                OpExecutionMode %12 OriginUpperLeft
838                OpSource ESSL 310
839           %2 = OpTypeVoid
840           %3 = OpTypeFunction %2
841           %6 = OpTypeInt 32 1
842           %7 = OpConstant %6 24
843          %12 = OpFunction %2 None %3
844          %13 = OpLabel
845          %14 = OpSNegate %6 %7
846          %15 = OpSNegate %6 %14
847                OpReturn
848                OpFunctionEnd
849   )";
850 
851   const auto env = SPV_ENV_UNIVERSAL_1_3;
852   const auto consumer = nullptr;
853   const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
854   ASSERT_TRUE(IsValid(env, context.get()));
855 
856   FactManager fact_manager;
857 
858   fact_manager.AddFactIdEquation(14, SpvOpSNegate, {7}, context.get());
859   fact_manager.AddFactIdEquation(15, SpvOpSNegate, {14}, context.get());
860 
861   ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(7, {}),
862                                         MakeDataDescriptor(15, {})));
863 }
864 
TEST(FactManagerTest,AddSubNegateFacts1)865 TEST(FactManagerTest, AddSubNegateFacts1) {
866   std::string shader = R"(
867                OpCapability Shader
868           %1 = OpExtInstImport "GLSL.std.450"
869                OpMemoryModel Logical GLSL450
870                OpEntryPoint Fragment %12 "main"
871                OpExecutionMode %12 OriginUpperLeft
872                OpSource ESSL 310
873           %2 = OpTypeVoid
874           %3 = OpTypeFunction %2
875           %6 = OpTypeInt 32 1
876          %15 = OpConstant %6 24
877          %16 = OpConstant %6 37
878          %12 = OpFunction %2 None %3
879          %13 = OpLabel
880          %14 = OpIAdd %6 %15 %16
881          %17 = OpCopyObject %6 %15
882          %18 = OpCopyObject %6 %16
883          %19 = OpISub %6 %14 %18 ; ==> synonymous(%19, %15)
884          %20 = OpISub %6 %14 %17 ; ==> synonymous(%20, %16)
885          %21 = OpCopyObject %6 %14
886          %22 = OpISub %6 %16 %21
887          %23 = OpCopyObject %6 %22
888          %24 = OpSNegate %6 %23 ; ==> synonymous(%24, %15)
889                OpReturn
890                OpFunctionEnd
891   )";
892 
893   const auto env = SPV_ENV_UNIVERSAL_1_3;
894   const auto consumer = nullptr;
895   const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
896   ASSERT_TRUE(IsValid(env, context.get()));
897 
898   FactManager fact_manager;
899 
900   fact_manager.AddFactIdEquation(14, SpvOpIAdd, {15, 16}, context.get());
901   fact_manager.AddFactDataSynonym(MakeDataDescriptor(17, {}),
902                                   MakeDataDescriptor(15, {}), context.get());
903   fact_manager.AddFactDataSynonym(MakeDataDescriptor(18, {}),
904                                   MakeDataDescriptor(16, {}), context.get());
905   fact_manager.AddFactIdEquation(19, SpvOpISub, {14, 18}, context.get());
906   fact_manager.AddFactIdEquation(20, SpvOpISub, {14, 17}, context.get());
907   fact_manager.AddFactDataSynonym(MakeDataDescriptor(21, {}),
908                                   MakeDataDescriptor(14, {}), context.get());
909   fact_manager.AddFactIdEquation(22, SpvOpISub, {16, 21}, context.get());
910   fact_manager.AddFactDataSynonym(MakeDataDescriptor(23, {}),
911                                   MakeDataDescriptor(22, {}), context.get());
912   fact_manager.AddFactIdEquation(24, SpvOpSNegate, {23}, context.get());
913 
914   ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(19, {}),
915                                         MakeDataDescriptor(15, {})));
916   ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(20, {}),
917                                         MakeDataDescriptor(16, {})));
918   ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(24, {}),
919                                         MakeDataDescriptor(15, {})));
920 }
921 
TEST(FactManagerTest,AddSubNegateFacts2)922 TEST(FactManagerTest, AddSubNegateFacts2) {
923   std::string shader = R"(
924                OpCapability Shader
925           %1 = OpExtInstImport "GLSL.std.450"
926                OpMemoryModel Logical GLSL450
927                OpEntryPoint Fragment %12 "main"
928                OpExecutionMode %12 OriginUpperLeft
929                OpSource ESSL 310
930           %2 = OpTypeVoid
931           %3 = OpTypeFunction %2
932           %6 = OpTypeInt 32 1
933          %15 = OpConstant %6 24
934          %16 = OpConstant %6 37
935          %12 = OpFunction %2 None %3
936          %13 = OpLabel
937          %14 = OpISub %6 %15 %16
938          %17 = OpIAdd %6 %14 %16 ; ==> synonymous(%17, %15)
939          %18 = OpIAdd %6 %16 %14 ; ==> synonymous(%17, %18, %15)
940          %19 = OpISub %6 %14 %15
941          %20 = OpSNegate %6 %19 ; ==> synonymous(%20, %16)
942          %21 = OpISub %6 %14 %19 ; ==> synonymous(%21, %15)
943          %22 = OpISub %6 %14 %18
944          %23 = OpSNegate %6 %22 ; ==> synonymous(%23, %16)
945                OpReturn
946                OpFunctionEnd
947   )";
948 
949   const auto env = SPV_ENV_UNIVERSAL_1_3;
950   const auto consumer = nullptr;
951   const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
952   ASSERT_TRUE(IsValid(env, context.get()));
953 
954   FactManager fact_manager;
955 
956   fact_manager.AddFactIdEquation(14, SpvOpISub, {15, 16}, context.get());
957   fact_manager.AddFactIdEquation(17, SpvOpIAdd, {14, 16}, context.get());
958 
959   ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(17, {}),
960                                         MakeDataDescriptor(15, {})));
961 
962   fact_manager.AddFactIdEquation(18, SpvOpIAdd, {16, 14}, context.get());
963 
964   ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(18, {}),
965                                         MakeDataDescriptor(15, {})));
966   ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(17, {}),
967                                         MakeDataDescriptor(18, {})));
968 
969   fact_manager.AddFactIdEquation(19, SpvOpISub, {14, 15}, context.get());
970   fact_manager.AddFactIdEquation(20, SpvOpSNegate, {19}, context.get());
971 
972   ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(20, {}),
973                                         MakeDataDescriptor(16, {})));
974 
975   fact_manager.AddFactIdEquation(21, SpvOpISub, {14, 19}, context.get());
976   ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(21, {}),
977                                         MakeDataDescriptor(15, {})));
978 
979   fact_manager.AddFactIdEquation(22, SpvOpISub, {14, 18}, context.get());
980   fact_manager.AddFactIdEquation(23, SpvOpSNegate, {22}, context.get());
981   ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(23, {}),
982                                         MakeDataDescriptor(16, {})));
983 }
984 
TEST(FactManagerTest,EquationAndEquivalenceFacts)985 TEST(FactManagerTest, EquationAndEquivalenceFacts) {
986   std::string shader = R"(
987                OpCapability Shader
988           %1 = OpExtInstImport "GLSL.std.450"
989                OpMemoryModel Logical GLSL450
990                OpEntryPoint Fragment %12 "main"
991                OpExecutionMode %12 OriginUpperLeft
992                OpSource ESSL 310
993           %2 = OpTypeVoid
994           %3 = OpTypeFunction %2
995           %6 = OpTypeInt 32 1
996          %15 = OpConstant %6 24
997          %16 = OpConstant %6 37
998          %12 = OpFunction %2 None %3
999          %13 = OpLabel
1000          %14 = OpISub %6 %15 %16
1001         %114 = OpCopyObject %6 %14
1002          %17 = OpIAdd %6 %114 %16 ; ==> synonymous(%17, %15)
1003          %18 = OpIAdd %6 %16 %114 ; ==> synonymous(%17, %18, %15)
1004          %19 = OpISub %6 %114 %15
1005         %119 = OpCopyObject %6 %19
1006          %20 = OpSNegate %6 %119 ; ==> synonymous(%20, %16)
1007          %21 = OpISub %6 %14 %19 ; ==> synonymous(%21, %15)
1008          %22 = OpISub %6 %14 %18
1009         %220 = OpCopyObject %6 %22
1010          %23 = OpSNegate %6 %220 ; ==> synonymous(%23, %16)
1011                OpReturn
1012                OpFunctionEnd
1013   )";
1014 
1015   const auto env = SPV_ENV_UNIVERSAL_1_3;
1016   const auto consumer = nullptr;
1017   const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
1018   ASSERT_TRUE(IsValid(env, context.get()));
1019 
1020   FactManager fact_manager;
1021 
1022   fact_manager.AddFactIdEquation(14, SpvOpISub, {15, 16}, context.get());
1023   fact_manager.AddFactDataSynonym(MakeDataDescriptor(114, {}),
1024                                   MakeDataDescriptor(14, {}), context.get());
1025   fact_manager.AddFactIdEquation(17, SpvOpIAdd, {114, 16}, context.get());
1026 
1027   ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(17, {}),
1028                                         MakeDataDescriptor(15, {})));
1029 
1030   fact_manager.AddFactIdEquation(18, SpvOpIAdd, {16, 114}, context.get());
1031 
1032   ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(18, {}),
1033                                         MakeDataDescriptor(15, {})));
1034   ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(17, {}),
1035                                         MakeDataDescriptor(18, {})));
1036 
1037   fact_manager.AddFactIdEquation(19, SpvOpISub, {14, 15}, context.get());
1038   fact_manager.AddFactDataSynonym(MakeDataDescriptor(119, {}),
1039                                   MakeDataDescriptor(19, {}), context.get());
1040   fact_manager.AddFactIdEquation(20, SpvOpSNegate, {119}, context.get());
1041 
1042   ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(20, {}),
1043                                         MakeDataDescriptor(16, {})));
1044 
1045   fact_manager.AddFactIdEquation(21, SpvOpISub, {14, 19}, context.get());
1046   ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(21, {}),
1047                                         MakeDataDescriptor(15, {})));
1048 
1049   fact_manager.AddFactIdEquation(22, SpvOpISub, {14, 18}, context.get());
1050   fact_manager.AddFactDataSynonym(MakeDataDescriptor(22, {}),
1051                                   MakeDataDescriptor(220, {}), context.get());
1052   fact_manager.AddFactIdEquation(23, SpvOpSNegate, {220}, context.get());
1053   ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(23, {}),
1054                                         MakeDataDescriptor(16, {})));
1055 }
1056 
1057 }  // namespace
1058 }  // namespace fuzz
1059 }  // namespace spvtools
1060