// Copyright (c) 2020 André Perez Maselco
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#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& /*unused*/) const {
  auto instruction =
      FindInstruction(message_.instruction_descriptor(), ir_context);

  // It must be a linear algebra instruction.
  if (!spvOpcodeIsLinearAlgebra(instruction->opcode())) {
    return false;
  }

  // |message_.fresh_ids.size| must be the exact number of fresh ids needed to
  // apply the transformation.
  if (static_cast<uint32_t>(message_.fresh_ids().size()) !=
      GetRequiredFreshIdCount(ir_context, instruction)) {
    return false;
  }

  // All ids in |message_.fresh_ids| must be fresh.
  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* /*unused*/) const {
  auto linear_algebra_instruction =
      FindInstruction(message_.instruction_descriptor(), ir_context);

  switch (linear_algebra_instruction->opcode()) {
    case SpvOpTranspose:
      ReplaceOpTranspose(ir_context, linear_algebra_instruction);
      break;
    case SpvOpVectorTimesScalar:
      ReplaceOpVectorTimesScalar(ir_context, linear_algebra_instruction);
      break;
    case SpvOpMatrixTimesScalar:
      ReplaceOpMatrixTimesScalar(ir_context, linear_algebra_instruction);
      break;
    case SpvOpVectorTimesMatrix:
      ReplaceOpVectorTimesMatrix(ir_context, linear_algebra_instruction);
      break;
    case SpvOpMatrixTimesVector:
      ReplaceOpMatrixTimesVector(ir_context, linear_algebra_instruction);
      break;
    case SpvOpMatrixTimesMatrix:
      ReplaceOpMatrixTimesMatrix(ir_context, linear_algebra_instruction);
      break;
    case SpvOpOuterProduct:
      ReplaceOpOuterProduct(ir_context, linear_algebra_instruction);
      break;
    case SpvOpDot:
      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) {
  // TODO(https://github.com/KhronosGroup/SPIRV-Tools/issues/3354):
  // Right now we only support certain operations.
  switch (instruction->opcode()) {
    case SpvOpTranspose: {
      // For each matrix row, |2 * matrix_column_count| OpCompositeExtract and 1
      // OpCompositeConstruct will be inserted.
      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 SpvOpVectorTimesScalar:
      // For each vector component, 1 OpCompositeExtract and 1 OpFMul will be
      // inserted.
      return 2 *
             ir_context->get_type_mgr()
                 ->GetType(ir_context->get_def_use_mgr()
                               ->GetDef(instruction->GetSingleWordInOperand(0))
                               ->type_id())
                 ->AsVector()
                 ->element_count();
    case SpvOpMatrixTimesScalar: {
      // For each matrix column, |1 + column.size| OpCompositeExtract,
      // |column.size| OpFMul and 1 OpCompositeConstruct instructions will be
      // inserted.
      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 SpvOpVectorTimesMatrix: {
      // For each vector component, 1 OpCompositeExtract instruction will be
      // inserted. For each matrix column, |1 + vector_component_count|
      // OpCompositeExtract, |vector_component_count| OpFMul and
      // |vector_component_count - 1| OpFAdd instructions will be inserted.
      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 SpvOpMatrixTimesVector: {
      // For each matrix column, |1 + matrix_row_count| OpCompositeExtract
      // will be inserted. For each matrix row, |matrix_column_count| OpFMul and
      // |matrix_column_count - 1| OpFAdd instructions will be inserted. For
      // each vector component, 1 OpCompositeExtract instruction will be
      // inserted.
      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 SpvOpMatrixTimesMatrix: {
      // For each matrix 2 column, 1 OpCompositeExtract, 1 OpCompositeConstruct,
      // |3 * matrix_1_row_count * matrix_1_column_count| OpCompositeExtract,
      // |matrix_1_row_count * matrix_1_column_count| OpFMul,
      // |matrix_1_row_count * (matrix_1_column_count - 1)| OpFAdd instructions
      // will be inserted.
      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 SpvOpOuterProduct: {
      // For each |vector_2| component, |vector_1_component_count + 1|
      // OpCompositeExtract, |vector_1_component_count| OpFMul and 1
      // OpCompositeConstruct instructions will be inserted.
      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 SpvOpDot:
      // For each pair of vector components, 2 OpCompositeExtract and 1 OpFMul
      // will be inserted. The first two OpFMul instructions will result the
      // first OpFAdd instruction to be inserted. For each remaining OpFMul, 1
      // OpFAdd will be inserted. The last OpFAdd instruction is got by changing
      // the OpDot instruction.
      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 {
  // Gets OpTranspose instruction information.
  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++) {
      // Extracts the matrix column.
      uint32_t matrix_column_id = message_.fresh_ids(fresh_id_index++);
      linear_algebra_instruction->InsertBefore(MakeUnique<opt::Instruction>(
          ir_context, SpvOpCompositeExtract,
          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}}})));

      // Extracts the matrix column component.
      column_component_ids[j] = message_.fresh_ids(fresh_id_index++);
      linear_algebra_instruction->InsertBefore(MakeUnique<opt::Instruction>(
          ir_context, SpvOpCompositeExtract,
          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}}})));
    }

    // Inserts the resulting matrix column.
    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, SpvOpCompositeConstruct,
        ir_context->get_type_mgr()->GetId(resulting_matrix_column_type),
        result_column_ids[i], opt::Instruction::OperandList(in_operands)));
  }

  // The OpTranspose instruction is changed to an OpCompositeConstruct
  // instruction.
  linear_algebra_instruction->SetOpcode(SpvOpCompositeConstruct);
  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 {
  // Gets OpVectorTimesScalar in operands.
  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++) {
    // Extracts |vector| component.
    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, SpvOpCompositeExtract, scalar->type_id(), vector_extract_id,
        opt::Instruction::OperandList(
            {{SPV_OPERAND_TYPE_ID, {vector->result_id()}},
             {SPV_OPERAND_TYPE_LITERAL_INTEGER, {i}}})));

    // Multiplies the |vector| component with the |scalar|.
    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, SpvOpFMul, scalar->type_id(), float_multiplication_id,
        opt::Instruction::OperandList(
            {{SPV_OPERAND_TYPE_ID, {vector_extract_id}},
             {SPV_OPERAND_TYPE_ID, {scalar->result_id()}}})));
  }

  // The OpVectorTimesScalar instruction is changed to an OpCompositeConstruct
  // instruction.
  linear_algebra_instruction->SetOpcode(SpvOpCompositeConstruct);
  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 {
  // Gets OpMatrixTimesScalar in operands.
  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));

  // Gets matrix information.
  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++) {
    // Extracts |matrix| column.
    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, SpvOpCompositeExtract,
        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++) {
      // Extracts |column| component.
      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, SpvOpCompositeExtract, scalar_instruction->type_id(),
          column_extract_id,
          opt::Instruction::OperandList(
              {{SPV_OPERAND_TYPE_ID, {matrix_extract_id}},
               {SPV_OPERAND_TYPE_LITERAL_INTEGER, {j}}})));

      // Multiplies the |column| component with the |scalar|.
      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, SpvOpFMul, 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()}}})));
    }

    // Constructs a new column multiplied by |scalar|.
    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, SpvOpCompositeConstruct,
        ir_context->get_type_mgr()->GetId(matrix_column_type),
        composite_construct_ids[i], composite_construct_in_operands));
  }

  // The OpMatrixTimesScalar instruction is changed to an OpCompositeConstruct
  // instruction.
  linear_algebra_instruction->SetOpcode(SpvOpCompositeConstruct);
  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 {
  // Gets vector information.
  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();

  // Extracts vector components.
  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, SpvOpCompositeExtract,
        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}}})));
  }

  // Gets matrix information.
  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++) {
    // Extracts matrix column.
    uint32_t matrix_extract_id = message_.fresh_ids(fresh_id_index++);
    linear_algebra_instruction->InsertBefore(MakeUnique<opt::Instruction>(
        ir_context, SpvOpCompositeExtract,
        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++) {
      // Extracts column component.
      uint32_t column_extract_id = message_.fresh_ids(fresh_id_index++);
      linear_algebra_instruction->InsertBefore(MakeUnique<opt::Instruction>(
          ir_context, SpvOpCompositeExtract,
          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}}})));

      // Multiplies corresponding vector and column components.
      float_multiplication_ids[j] = message_.fresh_ids(fresh_id_index++);
      linear_algebra_instruction->InsertBefore(MakeUnique<opt::Instruction>(
          ir_context, SpvOpFMul,
          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}}})));
    }

    // Adds the multiplication results.
    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, SpvOpFAdd,
        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, SpvOpFAdd,
          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();
  }

  // The OpVectorTimesMatrix instruction is changed to an OpCompositeConstruct
  // instruction.
  linear_algebra_instruction->SetOpcode(SpvOpCompositeConstruct);
  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 {
  // Gets matrix information.
  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();

  // Extracts matrix columns.
  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, SpvOpCompositeExtract,
        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}}})));
  }

  // Gets vector information.
  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();

  // Extracts vector components.
  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, SpvOpCompositeExtract,
        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++) {
      // Extracts column component.
      uint32_t column_extract_id = message_.fresh_ids(fresh_id_index++);
      linear_algebra_instruction->InsertBefore(MakeUnique<opt::Instruction>(
          ir_context, SpvOpCompositeExtract,
          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}}})));

      // Multiplies corresponding vector and column components.
      float_multiplication_ids[j] = message_.fresh_ids(fresh_id_index++);
      linear_algebra_instruction->InsertBefore(MakeUnique<opt::Instruction>(
          ir_context, SpvOpFMul,
          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]}}})));
    }

    // Adds the multiplication results.
    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, SpvOpFAdd,
        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, SpvOpFAdd,
          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();
  }

  // The OpMatrixTimesVector instruction is changed to an OpCompositeConstruct
  // instruction.
  linear_algebra_instruction->SetOpcode(SpvOpCompositeConstruct);
  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 {
  // Gets matrix 1 information.
  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();

  // Gets matrix 2 information.
  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++) {
    // Extracts matrix 2 column.
    uint32_t matrix_2_column_id = message_.fresh_ids(fresh_id_index++);
    linear_algebra_instruction->InsertBefore(MakeUnique<opt::Instruction>(
        ir_context, SpvOpCompositeExtract,
        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++) {
        // Extracts matrix 1 column.
        uint32_t matrix_1_column_id = message_.fresh_ids(fresh_id_index++);
        linear_algebra_instruction->InsertBefore(MakeUnique<opt::Instruction>(
            ir_context, SpvOpCompositeExtract,
            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}}})));

        // Extracts matrix 1 column component.
        uint32_t matrix_1_column_component_id =
            message_.fresh_ids(fresh_id_index++);
        linear_algebra_instruction->InsertBefore(MakeUnique<opt::Instruction>(
            ir_context, SpvOpCompositeExtract,
            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}}})));

        // Extracts matrix 2 column component.
        uint32_t matrix_2_column_component_id =
            message_.fresh_ids(fresh_id_index++);
        linear_algebra_instruction->InsertBefore(MakeUnique<opt::Instruction>(
            ir_context, SpvOpCompositeExtract,
            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}}})));

        // Multiplies corresponding matrix 1 and matrix 2 column components.
        float_multiplication_ids[k] = message_.fresh_ids(fresh_id_index++);
        linear_algebra_instruction->InsertBefore(MakeUnique<opt::Instruction>(
            ir_context, SpvOpFMul,
            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}}})));
      }

      // Adds the multiplication results.
      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, SpvOpFAdd,
          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, SpvOpFAdd,
            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();
    }

    // Inserts the resulting matrix column.
    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, SpvOpCompositeConstruct,
        ir_context->get_type_mgr()->GetId(matrix_1_column_type),
        result_column_ids[i], opt::Instruction::OperandList(in_operands)));
  }

  // The OpMatrixTimesMatrix instruction is changed to an OpCompositeConstruct
  // instruction.
  linear_algebra_instruction->SetOpcode(SpvOpCompositeConstruct);
  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 {
  // Gets vector 1 information.
  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();

  // Gets vector 2 information.
  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++) {
    // Extracts |vector_2| component.
    uint32_t vector_2_component_id = message_.fresh_ids(fresh_id_index++);
    linear_algebra_instruction->InsertBefore(MakeUnique<opt::Instruction>(
        ir_context, SpvOpCompositeExtract,
        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++) {
      // Extracts |vector_1| component.
      uint32_t vector_1_component_id = message_.fresh_ids(fresh_id_index++);
      linear_algebra_instruction->InsertBefore(MakeUnique<opt::Instruction>(
          ir_context, SpvOpCompositeExtract,
          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}}})));

      // Multiplies |vector_1| and |vector_2| components.
      column_component_ids[j] = message_.fresh_ids(fresh_id_index++);
      linear_algebra_instruction->InsertBefore(MakeUnique<opt::Instruction>(
          ir_context, SpvOpFMul,
          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}}})));
    }

    // Inserts the resulting matrix column.
    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, SpvOpCompositeConstruct, vector_1_instruction->type_id(),
        result_column_ids[i], in_operands));
  }

  // The OpOuterProduct instruction is changed to an OpCompositeConstruct
  // instruction.
  linear_algebra_instruction->SetOpcode(SpvOpCompositeConstruct);
  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 {
  // Gets OpDot in operands.
  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++) {
    // Extracts |vector_1| component.
    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, SpvOpCompositeExtract,
        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}}})));

    // Extracts |vector_2| component.
    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, SpvOpCompositeExtract,
        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}}})));

    // Multiplies the pair of components.
    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, SpvOpFMul, 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 the vector has 2 components, then there will be 2 float multiplication
  // instructions.
  if (vectors_component_count == 2) {
    linear_algebra_instruction->SetOpcode(SpvOpFAdd);
    linear_algebra_instruction->SetInOperand(0, {float_multiplication_ids[0]});
    linear_algebra_instruction->SetInOperand(1, {float_multiplication_ids[1]});
  } else {
    // The first OpFAdd instruction has as operands the first two OpFMul
    // instructions.
    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, SpvOpFAdd, 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]}}})));

    // The remaining OpFAdd instructions has as operands an OpFMul and an OpFAdd
    // instruction.
    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, SpvOpFAdd, 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]}}})));
    }

    // The last OpFAdd instruction is got by changing some of the OpDot
    // instruction attributes.
    linear_algebra_instruction->SetOpcode(SpvOpFAdd);
    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;
}

}  // namespace fuzz
}  // namespace spvtools
