// 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/opt/loop_fusion.h"

#include <algorithm>
#include <vector>

#include "source/opt/ir_context.h"
#include "source/opt/loop_dependence.h"
#include "source/opt/loop_descriptor.h"

namespace spvtools {
namespace opt {

namespace {

// Append all the loops nested in |loop| to |loops|.
void CollectChildren(Loop* loop, std::vector<const Loop*>* loops) {
  for (auto child : *loop) {
    loops->push_back(child);
    if (child->NumImmediateChildren() != 0) {
      CollectChildren(child, loops);
    }
  }
}

// Return the set of locations accessed by |stores| and |loads|.
std::set<Instruction*> GetLocationsAccessed(
    const std::map<Instruction*, std::vector<Instruction*>>& stores,
    const std::map<Instruction*, std::vector<Instruction*>>& loads) {
  std::set<Instruction*> locations{};

  for (const auto& kv : stores) {
    locations.insert(std::get<0>(kv));
  }

  for (const auto& kv : loads) {
    locations.insert(std::get<0>(kv));
  }

  return locations;
}

// Append all dependences from |sources| to |destinations| to |dependences|.
void GetDependences(std::vector<DistanceVector>* dependences,
                    LoopDependenceAnalysis* analysis,
                    const std::vector<Instruction*>& sources,
                    const std::vector<Instruction*>& destinations,
                    size_t num_entries) {
  for (auto source : sources) {
    for (auto destination : destinations) {
      DistanceVector dist(num_entries);
      if (!analysis->GetDependence(source, destination, &dist)) {
        dependences->push_back(dist);
      }
    }
  }
}

// Apped all instructions in |block| to |instructions|.
void AddInstructionsInBlock(std::vector<Instruction*>* instructions,
                            BasicBlock* block) {
  for (auto& inst : *block) {
    instructions->push_back(&inst);
  }

  instructions->push_back(block->GetLabelInst());
}

}  // namespace

bool LoopFusion::UsedInContinueOrConditionBlock(Instruction* phi_instruction,
                                                Loop* loop) {
  auto condition_block = loop->FindConditionBlock()->id();
  auto continue_block = loop->GetContinueBlock()->id();
  auto not_used = context_->get_def_use_mgr()->WhileEachUser(
      phi_instruction,
      [this, condition_block, continue_block](Instruction* instruction) {
        auto block_id = context_->get_instr_block(instruction)->id();
        return block_id != condition_block && block_id != continue_block;
      });

  return !not_used;
}

void LoopFusion::RemoveIfNotUsedContinueOrConditionBlock(
    std::vector<Instruction*>* instructions, Loop* loop) {
  instructions->erase(
      std::remove_if(std::begin(*instructions), std::end(*instructions),
                     [this, loop](Instruction* instruction) {
                       return !UsedInContinueOrConditionBlock(instruction,
                                                              loop);
                     }),
      std::end(*instructions));
}

bool LoopFusion::AreCompatible() {
  // Check that the loops are in the same function.
  if (loop_0_->GetHeaderBlock()->GetParent() !=
      loop_1_->GetHeaderBlock()->GetParent()) {
    return false;
  }

  // Check that both loops have pre-header blocks.
  if (!loop_0_->GetPreHeaderBlock() || !loop_1_->GetPreHeaderBlock()) {
    return false;
  }

  // Check there are no breaks.
  if (context_->cfg()->preds(loop_0_->GetMergeBlock()->id()).size() != 1 ||
      context_->cfg()->preds(loop_1_->GetMergeBlock()->id()).size() != 1) {
    return false;
  }

  // Check there are no continues.
  if (context_->cfg()->preds(loop_0_->GetContinueBlock()->id()).size() != 1 ||
      context_->cfg()->preds(loop_1_->GetContinueBlock()->id()).size() != 1) {
    return false;
  }

  // |GetInductionVariables| returns all OpPhi in the header. Check that both
  // loops have exactly one that is used in the continue and condition blocks.
  std::vector<Instruction*> inductions_0{}, inductions_1{};
  loop_0_->GetInductionVariables(inductions_0);
  RemoveIfNotUsedContinueOrConditionBlock(&inductions_0, loop_0_);

  if (inductions_0.size() != 1) {
    return false;
  }

  induction_0_ = inductions_0.front();

  loop_1_->GetInductionVariables(inductions_1);
  RemoveIfNotUsedContinueOrConditionBlock(&inductions_1, loop_1_);

  if (inductions_1.size() != 1) {
    return false;
  }

  induction_1_ = inductions_1.front();

  if (!CheckInit()) {
    return false;
  }

  if (!CheckCondition()) {
    return false;
  }

  if (!CheckStep()) {
    return false;
  }

  // Check adjacency, |loop_0_| should come just before |loop_1_|.
  // There is always at least one block between loops, even if it's empty.
  // We'll check at most 2 preceeding blocks.

  auto pre_header_1 = loop_1_->GetPreHeaderBlock();

  std::vector<BasicBlock*> block_to_check{};
  block_to_check.push_back(pre_header_1);

  if (loop_0_->GetMergeBlock() != loop_1_->GetPreHeaderBlock()) {
    // Follow CFG for one more block.
    auto preds = context_->cfg()->preds(pre_header_1->id());
    if (preds.size() == 1) {
      auto block = &*containing_function_->FindBlock(preds.front());
      if (block == loop_0_->GetMergeBlock()) {
        block_to_check.push_back(block);
      } else {
        return false;
      }
    } else {
      return false;
    }
  }

  // Check that the separating blocks are either empty or only contains a store
  // to a local variable that is never read (left behind by
  // '--eliminate-local-multi-store'). Also allow OpPhi, since the loop could be
  // in LCSSA form.
  for (auto block : block_to_check) {
    for (auto& inst : *block) {
      if (inst.opcode() == SpvOpStore) {
        // Get the definition of the target to check it's function scope so
        // there are no observable side effects.
        auto variable =
            context_->get_def_use_mgr()->GetDef(inst.GetSingleWordInOperand(0));

        if (variable->opcode() != SpvOpVariable ||
            variable->GetSingleWordInOperand(0) != SpvStorageClassFunction) {
          return false;
        }

        // Check the target is never loaded.
        auto is_used = false;
        context_->get_def_use_mgr()->ForEachUse(
            inst.GetSingleWordInOperand(0),
            [&is_used](Instruction* use_inst, uint32_t) {
              if (use_inst->opcode() == SpvOpLoad) {
                is_used = true;
              }
            });

        if (is_used) {
          return false;
        }
      } else if (inst.opcode() == SpvOpPhi) {
        if (inst.NumInOperands() != 2) {
          return false;
        }
      } else if (inst.opcode() != SpvOpBranch) {
        return false;
      }
    }
  }

  return true;
}  // namespace opt

bool LoopFusion::ContainsBarriersOrFunctionCalls(Loop* loop) {
  for (const auto& block : loop->GetBlocks()) {
    for (const auto& inst : *containing_function_->FindBlock(block)) {
      auto opcode = inst.opcode();
      if (opcode == SpvOpFunctionCall || opcode == SpvOpControlBarrier ||
          opcode == SpvOpMemoryBarrier || opcode == SpvOpTypeNamedBarrier ||
          opcode == SpvOpNamedBarrierInitialize ||
          opcode == SpvOpMemoryNamedBarrier) {
        return true;
      }
    }
  }

  return false;
}

bool LoopFusion::CheckInit() {
  int64_t loop_0_init;
  if (!loop_0_->GetInductionInitValue(induction_0_, &loop_0_init)) {
    return false;
  }

  int64_t loop_1_init;
  if (!loop_1_->GetInductionInitValue(induction_1_, &loop_1_init)) {
    return false;
  }

  if (loop_0_init != loop_1_init) {
    return false;
  }

  return true;
}

bool LoopFusion::CheckCondition() {
  auto condition_0 = loop_0_->GetConditionInst();
  auto condition_1 = loop_1_->GetConditionInst();

  if (!loop_0_->IsSupportedCondition(condition_0->opcode()) ||
      !loop_1_->IsSupportedCondition(condition_1->opcode())) {
    return false;
  }

  if (condition_0->opcode() != condition_1->opcode()) {
    return false;
  }

  for (uint32_t i = 0; i < condition_0->NumInOperandWords(); ++i) {
    auto arg_0 = context_->get_def_use_mgr()->GetDef(
        condition_0->GetSingleWordInOperand(i));
    auto arg_1 = context_->get_def_use_mgr()->GetDef(
        condition_1->GetSingleWordInOperand(i));

    if (arg_0 == induction_0_ && arg_1 == induction_1_) {
      continue;
    }

    if (arg_0 == induction_0_ && arg_1 != induction_1_) {
      return false;
    }

    if (arg_1 == induction_1_ && arg_0 != induction_0_) {
      return false;
    }

    if (arg_0 != arg_1) {
      return false;
    }
  }

  return true;
}

bool LoopFusion::CheckStep() {
  auto scalar_analysis = context_->GetScalarEvolutionAnalysis();
  SENode* induction_node_0 = scalar_analysis->SimplifyExpression(
      scalar_analysis->AnalyzeInstruction(induction_0_));
  if (!induction_node_0->AsSERecurrentNode()) {
    return false;
  }

  SENode* induction_step_0 =
      induction_node_0->AsSERecurrentNode()->GetCoefficient();
  if (!induction_step_0->AsSEConstantNode()) {
    return false;
  }

  SENode* induction_node_1 = scalar_analysis->SimplifyExpression(
      scalar_analysis->AnalyzeInstruction(induction_1_));
  if (!induction_node_1->AsSERecurrentNode()) {
    return false;
  }

  SENode* induction_step_1 =
      induction_node_1->AsSERecurrentNode()->GetCoefficient();
  if (!induction_step_1->AsSEConstantNode()) {
    return false;
  }

  if (*induction_step_0 != *induction_step_1) {
    return false;
  }

  return true;
}

std::map<Instruction*, std::vector<Instruction*>> LoopFusion::LocationToMemOps(
    const std::vector<Instruction*>& mem_ops) {
  std::map<Instruction*, std::vector<Instruction*>> location_map{};

  for (auto instruction : mem_ops) {
    auto access_location = context_->get_def_use_mgr()->GetDef(
        instruction->GetSingleWordInOperand(0));

    while (access_location->opcode() == SpvOpAccessChain) {
      access_location = context_->get_def_use_mgr()->GetDef(
          access_location->GetSingleWordInOperand(0));
    }

    location_map[access_location].push_back(instruction);
  }

  return location_map;
}

std::pair<std::vector<Instruction*>, std::vector<Instruction*>>
LoopFusion::GetLoadsAndStoresInLoop(Loop* loop) {
  std::vector<Instruction*> loads{};
  std::vector<Instruction*> stores{};

  for (auto block_id : loop->GetBlocks()) {
    if (block_id == loop->GetContinueBlock()->id()) {
      continue;
    }

    for (auto& instruction : *containing_function_->FindBlock(block_id)) {
      if (instruction.opcode() == SpvOpLoad) {
        loads.push_back(&instruction);
      } else if (instruction.opcode() == SpvOpStore) {
        stores.push_back(&instruction);
      }
    }
  }

  return std::make_pair(loads, stores);
}

bool LoopFusion::IsUsedInLoop(Instruction* instruction, Loop* loop) {
  auto not_used = context_->get_def_use_mgr()->WhileEachUser(
      instruction, [this, loop](Instruction* user) {
        auto block_id = context_->get_instr_block(user)->id();
        return !loop->IsInsideLoop(block_id);
      });

  return !not_used;
}

bool LoopFusion::IsLegal() {
  assert(AreCompatible() && "Fusion can't be legal, loops are not compatible.");

  // Bail out if there are function calls as they could have side-effects that
  // cause dependencies or if there are any barriers.
  if (ContainsBarriersOrFunctionCalls(loop_0_) ||
      ContainsBarriersOrFunctionCalls(loop_1_)) {
    return false;
  }

  std::vector<Instruction*> phi_instructions{};
  loop_0_->GetInductionVariables(phi_instructions);

  // Check no OpPhi in |loop_0_| is used in |loop_1_|.
  for (auto phi_instruction : phi_instructions) {
    if (IsUsedInLoop(phi_instruction, loop_1_)) {
      return false;
    }
  }

  // Check no LCSSA OpPhi in merge block of |loop_0_| is used in |loop_1_|.
  auto phi_used = false;
  loop_0_->GetMergeBlock()->ForEachPhiInst(
      [this, &phi_used](Instruction* phi_instruction) {
        phi_used |= IsUsedInLoop(phi_instruction, loop_1_);
      });

  if (phi_used) {
    return false;
  }

  // Grab loads & stores from both loops.
  auto loads_stores_0 = GetLoadsAndStoresInLoop(loop_0_);
  auto loads_stores_1 = GetLoadsAndStoresInLoop(loop_1_);

  // Build memory location to operation maps.
  auto load_locs_0 = LocationToMemOps(std::get<0>(loads_stores_0));
  auto store_locs_0 = LocationToMemOps(std::get<1>(loads_stores_0));

  auto load_locs_1 = LocationToMemOps(std::get<0>(loads_stores_1));
  auto store_locs_1 = LocationToMemOps(std::get<1>(loads_stores_1));

  // Get the locations accessed in both loops.
  auto locations_0 = GetLocationsAccessed(store_locs_0, load_locs_0);
  auto locations_1 = GetLocationsAccessed(store_locs_1, load_locs_1);

  std::vector<Instruction*> potential_clashes{};

  std::set_intersection(std::begin(locations_0), std::end(locations_0),
                        std::begin(locations_1), std::end(locations_1),
                        std::back_inserter(potential_clashes));

  // If the loops don't access the same variables, the fusion is legal.
  if (potential_clashes.empty()) {
    return true;
  }

  // Find variables that have at least one store.
  std::vector<Instruction*> potential_clashes_with_stores{};
  for (auto location : potential_clashes) {
    if (store_locs_0.find(location) != std::end(store_locs_0) ||
        store_locs_1.find(location) != std::end(store_locs_1)) {
      potential_clashes_with_stores.push_back(location);
    }
  }

  // If there are only loads to the same variables, the fusion is legal.
  if (potential_clashes_with_stores.empty()) {
    return true;
  }

  // Else if loads and at least one store (across loops) to the same variable
  // there is a potential dependence and we need to check the dependence
  // distance.

  // Find all the loops in this loop nest for the dependency analysis.
  std::vector<const Loop*> loops{};

  // Find the parents.
  for (auto current_loop = loop_0_; current_loop != nullptr;
       current_loop = current_loop->GetParent()) {
    loops.push_back(current_loop);
  }

  auto this_loop_position = loops.size() - 1;
  std::reverse(std::begin(loops), std::end(loops));

  // Find the children.
  CollectChildren(loop_0_, &loops);
  CollectChildren(loop_1_, &loops);

  // Check that any dependes created are legal. That means the fused loops do
  // not have any dependencies with dependence distance greater than 0 that did
  // not exist in the original loops.

  LoopDependenceAnalysis analysis(context_, loops);

  analysis.GetScalarEvolution()->AddLoopsToPretendAreTheSame(
      {loop_0_, loop_1_});

  for (auto location : potential_clashes_with_stores) {
    // Analyse dependences from |loop_0_| to |loop_1_|.
    std::vector<DistanceVector> dependences;
    // Read-After-Write.
    GetDependences(&dependences, &analysis, store_locs_0[location],
                   load_locs_1[location], loops.size());
    // Write-After-Read.
    GetDependences(&dependences, &analysis, load_locs_0[location],
                   store_locs_1[location], loops.size());
    // Write-After-Write.
    GetDependences(&dependences, &analysis, store_locs_0[location],
                   store_locs_1[location], loops.size());

    // Check that the induction variables either don't appear in the subscripts
    // or the dependence distance is negative.
    for (const auto& dependence : dependences) {
      const auto& entry = dependence.GetEntries()[this_loop_position];
      if ((entry.dependence_information ==
               DistanceEntry::DependenceInformation::DISTANCE &&
           entry.distance < 1) ||
          (entry.dependence_information ==
           DistanceEntry::DependenceInformation::IRRELEVANT)) {
        continue;
      } else {
        return false;
      }
    }
  }

  return true;
}

void ReplacePhiParentWith(Instruction* inst, uint32_t orig_block,
                          uint32_t new_block) {
  if (inst->GetSingleWordInOperand(1) == orig_block) {
    inst->SetInOperand(1, {new_block});
  } else {
    inst->SetInOperand(3, {new_block});
  }
}

void LoopFusion::Fuse() {
  assert(AreCompatible() && "Can't fuse, loops aren't compatible");
  assert(IsLegal() && "Can't fuse, illegal");

  // Save the pointers/ids, won't be found in the middle of doing modifications.
  auto header_1 = loop_1_->GetHeaderBlock()->id();
  auto condition_1 = loop_1_->FindConditionBlock()->id();
  auto continue_1 = loop_1_->GetContinueBlock()->id();
  auto continue_0 = loop_0_->GetContinueBlock()->id();
  auto condition_block_of_0 = loop_0_->FindConditionBlock();

  // Find the blocks whose branches need updating.
  auto first_block_of_1 = &*(++containing_function_->FindBlock(condition_1));
  auto last_block_of_1 = &*(--containing_function_->FindBlock(continue_1));
  auto last_block_of_0 = &*(--containing_function_->FindBlock(continue_0));

  // Update the branch for |last_block_of_loop_0| to go to |first_block_of_1|.
  last_block_of_0->ForEachSuccessorLabel(
      [first_block_of_1](uint32_t* succ) { *succ = first_block_of_1->id(); });

  // Update the branch for the |last_block_of_loop_1| to go to the continue
  // block of |loop_0_|.
  last_block_of_1->ForEachSuccessorLabel(
      [this](uint32_t* succ) { *succ = loop_0_->GetContinueBlock()->id(); });

  // Update merge block id in the header of |loop_0_| to the merge block of
  // |loop_1_|.
  loop_0_->GetHeaderBlock()->ForEachInst([this](Instruction* inst) {
    if (inst->opcode() == SpvOpLoopMerge) {
      inst->SetInOperand(0, {loop_1_->GetMergeBlock()->id()});
    }
  });

  // Update condition branch target in |loop_0_| to the merge block of
  // |loop_1_|.
  condition_block_of_0->ForEachInst([this](Instruction* inst) {
    if (inst->opcode() == SpvOpBranchConditional) {
      auto loop_0_merge_block_id = loop_0_->GetMergeBlock()->id();

      if (inst->GetSingleWordInOperand(1) == loop_0_merge_block_id) {
        inst->SetInOperand(1, {loop_1_->GetMergeBlock()->id()});
      } else {
        inst->SetInOperand(2, {loop_1_->GetMergeBlock()->id()});
      }
    }
  });

  // Move OpPhi instructions not corresponding to the induction variable from
  // the header of |loop_1_| to the header of |loop_0_|.
  std::vector<Instruction*> instructions_to_move{};
  for (auto& instruction : *loop_1_->GetHeaderBlock()) {
    if (instruction.opcode() == SpvOpPhi && &instruction != induction_1_) {
      instructions_to_move.push_back(&instruction);
    }
  }

  for (auto& it : instructions_to_move) {
    it->RemoveFromList();
    it->InsertBefore(induction_0_);
  }

  // Update the OpPhi parents to the correct blocks in |loop_0_|.
  loop_0_->GetHeaderBlock()->ForEachPhiInst([this](Instruction* i) {
    ReplacePhiParentWith(i, loop_1_->GetPreHeaderBlock()->id(),
                         loop_0_->GetPreHeaderBlock()->id());

    ReplacePhiParentWith(i, loop_1_->GetContinueBlock()->id(),
                         loop_0_->GetContinueBlock()->id());
  });

  // Update instruction to block mapping & DefUseManager.
  for (auto& phi_instruction : instructions_to_move) {
    context_->set_instr_block(phi_instruction, loop_0_->GetHeaderBlock());
    context_->get_def_use_mgr()->AnalyzeInstUse(phi_instruction);
  }

  // Replace the uses of the induction variable of |loop_1_| with that the
  // induction variable of |loop_0_|.
  context_->ReplaceAllUsesWith(induction_1_->result_id(),
                               induction_0_->result_id());

  // Replace LCSSA OpPhi in merge block of |loop_0_|.
  loop_0_->GetMergeBlock()->ForEachPhiInst([this](Instruction* instruction) {
    context_->ReplaceAllUsesWith(instruction->result_id(),
                                 instruction->GetSingleWordInOperand(0));
  });

  // Update LCSSA OpPhi in merge block of |loop_1_|.
  loop_1_->GetMergeBlock()->ForEachPhiInst(
      [condition_block_of_0](Instruction* instruction) {
        instruction->SetInOperand(1, {condition_block_of_0->id()});
      });

  // Move the continue block of |loop_0_| after the last block of |loop_1_|.
  containing_function_->MoveBasicBlockToAfter(continue_0, last_block_of_1);

  // Gather all instructions to be killed from |loop_1_| (induction variable
  // initialisation, header, condition and continue blocks).
  std::vector<Instruction*> instr_to_delete{};
  AddInstructionsInBlock(&instr_to_delete, loop_1_->GetPreHeaderBlock());
  AddInstructionsInBlock(&instr_to_delete, loop_1_->GetHeaderBlock());
  AddInstructionsInBlock(&instr_to_delete, loop_1_->FindConditionBlock());
  AddInstructionsInBlock(&instr_to_delete, loop_1_->GetContinueBlock());

  // There was an additional empty block between the loops, kill that too.
  if (loop_0_->GetMergeBlock() != loop_1_->GetPreHeaderBlock()) {
    AddInstructionsInBlock(&instr_to_delete, loop_0_->GetMergeBlock());
  }

  // Update the CFG, so it wouldn't need invalidating.
  auto cfg = context_->cfg();

  cfg->ForgetBlock(loop_1_->GetPreHeaderBlock());
  cfg->ForgetBlock(loop_1_->GetHeaderBlock());
  cfg->ForgetBlock(loop_1_->FindConditionBlock());
  cfg->ForgetBlock(loop_1_->GetContinueBlock());

  if (loop_0_->GetMergeBlock() != loop_1_->GetPreHeaderBlock()) {
    cfg->ForgetBlock(loop_0_->GetMergeBlock());
  }

  cfg->RemoveEdge(last_block_of_0->id(), loop_0_->GetContinueBlock()->id());
  cfg->AddEdge(last_block_of_0->id(), first_block_of_1->id());

  cfg->AddEdge(last_block_of_1->id(), loop_0_->GetContinueBlock()->id());

  cfg->AddEdge(loop_0_->GetContinueBlock()->id(),
               loop_1_->GetHeaderBlock()->id());

  cfg->AddEdge(condition_block_of_0->id(), loop_1_->GetMergeBlock()->id());

  // Update DefUseManager.
  auto def_use_mgr = context_->get_def_use_mgr();

  // Uses of labels that are in updated branches need analysing.
  def_use_mgr->AnalyzeInstUse(last_block_of_0->terminator());
  def_use_mgr->AnalyzeInstUse(last_block_of_1->terminator());
  def_use_mgr->AnalyzeInstUse(loop_0_->GetHeaderBlock()->GetLoopMergeInst());
  def_use_mgr->AnalyzeInstUse(condition_block_of_0->terminator());

  // Update the LoopDescriptor, so it wouldn't need invalidating.
  auto ld = context_->GetLoopDescriptor(containing_function_);

  // Create a copy, so the iterator wouldn't be invalidated.
  std::vector<Loop*> loops_to_add_remove{};
  for (auto child_loop : *loop_1_) {
    loops_to_add_remove.push_back(child_loop);
  }

  for (auto child_loop : loops_to_add_remove) {
    loop_1_->RemoveChildLoop(child_loop);
    loop_0_->AddNestedLoop(child_loop);
  }

  auto loop_1_blocks = loop_1_->GetBlocks();

  for (auto block : loop_1_blocks) {
    loop_1_->RemoveBasicBlock(block);
    if (block != header_1 && block != condition_1 && block != continue_1) {
      loop_0_->AddBasicBlock(block);
      if ((*ld)[block] == loop_1_) {
        ld->SetBasicBlockToLoop(block, loop_0_);
      }
    }

    if ((*ld)[block] == loop_1_) {
      ld->ForgetBasicBlock(block);
    }
  }

  loop_1_->RemoveBasicBlock(loop_1_->GetPreHeaderBlock()->id());
  ld->ForgetBasicBlock(loop_1_->GetPreHeaderBlock()->id());

  if (loop_0_->GetMergeBlock() != loop_1_->GetPreHeaderBlock()) {
    loop_0_->RemoveBasicBlock(loop_0_->GetMergeBlock()->id());
    ld->ForgetBasicBlock(loop_0_->GetMergeBlock()->id());
  }

  loop_0_->SetMergeBlock(loop_1_->GetMergeBlock());

  loop_1_->ClearBlocks();

  ld->RemoveLoop(loop_1_);

  // Kill unnessecary instructions and remove all empty blocks.
  for (auto inst : instr_to_delete) {
    context_->KillInst(inst);
  }

  containing_function_->RemoveEmptyBlocks();

  // Invalidate analyses.
  context_->InvalidateAnalysesExceptFor(
      IRContext::Analysis::kAnalysisInstrToBlockMapping |
      IRContext::Analysis::kAnalysisLoopAnalysis |
      IRContext::Analysis::kAnalysisDefUse | IRContext::Analysis::kAnalysisCFG);
}

}  // namespace opt
}  // namespace spvtools
