/*
 * 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"

namespace art {

void SsaDeadPhiElimination::Run() {
  MarkDeadPhis();
  EliminateDeadPhis();
}

void SsaDeadPhiElimination::MarkDeadPhis() {
  // Add to the worklist phis referenced by non-phi instructions.
  for (HReversePostOrderIterator it(*graph_); !it.Done(); it.Advance()) {
    HBasicBlock* block = it.Current();
    for (HInstructionIterator inst_it(block->GetPhis()); !inst_it.Done(); inst_it.Advance()) {
      HPhi* phi = inst_it.Current()->AsPhi();
      // Set dead ahead of running through uses. The phi may have no use.
      phi->SetDead();
      for (HUseIterator<HInstruction*> use_it(phi->GetUses()); !use_it.Done(); use_it.Advance()) {
        HUseListNode<HInstruction*>* current = use_it.Current();
        HInstruction* user = current->GetUser();
        if (!user->IsPhi()) {
          worklist_.Add(phi);
          phi->SetLive();
          break;
        }
      }
    }
  }

  // Process the worklist by propagating liveness to phi inputs.
  while (!worklist_.IsEmpty()) {
    HPhi* phi = worklist_.Pop();
    for (HInputIterator it(phi); !it.Done(); it.Advance()) {
      HInstruction* input = it.Current();
      if (input->IsPhi() && input->AsPhi()->IsDead()) {
        worklist_.Add(input->AsPhi());
        input->AsPhi()->SetLive();
      }
    }
  }
}

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 (HPostOrderIterator it(*graph_); !it.Done(); it.Advance()) {
    HBasicBlock* block = it.Current();
    HInstruction* current = block->GetFirstPhi();
    HInstruction* next = nullptr;
    while (current != nullptr) {
      next = current->GetNext();
      if (current->AsPhi()->IsDead()) {
        if (current->HasUses()) {
          for (HUseIterator<HInstruction*> use_it(current->GetUses()); !use_it.Done();
               use_it.Advance()) {
            HUseListNode<HInstruction*>* user_node = use_it.Current();
            HInstruction* user = user_node->GetUser();
            DCHECK(user->IsLoopHeaderPhi()) << user->GetId();
            DCHECK(user->AsPhi()->IsDead()) << user->GetId();
            // Just put itself as an input. The phi will be removed in this loop anyway.
            user->SetRawInputAt(user_node->GetIndex(), user);
            current->RemoveUser(user, user_node->GetIndex());
          }
        }
        if (current->HasEnvironmentUses()) {
          for (HUseIterator<HEnvironment*> use_it(current->GetEnvUses()); !use_it.Done();
               use_it.Advance()) {
            HUseListNode<HEnvironment*>* user_node = use_it.Current();
            HEnvironment* user = user_node->GetUser();
            user->SetRawEnvAt(user_node->GetIndex(), nullptr);
            current->RemoveEnvironmentUser(user_node);
          }
        }
        block->RemovePhi(current->AsPhi());
      }
      current = next;
    }
  }
}

void SsaRedundantPhiElimination::Run() {
  // Add all phis in the worklist.
  for (HReversePostOrderIterator it(*graph_); !it.Done(); it.Advance()) {
    HBasicBlock* block = it.Current();
    for (HInstructionIterator inst_it(block->GetPhis()); !inst_it.Done(); inst_it.Advance()) {
      worklist_.Add(inst_it.Current()->AsPhi());
    }
  }

  while (!worklist_.IsEmpty()) {
    HPhi* phi = worklist_.Pop();

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

    // Find if the inputs of the phi are the same instruction.
    HInstruction* candidate = phi->InputAt(0);
    // A loop phi cannot have itself as the first phi. Note that this
    // check relies on our simplification pass ensuring the pre-header
    // block is first in the list of predecessors of the loop header.
    DCHECK(!phi->IsLoopHeaderPhi() || phi->GetBlock()->IsLoopPreHeaderFirstPredecessor());
    DCHECK_NE(phi, candidate);

    for (size_t i = 1; i < phi->InputCount(); ++i) {
      HInstruction* input = phi->InputAt(i);
      // For a loop phi, if the input is the phi, the phi is still candidate for
      // elimination.
      if (input != candidate && input != phi) {
        candidate = nullptr;
        break;
      }
    }

    // If the inputs are not the same, continue.
    if (candidate == nullptr) {
      continue;
    }

    if (phi->IsInLoop()) {
      // Because we're updating the users of this phi, we may have new
      // phis candidate for elimination if this phi is in a loop. Add phis that
      // used this phi to the worklist.
      for (HUseIterator<HInstruction*> it(phi->GetUses()); !it.Done(); it.Advance()) {
        HUseListNode<HInstruction*>* current = it.Current();
        HInstruction* user = current->GetUser();
        if (user->IsPhi()) {
          worklist_.Add(user->AsPhi());
        }
      }
    }
    phi->ReplaceWith(candidate);
    phi->GetBlock()->RemovePhi(phi);
  }
}

}  // namespace art
