// Copyright (c) 2014, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

library dart2js.cps_ir.redundant_phi_elimination;

import 'cps_ir_nodes.dart';
import 'optimizers.dart';

/// Eliminate redundant phis from the given [FunctionDefinition].
///
/// Phis in this case are [Continuations] together with corresponding
/// [InvokeContinuation]s. A [Continuation] parameter at position i is redundant
/// if for all [InvokeContinuation]s, the parameter at position i is identical
/// (except for feedback). Redundant parameters are removed from the
/// continuation signature, all invocations, and replaced within the
/// continuation body.
class RedundantPhiEliminator extends TrampolineRecursiveVisitor implements Pass {
  String get passName => 'Redundant phi elimination';

  final Set<Continuation> workSet = new Set<Continuation>();

  @override
  void rewrite(FunctionDefinition root) {
    // Traverse the tree once to build the work set.
    visit(root);

    // Process each continuation one-by-one.
    while (workSet.isNotEmpty) {
      Continuation cont = workSet.first;
      workSet.remove(cont);

      if (cont.isReturnContinuation) {
        continue; // Skip function return continuations.
      }

      _processContinuation(cont);
    }
  }

  /// Called for each continuation on the work set. Modifies the IR graph if
  /// [cont] is a candidate for redundant phi elimination.
  void _processContinuation(Continuation cont) {
    // Generate the list of all cont invocations. If cont is used in any other
    // context (i.e. as a continuation of InvokeMethod), it is not possible to
    // optimize.
    List<InvokeContinuation> invokes = <InvokeContinuation>[];
    for (Reference ref = cont.firstRef; ref != null; ref = ref.next) {
      Node parent = ref.parent;
      if (parent is InvokeContinuation && ref == parent.continuation) {
        invokes.add(parent);
      } else {
        return; // Can't optimize.
      }
    }

    if (invokes.isEmpty) {
      return; // Continuation is never invoked, can't optimize.
    }

    /// Returns the unique definition of parameter i if it exists and null
    /// otherwise. A definition is unique if it is the only value used to
    /// invoke the continuation, excluding feedback.
    Primitive uniqueDefinitionOf(int i) {
      Primitive value = null;
      for (InvokeContinuation invoke in invokes) {
        Primitive def = invoke.arguments[i].definition.effectiveDefinition;

        if (cont.parameters[i] == def) {
          // Invocation param == param in LetCont (i.e. a recursive call).
          continue;
        } else if (value == null) {
          value = def; // Set initial comparison value.
        } else if (value != def) {
          return null; // Differing invocation arguments.
        }
      }

      return value;
    }

    // If uniqueDefinition is in the body of the LetCont binding the
    // continuation, then we will drop the continuation binding to just inside
    // the binding of uniqueDefiniton.  This is not safe if we drop the
    // continuation binding inside a LetHandler exception handler binding.
    LetCont letCont = cont.parent;
    bool safeForHandlers(Definition uniqueDefinition) {
      bool seenHandler = false;
      Node current = uniqueDefinition.parent;
      while (current != null) {
        if (current == letCont) return !seenHandler;
        seenHandler = seenHandler || current is LetHandler;
        current = current.parent;
      }
      // When uniqueDefinition is not in the body of the LetCont binding the
      // continuation, we will not move any code, so that is safe.
      return true;
    }

    // Check if individual parameters are always called with a unique
    // definition, and remove them if that is the case. During each iteration,
    // we read the current parameter/argument from index `src` and copy it
    // to index `dst`.
    int dst = 0;
    for (int src = 0; src < cont.parameters.length; src++) {
      // Is the current phi redundant?
      Primitive uniqueDefinition = uniqueDefinitionOf(src);
      if (uniqueDefinition == null || !safeForHandlers(uniqueDefinition)) {
        // Reorganize parameters and arguments in case of deletions.
        if (src != dst) {
          cont.parameters[dst] = cont.parameters[src];
          for (InvokeContinuation invoke in invokes) {
            invoke.arguments[dst] = invoke.arguments[src];
          }
        }
        dst++;
        continue;
      }

      Primitive oldDefinition = cont.parameters[src];

      // Add continuations of about-to-be modified invokes to worklist since
      // we might introduce new optimization opportunities.
      for (Reference ref = oldDefinition.firstRef;
           ref != null;
           ref = ref.next) {
        Node parent = ref.parent;
        if (parent is InvokeContinuation) {
          Continuation thatCont = parent.continuation.definition;
          if (thatCont != cont) {
            workSet.add(thatCont);
          }
        }
      }

      // Replace individual parameters:
      // * In the continuation body, replace occurrence of param with value,
      // * and implicitly remove param from continuation signature and
      //   invocations by not incrementing `dst`. References of removed
      //   arguments are unlinked to keep definition usages up to date.
      oldDefinition.replaceUsesWith(uniqueDefinition);
      for (InvokeContinuation invoke in invokes) {
        invoke.arguments[src].unlink();
      }

      // Finally, if the substituted definition is not in scope of the affected
      // continuation, move the continuation binding. This is safe to do since
      // the continuation is referenced only as the target in continuation
      // invokes, and all such invokes must be within the scope of
      // [uniqueDefinition]. Note that this is linear in the depth of
      // the binding of [uniqueDefinition].
      letCont = _makeUniqueBinding(cont);
      _moveIntoScopeOf(letCont, uniqueDefinition);
    }

    // Remove trailing items from parameter and argument lists.
    cont.parameters.length = dst;
    for (InvokeContinuation invoke in invokes) {
      invoke.arguments.length = dst;
    }
  }

  void processLetCont(LetCont node) {
    node.continuations.forEach(workSet.add);
  }
}

/// Returns true, iff [letCont] is not scope of [definition].
/// Linear in the depth of definition within the IR graph.
bool _isInScopeOf(LetCont letCont, Definition definition) {
  for (Node node = definition.parent; node != null; node = node.parent) {
    if (node == letCont) {
      return false;
    }
  }

  return true;
}

/// Moves [letCont] below the binding of [definition] within the IR graph.
/// Does nothing if [letCont] is already within the scope of [definition].
/// Assumes that one argument is nested within the scope of the other
/// when this method is called.
void _moveIntoScopeOf(LetCont letCont, Definition definition) {
  if (_isInScopeOf(letCont, definition)) return;

  InteriorNode binding = definition.parent;
  letCont.remove();
  letCont.insertBelow(binding);
}

/// Ensures [continuation] has its own LetCont binding by creating
/// a new LetCont below its current binding, if necessary.
///
/// Returns the LetCont that now binds [continuation].
LetCont _makeUniqueBinding(Continuation continuation) {
  LetCont letCont = continuation.parent;
  if (letCont.continuations.length == 1) return letCont;
  letCont.continuations.remove(continuation);
  LetCont newBinding = new LetCont(continuation, null);
  continuation.parent = newBinding;
  newBinding.insertBelow(letCont);
  return newBinding;
}
