/*
 * Copyright (C) 2014 The Android Open Source Project
 *
 * 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 "dead_code_elimination.h"

#include "android-base/logging.h"
#include "base/array_ref.h"
#include "base/bit_vector-inl.h"
#include "base/logging.h"
#include "base/scoped_arena_allocator.h"
#include "base/scoped_arena_containers.h"
#include "base/stl_util.h"
#include "optimizing/nodes.h"
#include "optimizing/nodes_vector.h"
#include "ssa_phi_elimination.h"

namespace art HIDDEN {

static void MarkReachableBlocks(HGraph* graph, ArenaBitVector* visited) {
  // Use local allocator for allocating memory.
  ScopedArenaAllocator allocator(graph->GetArenaStack());

  ScopedArenaVector<HBasicBlock*> worklist(allocator.Adapter(kArenaAllocDCE));
  constexpr size_t kDefaultWorlistSize = 8;
  worklist.reserve(kDefaultWorlistSize);
  visited->SetBit(graph->GetEntryBlock()->GetBlockId());
  worklist.push_back(graph->GetEntryBlock());

  while (!worklist.empty()) {
    HBasicBlock* block = worklist.back();
    worklist.pop_back();
    int block_id = block->GetBlockId();
    DCHECK(visited->IsBitSet(block_id));

    ArrayRef<HBasicBlock* const> live_successors(block->GetSuccessors());
    HInstruction* last_instruction = block->GetLastInstruction();
    if (last_instruction->IsIf()) {
      HIf* if_instruction = last_instruction->AsIf();
      HInstruction* condition = if_instruction->InputAt(0);
      if (condition->IsIntConstant()) {
        if (condition->AsIntConstant()->IsTrue()) {
          live_successors = live_successors.SubArray(0u, 1u);
          DCHECK_EQ(live_successors[0], if_instruction->IfTrueSuccessor());
        } else {
          DCHECK(condition->AsIntConstant()->IsFalse()) << condition->AsIntConstant()->GetValue();
          live_successors = live_successors.SubArray(1u, 1u);
          DCHECK_EQ(live_successors[0], if_instruction->IfFalseSuccessor());
        }
      }
    } else if (last_instruction->IsPackedSwitch()) {
      HPackedSwitch* switch_instruction = last_instruction->AsPackedSwitch();
      HInstruction* switch_input = switch_instruction->InputAt(0);
      if (switch_input->IsIntConstant()) {
        int32_t switch_value = switch_input->AsIntConstant()->GetValue();
        int32_t start_value = switch_instruction->GetStartValue();
        // Note: Though the spec forbids packed-switch values to wrap around, we leave
        // that task to the verifier and use unsigned arithmetic with it's "modulo 2^32"
        // semantics to check if the value is in range, wrapped or not.
        uint32_t switch_index =
            static_cast<uint32_t>(switch_value) - static_cast<uint32_t>(start_value);
        if (switch_index < switch_instruction->GetNumEntries()) {
          live_successors = live_successors.SubArray(switch_index, 1u);
          DCHECK_EQ(live_successors[0], block->GetSuccessors()[switch_index]);
        } else {
          live_successors = live_successors.SubArray(switch_instruction->GetNumEntries(), 1u);
          DCHECK_EQ(live_successors[0], switch_instruction->GetDefaultBlock());
        }
      }
    }

    for (HBasicBlock* successor : live_successors) {
      // Add only those successors that have not been visited yet.
      if (!visited->IsBitSet(successor->GetBlockId())) {
        visited->SetBit(successor->GetBlockId());
        worklist.push_back(successor);
      }
    }
  }
}

void HDeadCodeElimination::MaybeRecordDeadBlock(HBasicBlock* block) {
  if (stats_ != nullptr) {
    stats_->RecordStat(MethodCompilationStat::kRemovedDeadInstruction,
                       block->GetPhis().CountSize() + block->GetInstructions().CountSize());
  }
}

void HDeadCodeElimination::MaybeRecordSimplifyIf() {
  if (stats_ != nullptr) {
    stats_->RecordStat(MethodCompilationStat::kSimplifyIf);
  }
}

static bool HasInput(HCondition* instruction, HInstruction* input) {
  return (instruction->InputAt(0) == input) ||
         (instruction->InputAt(1) == input);
}

static bool HasEquality(IfCondition condition) {
  switch (condition) {
    case kCondEQ:
    case kCondLE:
    case kCondGE:
    case kCondBE:
    case kCondAE:
      return true;
    case kCondNE:
    case kCondLT:
    case kCondGT:
    case kCondB:
    case kCondA:
      return false;
  }
}

static HConstant* Evaluate(HCondition* condition, HInstruction* left, HInstruction* right) {
  if (left == right && !DataType::IsFloatingPointType(left->GetType())) {
    return condition->GetBlock()->GetGraph()->GetIntConstant(
        HasEquality(condition->GetCondition()) ? 1 : 0);
  }

  if (!left->IsConstant() || !right->IsConstant()) {
    return nullptr;
  }

  if (left->IsIntConstant()) {
    return condition->Evaluate(left->AsIntConstant(), right->AsIntConstant());
  } else if (left->IsNullConstant()) {
    return condition->Evaluate(left->AsNullConstant(), right->AsNullConstant());
  } else if (left->IsLongConstant()) {
    return condition->Evaluate(left->AsLongConstant(), right->AsLongConstant());
  } else if (left->IsFloatConstant()) {
    return condition->Evaluate(left->AsFloatConstant(), right->AsFloatConstant());
  } else {
    DCHECK(left->IsDoubleConstant());
    return condition->Evaluate(left->AsDoubleConstant(), right->AsDoubleConstant());
  }
}

static bool RemoveNonNullControlDependences(HBasicBlock* block, HBasicBlock* throws) {
  // Test for an if as last statement.
  if (!block->EndsWithIf()) {
    return false;
  }
  HIf* ifs = block->GetLastInstruction()->AsIf();
  // Find either:
  //   if obj == null
  //     throws
  //   else
  //     not_throws
  // or:
  //   if obj != null
  //     not_throws
  //   else
  //     throws
  HInstruction* cond = ifs->InputAt(0);
  HBasicBlock* not_throws = nullptr;
  if (throws == ifs->IfTrueSuccessor() && cond->IsEqual()) {
    not_throws = ifs->IfFalseSuccessor();
  } else if (throws == ifs->IfFalseSuccessor() && cond->IsNotEqual()) {
    not_throws = ifs->IfTrueSuccessor();
  } else {
    return false;
  }
  DCHECK(cond->IsEqual() || cond->IsNotEqual());
  HInstruction* obj = cond->InputAt(1);
  if (obj->IsNullConstant()) {
    obj = cond->InputAt(0);
  } else if (!cond->InputAt(0)->IsNullConstant()) {
    return false;
  }

  // We can't create a BoundType for an object with an invalid RTI.
  const ReferenceTypeInfo ti = obj->GetReferenceTypeInfo();
  if (!ti.IsValid()) {
    return false;
  }

  // Scan all uses of obj and find null check under control dependence.
  HBoundType* bound = nullptr;
  const HUseList<HInstruction*>& uses = obj->GetUses();
  for (auto it = uses.begin(), end = uses.end(); it != end;) {
    HInstruction* user = it->GetUser();
    ++it;  // increment before possibly replacing
    if (user->IsNullCheck()) {
      HBasicBlock* user_block = user->GetBlock();
      if (user_block != block &&
          user_block != throws &&
          block->Dominates(user_block)) {
        if (bound == nullptr) {
          bound = new (obj->GetBlock()->GetGraph()->GetAllocator()) HBoundType(obj);
          bound->SetUpperBound(ti, /*can_be_null*/ false);
          bound->SetReferenceTypeInfo(ti);
          bound->SetCanBeNull(false);
          not_throws->InsertInstructionBefore(bound, not_throws->GetFirstInstruction());
        }
        user->ReplaceWith(bound);
        user_block->RemoveInstruction(user);
      }
    }
  }
  return bound != nullptr;
}

// Simplify the pattern:
//
//           B1
//          /  \
//          |   instr_1
//          |   ...
//          |   instr_n
//          |   foo()  // always throws
//          |   instr_n+2
//          |   ...
//          |   instr_n+m
//          \   goto B2
//           \ /
//            B2
//
// Into:
//
//           B1
//          /  \
//          |  instr_1
//          |  ...
//          |  instr_n
//          |  foo()
//          |  goto Exit
//          |   |
//         B2  Exit
//
// Rationale:
// Removal of the never taken edge to B2 may expose other optimization opportunities, such as code
// sinking.
//
// Note: The example above is a simple one that uses a `goto` but we could end the block with an If,
// for example.
bool HDeadCodeElimination::SimplifyAlwaysThrows() {
  HBasicBlock* exit = graph_->GetExitBlock();
  if (!graph_->HasAlwaysThrowingInvokes() || exit == nullptr) {
    return false;
  }

  bool rerun_dominance_and_loop_analysis = false;

  // Order does not matter, just pick one.
  for (HBasicBlock* block : graph_->GetReversePostOrder()) {
    if (block->IsTryBlock()) {
      // We don't want to perform the simplify always throws optimizations for throws inside of
      // tries since those throws might not go to the exit block.
      continue;
    }

    // We iterate to find the first instruction that always throws. If two instructions always
    // throw, the first one will throw and the second one will never be reached.
    HInstruction* throwing_invoke = nullptr;
    for (HInstructionIterator it(block->GetInstructions()); !it.Done(); it.Advance()) {
      if (it.Current()->IsInvoke() && it.Current()->AsInvoke()->AlwaysThrows()) {
        throwing_invoke = it.Current();
        break;
      }
    }

    if (throwing_invoke == nullptr) {
      // No always-throwing instruction found. Continue with the rest of the blocks.
      continue;
    }

    // If we are already pointing at the exit block we could still remove the instructions
    // between the always throwing instruction, and the exit block. If we have no other
    // instructions, just continue since there's nothing to do.
    if (block->GetSuccessors().size() == 1 &&
        block->GetSingleSuccessor() == exit &&
        block->GetLastInstruction()->GetPrevious() == throwing_invoke) {
      continue;
    }

    // We split the block at the throwing instruction, and the instructions after the throwing
    // instructions will be disconnected from the graph after `block` points to the exit.
    // `RemoveDeadBlocks` will take care of removing this new block and its instructions.
    // Even though `SplitBefore` doesn't guarantee the graph to remain in SSA form, it is fine
    // since we do not break it.
    HBasicBlock* new_block = block->SplitBefore(throwing_invoke->GetNext(),
                                                /* require_graph_not_in_ssa_form= */ false);
    DCHECK_EQ(block->GetSingleSuccessor(), new_block);
    block->ReplaceSuccessor(new_block, exit);

    rerun_dominance_and_loop_analysis = true;
    MaybeRecordStat(stats_, MethodCompilationStat::kSimplifyThrowingInvoke);
    // Perform a quick follow up optimization on object != null control dependences
    // that is much cheaper to perform now than in a later phase.
    // If there are multiple predecessors, none may end with a HIf as required in
    // RemoveNonNullControlDependences because we split critical edges.
    if (block->GetPredecessors().size() == 1u &&
        RemoveNonNullControlDependences(block->GetSinglePredecessor(), block)) {
      MaybeRecordStat(stats_, MethodCompilationStat::kRemovedNullCheck);
    }
  }

  // We need to re-analyze the graph in order to run DCE afterwards.
  if (rerun_dominance_and_loop_analysis) {
    graph_->ClearLoopInformation();
    graph_->ClearDominanceInformation();
    graph_->BuildDominatorTree();
    return true;
  }
  return false;
}

bool HDeadCodeElimination::SimplifyIfs() {
  bool simplified_one_or_more_ifs = false;
  bool rerun_dominance_and_loop_analysis = false;

  // Iterating in PostOrder it's better for MaybeAddPhi as it can add a Phi for multiple If
  // instructions in a chain without updating the dominator chain. The branch redirection itself can
  // work in PostOrder or ReversePostOrder without issues.
  for (HBasicBlock* block : graph_->GetPostOrder()) {
    if (block->IsCatchBlock()) {
      // This simplification cannot be applied to catch blocks, because exception handler edges do
      // not represent normal control flow. Though in theory this could still apply to normal
      // control flow going directly to a catch block, we cannot support it at the moment because
      // the catch Phi's inputs do not correspond to the catch block's predecessors, so we cannot
      // identify which predecessor corresponds to a given statically evaluated input.
      continue;
    }

    HInstruction* last = block->GetLastInstruction();
    if (!last->IsIf()) {
      continue;
    }

    if (block->IsLoopHeader()) {
      // We do not apply this optimization to loop headers as this could create irreducible loops.
      continue;
    }

    // We will add a Phi which allows the simplification to take place in cases where it wouldn't.
    MaybeAddPhi(block);

    // TODO(solanes): Investigate support for multiple phis in `block`. We can potentially "push
    // downwards" existing Phis into the true/false branches. For example, let's say we have another
    // Phi: Phi(x1,x2,x3,x4,x5,x6). This could turn into Phi(x1,x2) in the true branch, Phi(x3,x4)
    // in the false branch, and remain as Phi(x5,x6) in `block` (for edges that we couldn't
    // redirect). We might even be able to remove some phis altogether as they will have only one
    // value.
    if (block->HasSinglePhi() &&
        block->GetFirstPhi()->HasOnlyOneNonEnvironmentUse()) {
      HInstruction* first = block->GetFirstInstruction();
      bool has_only_phi_and_if = (last == first) && (last->InputAt(0) == block->GetFirstPhi());
      bool has_only_phi_condition_and_if =
          !has_only_phi_and_if &&
          first->IsCondition() &&
          HasInput(first->AsCondition(), block->GetFirstPhi()) &&
          (first->GetNext() == last) &&
          (last->InputAt(0) == first) &&
          first->HasOnlyOneNonEnvironmentUse();

      if (has_only_phi_and_if || has_only_phi_condition_and_if) {
        HPhi* phi = block->GetFirstPhi()->AsPhi();
        bool phi_input_is_left = (first->InputAt(0) == phi);

        // Walk over all inputs of the phis and update the control flow of
        // predecessors feeding constants to the phi.
        // Note that phi->InputCount() may change inside the loop.
        for (size_t i = 0; i < phi->InputCount();) {
          HInstruction* input = phi->InputAt(i);
          HInstruction* value_to_check = nullptr;
          if (has_only_phi_and_if) {
            if (input->IsIntConstant()) {
              value_to_check = input;
            }
          } else {
            DCHECK(has_only_phi_condition_and_if);
            if (phi_input_is_left) {
              value_to_check = Evaluate(first->AsCondition(), input, first->InputAt(1));
            } else {
              value_to_check = Evaluate(first->AsCondition(), first->InputAt(0), input);
            }
          }
          if (value_to_check == nullptr) {
            // Could not evaluate to a constant, continue iterating over the inputs.
            ++i;
          } else {
            HBasicBlock* predecessor_to_update = block->GetPredecessors()[i];
            HBasicBlock* successor_to_update = nullptr;
            if (value_to_check->AsIntConstant()->IsTrue()) {
              successor_to_update = last->AsIf()->IfTrueSuccessor();
            } else {
              DCHECK(value_to_check->AsIntConstant()->IsFalse())
                  << value_to_check->AsIntConstant()->GetValue();
              successor_to_update = last->AsIf()->IfFalseSuccessor();
            }
            predecessor_to_update->ReplaceSuccessor(block, successor_to_update);
            phi->RemoveInputAt(i);
            simplified_one_or_more_ifs = true;
            if (block->IsInLoop()) {
              rerun_dominance_and_loop_analysis = true;
            }
            // For simplicity, don't create a dead block, let the dead code elimination
            // pass deal with it.
            if (phi->InputCount() == 1) {
              break;
            }
          }
        }
        if (block->GetPredecessors().size() == 1) {
          phi->ReplaceWith(phi->InputAt(0));
          block->RemovePhi(phi);
          if (has_only_phi_condition_and_if) {
            // Evaluate here (and not wait for a constant folding pass) to open
            // more opportunities for DCE.
            HInstruction* result = first->AsCondition()->TryStaticEvaluation();
            if (result != nullptr) {
              first->ReplaceWith(result);
              block->RemoveInstruction(first);
            }
          }
        }
        if (simplified_one_or_more_ifs) {
          MaybeRecordSimplifyIf();
        }
      }
    }
  }
  // We need to re-analyze the graph in order to run DCE afterwards.
  if (simplified_one_or_more_ifs) {
    if (rerun_dominance_and_loop_analysis) {
      graph_->ClearLoopInformation();
      graph_->ClearDominanceInformation();
      graph_->BuildDominatorTree();
    } else {
      graph_->ClearDominanceInformation();
      // We have introduced critical edges, remove them.
      graph_->SimplifyCFG();
      graph_->ComputeDominanceInformation();
      graph_->ComputeTryBlockInformation();
    }
  }

  return simplified_one_or_more_ifs;
}

void HDeadCodeElimination::MaybeAddPhi(HBasicBlock* block) {
  DCHECK(block->GetLastInstruction()->IsIf());
  HIf* if_instruction = block->GetLastInstruction()->AsIf();
  if (if_instruction->InputAt(0)->IsConstant()) {
    // Constant values are handled in RemoveDeadBlocks.
    return;
  }

  if (block->GetNumberOfPredecessors() < 2u) {
    // Nothing to redirect.
    return;
  }

  if (!block->GetPhis().IsEmpty()) {
    // SimplifyIf doesn't currently work with multiple phis. Adding a phi here won't help that
    // optimization.
    return;
  }

  HBasicBlock* dominator = block->GetDominator();
  if (!dominator->EndsWithIf()) {
    return;
  }

  HInstruction* input = if_instruction->InputAt(0);
  HInstruction* dominator_input = dominator->GetLastInstruction()->AsIf()->InputAt(0);
  const bool same_input = dominator_input == input;
  if (!same_input) {
    // Try to see if the dominator has the opposite input (e.g. if(cond) and if(!cond)). If that's
    // the case, we can perform the optimization with the false and true branches reversed.
    if (!dominator_input->IsCondition() || !input->IsCondition()) {
      return;
    }

    HCondition* block_cond = input->AsCondition();
    HCondition* dominator_cond = dominator_input->AsCondition();

    if (block_cond->GetLeft() != dominator_cond->GetLeft() ||
        block_cond->GetRight() != dominator_cond->GetRight() ||
        block_cond->GetOppositeCondition() != dominator_cond->GetCondition()) {
      return;
    }
  }

  if (kIsDebugBuild) {
    // `block`'s successors should have only one predecessor. Otherwise, we have a critical edge in
    // the graph.
    for (HBasicBlock* succ : block->GetSuccessors()) {
      DCHECK_EQ(succ->GetNumberOfPredecessors(), 1u);
    }
  }

  const size_t pred_size = block->GetNumberOfPredecessors();
  HPhi* new_phi = new (graph_->GetAllocator())
      HPhi(graph_->GetAllocator(), kNoRegNumber, pred_size, DataType::Type::kInt32);

  for (size_t index = 0; index < pred_size; index++) {
    HBasicBlock* pred = block->GetPredecessors()[index];
    const bool dominated_by_true =
        dominator->GetLastInstruction()->AsIf()->IfTrueSuccessor()->Dominates(pred);
    const bool dominated_by_false =
        dominator->GetLastInstruction()->AsIf()->IfFalseSuccessor()->Dominates(pred);
    if (dominated_by_true == dominated_by_false) {
      // In this case, we can't know if we are coming from the true branch, or the false branch. It
      // happens in cases like:
      //      1 (outer if)
      //     / \
      //    2   3 (inner if)
      //    |  / \
      //    | 4  5
      //     \/  |
      //      6  |
      //       \ |
      //         7 (has the same if(cond) as 1)
      //         |
      //         8
      // `7` (which would be `block` in this example), and `6` will come from both the true path and
      // the false path of `1`. We bumped into something similar in SelectGenerator. See
      // HSelectGenerator::TryFixupDoubleDiamondPattern.
      // TODO(solanes): Figure out if we can fix up the graph into a double diamond in a generic way
      // so that DeadCodeElimination and SelectGenerator can take advantage of it.

      if (!same_input) {
        // `1` and `7` having the opposite condition is a case we are missing. We could potentially
        // add a BooleanNot instruction to be able to add the Phi, but it seems like overkill since
        // this case is not that common.
        return;
      }

      // The Phi will have `0`, `1`, and `cond` as inputs. If SimplifyIf redirects 0s and 1s, we
      // will end up with Phi(cond,...,cond) which will be replaced by `cond`. Effectively, we will
      // redirect edges that we are able to redirect and the rest will remain as before (i.e. we
      // won't have an extra Phi).
      new_phi->SetRawInputAt(index, input);
    } else {
      // Redirect to either the true branch (1), or the false branch (0).
      // Given that `dominated_by_true` is the exact opposite of `dominated_by_false`,
      // `(same_input && dominated_by_true) || (!same_input && dominated_by_false)` is equivalent to
      // `same_input == dominated_by_true`.
      new_phi->SetRawInputAt(
          index,
          same_input == dominated_by_true ? graph_->GetIntConstant(1) : graph_->GetIntConstant(0));
    }
  }

  block->AddPhi(new_phi);
  if_instruction->ReplaceInput(new_phi, 0);

  // Remove the old input now, if possible. This allows the branch redirection in SimplifyIf to
  // work without waiting for another pass of DCE.
  if (input->IsDeadAndRemovable()) {
    DCHECK(!same_input)
        << " if both blocks have the same condition, it shouldn't be dead and removable since the "
        << "dominator block's If instruction would be using that condition.";
    input->GetBlock()->RemoveInstruction(input);
  }
  MaybeRecordStat(stats_, MethodCompilationStat::kSimplifyIfAddedPhi);
}

void HDeadCodeElimination::ConnectSuccessiveBlocks() {
  // Order does not matter. Skip the entry block by starting at index 1 in reverse post order.
  for (size_t i = 1u, size = graph_->GetReversePostOrder().size(); i != size; ++i) {
    HBasicBlock* block  = graph_->GetReversePostOrder()[i];
    DCHECK(!block->IsEntryBlock());
    while (block->GetLastInstruction()->IsGoto()) {
      HBasicBlock* successor = block->GetSingleSuccessor();
      if (successor->IsExitBlock() || successor->GetPredecessors().size() != 1u) {
        break;
      }
      DCHECK_LT(i, IndexOfElement(graph_->GetReversePostOrder(), successor));
      block->MergeWith(successor);
      --size;
      DCHECK_EQ(size, graph_->GetReversePostOrder().size());
      DCHECK_EQ(block, graph_->GetReversePostOrder()[i]);
      // Reiterate on this block in case it can be merged with its new successor.
    }
  }
}

struct HDeadCodeElimination::TryBelongingInformation {
  explicit TryBelongingInformation(ScopedArenaAllocator* allocator)
      : blocks_in_try(allocator->Adapter(kArenaAllocDCE)),
        coalesced_try_entries(allocator->Adapter(kArenaAllocDCE)) {}

  // Which blocks belong in the try.
  ScopedArenaSet<HBasicBlock*> blocks_in_try;
  // Which other try entries are referencing this same try.
  ScopedArenaSet<HBasicBlock*> coalesced_try_entries;
};

bool HDeadCodeElimination::CanPerformTryRemoval(const TryBelongingInformation& try_belonging_info) {
  for (HBasicBlock* block : try_belonging_info.blocks_in_try) {
    for (HInstructionIterator it(block->GetInstructions()); !it.Done(); it.Advance()) {
      if (it.Current()->CanThrow()) {
        return false;
      }
    }
  }
  return true;
}

void HDeadCodeElimination::DisconnectHandlersAndUpdateTryBoundary(
    HBasicBlock* block,
    /* out */ bool* any_block_in_loop) {
  if (block->IsInLoop()) {
    *any_block_in_loop = true;
  }

  // Disconnect the handlers.
  while (block->GetSuccessors().size() > 1) {
    HBasicBlock* handler = block->GetSuccessors()[1];
    DCHECK(handler->IsCatchBlock());
    block->RemoveSuccessor(handler);
    handler->RemovePredecessor(block);
    if (handler->IsInLoop()) {
      *any_block_in_loop = true;
    }
  }

  // Change TryBoundary to Goto.
  DCHECK(block->EndsWithTryBoundary());
  HInstruction* last = block->GetLastInstruction();
  block->RemoveInstruction(last);
  block->AddInstruction(new (graph_->GetAllocator()) HGoto(last->GetDexPc()));
  DCHECK_EQ(block->GetSuccessors().size(), 1u);
}

void HDeadCodeElimination::RemoveTry(HBasicBlock* try_entry,
                                     const TryBelongingInformation& try_belonging_info,
                                     /* out */ bool* any_block_in_loop) {
  // Update all try entries.
  DCHECK(try_entry->EndsWithTryBoundary());
  DCHECK(try_entry->GetLastInstruction()->AsTryBoundary()->IsEntry());
  DisconnectHandlersAndUpdateTryBoundary(try_entry, any_block_in_loop);

  for (HBasicBlock* other_try_entry : try_belonging_info.coalesced_try_entries) {
    DCHECK(other_try_entry->EndsWithTryBoundary());
    DCHECK(other_try_entry->GetLastInstruction()->AsTryBoundary()->IsEntry());
    DisconnectHandlersAndUpdateTryBoundary(other_try_entry, any_block_in_loop);
  }

  // Update the blocks in the try.
  for (HBasicBlock* block : try_belonging_info.blocks_in_try) {
    // Update the try catch information since now the try doesn't exist.
    block->SetTryCatchInformation(nullptr);
    if (block->IsInLoop()) {
      *any_block_in_loop = true;
    }

    if (block->EndsWithTryBoundary()) {
      // Try exits.
      DCHECK(!block->GetLastInstruction()->AsTryBoundary()->IsEntry());
      DisconnectHandlersAndUpdateTryBoundary(block, any_block_in_loop);

      if (block->GetSingleSuccessor()->IsExitBlock()) {
        // `block` used to be a single exit TryBoundary that got turned into a Goto. It
        // is now pointing to the exit which we don't allow. To fix it, we disconnect
        // `block` from its predecessor and RemoveDeadBlocks will remove it from the
        // graph.
        DCHECK(block->IsSingleGoto());
        HBasicBlock* predecessor = block->GetSinglePredecessor();
        predecessor->ReplaceSuccessor(block, graph_->GetExitBlock());

        if (!block->GetDominatedBlocks().empty()) {
          // Update domination tree if `block` dominates a block to keep the graph consistent.
          DCHECK_EQ(block->GetDominatedBlocks().size(), 1u);
          DCHECK_EQ(graph_->GetExitBlock()->GetDominator(), block);
          predecessor->AddDominatedBlock(graph_->GetExitBlock());
          graph_->GetExitBlock()->SetDominator(predecessor);
          block->RemoveDominatedBlock(graph_->GetExitBlock());
        }
      }
    }
  }
}

bool HDeadCodeElimination::RemoveUnneededTries() {
  if (!graph_->HasTryCatch()) {
    return false;
  }

  // Use local allocator for allocating memory.
  ScopedArenaAllocator allocator(graph_->GetArenaStack());

  // Collect which blocks are part of which try.
  std::unordered_map<HBasicBlock*, TryBelongingInformation> tries;
  for (HBasicBlock* block : graph_->GetReversePostOrderSkipEntryBlock()) {
    if (block->IsTryBlock()) {
      HBasicBlock* key = block->GetTryCatchInformation()->GetTryEntry().GetBlock();
      auto it = tries.find(key);
      if (it == tries.end()) {
        it = tries.insert({key, TryBelongingInformation(&allocator)}).first;
      }
      it->second.blocks_in_try.insert(block);
    }
  }

  // Deduplicate the tries which have different try entries but they are really the same try.
  for (auto it = tries.begin(); it != tries.end(); it++) {
    DCHECK(it->first->EndsWithTryBoundary());
    HTryBoundary* try_boundary = it->first->GetLastInstruction()->AsTryBoundary();
    for (auto other_it = next(it); other_it != tries.end(); /*other_it++ in the loop*/) {
      DCHECK(other_it->first->EndsWithTryBoundary());
      HTryBoundary* other_try_boundary = other_it->first->GetLastInstruction()->AsTryBoundary();
      if (try_boundary->HasSameExceptionHandlersAs(*other_try_boundary)) {
        // Merge the entries as they are really the same one.
        // Block merging.
        it->second.blocks_in_try.insert(other_it->second.blocks_in_try.begin(),
                                        other_it->second.blocks_in_try.end());

        // Add the coalesced try entry to update it too.
        it->second.coalesced_try_entries.insert(other_it->first);

        // Erase the other entry.
        other_it = tries.erase(other_it);
      } else {
        other_it++;
      }
    }
  }

  size_t removed_tries = 0;
  bool any_block_in_loop = false;

  // Check which tries contain throwing instructions.
  for (const auto& entry : tries) {
    if (CanPerformTryRemoval(entry.second)) {
      ++removed_tries;
      RemoveTry(entry.first, entry.second, &any_block_in_loop);
    }
  }

  if (removed_tries != 0) {
    // We want to:
    //   1) Update the dominance information
    //   2) Remove catch block subtrees, if they are now unreachable.
    // If we run the dominance recomputation without removing the code, those catch blocks will
    // not be part of the post order and won't be removed. If we don't run the dominance
    // recomputation, we risk RemoveDeadBlocks not running it and leaving the graph in an
    // inconsistent state. So, what we can do is run RemoveDeadBlocks and force a recomputation.
    // Note that we are not guaranteed to remove a catch block if we have nested try blocks:
    //
    //   try {
    //     ... nothing can throw. TryBoundary A ...
    //     try {
    //       ... can throw. TryBoundary B...
    //     } catch (Error e) {}
    //   } catch (Exception e) {}
    //
    // In the example above, we can remove the TryBoundary A but the Exception catch cannot be
    // removed as the TryBoundary B might still throw into that catch. TryBoundary A and B don't get
    // coalesced since they have different catch handlers.

    RemoveDeadBlocks(/* force_recomputation= */ true, any_block_in_loop);
    MaybeRecordStat(stats_, MethodCompilationStat::kRemovedTry, removed_tries);
    return true;
  } else {
    return false;
  }
}

bool HDeadCodeElimination::RemoveDeadBlocks(bool force_recomputation,
                                            bool force_loop_recomputation) {
  DCHECK_IMPLIES(force_loop_recomputation, force_recomputation);

  // Use local allocator for allocating memory.
  ScopedArenaAllocator allocator(graph_->GetArenaStack());

  // Classify blocks as reachable/unreachable.
  ArenaBitVector live_blocks(&allocator, graph_->GetBlocks().size(), false, kArenaAllocDCE);
  live_blocks.ClearAllBits();

  MarkReachableBlocks(graph_, &live_blocks);
  bool removed_one_or_more_blocks = false;
  bool rerun_dominance_and_loop_analysis = false;

  // Remove all dead blocks. Iterate in post order because removal needs the
  // block's chain of dominators and nested loops need to be updated from the
  // inside out.
  for (HBasicBlock* block : graph_->GetPostOrder()) {
    int id = block->GetBlockId();
    if (!live_blocks.IsBitSet(id)) {
      MaybeRecordDeadBlock(block);
      block->DisconnectAndDelete();
      removed_one_or_more_blocks = true;
      if (block->IsInLoop()) {
        rerun_dominance_and_loop_analysis = true;
      }
    }
  }

  // If we removed at least one block, we need to recompute the full
  // dominator tree and try block membership.
  if (removed_one_or_more_blocks || force_recomputation) {
    if (rerun_dominance_and_loop_analysis || force_loop_recomputation) {
      graph_->ClearLoopInformation();
      graph_->ClearDominanceInformation();
      graph_->BuildDominatorTree();
    } else {
      graph_->ClearDominanceInformation();
      graph_->ComputeDominanceInformation();
      graph_->ComputeTryBlockInformation();
    }
  }
  return removed_one_or_more_blocks;
}

void HDeadCodeElimination::RemoveDeadInstructions() {
  // Process basic blocks in post-order in the dominator tree, so that
  // a dead instruction depending on another dead instruction is removed.
  for (HBasicBlock* block : graph_->GetPostOrder()) {
    // Traverse this block's instructions in backward order and remove
    // the unused ones.
    HBackwardInstructionIterator i(block->GetInstructions());
    // Skip the first iteration, as the last instruction of a block is
    // a branching instruction.
    DCHECK(i.Current()->IsControlFlow());
    for (i.Advance(); !i.Done(); i.Advance()) {
      HInstruction* inst = i.Current();
      DCHECK(!inst->IsControlFlow());
      if (inst->IsDeadAndRemovable()) {
        block->RemoveInstruction(inst);
        MaybeRecordStat(stats_, MethodCompilationStat::kRemovedDeadInstruction);
      }
    }
  }
}

void HDeadCodeElimination::UpdateGraphFlags() {
  bool has_monitor_operations = false;
  bool has_traditional_simd = false;
  bool has_predicated_simd = false;
  bool has_bounds_checks = false;
  bool has_always_throwing_invokes = false;

  for (HBasicBlock* block : graph_->GetReversePostOrder()) {
    for (HInstructionIterator it(block->GetInstructions()); !it.Done(); it.Advance()) {
      HInstruction* instruction = it.Current();
      if (instruction->IsMonitorOperation()) {
        has_monitor_operations = true;
      } else if (instruction->IsVecOperation()) {
        HVecOperation* vec_instruction = instruction->AsVecOperation();
        if (vec_instruction->IsPredicated()) {
          has_predicated_simd = true;
        } else {
          has_traditional_simd = true;
        }
      } else if (instruction->IsBoundsCheck()) {
        has_bounds_checks = true;
      } else if (instruction->IsInvoke() && instruction->AsInvoke()->AlwaysThrows()) {
        has_always_throwing_invokes = true;
      }
    }
  }

  graph_->SetHasMonitorOperations(has_monitor_operations);
  graph_->SetHasTraditionalSIMD(has_traditional_simd);
  graph_->SetHasPredicatedSIMD(has_predicated_simd);
  graph_->SetHasBoundsChecks(has_bounds_checks);
  graph_->SetHasAlwaysThrowingInvokes(has_always_throwing_invokes);
}

bool HDeadCodeElimination::Run() {
  // Do not eliminate dead blocks if the graph has irreducible loops. We could
  // support it, but that would require changes in our loop representation to handle
  // multiple entry points. We decided it was not worth the complexity.
  if (!graph_->HasIrreducibleLoops()) {
    // Simplify graph to generate more dead block patterns.
    ConnectSuccessiveBlocks();
    bool did_any_simplification = false;
    did_any_simplification |= SimplifyAlwaysThrows();
    did_any_simplification |= SimplifyIfs();
    did_any_simplification |= RemoveDeadBlocks();
    // We call RemoveDeadBlocks before RemoveUnneededTries to remove the dead blocks from the
    // previous optimizations. Otherwise, we might detect that a try has throwing instructions but
    // they are actually dead code. RemoveUnneededTryBoundary will call RemoveDeadBlocks again if
    // needed.
    did_any_simplification |= RemoveUnneededTries();
    if (did_any_simplification) {
      // Connect successive blocks created by dead branches.
      ConnectSuccessiveBlocks();
    }
  }
  SsaRedundantPhiElimination(graph_).Run();
  RemoveDeadInstructions();
  UpdateGraphFlags();
  return true;
}

}  // namespace art
