mirror of
https://github.com/KhronosGroup/SPIRV-Tools
synced 2024-11-29 14:31:04 +00:00
spirv-fuzz: Refactor conditions in the fact manager (#3867)
Refactors conditions and names of some methods in the fact manager. Part of #3698.
This commit is contained in:
parent
615fbe6cbc
commit
16cc197c8c
@ -163,7 +163,8 @@ bool ConstantUniformFacts::FloatingPointValueIsSuitable(
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ConstantUniformFacts::AddFact(const protobufs::FactConstantUniform& fact) {
|
||||
bool ConstantUniformFacts::MaybeAddFact(
|
||||
const protobufs::FactConstantUniform& fact) {
|
||||
// Try to find a unique instruction that declares a variable such that the
|
||||
// variable is decorated with the descriptor set and binding associated with
|
||||
// the constant uniform fact.
|
||||
|
@ -31,7 +31,7 @@ class ConstantUniformFacts {
|
||||
explicit ConstantUniformFacts(opt::IRContext* ir_context);
|
||||
|
||||
// See method in FactManager which delegates to this method.
|
||||
bool AddFact(const protobufs::FactConstantUniform& fact);
|
||||
bool MaybeAddFact(const protobufs::FactConstantUniform& fact);
|
||||
|
||||
// See method in FactManager which delegates to this method.
|
||||
std::vector<uint32_t> GetConstantsAvailableFromUniformsForType(
|
||||
|
@ -55,32 +55,39 @@ DataSynonymAndIdEquationFacts::DataSynonymAndIdEquationFacts(
|
||||
opt::IRContext* ir_context)
|
||||
: ir_context_(ir_context) {}
|
||||
|
||||
void DataSynonymAndIdEquationFacts::AddFact(
|
||||
bool DataSynonymAndIdEquationFacts::MaybeAddFact(
|
||||
const protobufs::FactDataSynonym& fact,
|
||||
const DeadBlockFacts& dead_block_facts,
|
||||
const IrrelevantValueFacts& irrelevant_value_facts) {
|
||||
(void)dead_block_facts; // Keep release compilers happy.
|
||||
(void)irrelevant_value_facts; // Keep release compilers happy.
|
||||
assert(!irrelevant_value_facts.IdIsIrrelevant(fact.data1().object(),
|
||||
dead_block_facts) &&
|
||||
!irrelevant_value_facts.IdIsIrrelevant(fact.data2().object(),
|
||||
dead_block_facts) &&
|
||||
"Irrelevant ids cannot be synonymous with other ids.");
|
||||
if (irrelevant_value_facts.IdIsIrrelevant(fact.data1().object(),
|
||||
dead_block_facts) ||
|
||||
irrelevant_value_facts.IdIsIrrelevant(fact.data2().object(),
|
||||
dead_block_facts)) {
|
||||
// Irrelevant ids cannot be synonymous with other ids.
|
||||
return false;
|
||||
}
|
||||
|
||||
// Add the fact, including all facts relating sub-components of the data
|
||||
// descriptors that are involved.
|
||||
AddDataSynonymFactRecursive(fact.data1(), fact.data2());
|
||||
return true;
|
||||
}
|
||||
|
||||
void DataSynonymAndIdEquationFacts::AddFact(
|
||||
bool DataSynonymAndIdEquationFacts::MaybeAddFact(
|
||||
const protobufs::FactIdEquation& fact,
|
||||
const DeadBlockFacts& dead_block_facts,
|
||||
const IrrelevantValueFacts& irrelevant_value_facts) {
|
||||
(void)dead_block_facts; // Keep release compilers happy.
|
||||
(void)irrelevant_value_facts; // Keep release compilers happy.
|
||||
assert(
|
||||
!irrelevant_value_facts.IdIsIrrelevant(fact.lhs_id(), dead_block_facts) &&
|
||||
"Irrelevant ids are not allowed.");
|
||||
if (irrelevant_value_facts.IdIsIrrelevant(fact.lhs_id(), dead_block_facts)) {
|
||||
// Irrelevant ids cannot participate in IdEquation facts.
|
||||
return false;
|
||||
}
|
||||
|
||||
for (auto id : fact.rhs_id()) {
|
||||
if (irrelevant_value_facts.IdIsIrrelevant(id, dead_block_facts)) {
|
||||
// Irrelevant ids cannot participate in IdEquation facts.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
protobufs::DataDescriptor lhs_dd = MakeDataDescriptor(fact.lhs_id(), {});
|
||||
|
||||
@ -91,9 +98,6 @@ void DataSynonymAndIdEquationFacts::AddFact(
|
||||
// equation.
|
||||
std::vector<const protobufs::DataDescriptor*> rhs_dds;
|
||||
for (auto rhs_id : fact.rhs_id()) {
|
||||
assert(!irrelevant_value_facts.IdIsIrrelevant(rhs_id, dead_block_facts) &&
|
||||
"Irrelevant ids are not allowed.");
|
||||
|
||||
// Register a data descriptor based on this id in the equivalence relation
|
||||
// if needed, and then record the equivalence class representative.
|
||||
rhs_dds.push_back(RegisterDataDescriptor(MakeDataDescriptor(rhs_id, {})));
|
||||
@ -101,6 +105,7 @@ void DataSynonymAndIdEquationFacts::AddFact(
|
||||
|
||||
// Now add the fact.
|
||||
AddEquationFactRecursive(lhs_dd, static_cast<SpvOp>(fact.opcode()), rhs_dds);
|
||||
return true;
|
||||
}
|
||||
|
||||
DataSynonymAndIdEquationFacts::OperationSet
|
||||
|
@ -38,19 +38,21 @@ class DataSynonymAndIdEquationFacts {
|
||||
public:
|
||||
explicit DataSynonymAndIdEquationFacts(opt::IRContext* ir_context);
|
||||
|
||||
// See method in FactManager which delegates to this method.
|
||||
// |dead_block_facts| and |irrelevant_value_facts| are passed for consistency
|
||||
// checks.
|
||||
void AddFact(const protobufs::FactDataSynonym& fact,
|
||||
const DeadBlockFacts& dead_block_facts,
|
||||
const IrrelevantValueFacts& irrelevant_value_facts);
|
||||
// See method in FactManager which delegates to this method. Returns true if
|
||||
// neither |fact.data1()| nor |fact.data2()| contain an
|
||||
// irrelevant id. Otherwise, returns false. |dead_block_facts| and
|
||||
// |irrelevant_value_facts| are passed for consistency checks.
|
||||
bool MaybeAddFact(const protobufs::FactDataSynonym& fact,
|
||||
const DeadBlockFacts& dead_block_facts,
|
||||
const IrrelevantValueFacts& irrelevant_value_facts);
|
||||
|
||||
// See method in FactManager which delegates to this method.
|
||||
// |dead_block_facts| and |irrelevant_value_facts| are passed for consistency
|
||||
// checks.
|
||||
void AddFact(const protobufs::FactIdEquation& fact,
|
||||
const DeadBlockFacts& dead_block_facts,
|
||||
const IrrelevantValueFacts& irrelevant_value_facts);
|
||||
// See method in FactManager which delegates to this method. Returns true if
|
||||
// neither |fact.lhs_id()| nor any of |fact.rhs_id()| is irrelevant. Returns
|
||||
// false otherwise. |dead_block_facts| and |irrelevant_value_facts| are passed
|
||||
// for consistency checks.
|
||||
bool MaybeAddFact(const protobufs::FactIdEquation& fact,
|
||||
const DeadBlockFacts& dead_block_facts,
|
||||
const IrrelevantValueFacts& irrelevant_value_facts);
|
||||
|
||||
// See method in FactManager which delegates to this method.
|
||||
std::vector<const protobufs::DataDescriptor*> GetSynonymsForId(
|
||||
|
@ -14,12 +14,22 @@
|
||||
|
||||
#include "source/fuzz/fact_manager/dead_block_facts.h"
|
||||
|
||||
#include "source/fuzz/fuzzer_util.h"
|
||||
|
||||
namespace spvtools {
|
||||
namespace fuzz {
|
||||
namespace fact_manager {
|
||||
|
||||
void DeadBlockFacts::AddFact(const protobufs::FactBlockIsDead& fact) {
|
||||
DeadBlockFacts::DeadBlockFacts(opt::IRContext* ir_context)
|
||||
: ir_context_(ir_context) {}
|
||||
|
||||
bool DeadBlockFacts::MaybeAddFact(const protobufs::FactBlockIsDead& fact) {
|
||||
if (!fuzzerutil::MaybeFindBlock(ir_context_, fact.block_id())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
dead_block_ids_.insert(fact.block_id());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DeadBlockFacts::BlockIsDead(uint32_t block_id) const {
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include <unordered_set>
|
||||
|
||||
#include "source/fuzz/protobufs/spirvfuzz_protobufs.h"
|
||||
#include "source/opt/ir_context.h"
|
||||
|
||||
namespace spvtools {
|
||||
namespace fuzz {
|
||||
@ -27,8 +28,12 @@ namespace fact_manager {
|
||||
// facts about data blocks.
|
||||
class DeadBlockFacts {
|
||||
public:
|
||||
// See method in FactManager which delegates to this method.
|
||||
void AddFact(const protobufs::FactBlockIsDead& fact);
|
||||
explicit DeadBlockFacts(opt::IRContext* ir_context);
|
||||
|
||||
// Marks |fact.block_id()| as being dead. Returns true if |fact.block_id()|
|
||||
// represents a result id of some OpLabel instruction in |ir_context_|.
|
||||
// Returns false otherwise.
|
||||
bool MaybeAddFact(const protobufs::FactBlockIsDead& fact);
|
||||
|
||||
// See method in FactManager which delegates to this method.
|
||||
bool BlockIsDead(uint32_t block_id) const;
|
||||
@ -38,6 +43,7 @@ class DeadBlockFacts {
|
||||
|
||||
private:
|
||||
std::unordered_set<uint32_t> dead_block_ids_;
|
||||
opt::IRContext* ir_context_;
|
||||
};
|
||||
|
||||
} // namespace fact_manager
|
||||
|
@ -90,38 +90,49 @@ std::string ToString(const protobufs::Fact& fact) {
|
||||
FactManager::FactManager(opt::IRContext* ir_context)
|
||||
: constant_uniform_facts_(ir_context),
|
||||
data_synonym_and_id_equation_facts_(ir_context),
|
||||
dead_block_facts_(),
|
||||
livesafe_function_facts_(),
|
||||
dead_block_facts_(ir_context),
|
||||
livesafe_function_facts_(ir_context),
|
||||
irrelevant_value_facts_(ir_context) {}
|
||||
|
||||
void FactManager::AddFacts(const MessageConsumer& message_consumer,
|
||||
const protobufs::FactSequence& initial_facts) {
|
||||
for (auto& fact : initial_facts.fact()) {
|
||||
if (!AddFact(fact)) {
|
||||
void FactManager::AddInitialFacts(const MessageConsumer& message_consumer,
|
||||
const protobufs::FactSequence& facts) {
|
||||
for (auto& fact : facts.fact()) {
|
||||
if (!MaybeAddFact(fact)) {
|
||||
auto message = "Invalid fact " + ToString(fact) + " ignored.";
|
||||
message_consumer(SPV_MSG_WARNING, nullptr, {}, message.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool FactManager::AddFact(const fuzz::protobufs::Fact& fact) {
|
||||
bool FactManager::MaybeAddFact(const fuzz::protobufs::Fact& fact) {
|
||||
switch (fact.fact_case()) {
|
||||
case protobufs::Fact::kConstantUniformFact:
|
||||
return constant_uniform_facts_.AddFact(fact.constant_uniform_fact());
|
||||
case protobufs::Fact::kDataSynonymFact:
|
||||
data_synonym_and_id_equation_facts_.AddFact(
|
||||
fact.data_synonym_fact(), dead_block_facts_, irrelevant_value_facts_);
|
||||
return true;
|
||||
case protobufs::Fact::kBlockIsDeadFact:
|
||||
dead_block_facts_.AddFact(fact.block_is_dead_fact());
|
||||
return true;
|
||||
return dead_block_facts_.MaybeAddFact(fact.block_is_dead_fact());
|
||||
case protobufs::Fact::kConstantUniformFact:
|
||||
return constant_uniform_facts_.MaybeAddFact(fact.constant_uniform_fact());
|
||||
case protobufs::Fact::kDataSynonymFact:
|
||||
return data_synonym_and_id_equation_facts_.MaybeAddFact(
|
||||
fact.data_synonym_fact(), dead_block_facts_, irrelevant_value_facts_);
|
||||
case protobufs::Fact::kFunctionIsLivesafeFact:
|
||||
livesafe_function_facts_.AddFact(fact.function_is_livesafe_fact());
|
||||
return true;
|
||||
default:
|
||||
assert(false && "Unknown fact type.");
|
||||
return livesafe_function_facts_.MaybeAddFact(
|
||||
fact.function_is_livesafe_fact());
|
||||
case protobufs::Fact::kIdEquationFact:
|
||||
return data_synonym_and_id_equation_facts_.MaybeAddFact(
|
||||
fact.id_equation_fact(), dead_block_facts_, irrelevant_value_facts_);
|
||||
case protobufs::Fact::kIdIsIrrelevant:
|
||||
return irrelevant_value_facts_.MaybeAddFact(
|
||||
fact.id_is_irrelevant(), data_synonym_and_id_equation_facts_);
|
||||
case protobufs::Fact::kPointeeValueIsIrrelevantFact:
|
||||
return irrelevant_value_facts_.MaybeAddFact(
|
||||
fact.pointee_value_is_irrelevant_fact(),
|
||||
data_synonym_and_id_equation_facts_);
|
||||
case protobufs::Fact::FACT_NOT_SET:
|
||||
assert(false && "The fact must be set");
|
||||
return false;
|
||||
}
|
||||
|
||||
assert(false && "Unreachable");
|
||||
return false;
|
||||
}
|
||||
|
||||
void FactManager::AddFactDataSynonym(const protobufs::DataDescriptor& data1,
|
||||
@ -129,8 +140,10 @@ void FactManager::AddFactDataSynonym(const protobufs::DataDescriptor& data1,
|
||||
protobufs::FactDataSynonym fact;
|
||||
*fact.mutable_data1() = data1;
|
||||
*fact.mutable_data2() = data2;
|
||||
data_synonym_and_id_equation_facts_.AddFact(fact, dead_block_facts_,
|
||||
irrelevant_value_facts_);
|
||||
auto success = data_synonym_and_id_equation_facts_.MaybeAddFact(
|
||||
fact, dead_block_facts_, irrelevant_value_facts_);
|
||||
(void)success; // Keep compilers happy in release mode.
|
||||
assert(success && "Unable to create DataSynonym fact");
|
||||
}
|
||||
|
||||
std::vector<uint32_t> FactManager::GetConstantsAvailableFromUniformsForType(
|
||||
@ -190,7 +203,9 @@ bool FactManager::BlockIsDead(uint32_t block_id) const {
|
||||
void FactManager::AddFactBlockIsDead(uint32_t block_id) {
|
||||
protobufs::FactBlockIsDead fact;
|
||||
fact.set_block_id(block_id);
|
||||
dead_block_facts_.AddFact(fact);
|
||||
auto success = dead_block_facts_.MaybeAddFact(fact);
|
||||
(void)success; // Keep compilers happy in release mode.
|
||||
assert(success && "|block_id| is invalid");
|
||||
}
|
||||
|
||||
bool FactManager::FunctionIsLivesafe(uint32_t function_id) const {
|
||||
@ -200,7 +215,9 @@ bool FactManager::FunctionIsLivesafe(uint32_t function_id) const {
|
||||
void FactManager::AddFactFunctionIsLivesafe(uint32_t function_id) {
|
||||
protobufs::FactFunctionIsLivesafe fact;
|
||||
fact.set_function_id(function_id);
|
||||
livesafe_function_facts_.AddFact(fact);
|
||||
auto success = livesafe_function_facts_.MaybeAddFact(fact);
|
||||
(void)success; // Keep compilers happy in release mode.
|
||||
assert(success && "|function_id| is invalid");
|
||||
}
|
||||
|
||||
bool FactManager::PointeeValueIsIrrelevant(uint32_t pointer_id) const {
|
||||
@ -218,13 +235,19 @@ std::unordered_set<uint32_t> FactManager::GetIrrelevantIds() const {
|
||||
void FactManager::AddFactValueOfPointeeIsIrrelevant(uint32_t pointer_id) {
|
||||
protobufs::FactPointeeValueIsIrrelevant fact;
|
||||
fact.set_pointer_id(pointer_id);
|
||||
irrelevant_value_facts_.AddFact(fact, data_synonym_and_id_equation_facts_);
|
||||
auto success = irrelevant_value_facts_.MaybeAddFact(
|
||||
fact, data_synonym_and_id_equation_facts_);
|
||||
(void)success; // Keep compilers happy in release mode.
|
||||
assert(success && "|pointer_id| is invalid");
|
||||
}
|
||||
|
||||
void FactManager::AddFactIdIsIrrelevant(uint32_t result_id) {
|
||||
protobufs::FactIdIsIrrelevant fact;
|
||||
fact.set_result_id(result_id);
|
||||
irrelevant_value_facts_.AddFact(fact, data_synonym_and_id_equation_facts_);
|
||||
auto success = irrelevant_value_facts_.MaybeAddFact(
|
||||
fact, data_synonym_and_id_equation_facts_);
|
||||
(void)success; // Keep compilers happy in release mode.
|
||||
assert(success && "|result_id| is invalid");
|
||||
}
|
||||
|
||||
void FactManager::AddFactIdEquation(uint32_t lhs_id, SpvOp opcode,
|
||||
@ -235,8 +258,10 @@ void FactManager::AddFactIdEquation(uint32_t lhs_id, SpvOp opcode,
|
||||
for (auto an_rhs_id : rhs_id) {
|
||||
fact.add_rhs_id(an_rhs_id);
|
||||
}
|
||||
data_synonym_and_id_equation_facts_.AddFact(fact, dead_block_facts_,
|
||||
irrelevant_value_facts_);
|
||||
auto success = data_synonym_and_id_equation_facts_.MaybeAddFact(
|
||||
fact, dead_block_facts_, irrelevant_value_facts_);
|
||||
(void)success; // Keep compilers happy in release mode.
|
||||
assert(success && "Can't create IdIsIrrelevant fact");
|
||||
}
|
||||
|
||||
void FactManager::ComputeClosureOfFacts(
|
||||
|
@ -45,24 +45,27 @@ class FactManager {
|
||||
explicit FactManager(opt::IRContext* ir_context);
|
||||
|
||||
// Adds all the facts from |facts|, checking them for validity with respect to
|
||||
// |context|. Warnings about invalid facts are communicated via
|
||||
// |ir_context_|. Warnings about invalid facts are communicated via
|
||||
// |message_consumer|; such facts are otherwise ignored.
|
||||
void AddFacts(const MessageConsumer& message_consumer,
|
||||
const protobufs::FactSequence& facts);
|
||||
void AddInitialFacts(const MessageConsumer& message_consumer,
|
||||
const protobufs::FactSequence& facts);
|
||||
|
||||
// Checks the fact for validity with respect to |context|. Returns false,
|
||||
// with no side effects, if the fact is invalid. Otherwise adds |fact| to the
|
||||
// Checks the fact for validity with respect to |ir_context_|. Returns false,
|
||||
// with no side effects, if the fact is invalid. Otherwise adds |fact| to the
|
||||
// fact manager.
|
||||
bool AddFact(const protobufs::Fact& fact);
|
||||
bool MaybeAddFact(const protobufs::Fact& fact);
|
||||
|
||||
// Record the fact that |data1| and |data2| are synonymous.
|
||||
// Record the fact that |data1| and |data2| are synonymous. Neither |data1|
|
||||
// nor |data2| may contain an irrelevant id.
|
||||
void AddFactDataSynonym(const protobufs::DataDescriptor& data1,
|
||||
const protobufs::DataDescriptor& data2);
|
||||
|
||||
// Records the fact that |block_id| is dead.
|
||||
// Records the fact that |block_id| is dead. |block_id| must be a result id
|
||||
// of some OpLabel instruction in the |ir_context_|.
|
||||
void AddFactBlockIsDead(uint32_t block_id);
|
||||
|
||||
// Records the fact that |function_id| is livesafe.
|
||||
// Records the fact that |function_id| is livesafe. |function_id| must be a
|
||||
// result id of some non-entry-point function in the module.
|
||||
void AddFactFunctionIsLivesafe(uint32_t function_id);
|
||||
|
||||
// Records the fact that the value of the pointee associated with |pointer_id|
|
||||
@ -72,13 +75,14 @@ class FactManager {
|
||||
|
||||
// Records a fact that the |result_id| is irrelevant (i.e. it doesn't affect
|
||||
// the semantics of the module).
|
||||
// |result_id| must exist in the module and actually be a pointer.
|
||||
// |result_id| must exist in the module and it may not be a pointer.
|
||||
void AddFactIdIsIrrelevant(uint32_t result_id);
|
||||
|
||||
// Records the fact that |lhs_id| is defined by the equation:
|
||||
//
|
||||
// |lhs_id| = |opcode| |rhs_id[0]| ... |rhs_id[N-1]|
|
||||
//
|
||||
// Neither |lhs_id| nor any of |rhs_id| may be irrelevant.
|
||||
void AddFactIdEquation(uint32_t lhs_id, SpvOp opcode,
|
||||
const std::vector<uint32_t>& rhs_id);
|
||||
|
||||
@ -117,7 +121,7 @@ class FactManager {
|
||||
uint32_t type_id) const;
|
||||
|
||||
// Provides details of all uniform elements that are known to be equal to the
|
||||
// constant associated with |constant_id| in |ir_context|.
|
||||
// constant associated with |constant_id| in |ir_context_|.
|
||||
std::vector<protobufs::UniformBufferElementDescriptor>
|
||||
GetUniformDescriptorsForConstant(uint32_t constant_id) const;
|
||||
|
||||
|
@ -27,36 +27,52 @@ namespace fact_manager {
|
||||
IrrelevantValueFacts::IrrelevantValueFacts(opt::IRContext* ir_context)
|
||||
: ir_context_(ir_context) {}
|
||||
|
||||
void IrrelevantValueFacts::AddFact(
|
||||
bool IrrelevantValueFacts::MaybeAddFact(
|
||||
const protobufs::FactPointeeValueIsIrrelevant& fact,
|
||||
const DataSynonymAndIdEquationFacts& data_synonym_and_id_equation_facts) {
|
||||
(void)data_synonym_and_id_equation_facts; // Keep release compilers happy.
|
||||
assert(data_synonym_and_id_equation_facts.GetSynonymsForId(fact.pointer_id())
|
||||
.empty() &&
|
||||
"The id cannot participate in DataSynonym facts.");
|
||||
auto pointer_def = ir_context_->get_def_use_mgr()->GetDef(fact.pointer_id());
|
||||
assert(pointer_def && "The id must exist in the module.");
|
||||
auto type = ir_context_->get_type_mgr()->GetType(pointer_def->type_id());
|
||||
(void)type; // Keep release compilers happy.
|
||||
assert(type && type->AsPointer() && "The id must be a pointer.");
|
||||
const auto* inst = ir_context_->get_def_use_mgr()->GetDef(fact.pointer_id());
|
||||
if (!inst || !inst->type_id()) {
|
||||
// The id must exist in the module and have type id.
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!ir_context_->get_type_mgr()->GetType(inst->type_id())->AsPointer()) {
|
||||
// The id must be a pointer.
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!data_synonym_and_id_equation_facts.GetSynonymsForId(fact.pointer_id())
|
||||
.empty()) {
|
||||
// Irrelevant id cannot participate in DataSynonym facts.
|
||||
return false;
|
||||
}
|
||||
|
||||
pointers_to_irrelevant_pointees_ids_.insert(fact.pointer_id());
|
||||
return true;
|
||||
}
|
||||
|
||||
void IrrelevantValueFacts::AddFact(
|
||||
bool IrrelevantValueFacts::MaybeAddFact(
|
||||
const protobufs::FactIdIsIrrelevant& fact,
|
||||
const DataSynonymAndIdEquationFacts& data_synonym_and_id_equation_facts) {
|
||||
(void)data_synonym_and_id_equation_facts; // Keep release compilers happy.
|
||||
assert(data_synonym_and_id_equation_facts.GetSynonymsForId(fact.result_id())
|
||||
.empty() &&
|
||||
"The id cannot participate in DataSynonym facts.");
|
||||
auto pointer_def = ir_context_->get_def_use_mgr()->GetDef(fact.result_id());
|
||||
assert(pointer_def && "The id must exist in the module.");
|
||||
auto type = ir_context_->get_type_mgr()->GetType(pointer_def->type_id());
|
||||
(void)type; // Keep release compilers happy.
|
||||
assert(type && !type->AsPointer() && "The id must not be a pointer.");
|
||||
const auto* inst = ir_context_->get_def_use_mgr()->GetDef(fact.result_id());
|
||||
if (!inst || !inst->type_id()) {
|
||||
// The id must exist in the module and have type id.
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ir_context_->get_type_mgr()->GetType(inst->type_id())->AsPointer()) {
|
||||
// The id may not be a pointer.
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!data_synonym_and_id_equation_facts.GetSynonymsForId(fact.result_id())
|
||||
.empty()) {
|
||||
// Irrelevant id cannot participate in DataSynonym facts.
|
||||
return false;
|
||||
}
|
||||
|
||||
irrelevant_ids_.insert(fact.result_id());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IrrelevantValueFacts::PointeeValueIsIrrelevant(uint32_t pointer_id) const {
|
||||
|
@ -35,17 +35,21 @@ class IrrelevantValueFacts {
|
||||
public:
|
||||
explicit IrrelevantValueFacts(opt::IRContext* ir_context);
|
||||
|
||||
// See method in FactManager which delegates to this method.
|
||||
// |data_synonym_and_id_equation_facts| and |context| are passed for
|
||||
// consistency checks.
|
||||
void AddFact(
|
||||
// See method in FactManager which delegates to this method. Returns true if
|
||||
// |fact.pointer_id()| is a result id of pointer type in the |ir_context_| and
|
||||
// |fact.pointer_id()| does not participate in DataSynonym facts. Returns
|
||||
// false otherwise. |data_synonym_and_id_equation_facts| and |context| are
|
||||
// passed for consistency checks.
|
||||
bool MaybeAddFact(
|
||||
const protobufs::FactPointeeValueIsIrrelevant& fact,
|
||||
const DataSynonymAndIdEquationFacts& data_synonym_and_id_equation_facts);
|
||||
|
||||
// See method in FactManager which delegates to this method.
|
||||
// |data_synonym_and_id_equation_facts| and |context| are passed for
|
||||
// consistency checks.
|
||||
void AddFact(
|
||||
// See method in FactManager which delegates to this method. Returns true if
|
||||
// |fact.result_id()| is a result id of non-pointer type in the |ir_context_|
|
||||
// and |fact.result_id()| does not participate in DataSynonym facts. Returns
|
||||
// false otherwise. |data_synonym_and_id_equation_facts| and |context| are
|
||||
// passed for consistency checks.
|
||||
bool MaybeAddFact(
|
||||
const protobufs::FactIdIsIrrelevant& fact,
|
||||
const DataSynonymAndIdEquationFacts& data_synonym_and_id_equation_facts);
|
||||
|
||||
|
@ -14,13 +14,27 @@
|
||||
|
||||
#include "source/fuzz/fact_manager/livesafe_function_facts.h"
|
||||
|
||||
#include "source/fuzz/fuzzer_util.h"
|
||||
|
||||
namespace spvtools {
|
||||
namespace fuzz {
|
||||
namespace fact_manager {
|
||||
|
||||
void LivesafeFunctionFacts::AddFact(
|
||||
LivesafeFunctionFacts::LivesafeFunctionFacts(opt::IRContext* ir_context)
|
||||
: ir_context_(ir_context) {}
|
||||
|
||||
bool LivesafeFunctionFacts::MaybeAddFact(
|
||||
const protobufs::FactFunctionIsLivesafe& fact) {
|
||||
if (!fuzzerutil::FindFunction(ir_context_, fact.function_id())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (fuzzerutil::FunctionIsEntryPoint(ir_context_, fact.function_id())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
livesafe_function_ids_.insert(fact.function_id());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LivesafeFunctionFacts::FunctionIsLivesafe(uint32_t function_id) const {
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include <unordered_set>
|
||||
|
||||
#include "source/fuzz/protobufs/spirvfuzz_protobufs.h"
|
||||
#include "source/opt/ir_context.h"
|
||||
|
||||
namespace spvtools {
|
||||
namespace fuzz {
|
||||
@ -27,14 +28,19 @@ namespace fact_manager {
|
||||
// facts about livesafe functions.
|
||||
class LivesafeFunctionFacts {
|
||||
public:
|
||||
// See method in FactManager which delegates to this method.
|
||||
void AddFact(const protobufs::FactFunctionIsLivesafe& fact);
|
||||
explicit LivesafeFunctionFacts(opt::IRContext* ir_context);
|
||||
|
||||
// See method in FactManager which delegates to this method. Returns true if
|
||||
// |fact.function_id()| is a result id of some non-entry-point function in
|
||||
// |ir_context_|. Returns false otherwise.
|
||||
bool MaybeAddFact(const protobufs::FactFunctionIsLivesafe& fact);
|
||||
|
||||
// See method in FactManager which delegates to this method.
|
||||
bool FunctionIsLivesafe(uint32_t function_id) const;
|
||||
|
||||
private:
|
||||
std::unordered_set<uint32_t> livesafe_function_ids_;
|
||||
opt::IRContext* ir_context_;
|
||||
};
|
||||
|
||||
} // namespace fact_manager
|
||||
|
@ -185,7 +185,7 @@ bool ForceRenderRed(
|
||||
TransformationContext transformation_context(
|
||||
MakeUnique<FactManager>(ir_context.get()), validator_options);
|
||||
for (auto& fact : initial_facts.fact()) {
|
||||
transformation_context.GetFactManager()->AddFact(fact);
|
||||
transformation_context.GetFactManager()->MaybeAddFact(fact);
|
||||
}
|
||||
|
||||
auto entry_point_function =
|
||||
|
@ -216,8 +216,8 @@ Fuzzer::FuzzerResult Fuzzer::Run() {
|
||||
|
||||
transformation_context_ = MakeUnique<TransformationContext>(
|
||||
MakeUnique<FactManager>(ir_context_.get()), validator_options_);
|
||||
transformation_context_->GetFactManager()->AddFacts(consumer_,
|
||||
initial_facts_);
|
||||
transformation_context_->GetFactManager()->AddInitialFacts(consumer_,
|
||||
initial_facts_);
|
||||
|
||||
RepeatedPassInstances pass_instances{};
|
||||
|
||||
|
@ -108,7 +108,8 @@ Replayer::ReplayerResult Replayer::Run() {
|
||||
MakeUnique<TransformationContext>(
|
||||
MakeUnique<FactManager>(ir_context.get()), validator_options_,
|
||||
MakeUnique<CounterOverflowIdSource>(first_overflow_id));
|
||||
transformation_context->GetFactManager()->AddFacts(consumer_, initial_facts_);
|
||||
transformation_context->GetFactManager()->AddInitialFacts(consumer_,
|
||||
initial_facts_);
|
||||
|
||||
// We track the largest id bound observed, to ensure that it only increases
|
||||
// as transformations are applied.
|
||||
|
@ -157,10 +157,6 @@ void TransformationAddDeadBlock::Apply(
|
||||
enclosing_function->InsertBasicBlockAfter(std::move(new_block),
|
||||
existing_block);
|
||||
|
||||
// Record the fact that the new block is dead.
|
||||
transformation_context->GetFactManager()->AddFactBlockIsDead(
|
||||
message_.fresh_id());
|
||||
|
||||
// Fix up OpPhi instructions in the successor block, so that the values they
|
||||
// yield when control has transferred from the new block are the same as if
|
||||
// control had transferred from |message_.existing_block|. This is guaranteed
|
||||
@ -181,6 +177,10 @@ void TransformationAddDeadBlock::Apply(
|
||||
// Do not rely on any existing analysis results since the control flow graph
|
||||
// of the module has changed.
|
||||
ir_context->InvalidateAnalysesExceptFor(opt::IRContext::kAnalysisNone);
|
||||
|
||||
// Record the fact that the new block is dead.
|
||||
transformation_context->GetFactManager()->AddFactBlockIsDead(
|
||||
message_.fresh_id());
|
||||
}
|
||||
|
||||
protobufs::Transformation TransformationAddDeadBlock::ToMessage() const {
|
||||
|
@ -173,11 +173,15 @@ void TransformationAddFunction::Apply(
|
||||
success = TryToMakeFunctionLivesafe(ir_context, *transformation_context);
|
||||
assert(success && "It should be possible to make the function livesafe.");
|
||||
(void)(success); // Keep release builds happy.
|
||||
}
|
||||
ir_context->InvalidateAnalysesExceptFor(opt::IRContext::kAnalysisNone);
|
||||
|
||||
assert(message_.instruction(0).opcode() == SpvOpFunction &&
|
||||
"The first instruction of an 'add function' transformation must be "
|
||||
"OpFunction.");
|
||||
|
||||
if (message_.is_livesafe()) {
|
||||
// Inform the fact manager that the function is livesafe.
|
||||
assert(message_.instruction(0).opcode() == SpvOpFunction &&
|
||||
"The first instruction of an 'add function' transformation must be "
|
||||
"OpFunction.");
|
||||
transformation_context->GetFactManager()->AddFactFunctionIsLivesafe(
|
||||
message_.instruction(0).result_id());
|
||||
} else {
|
||||
@ -189,7 +193,6 @@ void TransformationAddFunction::Apply(
|
||||
}
|
||||
}
|
||||
}
|
||||
ir_context->InvalidateAnalysesExceptFor(opt::IRContext::kAnalysisNone);
|
||||
|
||||
// Record the fact that all pointer parameters and variables declared in the
|
||||
// function should be regarded as having irrelevant values. This allows other
|
||||
|
@ -358,14 +358,6 @@ void TransformationOutlineFunction::Apply(
|
||||
region_input_ids, region_output_ids, input_id_to_fresh_id_map, ir_context,
|
||||
transformation_context);
|
||||
|
||||
// If the original function was livesafe, the new function should also be
|
||||
// livesafe.
|
||||
if (transformation_context->GetFactManager()->FunctionIsLivesafe(
|
||||
original_region_entry_block->GetParent()->result_id())) {
|
||||
transformation_context->GetFactManager()->AddFactFunctionIsLivesafe(
|
||||
message_.new_function_id());
|
||||
}
|
||||
|
||||
// Adapt the region to be outlined so that its input ids are replaced with the
|
||||
// ids of the outlined function's input parameters, and so that output ids
|
||||
// are similarly remapped.
|
||||
@ -375,10 +367,10 @@ void TransformationOutlineFunction::Apply(
|
||||
|
||||
// Fill out the body of the outlined function according to the region that is
|
||||
// being outlined.
|
||||
PopulateOutlinedFunction(
|
||||
*original_region_entry_block, *original_region_exit_block, region_blocks,
|
||||
region_output_ids, output_id_to_fresh_id_map, ir_context,
|
||||
outlined_function.get(), transformation_context);
|
||||
PopulateOutlinedFunction(*original_region_entry_block,
|
||||
*original_region_exit_block, region_blocks,
|
||||
region_output_ids, output_id_to_fresh_id_map,
|
||||
ir_context, outlined_function.get());
|
||||
|
||||
// Collapse the region that has been outlined into a function down to a single
|
||||
// block that calls said function.
|
||||
@ -389,11 +381,28 @@ void TransformationOutlineFunction::Apply(
|
||||
std::move(cloned_exit_block_terminator), original_region_entry_block);
|
||||
|
||||
// Add the outlined function to the module.
|
||||
const auto* outlined_function_ptr = outlined_function.get();
|
||||
ir_context->module()->AddFunction(std::move(outlined_function));
|
||||
|
||||
// Major surgery has been conducted on the module, so invalidate all analyses.
|
||||
ir_context->InvalidateAnalysesExceptFor(
|
||||
opt::IRContext::Analysis::kAnalysisNone);
|
||||
|
||||
// If the original function was livesafe, the new function should also be
|
||||
// livesafe.
|
||||
if (transformation_context->GetFactManager()->FunctionIsLivesafe(
|
||||
original_region_entry_block->GetParent()->result_id())) {
|
||||
transformation_context->GetFactManager()->AddFactFunctionIsLivesafe(
|
||||
message_.new_function_id());
|
||||
}
|
||||
|
||||
// Record the fact that all blocks in the outlined region are dead if the
|
||||
// first block is dead.
|
||||
if (transformation_context->GetFactManager()->BlockIsDead(
|
||||
original_region_entry_block->id())) {
|
||||
transformation_context->GetFactManager()->AddFactBlockIsDead(
|
||||
outlined_function_ptr->entry()->id());
|
||||
}
|
||||
}
|
||||
|
||||
protobufs::Transformation TransformationOutlineFunction::ToMessage() const {
|
||||
@ -750,8 +759,7 @@ void TransformationOutlineFunction::PopulateOutlinedFunction(
|
||||
const std::set<opt::BasicBlock*>& region_blocks,
|
||||
const std::vector<uint32_t>& region_output_ids,
|
||||
const std::map<uint32_t, uint32_t>& output_id_to_fresh_id_map,
|
||||
opt::IRContext* ir_context, opt::Function* outlined_function,
|
||||
TransformationContext* transformation_context) const {
|
||||
opt::IRContext* ir_context, opt::Function* outlined_function) const {
|
||||
// When we create the exit block for the outlined region, we use this pointer
|
||||
// to track of it so that we can manipulate it later.
|
||||
opt::BasicBlock* outlined_region_exit_block = nullptr;
|
||||
@ -765,14 +773,6 @@ void TransformationOutlineFunction::PopulateOutlinedFunction(
|
||||
opt::Instruction::OperandList()));
|
||||
outlined_region_entry_block->SetParent(outlined_function);
|
||||
|
||||
// If the original region's entry block was dead, the outlined region's entry
|
||||
// block is also dead.
|
||||
if (transformation_context->GetFactManager()->BlockIsDead(
|
||||
original_region_entry_block.id())) {
|
||||
transformation_context->GetFactManager()->AddFactBlockIsDead(
|
||||
outlined_region_entry_block->id());
|
||||
}
|
||||
|
||||
if (&original_region_entry_block == &original_region_exit_block) {
|
||||
outlined_region_exit_block = outlined_region_entry_block.get();
|
||||
}
|
||||
@ -879,7 +879,7 @@ void TransformationOutlineFunction::PopulateOutlinedFunction(
|
||||
}
|
||||
|
||||
void TransformationOutlineFunction::ShrinkOriginalRegion(
|
||||
opt::IRContext* ir_context, std::set<opt::BasicBlock*>& region_blocks,
|
||||
opt::IRContext* ir_context, const std::set<opt::BasicBlock*>& region_blocks,
|
||||
const std::vector<uint32_t>& region_input_ids,
|
||||
const std::vector<uint32_t>& region_output_ids,
|
||||
const std::map<uint32_t, uint32_t>& output_id_to_type_id,
|
||||
|
@ -189,8 +189,7 @@ class TransformationOutlineFunction : public Transformation {
|
||||
const std::set<opt::BasicBlock*>& region_blocks,
|
||||
const std::vector<uint32_t>& region_output_ids,
|
||||
const std::map<uint32_t, uint32_t>& output_id_to_fresh_id_map,
|
||||
opt::IRContext* ir_context, opt::Function* outlined_function,
|
||||
TransformationContext* transformation_context) const;
|
||||
opt::IRContext* ir_context, opt::Function* outlined_function) const;
|
||||
|
||||
// Shrinks the outlined region, given by |region_blocks|, down to the single
|
||||
// block |original_region_entry_block|. This block is itself shrunk to just
|
||||
@ -209,7 +208,8 @@ class TransformationOutlineFunction : public Transformation {
|
||||
// function is called, this information cannot be gotten from the def-use
|
||||
// manager.
|
||||
void ShrinkOriginalRegion(
|
||||
opt::IRContext* ir_context, std::set<opt::BasicBlock*>& region_blocks,
|
||||
opt::IRContext* ir_context,
|
||||
const std::set<opt::BasicBlock*>& region_blocks,
|
||||
const std::vector<uint32_t>& region_input_ids,
|
||||
const std::vector<uint32_t>& region_output_ids,
|
||||
const std::map<uint32_t, uint32_t>& output_id_to_type_id,
|
||||
|
@ -124,6 +124,10 @@ void TransformationSplitBlock::Apply(
|
||||
phi_inst->SetInOperand(1, {block_to_split->id()});
|
||||
});
|
||||
|
||||
// Invalidate all analyses
|
||||
ir_context->InvalidateAnalysesExceptFor(
|
||||
opt::IRContext::Analysis::kAnalysisNone);
|
||||
|
||||
// If the block being split was dead, the new block arising from the split is
|
||||
// also dead.
|
||||
if (transformation_context->GetFactManager()->BlockIsDead(
|
||||
@ -131,10 +135,6 @@ void TransformationSplitBlock::Apply(
|
||||
transformation_context->GetFactManager()->AddFactBlockIsDead(
|
||||
message_.fresh_id());
|
||||
}
|
||||
|
||||
// Invalidate all analyses
|
||||
ir_context->InvalidateAnalysesExceptFor(
|
||||
opt::IRContext::Analysis::kAnalysisNone);
|
||||
}
|
||||
|
||||
protobufs::Transformation TransformationSplitBlock::ToMessage() const {
|
||||
|
@ -125,19 +125,20 @@ TEST(DataSynonymTransformationTest, ArrayCompositeSynonyms) {
|
||||
spvtools::ValidatorOptions validator_options;
|
||||
TransformationContext transformation_context(
|
||||
MakeUnique<FactManager>(context.get()), validator_options);
|
||||
transformation_context.GetFactManager()->AddFact(
|
||||
|
||||
transformation_context.GetFactManager()->MaybeAddFact(
|
||||
MakeSynonymFact(12, {}, 100, {0}));
|
||||
transformation_context.GetFactManager()->AddFact(
|
||||
transformation_context.GetFactManager()->MaybeAddFact(
|
||||
MakeSynonymFact(13, {}, 100, {1}));
|
||||
transformation_context.GetFactManager()->AddFact(
|
||||
transformation_context.GetFactManager()->MaybeAddFact(
|
||||
MakeSynonymFact(22, {}, 100, {2}));
|
||||
transformation_context.GetFactManager()->AddFact(
|
||||
transformation_context.GetFactManager()->MaybeAddFact(
|
||||
MakeSynonymFact(28, {}, 101, {0}));
|
||||
transformation_context.GetFactManager()->AddFact(
|
||||
transformation_context.GetFactManager()->MaybeAddFact(
|
||||
MakeSynonymFact(23, {}, 101, {1}));
|
||||
transformation_context.GetFactManager()->AddFact(
|
||||
transformation_context.GetFactManager()->MaybeAddFact(
|
||||
MakeSynonymFact(32, {}, 101, {2}));
|
||||
transformation_context.GetFactManager()->AddFact(
|
||||
transformation_context.GetFactManager()->MaybeAddFact(
|
||||
MakeSynonymFact(23, {}, 101, {3}));
|
||||
|
||||
// Replace %12 with %100[0] in '%25 = OpAccessChain %24 %20 %12'
|
||||
@ -411,11 +412,12 @@ TEST(DataSynonymTransformationTest, MatrixCompositeSynonyms) {
|
||||
spvtools::ValidatorOptions validator_options;
|
||||
TransformationContext transformation_context(
|
||||
MakeUnique<FactManager>(context.get()), validator_options);
|
||||
transformation_context.GetFactManager()->AddFact(
|
||||
|
||||
transformation_context.GetFactManager()->MaybeAddFact(
|
||||
MakeSynonymFact(23, {}, 100, {0}));
|
||||
transformation_context.GetFactManager()->AddFact(
|
||||
transformation_context.GetFactManager()->MaybeAddFact(
|
||||
MakeSynonymFact(25, {}, 100, {1}));
|
||||
transformation_context.GetFactManager()->AddFact(
|
||||
transformation_context.GetFactManager()->MaybeAddFact(
|
||||
MakeSynonymFact(50, {}, 100, {2}));
|
||||
|
||||
// Replace %23 with %100[0] in '%26 = OpFAdd %7 %23 %25'
|
||||
@ -579,19 +581,20 @@ TEST(DataSynonymTransformationTest, StructCompositeSynonyms) {
|
||||
spvtools::ValidatorOptions validator_options;
|
||||
TransformationContext transformation_context(
|
||||
MakeUnique<FactManager>(context.get()), validator_options);
|
||||
transformation_context.GetFactManager()->AddFact(
|
||||
|
||||
transformation_context.GetFactManager()->MaybeAddFact(
|
||||
MakeSynonymFact(16, {}, 100, {0}));
|
||||
transformation_context.GetFactManager()->AddFact(
|
||||
transformation_context.GetFactManager()->MaybeAddFact(
|
||||
MakeSynonymFact(45, {}, 100, {1}));
|
||||
transformation_context.GetFactManager()->AddFact(
|
||||
transformation_context.GetFactManager()->MaybeAddFact(
|
||||
MakeSynonymFact(27, {}, 101, {0}));
|
||||
transformation_context.GetFactManager()->AddFact(
|
||||
transformation_context.GetFactManager()->MaybeAddFact(
|
||||
MakeSynonymFact(36, {}, 101, {1}));
|
||||
transformation_context.GetFactManager()->AddFact(
|
||||
transformation_context.GetFactManager()->MaybeAddFact(
|
||||
MakeSynonymFact(27, {}, 101, {2}));
|
||||
transformation_context.GetFactManager()->AddFact(
|
||||
transformation_context.GetFactManager()->MaybeAddFact(
|
||||
MakeSynonymFact(22, {}, 102, {0}));
|
||||
transformation_context.GetFactManager()->AddFact(
|
||||
transformation_context.GetFactManager()->MaybeAddFact(
|
||||
MakeSynonymFact(15, {}, 102, {1}));
|
||||
|
||||
// Replace %45 with %100[1] in '%46 = OpCompositeConstruct %32 %35 %45'
|
||||
@ -867,45 +870,46 @@ TEST(DataSynonymTransformationTest, VectorCompositeSynonyms) {
|
||||
spvtools::ValidatorOptions validator_options;
|
||||
TransformationContext transformation_context(
|
||||
MakeUnique<FactManager>(context.get()), validator_options);
|
||||
transformation_context.GetFactManager()->AddFact(
|
||||
|
||||
transformation_context.GetFactManager()->MaybeAddFact(
|
||||
MakeSynonymFact(20, {0}, 100, {0}));
|
||||
transformation_context.GetFactManager()->AddFact(
|
||||
transformation_context.GetFactManager()->MaybeAddFact(
|
||||
MakeSynonymFact(20, {1}, 100, {1}));
|
||||
transformation_context.GetFactManager()->AddFact(
|
||||
transformation_context.GetFactManager()->MaybeAddFact(
|
||||
MakeSynonymFact(20, {2}, 100, {2}));
|
||||
transformation_context.GetFactManager()->AddFact(
|
||||
transformation_context.GetFactManager()->MaybeAddFact(
|
||||
MakeSynonymFact(54, {}, 100, {3}));
|
||||
transformation_context.GetFactManager()->AddFact(
|
||||
transformation_context.GetFactManager()->MaybeAddFact(
|
||||
MakeSynonymFact(15, {0}, 101, {0}));
|
||||
transformation_context.GetFactManager()->AddFact(
|
||||
transformation_context.GetFactManager()->MaybeAddFact(
|
||||
MakeSynonymFact(15, {1}, 101, {1}));
|
||||
transformation_context.GetFactManager()->AddFact(
|
||||
transformation_context.GetFactManager()->MaybeAddFact(
|
||||
MakeSynonymFact(19, {0}, 101, {2}));
|
||||
transformation_context.GetFactManager()->AddFact(
|
||||
transformation_context.GetFactManager()->MaybeAddFact(
|
||||
MakeSynonymFact(19, {1}, 101, {3}));
|
||||
transformation_context.GetFactManager()->AddFact(
|
||||
transformation_context.GetFactManager()->MaybeAddFact(
|
||||
MakeSynonymFact(27, {}, 102, {0}));
|
||||
transformation_context.GetFactManager()->AddFact(
|
||||
transformation_context.GetFactManager()->MaybeAddFact(
|
||||
MakeSynonymFact(15, {0}, 102, {1}));
|
||||
transformation_context.GetFactManager()->AddFact(
|
||||
transformation_context.GetFactManager()->MaybeAddFact(
|
||||
MakeSynonymFact(15, {1}, 102, {2}));
|
||||
transformation_context.GetFactManager()->AddFact(
|
||||
transformation_context.GetFactManager()->MaybeAddFact(
|
||||
MakeSynonymFact(33, {}, 103, {0}));
|
||||
transformation_context.GetFactManager()->AddFact(
|
||||
transformation_context.GetFactManager()->MaybeAddFact(
|
||||
MakeSynonymFact(47, {0}, 103, {1}));
|
||||
transformation_context.GetFactManager()->AddFact(
|
||||
transformation_context.GetFactManager()->MaybeAddFact(
|
||||
MakeSynonymFact(47, {1}, 103, {2}));
|
||||
transformation_context.GetFactManager()->AddFact(
|
||||
transformation_context.GetFactManager()->MaybeAddFact(
|
||||
MakeSynonymFact(47, {2}, 103, {3}));
|
||||
transformation_context.GetFactManager()->AddFact(
|
||||
transformation_context.GetFactManager()->MaybeAddFact(
|
||||
MakeSynonymFact(42, {}, 104, {0}));
|
||||
transformation_context.GetFactManager()->AddFact(
|
||||
transformation_context.GetFactManager()->MaybeAddFact(
|
||||
MakeSynonymFact(45, {}, 104, {1}));
|
||||
transformation_context.GetFactManager()->AddFact(
|
||||
transformation_context.GetFactManager()->MaybeAddFact(
|
||||
MakeSynonymFact(38, {0}, 105, {0}));
|
||||
transformation_context.GetFactManager()->AddFact(
|
||||
transformation_context.GetFactManager()->MaybeAddFact(
|
||||
MakeSynonymFact(38, {1}, 105, {1}));
|
||||
transformation_context.GetFactManager()->AddFact(
|
||||
transformation_context.GetFactManager()->MaybeAddFact(
|
||||
MakeSynonymFact(46, {}, 105, {2}));
|
||||
|
||||
// Replace %20 with %100[0:2] in '%80 = OpCopyObject %16 %20'
|
||||
|
@ -45,7 +45,7 @@ bool AddFactHelper(
|
||||
descriptor;
|
||||
protobufs::Fact fact;
|
||||
*fact.mutable_constant_uniform_fact() = constant_uniform_fact;
|
||||
return fact_manager->AddFact(fact);
|
||||
return fact_manager->MaybeAddFact(fact);
|
||||
}
|
||||
|
||||
TEST(FactManagerTest, ConstantsAvailableViaUniforms) {
|
||||
|
@ -32,21 +32,21 @@ protobufs::Fact MakeSynonymFact(uint32_t first, uint32_t second) {
|
||||
// Adds synonym facts to the fact manager.
|
||||
void SetUpIdSynonyms(FactManager* fact_manager) {
|
||||
// Synonyms {9, 11, 15, 16, 21, 22}
|
||||
fact_manager->AddFact(MakeSynonymFact(11, 9));
|
||||
fact_manager->AddFact(MakeSynonymFact(15, 9));
|
||||
fact_manager->AddFact(MakeSynonymFact(16, 9));
|
||||
fact_manager->AddFact(MakeSynonymFact(21, 9));
|
||||
fact_manager->AddFact(MakeSynonymFact(22, 9));
|
||||
fact_manager->MaybeAddFact(MakeSynonymFact(11, 9));
|
||||
fact_manager->MaybeAddFact(MakeSynonymFact(15, 9));
|
||||
fact_manager->MaybeAddFact(MakeSynonymFact(16, 9));
|
||||
fact_manager->MaybeAddFact(MakeSynonymFact(21, 9));
|
||||
fact_manager->MaybeAddFact(MakeSynonymFact(22, 9));
|
||||
|
||||
// Synonyms {10, 23}
|
||||
fact_manager->AddFact(MakeSynonymFact(10, 23));
|
||||
fact_manager->MaybeAddFact(MakeSynonymFact(10, 23));
|
||||
|
||||
// Synonyms {14, 27}
|
||||
fact_manager->AddFact(MakeSynonymFact(14, 27));
|
||||
fact_manager->MaybeAddFact(MakeSynonymFact(14, 27));
|
||||
|
||||
// Synonyms {24, 26, 30}
|
||||
fact_manager->AddFact(MakeSynonymFact(26, 24));
|
||||
fact_manager->AddFact(MakeSynonymFact(30, 24));
|
||||
fact_manager->MaybeAddFact(MakeSynonymFact(26, 24));
|
||||
fact_manager->MaybeAddFact(MakeSynonymFact(30, 24));
|
||||
}
|
||||
|
||||
// Returns true if the given lists have the same elements, regardless of their
|
||||
|
@ -31,12 +31,12 @@ protobufs::Fact MakeSynonymFact(uint32_t first, uint32_t second) {
|
||||
|
||||
// Adds synonym facts to the fact manager.
|
||||
void SetUpIdSynonyms(FactManager* fact_manager) {
|
||||
fact_manager->AddFact(MakeSynonymFact(11, 9));
|
||||
fact_manager->AddFact(MakeSynonymFact(13, 9));
|
||||
fact_manager->AddFact(MakeSynonymFact(14, 9));
|
||||
fact_manager->AddFact(MakeSynonymFact(19, 9));
|
||||
fact_manager->AddFact(MakeSynonymFact(20, 9));
|
||||
fact_manager->AddFact(MakeSynonymFact(10, 21));
|
||||
fact_manager->MaybeAddFact(MakeSynonymFact(11, 9));
|
||||
fact_manager->MaybeAddFact(MakeSynonymFact(13, 9));
|
||||
fact_manager->MaybeAddFact(MakeSynonymFact(14, 9));
|
||||
fact_manager->MaybeAddFact(MakeSynonymFact(19, 9));
|
||||
fact_manager->MaybeAddFact(MakeSynonymFact(20, 9));
|
||||
fact_manager->MaybeAddFact(MakeSynonymFact(10, 21));
|
||||
}
|
||||
|
||||
TEST(TransformationAddOpPhiSynonymTest, Inapplicable) {
|
||||
@ -89,7 +89,8 @@ TEST(TransformationAddOpPhiSynonymTest, Inapplicable) {
|
||||
TransformationContext transformation_context(
|
||||
MakeUnique<FactManager>(context.get()), validator_options);
|
||||
SetUpIdSynonyms(transformation_context.GetFactManager());
|
||||
transformation_context.GetFactManager()->AddFact(MakeSynonymFact(23, 24));
|
||||
transformation_context.GetFactManager()->MaybeAddFact(
|
||||
MakeSynonymFact(23, 24));
|
||||
|
||||
// %13 is not a block label.
|
||||
ASSERT_FALSE(TransformationAddOpPhiSynonym(13, {{}}, 100)
|
||||
@ -211,8 +212,8 @@ TEST(TransformationAddOpPhiSynonymTest, Apply) {
|
||||
SetUpIdSynonyms(transformation_context.GetFactManager());
|
||||
|
||||
// Add some further synonym facts.
|
||||
transformation_context.GetFactManager()->AddFact(MakeSynonymFact(28, 9));
|
||||
transformation_context.GetFactManager()->AddFact(MakeSynonymFact(30, 9));
|
||||
transformation_context.GetFactManager()->MaybeAddFact(MakeSynonymFact(28, 9));
|
||||
transformation_context.GetFactManager()->MaybeAddFact(MakeSynonymFact(30, 9));
|
||||
|
||||
auto transformation1 = TransformationAddOpPhiSynonym(17, {{{15, 13}}}, 100);
|
||||
ASSERT_TRUE(
|
||||
@ -356,8 +357,9 @@ TEST(TransformationAddOpPhiSynonymTest, VariablePointers) {
|
||||
TransformationContext transformation_context(
|
||||
MakeUnique<FactManager>(context.get()), validator_options);
|
||||
// Declare synonyms
|
||||
transformation_context.GetFactManager()->AddFact(MakeSynonymFact(3, 15));
|
||||
transformation_context.GetFactManager()->AddFact(MakeSynonymFact(12, 16));
|
||||
transformation_context.GetFactManager()->MaybeAddFact(MakeSynonymFact(3, 15));
|
||||
transformation_context.GetFactManager()->MaybeAddFact(
|
||||
MakeSynonymFact(12, 16));
|
||||
|
||||
// Remove the VariablePointers capability.
|
||||
context.get()->get_feature_mgr()->RemoveCapability(
|
||||
|
@ -31,7 +31,7 @@ bool AddFactHelper(
|
||||
descriptor;
|
||||
protobufs::Fact fact;
|
||||
*fact.mutable_constant_uniform_fact() = constant_uniform_fact;
|
||||
return transformation_context->GetFactManager()->AddFact(fact);
|
||||
return transformation_context->GetFactManager()->MaybeAddFact(fact);
|
||||
}
|
||||
|
||||
TEST(TransformationReplaceConstantWithUniformTest, BasicReplacements) {
|
||||
|
@ -200,17 +200,17 @@ protobufs::Fact MakeSynonymFact(uint32_t first, uint32_t second) {
|
||||
|
||||
// Equips the fact manager with synonym facts for the above shader.
|
||||
void SetUpIdSynonyms(FactManager* fact_manager) {
|
||||
fact_manager->AddFact(MakeSynonymFact(15, 200));
|
||||
fact_manager->AddFact(MakeSynonymFact(15, 201));
|
||||
fact_manager->AddFact(MakeSynonymFact(15, 202));
|
||||
fact_manager->AddFact(MakeSynonymFact(55, 203));
|
||||
fact_manager->AddFact(MakeSynonymFact(54, 204));
|
||||
fact_manager->AddFact(MakeSynonymFact(74, 205));
|
||||
fact_manager->AddFact(MakeSynonymFact(78, 206));
|
||||
fact_manager->AddFact(MakeSynonymFact(84, 207));
|
||||
fact_manager->AddFact(MakeSynonymFact(33, 208));
|
||||
fact_manager->AddFact(MakeSynonymFact(12, 209));
|
||||
fact_manager->AddFact(MakeSynonymFact(19, 210));
|
||||
fact_manager->MaybeAddFact(MakeSynonymFact(15, 200));
|
||||
fact_manager->MaybeAddFact(MakeSynonymFact(15, 201));
|
||||
fact_manager->MaybeAddFact(MakeSynonymFact(15, 202));
|
||||
fact_manager->MaybeAddFact(MakeSynonymFact(55, 203));
|
||||
fact_manager->MaybeAddFact(MakeSynonymFact(54, 204));
|
||||
fact_manager->MaybeAddFact(MakeSynonymFact(74, 205));
|
||||
fact_manager->MaybeAddFact(MakeSynonymFact(78, 206));
|
||||
fact_manager->MaybeAddFact(MakeSynonymFact(84, 207));
|
||||
fact_manager->MaybeAddFact(MakeSynonymFact(33, 208));
|
||||
fact_manager->MaybeAddFact(MakeSynonymFact(12, 209));
|
||||
fact_manager->MaybeAddFact(MakeSynonymFact(19, 210));
|
||||
}
|
||||
|
||||
TEST(TransformationReplaceIdWithSynonymTest, IllegalTransformations) {
|
||||
@ -520,8 +520,10 @@ TEST(TransformationReplaceIdWithSynonymTest, SynonymsOfVariables) {
|
||||
spvtools::ValidatorOptions validator_options;
|
||||
TransformationContext transformation_context(
|
||||
MakeUnique<FactManager>(context.get()), validator_options);
|
||||
transformation_context.GetFactManager()->AddFact(MakeSynonymFact(10, 100));
|
||||
transformation_context.GetFactManager()->AddFact(MakeSynonymFact(8, 101));
|
||||
transformation_context.GetFactManager()->MaybeAddFact(
|
||||
MakeSynonymFact(10, 100));
|
||||
transformation_context.GetFactManager()->MaybeAddFact(
|
||||
MakeSynonymFact(8, 101));
|
||||
|
||||
// Replace %10 with %100 in:
|
||||
// %11 = OpLoad %6 %10
|
||||
@ -650,7 +652,8 @@ TEST(TransformationReplaceIdWithSynonymTest,
|
||||
spvtools::ValidatorOptions validator_options;
|
||||
TransformationContext transformation_context(
|
||||
MakeUnique<FactManager>(context.get()), validator_options);
|
||||
transformation_context.GetFactManager()->AddFact(MakeSynonymFact(14, 100));
|
||||
transformation_context.GetFactManager()->MaybeAddFact(
|
||||
MakeSynonymFact(14, 100));
|
||||
|
||||
// Replace %14 with %100 in:
|
||||
// %16 = OpFunctionCall %2 %10 %14
|
||||
@ -815,19 +818,32 @@ TEST(TransformationReplaceIdWithSynonymTest, SynonymsOfAccessChainIndices) {
|
||||
MakeUnique<FactManager>(context.get()), validator_options);
|
||||
// Add synonym facts corresponding to the OpCopyObject operations that have
|
||||
// been applied to all constants in the module.
|
||||
transformation_context.GetFactManager()->AddFact(MakeSynonymFact(16, 100));
|
||||
transformation_context.GetFactManager()->AddFact(MakeSynonymFact(21, 101));
|
||||
transformation_context.GetFactManager()->AddFact(MakeSynonymFact(17, 102));
|
||||
transformation_context.GetFactManager()->AddFact(MakeSynonymFact(57, 103));
|
||||
transformation_context.GetFactManager()->AddFact(MakeSynonymFact(18, 104));
|
||||
transformation_context.GetFactManager()->AddFact(MakeSynonymFact(40, 105));
|
||||
transformation_context.GetFactManager()->AddFact(MakeSynonymFact(32, 106));
|
||||
transformation_context.GetFactManager()->AddFact(MakeSynonymFact(43, 107));
|
||||
transformation_context.GetFactManager()->AddFact(MakeSynonymFact(55, 108));
|
||||
transformation_context.GetFactManager()->AddFact(MakeSynonymFact(8, 109));
|
||||
transformation_context.GetFactManager()->AddFact(MakeSynonymFact(47, 110));
|
||||
transformation_context.GetFactManager()->AddFact(MakeSynonymFact(28, 111));
|
||||
transformation_context.GetFactManager()->AddFact(MakeSynonymFact(45, 112));
|
||||
transformation_context.GetFactManager()->MaybeAddFact(
|
||||
MakeSynonymFact(16, 100));
|
||||
transformation_context.GetFactManager()->MaybeAddFact(
|
||||
MakeSynonymFact(21, 101));
|
||||
transformation_context.GetFactManager()->MaybeAddFact(
|
||||
MakeSynonymFact(17, 102));
|
||||
transformation_context.GetFactManager()->MaybeAddFact(
|
||||
MakeSynonymFact(57, 103));
|
||||
transformation_context.GetFactManager()->MaybeAddFact(
|
||||
MakeSynonymFact(18, 104));
|
||||
transformation_context.GetFactManager()->MaybeAddFact(
|
||||
MakeSynonymFact(40, 105));
|
||||
transformation_context.GetFactManager()->MaybeAddFact(
|
||||
MakeSynonymFact(32, 106));
|
||||
transformation_context.GetFactManager()->MaybeAddFact(
|
||||
MakeSynonymFact(43, 107));
|
||||
transformation_context.GetFactManager()->MaybeAddFact(
|
||||
MakeSynonymFact(55, 108));
|
||||
transformation_context.GetFactManager()->MaybeAddFact(
|
||||
MakeSynonymFact(8, 109));
|
||||
transformation_context.GetFactManager()->MaybeAddFact(
|
||||
MakeSynonymFact(47, 110));
|
||||
transformation_context.GetFactManager()->MaybeAddFact(
|
||||
MakeSynonymFact(28, 111));
|
||||
transformation_context.GetFactManager()->MaybeAddFact(
|
||||
MakeSynonymFact(45, 112));
|
||||
|
||||
// Replacements of the form %16 -> %100
|
||||
|
||||
@ -1300,9 +1316,11 @@ TEST(TransformationReplaceIdWithSynonymTest, RuntimeArrayTest) {
|
||||
TransformationContext transformation_context(
|
||||
MakeUnique<FactManager>(context.get()), validator_options);
|
||||
// Add synonym fact relating %50 and %12.
|
||||
transformation_context.GetFactManager()->AddFact(MakeSynonymFact(50, 12));
|
||||
transformation_context.GetFactManager()->MaybeAddFact(
|
||||
MakeSynonymFact(50, 12));
|
||||
// Add synonym fact relating %51 and %14.
|
||||
transformation_context.GetFactManager()->AddFact(MakeSynonymFact(51, 14));
|
||||
transformation_context.GetFactManager()->MaybeAddFact(
|
||||
MakeSynonymFact(51, 14));
|
||||
|
||||
// Not legal because the index being replaced is a struct index.
|
||||
ASSERT_FALSE(
|
||||
@ -1409,7 +1427,8 @@ TEST(TransformationReplaceIdWithSynonymTest,
|
||||
TransformationContext transformation_context(
|
||||
MakeUnique<FactManager>(context.get()), validator_options);
|
||||
// Add synonym fact relating %100 and %9.
|
||||
transformation_context.GetFactManager()->AddFact(MakeSynonymFact(100, 9));
|
||||
transformation_context.GetFactManager()->MaybeAddFact(
|
||||
MakeSynonymFact(100, 9));
|
||||
|
||||
// Not legal the Sample argument of OpImageTexelPointer needs to be a zero
|
||||
// constant.
|
||||
@ -1469,7 +1488,8 @@ TEST(TransformationReplaceIdWithSynonymTest, EquivalentIntegerConstants) {
|
||||
MakeUnique<FactManager>(context.get()), validator_options);
|
||||
// Add synonym fact relating %10 and %13 (equivalent integer constant with
|
||||
// different signedness).
|
||||
transformation_context.GetFactManager()->AddFact(MakeSynonymFact(10, 13));
|
||||
transformation_context.GetFactManager()->MaybeAddFact(
|
||||
MakeSynonymFact(10, 13));
|
||||
|
||||
// Legal because OpSNegate always considers the integer as signed
|
||||
auto replacement1 = TransformationReplaceIdWithSynonym(
|
||||
@ -1611,7 +1631,8 @@ TEST(TransformationReplaceIdWithSynonymTest, EquivalentIntegerVectorConstants) {
|
||||
MakeUnique<FactManager>(context.get()), validator_options);
|
||||
// Add synonym fact relating %10 and %13 (equivalent integer vectors with
|
||||
// different signedness).
|
||||
transformation_context.GetFactManager()->AddFact(MakeSynonymFact(14, 15));
|
||||
transformation_context.GetFactManager()->MaybeAddFact(
|
||||
MakeSynonymFact(14, 15));
|
||||
|
||||
// Legal because OpIAdd does not consider the signedness of the operands
|
||||
auto replacement1 = TransformationReplaceIdWithSynonym(
|
||||
@ -1630,7 +1651,8 @@ TEST(TransformationReplaceIdWithSynonymTest, EquivalentIntegerVectorConstants) {
|
||||
|
||||
// Add synonym fact relating %12 and %13 (equivalent integer constants with
|
||||
// different signedness).
|
||||
transformation_context.GetFactManager()->AddFact(MakeSynonymFact(12, 13));
|
||||
transformation_context.GetFactManager()->MaybeAddFact(
|
||||
MakeSynonymFact(12, 13));
|
||||
|
||||
// Legal because the indices of OpAccessChain are always treated as signed
|
||||
auto replacement2 = TransformationReplaceIdWithSynonym(
|
||||
|
Loading…
Reference in New Issue
Block a user