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