// Copyright (c) 2020 Google LLC
//
// 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_duplicate_region_with_selection.h"

#include "source/fuzz/fuzzer_util.h"

namespace spvtools {
namespace fuzz {

TransformationDuplicateRegionWithSelection::
    TransformationDuplicateRegionWithSelection(
        protobufs::TransformationDuplicateRegionWithSelection message)
    : message_(std::move(message)) {}

TransformationDuplicateRegionWithSelection::
    TransformationDuplicateRegionWithSelection(
        uint32_t new_entry_fresh_id, uint32_t condition_id,
        uint32_t merge_label_fresh_id, uint32_t entry_block_id,
        uint32_t exit_block_id,
        const std::map<uint32_t, uint32_t>& original_label_to_duplicate_label,
        const std::map<uint32_t, uint32_t>& original_id_to_duplicate_id,
        const std::map<uint32_t, uint32_t>& original_id_to_phi_id) {
  message_.set_new_entry_fresh_id(new_entry_fresh_id);
  message_.set_condition_id(condition_id);
  message_.set_merge_label_fresh_id(merge_label_fresh_id);
  message_.set_entry_block_id(entry_block_id);
  message_.set_exit_block_id(exit_block_id);
  *message_.mutable_original_label_to_duplicate_label() =
      fuzzerutil::MapToRepeatedUInt32Pair(original_label_to_duplicate_label);
  *message_.mutable_original_id_to_duplicate_id() =
      fuzzerutil::MapToRepeatedUInt32Pair(original_id_to_duplicate_id);
  *message_.mutable_original_id_to_phi_id() =
      fuzzerutil::MapToRepeatedUInt32Pair(original_id_to_phi_id);
}

bool TransformationDuplicateRegionWithSelection::IsApplicable(
    opt::IRContext* ir_context,
    const TransformationContext& transformation_context) const {
  // Instruction with the id |condition_id| must exist and must be of a bool
  // type.
  auto bool_instr =
      ir_context->get_def_use_mgr()->GetDef(message_.condition_id());
  if (bool_instr == nullptr || !bool_instr->type_id()) {
    return false;
  }
  if (!ir_context->get_type_mgr()->GetType(bool_instr->type_id())->AsBool()) {
    return false;
  }

  // The |new_entry_fresh_id| must be fresh and distinct.
  std::set<uint32_t> ids_used_by_this_transformation;
  if (!CheckIdIsFreshAndNotUsedByThisTransformation(
          message_.new_entry_fresh_id(), ir_context,
          &ids_used_by_this_transformation)) {
    return false;
  }

  // The |merge_label_fresh_id| must be fresh and distinct.
  if (!CheckIdIsFreshAndNotUsedByThisTransformation(
          message_.merge_label_fresh_id(), ir_context,
          &ids_used_by_this_transformation)) {
    return false;
  }

  // The entry and exit block ids must refer to blocks.
  for (auto block_id : {message_.entry_block_id(), message_.exit_block_id()}) {
    auto block_label = ir_context->get_def_use_mgr()->GetDef(block_id);
    if (!block_label || block_label->opcode() != SpvOpLabel) {
      return false;
    }
  }
  auto entry_block = ir_context->cfg()->block(message_.entry_block_id());
  auto exit_block = ir_context->cfg()->block(message_.exit_block_id());

  // The |entry_block| and the |exit_block| must be in the same function.
  if (entry_block->GetParent() != exit_block->GetParent()) {
    return false;
  }

  // The |entry_block| must dominate the |exit_block|.
  auto dominator_analysis =
      ir_context->GetDominatorAnalysis(entry_block->GetParent());
  if (!dominator_analysis->Dominates(entry_block, exit_block)) {
    return false;
  }

  // The |exit_block| must post-dominate the |entry_block|.
  auto postdominator_analysis =
      ir_context->GetPostDominatorAnalysis(entry_block->GetParent());
  if (!postdominator_analysis->Dominates(exit_block, entry_block)) {
    return false;
  }

  auto enclosing_function = entry_block->GetParent();

  // |entry_block| cannot be the first block of the |enclosing_function|.
  if (&*enclosing_function->begin() == entry_block) {
    return false;
  }

  // To make the process of resolving OpPhi instructions easier, we require that
  // the entry block has only one predecessor.
  auto entry_block_preds = ir_context->cfg()->preds(entry_block->id());
  std::sort(entry_block_preds.begin(), entry_block_preds.end());
  entry_block_preds.erase(
      std::unique(entry_block_preds.begin(), entry_block_preds.end()),
      entry_block_preds.end());
  if (entry_block_preds.size() > 1) {
    return false;
  }

  // TODO(https://github.com/KhronosGroup/SPIRV-Tools/issues/3785):
  //     The following code has been copied from TransformationOutlineFunction.
  //     Consider refactoring to avoid duplication.
  auto region_set = GetRegionBlocks(ir_context, entry_block, exit_block);

  // Check whether |region_set| really is a single-entry single-exit region, and
  // also check whether structured control flow constructs and their merge
  // and continue constructs are either wholly in or wholly out of the region -
  // e.g. avoid the situation where the region contains the head of a loop but
  // not the loop's continue construct.
  //
  // This is achieved by going through every block in the |enclosing_function|
  for (auto& block : *enclosing_function) {
    if (&block == exit_block) {
      // It is not OK for the exit block to head a loop construct or a
      // conditional construct.
      if (block.GetMergeInst()) {
        return false;
      }
      continue;
    }
    if (region_set.count(&block) != 0) {
      // The block is in the region and is not the region's exit block.  Let's
      // see whether all of the block's successors are in the region. If they
      // are not, the region is not single-entry single-exit.
      bool all_successors_in_region = true;
      block.WhileEachSuccessorLabel([&all_successors_in_region, ir_context,
                                     &region_set](uint32_t successor) -> bool {
        if (region_set.count(ir_context->cfg()->block(successor)) == 0) {
          all_successors_in_region = false;
          return false;
        }
        return true;
      });
      if (!all_successors_in_region) {
        return false;
      }
    }

    if (auto merge = block.GetMergeInst()) {
      // The block is a loop or selection header. The header and its
      // associated merge block must be both in the region or both be
      // outside the region.
      auto merge_block =
          ir_context->cfg()->block(merge->GetSingleWordOperand(0));
      if (region_set.count(&block) != region_set.count(merge_block)) {
        return false;
      }
    }

    if (auto loop_merge = block.GetLoopMergeInst()) {
      // The continue target of a loop must be within the region if and only if
      // the header of the loop is.
      auto continue_target =
          ir_context->cfg()->block(loop_merge->GetSingleWordOperand(1));
      // The continue target is a single-entry, single-exit region. Therefore,
      // if the continue target is the exit block, the region might not contain
      // the loop header. However, we would like to exclude this situation,
      // since it would be impossible for the modified exit block to branch to
      // the new selection merge block. In this scenario the exit block is
      // required to branch to the loop header.
      if (region_set.count(&block) != region_set.count(continue_target)) {
        return false;
      }
    }
  }

  // Get the maps from the protobuf.
  std::map<uint32_t, uint32_t> original_label_to_duplicate_label =
      fuzzerutil::RepeatedUInt32PairToMap(
          message_.original_label_to_duplicate_label());

  std::map<uint32_t, uint32_t> original_id_to_duplicate_id =
      fuzzerutil::RepeatedUInt32PairToMap(
          message_.original_id_to_duplicate_id());

  std::map<uint32_t, uint32_t> original_id_to_phi_id =
      fuzzerutil::RepeatedUInt32PairToMap(message_.original_id_to_phi_id());

  for (auto block : region_set) {
    // The label of every block in the region must be present in the map
    // |original_label_to_duplicate_label|, unless overflow ids are present.
    if (original_label_to_duplicate_label.count(block->id()) == 0) {
      if (!transformation_context.GetOverflowIdSource()->HasOverflowIds()) {
        return false;
      }
    } else {
      auto duplicate_label = original_label_to_duplicate_label.at(block->id());
      // Each id assigned to labels in the region must be distinct and fresh.
      if (!duplicate_label ||
          !CheckIdIsFreshAndNotUsedByThisTransformation(
              duplicate_label, ir_context, &ids_used_by_this_transformation)) {
        return false;
      }
    }
    for (auto& instr : *block) {
      if (!instr.HasResultId()) {
        continue;
      }
      // Every instruction with a result id in the region must be present in the
      // map |original_id_to_duplicate_id|, unless overflow ids are present.
      if (original_id_to_duplicate_id.count(instr.result_id()) == 0) {
        if (!transformation_context.GetOverflowIdSource()->HasOverflowIds()) {
          return false;
        }
      } else {
        auto duplicate_id = original_id_to_duplicate_id.at(instr.result_id());
        // Id assigned to this result id in the region must be distinct and
        // fresh.
        if (!duplicate_id ||
            !CheckIdIsFreshAndNotUsedByThisTransformation(
                duplicate_id, ir_context, &ids_used_by_this_transformation)) {
          return false;
        }
      }
      // If the instruction is available at the end of the region then we would
      // like to be able to add an OpPhi instruction at the merge point of the
      // duplicated region to capture the values computed by both duplicates of
      // the instruction, so that this is also available after the region.  We
      // do this not just for instructions that are already used after the
      // region, but for all instructions so that the phi is available to future
      // transformations.
      if (AvailableAfterRegion(instr, exit_block, ir_context)) {
        if (!ValidOpPhiArgument(instr, ir_context)) {
          // The instruction cannot be used as an OpPhi argument.  This is a
          // blocker if there are uses of the instruction after the region.
          // Otherwise we can simply avoid generating an OpPhi for this
          // instruction and its duplicate.
          if (!ir_context->get_def_use_mgr()->WhileEachUser(
                  &instr,
                  [ir_context,
                   &region_set](opt::Instruction* use_instr) -> bool {
                    opt::BasicBlock* use_block =
                        ir_context->get_instr_block(use_instr);
                    return use_block == nullptr ||
                           region_set.count(use_block) > 0;
                  })) {
            return false;
          }
        } else {
          // Every instruction with a result id available at the end of the
          // region must be present in the map |original_id_to_phi_id|, unless
          // overflow ids are present.
          if (original_id_to_phi_id.count(instr.result_id()) == 0) {
            if (!transformation_context.GetOverflowIdSource()
                     ->HasOverflowIds()) {
              return false;
            }
          } else {
            auto phi_id = original_id_to_phi_id.at(instr.result_id());
            // Id assigned to this result id in the region must be distinct and
            // fresh.
            if (!phi_id ||
                !CheckIdIsFreshAndNotUsedByThisTransformation(
                    phi_id, ir_context, &ids_used_by_this_transformation)) {
              return false;
            }
          }
        }
      }
    }
  }
  return true;
}

void TransformationDuplicateRegionWithSelection::Apply(
    opt::IRContext* ir_context,
    TransformationContext* transformation_context) const {
  fuzzerutil::UpdateModuleIdBound(ir_context, message_.new_entry_fresh_id());
  fuzzerutil::UpdateModuleIdBound(ir_context, message_.merge_label_fresh_id());

  // Create the new entry block containing the main conditional instruction. Set
  // its parent to the parent of the original entry block, since it is located
  // in the same function.
  std::unique_ptr<opt::BasicBlock> new_entry_block =
      MakeUnique<opt::BasicBlock>(MakeUnique<opt::Instruction>(
          ir_context, SpvOpLabel, 0, message_.new_entry_fresh_id(),
          opt::Instruction::OperandList()));
  auto entry_block = ir_context->cfg()->block(message_.entry_block_id());
  auto enclosing_function = entry_block->GetParent();
  auto exit_block = ir_context->cfg()->block(message_.exit_block_id());

  // Get the blocks contained in the region.
  std::set<opt::BasicBlock*> region_blocks =
      GetRegionBlocks(ir_context, entry_block, exit_block);

  // Construct the merge block.
  std::unique_ptr<opt::BasicBlock> merge_block =
      MakeUnique<opt::BasicBlock>(MakeUnique<opt::Instruction>(opt::Instruction(
          ir_context, SpvOpLabel, 0, message_.merge_label_fresh_id(),
          opt::Instruction::OperandList())));

  // Get the maps from the protobuf.
  std::map<uint32_t, uint32_t> original_label_to_duplicate_label =
      fuzzerutil::RepeatedUInt32PairToMap(
          message_.original_label_to_duplicate_label());

  std::map<uint32_t, uint32_t> original_id_to_duplicate_id =
      fuzzerutil::RepeatedUInt32PairToMap(
          message_.original_id_to_duplicate_id());

  std::map<uint32_t, uint32_t> original_id_to_phi_id =
      fuzzerutil::RepeatedUInt32PairToMap(message_.original_id_to_phi_id());

  // Use oveflow ids to fill in any required ids that are missing from these
  // maps.
  for (auto block : region_blocks) {
    if (original_label_to_duplicate_label.count(block->id()) == 0) {
      original_label_to_duplicate_label.insert(
          {block->id(),
           transformation_context->GetOverflowIdSource()->GetNextOverflowId()});
    }
    for (auto& instr : *block) {
      if (!instr.HasResultId()) {
        continue;
      }
      if (original_id_to_duplicate_id.count(instr.result_id()) == 0) {
        original_id_to_duplicate_id.insert(
            {instr.result_id(), transformation_context->GetOverflowIdSource()
                                    ->GetNextOverflowId()});
      }
      if (AvailableAfterRegion(instr, exit_block, ir_context) &&
          ValidOpPhiArgument(instr, ir_context)) {
        if (original_id_to_phi_id.count(instr.result_id()) == 0) {
          original_id_to_phi_id.insert(
              {instr.result_id(), transformation_context->GetOverflowIdSource()
                                      ->GetNextOverflowId()});
        }
      }
    }
  }

  // Before adding duplicate blocks, we need to update the OpPhi instructions in
  // the successors of the |exit_block|. We know that the execution of the
  // transformed region will end in |merge_block|. Hence, we need to change all
  // occurrences of the label id of the |exit_block| to the label id of the
  // |merge_block|.
  exit_block->ForEachSuccessorLabel([this, ir_context](uint32_t label_id) {
    auto block = ir_context->cfg()->block(label_id);
    for (auto& instr : *block) {
      if (instr.opcode() == SpvOpPhi) {
        instr.ForEachId([this](uint32_t* id) {
          if (*id == message_.exit_block_id()) {
            *id = message_.merge_label_fresh_id();
          }
        });
      }
    }
  });

  // Get vector of predecessors id of |entry_block|. Remove any duplicate
  // values.
  auto entry_block_preds = ir_context->cfg()->preds(entry_block->id());
  std::sort(entry_block_preds.begin(), entry_block_preds.end());
  entry_block_preds.erase(
      unique(entry_block_preds.begin(), entry_block_preds.end()),
      entry_block_preds.end());
  // We know that |entry_block| has only one predecessor, since the region is
  // single-entry, single-exit and its constructs and their merge blocks must be
  // either wholly within or wholly outside of the region.
  assert(entry_block_preds.size() == 1 &&
         "The entry of the region to be duplicated can have only one "
         "predecessor.");
  uint32_t entry_block_pred_id =
      ir_context->get_instr_block(entry_block_preds[0])->id();
  // Update all the OpPhi instructions in the |entry_block|. Change every
  // occurrence of |entry_block_pred_id| to the id of |new_entry|, because we
  // will insert |new_entry| before |entry_block|.
  for (auto& instr : *entry_block) {
    if (instr.opcode() == SpvOpPhi) {
      instr.ForEachId([this, entry_block_pred_id](uint32_t* id) {
        if (*id == entry_block_pred_id) {
          *id = message_.new_entry_fresh_id();
        }
      });
    }
  }

  // Duplication of blocks will invalidate iterators. Store all the blocks from
  // the enclosing function.
  std::vector<opt::BasicBlock*> blocks;
  for (auto& block : *enclosing_function) {
    blocks.push_back(&block);
  }

  opt::BasicBlock* previous_block = nullptr;
  opt::BasicBlock* duplicated_exit_block = nullptr;
  // Iterate over all blocks of the function to duplicate blocks of the original
  // region and their instructions.
  for (auto& block : blocks) {
    // The block must be contained in the region.
    if (region_blocks.count(block) == 0) {
      continue;
    }

    fuzzerutil::UpdateModuleIdBound(
        ir_context, original_label_to_duplicate_label.at(block->id()));

    std::unique_ptr<opt::BasicBlock> duplicated_block =
        MakeUnique<opt::BasicBlock>(MakeUnique<opt::Instruction>(
            ir_context, SpvOpLabel, 0,
            original_label_to_duplicate_label.at(block->id()),
            opt::Instruction::OperandList()));

    for (auto& instr : *block) {
      // Case where an instruction is the terminator of the exit block is
      // handled separately.
      if (block == exit_block && instr.IsBlockTerminator()) {
        switch (instr.opcode()) {
          case SpvOpBranch:
          case SpvOpBranchConditional:
          case SpvOpReturn:
          case SpvOpReturnValue:
          case SpvOpUnreachable:
          case SpvOpKill:
            continue;
          default:
            assert(false &&
                   "Unexpected terminator for |exit_block| of the region.");
        }
      }
      // Duplicate the instruction.
      auto cloned_instr = instr.Clone(ir_context);
      duplicated_block->AddInstruction(
          std::unique_ptr<opt::Instruction>(cloned_instr));

      if (instr.HasResultId()) {
        fuzzerutil::UpdateModuleIdBound(
            ir_context, original_id_to_duplicate_id.at(instr.result_id()));
      }

      // If an id from the original region was used in this instruction,
      // replace it with the value from |original_id_to_duplicate_id|.
      // If a label from the original region was used in this instruction,
      // replace it with the value from |original_label_to_duplicate_label|.
      cloned_instr->ForEachId(
          [original_id_to_duplicate_id,
           original_label_to_duplicate_label](uint32_t* op) {
            if (original_id_to_duplicate_id.count(*op) != 0) {
              *op = original_id_to_duplicate_id.at(*op);
            } else if (original_label_to_duplicate_label.count(*op) != 0) {
              *op = original_label_to_duplicate_label.at(*op);
            }
          });
    }

    // If the block is the first duplicated block, insert it after the exit
    // block of the original region. Otherwise, insert it after the preceding
    // one.
    auto duplicated_block_ptr = duplicated_block.get();
    if (previous_block) {
      enclosing_function->InsertBasicBlockAfter(std::move(duplicated_block),
                                                previous_block);
    } else {
      enclosing_function->InsertBasicBlockAfter(std::move(duplicated_block),
                                                exit_block);
    }
    previous_block = duplicated_block_ptr;
    if (block == exit_block) {
      // After execution of the loop, this variable stores a pointer to the last
      // duplicated block.
      duplicated_exit_block = duplicated_block_ptr;
    }
  }

  for (auto& block : region_blocks) {
    for (auto& instr : *block) {
      if (instr.result_id() == 0) {
        continue;
      }
      if (AvailableAfterRegion(instr, exit_block, ir_context) &&
          ValidOpPhiArgument(instr, ir_context)) {
        // Add an OpPhi instruction for every result id that is available at
        // the end of the region, as long as the result id is valid for use
        // with OpPhi.
        merge_block->AddInstruction(MakeUnique<opt::Instruction>(
            ir_context, SpvOpPhi, instr.type_id(),
            original_id_to_phi_id.at(instr.result_id()),
            opt::Instruction::OperandList({
                {SPV_OPERAND_TYPE_ID, {instr.result_id()}},
                {SPV_OPERAND_TYPE_ID, {exit_block->id()}},
                {SPV_OPERAND_TYPE_ID,
                 {original_id_to_duplicate_id.at(instr.result_id())}},
                {SPV_OPERAND_TYPE_ID, {duplicated_exit_block->id()}},
            })));

        fuzzerutil::UpdateModuleIdBound(
            ir_context, original_id_to_phi_id.at(instr.result_id()));

        // If the instruction has been remapped by an OpPhi, look
        // for all its uses outside of the region and outside of the
        // merge block (to not overwrite just added instructions in
        // the merge block) and replace the original instruction id
        // with the id of the corresponding OpPhi instruction.
        ir_context->get_def_use_mgr()->ForEachUse(
            &instr,
            [ir_context, &instr, region_blocks, original_id_to_phi_id,
             &merge_block](opt::Instruction* user, uint32_t operand_index) {
              auto user_block = ir_context->get_instr_block(user);
              if ((region_blocks.find(user_block) != region_blocks.end()) ||
                  user_block == merge_block.get()) {
                return;
              }
              user->SetOperand(operand_index,
                               {original_id_to_phi_id.at(instr.result_id())});
            });
      }
    }
  }

  // Construct a conditional instruction in the |new_entry_block|.
  // If the condition is true, the execution proceeds in the
  // |entry_block| of the original region. If the condition is
  // false, the execution proceeds in the first block of the
  // duplicated region.
  new_entry_block->AddInstruction(MakeUnique<opt::Instruction>(
      ir_context, SpvOpSelectionMerge, 0, 0,
      opt::Instruction::OperandList(
          {{SPV_OPERAND_TYPE_ID, {message_.merge_label_fresh_id()}},
           {SPV_OPERAND_TYPE_SELECTION_CONTROL,
            {SpvSelectionControlMaskNone}}})));

  new_entry_block->AddInstruction(MakeUnique<opt::Instruction>(
      ir_context, SpvOpBranchConditional, 0, 0,
      opt::Instruction::OperandList(
          {{SPV_OPERAND_TYPE_ID, {message_.condition_id()}},
           {SPV_OPERAND_TYPE_ID, {message_.entry_block_id()}},
           {SPV_OPERAND_TYPE_ID,
            {original_label_to_duplicate_label.at(
                message_.entry_block_id())}}})));

  // Move the terminator of |exit_block| to the end of
  // |merge_block|.
  auto exit_block_terminator = exit_block->terminator();
  auto cloned_instr = exit_block_terminator->Clone(ir_context);
  merge_block->AddInstruction(std::unique_ptr<opt::Instruction>(cloned_instr));
  ir_context->KillInst(exit_block_terminator);

  // Add OpBranch instruction to the merge block at the end of
  // |exit_block| and at the end of |duplicated_exit_block|, so that
  // the execution proceeds in the |merge_block|.
  opt::Instruction merge_branch_instr = opt::Instruction(
      ir_context, SpvOpBranch, 0, 0,
      opt::Instruction::OperandList(
          {{SPV_OPERAND_TYPE_ID, {message_.merge_label_fresh_id()}}}));
  exit_block->AddInstruction(MakeUnique<opt::Instruction>(merge_branch_instr));
  duplicated_exit_block->AddInstruction(
      std::unique_ptr<opt::Instruction>(merge_branch_instr.Clone(ir_context)));

  // Execution needs to start in the |new_entry_block|. Change all
  // the uses of |entry_block_label_instr| outside of the original
  // region to |message_.new_entry_fresh_id|.
  auto entry_block_label_instr =
      ir_context->get_def_use_mgr()->GetDef(message_.entry_block_id());
  ir_context->get_def_use_mgr()->ForEachUse(
      entry_block_label_instr,
      [this, ir_context, region_blocks](opt::Instruction* user,
                                        uint32_t operand_index) {
        auto user_block = ir_context->get_instr_block(user);
        if ((region_blocks.count(user_block) != 0)) {
          return;
        }
        switch (user->opcode()) {
          case SpvOpSwitch:
          case SpvOpBranch:
          case SpvOpBranchConditional:
          case SpvOpLoopMerge:
          case SpvOpSelectionMerge: {
            user->SetOperand(operand_index, {message_.new_entry_fresh_id()});
          } break;
          case SpvOpName:
            break;
          default:
            assert(false &&
                   "The label id cannot be used by instructions "
                   "other than "
                   "OpSwitch, OpBranch, OpBranchConditional, "
                   "OpLoopMerge, "
                   "OpSelectionMerge");
        }
      });

  opt::Instruction* merge_block_terminator = merge_block->terminator();
  switch (merge_block_terminator->opcode()) {
    case SpvOpReturnValue:
    case SpvOpBranchConditional: {
      uint32_t operand = merge_block_terminator->GetSingleWordInOperand(0);
      if (original_id_to_phi_id.count(operand)) {
        merge_block_terminator->SetInOperand(
            0, {original_id_to_phi_id.at(operand)});
      }
      break;
    }
    default:
      break;
  }

  // Insert the merge block after the |duplicated_exit_block| (the
  // last duplicated block).
  enclosing_function->InsertBasicBlockAfter(std::move(merge_block),
                                            duplicated_exit_block);

  // Insert the |new_entry_block| before the entry block of the
  // original region.
  enclosing_function->InsertBasicBlockBefore(std::move(new_entry_block),
                                             entry_block);

  // Since we have changed the module, most of the analysis are now
  // invalid. We can invalidate analyses now after all of the blocks
  // have been registered.
  ir_context->InvalidateAnalysesExceptFor(opt::IRContext::kAnalysisNone);
}

// TODO(https://github.com/KhronosGroup/SPIRV-Tools/issues/3785):
//     The following method has been copied from
//     TransformationOutlineFunction. Consider refactoring to avoid
//     duplication.
std::set<opt::BasicBlock*>
TransformationDuplicateRegionWithSelection::GetRegionBlocks(
    opt::IRContext* ir_context, opt::BasicBlock* entry_block,
    opt::BasicBlock* exit_block) {
  auto enclosing_function = entry_block->GetParent();
  auto dominator_analysis =
      ir_context->GetDominatorAnalysis(enclosing_function);
  auto postdominator_analysis =
      ir_context->GetPostDominatorAnalysis(enclosing_function);

  // A block belongs to a region between the entry block and the exit
  // block if and only if it is dominated by the entry block and
  // post-dominated by the exit block.
  std::set<opt::BasicBlock*> result;
  for (auto& block : *enclosing_function) {
    if (dominator_analysis->Dominates(entry_block, &block) &&
        postdominator_analysis->Dominates(exit_block, &block)) {
      result.insert(&block);
    }
  }
  return result;
}

protobufs::Transformation
TransformationDuplicateRegionWithSelection::ToMessage() const {
  protobufs::Transformation result;
  *result.mutable_duplicate_region_with_selection() = message_;
  return result;
}

std::unordered_set<uint32_t>
TransformationDuplicateRegionWithSelection::GetFreshIds() const {
  std::unordered_set<uint32_t> result = {message_.new_entry_fresh_id(),
                                         message_.merge_label_fresh_id()};
  for (auto& pair : message_.original_label_to_duplicate_label()) {
    result.insert(pair.second());
  }
  for (auto& pair : message_.original_id_to_duplicate_id()) {
    result.insert(pair.second());
  }
  for (auto& pair : message_.original_id_to_phi_id()) {
    result.insert(pair.second());
  }
  return result;
}

bool TransformationDuplicateRegionWithSelection::AvailableAfterRegion(
    const opt::Instruction& instr, opt::BasicBlock* exit_block,
    opt::IRContext* ir_context) {
  opt::Instruction* final_instruction_in_region = &*exit_block->tail();
  return &instr == final_instruction_in_region ||
         fuzzerutil::IdIsAvailableBeforeInstruction(
             ir_context, final_instruction_in_region, instr.result_id());
}

bool TransformationDuplicateRegionWithSelection::ValidOpPhiArgument(
    const opt::Instruction& instr, opt::IRContext* ir_context) {
  opt::Instruction* instr_type =
      ir_context->get_def_use_mgr()->GetDef(instr.type_id());

  // It is invalid to apply OpPhi to void-typed values.
  if (instr_type->opcode() == SpvOpTypeVoid) {
    return false;
  }

  // Using pointers with OpPhi requires capability VariablePointers.
  if (instr_type->opcode() == SpvOpTypePointer &&
      !ir_context->get_feature_mgr()->HasCapability(
          SpvCapabilityVariablePointers)) {
    return false;
  }

  // OpTypeSampledImage cannot be the result type of an OpPhi instruction.
  if (instr_type->opcode() == SpvOpTypeSampledImage) {
    return false;
  }
  return true;
}

}  // namespace fuzz
}  // namespace spvtools
