// Copyright 2015 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "src/compiler/branch-elimination.h"

#include "src/compiler/js-graph.h"
#include "src/compiler/node-properties.h"
#include "src/compiler/simplified-operator.h"

namespace v8 {
namespace internal {
namespace compiler {

BranchElimination::BranchElimination(Editor* editor, JSGraph* js_graph,
                                     Zone* zone)
    : AdvancedReducer(editor),
      jsgraph_(js_graph),
      node_conditions_(zone, js_graph->graph()->NodeCount()),
      zone_(zone),
      dead_(js_graph->graph()->NewNode(js_graph->common()->Dead())) {
  NodeProperties::SetType(dead_, Type::None());
}

BranchElimination::~BranchElimination() {}


Reduction BranchElimination::Reduce(Node* node) {
  switch (node->opcode()) {
    case IrOpcode::kDead:
      return NoChange();
    case IrOpcode::kDeoptimizeIf:
    case IrOpcode::kDeoptimizeUnless:
      return ReduceDeoptimizeConditional(node);
    case IrOpcode::kMerge:
      return ReduceMerge(node);
    case IrOpcode::kLoop:
      return ReduceLoop(node);
    case IrOpcode::kBranch:
      return ReduceBranch(node);
    case IrOpcode::kIfFalse:
      return ReduceIf(node, false);
    case IrOpcode::kIfTrue:
      return ReduceIf(node, true);
    case IrOpcode::kStart:
      return ReduceStart(node);
    default:
      if (node->op()->ControlOutputCount() > 0) {
        return ReduceOtherControl(node);
      }
      break;
  }
  return NoChange();
}


Reduction BranchElimination::ReduceBranch(Node* node) {
  Node* condition = node->InputAt(0);
  Node* control_input = NodeProperties::GetControlInput(node, 0);
  const ControlPathConditions* from_input = node_conditions_.Get(control_input);
  if (from_input != nullptr) {
    Maybe<bool> condition_value = from_input->LookupCondition(condition);
    // If we know the condition we can discard the branch.
    if (condition_value.IsJust()) {
      bool known_value = condition_value.FromJust();
      for (Node* const use : node->uses()) {
        switch (use->opcode()) {
          case IrOpcode::kIfTrue:
            Replace(use, known_value ? control_input : dead());
            break;
          case IrOpcode::kIfFalse:
            Replace(use, known_value ? dead() : control_input);
            break;
          default:
            UNREACHABLE();
        }
      }
      return Replace(dead());
    }
  }
  return TakeConditionsFromFirstControl(node);
}

Reduction BranchElimination::ReduceDeoptimizeConditional(Node* node) {
  DCHECK(node->opcode() == IrOpcode::kDeoptimizeIf ||
         node->opcode() == IrOpcode::kDeoptimizeUnless);
  bool condition_is_true = node->opcode() == IrOpcode::kDeoptimizeUnless;
  DeoptimizeParameters p = DeoptimizeParametersOf(node->op());
  Node* condition = NodeProperties::GetValueInput(node, 0);
  Node* frame_state = NodeProperties::GetValueInput(node, 1);
  Node* effect = NodeProperties::GetEffectInput(node);
  Node* control = NodeProperties::GetControlInput(node);
  ControlPathConditions const* conditions = node_conditions_.Get(control);
  // If we do not know anything about the predecessor, do not propagate just
  // yet because we will have to recompute anyway once we compute the
  // predecessor.
  if (conditions == nullptr) {
    return UpdateConditions(node, conditions);
  }
  Maybe<bool> condition_value = conditions->LookupCondition(condition);
  if (condition_value.IsJust()) {
    // If we know the condition we can discard the branch.
    if (condition_is_true == condition_value.FromJust()) {
      // We don't update the conditions here, because we're replacing {node}
      // with the {control} node that already contains the right information.
      ReplaceWithValue(node, dead(), effect, control);
    } else {
      control = graph()->NewNode(common()->Deoptimize(p.kind(), p.reason()),
                                 frame_state, effect, control);
      // TODO(bmeurer): This should be on the AdvancedReducer somehow.
      NodeProperties::MergeControlToEnd(graph(), common(), control);
      Revisit(graph()->end());
    }
    return Replace(dead());
  }
  return UpdateConditions(node, conditions, condition, condition_is_true);
}

Reduction BranchElimination::ReduceIf(Node* node, bool is_true_branch) {
  // Add the condition to the list arriving from the input branch.
  Node* branch = NodeProperties::GetControlInput(node, 0);
  const ControlPathConditions* from_branch = node_conditions_.Get(branch);
  // If we do not know anything about the predecessor, do not propagate just
  // yet because we will have to recompute anyway once we compute the
  // predecessor.
  if (from_branch == nullptr) {
    return UpdateConditions(node, nullptr);
  }
  Node* condition = branch->InputAt(0);
  return UpdateConditions(node, from_branch, condition, is_true_branch);
}


Reduction BranchElimination::ReduceLoop(Node* node) {
  // Here we rely on having only reducible loops:
  // The loop entry edge always dominates the header, so we can just use
  // the information from the loop entry edge.
  return TakeConditionsFromFirstControl(node);
}


Reduction BranchElimination::ReduceMerge(Node* node) {
  // Shortcut for the case when we do not know anything about some
  // input.
  Node::Inputs inputs = node->inputs();
  for (Node* input : inputs) {
    if (node_conditions_.Get(input) == nullptr) {
      return UpdateConditions(node, nullptr);
    }
  }

  auto input_it = inputs.begin();

  DCHECK_GT(inputs.count(), 0);

  const ControlPathConditions* first = node_conditions_.Get(*input_it);
  ++input_it;
  // Make a copy of the first input's conditions and merge with the conditions
  // from other inputs.
  ControlPathConditions* conditions =
      new (zone_->New(sizeof(ControlPathConditions)))
          ControlPathConditions(*first);
  auto input_end = inputs.end();
  for (; input_it != input_end; ++input_it) {
    conditions->Merge(*(node_conditions_.Get(*input_it)));
  }

  return UpdateConditions(node, conditions);
}


Reduction BranchElimination::ReduceStart(Node* node) {
  return UpdateConditions(node, ControlPathConditions::Empty(zone_));
}

const BranchElimination::ControlPathConditions*
BranchElimination::PathConditionsForControlNodes::Get(Node* node) const {
  if (static_cast<size_t>(node->id()) < info_for_node_.size()) {
    return info_for_node_[node->id()];
  }
  return nullptr;
}


void BranchElimination::PathConditionsForControlNodes::Set(
    Node* node, const ControlPathConditions* conditions) {
  size_t index = static_cast<size_t>(node->id());
  if (index >= info_for_node_.size()) {
    info_for_node_.resize(index + 1, nullptr);
  }
  info_for_node_[index] = conditions;
}


Reduction BranchElimination::ReduceOtherControl(Node* node) {
  DCHECK_EQ(1, node->op()->ControlInputCount());
  return TakeConditionsFromFirstControl(node);
}


Reduction BranchElimination::TakeConditionsFromFirstControl(Node* node) {
  // We just propagate the information from the control input (ideally,
  // we would only revisit control uses if there is change).
  const ControlPathConditions* from_input =
      node_conditions_.Get(NodeProperties::GetControlInput(node, 0));
  return UpdateConditions(node, from_input);
}


Reduction BranchElimination::UpdateConditions(
    Node* node, const ControlPathConditions* conditions) {
  const ControlPathConditions* original = node_conditions_.Get(node);
  // Only signal that the node has Changed if the condition information has
  // changed.
  if (conditions != original) {
    if (conditions == nullptr || original == nullptr ||
        *conditions != *original) {
      node_conditions_.Set(node, conditions);
      return Changed(node);
    }
  }
  return NoChange();
}

Reduction BranchElimination::UpdateConditions(
    Node* node, const ControlPathConditions* prev_conditions,
    Node* current_condition, bool is_true_branch) {
  const ControlPathConditions* original = node_conditions_.Get(node);
  DCHECK(prev_conditions != nullptr && current_condition != nullptr);
  // The control path for the node is the path obtained by appending the
  // current_condition to the prev_conditions. Check if this new control path
  // would be the same as the already recorded path (original).
  if (original == nullptr || !prev_conditions->EqualsAfterAddingCondition(
                                 original, current_condition, is_true_branch)) {
    // If this is the first visit or if the control path is different from the
    // recorded path create the new control path and record it.
    const ControlPathConditions* new_condition =
        prev_conditions->AddCondition(zone_, current_condition, is_true_branch);
    node_conditions_.Set(node, new_condition);
    return Changed(node);
  }
  return NoChange();
}

// static
const BranchElimination::ControlPathConditions*
BranchElimination::ControlPathConditions::Empty(Zone* zone) {
  return new (zone->New(sizeof(ControlPathConditions)))
      ControlPathConditions(nullptr, 0);
}


void BranchElimination::ControlPathConditions::Merge(
    const ControlPathConditions& other) {
  // Change the current condition list to a longest common tail
  // of this condition list and the other list. (The common tail
  // should correspond to the list from the common dominator.)

  // First, we throw away the prefix of the longer list, so that
  // we have lists of the same length.
  size_t other_size = other.condition_count_;
  BranchCondition* other_condition = other.head_;
  while (other_size > condition_count_) {
    other_condition = other_condition->next;
    other_size--;
  }
  while (condition_count_ > other_size) {
    head_ = head_->next;
    condition_count_--;
  }

  // Then we go through both lists in lock-step until we find
  // the common tail.
  while (head_ != other_condition) {
    DCHECK_LT(0, condition_count_);
    condition_count_--;
    other_condition = other_condition->next;
    head_ = head_->next;
  }
}


const BranchElimination::ControlPathConditions*
BranchElimination::ControlPathConditions::AddCondition(Zone* zone,
                                                       Node* condition,
                                                       bool is_true) const {
  DCHECK(LookupCondition(condition).IsNothing());

  BranchCondition* new_head = new (zone->New(sizeof(BranchCondition)))
      BranchCondition(condition, is_true, head_);

  ControlPathConditions* conditions =
      new (zone->New(sizeof(ControlPathConditions)))
          ControlPathConditions(new_head, condition_count_ + 1);
  return conditions;
}


Maybe<bool> BranchElimination::ControlPathConditions::LookupCondition(
    Node* condition) const {
  for (BranchCondition* current = head_; current != nullptr;
       current = current->next) {
    if (current->condition == condition) {
      return Just<bool>(current->is_true);
    }
  }
  return Nothing<bool>();
}

bool BranchElimination::ControlPathConditions::IsSamePath(
    BranchCondition* this_condition, BranchCondition* other_condition) const {
  while (true) {
    if (this_condition == other_condition) return true;
    if (this_condition->condition != other_condition->condition ||
        this_condition->is_true != other_condition->is_true) {
      return false;
    }
    this_condition = this_condition->next;
    other_condition = other_condition->next;
  }
  UNREACHABLE();
}

bool BranchElimination::ControlPathConditions::operator==(
    const ControlPathConditions& other) const {
  if (condition_count_ != other.condition_count_) return false;
  return IsSamePath(head_, other.head_);
}

bool BranchElimination::ControlPathConditions::EqualsAfterAddingCondition(
    const ControlPathConditions* other, const Node* new_condition,
    bool new_branch_direction) const {
  // When an extra condition is added to the current chain, the count of
  // the resulting chain would increase by 1. Quick check to see if counts
  // match.
  if (other->condition_count_ != condition_count_ + 1) return false;

  // Check if the head of the other chain is same as the new condition that
  // would be added.
  if (other->head_->condition != new_condition ||
      other->head_->is_true != new_branch_direction) {
    return false;
  }

  // Check if the rest of the path is the same as the prev_condition.
  return IsSamePath(other->head_->next, head_);
}

Graph* BranchElimination::graph() const { return jsgraph()->graph(); }

CommonOperatorBuilder* BranchElimination::common() const {
  return jsgraph()->common();
}

}  // namespace compiler
}  // namespace internal
}  // namespace v8
