// Copyright (c) 2018 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/reduce/structured_loop_to_selection_reduction_opportunity.h"

#include "source/opt/aggressive_dead_code_elim_pass.h"
#include "source/opt/ir_context.h"
#include "source/reduce/reduction_util.h"

namespace spvtools {
namespace reduce {

namespace {
const uint32_t kMergeNodeIndex = 0;
}  // namespace

bool StructuredLoopToSelectionReductionOpportunity::PreconditionHolds() {
  // Is the loop header reachable?
  return loop_construct_header_->GetLabel()->context()->IsReachable(
      *loop_construct_header_);
}

void StructuredLoopToSelectionReductionOpportunity::Apply() {
  // Force computation of dominator analysis, CFG and structured CFG analysis
  // before we start to mess with edges in the function.
  context_->GetDominatorAnalysis(loop_construct_header_->GetParent());
  context_->cfg();
  context_->GetStructuredCFGAnalysis();

  // (1) Redirect edges that point to the loop's continue target to their
  // closest merge block.
  RedirectToClosestMergeBlock(loop_construct_header_->ContinueBlockId());

  // (2) Redirect edges that point to the loop's merge block to their closest
  // merge block (which might be that of an enclosing selection, for instance).
  RedirectToClosestMergeBlock(loop_construct_header_->MergeBlockId());

  // (3) Turn the loop construct header into a selection.
  ChangeLoopToSelection();

  // We have made control flow changes that do not preserve the analyses that
  // were performed.
  context_->InvalidateAnalysesExceptFor(
      opt::IRContext::Analysis::kAnalysisNone);

  // (4) By changing CFG edges we may have created scenarios where ids are used
  // without being dominated; we fix instances of this.
  FixNonDominatedIdUses();

  // Invalidate the analyses we just used.
  context_->InvalidateAnalysesExceptFor(
      opt::IRContext::Analysis::kAnalysisNone);
}

void StructuredLoopToSelectionReductionOpportunity::RedirectToClosestMergeBlock(
    uint32_t original_target_id) {
  // Consider every predecessor of the node with respect to which edges should
  // be redirected.
  std::set<uint32_t> already_seen;
  for (auto pred : context_->cfg()->preds(original_target_id)) {
    if (already_seen.find(pred) != already_seen.end()) {
      // We have already handled this predecessor (this scenario can arise if
      // there are multiple edges from a block b to original_target_id).
      continue;
    }
    already_seen.insert(pred);

    if (!context_->IsReachable(*context_->cfg()->block(pred))) {
      // We do not care about unreachable predecessors (and dominance
      // information, and thus the notion of structured control flow, makes
      // little sense for unreachable blocks).
      continue;
    }
    // Find the merge block of the structured control construct that most
    // tightly encloses the predecessor.
    uint32_t new_merge_target;
    // The structured CFG analysis deliberately does not regard a header as
    // belonging to the structure that it heads. We want it to, so handle this
    // case specially.
    if (context_->cfg()->block(pred)->MergeBlockIdIfAny()) {
      new_merge_target = context_->cfg()->block(pred)->MergeBlockIdIfAny();
    } else {
      new_merge_target = context_->GetStructuredCFGAnalysis()->MergeBlock(pred);
    }
    assert(new_merge_target != pred);

    if (!new_merge_target) {
      // If the loop being transformed is outermost, and the predecessor is
      // part of that loop's continue construct, there will be no such
      // enclosing control construct.  In this case, the continue construct
      // will become unreachable anyway, so it is fine not to redirect the
      // edge.
      continue;
    }

    if (new_merge_target != original_target_id) {
      // Redirect the edge if it doesn't already point to the desired block.
      RedirectEdge(pred, original_target_id, new_merge_target);
    }
  }
}

void StructuredLoopToSelectionReductionOpportunity::RedirectEdge(
    uint32_t source_id, uint32_t original_target_id, uint32_t new_target_id) {
  // Redirect edge source_id->original_target_id to edge
  // source_id->new_target_id, where the blocks involved are all different.
  assert(source_id != original_target_id);
  assert(source_id != new_target_id);
  assert(original_target_id != new_target_id);

  // original_target_id must either be the merge target or continue construct
  // for the loop being operated on.
  assert(original_target_id == loop_construct_header_->MergeBlockId() ||
         original_target_id == loop_construct_header_->ContinueBlockId());

  auto terminator = context_->cfg()->block(source_id)->terminator();

  // Figure out which operands of the terminator need to be considered for
  // redirection.
  std::vector<uint32_t> operand_indices;
  if (terminator->opcode() == SpvOpBranch) {
    operand_indices = {0};
  } else if (terminator->opcode() == SpvOpBranchConditional) {
    operand_indices = {1, 2};
  } else {
    assert(terminator->opcode() == SpvOpSwitch);
    for (uint32_t label_index = 1; label_index < terminator->NumOperands();
         label_index += 2) {
      operand_indices.push_back(label_index);
    }
  }

  // Redirect the relevant operands, asserting that at least one redirection is
  // made.
  bool redirected = false;
  for (auto operand_index : operand_indices) {
    if (terminator->GetSingleWordOperand(operand_index) == original_target_id) {
      terminator->SetOperand(operand_index, {new_target_id});
      redirected = true;
    }
  }
  (void)(redirected);
  assert(redirected);

  // The old and new targets may have phi instructions; these will need to
  // respect the change in edges.
  AdaptPhiInstructionsForRemovedEdge(
      source_id, context_->cfg()->block(original_target_id));
  AdaptPhiInstructionsForAddedEdge(source_id,
                                   context_->cfg()->block(new_target_id));
}

void StructuredLoopToSelectionReductionOpportunity::
    AdaptPhiInstructionsForAddedEdge(uint32_t from_id,
                                     opt::BasicBlock* to_block) {
  to_block->ForEachPhiInst([this, &from_id](opt::Instruction* phi_inst) {
    // Add to the phi operand an (undef, from_id) pair to reflect the added
    // edge.
    auto undef_id = FindOrCreateGlobalUndef(context_, phi_inst->type_id());
    phi_inst->AddOperand(opt::Operand(SPV_OPERAND_TYPE_ID, {undef_id}));
    phi_inst->AddOperand(opt::Operand(SPV_OPERAND_TYPE_ID, {from_id}));
  });
}

void StructuredLoopToSelectionReductionOpportunity::ChangeLoopToSelection() {
  // Change the merge instruction from OpLoopMerge to OpSelectionMerge, with
  // the same merge block.
  auto loop_merge_inst = loop_construct_header_->GetLoopMergeInst();
  auto const loop_merge_block_id =
      loop_merge_inst->GetSingleWordOperand(kMergeNodeIndex);
  loop_merge_inst->SetOpcode(SpvOpSelectionMerge);
  loop_merge_inst->ReplaceOperands(
      {{loop_merge_inst->GetOperand(kMergeNodeIndex).type,
        {loop_merge_block_id}},
       {SPV_OPERAND_TYPE_SELECTION_CONTROL, {SpvSelectionControlMaskNone}}});

  // The loop header either finishes with OpBranch or OpBranchConditional.
  // The latter is fine for a selection.  In the former case we need to turn
  // it into OpBranchConditional.  We use "true" as the condition, and make
  // the "else" branch be the merge block.
  auto terminator = loop_construct_header_->terminator();
  if (terminator->opcode() == SpvOpBranch) {
    opt::analysis::Bool temp;
    const opt::analysis::Bool* bool_type =
        context_->get_type_mgr()->GetRegisteredType(&temp)->AsBool();
    auto const_mgr = context_->get_constant_mgr();
    auto true_const = const_mgr->GetConstant(bool_type, {1});
    auto true_const_result_id =
        const_mgr->GetDefiningInstruction(true_const)->result_id();
    auto original_branch_id = terminator->GetSingleWordOperand(0);
    terminator->SetOpcode(SpvOpBranchConditional);
    terminator->ReplaceOperands({{SPV_OPERAND_TYPE_ID, {true_const_result_id}},
                                 {SPV_OPERAND_TYPE_ID, {original_branch_id}},
                                 {SPV_OPERAND_TYPE_ID, {loop_merge_block_id}}});
    if (original_branch_id != loop_merge_block_id) {
      AdaptPhiInstructionsForAddedEdge(
          loop_construct_header_->id(),
          context_->cfg()->block(loop_merge_block_id));
    }
  }
}

void StructuredLoopToSelectionReductionOpportunity::FixNonDominatedIdUses() {
  // Consider each instruction in the function.
  for (auto& block : *loop_construct_header_->GetParent()) {
    for (auto& def : block) {
      if (def.opcode() == SpvOpVariable) {
        // Variables are defined at the start of the function, and can be
        // accessed by all blocks, even by unreachable blocks that have no
        // dominators, so we do not need to worry about them.
        continue;
      }
      context_->get_def_use_mgr()->ForEachUse(&def, [this, &block, &def](
                                                        opt::Instruction* use,
                                                        uint32_t index) {
        // Ignore uses outside of blocks, such as in OpDecorate.
        if (context_->get_instr_block(use) == nullptr) {
          return;
        }
        // If a use is not appropriately dominated by its definition,
        // replace the use with an OpUndef, unless the definition is an
        // access chain, in which case replace it with some (possibly fresh)
        // variable (as we cannot load from / store to OpUndef).
        if (!DefinitionSufficientlyDominatesUse(&def, use, index, block)) {
          if (def.opcode() == SpvOpAccessChain) {
            auto pointer_type =
                context_->get_type_mgr()->GetType(def.type_id())->AsPointer();
            switch (pointer_type->storage_class()) {
              case SpvStorageClassFunction:
                use->SetOperand(
                    index, {FindOrCreateFunctionVariable(
                               context_, loop_construct_header_->GetParent(),
                               context_->get_type_mgr()->GetId(pointer_type))});
                break;
              default:
                // TODO(2183) Need to think carefully about whether it makes
                //  sense to add new variables for all storage classes; it's
                //  fine for Private but might not be OK for input/output
                //  storage classes for example.
                use->SetOperand(
                    index, {FindOrCreateGlobalVariable(
                               context_,
                               context_->get_type_mgr()->GetId(pointer_type))});
                break;
                break;
            }
          } else {
            use->SetOperand(index,
                            {FindOrCreateGlobalUndef(context_, def.type_id())});
          }
        }
      });
    }
  }
}

bool StructuredLoopToSelectionReductionOpportunity::
    DefinitionSufficientlyDominatesUse(opt::Instruction* def,
                                       opt::Instruction* use,
                                       uint32_t use_index,
                                       opt::BasicBlock& def_block) {
  if (use->opcode() == SpvOpPhi) {
    // A use in a phi doesn't need to be dominated by its definition, but the
    // associated parent block does need to be dominated by the definition.
    return context_->GetDominatorAnalysis(loop_construct_header_->GetParent())
        ->Dominates(def_block.id(), use->GetSingleWordOperand(use_index + 1));
  }
  // In non-phi cases, a use needs to be dominated by its definition.
  return context_->GetDominatorAnalysis(loop_construct_header_->GetParent())
      ->Dominates(def, use);
}

}  // namespace reduce
}  // namespace spvtools
