// Copyright (c) 2015, 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.loop_invariant_code_motion;

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

/// Lifts primitives out of loops when it is safe and profitable.
/// 
/// Currently we only do this for interceptors.
class LoopInvariantCodeMotion extends RecursiveVisitor implements Pass {
  String get passName => 'Loop-invariant code motion';

  final Map<Primitive, Continuation> primitiveLoop = 
      <Primitive, Continuation>{};

  LoopHierarchy loopHierarchy;
  Continuation currentLoopHeader;

  /// When processing the dependencies of a primitive, [referencedLoop]
  /// refers to the innermost loop that contains one of the dependencies
  /// seen so far (or `null` if none of the dependencies are bound in a loop).
  ///
  /// This is used to determine how far the primitive can be lifted without
  /// falling out of scope of its dependencies.
  Continuation referencedLoop;

  void rewrite(FunctionDefinition node) {
    loopHierarchy = new LoopHierarchy(node);
    visit(node.body);
  }

  @override
  Expression traverseContinuation(Continuation cont) {
    Continuation oldLoopHeader = currentLoopHeader;
    pushAction(() {
      currentLoopHeader = oldLoopHeader;
    });
    currentLoopHeader = loopHierarchy.getLoopHeader(cont);
    for (Parameter param in cont.parameters) {
      primitiveLoop[param] = currentLoopHeader;
    }
    return cont.body;
  }

  @override
  Expression traverseLetPrim(LetPrim node) {
    primitiveLoop[node.primitive] = currentLoopHeader;
    if (!shouldLift(node.primitive)) {
      return node.body;
    }
    referencedLoop = null;
    visit(node.primitive); // Sets referencedLoop.
    Expression next = node.body;
    if (referencedLoop != currentLoopHeader) {
      // Bind the primitive inside [referencedLoop] (possibly null),
      // immediately before the binding of the inner loop.

      // Find the inner loop.
      Continuation loop = currentLoopHeader;
      Continuation enclosing = loopHierarchy.getEnclosingLoop(loop);
      while (enclosing != referencedLoop) {
        assert(loop != null);
        loop = enclosing;
        enclosing = loopHierarchy.getEnclosingLoop(loop);
      }
      assert(loop != null);

      // Remove LetPrim from its current position.
      node.parent.body = node.body;
      node.body.parent = node.parent;

      // Insert the LetPrim immediately before the loop.
      LetCont loopBinding = loop.parent;
      InteriorNode newParent = loopBinding.parent;
      newParent.body = node;
      node.body = loopBinding;
      loopBinding.parent = node;
      node.parent = newParent;

      // A different loop now contains the primitive.
      primitiveLoop[node.primitive] = enclosing;
    }
    return next;
  }

  /// Returns the the innermost loop that effectively encloses both
  /// c1 and c2 (or `null` if there is no such loop).
  Continuation leastCommonAncestor(Continuation c1, Continuation c2) {
    int d1 = getDepth(c1), d2 = getDepth(c2);
    while (c1 != c2) {
      if (d1 <= d2) {
        c2 = loopHierarchy.getEnclosingLoop(c2);
        d2 = getDepth(c2);
      } else {
        c1 = loopHierarchy.getEnclosingLoop(c1);
        d1 = getDepth(c1);
      }
    }
    return c1;
  }

  @override
  void processReference(Reference ref) {
    Continuation loop = 
        leastCommonAncestor(currentLoopHeader, primitiveLoop[ref.definition]);
    referencedLoop = getInnerLoop(loop, referencedLoop);
  }

  int getDepth(Continuation loop) {
    if (loop == null) return -1;
    return loopHierarchy.loopDepth[loop];
  }

  Continuation getInnerLoop(Continuation loop1, Continuation loop2) {
    if (loop1 == null) return loop2;
    if (loop2 == null) return loop1;
    if (loopHierarchy.loopDepth[loop1] > loopHierarchy.loopDepth[loop2]) {
      return loop1;
    } else {
      return loop2;
    }
  }

  bool shouldLift(Primitive prim) {
    // Interceptors are generally safe and almost always profitable for lifting
    // out of loops. Several other primitive could be lifted too, but it's not
    // always profitable to do so.

    // Note that the type of the interceptor is technically not sound after
    // lifting because its current type might have been computed based on a
    // refinement node (which has since been removed). As a whole, it still
    // works out because all uses of the interceptor must occur in a context
    // where it indeed has the type it claims to have.
    return prim is Interceptor;
  }
}
