spirv-fuzz: Support bitwise or and xor in TransformationAddBitInstructionSynonym (#4310)

Fixes #4172.
This commit is contained in:
EGJ1996 2021-06-09 17:23:26 +02:00 committed by GitHub
parent d07505c761
commit c1a75bfabf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 88 additions and 47 deletions

View File

@ -79,6 +79,8 @@ void FuzzerPassAddSynonyms::Apply() {
case protobufs::TransformationAddSynonym::ADD_ZERO:
case protobufs::TransformationAddSynonym::SUB_ZERO:
case protobufs::TransformationAddSynonym::LOGICAL_OR:
case protobufs::TransformationAddSynonym::BITWISE_OR:
case protobufs::TransformationAddSynonym::BITWISE_XOR:
// Create a zero constant to be used as an operand of the synonymous
// instruction.
FindOrCreateZeroConstant(existing_synonym->type_id(), false);

View File

@ -1136,6 +1136,14 @@ message TransformationAddSynonym {
// New synonym is derived by applying OpLogicalAnd to |result_id| with the second
// operand being 'true'.
LOGICAL_AND = 5;
// New synonym is derived by applying OpBitwiseOr to |result_id| with the second
// operand being 0 taken with the same bit length as |result_id|
BITWISE_OR = 6;
// New synonym is derived by applying OpBitwiseXor to |result_id| with the second
// operand being 0 taken with the same bit length as |result_id|
BITWISE_XOR = 7;
}
// Type of the synonym to create. See SynonymType for more details.

View File

@ -170,6 +170,18 @@ bool TransformationAddSynonym::IsInstructionValid(
return type->AsInteger() || type->AsFloat();
}
case protobufs::TransformationAddSynonym::BITWISE_OR:
case protobufs::TransformationAddSynonym::BITWISE_XOR: {
// The instruction must be either an integer or a vector of integers.
const auto* type = ir_context->get_type_mgr()->GetType(inst->type_id());
assert(type && "Instruction's result id is invalid");
if (const auto* vector = type->AsVector()) {
return vector->element_type()->AsInteger();
}
return type->AsInteger();
}
case protobufs::TransformationAddSynonym::COPY_OBJECT:
// All checks for OpCopyObject are handled by
// fuzzerutil::CanMakeSynonymOf.
@ -195,68 +207,56 @@ TransformationAddSynonym::MakeSynonymousInstruction(
auto synonym_type_id =
fuzzerutil::GetTypeId(ir_context, message_.result_id());
assert(synonym_type_id && "Synonym has invalid type id");
auto opcode = SpvOpNop;
const auto* synonym_type =
ir_context->get_type_mgr()->GetType(synonym_type_id);
assert(synonym_type && "Synonym has invalid type");
auto is_integral = (synonym_type->AsVector() &&
synonym_type->AsVector()->element_type()->AsInteger()) ||
synonym_type->AsInteger();
switch (message_.synonym_type()) {
case protobufs::TransformationAddSynonym::SUB_ZERO:
opcode = is_integral ? SpvOpISub : SpvOpFSub;
break;
case protobufs::TransformationAddSynonym::MUL_ONE:
case protobufs::TransformationAddSynonym::ADD_ZERO: {
const auto* synonym_type =
ir_context->get_type_mgr()->GetType(synonym_type_id);
assert(synonym_type && "Synonym has invalid type");
opcode = is_integral ? SpvOpIMul : SpvOpFMul;
break;
case protobufs::TransformationAddSynonym::ADD_ZERO:
opcode = is_integral ? SpvOpIAdd : SpvOpFAdd;
break;
case protobufs::TransformationAddSynonym::LOGICAL_OR:
opcode = SpvOpLogicalOr;
break;
case protobufs::TransformationAddSynonym::LOGICAL_AND:
opcode = SpvOpLogicalAnd;
break;
case protobufs::TransformationAddSynonym::BITWISE_OR:
opcode = SpvOpBitwiseOr;
break;
case protobufs::TransformationAddSynonym::BITWISE_XOR:
opcode = SpvOpBitwiseXor;
break;
// Compute instruction's opcode based on the type of the operand.
// We have already checked that the operand is either a scalar or a vector
// of either integers or floats.
auto is_integral =
(synonym_type->AsVector() &&
synonym_type->AsVector()->element_type()->AsInteger()) ||
synonym_type->AsInteger();
auto opcode = SpvOpNop;
switch (message_.synonym_type()) {
case protobufs::TransformationAddSynonym::SUB_ZERO:
opcode = is_integral ? SpvOpISub : SpvOpFSub;
break;
case protobufs::TransformationAddSynonym::MUL_ONE:
opcode = is_integral ? SpvOpIMul : SpvOpFMul;
break;
case protobufs::TransformationAddSynonym::ADD_ZERO:
opcode = is_integral ? SpvOpIAdd : SpvOpFAdd;
break;
default:
assert(false && "Unreachable");
break;
}
return MakeUnique<opt::Instruction>(
ir_context, opcode, synonym_type_id, message_.synonym_fresh_id(),
opt::Instruction::OperandList{
{SPV_OPERAND_TYPE_ID, {message_.result_id()}},
{SPV_OPERAND_TYPE_ID,
{MaybeGetConstantId(ir_context, transformation_context)}}});
}
case protobufs::TransformationAddSynonym::COPY_OBJECT:
return MakeUnique<opt::Instruction>(
ir_context, SpvOpCopyObject, synonym_type_id,
message_.synonym_fresh_id(),
opt::Instruction::OperandList{
{SPV_OPERAND_TYPE_ID, {message_.result_id()}}});
case protobufs::TransformationAddSynonym::LOGICAL_OR:
case protobufs::TransformationAddSynonym::LOGICAL_AND: {
auto opcode = message_.synonym_type() ==
protobufs::TransformationAddSynonym::LOGICAL_OR
? SpvOpLogicalOr
: SpvOpLogicalAnd;
return MakeUnique<opt::Instruction>(
ir_context, opcode, synonym_type_id, message_.synonym_fresh_id(),
opt::Instruction::OperandList{
{SPV_OPERAND_TYPE_ID, {message_.result_id()}},
{SPV_OPERAND_TYPE_ID,
{MaybeGetConstantId(ir_context, transformation_context)}}});
}
default:
assert(false && "Unhandled synonym type");
return nullptr;
}
return MakeUnique<opt::Instruction>(
ir_context, opcode, synonym_type_id, message_.synonym_fresh_id(),
opt::Instruction::OperandList{
{SPV_OPERAND_TYPE_ID, {message_.result_id()}},
{SPV_OPERAND_TYPE_ID,
{MaybeGetConstantId(ir_context, transformation_context)}}});
}
uint32_t TransformationAddSynonym::MaybeGetConstantId(
@ -273,6 +273,8 @@ uint32_t TransformationAddSynonym::MaybeGetConstantId(
case protobufs::TransformationAddSynonym::ADD_ZERO:
case protobufs::TransformationAddSynonym::SUB_ZERO:
case protobufs::TransformationAddSynonym::LOGICAL_OR:
case protobufs::TransformationAddSynonym::BITWISE_OR:
case protobufs::TransformationAddSynonym::BITWISE_XOR:
return fuzzerutil::MaybeGetZeroConstant(
ir_context, transformation_context, synonym_type_id, false);
case protobufs::TransformationAddSynonym::MUL_ONE:
@ -319,6 +321,8 @@ bool TransformationAddSynonym::IsAdditionalConstantRequired(
case protobufs::TransformationAddSynonym::LOGICAL_OR:
case protobufs::TransformationAddSynonym::MUL_ONE:
case protobufs::TransformationAddSynonym::LOGICAL_AND:
case protobufs::TransformationAddSynonym::BITWISE_OR:
case protobufs::TransformationAddSynonym::BITWISE_XOR:
return true;
default:
return false;

View File

@ -197,6 +197,7 @@ TEST(TransformationAddSynonymTest, AddZeroSubZeroMulOne) {
%37 = OpTypeVector %36 2
%38 = OpConstantTrue %36
%39 = OpConstantComposite %37 %38 %38
%40 = OpConstant %6 37
%4 = OpFunction %2 None %3
%5 = OpLabel
OpReturn
@ -249,6 +250,29 @@ TEST(TransformationAddSynonymTest, AddZeroSubZeroMulOne) {
++fresh_id;
}
}
{
TransformationAddSynonym transformation(
40, protobufs::TransformationAddSynonym::BITWISE_OR, fresh_id,
insert_before);
ASSERT_TRUE(
transformation.IsApplicable(context.get(), transformation_context));
ApplyAndCheckFreshIds(transformation, context.get(),
&transformation_context);
ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
MakeDataDescriptor(40, {}), MakeDataDescriptor(fresh_id, {})));
++fresh_id;
}
{
TransformationAddSynonym transformation(
40, protobufs::TransformationAddSynonym::BITWISE_XOR, fresh_id,
insert_before);
ASSERT_TRUE(
transformation.IsApplicable(context.get(), transformation_context));
ApplyAndCheckFreshIds(transformation, context.get(),
&transformation_context);
ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
MakeDataDescriptor(40, {}), MakeDataDescriptor(fresh_id, {})));
}
std::string expected_shader = R"(
OpCapability Shader
@ -289,6 +313,7 @@ TEST(TransformationAddSynonymTest, AddZeroSubZeroMulOne) {
%37 = OpTypeVector %36 2
%38 = OpConstantTrue %36
%39 = OpConstantComposite %37 %38 %38
%40 = OpConstant %6 37
%4 = OpFunction %2 None %3
%5 = OpLabel
%50 = OpIAdd %6 %9 %7
@ -303,6 +328,8 @@ TEST(TransformationAddSynonymTest, AddZeroSubZeroMulOne) {
%59 = OpFMul %14 %17 %16
%60 = OpFMul %18 %23 %20
%61 = OpIMul %24 %29 %26
%62 = OpBitwiseOr %6 %40 %7
%63 = OpBitwiseXor %6 %40 %7
OpReturn
OpFunctionEnd
)";