/*
 * 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 "ssa_phi_elimination.h"

#include "base/arena_bit_vector.h"
#include "base/scoped_arena_allocator.h"
#include "base/scoped_arena_containers.h"
#include "base/bit_vector-inl.h"

namespace art {

bool SsaDeadPhiElimination::Run() {
  MarkDeadPhis();
  EliminateDeadPhis();
  return true;
}

void SsaDeadPhiElimination::MarkDeadPhis() {
  // Use local allocator for allocating memory used by this optimization.
  ScopedArenaAllocator allocator(graph_->GetArenaStack());

  static constexpr size_t kDefaultWorklistSize = 8;
  ScopedArenaVector<HPhi*> worklist(allocator.Adapter(kArenaAllocSsaPhiElimination));
  worklist.reserve(kDefaultWorklistSize);

  // Phis are constructed live and should not be revived if previously marked
  // dead. This algorithm temporarily breaks that invariant but we DCHECK that
  // only phis which were initially live are revived.
  ScopedArenaSet<HPhi*> initially_live(allocator.Adapter(kArenaAllocSsaPhiElimination));

  // Add to the worklist phis referenced by non-phi instructions.
  for (HBasicBlock* block : graph_->GetReversePostOrder()) {
    for (HInstructionIterator inst_it(block->GetPhis()); !inst_it.Done(); inst_it.Advance()) {
      HPhi* phi = inst_it.Current()->AsPhi();
      if (phi->IsDead()) {
        continue;
      }

      bool keep_alive = (graph_->IsDebuggable() && phi->HasEnvironmentUses());
      if (!keep_alive) {
        for (const HUseListNode<HInstruction*>& use : phi->GetUses()) {
          if (!use.GetUser()->IsPhi()) {
            keep_alive = true;
            break;
          }
        }
      }

      if (keep_alive) {
        worklist.push_back(phi);
      } else {
        phi->SetDead();
        if (kIsDebugBuild) {
          initially_live.insert(phi);
        }
      }
    }
  }

  // Process the worklist by propagating liveness to phi inputs.
  while (!worklist.empty()) {
    HPhi* phi = worklist.back();
    worklist.pop_back();
    for (HInstruction* raw_input : phi->GetInputs()) {
      HPhi* input = raw_input->AsPhi();
      if (input != nullptr && input->IsDead()) {
        // Input is a dead phi. Revive it and add to the worklist. We make sure
        // that the phi was not dead initially (see definition of `initially_live`).
        DCHECK(ContainsElement(initially_live, input));
        input->SetLive();
        worklist.push_back(input);
      }
    }
  }
}

void SsaDeadPhiElimination::EliminateDeadPhis() {
  // Remove phis that are not live. Visit in post order so that phis
  // that are not inputs of loop phis can be removed when they have
  // no users left (dead phis might use dead phis).
  for (HBasicBlock* block : graph_->GetPostOrder()) {
    HInstruction* current = block->GetFirstPhi();
    HInstruction* next = nullptr;
    HPhi* phi;
    while (current != nullptr) {
      phi = current->AsPhi();
      next = current->GetNext();
      if (phi->IsDead()) {
        // Make sure the phi is only used by other dead phis.
        if (kIsDebugBuild) {
          for (const HUseListNode<HInstruction*>& use : phi->GetUses()) {
            HInstruction* user = use.GetUser();
            DCHECK(user->IsLoopHeaderPhi());
            DCHECK(user->AsPhi()->IsDead());
          }
        }
        // Remove the phi from use lists of its inputs.
        phi->RemoveAsUserOfAllInputs();
        // Remove the phi from environments that use it.
        for (const HUseListNode<HEnvironment*>& use : phi->GetEnvUses()) {
          HEnvironment* user = use.GetUser();
          user->SetRawEnvAt(use.GetIndex(), nullptr);
        }
        // Delete it from the instruction list.
        block->RemovePhi(phi, /*ensure_safety=*/ false);
      }
      current = next;
    }
  }
}

bool SsaRedundantPhiElimination::Run() {
  // Use local allocator for allocating memory used by this optimization.
  ScopedArenaAllocator allocator(graph_->GetArenaStack());

  static constexpr size_t kDefaultWorklistSize = 8;
  ScopedArenaVector<HPhi*> worklist(allocator.Adapter(kArenaAllocSsaPhiElimination));
  worklist.reserve(kDefaultWorklistSize);

  // Add all phis in the worklist. Order does not matter for correctness, and
  // neither will necessarily converge faster.
  for (HBasicBlock* block : graph_->GetReversePostOrder()) {
    for (HInstructionIterator inst_it(block->GetPhis()); !inst_it.Done(); inst_it.Advance()) {
      worklist.push_back(inst_it.Current()->AsPhi());
    }
  }

  ArenaBitVector visited_phis_in_cycle(&allocator,
                                       graph_->GetCurrentInstructionId(),
                                       /* expandable */ false,
                                       kArenaAllocSsaPhiElimination);
  visited_phis_in_cycle.ClearAllBits();
  ScopedArenaVector<HPhi*> cycle_worklist(allocator.Adapter(kArenaAllocSsaPhiElimination));

  while (!worklist.empty()) {
    HPhi* phi = worklist.back();
    worklist.pop_back();

    // If the phi has already been processed, continue.
    if (!phi->IsInBlock()) {
      continue;
    }

    // If the phi is dead, we know we won't revive it and it will be removed,
    // so don't process it.
    if (phi->IsDead()) {
      continue;
    }

    HInstruction* candidate = nullptr;
    visited_phis_in_cycle.ClearAllBits();
    cycle_worklist.clear();

    cycle_worklist.push_back(phi);
    visited_phis_in_cycle.SetBit(phi->GetId());
    bool catch_phi_in_cycle = phi->IsCatchPhi();
    bool irreducible_loop_phi_in_cycle = phi->IsIrreducibleLoopHeaderPhi();

    // First do a simple loop over inputs and check if they are all the same.
    for (HInstruction* input : phi->GetInputs()) {
      if (input == phi) {
        continue;
      } else if (candidate == nullptr) {
        candidate = input;
      } else if (candidate != input) {
        candidate = nullptr;
        break;
      }
    }

    // If we haven't found a candidate, check for a phi cycle. Note that we need to detect
    // such cycles to avoid having reference and non-reference equivalents. We check this
    // invariant in the graph checker.
    if (candidate == nullptr) {
      // We iterate over the array as long as it grows.
      for (size_t i = 0; i < cycle_worklist.size(); ++i) {
        HPhi* current = cycle_worklist[i];
        DCHECK(!current->IsLoopHeaderPhi() ||
               current->GetBlock()->IsLoopPreHeaderFirstPredecessor());

        for (HInstruction* input : current->GetInputs()) {
          if (input == current) {
            continue;
          } else if (input->IsPhi()) {
            if (!visited_phis_in_cycle.IsBitSet(input->GetId())) {
              cycle_worklist.push_back(input->AsPhi());
              visited_phis_in_cycle.SetBit(input->GetId());
              catch_phi_in_cycle |= input->AsPhi()->IsCatchPhi();
              irreducible_loop_phi_in_cycle |= input->IsIrreducibleLoopHeaderPhi();
            } else {
              // Already visited, nothing to do.
            }
          } else if (candidate == nullptr) {
            candidate = input;
          } else if (candidate != input) {
            candidate = nullptr;
            // Clear the cycle worklist to break out of the outer loop.
            cycle_worklist.clear();
            break;
          }
        }
      }
    }

    if (candidate == nullptr) {
      continue;
    }

    if (irreducible_loop_phi_in_cycle && !candidate->IsConstant()) {
      // For irreducible loops, we need to keep the phis to satisfy our linear scan
      // algorithm.
      // There is one exception for constants, as the type propagation requires redundant
      // cyclic phis of a constant to be removed. This is ok for the linear scan as it
      // has to deal with constants anyway, and they can trivially be rematerialized.
      continue;
    }

    for (HPhi* current : cycle_worklist) {
      // The candidate may not dominate a phi in a catch block: there may be non-throwing
      // instructions at the beginning of a try range, that may be the first input of
      // catch phis.
      // TODO(dbrazdil): Remove this situation by moving those non-throwing instructions
      // before the try entry.
      if (catch_phi_in_cycle) {
        if (!candidate->StrictlyDominates(current)) {
          continue;
        }
      } else {
        DCHECK(candidate->StrictlyDominates(current));
      }

      // Because we're updating the users of this phi, we may have new candidates
      // for elimination. Add phis that use this phi to the worklist.
      for (const HUseListNode<HInstruction*>& use : current->GetUses()) {
        HInstruction* user = use.GetUser();
        if (user->IsPhi() && !visited_phis_in_cycle.IsBitSet(user->GetId())) {
          worklist.push_back(user->AsPhi());
        }
      }
      DCHECK(candidate->StrictlyDominates(current));
      current->ReplaceWith(candidate);
      current->GetBlock()->RemovePhi(current);
    }
  }
  return true;
}

}  // namespace art
