spirv-fuzz: Refactor fact manager tests (#3879)
Fixes #3698.
diff --git a/test/fuzz/CMakeLists.txt b/test/fuzz/CMakeLists.txt
index 89ffa59..7d08506 100644
--- a/test/fuzz/CMakeLists.txt
+++ b/test/fuzz/CMakeLists.txt
@@ -21,7 +21,10 @@
comparator_deep_blocks_first_test.cpp
data_synonym_transformation_test.cpp
equivalence_relation_test.cpp
- fact_manager_test.cpp
+ fact_manager/constant_uniform_facts_test.cpp
+ fact_manager/data_synonym_and_id_equation_facts_test.cpp
+ fact_manager/dead_block_facts_test.cpp
+ fact_manager/irrelevant_value_facts_test.cpp
fuzz_test_util.cpp
fuzzer_pass_add_opphi_synonyms_test.cpp
fuzzer_pass_construct_composites_test.cpp
diff --git a/test/fuzz/fact_manager/constant_uniform_facts_test.cpp b/test/fuzz/fact_manager/constant_uniform_facts_test.cpp
new file mode 100644
index 0000000..a6a49be
--- /dev/null
+++ b/test/fuzz/fact_manager/constant_uniform_facts_test.cpp
@@ -0,0 +1,784 @@
+// Copyright (c) 2019 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include <limits>
+
+#include "source/fuzz/fact_manager/fact_manager.h"
+#include "source/fuzz/uniform_buffer_element_descriptor.h"
+#include "test/fuzz/fuzz_test_util.h"
+
+namespace spvtools {
+namespace fuzz {
+namespace {
+
+using opt::analysis::BoolConstant;
+using opt::analysis::FloatConstant;
+using opt::analysis::IntConstant;
+using opt::analysis::ScalarConstant;
+
+using opt::analysis::Bool;
+using opt::analysis::Float;
+using opt::analysis::Integer;
+using opt::analysis::Type;
+
+bool AddFactHelper(
+ FactManager* fact_manager, const std::vector<uint32_t>& words,
+ const protobufs::UniformBufferElementDescriptor& descriptor) {
+ protobufs::FactConstantUniform constant_uniform_fact;
+ for (auto word : words) {
+ constant_uniform_fact.add_constant_word(word);
+ }
+ *constant_uniform_fact.mutable_uniform_buffer_element_descriptor() =
+ descriptor;
+ protobufs::Fact fact;
+ *fact.mutable_constant_uniform_fact() = constant_uniform_fact;
+ return fact_manager->MaybeAddFact(fact);
+}
+
+TEST(ConstantUniformFactsTest, ConstantsAvailableViaUniforms) {
+ std::string shader = R"(
+ OpCapability Shader
+ OpCapability Int64
+ OpCapability Float64
+ %1 = OpExtInstImport "GLSL.std.450"
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %4 "main"
+ OpExecutionMode %4 OriginUpperLeft
+ OpSource GLSL 450
+ OpName %4 "main"
+ OpDecorate %100 DescriptorSet 0
+ OpDecorate %100 Binding 0
+ OpDecorate %200 DescriptorSet 0
+ OpDecorate %200 Binding 1
+ OpDecorate %300 DescriptorSet 0
+ OpDecorate %300 Binding 2
+ OpDecorate %400 DescriptorSet 0
+ OpDecorate %400 Binding 3
+ OpDecorate %500 DescriptorSet 0
+ OpDecorate %500 Binding 4
+ OpDecorate %600 DescriptorSet 0
+ OpDecorate %600 Binding 5
+ OpDecorate %700 DescriptorSet 0
+ OpDecorate %700 Binding 6
+ OpDecorate %800 DescriptorSet 1
+ OpDecorate %800 Binding 0
+ OpDecorate %900 DescriptorSet 1
+ OpDecorate %900 Binding 1
+ OpDecorate %1000 DescriptorSet 1
+ OpDecorate %1000 Binding 2
+ OpDecorate %1100 DescriptorSet 1
+ OpDecorate %1100 Binding 3
+ OpDecorate %1200 DescriptorSet 1
+ OpDecorate %1200 Binding 4
+ OpDecorate %1300 DescriptorSet 1
+ OpDecorate %1300 Binding 5
+ OpDecorate %1400 DescriptorSet 1
+ OpDecorate %1400 Binding 6
+ OpDecorate %1500 DescriptorSet 2
+ OpDecorate %1500 Binding 0
+ OpDecorate %1600 DescriptorSet 2
+ OpDecorate %1600 Binding 1
+ OpDecorate %1700 DescriptorSet 2
+ OpDecorate %1700 Binding 2
+ OpDecorate %1800 DescriptorSet 2
+ OpDecorate %1800 Binding 3
+ OpDecorate %1900 DescriptorSet 2
+ OpDecorate %1900 Binding 4
+ %2 = OpTypeVoid
+ %3 = OpTypeFunction %2
+ %10 = OpTypeInt 32 0
+ %11 = OpTypeInt 32 1
+ %12 = OpTypeInt 64 0
+ %13 = OpTypeInt 64 1
+ %15 = OpTypeFloat 32
+ %16 = OpTypeFloat 64
+ %17 = OpConstant %11 5
+ %18 = OpConstant %11 20
+ %19 = OpTypeVector %10 4
+ %20 = OpConstant %11 6
+ %21 = OpTypeVector %12 4
+ %22 = OpConstant %11 10
+ %23 = OpTypeVector %11 4
+
+ %102 = OpTypeStruct %10 %10 %23
+ %101 = OpTypePointer Uniform %102
+ %100 = OpVariable %101 Uniform
+
+ %203 = OpTypeArray %23 %17
+ %202 = OpTypeArray %203 %18
+ %201 = OpTypePointer Uniform %202
+ %200 = OpVariable %201 Uniform
+
+ %305 = OpTypeStruct %16 %16 %16 %11 %16
+ %304 = OpTypeStruct %16 %16 %305
+ %303 = OpTypeStruct %304
+ %302 = OpTypeStruct %10 %303
+ %301 = OpTypePointer Uniform %302
+ %300 = OpVariable %301 Uniform
+
+ %400 = OpVariable %101 Uniform
+
+ %500 = OpVariable %201 Uniform
+
+ %604 = OpTypeArray %13 %20
+ %603 = OpTypeArray %604 %20
+ %602 = OpTypeArray %603 %20
+ %601 = OpTypePointer Uniform %602
+ %600 = OpVariable %601 Uniform
+
+ %703 = OpTypeArray %13 %20
+ %702 = OpTypeArray %703 %20
+ %701 = OpTypePointer Uniform %702
+ %700 = OpVariable %701 Uniform
+
+ %802 = OpTypeStruct %702 %602 %19 %202 %302
+ %801 = OpTypePointer Uniform %802
+ %800 = OpVariable %801 Uniform
+
+ %902 = OpTypeStruct %702 %802 %19 %202 %302
+ %901 = OpTypePointer Uniform %902
+ %900 = OpVariable %901 Uniform
+
+ %1003 = OpTypeStruct %802
+ %1002 = OpTypeArray %1003 %20
+ %1001 = OpTypePointer Uniform %1002
+ %1000 = OpVariable %1001 Uniform
+
+ %1101 = OpTypePointer Uniform %21
+ %1100 = OpVariable %1101 Uniform
+
+ %1202 = OpTypeArray %21 %20
+ %1201 = OpTypePointer Uniform %1202
+ %1200 = OpVariable %1201 Uniform
+
+ %1302 = OpTypeArray %21 %20
+ %1301 = OpTypePointer Uniform %1302
+ %1300 = OpVariable %1301 Uniform
+
+ %1402 = OpTypeArray %15 %22
+ %1401 = OpTypePointer Uniform %1402
+ %1400 = OpVariable %1401 Uniform
+
+ %1501 = OpTypePointer Uniform %1402
+ %1500 = OpVariable %1501 Uniform
+
+ %1602 = OpTypeArray %1402 %22
+ %1601 = OpTypePointer Uniform %1602
+ %1600 = OpVariable %1601 Uniform
+
+ %1704 = OpTypeStruct %16 %16 %16
+ %1703 = OpTypeArray %1704 %22
+ %1702 = OpTypeArray %1703 %22
+ %1701 = OpTypePointer Uniform %1702
+ %1700 = OpVariable %1701 Uniform
+
+ %1800 = OpVariable %1701 Uniform
+
+ %1906 = OpTypeStruct %16
+ %1905 = OpTypeStruct %1906
+ %1904 = OpTypeStruct %1905
+ %1903 = OpTypeStruct %1904
+ %1902 = OpTypeStruct %1903
+ %1901 = OpTypePointer Uniform %1902
+ %1900 = OpVariable %1901 Uniform
+
+ %4 = OpFunction %2 None %3
+ %5 = OpLabel
+ OpReturn
+ OpFunctionEnd
+ )";
+
+ const auto env = SPV_ENV_UNIVERSAL_1_3;
+ const auto consumer = nullptr;
+ const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
+ ASSERT_TRUE(IsValid(env, context.get()));
+
+ uint32_t buffer_int32_min[1];
+ uint32_t buffer_int64_1[2];
+ uint32_t buffer_int64_max[2];
+ uint32_t buffer_uint64_1[2];
+ uint32_t buffer_uint64_max[2];
+ uint32_t buffer_float_10[1];
+ uint32_t buffer_double_10[2];
+ uint32_t buffer_double_20[2];
+
+ {
+ int32_t temp = std::numeric_limits<int32_t>::min();
+ std::memcpy(&buffer_int32_min, &temp, sizeof(temp));
+ }
+
+ {
+ int64_t temp = 1;
+ std::memcpy(&buffer_int64_1, &temp, sizeof(temp));
+ }
+
+ {
+ int64_t temp = std::numeric_limits<int64_t>::max();
+ std::memcpy(&buffer_int64_max, &temp, sizeof(temp));
+ }
+
+ {
+ uint64_t temp = 1;
+ std::memcpy(&buffer_uint64_1, &temp, sizeof(temp));
+ }
+
+ {
+ uint64_t temp = std::numeric_limits<uint64_t>::max();
+ std::memcpy(&buffer_uint64_max, &temp, sizeof(temp));
+ }
+
+ {
+ float temp = 10.0f;
+ std::memcpy(&buffer_float_10, &temp, sizeof(float));
+ }
+
+ {
+ double temp = 10.0;
+ std::memcpy(&buffer_double_10, &temp, sizeof(temp));
+ }
+
+ {
+ double temp = 20.0;
+ std::memcpy(&buffer_double_20, &temp, sizeof(temp));
+ }
+
+ FactManager fact_manager(context.get());
+
+ uint32_t type_int32_id = 11;
+ uint32_t type_int64_id = 13;
+ uint32_t type_uint32_id = 10;
+ uint32_t type_uint64_id = 12;
+ uint32_t type_float_id = 15;
+ uint32_t type_double_id = 16;
+
+ // Initially there should be no facts about uniforms.
+ ASSERT_TRUE(
+ fact_manager.GetConstantsAvailableFromUniformsForType(type_uint32_id)
+ .empty());
+
+ // In the comments that follow we write v[...][...] to refer to uniform
+ // variable v indexed with some given indices, when in practice v is
+ // identified via a (descriptor set, binding) pair.
+
+ // 100[2][3] == int(1)
+ ASSERT_TRUE(AddFactHelper(&fact_manager, {1},
+ MakeUniformBufferElementDescriptor(0, 0, {2, 3})));
+
+ // 200[1][2][3] == int(1)
+ ASSERT_TRUE(AddFactHelper(
+ &fact_manager, {1}, MakeUniformBufferElementDescriptor(0, 1, {1, 2, 3})));
+
+ // 300[1][0][2][3] == int(1)
+ ASSERT_TRUE(
+ AddFactHelper(&fact_manager, {1},
+ MakeUniformBufferElementDescriptor(0, 2, {1, 0, 2, 3})));
+
+ // 400[2][3] = int32_min
+ ASSERT_TRUE(AddFactHelper(&fact_manager, {buffer_int32_min[0]},
+ MakeUniformBufferElementDescriptor(0, 3, {2, 3})));
+
+ // 500[1][2][3] = int32_min
+ ASSERT_TRUE(
+ AddFactHelper(&fact_manager, {buffer_int32_min[0]},
+ MakeUniformBufferElementDescriptor(0, 4, {1, 2, 3})));
+
+ // 600[1][2][3] = int64_max
+ ASSERT_TRUE(
+ AddFactHelper(&fact_manager, {buffer_int64_max[0], buffer_int64_max[1]},
+ MakeUniformBufferElementDescriptor(0, 5, {1, 2, 3})));
+
+ // 700[1][1] = int64_max
+ ASSERT_TRUE(AddFactHelper(&fact_manager,
+ {buffer_int64_max[0], buffer_int64_max[1]},
+ MakeUniformBufferElementDescriptor(0, 6, {1, 1})));
+
+ // 800[2][3] = uint(1)
+ ASSERT_TRUE(AddFactHelper(&fact_manager, {1},
+ MakeUniformBufferElementDescriptor(1, 0, {2, 3})));
+
+ // 900[1][2][3] = uint(1)
+ ASSERT_TRUE(AddFactHelper(
+ &fact_manager, {1}, MakeUniformBufferElementDescriptor(1, 1, {1, 2, 3})));
+
+ // 1000[1][0][2][3] = uint(1)
+ ASSERT_TRUE(
+ AddFactHelper(&fact_manager, {1},
+ MakeUniformBufferElementDescriptor(1, 2, {1, 0, 2, 3})));
+
+ // 1100[0] = uint64(1)
+ ASSERT_TRUE(AddFactHelper(&fact_manager,
+ {buffer_uint64_1[0], buffer_uint64_1[1]},
+ MakeUniformBufferElementDescriptor(1, 3, {0})));
+
+ // 1200[0][0] = uint64_max
+ ASSERT_TRUE(AddFactHelper(&fact_manager,
+ {buffer_uint64_max[0], buffer_uint64_max[1]},
+ MakeUniformBufferElementDescriptor(1, 4, {0, 0})));
+
+ // 1300[1][0] = uint64_max
+ ASSERT_TRUE(AddFactHelper(&fact_manager,
+ {buffer_uint64_max[0], buffer_uint64_max[1]},
+ MakeUniformBufferElementDescriptor(1, 5, {1, 0})));
+
+ // 1400[6] = float(10.0)
+ ASSERT_TRUE(AddFactHelper(&fact_manager, {buffer_float_10[0]},
+ MakeUniformBufferElementDescriptor(1, 6, {6})));
+
+ // 1500[7] = float(10.0)
+ ASSERT_TRUE(AddFactHelper(&fact_manager, {buffer_float_10[0]},
+ MakeUniformBufferElementDescriptor(2, 0, {7})));
+
+ // 1600[9][9] = float(10.0)
+ ASSERT_TRUE(AddFactHelper(&fact_manager, {buffer_float_10[0]},
+ MakeUniformBufferElementDescriptor(2, 1, {9, 9})));
+
+ // 1700[9][9][1] = double(10.0)
+ ASSERT_TRUE(
+ AddFactHelper(&fact_manager, {buffer_double_10[0], buffer_double_10[1]},
+ MakeUniformBufferElementDescriptor(2, 2, {9, 9, 1})));
+
+ // 1800[9][9][2] = double(10.0)
+ ASSERT_TRUE(
+ AddFactHelper(&fact_manager, {buffer_double_10[0], buffer_double_10[1]},
+ MakeUniformBufferElementDescriptor(2, 3, {9, 9, 2})));
+
+ // 1900[0][0][0][0][0] = double(20.0)
+ ASSERT_TRUE(
+ AddFactHelper(&fact_manager, {buffer_double_20[0], buffer_double_20[1]},
+ MakeUniformBufferElementDescriptor(2, 4, {0, 0, 0, 0, 0})));
+
+ opt::Instruction::OperandList operands = {
+ {SPV_OPERAND_TYPE_LITERAL_INTEGER, {1}}};
+ context->module()->AddGlobalValue(MakeUnique<opt::Instruction>(
+ context.get(), SpvOpConstant, type_int32_id, 50, operands));
+ operands = {{SPV_OPERAND_TYPE_LITERAL_INTEGER, {buffer_int32_min[0]}}};
+ context->module()->AddGlobalValue(MakeUnique<opt::Instruction>(
+ context.get(), SpvOpConstant, type_int32_id, 51, operands));
+ operands = {{SPV_OPERAND_TYPE_LITERAL_INTEGER, {buffer_int64_max[0]}},
+ {SPV_OPERAND_TYPE_LITERAL_INTEGER, {buffer_int64_max[1]}}};
+ context->module()->AddGlobalValue(MakeUnique<opt::Instruction>(
+ context.get(), SpvOpConstant, type_int64_id, 52, operands));
+ operands = {{SPV_OPERAND_TYPE_LITERAL_INTEGER, {1}}};
+ context->module()->AddGlobalValue(MakeUnique<opt::Instruction>(
+ context.get(), SpvOpConstant, type_uint32_id, 53, operands));
+ operands = {{SPV_OPERAND_TYPE_LITERAL_INTEGER, {buffer_uint64_1[0]}},
+ {SPV_OPERAND_TYPE_LITERAL_INTEGER, {buffer_uint64_1[1]}}};
+ context->module()->AddGlobalValue(MakeUnique<opt::Instruction>(
+ context.get(), SpvOpConstant, type_uint64_id, 54, operands));
+ operands = {{SPV_OPERAND_TYPE_LITERAL_INTEGER, {buffer_uint64_max[0]}},
+ {SPV_OPERAND_TYPE_LITERAL_INTEGER, {buffer_uint64_max[1]}}};
+ context->module()->AddGlobalValue(MakeUnique<opt::Instruction>(
+ context.get(), SpvOpConstant, type_uint64_id, 55, operands));
+ operands = {{SPV_OPERAND_TYPE_LITERAL_INTEGER, {buffer_float_10[0]}}};
+ context->module()->AddGlobalValue(MakeUnique<opt::Instruction>(
+ context.get(), SpvOpConstant, type_float_id, 56, operands));
+ operands = {{SPV_OPERAND_TYPE_LITERAL_INTEGER, {buffer_double_10[0]}},
+ {SPV_OPERAND_TYPE_LITERAL_INTEGER, {buffer_double_10[1]}}};
+ context->module()->AddGlobalValue(MakeUnique<opt::Instruction>(
+ context.get(), SpvOpConstant, type_double_id, 57, operands));
+ operands = {{SPV_OPERAND_TYPE_LITERAL_INTEGER, {buffer_double_20[0]}},
+ {SPV_OPERAND_TYPE_LITERAL_INTEGER, {buffer_double_20[1]}}};
+ context->module()->AddGlobalValue(MakeUnique<opt::Instruction>(
+ context.get(), SpvOpConstant, type_double_id, 58, operands));
+
+ // A duplicate of the constant with id 59.
+ operands = {{SPV_OPERAND_TYPE_LITERAL_INTEGER, {1}}};
+ context->module()->AddGlobalValue(MakeUnique<opt::Instruction>(
+ context.get(), SpvOpConstant, type_int32_id, 59, operands));
+
+ context->InvalidateAnalysesExceptFor(opt::IRContext::Analysis::kAnalysisNone);
+
+ // Constants 1 and int32_min are available.
+ ASSERT_EQ(2,
+ fact_manager.GetConstantsAvailableFromUniformsForType(type_int32_id)
+ .size());
+ // Constant int64_max is available.
+ ASSERT_EQ(1,
+ fact_manager.GetConstantsAvailableFromUniformsForType(type_int64_id)
+ .size());
+ // Constant 1u is available.
+ ASSERT_EQ(
+ 1, fact_manager.GetConstantsAvailableFromUniformsForType(type_uint32_id)
+ .size());
+ // Constants 1u and uint64_max are available.
+ ASSERT_EQ(
+ 2, fact_manager.GetConstantsAvailableFromUniformsForType(type_uint64_id)
+ .size());
+ // Constant 10.0 is available.
+ ASSERT_EQ(1,
+ fact_manager.GetConstantsAvailableFromUniformsForType(type_float_id)
+ .size());
+ // Constants 10.0 and 20.0 are available.
+ ASSERT_EQ(
+ 2, fact_manager.GetConstantsAvailableFromUniformsForType(type_double_id)
+ .size());
+
+ ASSERT_EQ(std::numeric_limits<int64_t>::max(),
+ context->get_constant_mgr()
+ ->FindDeclaredConstant(
+ fact_manager.GetConstantsAvailableFromUniformsForType(
+ type_int64_id)[0])
+ ->AsIntConstant()
+ ->GetS64());
+ ASSERT_EQ(1, context->get_constant_mgr()
+ ->FindDeclaredConstant(
+ fact_manager.GetConstantsAvailableFromUniformsForType(
+ type_uint32_id)[0])
+ ->AsIntConstant()
+ ->GetU32());
+ ASSERT_EQ(10.0f,
+ context->get_constant_mgr()
+ ->FindDeclaredConstant(
+ fact_manager.GetConstantsAvailableFromUniformsForType(
+ type_float_id)[0])
+ ->AsFloatConstant()
+ ->GetFloat());
+ const std::vector<uint32_t>& double_constant_ids =
+ fact_manager.GetConstantsAvailableFromUniformsForType(type_double_id);
+ ASSERT_EQ(10.0, context->get_constant_mgr()
+ ->FindDeclaredConstant(double_constant_ids[0])
+ ->AsFloatConstant()
+ ->GetDouble());
+ ASSERT_EQ(20.0, context->get_constant_mgr()
+ ->FindDeclaredConstant(double_constant_ids[1])
+ ->AsFloatConstant()
+ ->GetDouble());
+
+ const std::vector<protobufs::UniformBufferElementDescriptor>
+ descriptors_for_double_10 =
+ fact_manager.GetUniformDescriptorsForConstant(double_constant_ids[0]);
+ ASSERT_EQ(2, descriptors_for_double_10.size());
+ {
+ auto temp = MakeUniformBufferElementDescriptor(2, 2, {9, 9, 1});
+ ASSERT_TRUE(UniformBufferElementDescriptorEquals()(
+ &temp, &descriptors_for_double_10[0]));
+ }
+ {
+ auto temp = MakeUniformBufferElementDescriptor(2, 3, {9, 9, 2});
+ ASSERT_TRUE(UniformBufferElementDescriptorEquals()(
+ &temp, &descriptors_for_double_10[1]));
+ }
+ const std::vector<protobufs::UniformBufferElementDescriptor>
+ descriptors_for_double_20 =
+ fact_manager.GetUniformDescriptorsForConstant(double_constant_ids[1]);
+ ASSERT_EQ(1, descriptors_for_double_20.size());
+ {
+ auto temp = MakeUniformBufferElementDescriptor(2, 4, {0, 0, 0, 0, 0});
+ ASSERT_TRUE(UniformBufferElementDescriptorEquals()(
+ &temp, &descriptors_for_double_20[0]));
+ }
+
+ auto constant_1_id = fact_manager.GetConstantFromUniformDescriptor(
+ MakeUniformBufferElementDescriptor(2, 3, {9, 9, 2}));
+ ASSERT_TRUE(constant_1_id);
+
+ auto constant_2_id = fact_manager.GetConstantFromUniformDescriptor(
+ MakeUniformBufferElementDescriptor(2, 4, {0, 0, 0, 0, 0}));
+ ASSERT_TRUE(constant_2_id);
+
+ ASSERT_EQ(double_constant_ids[0], constant_1_id);
+
+ ASSERT_EQ(double_constant_ids[1], constant_2_id);
+}
+
+TEST(ConstantUniformFactsTest, TwoConstantsWithSameValue) {
+ std::string shader = R"(
+ OpCapability Shader
+ %1 = OpExtInstImport "GLSL.std.450"
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %4 "main"
+ OpExecutionMode %4 OriginUpperLeft
+ OpSource ESSL 310
+ OpName %4 "main"
+ OpName %8 "x"
+ OpName %10 "buf"
+ OpMemberName %10 0 "a"
+ OpName %12 ""
+ OpDecorate %8 RelaxedPrecision
+ OpMemberDecorate %10 0 RelaxedPrecision
+ OpMemberDecorate %10 0 Offset 0
+ OpDecorate %10 Block
+ OpDecorate %12 DescriptorSet 0
+ OpDecorate %12 Binding 0
+ %2 = OpTypeVoid
+ %3 = OpTypeFunction %2
+ %6 = OpTypeInt 32 1
+ %7 = OpTypePointer Function %6
+ %9 = OpConstant %6 1
+ %20 = OpConstant %6 1
+ %10 = OpTypeStruct %6
+ %11 = OpTypePointer Uniform %10
+ %12 = OpVariable %11 Uniform
+ %4 = OpFunction %2 None %3
+ %5 = OpLabel
+ %8 = OpVariable %7 Function
+ OpStore %8 %9
+ OpReturn
+ OpFunctionEnd
+ )";
+
+ const auto env = SPV_ENV_UNIVERSAL_1_3;
+ const auto consumer = nullptr;
+ const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
+ ASSERT_TRUE(IsValid(env, context.get()));
+
+ FactManager fact_manager(context.get());
+
+ auto uniform_buffer_element_descriptor =
+ MakeUniformBufferElementDescriptor(0, 0, {0});
+
+ // (0, 0, [0]) = int(1)
+ ASSERT_TRUE(
+ AddFactHelper(&fact_manager, {1}, uniform_buffer_element_descriptor));
+ auto constants = fact_manager.GetConstantsAvailableFromUniformsForType(6);
+ ASSERT_EQ(1, constants.size());
+ ASSERT_TRUE(constants[0] == 9 || constants[0] == 20);
+
+ auto constant = fact_manager.GetConstantFromUniformDescriptor(
+ uniform_buffer_element_descriptor);
+ ASSERT_TRUE(constant == 9 || constant == 20);
+
+ // Because the constants with ids 9 and 20 are equal, we should get the same
+ // single uniform buffer element descriptor when we look up the descriptors
+ // for either one of them.
+ for (auto constant_id : {9u, 20u}) {
+ auto descriptors =
+ fact_manager.GetUniformDescriptorsForConstant(constant_id);
+ ASSERT_EQ(1, descriptors.size());
+ ASSERT_TRUE(UniformBufferElementDescriptorEquals()(
+ &uniform_buffer_element_descriptor, &descriptors[0]));
+ }
+}
+
+TEST(ConstantUniformFactsTest, NonFiniteFactsAreNotValid) {
+ std::string shader = R"(
+ OpCapability Shader
+ OpCapability Float64
+ %1 = OpExtInstImport "GLSL.std.450"
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %4 "main"
+ OpExecutionMode %4 OriginUpperLeft
+ OpSource ESSL 310
+ OpName %4 "main"
+ OpName %7 "buf"
+ OpMemberName %7 0 "f"
+ OpMemberName %7 1 "d"
+ OpName %9 ""
+ OpMemberDecorate %7 0 Offset 0
+ OpMemberDecorate %7 1 Offset 8
+ OpDecorate %7 Block
+ OpDecorate %9 DescriptorSet 0
+ OpDecorate %9 Binding 0
+ %2 = OpTypeVoid
+ %3 = OpTypeFunction %2
+ %6 = OpTypeFloat 32
+ %10 = OpTypeFloat 64
+ %7 = OpTypeStruct %6 %10
+ %8 = OpTypePointer Uniform %7
+ %9 = OpVariable %8 Uniform
+ %4 = OpFunction %2 None %3
+ %5 = OpLabel
+ OpReturn
+ OpFunctionEnd
+ )";
+
+ const auto env = SPV_ENV_UNIVERSAL_1_3;
+ const auto consumer = nullptr;
+ const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
+ ASSERT_TRUE(IsValid(env, context.get()));
+
+ FactManager fact_manager(context.get());
+ auto uniform_buffer_element_descriptor_f =
+ MakeUniformBufferElementDescriptor(0, 0, {0});
+
+ auto uniform_buffer_element_descriptor_d =
+ MakeUniformBufferElementDescriptor(0, 0, {1});
+
+ if (std::numeric_limits<float>::has_infinity) {
+ // f == +inf
+ float positive_infinity_float = std::numeric_limits<float>::infinity();
+ uint32_t words[1];
+ memcpy(words, &positive_infinity_float, sizeof(float));
+ ASSERT_FALSE(AddFactHelper(&fact_manager, {words[0]},
+ uniform_buffer_element_descriptor_f));
+ // f == -inf
+ float negative_infinity_float = std::numeric_limits<float>::infinity();
+ memcpy(words, &negative_infinity_float, sizeof(float));
+ ASSERT_FALSE(AddFactHelper(&fact_manager, {words[0]},
+ uniform_buffer_element_descriptor_f));
+ }
+
+ if (std::numeric_limits<float>::has_quiet_NaN) {
+ // f == NaN
+ float quiet_nan_float = std::numeric_limits<float>::quiet_NaN();
+ uint32_t words[1];
+ memcpy(words, &quiet_nan_float, sizeof(float));
+ ASSERT_FALSE(AddFactHelper(&fact_manager, {words[0]},
+ uniform_buffer_element_descriptor_f));
+ }
+
+ if (std::numeric_limits<double>::has_infinity) {
+ // d == +inf
+ double positive_infinity_double = std::numeric_limits<double>::infinity();
+ uint32_t words[2];
+ memcpy(words, &positive_infinity_double, sizeof(double));
+ ASSERT_FALSE(AddFactHelper(&fact_manager, {words[0], words[1]},
+ uniform_buffer_element_descriptor_d));
+ // d == -inf
+ double negative_infinity_double = -std::numeric_limits<double>::infinity();
+ memcpy(words, &negative_infinity_double, sizeof(double));
+ ASSERT_FALSE(AddFactHelper(&fact_manager, {words[0], words[1]},
+ uniform_buffer_element_descriptor_d));
+ }
+
+ if (std::numeric_limits<double>::has_quiet_NaN) {
+ // d == NaN
+ double quiet_nan_double = std::numeric_limits<double>::quiet_NaN();
+ uint32_t words[2];
+ memcpy(words, &quiet_nan_double, sizeof(double));
+ ASSERT_FALSE(AddFactHelper(&fact_manager, {words[0], words[1]},
+ uniform_buffer_element_descriptor_d));
+ }
+}
+
+TEST(ConstantUniformFactsTest, AmbiguousFact) {
+ // This test came from the following GLSL:
+ //
+ // #version 310 es
+ //
+ // precision highp float;
+ //
+ // layout(set = 0, binding = 0) uniform buf {
+ // float f;
+ // };
+ //
+ // layout(set = 0, binding = 0) uniform buf2 {
+ // float g;
+ // };
+ //
+ // void main() {
+ //
+ // }
+
+ std::string shader = R"(
+ OpCapability Shader
+ %1 = OpExtInstImport "GLSL.std.450"
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %4 "main"
+ OpExecutionMode %4 OriginUpperLeft
+ OpSource ESSL 310
+ OpName %4 "main"
+ OpName %7 "buf"
+ OpMemberName %7 0 "f"
+ OpName %9 ""
+ OpName %10 "buf2"
+ OpMemberName %10 0 "g"
+ OpName %12 ""
+ OpMemberDecorate %7 0 Offset 0
+ OpDecorate %7 Block
+ OpDecorate %9 DescriptorSet 0
+ OpDecorate %9 Binding 0
+ OpMemberDecorate %10 0 Offset 0
+ OpDecorate %10 Block
+ OpDecorate %12 DescriptorSet 0
+ OpDecorate %12 Binding 0
+ %2 = OpTypeVoid
+ %3 = OpTypeFunction %2
+ %6 = OpTypeFloat 32
+ %7 = OpTypeStruct %6
+ %8 = OpTypePointer Uniform %7
+ %9 = OpVariable %8 Uniform
+ %10 = OpTypeStruct %6
+ %11 = OpTypePointer Uniform %10
+ %12 = OpVariable %11 Uniform
+ %4 = OpFunction %2 None %3
+ %5 = OpLabel
+ OpReturn
+ OpFunctionEnd
+ )";
+
+ const auto env = SPV_ENV_UNIVERSAL_1_3;
+ const auto consumer = nullptr;
+ const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
+ ASSERT_TRUE(IsValid(env, context.get()));
+
+ FactManager fact_manager(context.get());
+ auto uniform_buffer_element_descriptor =
+ MakeUniformBufferElementDescriptor(0, 0, {0});
+
+ // The fact cannot be added because it is ambiguous: there are two uniforms
+ // with descriptor set 0 and binding 0.
+ ASSERT_FALSE(
+ AddFactHelper(&fact_manager, {1}, uniform_buffer_element_descriptor));
+}
+
+TEST(ConstantUniformFactsTest, CheckingFactsDoesNotAddConstants) {
+ std::string shader = R"(
+ OpCapability Shader
+ %1 = OpExtInstImport "GLSL.std.450"
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %4 "main"
+ OpExecutionMode %4 OriginUpperLeft
+ OpSource ESSL 320
+ OpMemberDecorate %9 0 Offset 0
+ OpDecorate %9 Block
+ OpDecorate %11 DescriptorSet 0
+ OpDecorate %11 Binding 0
+ %2 = OpTypeVoid
+ %3 = OpTypeFunction %2
+ %6 = OpTypeInt 32 1
+ %7 = OpTypePointer Function %6
+ %9 = OpTypeStruct %6
+ %10 = OpTypePointer Uniform %9
+ %11 = OpVariable %10 Uniform
+ %12 = OpConstant %6 0
+ %13 = OpTypePointer Uniform %6
+ %4 = OpFunction %2 None %3
+ %5 = OpLabel
+ %8 = OpVariable %7 Function
+ %14 = OpAccessChain %13 %11 %12
+ %15 = OpLoad %6 %14
+ OpStore %8 %15
+ OpReturn
+ OpFunctionEnd
+ )";
+
+ const auto env = SPV_ENV_UNIVERSAL_1_3;
+ const auto consumer = nullptr;
+ const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
+ ASSERT_TRUE(IsValid(env, context.get()));
+
+ FactManager fact_manager(context.get());
+
+ // 8[0] == int(1)
+ ASSERT_TRUE(AddFactHelper(&fact_manager, {1},
+ MakeUniformBufferElementDescriptor(0, 0, {0})));
+
+ // Although 8[0] has the value 1, we do not have the constant 1 in the module.
+ // We thus should not find any constants available from uniforms for int type.
+ // Furthermore, the act of looking for appropriate constants should not change
+ // which constants are known to the constant manager.
+ auto int_type = context->get_type_mgr()->GetType(6)->AsInteger();
+ opt::analysis::IntConstant constant_one(int_type, {1});
+ ASSERT_FALSE(context->get_constant_mgr()->FindConstant(&constant_one));
+ auto available_constants =
+ fact_manager.GetConstantsAvailableFromUniformsForType(6);
+ ASSERT_EQ(0, available_constants.size());
+ ASSERT_TRUE(IsEqual(env, shader, context.get()));
+ ASSERT_FALSE(context->get_constant_mgr()->FindConstant(&constant_one));
+}
+
+} // namespace
+} // namespace fuzz
+} // namespace spvtools
diff --git a/test/fuzz/fact_manager/data_synonym_and_id_equation_facts_test.cpp b/test/fuzz/fact_manager/data_synonym_and_id_equation_facts_test.cpp
new file mode 100644
index 0000000..069268b
--- /dev/null
+++ b/test/fuzz/fact_manager/data_synonym_and_id_equation_facts_test.cpp
@@ -0,0 +1,644 @@
+// Copyright (c) 2019 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "source/fuzz/fact_manager/fact_manager.h"
+#include "source/fuzz/transformation_merge_blocks.h"
+#include "test/fuzz/fuzz_test_util.h"
+
+namespace spvtools {
+namespace fuzz {
+namespace {
+
+TEST(DataSynonymAndIdEquationFactsTest, RecursiveAdditionOfFacts) {
+ std::string shader = R"(
+ OpCapability Shader
+ %1 = OpExtInstImport "GLSL.std.450"
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %12 "main"
+ OpExecutionMode %12 OriginUpperLeft
+ OpSource ESSL 310
+ %2 = OpTypeVoid
+ %3 = OpTypeFunction %2
+ %6 = OpTypeFloat 32
+ %7 = OpTypeVector %6 4
+ %8 = OpTypeMatrix %7 4
+ %9 = OpConstant %6 0
+ %10 = OpConstantComposite %7 %9 %9 %9 %9
+ %11 = OpConstantComposite %8 %10 %10 %10 %10
+ %12 = OpFunction %2 None %3
+ %13 = OpLabel
+ OpReturn
+ OpFunctionEnd
+ )";
+
+ const auto env = SPV_ENV_UNIVERSAL_1_3;
+ const auto consumer = nullptr;
+ const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
+ ASSERT_TRUE(IsValid(env, context.get()));
+
+ FactManager fact_manager(context.get());
+
+ fact_manager.AddFactDataSynonym(MakeDataDescriptor(10, {}),
+ MakeDataDescriptor(11, {2}));
+
+ ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(10, {}),
+ MakeDataDescriptor(11, {2})));
+ ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(10, {0}),
+ MakeDataDescriptor(11, {2, 0})));
+ ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(10, {1}),
+ MakeDataDescriptor(11, {2, 1})));
+ ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(10, {2}),
+ MakeDataDescriptor(11, {2, 2})));
+ ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(10, {3}),
+ MakeDataDescriptor(11, {2, 3})));
+}
+
+TEST(DataSynonymAndIdEquationFactsTest, CorollaryConversionFacts) {
+ std::string shader = R"(
+ OpCapability Shader
+ %1 = OpExtInstImport "GLSL.std.450"
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %12 "main"
+ OpExecutionMode %12 OriginUpperLeft
+ OpSource ESSL 310
+ %2 = OpTypeVoid
+ %3 = OpTypeFunction %2
+ %6 = OpTypeInt 32 1
+ %7 = OpTypeInt 32 0
+ %8 = OpTypeVector %6 2
+ %9 = OpTypeVector %7 2
+ %10 = OpTypeFloat 32
+ %11 = OpTypeVector %10 2
+ %15 = OpConstant %6 24 ; synonym of %16
+ %16 = OpConstant %6 24
+ %17 = OpConstant %7 24 ; synonym of %18
+ %18 = OpConstant %7 24
+ %19 = OpConstantComposite %8 %15 %15 ; synonym of %20
+ %20 = OpConstantComposite %8 %16 %16
+ %21 = OpConstantComposite %9 %17 %17 ; synonym of %22
+ %22 = OpConstantComposite %9 %18 %18
+ %23 = OpConstantComposite %8 %15 %15 ; not a synonym of %19
+ %12 = OpFunction %2 None %3
+ %13 = OpLabel
+ %24 = OpConvertSToF %10 %15 ; synonym of %25
+ %25 = OpConvertSToF %10 %16
+ %26 = OpConvertUToF %10 %17 ; not a synonym of %27 (different opcode)
+ %27 = OpConvertSToF %10 %18
+ %28 = OpConvertUToF %11 %19 ; synonym of %29
+ %29 = OpConvertUToF %11 %20
+ %30 = OpConvertSToF %11 %21 ; not a synonym of %31 (different opcode)
+ %31 = OpConvertUToF %11 %22
+ %32 = OpConvertUToF %11 %23 ; not a synonym of %28 (operand is not synonymous)
+ OpReturn
+ OpFunctionEnd
+ )";
+
+ const auto env = SPV_ENV_UNIVERSAL_1_3;
+ const auto consumer = nullptr;
+ const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
+ ASSERT_TRUE(IsValid(env, context.get()));
+
+ FactManager fact_manager(context.get());
+
+ // Add equation facts
+ fact_manager.AddFactIdEquation(24, SpvOpConvertSToF, {15});
+ fact_manager.AddFactIdEquation(25, SpvOpConvertSToF, {16});
+ fact_manager.AddFactIdEquation(26, SpvOpConvertUToF, {17});
+ fact_manager.AddFactIdEquation(27, SpvOpConvertSToF, {18});
+ fact_manager.AddFactIdEquation(28, SpvOpConvertUToF, {19});
+ fact_manager.AddFactIdEquation(29, SpvOpConvertUToF, {20});
+ fact_manager.AddFactIdEquation(30, SpvOpConvertSToF, {21});
+ fact_manager.AddFactIdEquation(31, SpvOpConvertUToF, {22});
+ fact_manager.AddFactIdEquation(32, SpvOpConvertUToF, {23});
+
+ fact_manager.AddFactDataSynonym(MakeDataDescriptor(15, {}),
+ MakeDataDescriptor(16, {}));
+ ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(24, {}),
+ MakeDataDescriptor(25, {})));
+
+ fact_manager.AddFactDataSynonym(MakeDataDescriptor(17, {}),
+ MakeDataDescriptor(18, {}));
+ ASSERT_FALSE(fact_manager.IsSynonymous(MakeDataDescriptor(26, {}),
+ MakeDataDescriptor(27, {})));
+
+ fact_manager.AddFactDataSynonym(MakeDataDescriptor(19, {}),
+ MakeDataDescriptor(20, {}));
+ ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(28, {}),
+ MakeDataDescriptor(29, {})));
+
+ fact_manager.AddFactDataSynonym(MakeDataDescriptor(21, {}),
+ MakeDataDescriptor(22, {}));
+ ASSERT_FALSE(fact_manager.IsSynonymous(MakeDataDescriptor(30, {}),
+ MakeDataDescriptor(31, {})));
+
+ ASSERT_FALSE(fact_manager.IsSynonymous(MakeDataDescriptor(32, {}),
+ MakeDataDescriptor(28, {})));
+ fact_manager.AddFactDataSynonym(MakeDataDescriptor(23, {}),
+ MakeDataDescriptor(19, {}));
+ ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(32, {}),
+ MakeDataDescriptor(28, {})));
+ ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(32, {}),
+ MakeDataDescriptor(29, {})));
+}
+
+TEST(DataSynonymAndIdEquationFactsTest, HandlesCorollariesWithInvalidIds) {
+ std::string shader = R"(
+ OpCapability Shader
+ %1 = OpExtInstImport "GLSL.std.450"
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %12 "main"
+ OpExecutionMode %12 OriginUpperLeft
+ OpSource ESSL 310
+ %2 = OpTypeVoid
+ %3 = OpTypeFunction %2
+ %6 = OpTypeFloat 32
+ %8 = OpTypeInt 32 1
+ %9 = OpConstant %8 3
+ %12 = OpFunction %2 None %3
+ %13 = OpLabel
+ %14 = OpConvertSToF %6 %9
+ OpBranch %16
+ %16 = OpLabel
+ %17 = OpPhi %6 %14 %13
+ %15 = OpConvertSToF %6 %9
+ %18 = OpConvertSToF %6 %9
+ OpReturn
+ OpFunctionEnd
+ )";
+
+ const auto env = SPV_ENV_UNIVERSAL_1_3;
+ const auto consumer = nullptr;
+ const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
+ ASSERT_TRUE(IsValid(env, context.get()));
+
+ spvtools::ValidatorOptions validator_options;
+ TransformationContext transformation_context(
+ MakeUnique<FactManager>(context.get()), validator_options);
+
+ // Add required facts.
+ transformation_context.GetFactManager()->AddFactIdEquation(
+ 14, SpvOpConvertSToF, {9});
+ transformation_context.GetFactManager()->AddFactDataSynonym(
+ MakeDataDescriptor(14, {}), MakeDataDescriptor(17, {}));
+
+ // Apply TransformationMergeBlocks which will remove %17 from the module.
+ TransformationMergeBlocks transformation(16);
+ ASSERT_TRUE(
+ transformation.IsApplicable(context.get(), transformation_context));
+ transformation.Apply(context.get(), &transformation_context);
+ ASSERT_TRUE(IsValid(env, context.get()));
+
+ ASSERT_EQ(context->get_def_use_mgr()->GetDef(17), nullptr);
+
+ // Add another equation.
+ transformation_context.GetFactManager()->AddFactIdEquation(
+ 15, SpvOpConvertSToF, {9});
+
+ // Check that two ids are synonymous even though one of them doesn't exist in
+ // the module (%17).
+ ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
+ MakeDataDescriptor(15, {}), MakeDataDescriptor(17, {})));
+ ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
+ MakeDataDescriptor(15, {}), MakeDataDescriptor(14, {})));
+
+ // Remove some instructions from the module. At this point, the equivalence
+ // class of %14 has no valid members.
+ ASSERT_TRUE(context->KillDef(14));
+ ASSERT_TRUE(context->KillDef(15));
+
+ transformation_context.GetFactManager()->AddFactIdEquation(
+ 18, SpvOpConvertSToF, {9});
+
+ // We don't create synonyms if at least one of the equivalence classes has no
+ // valid members.
+ ASSERT_FALSE(transformation_context.GetFactManager()->IsSynonymous(
+ MakeDataDescriptor(14, {}), MakeDataDescriptor(18, {})));
+}
+
+TEST(DataSynonymAndIdEquationFactsTest, LogicalNotEquationFacts) {
+ std::string shader = R"(
+ OpCapability Shader
+ %1 = OpExtInstImport "GLSL.std.450"
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %12 "main"
+ OpExecutionMode %12 OriginUpperLeft
+ OpSource ESSL 310
+ %2 = OpTypeVoid
+ %3 = OpTypeFunction %2
+ %6 = OpTypeBool
+ %7 = OpConstantTrue %6
+ %12 = OpFunction %2 None %3
+ %13 = OpLabel
+ %14 = OpLogicalNot %6 %7
+ %15 = OpCopyObject %6 %7
+ %16 = OpCopyObject %6 %14
+ %17 = OpLogicalNot %6 %16
+ OpReturn
+ OpFunctionEnd
+ )";
+
+ const auto env = SPV_ENV_UNIVERSAL_1_3;
+ const auto consumer = nullptr;
+ const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
+ ASSERT_TRUE(IsValid(env, context.get()));
+
+ FactManager fact_manager(context.get());
+
+ fact_manager.AddFactDataSynonym(MakeDataDescriptor(15, {}),
+ MakeDataDescriptor(7, {}));
+ fact_manager.AddFactDataSynonym(MakeDataDescriptor(16, {}),
+ MakeDataDescriptor(14, {}));
+ fact_manager.AddFactIdEquation(14, SpvOpLogicalNot, {7});
+ fact_manager.AddFactIdEquation(17, SpvOpLogicalNot, {16});
+
+ ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(15, {}),
+ MakeDataDescriptor(7, {})));
+ ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(17, {}),
+ MakeDataDescriptor(7, {})));
+ ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(15, {}),
+ MakeDataDescriptor(17, {})));
+ ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(16, {}),
+ MakeDataDescriptor(14, {})));
+}
+
+TEST(DataSynonymAndIdEquationFactsTest, SignedNegateEquationFacts) {
+ std::string shader = R"(
+ OpCapability Shader
+ %1 = OpExtInstImport "GLSL.std.450"
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %12 "main"
+ OpExecutionMode %12 OriginUpperLeft
+ OpSource ESSL 310
+ %2 = OpTypeVoid
+ %3 = OpTypeFunction %2
+ %6 = OpTypeInt 32 1
+ %7 = OpConstant %6 24
+ %12 = OpFunction %2 None %3
+ %13 = OpLabel
+ %14 = OpSNegate %6 %7
+ %15 = OpSNegate %6 %14
+ OpReturn
+ OpFunctionEnd
+ )";
+
+ const auto env = SPV_ENV_UNIVERSAL_1_3;
+ const auto consumer = nullptr;
+ const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
+ ASSERT_TRUE(IsValid(env, context.get()));
+
+ FactManager fact_manager(context.get());
+
+ fact_manager.AddFactIdEquation(14, SpvOpSNegate, {7});
+ fact_manager.AddFactIdEquation(15, SpvOpSNegate, {14});
+
+ ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(7, {}),
+ MakeDataDescriptor(15, {})));
+}
+
+TEST(DataSynonymAndIdEquationFactsTest, AddSubNegateFacts1) {
+ std::string shader = R"(
+ OpCapability Shader
+ %1 = OpExtInstImport "GLSL.std.450"
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %12 "main"
+ OpExecutionMode %12 OriginUpperLeft
+ OpSource ESSL 310
+ %2 = OpTypeVoid
+ %3 = OpTypeFunction %2
+ %6 = OpTypeInt 32 1
+ %15 = OpConstant %6 24
+ %16 = OpConstant %6 37
+ %12 = OpFunction %2 None %3
+ %13 = OpLabel
+ %14 = OpIAdd %6 %15 %16
+ %17 = OpCopyObject %6 %15
+ %18 = OpCopyObject %6 %16
+ %19 = OpISub %6 %14 %18 ; ==> synonymous(%19, %15)
+ %20 = OpISub %6 %14 %17 ; ==> synonymous(%20, %16)
+ %21 = OpCopyObject %6 %14
+ %22 = OpISub %6 %16 %21
+ %23 = OpCopyObject %6 %22
+ %24 = OpSNegate %6 %23 ; ==> synonymous(%24, %15)
+ OpReturn
+ OpFunctionEnd
+ )";
+
+ const auto env = SPV_ENV_UNIVERSAL_1_3;
+ const auto consumer = nullptr;
+ const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
+ ASSERT_TRUE(IsValid(env, context.get()));
+
+ FactManager fact_manager(context.get());
+
+ fact_manager.AddFactIdEquation(14, SpvOpIAdd, {15, 16});
+ fact_manager.AddFactDataSynonym(MakeDataDescriptor(17, {}),
+ MakeDataDescriptor(15, {}));
+ fact_manager.AddFactDataSynonym(MakeDataDescriptor(18, {}),
+ MakeDataDescriptor(16, {}));
+ fact_manager.AddFactIdEquation(19, SpvOpISub, {14, 18});
+ fact_manager.AddFactIdEquation(20, SpvOpISub, {14, 17});
+ fact_manager.AddFactDataSynonym(MakeDataDescriptor(21, {}),
+ MakeDataDescriptor(14, {}));
+ fact_manager.AddFactIdEquation(22, SpvOpISub, {16, 21});
+ fact_manager.AddFactDataSynonym(MakeDataDescriptor(23, {}),
+ MakeDataDescriptor(22, {}));
+ fact_manager.AddFactIdEquation(24, SpvOpSNegate, {23});
+
+ ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(19, {}),
+ MakeDataDescriptor(15, {})));
+ ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(20, {}),
+ MakeDataDescriptor(16, {})));
+ ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(24, {}),
+ MakeDataDescriptor(15, {})));
+}
+
+TEST(DataSynonymAndIdEquationFactsTest, AddSubNegateFacts2) {
+ std::string shader = R"(
+ OpCapability Shader
+ %1 = OpExtInstImport "GLSL.std.450"
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %12 "main"
+ OpExecutionMode %12 OriginUpperLeft
+ OpSource ESSL 310
+ %2 = OpTypeVoid
+ %3 = OpTypeFunction %2
+ %6 = OpTypeInt 32 1
+ %15 = OpConstant %6 24
+ %16 = OpConstant %6 37
+ %12 = OpFunction %2 None %3
+ %13 = OpLabel
+ %14 = OpISub %6 %15 %16
+ %17 = OpIAdd %6 %14 %16 ; ==> synonymous(%17, %15)
+ %18 = OpIAdd %6 %16 %14 ; ==> synonymous(%17, %18, %15)
+ %19 = OpISub %6 %14 %15
+ %20 = OpSNegate %6 %19 ; ==> synonymous(%20, %16)
+ %21 = OpISub %6 %14 %19 ; ==> synonymous(%21, %15)
+ %22 = OpISub %6 %14 %18
+ %23 = OpSNegate %6 %22 ; ==> synonymous(%23, %16)
+ OpReturn
+ OpFunctionEnd
+ )";
+
+ const auto env = SPV_ENV_UNIVERSAL_1_3;
+ const auto consumer = nullptr;
+ const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
+ ASSERT_TRUE(IsValid(env, context.get()));
+
+ FactManager fact_manager(context.get());
+
+ fact_manager.AddFactIdEquation(14, SpvOpISub, {15, 16});
+ fact_manager.AddFactIdEquation(17, SpvOpIAdd, {14, 16});
+
+ ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(17, {}),
+ MakeDataDescriptor(15, {})));
+
+ fact_manager.AddFactIdEquation(18, SpvOpIAdd, {16, 14});
+
+ ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(18, {}),
+ MakeDataDescriptor(15, {})));
+ ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(17, {}),
+ MakeDataDescriptor(18, {})));
+
+ fact_manager.AddFactIdEquation(19, SpvOpISub, {14, 15});
+ fact_manager.AddFactIdEquation(20, SpvOpSNegate, {19});
+
+ ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(20, {}),
+ MakeDataDescriptor(16, {})));
+
+ fact_manager.AddFactIdEquation(21, SpvOpISub, {14, 19});
+ ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(21, {}),
+ MakeDataDescriptor(15, {})));
+
+ fact_manager.AddFactIdEquation(22, SpvOpISub, {14, 18});
+ fact_manager.AddFactIdEquation(23, SpvOpSNegate, {22});
+ ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(23, {}),
+ MakeDataDescriptor(16, {})));
+}
+
+TEST(DataSynonymAndIdEquationFactsTest, ConversionEquations) {
+ std::string shader = R"(
+ OpCapability Shader
+ %1 = OpExtInstImport "GLSL.std.450"
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %12 "main"
+ OpExecutionMode %12 OriginUpperLeft
+ OpSource ESSL 310
+ %2 = OpTypeVoid
+ %3 = OpTypeFunction %2
+ %4 = OpTypeInt 32 1
+ %5 = OpTypeInt 32 0
+ %6 = OpTypeFloat 32
+ %14 = OpTypeVector %4 2
+ %15 = OpTypeVector %5 2
+ %24 = OpTypeVector %6 2
+ %16 = OpConstant %4 32 ; synonym of %17
+ %17 = OpConstant %4 32
+ %18 = OpConstant %5 32 ; synonym of %19
+ %19 = OpConstant %5 32
+ %20 = OpConstantComposite %14 %16 %16 ; synonym of %21
+ %21 = OpConstantComposite %14 %17 %17
+ %22 = OpConstantComposite %15 %18 %18 ; synonym of %23
+ %23 = OpConstantComposite %15 %19 %19
+ %12 = OpFunction %2 None %3
+ %13 = OpLabel
+ %25 = OpConvertUToF %6 %16 ; synonym of %26
+ %26 = OpConvertUToF %6 %17
+ %27 = OpConvertSToF %24 %20 ; not a synonym of %28 (wrong opcode)
+ %28 = OpConvertUToF %24 %21
+ %29 = OpConvertSToF %6 %18 ; not a synonym of %30 (wrong opcode)
+ %30 = OpConvertUToF %6 %19
+ %31 = OpConvertSToF %24 %22 ; synonym of %32
+ %32 = OpConvertSToF %24 %23
+ %33 = OpConvertUToF %6 %17 ; synonym of %26
+ %34 = OpConvertSToF %24 %23 ; synonym of %32
+ OpReturn
+ OpFunctionEnd
+ )";
+
+ const auto env = SPV_ENV_UNIVERSAL_1_3;
+ const auto consumer = nullptr;
+ const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
+ ASSERT_TRUE(IsValid(env, context.get()));
+
+ FactManager fact_manager(context.get());
+
+ fact_manager.AddFactDataSynonym(MakeDataDescriptor(16, {}),
+ MakeDataDescriptor(17, {}));
+ fact_manager.AddFactDataSynonym(MakeDataDescriptor(18, {}),
+ MakeDataDescriptor(19, {}));
+ fact_manager.AddFactDataSynonym(MakeDataDescriptor(20, {}),
+ MakeDataDescriptor(21, {}));
+ fact_manager.AddFactDataSynonym(MakeDataDescriptor(22, {}),
+ MakeDataDescriptor(23, {}));
+
+ fact_manager.AddFactIdEquation(25, SpvOpConvertUToF, {16});
+ fact_manager.AddFactIdEquation(26, SpvOpConvertUToF, {17});
+ ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(25, {}),
+ MakeDataDescriptor(26, {})));
+
+ fact_manager.AddFactIdEquation(27, SpvOpConvertSToF, {20});
+ fact_manager.AddFactIdEquation(28, SpvOpConvertUToF, {21});
+ ASSERT_FALSE(fact_manager.IsSynonymous(MakeDataDescriptor(27, {}),
+ MakeDataDescriptor(28, {})));
+
+ fact_manager.AddFactIdEquation(29, SpvOpConvertSToF, {18});
+ fact_manager.AddFactIdEquation(30, SpvOpConvertUToF, {19});
+ ASSERT_FALSE(fact_manager.IsSynonymous(MakeDataDescriptor(29, {}),
+ MakeDataDescriptor(30, {})));
+
+ fact_manager.AddFactIdEquation(31, SpvOpConvertSToF, {22});
+ fact_manager.AddFactIdEquation(32, SpvOpConvertSToF, {23});
+ ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(31, {}),
+ MakeDataDescriptor(32, {})));
+
+ fact_manager.AddFactIdEquation(33, SpvOpConvertUToF, {17});
+ ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(33, {}),
+ MakeDataDescriptor(26, {})));
+
+ fact_manager.AddFactIdEquation(34, SpvOpConvertSToF, {23});
+ ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(32, {}),
+ MakeDataDescriptor(34, {})));
+}
+
+TEST(DataSynonymAndIdEquationFactsTest, BitcastEquationFacts) {
+ std::string shader = R"(
+ OpCapability Shader
+ %1 = OpExtInstImport "GLSL.std.450"
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %12 "main"
+ OpExecutionMode %12 OriginUpperLeft
+ OpSource ESSL 310
+ %2 = OpTypeVoid
+ %3 = OpTypeFunction %2
+ %4 = OpTypeInt 32 1
+ %5 = OpTypeInt 32 0
+ %8 = OpTypeFloat 32
+ %9 = OpTypeVector %4 2
+ %10 = OpTypeVector %5 2
+ %11 = OpTypeVector %8 2
+ %6 = OpConstant %4 23
+ %7 = OpConstant %5 23
+ %19 = OpConstant %8 23
+ %20 = OpConstantComposite %9 %6 %6
+ %21 = OpConstantComposite %10 %7 %7
+ %22 = OpConstantComposite %11 %19 %19
+ %12 = OpFunction %2 None %3
+ %13 = OpLabel
+ %30 = OpBitcast %8 %6
+ %31 = OpBitcast %5 %6
+ %32 = OpBitcast %8 %7
+ %33 = OpBitcast %4 %7
+ %34 = OpBitcast %4 %19
+ %35 = OpBitcast %5 %19
+ %36 = OpBitcast %10 %20
+ %37 = OpBitcast %11 %20
+ %38 = OpBitcast %9 %21
+ %39 = OpBitcast %11 %21
+ %40 = OpBitcast %9 %22
+ %41 = OpBitcast %10 %22
+ OpReturn
+ OpFunctionEnd
+ )";
+
+ const auto env = SPV_ENV_UNIVERSAL_1_3;
+ const auto consumer = nullptr;
+ const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
+ ASSERT_TRUE(IsValid(env, context.get()));
+
+ FactManager fact_manager(context.get());
+
+ uint32_t lhs_id = 30;
+ for (uint32_t rhs_id : {6, 6, 7, 7, 19, 19, 20, 20, 21, 21, 22, 22}) {
+ fact_manager.AddFactIdEquation(lhs_id, SpvOpBitcast, {rhs_id});
+ ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(lhs_id, {}),
+ MakeDataDescriptor(rhs_id, {})));
+ ++lhs_id;
+ }
+}
+
+TEST(DataSynonymAndIdEquationFactsTest, EquationAndEquivalenceFacts) {
+ std::string shader = R"(
+ OpCapability Shader
+ %1 = OpExtInstImport "GLSL.std.450"
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %12 "main"
+ OpExecutionMode %12 OriginUpperLeft
+ OpSource ESSL 310
+ %2 = OpTypeVoid
+ %3 = OpTypeFunction %2
+ %6 = OpTypeInt 32 1
+ %15 = OpConstant %6 24
+ %16 = OpConstant %6 37
+ %12 = OpFunction %2 None %3
+ %13 = OpLabel
+ %14 = OpISub %6 %15 %16
+ %114 = OpCopyObject %6 %14
+ %17 = OpIAdd %6 %114 %16 ; ==> synonymous(%17, %15)
+ %18 = OpIAdd %6 %16 %114 ; ==> synonymous(%17, %18, %15)
+ %19 = OpISub %6 %114 %15
+ %119 = OpCopyObject %6 %19
+ %20 = OpSNegate %6 %119 ; ==> synonymous(%20, %16)
+ %21 = OpISub %6 %14 %19 ; ==> synonymous(%21, %15)
+ %22 = OpISub %6 %14 %18
+ %220 = OpCopyObject %6 %22
+ %23 = OpSNegate %6 %220 ; ==> synonymous(%23, %16)
+ OpReturn
+ OpFunctionEnd
+ )";
+
+ const auto env = SPV_ENV_UNIVERSAL_1_3;
+ const auto consumer = nullptr;
+ const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
+ ASSERT_TRUE(IsValid(env, context.get()));
+
+ FactManager fact_manager(context.get());
+
+ fact_manager.AddFactIdEquation(14, SpvOpISub, {15, 16});
+ fact_manager.AddFactDataSynonym(MakeDataDescriptor(114, {}),
+ MakeDataDescriptor(14, {}));
+ fact_manager.AddFactIdEquation(17, SpvOpIAdd, {114, 16});
+
+ ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(17, {}),
+ MakeDataDescriptor(15, {})));
+
+ fact_manager.AddFactIdEquation(18, SpvOpIAdd, {16, 114});
+
+ ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(18, {}),
+ MakeDataDescriptor(15, {})));
+ ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(17, {}),
+ MakeDataDescriptor(18, {})));
+
+ fact_manager.AddFactIdEquation(19, SpvOpISub, {14, 15});
+ fact_manager.AddFactDataSynonym(MakeDataDescriptor(119, {}),
+ MakeDataDescriptor(19, {}));
+ fact_manager.AddFactIdEquation(20, SpvOpSNegate, {119});
+
+ ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(20, {}),
+ MakeDataDescriptor(16, {})));
+
+ fact_manager.AddFactIdEquation(21, SpvOpISub, {14, 19});
+ ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(21, {}),
+ MakeDataDescriptor(15, {})));
+
+ fact_manager.AddFactIdEquation(22, SpvOpISub, {14, 18});
+ fact_manager.AddFactDataSynonym(MakeDataDescriptor(22, {}),
+ MakeDataDescriptor(220, {}));
+ fact_manager.AddFactIdEquation(23, SpvOpSNegate, {220});
+ ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(23, {}),
+ MakeDataDescriptor(16, {})));
+}
+
+} // namespace
+} // namespace fuzz
+} // namespace spvtools
diff --git a/test/fuzz/fact_manager/dead_block_facts_test.cpp b/test/fuzz/fact_manager/dead_block_facts_test.cpp
new file mode 100644
index 0000000..0799d00
--- /dev/null
+++ b/test/fuzz/fact_manager/dead_block_facts_test.cpp
@@ -0,0 +1,69 @@
+// Copyright (c) 2019 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "source/fuzz/fact_manager/fact_manager.h"
+#include "test/fuzz/fuzz_test_util.h"
+
+namespace spvtools {
+namespace fuzz {
+namespace {
+
+TEST(DeadBlockFactsTest, BlockIsDead) {
+ std::string shader = R"(
+ OpCapability Shader
+ %1 = OpExtInstImport "GLSL.std.450"
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %2 "main"
+ OpExecutionMode %2 OriginUpperLeft
+ OpSource ESSL 310
+ %3 = OpTypeVoid
+ %4 = OpTypeFunction %3
+ %5 = OpTypeBool
+ %6 = OpConstantTrue %5
+ %7 = OpTypeInt 32 1
+ %8 = OpTypePointer Function %7
+ %2 = OpFunction %3 None %4
+ %9 = OpLabel
+ OpSelectionMerge %10 None
+ OpBranchConditional %6 %11 %12
+ %11 = OpLabel
+ OpBranch %10
+ %12 = OpLabel
+ OpBranch %10
+ %10 = OpLabel
+ OpReturn
+ OpFunctionEnd
+)";
+
+ const auto env = SPV_ENV_UNIVERSAL_1_5;
+ const auto consumer = nullptr;
+ const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
+ ASSERT_TRUE(IsValid(env, context.get()));
+
+ FactManager fact_manager(context.get());
+
+ ASSERT_FALSE(fact_manager.BlockIsDead(9));
+ ASSERT_FALSE(fact_manager.BlockIsDead(11));
+ ASSERT_FALSE(fact_manager.BlockIsDead(12));
+
+ fact_manager.AddFactBlockIsDead(12);
+
+ ASSERT_FALSE(fact_manager.BlockIsDead(9));
+ ASSERT_FALSE(fact_manager.BlockIsDead(11));
+ ASSERT_TRUE(fact_manager.BlockIsDead(12));
+}
+
+} // namespace
+} // namespace fuzz
+} // namespace spvtools
diff --git a/test/fuzz/fact_manager/irrelevant_value_facts_test.cpp b/test/fuzz/fact_manager/irrelevant_value_facts_test.cpp
new file mode 100644
index 0000000..aae614a
--- /dev/null
+++ b/test/fuzz/fact_manager/irrelevant_value_facts_test.cpp
@@ -0,0 +1,170 @@
+// Copyright (c) 2019 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "source/fuzz/fact_manager/fact_manager.h"
+#include "test/fuzz/fuzz_test_util.h"
+
+namespace spvtools {
+namespace fuzz {
+namespace {
+
+TEST(IrrelevantValueFactsTest, IdIsIrrelevant) {
+ std::string shader = R"(
+ OpCapability Shader
+ %1 = OpExtInstImport "GLSL.std.450"
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %4 "main"
+ OpExecutionMode %4 OriginUpperLeft
+ OpSource ESSL 320
+ %2 = OpTypeVoid
+ %3 = OpTypeFunction %2
+ %6 = OpTypeInt 32 1
+ %12 = OpConstant %6 0
+ %13 = OpConstant %6 1
+ %4 = OpFunction %2 None %3
+ %5 = OpLabel
+ OpReturn
+ OpFunctionEnd
+ )";
+
+ const auto env = SPV_ENV_UNIVERSAL_1_3;
+ const auto consumer = nullptr;
+ const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
+ ASSERT_TRUE(IsValid(env, context.get()));
+
+ FactManager fact_manager(context.get());
+
+ ASSERT_FALSE(fact_manager.IdIsIrrelevant(12));
+ ASSERT_FALSE(fact_manager.IdIsIrrelevant(13));
+
+ fact_manager.AddFactIdIsIrrelevant(12);
+
+ ASSERT_TRUE(fact_manager.IdIsIrrelevant(12));
+ ASSERT_FALSE(fact_manager.IdIsIrrelevant(13));
+}
+
+TEST(IrrelevantValueFactsTest, GetIrrelevantIds) {
+ std::string shader = R"(
+ OpCapability Shader
+ %1 = OpExtInstImport "GLSL.std.450"
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %4 "main"
+ OpExecutionMode %4 OriginUpperLeft
+ OpSource ESSL 320
+ %2 = OpTypeVoid
+ %3 = OpTypeFunction %2
+ %6 = OpTypeInt 32 1
+ %12 = OpConstant %6 0
+ %13 = OpConstant %6 1
+ %14 = OpConstant %6 2
+ %4 = OpFunction %2 None %3
+ %5 = OpLabel
+ OpReturn
+ OpFunctionEnd
+ )";
+
+ const auto env = SPV_ENV_UNIVERSAL_1_3;
+ const auto consumer = nullptr;
+ const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
+ ASSERT_TRUE(IsValid(env, context.get()));
+
+ FactManager fact_manager(context.get());
+
+ ASSERT_EQ(fact_manager.GetIrrelevantIds(), std::unordered_set<uint32_t>({}));
+
+ fact_manager.AddFactIdIsIrrelevant(12);
+
+ ASSERT_EQ(fact_manager.GetIrrelevantIds(),
+ std::unordered_set<uint32_t>({12}));
+
+ fact_manager.AddFactIdIsIrrelevant(13);
+
+ ASSERT_EQ(fact_manager.GetIrrelevantIds(),
+ std::unordered_set<uint32_t>({12, 13}));
+}
+
+TEST(IrrelevantValueFactsTest, IdsFromDeadBlocksAreIrrelevant) {
+ std::string shader = R"(
+ OpCapability Shader
+ %1 = OpExtInstImport "GLSL.std.450"
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %2 "main"
+ OpExecutionMode %2 OriginUpperLeft
+ OpSource ESSL 310
+ %3 = OpTypeVoid
+ %4 = OpTypeFunction %3
+ %5 = OpTypeBool
+ %6 = OpConstantTrue %5
+ %7 = OpTypeInt 32 1
+ %8 = OpTypePointer Function %7
+ %9 = OpConstant %7 1
+ %2 = OpFunction %3 None %4
+ %10 = OpLabel
+ %11 = OpVariable %8 Function
+ OpSelectionMerge %12 None
+ OpBranchConditional %6 %13 %14
+ %13 = OpLabel
+ OpBranch %12
+ %14 = OpLabel
+ %15 = OpCopyObject %8 %11
+ %16 = OpCopyObject %7 %9
+ %17 = OpFunctionCall %3 %18
+ OpBranch %12
+ %12 = OpLabel
+ OpReturn
+ OpFunctionEnd
+ %18 = OpFunction %3 None %4
+ %19 = OpLabel
+ %20 = OpVariable %8 Function
+ %21 = OpCopyObject %7 %9
+ OpReturn
+ OpFunctionEnd
+)";
+
+ const auto env = SPV_ENV_UNIVERSAL_1_5;
+ const auto consumer = nullptr;
+ const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
+ ASSERT_TRUE(IsValid(env, context.get()));
+
+ FactManager fact_manager(context.get());
+
+ ASSERT_FALSE(fact_manager.BlockIsDead(14));
+ ASSERT_FALSE(fact_manager.BlockIsDead(19));
+
+ // Initially no id is irrelevant.
+ ASSERT_FALSE(fact_manager.IdIsIrrelevant(16));
+ ASSERT_FALSE(fact_manager.IdIsIrrelevant(17));
+ ASSERT_EQ(fact_manager.GetIrrelevantIds(), std::unordered_set<uint32_t>({}));
+
+ fact_manager.AddFactBlockIsDead(14);
+
+ // %16 and %17 should now be considered irrelevant.
+ ASSERT_TRUE(fact_manager.IdIsIrrelevant(16));
+ ASSERT_TRUE(fact_manager.IdIsIrrelevant(17));
+ ASSERT_EQ(fact_manager.GetIrrelevantIds(),
+ std::unordered_set<uint32_t>({16, 17}));
+
+ // Similarly for %21.
+ ASSERT_FALSE(fact_manager.IdIsIrrelevant(21));
+
+ fact_manager.AddFactBlockIsDead(19);
+
+ ASSERT_TRUE(fact_manager.IdIsIrrelevant(21));
+ ASSERT_EQ(fact_manager.GetIrrelevantIds(),
+ std::unordered_set<uint32_t>({16, 17, 21}));
+}
+
+} // namespace
+} // namespace fuzz
+} // namespace spvtools
diff --git a/test/fuzz/fact_manager_test.cpp b/test/fuzz/fact_manager_test.cpp
deleted file mode 100644
index 8322c7c..0000000
--- a/test/fuzz/fact_manager_test.cpp
+++ /dev/null
@@ -1,1595 +0,0 @@
-// Copyright (c) 2019 Google LLC
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include "source/fuzz/fact_manager/fact_manager.h"
-
-#include <limits>
-
-#include "source/fuzz/transformation_merge_blocks.h"
-#include "source/fuzz/uniform_buffer_element_descriptor.h"
-#include "test/fuzz/fuzz_test_util.h"
-
-namespace spvtools {
-namespace fuzz {
-namespace {
-
-using opt::analysis::BoolConstant;
-using opt::analysis::FloatConstant;
-using opt::analysis::IntConstant;
-using opt::analysis::ScalarConstant;
-
-using opt::analysis::Bool;
-using opt::analysis::Float;
-using opt::analysis::Integer;
-using opt::analysis::Type;
-
-bool AddFactHelper(
- FactManager* fact_manager, const std::vector<uint32_t>& words,
- const protobufs::UniformBufferElementDescriptor& descriptor) {
- protobufs::FactConstantUniform constant_uniform_fact;
- for (auto word : words) {
- constant_uniform_fact.add_constant_word(word);
- }
- *constant_uniform_fact.mutable_uniform_buffer_element_descriptor() =
- descriptor;
- protobufs::Fact fact;
- *fact.mutable_constant_uniform_fact() = constant_uniform_fact;
- return fact_manager->MaybeAddFact(fact);
-}
-
-TEST(FactManagerTest, ConstantsAvailableViaUniforms) {
- std::string shader = R"(
- OpCapability Shader
- OpCapability Int64
- OpCapability Float64
- %1 = OpExtInstImport "GLSL.std.450"
- OpMemoryModel Logical GLSL450
- OpEntryPoint Fragment %4 "main"
- OpExecutionMode %4 OriginUpperLeft
- OpSource GLSL 450
- OpName %4 "main"
- OpDecorate %100 DescriptorSet 0
- OpDecorate %100 Binding 0
- OpDecorate %200 DescriptorSet 0
- OpDecorate %200 Binding 1
- OpDecorate %300 DescriptorSet 0
- OpDecorate %300 Binding 2
- OpDecorate %400 DescriptorSet 0
- OpDecorate %400 Binding 3
- OpDecorate %500 DescriptorSet 0
- OpDecorate %500 Binding 4
- OpDecorate %600 DescriptorSet 0
- OpDecorate %600 Binding 5
- OpDecorate %700 DescriptorSet 0
- OpDecorate %700 Binding 6
- OpDecorate %800 DescriptorSet 1
- OpDecorate %800 Binding 0
- OpDecorate %900 DescriptorSet 1
- OpDecorate %900 Binding 1
- OpDecorate %1000 DescriptorSet 1
- OpDecorate %1000 Binding 2
- OpDecorate %1100 DescriptorSet 1
- OpDecorate %1100 Binding 3
- OpDecorate %1200 DescriptorSet 1
- OpDecorate %1200 Binding 4
- OpDecorate %1300 DescriptorSet 1
- OpDecorate %1300 Binding 5
- OpDecorate %1400 DescriptorSet 1
- OpDecorate %1400 Binding 6
- OpDecorate %1500 DescriptorSet 2
- OpDecorate %1500 Binding 0
- OpDecorate %1600 DescriptorSet 2
- OpDecorate %1600 Binding 1
- OpDecorate %1700 DescriptorSet 2
- OpDecorate %1700 Binding 2
- OpDecorate %1800 DescriptorSet 2
- OpDecorate %1800 Binding 3
- OpDecorate %1900 DescriptorSet 2
- OpDecorate %1900 Binding 4
- %2 = OpTypeVoid
- %3 = OpTypeFunction %2
- %10 = OpTypeInt 32 0
- %11 = OpTypeInt 32 1
- %12 = OpTypeInt 64 0
- %13 = OpTypeInt 64 1
- %15 = OpTypeFloat 32
- %16 = OpTypeFloat 64
- %17 = OpConstant %11 5
- %18 = OpConstant %11 20
- %19 = OpTypeVector %10 4
- %20 = OpConstant %11 6
- %21 = OpTypeVector %12 4
- %22 = OpConstant %11 10
- %23 = OpTypeVector %11 4
-
- %102 = OpTypeStruct %10 %10 %23
- %101 = OpTypePointer Uniform %102
- %100 = OpVariable %101 Uniform
-
- %203 = OpTypeArray %23 %17
- %202 = OpTypeArray %203 %18
- %201 = OpTypePointer Uniform %202
- %200 = OpVariable %201 Uniform
-
- %305 = OpTypeStruct %16 %16 %16 %11 %16
- %304 = OpTypeStruct %16 %16 %305
- %303 = OpTypeStruct %304
- %302 = OpTypeStruct %10 %303
- %301 = OpTypePointer Uniform %302
- %300 = OpVariable %301 Uniform
-
- %400 = OpVariable %101 Uniform
-
- %500 = OpVariable %201 Uniform
-
- %604 = OpTypeArray %13 %20
- %603 = OpTypeArray %604 %20
- %602 = OpTypeArray %603 %20
- %601 = OpTypePointer Uniform %602
- %600 = OpVariable %601 Uniform
-
- %703 = OpTypeArray %13 %20
- %702 = OpTypeArray %703 %20
- %701 = OpTypePointer Uniform %702
- %700 = OpVariable %701 Uniform
-
- %802 = OpTypeStruct %702 %602 %19 %202 %302
- %801 = OpTypePointer Uniform %802
- %800 = OpVariable %801 Uniform
-
- %902 = OpTypeStruct %702 %802 %19 %202 %302
- %901 = OpTypePointer Uniform %902
- %900 = OpVariable %901 Uniform
-
- %1003 = OpTypeStruct %802
- %1002 = OpTypeArray %1003 %20
- %1001 = OpTypePointer Uniform %1002
- %1000 = OpVariable %1001 Uniform
-
- %1101 = OpTypePointer Uniform %21
- %1100 = OpVariable %1101 Uniform
-
- %1202 = OpTypeArray %21 %20
- %1201 = OpTypePointer Uniform %1202
- %1200 = OpVariable %1201 Uniform
-
- %1302 = OpTypeArray %21 %20
- %1301 = OpTypePointer Uniform %1302
- %1300 = OpVariable %1301 Uniform
-
- %1402 = OpTypeArray %15 %22
- %1401 = OpTypePointer Uniform %1402
- %1400 = OpVariable %1401 Uniform
-
- %1501 = OpTypePointer Uniform %1402
- %1500 = OpVariable %1501 Uniform
-
- %1602 = OpTypeArray %1402 %22
- %1601 = OpTypePointer Uniform %1602
- %1600 = OpVariable %1601 Uniform
-
- %1704 = OpTypeStruct %16 %16 %16
- %1703 = OpTypeArray %1704 %22
- %1702 = OpTypeArray %1703 %22
- %1701 = OpTypePointer Uniform %1702
- %1700 = OpVariable %1701 Uniform
-
- %1800 = OpVariable %1701 Uniform
-
- %1906 = OpTypeStruct %16
- %1905 = OpTypeStruct %1906
- %1904 = OpTypeStruct %1905
- %1903 = OpTypeStruct %1904
- %1902 = OpTypeStruct %1903
- %1901 = OpTypePointer Uniform %1902
- %1900 = OpVariable %1901 Uniform
-
- %4 = OpFunction %2 None %3
- %5 = OpLabel
- OpReturn
- OpFunctionEnd
- )";
-
- const auto env = SPV_ENV_UNIVERSAL_1_3;
- const auto consumer = nullptr;
- const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
- ASSERT_TRUE(IsValid(env, context.get()));
-
- uint32_t buffer_int32_min[1];
- uint32_t buffer_int64_1[2];
- uint32_t buffer_int64_max[2];
- uint32_t buffer_uint64_1[2];
- uint32_t buffer_uint64_max[2];
- uint32_t buffer_float_10[1];
- uint32_t buffer_double_10[2];
- uint32_t buffer_double_20[2];
-
- {
- int32_t temp = std::numeric_limits<int32_t>::min();
- std::memcpy(&buffer_int32_min, &temp, sizeof(temp));
- }
-
- {
- int64_t temp = 1;
- std::memcpy(&buffer_int64_1, &temp, sizeof(temp));
- }
-
- {
- int64_t temp = std::numeric_limits<int64_t>::max();
- std::memcpy(&buffer_int64_max, &temp, sizeof(temp));
- }
-
- {
- uint64_t temp = 1;
- std::memcpy(&buffer_uint64_1, &temp, sizeof(temp));
- }
-
- {
- uint64_t temp = std::numeric_limits<uint64_t>::max();
- std::memcpy(&buffer_uint64_max, &temp, sizeof(temp));
- }
-
- {
- float temp = 10.0f;
- std::memcpy(&buffer_float_10, &temp, sizeof(float));
- }
-
- {
- double temp = 10.0;
- std::memcpy(&buffer_double_10, &temp, sizeof(temp));
- }
-
- {
- double temp = 20.0;
- std::memcpy(&buffer_double_20, &temp, sizeof(temp));
- }
-
- FactManager fact_manager(context.get());
-
- uint32_t type_int32_id = 11;
- uint32_t type_int64_id = 13;
- uint32_t type_uint32_id = 10;
- uint32_t type_uint64_id = 12;
- uint32_t type_float_id = 15;
- uint32_t type_double_id = 16;
-
- // Initially there should be no facts about uniforms.
- ASSERT_TRUE(
- fact_manager.GetConstantsAvailableFromUniformsForType(type_uint32_id)
- .empty());
-
- // In the comments that follow we write v[...][...] to refer to uniform
- // variable v indexed with some given indices, when in practice v is
- // identified via a (descriptor set, binding) pair.
-
- // 100[2][3] == int(1)
- ASSERT_TRUE(AddFactHelper(&fact_manager, {1},
- MakeUniformBufferElementDescriptor(0, 0, {2, 3})));
-
- // 200[1][2][3] == int(1)
- ASSERT_TRUE(AddFactHelper(
- &fact_manager, {1}, MakeUniformBufferElementDescriptor(0, 1, {1, 2, 3})));
-
- // 300[1][0][2][3] == int(1)
- ASSERT_TRUE(
- AddFactHelper(&fact_manager, {1},
- MakeUniformBufferElementDescriptor(0, 2, {1, 0, 2, 3})));
-
- // 400[2][3] = int32_min
- ASSERT_TRUE(AddFactHelper(&fact_manager, {buffer_int32_min[0]},
- MakeUniformBufferElementDescriptor(0, 3, {2, 3})));
-
- // 500[1][2][3] = int32_min
- ASSERT_TRUE(
- AddFactHelper(&fact_manager, {buffer_int32_min[0]},
- MakeUniformBufferElementDescriptor(0, 4, {1, 2, 3})));
-
- // 600[1][2][3] = int64_max
- ASSERT_TRUE(
- AddFactHelper(&fact_manager, {buffer_int64_max[0], buffer_int64_max[1]},
- MakeUniformBufferElementDescriptor(0, 5, {1, 2, 3})));
-
- // 700[1][1] = int64_max
- ASSERT_TRUE(AddFactHelper(&fact_manager,
- {buffer_int64_max[0], buffer_int64_max[1]},
- MakeUniformBufferElementDescriptor(0, 6, {1, 1})));
-
- // 800[2][3] = uint(1)
- ASSERT_TRUE(AddFactHelper(&fact_manager, {1},
- MakeUniformBufferElementDescriptor(1, 0, {2, 3})));
-
- // 900[1][2][3] = uint(1)
- ASSERT_TRUE(AddFactHelper(
- &fact_manager, {1}, MakeUniformBufferElementDescriptor(1, 1, {1, 2, 3})));
-
- // 1000[1][0][2][3] = uint(1)
- ASSERT_TRUE(
- AddFactHelper(&fact_manager, {1},
- MakeUniformBufferElementDescriptor(1, 2, {1, 0, 2, 3})));
-
- // 1100[0] = uint64(1)
- ASSERT_TRUE(AddFactHelper(&fact_manager,
- {buffer_uint64_1[0], buffer_uint64_1[1]},
- MakeUniformBufferElementDescriptor(1, 3, {0})));
-
- // 1200[0][0] = uint64_max
- ASSERT_TRUE(AddFactHelper(&fact_manager,
- {buffer_uint64_max[0], buffer_uint64_max[1]},
- MakeUniformBufferElementDescriptor(1, 4, {0, 0})));
-
- // 1300[1][0] = uint64_max
- ASSERT_TRUE(AddFactHelper(&fact_manager,
- {buffer_uint64_max[0], buffer_uint64_max[1]},
- MakeUniformBufferElementDescriptor(1, 5, {1, 0})));
-
- // 1400[6] = float(10.0)
- ASSERT_TRUE(AddFactHelper(&fact_manager, {buffer_float_10[0]},
- MakeUniformBufferElementDescriptor(1, 6, {6})));
-
- // 1500[7] = float(10.0)
- ASSERT_TRUE(AddFactHelper(&fact_manager, {buffer_float_10[0]},
- MakeUniformBufferElementDescriptor(2, 0, {7})));
-
- // 1600[9][9] = float(10.0)
- ASSERT_TRUE(AddFactHelper(&fact_manager, {buffer_float_10[0]},
- MakeUniformBufferElementDescriptor(2, 1, {9, 9})));
-
- // 1700[9][9][1] = double(10.0)
- ASSERT_TRUE(
- AddFactHelper(&fact_manager, {buffer_double_10[0], buffer_double_10[1]},
- MakeUniformBufferElementDescriptor(2, 2, {9, 9, 1})));
-
- // 1800[9][9][2] = double(10.0)
- ASSERT_TRUE(
- AddFactHelper(&fact_manager, {buffer_double_10[0], buffer_double_10[1]},
- MakeUniformBufferElementDescriptor(2, 3, {9, 9, 2})));
-
- // 1900[0][0][0][0][0] = double(20.0)
- ASSERT_TRUE(
- AddFactHelper(&fact_manager, {buffer_double_20[0], buffer_double_20[1]},
- MakeUniformBufferElementDescriptor(2, 4, {0, 0, 0, 0, 0})));
-
- opt::Instruction::OperandList operands = {
- {SPV_OPERAND_TYPE_LITERAL_INTEGER, {1}}};
- context->module()->AddGlobalValue(MakeUnique<opt::Instruction>(
- context.get(), SpvOpConstant, type_int32_id, 50, operands));
- operands = {{SPV_OPERAND_TYPE_LITERAL_INTEGER, {buffer_int32_min[0]}}};
- context->module()->AddGlobalValue(MakeUnique<opt::Instruction>(
- context.get(), SpvOpConstant, type_int32_id, 51, operands));
- operands = {{SPV_OPERAND_TYPE_LITERAL_INTEGER, {buffer_int64_max[0]}},
- {SPV_OPERAND_TYPE_LITERAL_INTEGER, {buffer_int64_max[1]}}};
- context->module()->AddGlobalValue(MakeUnique<opt::Instruction>(
- context.get(), SpvOpConstant, type_int64_id, 52, operands));
- operands = {{SPV_OPERAND_TYPE_LITERAL_INTEGER, {1}}};
- context->module()->AddGlobalValue(MakeUnique<opt::Instruction>(
- context.get(), SpvOpConstant, type_uint32_id, 53, operands));
- operands = {{SPV_OPERAND_TYPE_LITERAL_INTEGER, {buffer_uint64_1[0]}},
- {SPV_OPERAND_TYPE_LITERAL_INTEGER, {buffer_uint64_1[1]}}};
- context->module()->AddGlobalValue(MakeUnique<opt::Instruction>(
- context.get(), SpvOpConstant, type_uint64_id, 54, operands));
- operands = {{SPV_OPERAND_TYPE_LITERAL_INTEGER, {buffer_uint64_max[0]}},
- {SPV_OPERAND_TYPE_LITERAL_INTEGER, {buffer_uint64_max[1]}}};
- context->module()->AddGlobalValue(MakeUnique<opt::Instruction>(
- context.get(), SpvOpConstant, type_uint64_id, 55, operands));
- operands = {{SPV_OPERAND_TYPE_LITERAL_INTEGER, {buffer_float_10[0]}}};
- context->module()->AddGlobalValue(MakeUnique<opt::Instruction>(
- context.get(), SpvOpConstant, type_float_id, 56, operands));
- operands = {{SPV_OPERAND_TYPE_LITERAL_INTEGER, {buffer_double_10[0]}},
- {SPV_OPERAND_TYPE_LITERAL_INTEGER, {buffer_double_10[1]}}};
- context->module()->AddGlobalValue(MakeUnique<opt::Instruction>(
- context.get(), SpvOpConstant, type_double_id, 57, operands));
- operands = {{SPV_OPERAND_TYPE_LITERAL_INTEGER, {buffer_double_20[0]}},
- {SPV_OPERAND_TYPE_LITERAL_INTEGER, {buffer_double_20[1]}}};
- context->module()->AddGlobalValue(MakeUnique<opt::Instruction>(
- context.get(), SpvOpConstant, type_double_id, 58, operands));
-
- // A duplicate of the constant with id 59.
- operands = {{SPV_OPERAND_TYPE_LITERAL_INTEGER, {1}}};
- context->module()->AddGlobalValue(MakeUnique<opt::Instruction>(
- context.get(), SpvOpConstant, type_int32_id, 59, operands));
-
- context->InvalidateAnalysesExceptFor(opt::IRContext::Analysis::kAnalysisNone);
-
- // Constants 1 and int32_min are available.
- ASSERT_EQ(2,
- fact_manager.GetConstantsAvailableFromUniformsForType(type_int32_id)
- .size());
- // Constant int64_max is available.
- ASSERT_EQ(1,
- fact_manager.GetConstantsAvailableFromUniformsForType(type_int64_id)
- .size());
- // Constant 1u is available.
- ASSERT_EQ(
- 1, fact_manager.GetConstantsAvailableFromUniformsForType(type_uint32_id)
- .size());
- // Constants 1u and uint64_max are available.
- ASSERT_EQ(
- 2, fact_manager.GetConstantsAvailableFromUniformsForType(type_uint64_id)
- .size());
- // Constant 10.0 is available.
- ASSERT_EQ(1,
- fact_manager.GetConstantsAvailableFromUniformsForType(type_float_id)
- .size());
- // Constants 10.0 and 20.0 are available.
- ASSERT_EQ(
- 2, fact_manager.GetConstantsAvailableFromUniformsForType(type_double_id)
- .size());
-
- ASSERT_EQ(std::numeric_limits<int64_t>::max(),
- context->get_constant_mgr()
- ->FindDeclaredConstant(
- fact_manager.GetConstantsAvailableFromUniformsForType(
- type_int64_id)[0])
- ->AsIntConstant()
- ->GetS64());
- ASSERT_EQ(1, context->get_constant_mgr()
- ->FindDeclaredConstant(
- fact_manager.GetConstantsAvailableFromUniformsForType(
- type_uint32_id)[0])
- ->AsIntConstant()
- ->GetU32());
- ASSERT_EQ(10.0f,
- context->get_constant_mgr()
- ->FindDeclaredConstant(
- fact_manager.GetConstantsAvailableFromUniformsForType(
- type_float_id)[0])
- ->AsFloatConstant()
- ->GetFloat());
- const std::vector<uint32_t>& double_constant_ids =
- fact_manager.GetConstantsAvailableFromUniformsForType(type_double_id);
- ASSERT_EQ(10.0, context->get_constant_mgr()
- ->FindDeclaredConstant(double_constant_ids[0])
- ->AsFloatConstant()
- ->GetDouble());
- ASSERT_EQ(20.0, context->get_constant_mgr()
- ->FindDeclaredConstant(double_constant_ids[1])
- ->AsFloatConstant()
- ->GetDouble());
-
- const std::vector<protobufs::UniformBufferElementDescriptor>
- descriptors_for_double_10 =
- fact_manager.GetUniformDescriptorsForConstant(double_constant_ids[0]);
- ASSERT_EQ(2, descriptors_for_double_10.size());
- {
- auto temp = MakeUniformBufferElementDescriptor(2, 2, {9, 9, 1});
- ASSERT_TRUE(UniformBufferElementDescriptorEquals()(
- &temp, &descriptors_for_double_10[0]));
- }
- {
- auto temp = MakeUniformBufferElementDescriptor(2, 3, {9, 9, 2});
- ASSERT_TRUE(UniformBufferElementDescriptorEquals()(
- &temp, &descriptors_for_double_10[1]));
- }
- const std::vector<protobufs::UniformBufferElementDescriptor>
- descriptors_for_double_20 =
- fact_manager.GetUniformDescriptorsForConstant(double_constant_ids[1]);
- ASSERT_EQ(1, descriptors_for_double_20.size());
- {
- auto temp = MakeUniformBufferElementDescriptor(2, 4, {0, 0, 0, 0, 0});
- ASSERT_TRUE(UniformBufferElementDescriptorEquals()(
- &temp, &descriptors_for_double_20[0]));
- }
-
- auto constant_1_id = fact_manager.GetConstantFromUniformDescriptor(
- MakeUniformBufferElementDescriptor(2, 3, {9, 9, 2}));
- ASSERT_TRUE(constant_1_id);
-
- auto constant_2_id = fact_manager.GetConstantFromUniformDescriptor(
- MakeUniformBufferElementDescriptor(2, 4, {0, 0, 0, 0, 0}));
- ASSERT_TRUE(constant_2_id);
-
- ASSERT_EQ(double_constant_ids[0], constant_1_id);
-
- ASSERT_EQ(double_constant_ids[1], constant_2_id);
-}
-
-TEST(FactManagerTest, TwoConstantsWithSameValue) {
- std::string shader = R"(
- OpCapability Shader
- %1 = OpExtInstImport "GLSL.std.450"
- OpMemoryModel Logical GLSL450
- OpEntryPoint Fragment %4 "main"
- OpExecutionMode %4 OriginUpperLeft
- OpSource ESSL 310
- OpName %4 "main"
- OpName %8 "x"
- OpName %10 "buf"
- OpMemberName %10 0 "a"
- OpName %12 ""
- OpDecorate %8 RelaxedPrecision
- OpMemberDecorate %10 0 RelaxedPrecision
- OpMemberDecorate %10 0 Offset 0
- OpDecorate %10 Block
- OpDecorate %12 DescriptorSet 0
- OpDecorate %12 Binding 0
- %2 = OpTypeVoid
- %3 = OpTypeFunction %2
- %6 = OpTypeInt 32 1
- %7 = OpTypePointer Function %6
- %9 = OpConstant %6 1
- %20 = OpConstant %6 1
- %10 = OpTypeStruct %6
- %11 = OpTypePointer Uniform %10
- %12 = OpVariable %11 Uniform
- %4 = OpFunction %2 None %3
- %5 = OpLabel
- %8 = OpVariable %7 Function
- OpStore %8 %9
- OpReturn
- OpFunctionEnd
- )";
-
- const auto env = SPV_ENV_UNIVERSAL_1_3;
- const auto consumer = nullptr;
- const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
- ASSERT_TRUE(IsValid(env, context.get()));
-
- FactManager fact_manager(context.get());
-
- auto uniform_buffer_element_descriptor =
- MakeUniformBufferElementDescriptor(0, 0, {0});
-
- // (0, 0, [0]) = int(1)
- ASSERT_TRUE(
- AddFactHelper(&fact_manager, {1}, uniform_buffer_element_descriptor));
- auto constants = fact_manager.GetConstantsAvailableFromUniformsForType(6);
- ASSERT_EQ(1, constants.size());
- ASSERT_TRUE(constants[0] == 9 || constants[0] == 20);
-
- auto constant = fact_manager.GetConstantFromUniformDescriptor(
- uniform_buffer_element_descriptor);
- ASSERT_TRUE(constant == 9 || constant == 20);
-
- // Because the constants with ids 9 and 20 are equal, we should get the same
- // single uniform buffer element descriptor when we look up the descriptors
- // for either one of them.
- for (auto constant_id : {9u, 20u}) {
- auto descriptors =
- fact_manager.GetUniformDescriptorsForConstant(constant_id);
- ASSERT_EQ(1, descriptors.size());
- ASSERT_TRUE(UniformBufferElementDescriptorEquals()(
- &uniform_buffer_element_descriptor, &descriptors[0]));
- }
-}
-
-TEST(FactManagerTest, NonFiniteFactsAreNotValid) {
- std::string shader = R"(
- OpCapability Shader
- OpCapability Float64
- %1 = OpExtInstImport "GLSL.std.450"
- OpMemoryModel Logical GLSL450
- OpEntryPoint Fragment %4 "main"
- OpExecutionMode %4 OriginUpperLeft
- OpSource ESSL 310
- OpName %4 "main"
- OpName %7 "buf"
- OpMemberName %7 0 "f"
- OpMemberName %7 1 "d"
- OpName %9 ""
- OpMemberDecorate %7 0 Offset 0
- OpMemberDecorate %7 1 Offset 8
- OpDecorate %7 Block
- OpDecorate %9 DescriptorSet 0
- OpDecorate %9 Binding 0
- %2 = OpTypeVoid
- %3 = OpTypeFunction %2
- %6 = OpTypeFloat 32
- %10 = OpTypeFloat 64
- %7 = OpTypeStruct %6 %10
- %8 = OpTypePointer Uniform %7
- %9 = OpVariable %8 Uniform
- %4 = OpFunction %2 None %3
- %5 = OpLabel
- OpReturn
- OpFunctionEnd
- )";
-
- const auto env = SPV_ENV_UNIVERSAL_1_3;
- const auto consumer = nullptr;
- const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
- ASSERT_TRUE(IsValid(env, context.get()));
-
- FactManager fact_manager(context.get());
- auto uniform_buffer_element_descriptor_f =
- MakeUniformBufferElementDescriptor(0, 0, {0});
-
- auto uniform_buffer_element_descriptor_d =
- MakeUniformBufferElementDescriptor(0, 0, {1});
-
- if (std::numeric_limits<float>::has_infinity) {
- // f == +inf
- float positive_infinity_float = std::numeric_limits<float>::infinity();
- uint32_t words[1];
- memcpy(words, &positive_infinity_float, sizeof(float));
- ASSERT_FALSE(AddFactHelper(&fact_manager, {words[0]},
- uniform_buffer_element_descriptor_f));
- // f == -inf
- float negative_infinity_float = std::numeric_limits<float>::infinity();
- memcpy(words, &negative_infinity_float, sizeof(float));
- ASSERT_FALSE(AddFactHelper(&fact_manager, {words[0]},
- uniform_buffer_element_descriptor_f));
- }
-
- if (std::numeric_limits<float>::has_quiet_NaN) {
- // f == NaN
- float quiet_nan_float = std::numeric_limits<float>::quiet_NaN();
- uint32_t words[1];
- memcpy(words, &quiet_nan_float, sizeof(float));
- ASSERT_FALSE(AddFactHelper(&fact_manager, {words[0]},
- uniform_buffer_element_descriptor_f));
- }
-
- if (std::numeric_limits<double>::has_infinity) {
- // d == +inf
- double positive_infinity_double = std::numeric_limits<double>::infinity();
- uint32_t words[2];
- memcpy(words, &positive_infinity_double, sizeof(double));
- ASSERT_FALSE(AddFactHelper(&fact_manager, {words[0], words[1]},
- uniform_buffer_element_descriptor_d));
- // d == -inf
- double negative_infinity_double = -std::numeric_limits<double>::infinity();
- memcpy(words, &negative_infinity_double, sizeof(double));
- ASSERT_FALSE(AddFactHelper(&fact_manager, {words[0], words[1]},
- uniform_buffer_element_descriptor_d));
- }
-
- if (std::numeric_limits<double>::has_quiet_NaN) {
- // d == NaN
- double quiet_nan_double = std::numeric_limits<double>::quiet_NaN();
- uint32_t words[2];
- memcpy(words, &quiet_nan_double, sizeof(double));
- ASSERT_FALSE(AddFactHelper(&fact_manager, {words[0], words[1]},
- uniform_buffer_element_descriptor_d));
- }
-}
-
-TEST(FactManagerTest, AmbiguousFact) {
- // This test came from the following GLSL:
- //
- // #version 310 es
- //
- // precision highp float;
- //
- // layout(set = 0, binding = 0) uniform buf {
- // float f;
- // };
- //
- // layout(set = 0, binding = 0) uniform buf2 {
- // float g;
- // };
- //
- // void main() {
- //
- // }
-
- std::string shader = R"(
- OpCapability Shader
- %1 = OpExtInstImport "GLSL.std.450"
- OpMemoryModel Logical GLSL450
- OpEntryPoint Fragment %4 "main"
- OpExecutionMode %4 OriginUpperLeft
- OpSource ESSL 310
- OpName %4 "main"
- OpName %7 "buf"
- OpMemberName %7 0 "f"
- OpName %9 ""
- OpName %10 "buf2"
- OpMemberName %10 0 "g"
- OpName %12 ""
- OpMemberDecorate %7 0 Offset 0
- OpDecorate %7 Block
- OpDecorate %9 DescriptorSet 0
- OpDecorate %9 Binding 0
- OpMemberDecorate %10 0 Offset 0
- OpDecorate %10 Block
- OpDecorate %12 DescriptorSet 0
- OpDecorate %12 Binding 0
- %2 = OpTypeVoid
- %3 = OpTypeFunction %2
- %6 = OpTypeFloat 32
- %7 = OpTypeStruct %6
- %8 = OpTypePointer Uniform %7
- %9 = OpVariable %8 Uniform
- %10 = OpTypeStruct %6
- %11 = OpTypePointer Uniform %10
- %12 = OpVariable %11 Uniform
- %4 = OpFunction %2 None %3
- %5 = OpLabel
- OpReturn
- OpFunctionEnd
- )";
-
- const auto env = SPV_ENV_UNIVERSAL_1_3;
- const auto consumer = nullptr;
- const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
- ASSERT_TRUE(IsValid(env, context.get()));
-
- FactManager fact_manager(context.get());
- auto uniform_buffer_element_descriptor =
- MakeUniformBufferElementDescriptor(0, 0, {0});
-
- // The fact cannot be added because it is ambiguous: there are two uniforms
- // with descriptor set 0 and binding 0.
- ASSERT_FALSE(
- AddFactHelper(&fact_manager, {1}, uniform_buffer_element_descriptor));
-}
-
-TEST(FactManagerTest, RecursiveAdditionOfFacts) {
- std::string shader = R"(
- OpCapability Shader
- %1 = OpExtInstImport "GLSL.std.450"
- OpMemoryModel Logical GLSL450
- OpEntryPoint Fragment %12 "main"
- OpExecutionMode %12 OriginUpperLeft
- OpSource ESSL 310
- %2 = OpTypeVoid
- %3 = OpTypeFunction %2
- %6 = OpTypeFloat 32
- %7 = OpTypeVector %6 4
- %8 = OpTypeMatrix %7 4
- %9 = OpConstant %6 0
- %10 = OpConstantComposite %7 %9 %9 %9 %9
- %11 = OpConstantComposite %8 %10 %10 %10 %10
- %12 = OpFunction %2 None %3
- %13 = OpLabel
- OpReturn
- OpFunctionEnd
- )";
-
- const auto env = SPV_ENV_UNIVERSAL_1_3;
- const auto consumer = nullptr;
- const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
- ASSERT_TRUE(IsValid(env, context.get()));
-
- FactManager fact_manager(context.get());
-
- fact_manager.AddFactDataSynonym(MakeDataDescriptor(10, {}),
- MakeDataDescriptor(11, {2}));
-
- ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(10, {}),
- MakeDataDescriptor(11, {2})));
- ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(10, {0}),
- MakeDataDescriptor(11, {2, 0})));
- ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(10, {1}),
- MakeDataDescriptor(11, {2, 1})));
- ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(10, {2}),
- MakeDataDescriptor(11, {2, 2})));
- ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(10, {3}),
- MakeDataDescriptor(11, {2, 3})));
-}
-
-TEST(FactManagerTest, CorollaryConversionFacts) {
- std::string shader = R"(
- OpCapability Shader
- %1 = OpExtInstImport "GLSL.std.450"
- OpMemoryModel Logical GLSL450
- OpEntryPoint Fragment %12 "main"
- OpExecutionMode %12 OriginUpperLeft
- OpSource ESSL 310
- %2 = OpTypeVoid
- %3 = OpTypeFunction %2
- %6 = OpTypeInt 32 1
- %7 = OpTypeInt 32 0
- %8 = OpTypeVector %6 2
- %9 = OpTypeVector %7 2
- %10 = OpTypeFloat 32
- %11 = OpTypeVector %10 2
- %15 = OpConstant %6 24 ; synonym of %16
- %16 = OpConstant %6 24
- %17 = OpConstant %7 24 ; synonym of %18
- %18 = OpConstant %7 24
- %19 = OpConstantComposite %8 %15 %15 ; synonym of %20
- %20 = OpConstantComposite %8 %16 %16
- %21 = OpConstantComposite %9 %17 %17 ; synonym of %22
- %22 = OpConstantComposite %9 %18 %18
- %23 = OpConstantComposite %8 %15 %15 ; not a synonym of %19
- %12 = OpFunction %2 None %3
- %13 = OpLabel
- %24 = OpConvertSToF %10 %15 ; synonym of %25
- %25 = OpConvertSToF %10 %16
- %26 = OpConvertUToF %10 %17 ; not a synonym of %27 (different opcode)
- %27 = OpConvertSToF %10 %18
- %28 = OpConvertUToF %11 %19 ; synonym of %29
- %29 = OpConvertUToF %11 %20
- %30 = OpConvertSToF %11 %21 ; not a synonym of %31 (different opcode)
- %31 = OpConvertUToF %11 %22
- %32 = OpConvertUToF %11 %23 ; not a synonym of %28 (operand is not synonymous)
- OpReturn
- OpFunctionEnd
- )";
-
- const auto env = SPV_ENV_UNIVERSAL_1_3;
- const auto consumer = nullptr;
- const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
- ASSERT_TRUE(IsValid(env, context.get()));
-
- FactManager fact_manager(context.get());
-
- // Add equation facts
- fact_manager.AddFactIdEquation(24, SpvOpConvertSToF, {15});
- fact_manager.AddFactIdEquation(25, SpvOpConvertSToF, {16});
- fact_manager.AddFactIdEquation(26, SpvOpConvertUToF, {17});
- fact_manager.AddFactIdEquation(27, SpvOpConvertSToF, {18});
- fact_manager.AddFactIdEquation(28, SpvOpConvertUToF, {19});
- fact_manager.AddFactIdEquation(29, SpvOpConvertUToF, {20});
- fact_manager.AddFactIdEquation(30, SpvOpConvertSToF, {21});
- fact_manager.AddFactIdEquation(31, SpvOpConvertUToF, {22});
- fact_manager.AddFactIdEquation(32, SpvOpConvertUToF, {23});
-
- fact_manager.AddFactDataSynonym(MakeDataDescriptor(15, {}),
- MakeDataDescriptor(16, {}));
- ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(24, {}),
- MakeDataDescriptor(25, {})));
-
- fact_manager.AddFactDataSynonym(MakeDataDescriptor(17, {}),
- MakeDataDescriptor(18, {}));
- ASSERT_FALSE(fact_manager.IsSynonymous(MakeDataDescriptor(26, {}),
- MakeDataDescriptor(27, {})));
-
- fact_manager.AddFactDataSynonym(MakeDataDescriptor(19, {}),
- MakeDataDescriptor(20, {}));
- ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(28, {}),
- MakeDataDescriptor(29, {})));
-
- fact_manager.AddFactDataSynonym(MakeDataDescriptor(21, {}),
- MakeDataDescriptor(22, {}));
- ASSERT_FALSE(fact_manager.IsSynonymous(MakeDataDescriptor(30, {}),
- MakeDataDescriptor(31, {})));
-
- ASSERT_FALSE(fact_manager.IsSynonymous(MakeDataDescriptor(32, {}),
- MakeDataDescriptor(28, {})));
- fact_manager.AddFactDataSynonym(MakeDataDescriptor(23, {}),
- MakeDataDescriptor(19, {}));
- ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(32, {}),
- MakeDataDescriptor(28, {})));
- ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(32, {}),
- MakeDataDescriptor(29, {})));
-}
-
-TEST(FactManagerTest, HandlesCorollariesWithInvalidIds) {
- std::string shader = R"(
- OpCapability Shader
- %1 = OpExtInstImport "GLSL.std.450"
- OpMemoryModel Logical GLSL450
- OpEntryPoint Fragment %12 "main"
- OpExecutionMode %12 OriginUpperLeft
- OpSource ESSL 310
- %2 = OpTypeVoid
- %3 = OpTypeFunction %2
- %6 = OpTypeFloat 32
- %8 = OpTypeInt 32 1
- %9 = OpConstant %8 3
- %12 = OpFunction %2 None %3
- %13 = OpLabel
- %14 = OpConvertSToF %6 %9
- OpBranch %16
- %16 = OpLabel
- %17 = OpPhi %6 %14 %13
- %15 = OpConvertSToF %6 %9
- %18 = OpConvertSToF %6 %9
- OpReturn
- OpFunctionEnd
- )";
-
- const auto env = SPV_ENV_UNIVERSAL_1_3;
- const auto consumer = nullptr;
- const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
- ASSERT_TRUE(IsValid(env, context.get()));
-
- spvtools::ValidatorOptions validator_options;
- TransformationContext transformation_context(
- MakeUnique<FactManager>(context.get()), validator_options);
-
- // Add required facts.
- transformation_context.GetFactManager()->AddFactIdEquation(
- 14, SpvOpConvertSToF, {9});
- transformation_context.GetFactManager()->AddFactDataSynonym(
- MakeDataDescriptor(14, {}), MakeDataDescriptor(17, {}));
-
- // Apply TransformationMergeBlocks which will remove %17 from the module.
- TransformationMergeBlocks transformation(16);
- ASSERT_TRUE(
- transformation.IsApplicable(context.get(), transformation_context));
- transformation.Apply(context.get(), &transformation_context);
- ASSERT_TRUE(IsValid(env, context.get()));
-
- ASSERT_EQ(context->get_def_use_mgr()->GetDef(17), nullptr);
-
- // Add another equation.
- transformation_context.GetFactManager()->AddFactIdEquation(
- 15, SpvOpConvertSToF, {9});
-
- // Check that two ids are synonymous even though one of them doesn't exist in
- // the module (%17).
- ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
- MakeDataDescriptor(15, {}), MakeDataDescriptor(17, {})));
- ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
- MakeDataDescriptor(15, {}), MakeDataDescriptor(14, {})));
-
- // Remove some instructions from the module. At this point, the equivalence
- // class of %14 has no valid members.
- ASSERT_TRUE(context->KillDef(14));
- ASSERT_TRUE(context->KillDef(15));
-
- transformation_context.GetFactManager()->AddFactIdEquation(
- 18, SpvOpConvertSToF, {9});
-
- // We don't create synonyms if at least one of the equivalence classes has no
- // valid members.
- ASSERT_FALSE(transformation_context.GetFactManager()->IsSynonymous(
- MakeDataDescriptor(14, {}), MakeDataDescriptor(18, {})));
-}
-
-TEST(FactManagerTest, LogicalNotEquationFacts) {
- std::string shader = R"(
- OpCapability Shader
- %1 = OpExtInstImport "GLSL.std.450"
- OpMemoryModel Logical GLSL450
- OpEntryPoint Fragment %12 "main"
- OpExecutionMode %12 OriginUpperLeft
- OpSource ESSL 310
- %2 = OpTypeVoid
- %3 = OpTypeFunction %2
- %6 = OpTypeBool
- %7 = OpConstantTrue %6
- %12 = OpFunction %2 None %3
- %13 = OpLabel
- %14 = OpLogicalNot %6 %7
- %15 = OpCopyObject %6 %7
- %16 = OpCopyObject %6 %14
- %17 = OpLogicalNot %6 %16
- OpReturn
- OpFunctionEnd
- )";
-
- const auto env = SPV_ENV_UNIVERSAL_1_3;
- const auto consumer = nullptr;
- const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
- ASSERT_TRUE(IsValid(env, context.get()));
-
- FactManager fact_manager(context.get());
-
- fact_manager.AddFactDataSynonym(MakeDataDescriptor(15, {}),
- MakeDataDescriptor(7, {}));
- fact_manager.AddFactDataSynonym(MakeDataDescriptor(16, {}),
- MakeDataDescriptor(14, {}));
- fact_manager.AddFactIdEquation(14, SpvOpLogicalNot, {7});
- fact_manager.AddFactIdEquation(17, SpvOpLogicalNot, {16});
-
- ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(15, {}),
- MakeDataDescriptor(7, {})));
- ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(17, {}),
- MakeDataDescriptor(7, {})));
- ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(15, {}),
- MakeDataDescriptor(17, {})));
- ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(16, {}),
- MakeDataDescriptor(14, {})));
-}
-
-TEST(FactManagerTest, SignedNegateEquationFacts) {
- std::string shader = R"(
- OpCapability Shader
- %1 = OpExtInstImport "GLSL.std.450"
- OpMemoryModel Logical GLSL450
- OpEntryPoint Fragment %12 "main"
- OpExecutionMode %12 OriginUpperLeft
- OpSource ESSL 310
- %2 = OpTypeVoid
- %3 = OpTypeFunction %2
- %6 = OpTypeInt 32 1
- %7 = OpConstant %6 24
- %12 = OpFunction %2 None %3
- %13 = OpLabel
- %14 = OpSNegate %6 %7
- %15 = OpSNegate %6 %14
- OpReturn
- OpFunctionEnd
- )";
-
- const auto env = SPV_ENV_UNIVERSAL_1_3;
- const auto consumer = nullptr;
- const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
- ASSERT_TRUE(IsValid(env, context.get()));
-
- FactManager fact_manager(context.get());
-
- fact_manager.AddFactIdEquation(14, SpvOpSNegate, {7});
- fact_manager.AddFactIdEquation(15, SpvOpSNegate, {14});
-
- ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(7, {}),
- MakeDataDescriptor(15, {})));
-}
-
-TEST(FactManagerTest, AddSubNegateFacts1) {
- std::string shader = R"(
- OpCapability Shader
- %1 = OpExtInstImport "GLSL.std.450"
- OpMemoryModel Logical GLSL450
- OpEntryPoint Fragment %12 "main"
- OpExecutionMode %12 OriginUpperLeft
- OpSource ESSL 310
- %2 = OpTypeVoid
- %3 = OpTypeFunction %2
- %6 = OpTypeInt 32 1
- %15 = OpConstant %6 24
- %16 = OpConstant %6 37
- %12 = OpFunction %2 None %3
- %13 = OpLabel
- %14 = OpIAdd %6 %15 %16
- %17 = OpCopyObject %6 %15
- %18 = OpCopyObject %6 %16
- %19 = OpISub %6 %14 %18 ; ==> synonymous(%19, %15)
- %20 = OpISub %6 %14 %17 ; ==> synonymous(%20, %16)
- %21 = OpCopyObject %6 %14
- %22 = OpISub %6 %16 %21
- %23 = OpCopyObject %6 %22
- %24 = OpSNegate %6 %23 ; ==> synonymous(%24, %15)
- OpReturn
- OpFunctionEnd
- )";
-
- const auto env = SPV_ENV_UNIVERSAL_1_3;
- const auto consumer = nullptr;
- const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
- ASSERT_TRUE(IsValid(env, context.get()));
-
- FactManager fact_manager(context.get());
-
- fact_manager.AddFactIdEquation(14, SpvOpIAdd, {15, 16});
- fact_manager.AddFactDataSynonym(MakeDataDescriptor(17, {}),
- MakeDataDescriptor(15, {}));
- fact_manager.AddFactDataSynonym(MakeDataDescriptor(18, {}),
- MakeDataDescriptor(16, {}));
- fact_manager.AddFactIdEquation(19, SpvOpISub, {14, 18});
- fact_manager.AddFactIdEquation(20, SpvOpISub, {14, 17});
- fact_manager.AddFactDataSynonym(MakeDataDescriptor(21, {}),
- MakeDataDescriptor(14, {}));
- fact_manager.AddFactIdEquation(22, SpvOpISub, {16, 21});
- fact_manager.AddFactDataSynonym(MakeDataDescriptor(23, {}),
- MakeDataDescriptor(22, {}));
- fact_manager.AddFactIdEquation(24, SpvOpSNegate, {23});
-
- ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(19, {}),
- MakeDataDescriptor(15, {})));
- ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(20, {}),
- MakeDataDescriptor(16, {})));
- ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(24, {}),
- MakeDataDescriptor(15, {})));
-}
-
-TEST(FactManagerTest, AddSubNegateFacts2) {
- std::string shader = R"(
- OpCapability Shader
- %1 = OpExtInstImport "GLSL.std.450"
- OpMemoryModel Logical GLSL450
- OpEntryPoint Fragment %12 "main"
- OpExecutionMode %12 OriginUpperLeft
- OpSource ESSL 310
- %2 = OpTypeVoid
- %3 = OpTypeFunction %2
- %6 = OpTypeInt 32 1
- %15 = OpConstant %6 24
- %16 = OpConstant %6 37
- %12 = OpFunction %2 None %3
- %13 = OpLabel
- %14 = OpISub %6 %15 %16
- %17 = OpIAdd %6 %14 %16 ; ==> synonymous(%17, %15)
- %18 = OpIAdd %6 %16 %14 ; ==> synonymous(%17, %18, %15)
- %19 = OpISub %6 %14 %15
- %20 = OpSNegate %6 %19 ; ==> synonymous(%20, %16)
- %21 = OpISub %6 %14 %19 ; ==> synonymous(%21, %15)
- %22 = OpISub %6 %14 %18
- %23 = OpSNegate %6 %22 ; ==> synonymous(%23, %16)
- OpReturn
- OpFunctionEnd
- )";
-
- const auto env = SPV_ENV_UNIVERSAL_1_3;
- const auto consumer = nullptr;
- const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
- ASSERT_TRUE(IsValid(env, context.get()));
-
- FactManager fact_manager(context.get());
-
- fact_manager.AddFactIdEquation(14, SpvOpISub, {15, 16});
- fact_manager.AddFactIdEquation(17, SpvOpIAdd, {14, 16});
-
- ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(17, {}),
- MakeDataDescriptor(15, {})));
-
- fact_manager.AddFactIdEquation(18, SpvOpIAdd, {16, 14});
-
- ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(18, {}),
- MakeDataDescriptor(15, {})));
- ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(17, {}),
- MakeDataDescriptor(18, {})));
-
- fact_manager.AddFactIdEquation(19, SpvOpISub, {14, 15});
- fact_manager.AddFactIdEquation(20, SpvOpSNegate, {19});
-
- ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(20, {}),
- MakeDataDescriptor(16, {})));
-
- fact_manager.AddFactIdEquation(21, SpvOpISub, {14, 19});
- ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(21, {}),
- MakeDataDescriptor(15, {})));
-
- fact_manager.AddFactIdEquation(22, SpvOpISub, {14, 18});
- fact_manager.AddFactIdEquation(23, SpvOpSNegate, {22});
- ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(23, {}),
- MakeDataDescriptor(16, {})));
-}
-
-TEST(FactManagerTest, ConversionEquations) {
- std::string shader = R"(
- OpCapability Shader
- %1 = OpExtInstImport "GLSL.std.450"
- OpMemoryModel Logical GLSL450
- OpEntryPoint Fragment %12 "main"
- OpExecutionMode %12 OriginUpperLeft
- OpSource ESSL 310
- %2 = OpTypeVoid
- %3 = OpTypeFunction %2
- %4 = OpTypeInt 32 1
- %5 = OpTypeInt 32 0
- %6 = OpTypeFloat 32
- %14 = OpTypeVector %4 2
- %15 = OpTypeVector %5 2
- %24 = OpTypeVector %6 2
- %16 = OpConstant %4 32 ; synonym of %17
- %17 = OpConstant %4 32
- %18 = OpConstant %5 32 ; synonym of %19
- %19 = OpConstant %5 32
- %20 = OpConstantComposite %14 %16 %16 ; synonym of %21
- %21 = OpConstantComposite %14 %17 %17
- %22 = OpConstantComposite %15 %18 %18 ; synonym of %23
- %23 = OpConstantComposite %15 %19 %19
- %12 = OpFunction %2 None %3
- %13 = OpLabel
- %25 = OpConvertUToF %6 %16 ; synonym of %26
- %26 = OpConvertUToF %6 %17
- %27 = OpConvertSToF %24 %20 ; not a synonym of %28 (wrong opcode)
- %28 = OpConvertUToF %24 %21
- %29 = OpConvertSToF %6 %18 ; not a synonym of %30 (wrong opcode)
- %30 = OpConvertUToF %6 %19
- %31 = OpConvertSToF %24 %22 ; synonym of %32
- %32 = OpConvertSToF %24 %23
- %33 = OpConvertUToF %6 %17 ; synonym of %26
- %34 = OpConvertSToF %24 %23 ; synonym of %32
- OpReturn
- OpFunctionEnd
- )";
-
- const auto env = SPV_ENV_UNIVERSAL_1_3;
- const auto consumer = nullptr;
- const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
- ASSERT_TRUE(IsValid(env, context.get()));
-
- FactManager fact_manager(context.get());
-
- fact_manager.AddFactDataSynonym(MakeDataDescriptor(16, {}),
- MakeDataDescriptor(17, {}));
- fact_manager.AddFactDataSynonym(MakeDataDescriptor(18, {}),
- MakeDataDescriptor(19, {}));
- fact_manager.AddFactDataSynonym(MakeDataDescriptor(20, {}),
- MakeDataDescriptor(21, {}));
- fact_manager.AddFactDataSynonym(MakeDataDescriptor(22, {}),
- MakeDataDescriptor(23, {}));
-
- fact_manager.AddFactIdEquation(25, SpvOpConvertUToF, {16});
- fact_manager.AddFactIdEquation(26, SpvOpConvertUToF, {17});
- ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(25, {}),
- MakeDataDescriptor(26, {})));
-
- fact_manager.AddFactIdEquation(27, SpvOpConvertSToF, {20});
- fact_manager.AddFactIdEquation(28, SpvOpConvertUToF, {21});
- ASSERT_FALSE(fact_manager.IsSynonymous(MakeDataDescriptor(27, {}),
- MakeDataDescriptor(28, {})));
-
- fact_manager.AddFactIdEquation(29, SpvOpConvertSToF, {18});
- fact_manager.AddFactIdEquation(30, SpvOpConvertUToF, {19});
- ASSERT_FALSE(fact_manager.IsSynonymous(MakeDataDescriptor(29, {}),
- MakeDataDescriptor(30, {})));
-
- fact_manager.AddFactIdEquation(31, SpvOpConvertSToF, {22});
- fact_manager.AddFactIdEquation(32, SpvOpConvertSToF, {23});
- ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(31, {}),
- MakeDataDescriptor(32, {})));
-
- fact_manager.AddFactIdEquation(33, SpvOpConvertUToF, {17});
- ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(33, {}),
- MakeDataDescriptor(26, {})));
-
- fact_manager.AddFactIdEquation(34, SpvOpConvertSToF, {23});
- ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(32, {}),
- MakeDataDescriptor(34, {})));
-}
-
-TEST(FactManagerTest, BitcastEquationFacts) {
- std::string shader = R"(
- OpCapability Shader
- %1 = OpExtInstImport "GLSL.std.450"
- OpMemoryModel Logical GLSL450
- OpEntryPoint Fragment %12 "main"
- OpExecutionMode %12 OriginUpperLeft
- OpSource ESSL 310
- %2 = OpTypeVoid
- %3 = OpTypeFunction %2
- %4 = OpTypeInt 32 1
- %5 = OpTypeInt 32 0
- %8 = OpTypeFloat 32
- %9 = OpTypeVector %4 2
- %10 = OpTypeVector %5 2
- %11 = OpTypeVector %8 2
- %6 = OpConstant %4 23
- %7 = OpConstant %5 23
- %19 = OpConstant %8 23
- %20 = OpConstantComposite %9 %6 %6
- %21 = OpConstantComposite %10 %7 %7
- %22 = OpConstantComposite %11 %19 %19
- %12 = OpFunction %2 None %3
- %13 = OpLabel
- %30 = OpBitcast %8 %6
- %31 = OpBitcast %5 %6
- %32 = OpBitcast %8 %7
- %33 = OpBitcast %4 %7
- %34 = OpBitcast %4 %19
- %35 = OpBitcast %5 %19
- %36 = OpBitcast %10 %20
- %37 = OpBitcast %11 %20
- %38 = OpBitcast %9 %21
- %39 = OpBitcast %11 %21
- %40 = OpBitcast %9 %22
- %41 = OpBitcast %10 %22
- OpReturn
- OpFunctionEnd
- )";
-
- const auto env = SPV_ENV_UNIVERSAL_1_3;
- const auto consumer = nullptr;
- const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
- ASSERT_TRUE(IsValid(env, context.get()));
-
- FactManager fact_manager(context.get());
-
- uint32_t lhs_id = 30;
- for (uint32_t rhs_id : {6, 6, 7, 7, 19, 19, 20, 20, 21, 21, 22, 22}) {
- fact_manager.AddFactIdEquation(lhs_id, SpvOpBitcast, {rhs_id});
- ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(lhs_id, {}),
- MakeDataDescriptor(rhs_id, {})));
- ++lhs_id;
- }
-}
-
-TEST(FactManagerTest, EquationAndEquivalenceFacts) {
- std::string shader = R"(
- OpCapability Shader
- %1 = OpExtInstImport "GLSL.std.450"
- OpMemoryModel Logical GLSL450
- OpEntryPoint Fragment %12 "main"
- OpExecutionMode %12 OriginUpperLeft
- OpSource ESSL 310
- %2 = OpTypeVoid
- %3 = OpTypeFunction %2
- %6 = OpTypeInt 32 1
- %15 = OpConstant %6 24
- %16 = OpConstant %6 37
- %12 = OpFunction %2 None %3
- %13 = OpLabel
- %14 = OpISub %6 %15 %16
- %114 = OpCopyObject %6 %14
- %17 = OpIAdd %6 %114 %16 ; ==> synonymous(%17, %15)
- %18 = OpIAdd %6 %16 %114 ; ==> synonymous(%17, %18, %15)
- %19 = OpISub %6 %114 %15
- %119 = OpCopyObject %6 %19
- %20 = OpSNegate %6 %119 ; ==> synonymous(%20, %16)
- %21 = OpISub %6 %14 %19 ; ==> synonymous(%21, %15)
- %22 = OpISub %6 %14 %18
- %220 = OpCopyObject %6 %22
- %23 = OpSNegate %6 %220 ; ==> synonymous(%23, %16)
- OpReturn
- OpFunctionEnd
- )";
-
- const auto env = SPV_ENV_UNIVERSAL_1_3;
- const auto consumer = nullptr;
- const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
- ASSERT_TRUE(IsValid(env, context.get()));
-
- FactManager fact_manager(context.get());
-
- fact_manager.AddFactIdEquation(14, SpvOpISub, {15, 16});
- fact_manager.AddFactDataSynonym(MakeDataDescriptor(114, {}),
- MakeDataDescriptor(14, {}));
- fact_manager.AddFactIdEquation(17, SpvOpIAdd, {114, 16});
-
- ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(17, {}),
- MakeDataDescriptor(15, {})));
-
- fact_manager.AddFactIdEquation(18, SpvOpIAdd, {16, 114});
-
- ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(18, {}),
- MakeDataDescriptor(15, {})));
- ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(17, {}),
- MakeDataDescriptor(18, {})));
-
- fact_manager.AddFactIdEquation(19, SpvOpISub, {14, 15});
- fact_manager.AddFactDataSynonym(MakeDataDescriptor(119, {}),
- MakeDataDescriptor(19, {}));
- fact_manager.AddFactIdEquation(20, SpvOpSNegate, {119});
-
- ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(20, {}),
- MakeDataDescriptor(16, {})));
-
- fact_manager.AddFactIdEquation(21, SpvOpISub, {14, 19});
- ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(21, {}),
- MakeDataDescriptor(15, {})));
-
- fact_manager.AddFactIdEquation(22, SpvOpISub, {14, 18});
- fact_manager.AddFactDataSynonym(MakeDataDescriptor(22, {}),
- MakeDataDescriptor(220, {}));
- fact_manager.AddFactIdEquation(23, SpvOpSNegate, {220});
- ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(23, {}),
- MakeDataDescriptor(16, {})));
-}
-
-TEST(FactManagerTest, CheckingFactsDoesNotAddConstants) {
- std::string shader = R"(
- OpCapability Shader
- %1 = OpExtInstImport "GLSL.std.450"
- OpMemoryModel Logical GLSL450
- OpEntryPoint Fragment %4 "main"
- OpExecutionMode %4 OriginUpperLeft
- OpSource ESSL 320
- OpMemberDecorate %9 0 Offset 0
- OpDecorate %9 Block
- OpDecorate %11 DescriptorSet 0
- OpDecorate %11 Binding 0
- %2 = OpTypeVoid
- %3 = OpTypeFunction %2
- %6 = OpTypeInt 32 1
- %7 = OpTypePointer Function %6
- %9 = OpTypeStruct %6
- %10 = OpTypePointer Uniform %9
- %11 = OpVariable %10 Uniform
- %12 = OpConstant %6 0
- %13 = OpTypePointer Uniform %6
- %4 = OpFunction %2 None %3
- %5 = OpLabel
- %8 = OpVariable %7 Function
- %14 = OpAccessChain %13 %11 %12
- %15 = OpLoad %6 %14
- OpStore %8 %15
- OpReturn
- OpFunctionEnd
- )";
-
- const auto env = SPV_ENV_UNIVERSAL_1_3;
- const auto consumer = nullptr;
- const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
- ASSERT_TRUE(IsValid(env, context.get()));
-
- FactManager fact_manager(context.get());
-
- // 8[0] == int(1)
- ASSERT_TRUE(AddFactHelper(&fact_manager, {1},
- MakeUniformBufferElementDescriptor(0, 0, {0})));
-
- // Although 8[0] has the value 1, we do not have the constant 1 in the module.
- // We thus should not find any constants available from uniforms for int type.
- // Furthermore, the act of looking for appropriate constants should not change
- // which constants are known to the constant manager.
- auto int_type = context->get_type_mgr()->GetType(6)->AsInteger();
- opt::analysis::IntConstant constant_one(int_type, {1});
- ASSERT_FALSE(context->get_constant_mgr()->FindConstant(&constant_one));
- auto available_constants =
- fact_manager.GetConstantsAvailableFromUniformsForType(6);
- ASSERT_EQ(0, available_constants.size());
- ASSERT_TRUE(IsEqual(env, shader, context.get()));
- ASSERT_FALSE(context->get_constant_mgr()->FindConstant(&constant_one));
-}
-
-TEST(FactManagerTest, IdIsIrrelevant) {
- std::string shader = R"(
- OpCapability Shader
- %1 = OpExtInstImport "GLSL.std.450"
- OpMemoryModel Logical GLSL450
- OpEntryPoint Fragment %4 "main"
- OpExecutionMode %4 OriginUpperLeft
- OpSource ESSL 320
- %2 = OpTypeVoid
- %3 = OpTypeFunction %2
- %6 = OpTypeInt 32 1
- %12 = OpConstant %6 0
- %13 = OpConstant %6 1
- %4 = OpFunction %2 None %3
- %5 = OpLabel
- OpReturn
- OpFunctionEnd
- )";
-
- const auto env = SPV_ENV_UNIVERSAL_1_3;
- const auto consumer = nullptr;
- const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
- ASSERT_TRUE(IsValid(env, context.get()));
-
- FactManager fact_manager(context.get());
-
- ASSERT_FALSE(fact_manager.IdIsIrrelevant(12));
- ASSERT_FALSE(fact_manager.IdIsIrrelevant(13));
-
- fact_manager.AddFactIdIsIrrelevant(12);
-
- ASSERT_TRUE(fact_manager.IdIsIrrelevant(12));
- ASSERT_FALSE(fact_manager.IdIsIrrelevant(13));
-}
-
-TEST(FactManagerTest, GetIrrelevantIds) {
- std::string shader = R"(
- OpCapability Shader
- %1 = OpExtInstImport "GLSL.std.450"
- OpMemoryModel Logical GLSL450
- OpEntryPoint Fragment %4 "main"
- OpExecutionMode %4 OriginUpperLeft
- OpSource ESSL 320
- %2 = OpTypeVoid
- %3 = OpTypeFunction %2
- %6 = OpTypeInt 32 1
- %12 = OpConstant %6 0
- %13 = OpConstant %6 1
- %14 = OpConstant %6 2
- %4 = OpFunction %2 None %3
- %5 = OpLabel
- OpReturn
- OpFunctionEnd
- )";
-
- const auto env = SPV_ENV_UNIVERSAL_1_3;
- const auto consumer = nullptr;
- const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
- ASSERT_TRUE(IsValid(env, context.get()));
-
- FactManager fact_manager(context.get());
-
- ASSERT_EQ(fact_manager.GetIrrelevantIds(), std::unordered_set<uint32_t>({}));
-
- fact_manager.AddFactIdIsIrrelevant(12);
-
- ASSERT_EQ(fact_manager.GetIrrelevantIds(),
- std::unordered_set<uint32_t>({12}));
-
- fact_manager.AddFactIdIsIrrelevant(13);
-
- ASSERT_EQ(fact_manager.GetIrrelevantIds(),
- std::unordered_set<uint32_t>({12, 13}));
-}
-
-TEST(FactManagerTest, BlockIsDead) {
- std::string shader = R"(
- OpCapability Shader
- %1 = OpExtInstImport "GLSL.std.450"
- OpMemoryModel Logical GLSL450
- OpEntryPoint Fragment %2 "main"
- OpExecutionMode %2 OriginUpperLeft
- OpSource ESSL 310
- %3 = OpTypeVoid
- %4 = OpTypeFunction %3
- %5 = OpTypeBool
- %6 = OpConstantTrue %5
- %7 = OpTypeInt 32 1
- %8 = OpTypePointer Function %7
- %2 = OpFunction %3 None %4
- %9 = OpLabel
- OpSelectionMerge %10 None
- OpBranchConditional %6 %11 %12
- %11 = OpLabel
- OpBranch %10
- %12 = OpLabel
- OpBranch %10
- %10 = OpLabel
- OpReturn
- OpFunctionEnd
-)";
-
- const auto env = SPV_ENV_UNIVERSAL_1_5;
- const auto consumer = nullptr;
- const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
- ASSERT_TRUE(IsValid(env, context.get()));
-
- FactManager fact_manager(context.get());
-
- ASSERT_FALSE(fact_manager.BlockIsDead(9));
- ASSERT_FALSE(fact_manager.BlockIsDead(11));
- ASSERT_FALSE(fact_manager.BlockIsDead(12));
-
- fact_manager.AddFactBlockIsDead(12);
-
- ASSERT_FALSE(fact_manager.BlockIsDead(9));
- ASSERT_FALSE(fact_manager.BlockIsDead(11));
- ASSERT_TRUE(fact_manager.BlockIsDead(12));
-}
-
-TEST(FactManagerTest, IdsFromDeadBlocksAreIrrelevant) {
- std::string shader = R"(
- OpCapability Shader
- %1 = OpExtInstImport "GLSL.std.450"
- OpMemoryModel Logical GLSL450
- OpEntryPoint Fragment %2 "main"
- OpExecutionMode %2 OriginUpperLeft
- OpSource ESSL 310
- %3 = OpTypeVoid
- %4 = OpTypeFunction %3
- %5 = OpTypeBool
- %6 = OpConstantTrue %5
- %7 = OpTypeInt 32 1
- %8 = OpTypePointer Function %7
- %9 = OpConstant %7 1
- %2 = OpFunction %3 None %4
- %10 = OpLabel
- %11 = OpVariable %8 Function
- OpSelectionMerge %12 None
- OpBranchConditional %6 %13 %14
- %13 = OpLabel
- OpBranch %12
- %14 = OpLabel
- %15 = OpCopyObject %8 %11
- %16 = OpCopyObject %7 %9
- %17 = OpFunctionCall %3 %18
- OpBranch %12
- %12 = OpLabel
- OpReturn
- OpFunctionEnd
- %18 = OpFunction %3 None %4
- %19 = OpLabel
- %20 = OpVariable %8 Function
- %21 = OpCopyObject %7 %9
- OpReturn
- OpFunctionEnd
-)";
-
- const auto env = SPV_ENV_UNIVERSAL_1_5;
- const auto consumer = nullptr;
- const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
- ASSERT_TRUE(IsValid(env, context.get()));
-
- FactManager fact_manager(context.get());
-
- ASSERT_FALSE(fact_manager.BlockIsDead(14));
- ASSERT_FALSE(fact_manager.BlockIsDead(19));
-
- // Initially no id is irrelevant.
- ASSERT_FALSE(fact_manager.IdIsIrrelevant(16));
- ASSERT_FALSE(fact_manager.IdIsIrrelevant(17));
- ASSERT_EQ(fact_manager.GetIrrelevantIds(), std::unordered_set<uint32_t>({}));
-
- fact_manager.AddFactBlockIsDead(14);
-
- // %16 and %17 should now be considered irrelevant.
- ASSERT_TRUE(fact_manager.IdIsIrrelevant(16));
- ASSERT_TRUE(fact_manager.IdIsIrrelevant(17));
- ASSERT_EQ(fact_manager.GetIrrelevantIds(),
- std::unordered_set<uint32_t>({16, 17}));
-
- // Similarly for %21.
- ASSERT_FALSE(fact_manager.IdIsIrrelevant(21));
-
- fact_manager.AddFactBlockIsDead(19);
-
- ASSERT_TRUE(fact_manager.IdIsIrrelevant(21));
- ASSERT_EQ(fact_manager.GetIrrelevantIds(),
- std::unordered_set<uint32_t>({16, 17, 21}));
-}
-} // namespace
-} // namespace fuzz
-} // namespace spvtools