// Copyright (c) 2017 Google Inc.
//
// 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/opt/loop_descriptor.h"

#include <algorithm>
#include <iostream>
#include <limits>
#include <stack>
#include <type_traits>
#include <utility>
#include <vector>

#include "source/opt/cfg.h"
#include "source/opt/constants.h"
#include "source/opt/dominator_tree.h"
#include "source/opt/ir_builder.h"
#include "source/opt/ir_context.h"
#include "source/opt/iterator.h"
#include "source/opt/tree_iterator.h"
#include "source/util/make_unique.h"

namespace spvtools {
namespace opt {

// Takes in a phi instruction |induction| and the loop |header| and returns the
// step operation of the loop.
Instruction* Loop::GetInductionStepOperation(
    const Instruction* induction) const {
  // Induction must be a phi instruction.
  assert(induction->opcode() == SpvOpPhi);

  Instruction* step = nullptr;

  analysis::DefUseManager* def_use_manager = context_->get_def_use_mgr();

  // Traverse the incoming operands of the phi instruction.
  for (uint32_t operand_id = 1; operand_id < induction->NumInOperands();
       operand_id += 2) {
    // Incoming edge.
    BasicBlock* incoming_block =
        context_->cfg()->block(induction->GetSingleWordInOperand(operand_id));

    // Check if the block is dominated by header, and thus coming from within
    // the loop.
    if (IsInsideLoop(incoming_block)) {
      step = def_use_manager->GetDef(
          induction->GetSingleWordInOperand(operand_id - 1));
      break;
    }
  }

  if (!step || !IsSupportedStepOp(step->opcode())) {
    return nullptr;
  }

  // The induction variable which binds the loop must only be modified once.
  uint32_t lhs = step->GetSingleWordInOperand(0);
  uint32_t rhs = step->GetSingleWordInOperand(1);

  // One of the left hand side or right hand side of the step instruction must
  // be the induction phi and the other must be an OpConstant.
  if (lhs != induction->result_id() && rhs != induction->result_id()) {
    return nullptr;
  }

  if (def_use_manager->GetDef(lhs)->opcode() != SpvOp::SpvOpConstant &&
      def_use_manager->GetDef(rhs)->opcode() != SpvOp::SpvOpConstant) {
    return nullptr;
  }

  return step;
}

// Returns true if the |step| operation is an induction variable step operation
// which is currently handled.
bool Loop::IsSupportedStepOp(SpvOp step) const {
  switch (step) {
    case SpvOp::SpvOpISub:
    case SpvOp::SpvOpIAdd:
      return true;
    default:
      return false;
  }
}

bool Loop::IsSupportedCondition(SpvOp condition) const {
  switch (condition) {
    // <
    case SpvOp::SpvOpULessThan:
    case SpvOp::SpvOpSLessThan:
    // >
    case SpvOp::SpvOpUGreaterThan:
    case SpvOp::SpvOpSGreaterThan:

    // >=
    case SpvOp::SpvOpSGreaterThanEqual:
    case SpvOp::SpvOpUGreaterThanEqual:
    // <=
    case SpvOp::SpvOpSLessThanEqual:
    case SpvOp::SpvOpULessThanEqual:

      return true;
    default:
      return false;
  }
}

int64_t Loop::GetResidualConditionValue(SpvOp condition, int64_t initial_value,
                                        int64_t step_value,
                                        size_t number_of_iterations,
                                        size_t factor) {
  int64_t remainder =
      initial_value + (number_of_iterations % factor) * step_value;

  // We subtract or add one as the above formula calculates the remainder if the
  // loop where just less than or greater than. Adding or subtracting one should
  // give a functionally equivalent value.
  switch (condition) {
    case SpvOp::SpvOpSGreaterThanEqual:
    case SpvOp::SpvOpUGreaterThanEqual: {
      remainder -= 1;
      break;
    }
    case SpvOp::SpvOpSLessThanEqual:
    case SpvOp::SpvOpULessThanEqual: {
      remainder += 1;
      break;
    }

    default:
      break;
  }
  return remainder;
}

Instruction* Loop::GetConditionInst() const {
  BasicBlock* condition_block = FindConditionBlock();
  if (!condition_block) {
    return nullptr;
  }
  Instruction* branch_conditional = &*condition_block->tail();
  if (!branch_conditional ||
      branch_conditional->opcode() != SpvOpBranchConditional) {
    return nullptr;
  }
  Instruction* condition_inst = context_->get_def_use_mgr()->GetDef(
      branch_conditional->GetSingleWordInOperand(0));
  if (IsSupportedCondition(condition_inst->opcode())) {
    return condition_inst;
  }

  return nullptr;
}

// Extract the initial value from the |induction| OpPhi instruction and store it
// in |value|. If the function couldn't find the initial value of |induction|
// return false.
bool Loop::GetInductionInitValue(const Instruction* induction,
                                 int64_t* value) const {
  Instruction* constant_instruction = nullptr;
  analysis::DefUseManager* def_use_manager = context_->get_def_use_mgr();

  for (uint32_t operand_id = 0; operand_id < induction->NumInOperands();
       operand_id += 2) {
    BasicBlock* bb = context_->cfg()->block(
        induction->GetSingleWordInOperand(operand_id + 1));

    if (!IsInsideLoop(bb)) {
      constant_instruction = def_use_manager->GetDef(
          induction->GetSingleWordInOperand(operand_id));
    }
  }

  if (!constant_instruction) return false;

  const analysis::Constant* constant =
      context_->get_constant_mgr()->FindDeclaredConstant(
          constant_instruction->result_id());
  if (!constant) return false;

  if (value) {
    const analysis::Integer* type =
        constant->AsIntConstant()->type()->AsInteger();

    if (type->IsSigned()) {
      *value = constant->AsIntConstant()->GetS32BitValue();
    } else {
      *value = constant->AsIntConstant()->GetU32BitValue();
    }
  }

  return true;
}

Loop::Loop(IRContext* context, DominatorAnalysis* dom_analysis,
           BasicBlock* header, BasicBlock* continue_target,
           BasicBlock* merge_target)
    : context_(context),
      loop_header_(header),
      loop_continue_(continue_target),
      loop_merge_(merge_target),
      loop_preheader_(nullptr),
      parent_(nullptr),
      loop_is_marked_for_removal_(false) {
  assert(context);
  assert(dom_analysis);
  loop_preheader_ = FindLoopPreheader(dom_analysis);
  loop_latch_ = FindLatchBlock();
}

BasicBlock* Loop::FindLoopPreheader(DominatorAnalysis* dom_analysis) {
  CFG* cfg = context_->cfg();
  DominatorTree& dom_tree = dom_analysis->GetDomTree();
  DominatorTreeNode* header_node = dom_tree.GetTreeNode(loop_header_);

  // The loop predecessor.
  BasicBlock* loop_pred = nullptr;

  auto header_pred = cfg->preds(loop_header_->id());
  for (uint32_t p_id : header_pred) {
    DominatorTreeNode* node = dom_tree.GetTreeNode(p_id);
    if (node && !dom_tree.Dominates(header_node, node)) {
      // The predecessor is not part of the loop, so potential loop preheader.
      if (loop_pred && node->bb_ != loop_pred) {
        // If we saw 2 distinct predecessors that are outside the loop, we don't
        // have a loop preheader.
        return nullptr;
      }
      loop_pred = node->bb_;
    }
  }
  // Safe guard against invalid code, SPIR-V spec forbids loop with the entry
  // node as header.
  assert(loop_pred && "The header node is the entry block ?");

  // So we have a unique basic block that can enter this loop.
  // If this loop is the unique successor of this block, then it is a loop
  // preheader.
  bool is_preheader = true;
  uint32_t loop_header_id = loop_header_->id();
  const auto* const_loop_pred = loop_pred;
  const_loop_pred->ForEachSuccessorLabel(
      [&is_preheader, loop_header_id](const uint32_t id) {
        if (id != loop_header_id) is_preheader = false;
      });
  if (is_preheader) return loop_pred;
  return nullptr;
}

bool Loop::IsInsideLoop(Instruction* inst) const {
  const BasicBlock* parent_block = context_->get_instr_block(inst);
  if (!parent_block) return false;
  return IsInsideLoop(parent_block);
}

bool Loop::IsBasicBlockInLoopSlow(const BasicBlock* bb) {
  assert(bb->GetParent() && "The basic block does not belong to a function");
  DominatorAnalysis* dom_analysis =
      context_->GetDominatorAnalysis(bb->GetParent());
  if (dom_analysis->IsReachable(bb) &&
      !dom_analysis->Dominates(GetHeaderBlock(), bb))
    return false;

  return true;
}

BasicBlock* Loop::GetOrCreatePreHeaderBlock() {
  if (loop_preheader_) return loop_preheader_;

  CFG* cfg = context_->cfg();
  loop_header_ = cfg->SplitLoopHeader(loop_header_);
  return loop_preheader_;
}

void Loop::SetContinueBlock(BasicBlock* continue_block) {
  assert(IsInsideLoop(continue_block));
  loop_continue_ = continue_block;
}

void Loop::SetLatchBlock(BasicBlock* latch) {
#ifndef NDEBUG
  assert(latch->GetParent() && "The basic block does not belong to a function");

  const auto* const_latch = latch;
  const_latch->ForEachSuccessorLabel([this](uint32_t id) {
    assert((!IsInsideLoop(id) || id == GetHeaderBlock()->id()) &&
           "A predecessor of the continue block does not belong to the loop");
  });
#endif  // NDEBUG
  assert(IsInsideLoop(latch) && "The continue block is not in the loop");

  SetLatchBlockImpl(latch);
}

void Loop::SetMergeBlock(BasicBlock* merge) {
#ifndef NDEBUG
  assert(merge->GetParent() && "The basic block does not belong to a function");
#endif  // NDEBUG
  assert(!IsInsideLoop(merge) && "The merge block is in the loop");

  SetMergeBlockImpl(merge);
  if (GetHeaderBlock()->GetLoopMergeInst()) {
    UpdateLoopMergeInst();
  }
}

void Loop::SetPreHeaderBlock(BasicBlock* preheader) {
  if (preheader) {
    assert(!IsInsideLoop(preheader) && "The preheader block is in the loop");
    assert(preheader->tail()->opcode() == SpvOpBranch &&
           "The preheader block does not unconditionally branch to the header "
           "block");
    assert(preheader->tail()->GetSingleWordOperand(0) ==
               GetHeaderBlock()->id() &&
           "The preheader block does not unconditionally branch to the header "
           "block");
  }
  loop_preheader_ = preheader;
}

BasicBlock* Loop::FindLatchBlock() {
  CFG* cfg = context_->cfg();

  DominatorAnalysis* dominator_analysis =
      context_->GetDominatorAnalysis(loop_header_->GetParent());

  // Look at the predecessors of the loop header to find a predecessor block
  // which is dominated by the loop continue target. There should only be one
  // block which meets this criteria and this is the latch block, as per the
  // SPIR-V spec.
  for (uint32_t block_id : cfg->preds(loop_header_->id())) {
    if (dominator_analysis->Dominates(loop_continue_->id(), block_id)) {
      return cfg->block(block_id);
    }
  }

  assert(
      false &&
      "Every loop should have a latch block dominated by the continue target");
  return nullptr;
}

void Loop::GetExitBlocks(std::unordered_set<uint32_t>* exit_blocks) const {
  CFG* cfg = context_->cfg();
  exit_blocks->clear();

  for (uint32_t bb_id : GetBlocks()) {
    const BasicBlock* bb = cfg->block(bb_id);
    bb->ForEachSuccessorLabel([exit_blocks, this](uint32_t succ) {
      if (!IsInsideLoop(succ)) {
        exit_blocks->insert(succ);
      }
    });
  }
}

void Loop::GetMergingBlocks(
    std::unordered_set<uint32_t>* merging_blocks) const {
  assert(GetMergeBlock() && "This loop is not structured");
  CFG* cfg = context_->cfg();
  merging_blocks->clear();

  std::stack<const BasicBlock*> to_visit;
  to_visit.push(GetMergeBlock());
  while (!to_visit.empty()) {
    const BasicBlock* bb = to_visit.top();
    to_visit.pop();
    merging_blocks->insert(bb->id());
    for (uint32_t pred_id : cfg->preds(bb->id())) {
      if (!IsInsideLoop(pred_id) && !merging_blocks->count(pred_id)) {
        to_visit.push(cfg->block(pred_id));
      }
    }
  }
}

namespace {

static inline bool IsBasicBlockSafeToClone(IRContext* context, BasicBlock* bb) {
  for (Instruction& inst : *bb) {
    if (!inst.IsBranch() && !context->IsCombinatorInstruction(&inst))
      return false;
  }

  return true;
}

}  // namespace

bool Loop::IsSafeToClone() const {
  CFG& cfg = *context_->cfg();

  for (uint32_t bb_id : GetBlocks()) {
    BasicBlock* bb = cfg.block(bb_id);
    assert(bb);
    if (!IsBasicBlockSafeToClone(context_, bb)) return false;
  }

  // Look at the merge construct.
  if (GetHeaderBlock()->GetLoopMergeInst()) {
    std::unordered_set<uint32_t> blocks;
    GetMergingBlocks(&blocks);
    blocks.erase(GetMergeBlock()->id());
    for (uint32_t bb_id : blocks) {
      BasicBlock* bb = cfg.block(bb_id);
      assert(bb);
      if (!IsBasicBlockSafeToClone(context_, bb)) return false;
    }
  }

  return true;
}

bool Loop::IsLCSSA() const {
  CFG* cfg = context_->cfg();
  analysis::DefUseManager* def_use_mgr = context_->get_def_use_mgr();

  std::unordered_set<uint32_t> exit_blocks;
  GetExitBlocks(&exit_blocks);

  // Declare ir_context so we can capture context_ in the below lambda
  IRContext* ir_context = context_;

  for (uint32_t bb_id : GetBlocks()) {
    for (Instruction& insn : *cfg->block(bb_id)) {
      // All uses must be either:
      //  - In the loop;
      //  - In an exit block and in a phi instruction.
      if (!def_use_mgr->WhileEachUser(
              &insn,
              [&exit_blocks, ir_context, this](Instruction* use) -> bool {
                BasicBlock* parent = ir_context->get_instr_block(use);
                assert(parent && "Invalid analysis");
                if (IsInsideLoop(parent)) return true;
                if (use->opcode() != SpvOpPhi) return false;
                return exit_blocks.count(parent->id());
              }))
        return false;
    }
  }
  return true;
}

bool Loop::ShouldHoistInstruction(IRContext* context, Instruction* inst) {
  return AreAllOperandsOutsideLoop(context, inst) &&
         inst->IsOpcodeCodeMotionSafe();
}

bool Loop::AreAllOperandsOutsideLoop(IRContext* context, Instruction* inst) {
  analysis::DefUseManager* def_use_mgr = context->get_def_use_mgr();
  bool all_outside_loop = true;

  const std::function<void(uint32_t*)> operand_outside_loop =
      [this, &def_use_mgr, &all_outside_loop](uint32_t* id) {
        if (this->IsInsideLoop(def_use_mgr->GetDef(*id))) {
          all_outside_loop = false;
          return;
        }
      };

  inst->ForEachInId(operand_outside_loop);
  return all_outside_loop;
}

void Loop::ComputeLoopStructuredOrder(
    std::vector<BasicBlock*>* ordered_loop_blocks, bool include_pre_header,
    bool include_merge) const {
  CFG& cfg = *context_->cfg();

  // Reserve the memory: all blocks in the loop + extra if needed.
  ordered_loop_blocks->reserve(GetBlocks().size() + include_pre_header +
                               include_merge);

  if (include_pre_header && GetPreHeaderBlock())
    ordered_loop_blocks->push_back(loop_preheader_);
  cfg.ForEachBlockInReversePostOrder(
      loop_header_, [ordered_loop_blocks, this](BasicBlock* bb) {
        if (IsInsideLoop(bb)) ordered_loop_blocks->push_back(bb);
      });
  if (include_merge && GetMergeBlock())
    ordered_loop_blocks->push_back(loop_merge_);
}

LoopDescriptor::LoopDescriptor(IRContext* context, const Function* f)
    : loops_(), dummy_top_loop_(nullptr) {
  PopulateList(context, f);
}

LoopDescriptor::~LoopDescriptor() { ClearLoops(); }

void LoopDescriptor::PopulateList(IRContext* context, const Function* f) {
  DominatorAnalysis* dom_analysis = context->GetDominatorAnalysis(f);

  ClearLoops();

  // Post-order traversal of the dominator tree to find all the OpLoopMerge
  // instructions.
  DominatorTree& dom_tree = dom_analysis->GetDomTree();
  for (DominatorTreeNode& node :
       make_range(dom_tree.post_begin(), dom_tree.post_end())) {
    Instruction* merge_inst = node.bb_->GetLoopMergeInst();
    if (merge_inst) {
      bool all_backedge_unreachable = true;
      for (uint32_t pid : context->cfg()->preds(node.bb_->id())) {
        if (dom_analysis->IsReachable(pid) &&
            dom_analysis->Dominates(node.bb_->id(), pid)) {
          all_backedge_unreachable = false;
          break;
        }
      }
      if (all_backedge_unreachable)
        continue;  // ignore this one, we actually never branch back.

      // The id of the merge basic block of this loop.
      uint32_t merge_bb_id = merge_inst->GetSingleWordOperand(0);

      // The id of the continue basic block of this loop.
      uint32_t continue_bb_id = merge_inst->GetSingleWordOperand(1);

      // The merge target of this loop.
      BasicBlock* merge_bb = context->cfg()->block(merge_bb_id);

      // The continue target of this loop.
      BasicBlock* continue_bb = context->cfg()->block(continue_bb_id);

      // The basic block containing the merge instruction.
      BasicBlock* header_bb = context->get_instr_block(merge_inst);

      // Add the loop to the list of all the loops in the function.
      Loop* current_loop =
          new Loop(context, dom_analysis, header_bb, continue_bb, merge_bb);
      loops_.push_back(current_loop);

      // We have a bottom-up construction, so if this loop has nested-loops,
      // they are by construction at the tail of the loop list.
      for (auto itr = loops_.rbegin() + 1; itr != loops_.rend(); ++itr) {
        Loop* previous_loop = *itr;

        // If the loop already has a parent, then it has been processed.
        if (previous_loop->HasParent()) continue;

        // If the current loop does not dominates the previous loop then it is
        // not nested loop.
        if (!dom_analysis->Dominates(header_bb,
                                     previous_loop->GetHeaderBlock()))
          continue;
        // If the current loop merge dominates the previous loop then it is
        // not nested loop.
        if (dom_analysis->Dominates(merge_bb, previous_loop->GetHeaderBlock()))
          continue;

        current_loop->AddNestedLoop(previous_loop);
      }
      DominatorTreeNode* dom_merge_node = dom_tree.GetTreeNode(merge_bb);
      for (DominatorTreeNode& loop_node :
           make_range(node.df_begin(), node.df_end())) {
        // Check if we are in the loop.
        if (dom_tree.Dominates(dom_merge_node, &loop_node)) continue;
        current_loop->AddBasicBlock(loop_node.bb_);
        basic_block_to_loop_.insert(
            std::make_pair(loop_node.bb_->id(), current_loop));
      }
    }
  }
  for (Loop* loop : loops_) {
    if (!loop->HasParent()) dummy_top_loop_.nested_loops_.push_back(loop);
  }
}

std::vector<Loop*> LoopDescriptor::GetLoopsInBinaryLayoutOrder() {
  std::vector<uint32_t> ids{};

  for (size_t i = 0; i < NumLoops(); ++i) {
    ids.push_back(GetLoopByIndex(i).GetHeaderBlock()->id());
  }

  std::vector<Loop*> loops{};
  if (!ids.empty()) {
    auto function = GetLoopByIndex(0).GetHeaderBlock()->GetParent();
    for (const auto& block : *function) {
      auto block_id = block.id();

      auto element = std::find(std::begin(ids), std::end(ids), block_id);
      if (element != std::end(ids)) {
        loops.push_back(&GetLoopByIndex(element - std::begin(ids)));
      }
    }
  }

  return loops;
}

BasicBlock* Loop::FindConditionBlock() const {
  if (!loop_merge_) {
    return nullptr;
  }
  BasicBlock* condition_block = nullptr;

  uint32_t in_loop_pred = 0;
  for (uint32_t p : context_->cfg()->preds(loop_merge_->id())) {
    if (IsInsideLoop(p)) {
      if (in_loop_pred) {
        // 2 in-loop predecessors.
        return nullptr;
      }
      in_loop_pred = p;
    }
  }
  if (!in_loop_pred) {
    // Merge block is unreachable.
    return nullptr;
  }

  BasicBlock* bb = context_->cfg()->block(in_loop_pred);

  if (!bb) return nullptr;

  const Instruction& branch = *bb->ctail();

  // Make sure the branch is a conditional branch.
  if (branch.opcode() != SpvOpBranchConditional) return nullptr;

  // Make sure one of the two possible branches is to the merge block.
  if (branch.GetSingleWordInOperand(1) == loop_merge_->id() ||
      branch.GetSingleWordInOperand(2) == loop_merge_->id()) {
    condition_block = bb;
  }

  return condition_block;
}

bool Loop::FindNumberOfIterations(const Instruction* induction,
                                  const Instruction* branch_inst,
                                  size_t* iterations_out,
                                  int64_t* step_value_out,
                                  int64_t* init_value_out) const {
  // From the branch instruction find the branch condition.
  analysis::DefUseManager* def_use_manager = context_->get_def_use_mgr();

  // Condition instruction from the OpConditionalBranch.
  Instruction* condition =
      def_use_manager->GetDef(branch_inst->GetSingleWordOperand(0));

  assert(IsSupportedCondition(condition->opcode()));

  // Get the constant manager from the ir context.
  analysis::ConstantManager* const_manager = context_->get_constant_mgr();

  // Find the constant value used by the condition variable. Exit out if it
  // isn't a constant int.
  const analysis::Constant* upper_bound =
      const_manager->FindDeclaredConstant(condition->GetSingleWordOperand(3));
  if (!upper_bound) return false;

  // Must be integer because of the opcode on the condition.
  int64_t condition_value = 0;

  const analysis::Integer* type =
      upper_bound->AsIntConstant()->type()->AsInteger();

  if (type->width() > 32) {
    return false;
  }

  if (type->IsSigned()) {
    condition_value = upper_bound->AsIntConstant()->GetS32BitValue();
  } else {
    condition_value = upper_bound->AsIntConstant()->GetU32BitValue();
  }

  // Find the instruction which is stepping through the loop.
  Instruction* step_inst = GetInductionStepOperation(induction);
  if (!step_inst) return false;

  // Find the constant value used by the condition variable.
  const analysis::Constant* step_constant =
      const_manager->FindDeclaredConstant(step_inst->GetSingleWordOperand(3));
  if (!step_constant) return false;

  // Must be integer because of the opcode on the condition.
  int64_t step_value = 0;

  const analysis::Integer* step_type =
      step_constant->AsIntConstant()->type()->AsInteger();

  if (step_type->IsSigned()) {
    step_value = step_constant->AsIntConstant()->GetS32BitValue();
  } else {
    step_value = step_constant->AsIntConstant()->GetU32BitValue();
  }

  // If this is a subtraction step we should negate the step value.
  if (step_inst->opcode() == SpvOp::SpvOpISub) {
    step_value = -step_value;
  }

  // Find the inital value of the loop and make sure it is a constant integer.
  int64_t init_value = 0;
  if (!GetInductionInitValue(induction, &init_value)) return false;

  // If iterations is non null then store the value in that.
  int64_t num_itrs = GetIterations(condition->opcode(), condition_value,
                                   init_value, step_value);

  // If the loop body will not be reached return false.
  if (num_itrs <= 0) {
    return false;
  }

  if (iterations_out) {
    assert(static_cast<size_t>(num_itrs) <= std::numeric_limits<size_t>::max());
    *iterations_out = static_cast<size_t>(num_itrs);
  }

  if (step_value_out) {
    *step_value_out = step_value;
  }

  if (init_value_out) {
    *init_value_out = init_value;
  }

  return true;
}

// We retrieve the number of iterations using the following formula, diff /
// |step_value| where diff is calculated differently according to the
// |condition| and uses the |condition_value| and |init_value|. If diff /
// |step_value| is NOT cleanly divisable then we add one to the sum.
int64_t Loop::GetIterations(SpvOp condition, int64_t condition_value,
                            int64_t init_value, int64_t step_value) const {
  int64_t diff = 0;

  switch (condition) {
    case SpvOp::SpvOpSLessThan:
    case SpvOp::SpvOpULessThan: {
      // If the condition is not met to begin with the loop will never iterate.
      if (!(init_value < condition_value)) return 0;

      diff = condition_value - init_value;

      // If the operation is a less then operation then the diff and step must
      // have the same sign otherwise the induction will never cross the
      // condition (either never true or always true).
      if ((diff < 0 && step_value > 0) || (diff > 0 && step_value < 0)) {
        return 0;
      }

      break;
    }
    case SpvOp::SpvOpSGreaterThan:
    case SpvOp::SpvOpUGreaterThan: {
      // If the condition is not met to begin with the loop will never iterate.
      if (!(init_value > condition_value)) return 0;

      diff = init_value - condition_value;

      // If the operation is a greater than operation then the diff and step
      // must have opposite signs. Otherwise the condition will always be true
      // or will never be true.
      if ((diff < 0 && step_value < 0) || (diff > 0 && step_value > 0)) {
        return 0;
      }

      break;
    }

    case SpvOp::SpvOpSGreaterThanEqual:
    case SpvOp::SpvOpUGreaterThanEqual: {
      // If the condition is not met to begin with the loop will never iterate.
      if (!(init_value >= condition_value)) return 0;

      // We subract one to make it the same as SpvOpGreaterThan as it is
      // functionally equivalent.
      diff = init_value - (condition_value - 1);

      // If the operation is a greater than operation then the diff and step
      // must have opposite signs. Otherwise the condition will always be true
      // or will never be true.
      if ((diff > 0 && step_value > 0) || (diff < 0 && step_value < 0)) {
        return 0;
      }

      break;
    }

    case SpvOp::SpvOpSLessThanEqual:
    case SpvOp::SpvOpULessThanEqual: {
      // If the condition is not met to begin with the loop will never iterate.
      if (!(init_value <= condition_value)) return 0;

      // We add one to make it the same as SpvOpLessThan as it is functionally
      // equivalent.
      diff = (condition_value + 1) - init_value;

      // If the operation is a less than operation then the diff and step must
      // have the same sign otherwise the induction will never cross the
      // condition (either never true or always true).
      if ((diff < 0 && step_value > 0) || (diff > 0 && step_value < 0)) {
        return 0;
      }

      break;
    }

    default:
      assert(false &&
             "Could not retrieve number of iterations from the loop condition. "
             "Condition is not supported.");
  }

  // Take the abs of - step values.
  step_value = llabs(step_value);
  diff = llabs(diff);
  int64_t result = diff / step_value;

  if (diff % step_value != 0) {
    result += 1;
  }
  return result;
}

// Returns the list of induction variables within the loop.
void Loop::GetInductionVariables(
    std::vector<Instruction*>& induction_variables) const {
  for (Instruction& inst : *loop_header_) {
    if (inst.opcode() == SpvOp::SpvOpPhi) {
      induction_variables.push_back(&inst);
    }
  }
}

Instruction* Loop::FindConditionVariable(
    const BasicBlock* condition_block) const {
  // Find the branch instruction.
  const Instruction& branch_inst = *condition_block->ctail();

  Instruction* induction = nullptr;
  // Verify that the branch instruction is a conditional branch.
  if (branch_inst.opcode() == SpvOp::SpvOpBranchConditional) {
    // From the branch instruction find the branch condition.
    analysis::DefUseManager* def_use_manager = context_->get_def_use_mgr();

    // Find the instruction representing the condition used in the conditional
    // branch.
    Instruction* condition =
        def_use_manager->GetDef(branch_inst.GetSingleWordOperand(0));

    // Ensure that the condition is a less than operation.
    if (condition && IsSupportedCondition(condition->opcode())) {
      // The left hand side operand of the operation.
      Instruction* variable_inst =
          def_use_manager->GetDef(condition->GetSingleWordOperand(2));

      // Make sure the variable instruction used is a phi.
      if (!variable_inst || variable_inst->opcode() != SpvOpPhi) return nullptr;

      // Make sure the phi instruction only has two incoming blocks. Each
      // incoming block will be represented by two in operands in the phi
      // instruction, the value and the block which that value came from. We
      // assume the cannocalised phi will have two incoming values, one from the
      // preheader and one from the continue block.
      size_t max_supported_operands = 4;
      if (variable_inst->NumInOperands() == max_supported_operands) {
        // The operand index of the first incoming block label.
        uint32_t operand_label_1 = 1;

        // The operand index of the second incoming block label.
        uint32_t operand_label_2 = 3;

        // Make sure one of them is the preheader.
        if (!IsInsideLoop(
                variable_inst->GetSingleWordInOperand(operand_label_1)) &&
            !IsInsideLoop(
                variable_inst->GetSingleWordInOperand(operand_label_2))) {
          return nullptr;
        }

        // And make sure that the other is the latch block.
        if (variable_inst->GetSingleWordInOperand(operand_label_1) !=
                loop_latch_->id() &&
            variable_inst->GetSingleWordInOperand(operand_label_2) !=
                loop_latch_->id()) {
          return nullptr;
        }
      } else {
        return nullptr;
      }

      if (!FindNumberOfIterations(variable_inst, &branch_inst, nullptr))
        return nullptr;
      induction = variable_inst;
    }
  }

  return induction;
}

bool LoopDescriptor::CreatePreHeaderBlocksIfMissing() {
  auto modified = false;

  for (auto& loop : *this) {
    if (!loop.GetPreHeaderBlock()) {
      modified = true;
      // TODO(1841): Handle failure to create pre-header.
      loop.GetOrCreatePreHeaderBlock();
    }
  }

  return modified;
}

// Add and remove loops which have been marked for addition and removal to
// maintain the state of the loop descriptor class.
void LoopDescriptor::PostModificationCleanup() {
  LoopContainerType loops_to_remove_;
  for (Loop* loop : loops_) {
    if (loop->IsMarkedForRemoval()) {
      loops_to_remove_.push_back(loop);
      if (loop->HasParent()) {
        loop->GetParent()->RemoveChildLoop(loop);
      }
    }
  }

  for (Loop* loop : loops_to_remove_) {
    loops_.erase(std::find(loops_.begin(), loops_.end(), loop));
    delete loop;
  }

  for (auto& pair : loops_to_add_) {
    Loop* parent = pair.first;
    std::unique_ptr<Loop> loop = std::move(pair.second);

    if (parent) {
      loop->SetParent(nullptr);
      parent->AddNestedLoop(loop.get());

      for (uint32_t block_id : loop->GetBlocks()) {
        parent->AddBasicBlock(block_id);
      }
    }

    loops_.emplace_back(loop.release());
  }

  loops_to_add_.clear();
}

void LoopDescriptor::ClearLoops() {
  for (Loop* loop : loops_) {
    delete loop;
  }
  loops_.clear();
}

// Adds a new loop nest to the descriptor set.
Loop* LoopDescriptor::AddLoopNest(std::unique_ptr<Loop> new_loop) {
  Loop* loop = new_loop.release();
  if (!loop->HasParent()) dummy_top_loop_.nested_loops_.push_back(loop);
  // Iterate from inner to outer most loop, adding basic block to loop mapping
  // as we go.
  for (Loop& current_loop :
       make_range(iterator::begin(loop), iterator::end(nullptr))) {
    loops_.push_back(&current_loop);
    for (uint32_t bb_id : current_loop.GetBlocks())
      basic_block_to_loop_.insert(std::make_pair(bb_id, &current_loop));
  }

  return loop;
}

void LoopDescriptor::RemoveLoop(Loop* loop) {
  Loop* parent = loop->GetParent() ? loop->GetParent() : &dummy_top_loop_;
  parent->nested_loops_.erase(std::find(parent->nested_loops_.begin(),
                                        parent->nested_loops_.end(), loop));
  std::for_each(
      loop->nested_loops_.begin(), loop->nested_loops_.end(),
      [loop](Loop* sub_loop) { sub_loop->SetParent(loop->GetParent()); });
  parent->nested_loops_.insert(parent->nested_loops_.end(),
                               loop->nested_loops_.begin(),
                               loop->nested_loops_.end());
  for (uint32_t bb_id : loop->GetBlocks()) {
    Loop* l = FindLoopForBasicBlock(bb_id);
    if (l == loop) {
      SetBasicBlockToLoop(bb_id, l->GetParent());
    } else {
      ForgetBasicBlock(bb_id);
    }
  }

  LoopContainerType::iterator it =
      std::find(loops_.begin(), loops_.end(), loop);
  assert(it != loops_.end());
  delete loop;
  loops_.erase(it);
}

}  // namespace opt
}  // namespace spvtools
