#include "source/fuzz/transformation_replace_linear_algebra_instruction.h"
#include "source/fuzz/fuzzer_util.h"
#include "source/fuzz/instruction_descriptor.h"
namespace spvtools {
namespace fuzz {
TransformationReplaceLinearAlgebraInstruction::
TransformationReplaceLinearAlgebraInstruction(
protobufs::TransformationReplaceLinearAlgebraInstruction message)
: message_(std::move(message)) {}
TransformationReplaceLinearAlgebraInstruction::
TransformationReplaceLinearAlgebraInstruction(
const std::vector<uint32_t>& fresh_ids,
const protobufs::InstructionDescriptor& instruction_descriptor) {
for (auto fresh_id : fresh_ids) {
message_.add_fresh_ids(fresh_id);
}
*message_.mutable_instruction_descriptor() = instruction_descriptor;
}
bool TransformationReplaceLinearAlgebraInstruction::IsApplicable(
opt::IRContext* ir_context, const TransformationContext& ) const {
auto instruction =
FindInstruction(message_.instruction_descriptor(), ir_context);
if (!spvOpcodeIsLinearAlgebra(instruction->opcode())) {
return false;
}
if (static_cast<uint32_t>(message_.fresh_ids().size()) !=
GetRequiredFreshIdCount(ir_context, instruction)) {
return false;
}
for (uint32_t fresh_id : message_.fresh_ids()) {
if (!fuzzerutil::IsFreshId(ir_context, fresh_id)) {
return false;
}
}
return true;
}
void TransformationReplaceLinearAlgebraInstruction::Apply(
opt::IRContext* ir_context, TransformationContext* ) const {
auto linear_algebra_instruction =
FindInstruction(message_.instruction_descriptor(), ir_context);
switch (linear_algebra_instruction->opcode()) {
case spv::Op::OpTranspose:
ReplaceOpTranspose(ir_context, linear_algebra_instruction);
break;
case spv::Op::OpVectorTimesScalar:
ReplaceOpVectorTimesScalar(ir_context, linear_algebra_instruction);
break;
case spv::Op::OpMatrixTimesScalar:
ReplaceOpMatrixTimesScalar(ir_context, linear_algebra_instruction);
break;
case spv::Op::OpVectorTimesMatrix:
ReplaceOpVectorTimesMatrix(ir_context, linear_algebra_instruction);
break;
case spv::Op::OpMatrixTimesVector:
ReplaceOpMatrixTimesVector(ir_context, linear_algebra_instruction);
break;
case spv::Op::OpMatrixTimesMatrix:
ReplaceOpMatrixTimesMatrix(ir_context, linear_algebra_instruction);
break;
case spv::Op::OpOuterProduct:
ReplaceOpOuterProduct(ir_context, linear_algebra_instruction);
break;
case spv::Op::OpDot:
ReplaceOpDot(ir_context, linear_algebra_instruction);
break;
default:
assert(false && "Should be unreachable.");
break;
}
ir_context->InvalidateAnalysesExceptFor(opt::IRContext::kAnalysisNone);
}
protobufs::Transformation
TransformationReplaceLinearAlgebraInstruction::ToMessage() const {
protobufs::Transformation result;
*result.mutable_replace_linear_algebra_instruction() = message_;
return result;
}
uint32_t TransformationReplaceLinearAlgebraInstruction::GetRequiredFreshIdCount(
opt::IRContext* ir_context, opt::Instruction* instruction) {
switch (instruction->opcode()) {
case spv::Op::OpTranspose: {
auto matrix_instruction = ir_context->get_def_use_mgr()->GetDef(
instruction->GetSingleWordInOperand(0));
uint32_t matrix_column_count =
ir_context->get_type_mgr()
->GetType(matrix_instruction->type_id())
->AsMatrix()
->element_count();
uint32_t matrix_row_count = ir_context->get_type_mgr()
->GetType(matrix_instruction->type_id())
->AsMatrix()
->element_type()
->AsVector()
->element_count();
return matrix_row_count * (2 * matrix_column_count + 1);
}
case spv::Op::OpVectorTimesScalar:
return 2 *
ir_context->get_type_mgr()
->GetType(ir_context->get_def_use_mgr()
->GetDef(instruction->GetSingleWordInOperand(0))
->type_id())
->AsVector()
->element_count();
case spv::Op::OpMatrixTimesScalar: {
auto matrix_instruction = ir_context->get_def_use_mgr()->GetDef(
instruction->GetSingleWordInOperand(0));
auto matrix_type =
ir_context->get_type_mgr()->GetType(matrix_instruction->type_id());
return 2 * matrix_type->AsMatrix()->element_count() *
(1 + matrix_type->AsMatrix()
->element_type()
->AsVector()
->element_count());
}
case spv::Op::OpVectorTimesMatrix: {
auto vector_instruction = ir_context->get_def_use_mgr()->GetDef(
instruction->GetSingleWordInOperand(0));
auto matrix_instruction = ir_context->get_def_use_mgr()->GetDef(
instruction->GetSingleWordInOperand(1));
uint32_t vector_component_count =
ir_context->get_type_mgr()
->GetType(vector_instruction->type_id())
->AsVector()
->element_count();
uint32_t matrix_column_count =
ir_context->get_type_mgr()
->GetType(matrix_instruction->type_id())
->AsMatrix()
->element_count();
return vector_component_count * (3 * matrix_column_count + 1);
}
case spv::Op::OpMatrixTimesVector: {
auto matrix_instruction = ir_context->get_def_use_mgr()->GetDef(
instruction->GetSingleWordInOperand(0));
uint32_t matrix_column_count =
ir_context->get_type_mgr()
->GetType(matrix_instruction->type_id())
->AsMatrix()
->element_count();
uint32_t matrix_row_count = ir_context->get_type_mgr()
->GetType(matrix_instruction->type_id())
->AsMatrix()
->element_type()
->AsVector()
->element_count();
return 3 * matrix_column_count * matrix_row_count +
2 * matrix_column_count - matrix_row_count;
}
case spv::Op::OpMatrixTimesMatrix: {
auto matrix_1_instruction = ir_context->get_def_use_mgr()->GetDef(
instruction->GetSingleWordInOperand(0));
uint32_t matrix_1_column_count =
ir_context->get_type_mgr()
->GetType(matrix_1_instruction->type_id())
->AsMatrix()
->element_count();
uint32_t matrix_1_row_count =
ir_context->get_type_mgr()
->GetType(matrix_1_instruction->type_id())
->AsMatrix()
->element_type()
->AsVector()
->element_count();
auto matrix_2_instruction = ir_context->get_def_use_mgr()->GetDef(
instruction->GetSingleWordInOperand(1));
uint32_t matrix_2_column_count =
ir_context->get_type_mgr()
->GetType(matrix_2_instruction->type_id())
->AsMatrix()
->element_count();
return matrix_2_column_count *
(2 + matrix_1_row_count * (5 * matrix_1_column_count - 1));
}
case spv::Op::OpOuterProduct: {
auto vector_1_instruction = ir_context->get_def_use_mgr()->GetDef(
instruction->GetSingleWordInOperand(0));
auto vector_2_instruction = ir_context->get_def_use_mgr()->GetDef(
instruction->GetSingleWordInOperand(1));
uint32_t vector_1_component_count =
ir_context->get_type_mgr()
->GetType(vector_1_instruction->type_id())
->AsVector()
->element_count();
uint32_t vector_2_component_count =
ir_context->get_type_mgr()
->GetType(vector_2_instruction->type_id())
->AsVector()
->element_count();
return 2 * vector_2_component_count * (vector_1_component_count + 1);
}
case spv::Op::OpDot:
return 4 * ir_context->get_type_mgr()
->GetType(
ir_context->get_def_use_mgr()
->GetDef(instruction->GetSingleWordInOperand(0))
->type_id())
->AsVector()
->element_count() -
2;
default:
assert(false && "Unsupported linear algebra instruction.");
return 0;
}
}
void TransformationReplaceLinearAlgebraInstruction::ReplaceOpTranspose(
opt::IRContext* ir_context,
opt::Instruction* linear_algebra_instruction) const {
auto matrix_instruction = ir_context->get_def_use_mgr()->GetDef(
linear_algebra_instruction->GetSingleWordInOperand(0));
uint32_t matrix_column_count = ir_context->get_type_mgr()
->GetType(matrix_instruction->type_id())
->AsMatrix()
->element_count();
auto matrix_column_type = ir_context->get_type_mgr()
->GetType(matrix_instruction->type_id())
->AsMatrix()
->element_type();
auto matrix_column_component_type =
matrix_column_type->AsVector()->element_type();
uint32_t matrix_row_count = matrix_column_type->AsVector()->element_count();
auto resulting_matrix_column_type =
ir_context->get_type_mgr()
->GetType(linear_algebra_instruction->type_id())
->AsMatrix()
->element_type();
uint32_t fresh_id_index = 0;
std::vector<uint32_t> result_column_ids(matrix_row_count);
for (uint32_t i = 0; i < matrix_row_count; i++) {
std::vector<uint32_t> column_component_ids(matrix_column_count);
for (uint32_t j = 0; j < matrix_column_count; j++) {
uint32_t matrix_column_id = message_.fresh_ids(fresh_id_index++);
linear_algebra_instruction->InsertBefore(MakeUnique<opt::Instruction>(
ir_context, spv::Op::OpCompositeExtract,
ir_context->get_type_mgr()->GetId(matrix_column_type),
matrix_column_id,
opt::Instruction::OperandList(
{{SPV_OPERAND_TYPE_ID, {matrix_instruction->result_id()}},
{SPV_OPERAND_TYPE_LITERAL_INTEGER, {j}}})));
column_component_ids[j] = message_.fresh_ids(fresh_id_index++);
linear_algebra_instruction->InsertBefore(MakeUnique<opt::Instruction>(
ir_context, spv::Op::OpCompositeExtract,
ir_context->get_type_mgr()->GetId(matrix_column_component_type),
column_component_ids[j],
opt::Instruction::OperandList(
{{SPV_OPERAND_TYPE_ID, {matrix_column_id}},
{SPV_OPERAND_TYPE_LITERAL_INTEGER, {i}}})));
}
opt::Instruction::OperandList in_operands;
for (auto& column_component_id : column_component_ids) {
in_operands.push_back({SPV_OPERAND_TYPE_ID, {column_component_id}});
}
result_column_ids[i] = message_.fresh_ids(fresh_id_index++);
linear_algebra_instruction->InsertBefore(MakeUnique<opt::Instruction>(
ir_context, spv::Op::OpCompositeConstruct,
ir_context->get_type_mgr()->GetId(resulting_matrix_column_type),
result_column_ids[i], opt::Instruction::OperandList(in_operands)));
}
linear_algebra_instruction->SetOpcode(spv::Op::OpCompositeConstruct);
linear_algebra_instruction->SetInOperand(0, {result_column_ids[0]});
for (uint32_t i = 1; i < result_column_ids.size(); i++) {
linear_algebra_instruction->AddOperand(
{SPV_OPERAND_TYPE_ID, {result_column_ids[i]}});
}
fuzzerutil::UpdateModuleIdBound(
ir_context, message_.fresh_ids(message_.fresh_ids().size() - 1));
}
void TransformationReplaceLinearAlgebraInstruction::ReplaceOpVectorTimesScalar(
opt::IRContext* ir_context,
opt::Instruction* linear_algebra_instruction) const {
auto vector = ir_context->get_def_use_mgr()->GetDef(
linear_algebra_instruction->GetSingleWordInOperand(0));
auto scalar = ir_context->get_def_use_mgr()->GetDef(
linear_algebra_instruction->GetSingleWordInOperand(1));
uint32_t vector_component_count = ir_context->get_type_mgr()
->GetType(vector->type_id())
->AsVector()
->element_count();
std::vector<uint32_t> float_multiplication_ids(vector_component_count);
uint32_t fresh_id_index = 0;
for (uint32_t i = 0; i < vector_component_count; i++) {
uint32_t vector_extract_id = message_.fresh_ids(fresh_id_index++);
fuzzerutil::UpdateModuleIdBound(ir_context, vector_extract_id);
linear_algebra_instruction->InsertBefore(MakeUnique<opt::Instruction>(
ir_context, spv::Op::OpCompositeExtract, scalar->type_id(),
vector_extract_id,
opt::Instruction::OperandList(
{{SPV_OPERAND_TYPE_ID, {vector->result_id()}},
{SPV_OPERAND_TYPE_LITERAL_INTEGER, {i}}})));
uint32_t float_multiplication_id = message_.fresh_ids(fresh_id_index++);
float_multiplication_ids[i] = float_multiplication_id;
fuzzerutil::UpdateModuleIdBound(ir_context, float_multiplication_id);
linear_algebra_instruction->InsertBefore(MakeUnique<opt::Instruction>(
ir_context, spv::Op::OpFMul, scalar->type_id(), float_multiplication_id,
opt::Instruction::OperandList(
{{SPV_OPERAND_TYPE_ID, {vector_extract_id}},
{SPV_OPERAND_TYPE_ID, {scalar->result_id()}}})));
}
linear_algebra_instruction->SetOpcode(spv::Op::OpCompositeConstruct);
linear_algebra_instruction->SetInOperand(0, {float_multiplication_ids[0]});
linear_algebra_instruction->SetInOperand(1, {float_multiplication_ids[1]});
for (uint32_t i = 2; i < float_multiplication_ids.size(); i++) {
linear_algebra_instruction->AddOperand(
{SPV_OPERAND_TYPE_ID, {float_multiplication_ids[i]}});
}
}
void TransformationReplaceLinearAlgebraInstruction::ReplaceOpMatrixTimesScalar(
opt::IRContext* ir_context,
opt::Instruction* linear_algebra_instruction) const {
auto matrix_instruction = ir_context->get_def_use_mgr()->GetDef(
linear_algebra_instruction->GetSingleWordInOperand(0));
auto scalar_instruction = ir_context->get_def_use_mgr()->GetDef(
linear_algebra_instruction->GetSingleWordInOperand(1));
uint32_t matrix_column_count = ir_context->get_type_mgr()
->GetType(matrix_instruction->type_id())
->AsMatrix()
->element_count();
auto matrix_column_type = ir_context->get_type_mgr()
->GetType(matrix_instruction->type_id())
->AsMatrix()
->element_type();
uint32_t matrix_column_size = matrix_column_type->AsVector()->element_count();
std::vector<uint32_t> composite_construct_ids(matrix_column_count);
uint32_t fresh_id_index = 0;
for (uint32_t i = 0; i < matrix_column_count; i++) {
uint32_t matrix_extract_id = message_.fresh_ids(fresh_id_index++);
fuzzerutil::UpdateModuleIdBound(ir_context, matrix_extract_id);
linear_algebra_instruction->InsertBefore(MakeUnique<opt::Instruction>(
ir_context, spv::Op::OpCompositeExtract,
ir_context->get_type_mgr()->GetId(matrix_column_type),
matrix_extract_id,
opt::Instruction::OperandList(
{{SPV_OPERAND_TYPE_ID, {matrix_instruction->result_id()}},
{SPV_OPERAND_TYPE_LITERAL_INTEGER, {i}}})));
std::vector<uint32_t> float_multiplication_ids(matrix_column_size);
for (uint32_t j = 0; j < matrix_column_size; j++) {
uint32_t column_extract_id = message_.fresh_ids(fresh_id_index++);
fuzzerutil::UpdateModuleIdBound(ir_context, column_extract_id);
linear_algebra_instruction->InsertBefore(MakeUnique<opt::Instruction>(
ir_context, spv::Op::OpCompositeExtract,
scalar_instruction->type_id(), column_extract_id,
opt::Instruction::OperandList(
{{SPV_OPERAND_TYPE_ID, {matrix_extract_id}},
{SPV_OPERAND_TYPE_LITERAL_INTEGER, {j}}})));
float_multiplication_ids[j] = message_.fresh_ids(fresh_id_index++);
fuzzerutil::UpdateModuleIdBound(ir_context, float_multiplication_ids[j]);
linear_algebra_instruction->InsertBefore(MakeUnique<opt::Instruction>(
ir_context, spv::Op::OpFMul, scalar_instruction->type_id(),
float_multiplication_ids[j],
opt::Instruction::OperandList(
{{SPV_OPERAND_TYPE_ID, {column_extract_id}},
{SPV_OPERAND_TYPE_ID, {scalar_instruction->result_id()}}})));
}
opt::Instruction::OperandList composite_construct_in_operands;
for (uint32_t& float_multiplication_id : float_multiplication_ids) {
composite_construct_in_operands.push_back(
{SPV_OPERAND_TYPE_ID, {float_multiplication_id}});
}
composite_construct_ids[i] = message_.fresh_ids(fresh_id_index++);
fuzzerutil::UpdateModuleIdBound(ir_context, composite_construct_ids[i]);
linear_algebra_instruction->InsertBefore(MakeUnique<opt::Instruction>(
ir_context, spv::Op::OpCompositeConstruct,
ir_context->get_type_mgr()->GetId(matrix_column_type),
composite_construct_ids[i], composite_construct_in_operands));
}
linear_algebra_instruction->SetOpcode(spv::Op::OpCompositeConstruct);
linear_algebra_instruction->SetInOperand(0, {composite_construct_ids[0]});
linear_algebra_instruction->SetInOperand(1, {composite_construct_ids[1]});
for (uint32_t i = 2; i < composite_construct_ids.size(); i++) {
linear_algebra_instruction->AddOperand(
{SPV_OPERAND_TYPE_ID, {composite_construct_ids[i]}});
}
}
void TransformationReplaceLinearAlgebraInstruction::ReplaceOpVectorTimesMatrix(
opt::IRContext* ir_context,
opt::Instruction* linear_algebra_instruction) const {
auto vector_instruction = ir_context->get_def_use_mgr()->GetDef(
linear_algebra_instruction->GetSingleWordInOperand(0));
uint32_t vector_component_count = ir_context->get_type_mgr()
->GetType(vector_instruction->type_id())
->AsVector()
->element_count();
auto vector_component_type = ir_context->get_type_mgr()
->GetType(vector_instruction->type_id())
->AsVector()
->element_type();
uint32_t fresh_id_index = 0;
std::vector<uint32_t> vector_component_ids(vector_component_count);
for (uint32_t i = 0; i < vector_component_count; i++) {
vector_component_ids[i] = message_.fresh_ids(fresh_id_index++);
linear_algebra_instruction->InsertBefore(MakeUnique<opt::Instruction>(
ir_context, spv::Op::OpCompositeExtract,
ir_context->get_type_mgr()->GetId(vector_component_type),
vector_component_ids[i],
opt::Instruction::OperandList(
{{SPV_OPERAND_TYPE_ID, {vector_instruction->result_id()}},
{SPV_OPERAND_TYPE_LITERAL_INTEGER, {i}}})));
}
auto matrix_instruction = ir_context->get_def_use_mgr()->GetDef(
linear_algebra_instruction->GetSingleWordInOperand(1));
uint32_t matrix_column_count = ir_context->get_type_mgr()
->GetType(matrix_instruction->type_id())
->AsMatrix()
->element_count();
auto matrix_column_type = ir_context->get_type_mgr()
->GetType(matrix_instruction->type_id())
->AsMatrix()
->element_type();
std::vector<uint32_t> result_component_ids(matrix_column_count);
for (uint32_t i = 0; i < matrix_column_count; i++) {
uint32_t matrix_extract_id = message_.fresh_ids(fresh_id_index++);
linear_algebra_instruction->InsertBefore(MakeUnique<opt::Instruction>(
ir_context, spv::Op::OpCompositeExtract,
ir_context->get_type_mgr()->GetId(matrix_column_type),
matrix_extract_id,
opt::Instruction::OperandList(
{{SPV_OPERAND_TYPE_ID, {matrix_instruction->result_id()}},
{SPV_OPERAND_TYPE_LITERAL_INTEGER, {i}}})));
std::vector<uint32_t> float_multiplication_ids(vector_component_count);
for (uint32_t j = 0; j < vector_component_count; j++) {
uint32_t column_extract_id = message_.fresh_ids(fresh_id_index++);
linear_algebra_instruction->InsertBefore(MakeUnique<opt::Instruction>(
ir_context, spv::Op::OpCompositeExtract,
ir_context->get_type_mgr()->GetId(vector_component_type),
column_extract_id,
opt::Instruction::OperandList(
{{SPV_OPERAND_TYPE_ID, {matrix_extract_id}},
{SPV_OPERAND_TYPE_LITERAL_INTEGER, {j}}})));
float_multiplication_ids[j] = message_.fresh_ids(fresh_id_index++);
linear_algebra_instruction->InsertBefore(MakeUnique<opt::Instruction>(
ir_context, spv::Op::OpFMul,
ir_context->get_type_mgr()->GetId(vector_component_type),
float_multiplication_ids[j],
opt::Instruction::OperandList(
{{SPV_OPERAND_TYPE_ID, {vector_component_ids[j]}},
{SPV_OPERAND_TYPE_ID, {column_extract_id}}})));
}
std::vector<uint32_t> float_add_ids;
uint32_t float_add_id = message_.fresh_ids(fresh_id_index++);
float_add_ids.push_back(float_add_id);
linear_algebra_instruction->InsertBefore(MakeUnique<opt::Instruction>(
ir_context, spv::Op::OpFAdd,
ir_context->get_type_mgr()->GetId(vector_component_type), float_add_id,
opt::Instruction::OperandList(
{{SPV_OPERAND_TYPE_ID, {float_multiplication_ids[0]}},
{SPV_OPERAND_TYPE_ID, {float_multiplication_ids[1]}}})));
for (uint32_t j = 2; j < float_multiplication_ids.size(); j++) {
float_add_id = message_.fresh_ids(fresh_id_index++);
float_add_ids.push_back(float_add_id);
linear_algebra_instruction->InsertBefore(MakeUnique<opt::Instruction>(
ir_context, spv::Op::OpFAdd,
ir_context->get_type_mgr()->GetId(vector_component_type),
float_add_id,
opt::Instruction::OperandList(
{{SPV_OPERAND_TYPE_ID, {float_multiplication_ids[j]}},
{SPV_OPERAND_TYPE_ID, {float_add_ids[j - 2]}}})));
}
result_component_ids[i] = float_add_ids.back();
}
linear_algebra_instruction->SetOpcode(spv::Op::OpCompositeConstruct);
linear_algebra_instruction->SetInOperand(0, {result_component_ids[0]});
linear_algebra_instruction->SetInOperand(1, {result_component_ids[1]});
for (uint32_t i = 2; i < result_component_ids.size(); i++) {
linear_algebra_instruction->AddOperand(
{SPV_OPERAND_TYPE_ID, {result_component_ids[i]}});
}
fuzzerutil::UpdateModuleIdBound(
ir_context, message_.fresh_ids(message_.fresh_ids().size() - 1));
}
void TransformationReplaceLinearAlgebraInstruction::ReplaceOpMatrixTimesVector(
opt::IRContext* ir_context,
opt::Instruction* linear_algebra_instruction) const {
auto matrix_instruction = ir_context->get_def_use_mgr()->GetDef(
linear_algebra_instruction->GetSingleWordInOperand(0));
uint32_t matrix_column_count = ir_context->get_type_mgr()
->GetType(matrix_instruction->type_id())
->AsMatrix()
->element_count();
auto matrix_column_type = ir_context->get_type_mgr()
->GetType(matrix_instruction->type_id())
->AsMatrix()
->element_type();
uint32_t matrix_row_count = matrix_column_type->AsVector()->element_count();
uint32_t fresh_id_index = 0;
std::vector<uint32_t> matrix_column_ids(matrix_column_count);
for (uint32_t i = 0; i < matrix_column_count; i++) {
matrix_column_ids[i] = message_.fresh_ids(fresh_id_index++);
linear_algebra_instruction->InsertBefore(MakeUnique<opt::Instruction>(
ir_context, spv::Op::OpCompositeExtract,
ir_context->get_type_mgr()->GetId(matrix_column_type),
matrix_column_ids[i],
opt::Instruction::OperandList(
{{SPV_OPERAND_TYPE_ID, {matrix_instruction->result_id()}},
{SPV_OPERAND_TYPE_LITERAL_INTEGER, {i}}})));
}
auto vector_instruction = ir_context->get_def_use_mgr()->GetDef(
linear_algebra_instruction->GetSingleWordInOperand(1));
auto vector_component_type = ir_context->get_type_mgr()
->GetType(vector_instruction->type_id())
->AsVector()
->element_type();
std::vector<uint32_t> vector_component_ids(matrix_column_count);
for (uint32_t i = 0; i < matrix_column_count; i++) {
vector_component_ids[i] = message_.fresh_ids(fresh_id_index++);
linear_algebra_instruction->InsertBefore(MakeUnique<opt::Instruction>(
ir_context, spv::Op::OpCompositeExtract,
ir_context->get_type_mgr()->GetId(vector_component_type),
vector_component_ids[i],
opt::Instruction::OperandList(
{{SPV_OPERAND_TYPE_ID, {vector_instruction->result_id()}},
{SPV_OPERAND_TYPE_LITERAL_INTEGER, {i}}})));
}
std::vector<uint32_t> result_component_ids(matrix_row_count);
for (uint32_t i = 0; i < matrix_row_count; i++) {
std::vector<uint32_t> float_multiplication_ids(matrix_column_count);
for (uint32_t j = 0; j < matrix_column_count; j++) {
uint32_t column_extract_id = message_.fresh_ids(fresh_id_index++);
linear_algebra_instruction->InsertBefore(MakeUnique<opt::Instruction>(
ir_context, spv::Op::OpCompositeExtract,
ir_context->get_type_mgr()->GetId(vector_component_type),
column_extract_id,
opt::Instruction::OperandList(
{{SPV_OPERAND_TYPE_ID, {matrix_column_ids[j]}},
{SPV_OPERAND_TYPE_LITERAL_INTEGER, {i}}})));
float_multiplication_ids[j] = message_.fresh_ids(fresh_id_index++);
linear_algebra_instruction->InsertBefore(MakeUnique<opt::Instruction>(
ir_context, spv::Op::OpFMul,
ir_context->get_type_mgr()->GetId(vector_component_type),
float_multiplication_ids[j],
opt::Instruction::OperandList(
{{SPV_OPERAND_TYPE_ID, {column_extract_id}},
{SPV_OPERAND_TYPE_ID, {vector_component_ids[j]}}})));
}
std::vector<uint32_t> float_add_ids;
uint32_t float_add_id = message_.fresh_ids(fresh_id_index++);
float_add_ids.push_back(float_add_id);
linear_algebra_instruction->InsertBefore(MakeUnique<opt::Instruction>(
ir_context, spv::Op::OpFAdd,
ir_context->get_type_mgr()->GetId(vector_component_type), float_add_id,
opt::Instruction::OperandList(
{{SPV_OPERAND_TYPE_ID, {float_multiplication_ids[0]}},
{SPV_OPERAND_TYPE_ID, {float_multiplication_ids[1]}}})));
for (uint32_t j = 2; j < float_multiplication_ids.size(); j++) {
float_add_id = message_.fresh_ids(fresh_id_index++);
float_add_ids.push_back(float_add_id);
linear_algebra_instruction->InsertBefore(MakeUnique<opt::Instruction>(
ir_context, spv::Op::OpFAdd,
ir_context->get_type_mgr()->GetId(vector_component_type),
float_add_id,
opt::Instruction::OperandList(
{{SPV_OPERAND_TYPE_ID, {float_multiplication_ids[j]}},
{SPV_OPERAND_TYPE_ID, {float_add_ids[j - 2]}}})));
}
result_component_ids[i] = float_add_ids.back();
}
linear_algebra_instruction->SetOpcode(spv::Op::OpCompositeConstruct);
linear_algebra_instruction->SetInOperand(0, {result_component_ids[0]});
linear_algebra_instruction->SetInOperand(1, {result_component_ids[1]});
for (uint32_t i = 2; i < result_component_ids.size(); i++) {
linear_algebra_instruction->AddOperand(
{SPV_OPERAND_TYPE_ID, {result_component_ids[i]}});
}
fuzzerutil::UpdateModuleIdBound(
ir_context, message_.fresh_ids(message_.fresh_ids().size() - 1));
}
void TransformationReplaceLinearAlgebraInstruction::ReplaceOpMatrixTimesMatrix(
opt::IRContext* ir_context,
opt::Instruction* linear_algebra_instruction) const {
auto matrix_1_instruction = ir_context->get_def_use_mgr()->GetDef(
linear_algebra_instruction->GetSingleWordInOperand(0));
uint32_t matrix_1_column_count =
ir_context->get_type_mgr()
->GetType(matrix_1_instruction->type_id())
->AsMatrix()
->element_count();
auto matrix_1_column_type = ir_context->get_type_mgr()
->GetType(matrix_1_instruction->type_id())
->AsMatrix()
->element_type();
auto matrix_1_column_component_type =
matrix_1_column_type->AsVector()->element_type();
uint32_t matrix_1_row_count =
matrix_1_column_type->AsVector()->element_count();
auto matrix_2_instruction = ir_context->get_def_use_mgr()->GetDef(
linear_algebra_instruction->GetSingleWordInOperand(1));
uint32_t matrix_2_column_count =
ir_context->get_type_mgr()
->GetType(matrix_2_instruction->type_id())
->AsMatrix()
->element_count();
auto matrix_2_column_type = ir_context->get_type_mgr()
->GetType(matrix_2_instruction->type_id())
->AsMatrix()
->element_type();
uint32_t fresh_id_index = 0;
std::vector<uint32_t> result_column_ids(matrix_2_column_count);
for (uint32_t i = 0; i < matrix_2_column_count; i++) {
uint32_t matrix_2_column_id = message_.fresh_ids(fresh_id_index++);
linear_algebra_instruction->InsertBefore(MakeUnique<opt::Instruction>(
ir_context, spv::Op::OpCompositeExtract,
ir_context->get_type_mgr()->GetId(matrix_2_column_type),
matrix_2_column_id,
opt::Instruction::OperandList(
{{SPV_OPERAND_TYPE_ID, {matrix_2_instruction->result_id()}},
{SPV_OPERAND_TYPE_LITERAL_INTEGER, {i}}})));
std::vector<uint32_t> column_component_ids(matrix_1_row_count);
for (uint32_t j = 0; j < matrix_1_row_count; j++) {
std::vector<uint32_t> float_multiplication_ids(matrix_1_column_count);
for (uint32_t k = 0; k < matrix_1_column_count; k++) {
uint32_t matrix_1_column_id = message_.fresh_ids(fresh_id_index++);
linear_algebra_instruction->InsertBefore(MakeUnique<opt::Instruction>(
ir_context, spv::Op::OpCompositeExtract,
ir_context->get_type_mgr()->GetId(matrix_1_column_type),
matrix_1_column_id,
opt::Instruction::OperandList(
{{SPV_OPERAND_TYPE_ID, {matrix_1_instruction->result_id()}},
{SPV_OPERAND_TYPE_LITERAL_INTEGER, {k}}})));
uint32_t matrix_1_column_component_id =
message_.fresh_ids(fresh_id_index++);
linear_algebra_instruction->InsertBefore(MakeUnique<opt::Instruction>(
ir_context, spv::Op::OpCompositeExtract,
ir_context->get_type_mgr()->GetId(matrix_1_column_component_type),
matrix_1_column_component_id,
opt::Instruction::OperandList(
{{SPV_OPERAND_TYPE_ID, {matrix_1_column_id}},
{SPV_OPERAND_TYPE_LITERAL_INTEGER, {j}}})));
uint32_t matrix_2_column_component_id =
message_.fresh_ids(fresh_id_index++);
linear_algebra_instruction->InsertBefore(MakeUnique<opt::Instruction>(
ir_context, spv::Op::OpCompositeExtract,
ir_context->get_type_mgr()->GetId(matrix_1_column_component_type),
matrix_2_column_component_id,
opt::Instruction::OperandList(
{{SPV_OPERAND_TYPE_ID, {matrix_2_column_id}},
{SPV_OPERAND_TYPE_LITERAL_INTEGER, {k}}})));
float_multiplication_ids[k] = message_.fresh_ids(fresh_id_index++);
linear_algebra_instruction->InsertBefore(MakeUnique<opt::Instruction>(
ir_context, spv::Op::OpFMul,
ir_context->get_type_mgr()->GetId(matrix_1_column_component_type),
float_multiplication_ids[k],
opt::Instruction::OperandList(
{{SPV_OPERAND_TYPE_ID, {matrix_1_column_component_id}},
{SPV_OPERAND_TYPE_ID, {matrix_2_column_component_id}}})));
}
std::vector<uint32_t> float_add_ids;
uint32_t float_add_id = message_.fresh_ids(fresh_id_index++);
float_add_ids.push_back(float_add_id);
linear_algebra_instruction->InsertBefore(MakeUnique<opt::Instruction>(
ir_context, spv::Op::OpFAdd,
ir_context->get_type_mgr()->GetId(matrix_1_column_component_type),
float_add_id,
opt::Instruction::OperandList(
{{SPV_OPERAND_TYPE_ID, {float_multiplication_ids[0]}},
{SPV_OPERAND_TYPE_ID, {float_multiplication_ids[1]}}})));
for (uint32_t k = 2; k < float_multiplication_ids.size(); k++) {
float_add_id = message_.fresh_ids(fresh_id_index++);
float_add_ids.push_back(float_add_id);
linear_algebra_instruction->InsertBefore(MakeUnique<opt::Instruction>(
ir_context, spv::Op::OpFAdd,
ir_context->get_type_mgr()->GetId(matrix_1_column_component_type),
float_add_id,
opt::Instruction::OperandList(
{{SPV_OPERAND_TYPE_ID, {float_multiplication_ids[k]}},
{SPV_OPERAND_TYPE_ID, {float_add_ids[k - 2]}}})));
}
column_component_ids[j] = float_add_ids.back();
}
opt::Instruction::OperandList in_operands;
for (auto& column_component_id : column_component_ids) {
in_operands.push_back({SPV_OPERAND_TYPE_ID, {column_component_id}});
}
result_column_ids[i] = message_.fresh_ids(fresh_id_index++);
linear_algebra_instruction->InsertBefore(MakeUnique<opt::Instruction>(
ir_context, spv::Op::OpCompositeConstruct,
ir_context->get_type_mgr()->GetId(matrix_1_column_type),
result_column_ids[i], opt::Instruction::OperandList(in_operands)));
}
linear_algebra_instruction->SetOpcode(spv::Op::OpCompositeConstruct);
linear_algebra_instruction->SetInOperand(0, {result_column_ids[0]});
linear_algebra_instruction->SetInOperand(1, {result_column_ids[1]});
for (uint32_t i = 2; i < result_column_ids.size(); i++) {
linear_algebra_instruction->AddOperand(
{SPV_OPERAND_TYPE_ID, {result_column_ids[i]}});
}
fuzzerutil::UpdateModuleIdBound(
ir_context, message_.fresh_ids(message_.fresh_ids().size() - 1));
}
void TransformationReplaceLinearAlgebraInstruction::ReplaceOpOuterProduct(
opt::IRContext* ir_context,
opt::Instruction* linear_algebra_instruction) const {
auto vector_1_instruction = ir_context->get_def_use_mgr()->GetDef(
linear_algebra_instruction->GetSingleWordInOperand(0));
uint32_t vector_1_component_count =
ir_context->get_type_mgr()
->GetType(vector_1_instruction->type_id())
->AsVector()
->element_count();
auto vector_1_component_type = ir_context->get_type_mgr()
->GetType(vector_1_instruction->type_id())
->AsVector()
->element_type();
auto vector_2_instruction = ir_context->get_def_use_mgr()->GetDef(
linear_algebra_instruction->GetSingleWordInOperand(1));
uint32_t vector_2_component_count =
ir_context->get_type_mgr()
->GetType(vector_2_instruction->type_id())
->AsVector()
->element_count();
uint32_t fresh_id_index = 0;
std::vector<uint32_t> result_column_ids(vector_2_component_count);
for (uint32_t i = 0; i < vector_2_component_count; i++) {
uint32_t vector_2_component_id = message_.fresh_ids(fresh_id_index++);
linear_algebra_instruction->InsertBefore(MakeUnique<opt::Instruction>(
ir_context, spv::Op::OpCompositeExtract,
ir_context->get_type_mgr()->GetId(vector_1_component_type),
vector_2_component_id,
opt::Instruction::OperandList(
{{SPV_OPERAND_TYPE_ID, {vector_2_instruction->result_id()}},
{SPV_OPERAND_TYPE_LITERAL_INTEGER, {i}}})));
std::vector<uint32_t> column_component_ids(vector_1_component_count);
for (uint32_t j = 0; j < vector_1_component_count; j++) {
uint32_t vector_1_component_id = message_.fresh_ids(fresh_id_index++);
linear_algebra_instruction->InsertBefore(MakeUnique<opt::Instruction>(
ir_context, spv::Op::OpCompositeExtract,
ir_context->get_type_mgr()->GetId(vector_1_component_type),
vector_1_component_id,
opt::Instruction::OperandList(
{{SPV_OPERAND_TYPE_ID, {vector_1_instruction->result_id()}},
{SPV_OPERAND_TYPE_LITERAL_INTEGER, {j}}})));
column_component_ids[j] = message_.fresh_ids(fresh_id_index++);
linear_algebra_instruction->InsertBefore(MakeUnique<opt::Instruction>(
ir_context, spv::Op::OpFMul,
ir_context->get_type_mgr()->GetId(vector_1_component_type),
column_component_ids[j],
opt::Instruction::OperandList(
{{SPV_OPERAND_TYPE_ID, {vector_2_component_id}},
{SPV_OPERAND_TYPE_ID, {vector_1_component_id}}})));
}
opt::Instruction::OperandList in_operands;
for (auto& column_component_id : column_component_ids) {
in_operands.push_back({SPV_OPERAND_TYPE_ID, {column_component_id}});
}
result_column_ids[i] = message_.fresh_ids(fresh_id_index++);
linear_algebra_instruction->InsertBefore(MakeUnique<opt::Instruction>(
ir_context, spv::Op::OpCompositeConstruct,
vector_1_instruction->type_id(), result_column_ids[i], in_operands));
}
linear_algebra_instruction->SetOpcode(spv::Op::OpCompositeConstruct);
linear_algebra_instruction->SetInOperand(0, {result_column_ids[0]});
linear_algebra_instruction->SetInOperand(1, {result_column_ids[1]});
for (uint32_t i = 2; i < result_column_ids.size(); i++) {
linear_algebra_instruction->AddOperand(
{SPV_OPERAND_TYPE_ID, {result_column_ids[i]}});
}
fuzzerutil::UpdateModuleIdBound(
ir_context, message_.fresh_ids(message_.fresh_ids().size() - 1));
}
void TransformationReplaceLinearAlgebraInstruction::ReplaceOpDot(
opt::IRContext* ir_context,
opt::Instruction* linear_algebra_instruction) const {
auto vector_1 = ir_context->get_def_use_mgr()->GetDef(
linear_algebra_instruction->GetSingleWordInOperand(0));
auto vector_2 = ir_context->get_def_use_mgr()->GetDef(
linear_algebra_instruction->GetSingleWordInOperand(1));
uint32_t vectors_component_count = ir_context->get_type_mgr()
->GetType(vector_1->type_id())
->AsVector()
->element_count();
std::vector<uint32_t> float_multiplication_ids(vectors_component_count);
uint32_t fresh_id_index = 0;
for (uint32_t i = 0; i < vectors_component_count; i++) {
uint32_t vector_1_extract_id = message_.fresh_ids(fresh_id_index++);
fuzzerutil::UpdateModuleIdBound(ir_context, vector_1_extract_id);
linear_algebra_instruction->InsertBefore(MakeUnique<opt::Instruction>(
ir_context, spv::Op::OpCompositeExtract,
linear_algebra_instruction->type_id(), vector_1_extract_id,
opt::Instruction::OperandList(
{{SPV_OPERAND_TYPE_ID, {vector_1->result_id()}},
{SPV_OPERAND_TYPE_LITERAL_INTEGER, {i}}})));
uint32_t vector_2_extract_id = message_.fresh_ids(fresh_id_index++);
fuzzerutil::UpdateModuleIdBound(ir_context, vector_2_extract_id);
linear_algebra_instruction->InsertBefore(MakeUnique<opt::Instruction>(
ir_context, spv::Op::OpCompositeExtract,
linear_algebra_instruction->type_id(), vector_2_extract_id,
opt::Instruction::OperandList(
{{SPV_OPERAND_TYPE_ID, {vector_2->result_id()}},
{SPV_OPERAND_TYPE_LITERAL_INTEGER, {i}}})));
float_multiplication_ids[i] = message_.fresh_ids(fresh_id_index++);
fuzzerutil::UpdateModuleIdBound(ir_context, float_multiplication_ids[i]);
linear_algebra_instruction->InsertBefore(MakeUnique<opt::Instruction>(
ir_context, spv::Op::OpFMul, linear_algebra_instruction->type_id(),
float_multiplication_ids[i],
opt::Instruction::OperandList(
{{SPV_OPERAND_TYPE_ID, {vector_1_extract_id}},
{SPV_OPERAND_TYPE_ID, {vector_2_extract_id}}})));
}
if (vectors_component_count == 2) {
linear_algebra_instruction->SetOpcode(spv::Op::OpFAdd);
linear_algebra_instruction->SetInOperand(0, {float_multiplication_ids[0]});
linear_algebra_instruction->SetInOperand(1, {float_multiplication_ids[1]});
} else {
std::vector<uint32_t> float_add_ids;
uint32_t float_add_id = message_.fresh_ids(fresh_id_index++);
float_add_ids.push_back(float_add_id);
fuzzerutil::UpdateModuleIdBound(ir_context, float_add_id);
linear_algebra_instruction->InsertBefore(MakeUnique<opt::Instruction>(
ir_context, spv::Op::OpFAdd, linear_algebra_instruction->type_id(),
float_add_id,
opt::Instruction::OperandList(
{{SPV_OPERAND_TYPE_ID, {float_multiplication_ids[0]}},
{SPV_OPERAND_TYPE_ID, {float_multiplication_ids[1]}}})));
for (uint32_t i = 2; i < float_multiplication_ids.size() - 1; i++) {
float_add_id = message_.fresh_ids(fresh_id_index++);
fuzzerutil::UpdateModuleIdBound(ir_context, float_add_id);
float_add_ids.push_back(float_add_id);
linear_algebra_instruction->InsertBefore(MakeUnique<opt::Instruction>(
ir_context, spv::Op::OpFAdd, linear_algebra_instruction->type_id(),
float_add_id,
opt::Instruction::OperandList(
{{SPV_OPERAND_TYPE_ID, {float_multiplication_ids[i]}},
{SPV_OPERAND_TYPE_ID, {float_add_ids[i - 2]}}})));
}
linear_algebra_instruction->SetOpcode(spv::Op::OpFAdd);
linear_algebra_instruction->SetInOperand(
0, {float_multiplication_ids[float_multiplication_ids.size() - 1]});
linear_algebra_instruction->SetInOperand(
1, {float_add_ids[float_add_ids.size() - 1]});
}
}
std::unordered_set<uint32_t>
TransformationReplaceLinearAlgebraInstruction::GetFreshIds() const {
std::unordered_set<uint32_t> result;
for (auto id : message_.fresh_ids()) {
result.insert(id);
}
return result;
}
}
}