mirror of
https://github.com/KhronosGroup/SPIRV-Tools
synced 2024-11-26 05:10:05 +00:00
spirv-fuzz: Support bitwise or and xor in TransformationAddBitInstructionSynonym (#4310)
Fixes #4172.
This commit is contained in:
parent
d07505c761
commit
c1a75bfabf
@ -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);
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
)";
|
||||
|
Loading…
Reference in New Issue
Block a user