spirv-fuzz: Support bitwise or and xor in TransformationAddBitInstructionSynonym (#4310)
Fixes #4172.
diff --git a/source/fuzz/fuzzer_pass_add_synonyms.cpp b/source/fuzz/fuzzer_pass_add_synonyms.cpp
index 2a85e52..fd866f9 100644
--- a/source/fuzz/fuzzer_pass_add_synonyms.cpp
+++ b/source/fuzz/fuzzer_pass_add_synonyms.cpp
@@ -79,6 +79,8 @@
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);
diff --git a/source/fuzz/protobufs/spvtoolsfuzz.proto b/source/fuzz/protobufs/spvtoolsfuzz.proto
index eadf824..657e807 100644
--- a/source/fuzz/protobufs/spvtoolsfuzz.proto
+++ b/source/fuzz/protobufs/spvtoolsfuzz.proto
@@ -1136,6 +1136,14 @@
// 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.
diff --git a/source/fuzz/transformation_add_synonym.cpp b/source/fuzz/transformation_add_synonym.cpp
index 40768e2..a1949fb 100644
--- a/source/fuzz/transformation_add_synonym.cpp
+++ b/source/fuzz/transformation_add_synonym.cpp
@@ -170,6 +170,18 @@
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 @@
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 @@
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 @@
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;
diff --git a/test/fuzz/transformation_add_synonym_test.cpp b/test/fuzz/transformation_add_synonym_test.cpp
index 3803fa3..314b003 100644
--- a/test/fuzz/transformation_add_synonym_test.cpp
+++ b/test/fuzz/transformation_add_synonym_test.cpp
@@ -197,6 +197,7 @@
%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 @@
++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 @@
%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 @@
%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
)";