/*
 * Copyright 2008 Google Inc.
 *
 * 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.
 */
package com.google.gwt.dev.jjs.impl;

import com.google.gwt.dev.jjs.SourceInfo;
import com.google.gwt.dev.jjs.ast.Context;
import com.google.gwt.dev.jjs.ast.JBinaryOperation;
import com.google.gwt.dev.jjs.ast.JBinaryOperator;
import com.google.gwt.dev.jjs.ast.JBlock;
import com.google.gwt.dev.jjs.ast.JBooleanLiteral;
import com.google.gwt.dev.jjs.ast.JBreakStatement;
import com.google.gwt.dev.jjs.ast.JCaseStatement;
import com.google.gwt.dev.jjs.ast.JCastOperation;
import com.google.gwt.dev.jjs.ast.JCharLiteral;
import com.google.gwt.dev.jjs.ast.JClassType;
import com.google.gwt.dev.jjs.ast.JConditional;
import com.google.gwt.dev.jjs.ast.JContinueStatement;
import com.google.gwt.dev.jjs.ast.JDeclarationStatement;
import com.google.gwt.dev.jjs.ast.JDeclaredType;
import com.google.gwt.dev.jjs.ast.JDoStatement;
import com.google.gwt.dev.jjs.ast.JDoubleLiteral;
import com.google.gwt.dev.jjs.ast.JEnumField;
import com.google.gwt.dev.jjs.ast.JExpression;
import com.google.gwt.dev.jjs.ast.JExpressionStatement;
import com.google.gwt.dev.jjs.ast.JField;
import com.google.gwt.dev.jjs.ast.JFieldRef;
import com.google.gwt.dev.jjs.ast.JFloatLiteral;
import com.google.gwt.dev.jjs.ast.JForStatement;
import com.google.gwt.dev.jjs.ast.JIfStatement;
import com.google.gwt.dev.jjs.ast.JInstanceOf;
import com.google.gwt.dev.jjs.ast.JIntLiteral;
import com.google.gwt.dev.jjs.ast.JLiteral;
import com.google.gwt.dev.jjs.ast.JLocalRef;
import com.google.gwt.dev.jjs.ast.JLongLiteral;
import com.google.gwt.dev.jjs.ast.JMethod;
import com.google.gwt.dev.jjs.ast.JMethodCall;
import com.google.gwt.dev.jjs.ast.JNewInstance;
import com.google.gwt.dev.jjs.ast.JNode;
import com.google.gwt.dev.jjs.ast.JParameterRef;
import com.google.gwt.dev.jjs.ast.JPostfixOperation;
import com.google.gwt.dev.jjs.ast.JPrefixOperation;
import com.google.gwt.dev.jjs.ast.JPrimitiveType;
import com.google.gwt.dev.jjs.ast.JProgram;
import com.google.gwt.dev.jjs.ast.JReferenceType;
import com.google.gwt.dev.jjs.ast.JStatement;
import com.google.gwt.dev.jjs.ast.JStringLiteral;
import com.google.gwt.dev.jjs.ast.JSwitchStatement;
import com.google.gwt.dev.jjs.ast.JTryStatement;
import com.google.gwt.dev.jjs.ast.JType;
import com.google.gwt.dev.jjs.ast.JUnaryOperator;
import com.google.gwt.dev.jjs.ast.JValueLiteral;
import com.google.gwt.dev.jjs.ast.JVariableRef;
import com.google.gwt.dev.jjs.ast.JVisitor;
import com.google.gwt.dev.jjs.ast.JWhileStatement;
import com.google.gwt.dev.jjs.ast.RuntimeConstants;
import com.google.gwt.dev.jjs.ast.js.JMultiExpression;
import com.google.gwt.dev.util.Ieee754_64_Arithmetic;
import com.google.gwt.dev.util.log.speedtracer.CompilerEventType;
import com.google.gwt.dev.util.log.speedtracer.SpeedTracerLogger;
import com.google.gwt.dev.util.log.speedtracer.SpeedTracerLogger.Event;
import com.google.gwt.thirdparty.guava.common.annotations.VisibleForTesting;
import com.google.gwt.thirdparty.guava.common.collect.ImmutableMap;
import com.google.gwt.thirdparty.guava.common.collect.Lists;
import com.google.gwt.thirdparty.guava.common.collect.Sets;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * Removes certain kinds of dead code, and simplifies certain expressions. This
 * pass focuses on intraprocedural optimizations, that is, optimizations that
 * can be performed inside of a single method body (and usually a single
 * expression) rather than global transformations. Global optimizations done in
 * other passes will feed into this, however.
 */
public class DeadCodeElimination {

  /**
   * Eliminates dead or unreachable code when possible, and makes local
   * simplifications like changing "<code>x || true</code>" to "<code>x</code>".
   *
   * This visitor should perform all of its optimizations in a single pass.
   * Except in rare cases, running this pass multiple times should produce no
   * changes after the first pass. The only currently known exception to this
   * rule is in {@link #endVisit(JNewInstance, Context)}, where the target
   * constructor may be non-empty at the beginning of DCE and become empty
   * during the run, which potentially unlocks optimizations at call sites.
   *
   * TODO: leverage ignoring expression output more to remove intermediary
   * operations in favor of pure side effects.
   *
   * TODO: move more simplifications into methods like
   * {@link #cast(JExpression, SourceInfo, JType, JExpression) simplifyCast}, so
   * that more simplifications can be made on a single pass through a tree.
   */
  public class DeadCodeVisitor extends JChangeTrackingVisitor {

    public DeadCodeVisitor(OptimizerContext optimizerCtx) {
      super(optimizerCtx);
    }

    /**
     * Expressions whose result does not matter. A parent node should add any
     * children whose result does not matter to this set during the parent's
     * <code>visit()</code> method. It should then remove those children during
     * its own <code>endVisit()</code>.
     *
     * TODO: there's a latent bug here: some immutable nodes (such as literals)
     * can be multiply referenced in the AST. In theory, one reference to that
     * node could be put into this set while another reference actually contains
     * a result that is needed. In practice this is okay at the moment since the
     * existing uses of <code>ignoringExpressionOutput</code> are with mutable
     * nodes.
     */
    private final Set<JExpression> ignoringExpressionOutput = Sets.newHashSet();

    /**
     * Expressions being used as lvalues.
     */
    private final Set<JExpression> lvalues = Sets.newHashSet();

    private final Set<JBlock> switchBlocks = Sets.newHashSet();

    private final JMethod isScriptMethod = program.getIndexedMethod(RuntimeConstants.GWT_IS_SCRIPT);
    private final JMethod enumOrdinalMethod =
        program.getIndexedMethod(RuntimeConstants.ENUM_ORDINAL);
    private final JField enumOrdinalField =
        program.getIndexedField(RuntimeConstants.ENUM_ORDINAL);

    /**
     * Short circuit binary operations.
     */
    @Override
    public void endVisit(JBinaryOperation x, Context ctx) {
      JBinaryOperator op = x.getOp();
      JExpression lhs = x.getLhs();
      JExpression rhs = x.getRhs();

      // If either parameter is a multiexpression, restructure if possible.
      if (isNonEmptyMultiExpression(lhs)) {
        // Push the operation inside the multiexpression. This exposes other optimization
        // opportunities for latter passes e.g:
        //
        // (a(), b(), 1) + 2 ==> (a(), b(), 1 + 2) ==> (a(), b(), 3)
        //
        // There is no need to consider the symmetric case as it requires that all expression in the
        // rhs (except the last one) to be side effect free, in which case they will end up being
        // removed anyway.

        List<JExpression> expressions = ((JMultiExpression) lhs).getExpressions();
        JMultiExpression result = new JMultiExpression(lhs.getSourceInfo(),
            expressions.subList(0, expressions.size() - 1));
        result.addExpressions(new JBinaryOperation(x.getSourceInfo(), x.getType(), x.getOp(),
            expressions.get(expressions.size() - 1), rhs));
        ctx.replaceMe(result);
        return;
      }

      if (isNonEmptyMultiExpression(rhs) &&  lhs instanceof JValueLiteral &&
          op != JBinaryOperator.AND && op != JBinaryOperator.OR) {
        // Push the operation inside the multiexpression if the lhs is a value literal.
        // This exposes other optimization opportunities for latter passes e.g:
        //
        // 2 + (a(), b(), 1) ==> (a(), b(), 2 + 1) ==> (a(), b(), 3)
        //
        // And exception must be made for || and &&, as these operations might not evaluate the
        // rhs due to shortcutting.
        List<JExpression> expressions = ((JMultiExpression) rhs).getExpressions();
        JMultiExpression result = new JMultiExpression(rhs.getSourceInfo(),
            expressions.subList(0, expressions.size() - 1));
        result.addExpressions(new JBinaryOperation(x.getSourceInfo(), x.getType(), x.getOp(),
            lhs, expressions.get(expressions.size() - 1)));
        ctx.replaceMe(result);
        return;
      }

      if ((lhs instanceof JValueLiteral) && (rhs instanceof JValueLiteral)) {
        if (evalOpOnLiterals(op, (JValueLiteral) lhs, (JValueLiteral) rhs, ctx)) {
          return;
        }
      }

      switch (op) {
        case AND:
          maybeReplaceMe(x, Simplifier.simplifyAnd(x), ctx);
          break;
        case OR:
          maybeReplaceMe(x, Simplifier.simplifyOr(x), ctx);
          break;
        case BIT_XOR:
          simplifyXor(lhs, rhs, ctx);
          break;
        case EQ:
          simplifyEq(lhs, rhs, ctx, false);
          break;
        case NEQ:
          simplifyEq(lhs, rhs, ctx, true);
          break;
        case ADD:
          simplifyAdd(lhs, rhs, ctx, x.getType());
          break;
        case CONCAT:
          evalConcat(x.getSourceInfo(), lhs, rhs, ctx);
          break;
        case SUB:
          simplifySub(lhs, rhs, ctx, x.getType());
          break;
        case MUL:
          simplifyMul(lhs, rhs, ctx, x.getType());
          break;
        case DIV:
          simplifyDiv(lhs, rhs, ctx, x.getType());
          break;
        case SHL:
        case SHR:
        case SHRU:
          if (isLiteralZero(rhs)) {
            ctx.replaceMe(lhs);
          }
          break;
        default:
          if (op.isAssignment()) {
            lvalues.remove(lhs);
          }
          break;
      }
    }

    private boolean isNonEmptyMultiExpression(JExpression expression) {
      return expression instanceof JMultiExpression &&
          !((JMultiExpression) expression).getExpressions().isEmpty();
    }

    /**
     * Prune dead statements and empty blocks.
     */
    @Override
    public void endVisit(JBlock x, Context ctx) {
      // Switch blocks require special optimization code
      if (switchBlocks.contains(x)) {
        return;
      }

      /*
       * Remove any dead statements after an abrupt change in code flow and
       * promote safe statements within nested blocks to this block.
       */
      for (int i = 0; i < x.getStatements().size(); i++) {
        JStatement stmt = x.getStatements().get(i);

        if (stmt instanceof JBlock) {
          /*
           * Promote a sub-block's children to the current block, unless the
           * sub-block contains local declarations as children.
           */
          JBlock block = (JBlock) stmt;
          if (canPromoteBlock(block)) {
            x.removeStmt(i);
            x.addStmts(i, block.getStatements());
            i--;
            madeChanges();
            continue;
          }
        }

        if (stmt instanceof JExpressionStatement) {
          JExpressionStatement stmtExpr = (JExpressionStatement) stmt;
          if (stmtExpr.getExpr() instanceof JMultiExpression) {
            // Promote a multi's expressions to the current block
            x.removeStmt(i);
            int start = i;
            JMultiExpression multi = ((JMultiExpression) stmtExpr.getExpr());
            for (JExpression expr : multi.getExpressions()) {
              x.addStmt(i++, expr.makeStatement());
            }
            i = start - 1;
            continue;
          }
        }

        if (stmt.unconditionalControlBreak()) {
          // Abrupt change in flow, chop the remaining items from this block
          for (int j = i + 1; j < x.getStatements().size();) {
            x.removeStmt(j);
            madeChanges();
          }
        }
      }

      if (ctx.canRemove() && x.getStatements().size() == 0) {
        // Remove blocks with no effect
        ctx.removeMe();
      }
    }

    @Override
    public void endVisit(JCastOperation x, Context ctx) {
      maybeReplaceMe(x, Simplifier.simplifyCast(x), ctx);
    }

    @Override
    public void endVisit(JConditional x, Context ctx) {
      maybeReplaceMe(x, Simplifier.simplifyConditional(x), ctx);
    }

    @Override
    public void endVisit(JDeclarationStatement x, Context ctx) {
      JVariableRef variableRef = x.getVariableRef();
      lvalues.remove(variableRef);
    }

    /**
     * Convert do { } while (false); into a block.
     */
    @Override
    public void endVisit(JDoStatement x, Context ctx) {
      JExpression expression = x.getTestExpr();
      if (expression instanceof JBooleanLiteral) {
        JBooleanLiteral booleanLiteral = (JBooleanLiteral) expression;

        // If false, replace do with do's body
        if (!booleanLiteral.getValue()) {
          if (JjsUtils.isEmptyBlock(x.getBody())) {
            ctx.removeMe();
          } else { // Unless it contains break/continue statements
            FindBreakContinueStatementsVisitor visitor = new FindBreakContinueStatementsVisitor();
            visitor.accept(x.getBody());
            if (!visitor.hasBreakContinueStatements()) {
              ctx.replaceMe(x.getBody());
            }
          }
        }
      }
    }

    @Override
    public void endVisit(JExpressionStatement x, Context ctx) {
      ignoringExpressionOutput.remove(x.getExpr());
      if (!x.getExpr().hasSideEffects()) {
        removeMe(x, ctx);
      }
    }

    @Override
    public void endVisit(JFieldRef x, Context ctx) {

      if (x.getField() == enumOrdinalField) {
        maybeReplaceWithOrdinalValue(x.getInstance(), ctx);
        return;
      }

      JLiteral literal = tryGetConstant(x);
      if (literal == null && !ignoringExpressionOutput.contains(x)) {
        return;
      }
      /*
       * At this point, either we have a constant replacement, or our value is
       * irrelevant. We can inline the constant, if any, but we might also need
       * to evaluate an instance and run a clinit.
       */
      // We can inline the constant, but we might also need to evaluate an
      // instance and run a clinit.
      List<JExpression> exprs = Lists.newArrayList();

      JExpression instance = x.getInstance();
      if (instance != null) {
        exprs.add(instance);
      }

      if (x.hasClinit() && !x.getField().isCompileTimeConstant()) {
        // Access to compile time constants do not trigger class initialization (JLS 12.4.1).
        exprs.add(createClinitCall(x.getSourceInfo(), x.getField().getEnclosingType()));
      }

      if (literal != null) {
        exprs.add(literal);
      }

      JExpression replacement;
      if (exprs.size() == 1) {
        replacement = exprs.get(0);
      } else {
        replacement = new JMultiExpression(x.getSourceInfo(), exprs);
      }

      ctx.replaceMe(this.accept(replacement));
    }

    /**
     * Prune for (X; false; Y) statements, but make sure X is run.
     */
    @Override
    public void endVisit(JForStatement x, Context ctx) {
      JExpression expression = x.getCondition();
      if (expression instanceof JBooleanLiteral) {
        JBooleanLiteral booleanLiteral = (JBooleanLiteral) expression;

        // If false, replace the for statement with its initializers
        if (!booleanLiteral.getValue()) {
          JBlock block = new JBlock(x.getSourceInfo());
          block.addStmts(x.getInitializers());
          replaceMe(block, ctx);
        }
      }
    }

    /**
     * Simplify if statements.
     */
    @Override
    public void endVisit(JIfStatement x, Context ctx) {
      JType methodReturnType = getCurrentMethod() != null ? getCurrentMethod().getType() : null;
      maybeReplaceMe(x, Simplifier.simplifyIfStatement(x, methodReturnType), ctx);
    }

    /**
     * Simplify JInstanceOf expression whose output is ignored.
     */
    @Override
    public void endVisit(JInstanceOf x, Context ctx) {
      if (ignoringExpressionOutput.contains(x)) {
        ctx.replaceMe(x.getExpr());
        ignoringExpressionOutput.remove(x);
        return;
      }

      if (!(x.getExpr().getType() instanceof JReferenceType)) {
        return;
      }

      AnalysisResult analysisResult =
          staticallyEvaluateInstanceOf((JReferenceType) x.getExpr().getType(), x.getTestType());
      switch (analysisResult) {
        case TRUE:
          // replace with a simple null test:  (expr != null).
          ctx.replaceMe(
              JjsUtils.createOptimizedNotNullComparison(program, x.getSourceInfo(), x.getExpr()));
          break;
        case FALSE:
          // replace with a false literal
          ctx.replaceMe(JjsUtils.createOptimizedMultiExpression(x.getExpr(),
              program.getLiteralBoolean(false)));
          break;
        case UNKNOWN:
        default:
      }
    }

    @Override
    public void endVisit(JLocalRef x, Context ctx) {
      JLiteral literal = tryGetConstant(x);
      if (literal != null) {
        assert (!x.hasSideEffects());
        ctx.replaceMe(literal);
      }
    }

    /**
     * Resolve method calls that can be computed statically.
     */
    @Override
    public void endVisit(JMethodCall x, Context ctx) {
      // Restore ignored expressions.
      JMethod target = x.getTarget();
      JExpression instance = x.getInstance();
      if (target.isStatic() && instance != null) {
        ignoringExpressionOutput.remove(instance);
      }

      // Normal optimizations.
      JDeclaredType targetType = target.getEnclosingType();
      if (targetType == program.getTypeJavaLangString() ||
          (instance != null &&
              instance.getType().getUnderlyingType() == program.getTypeJavaLangString())) {
        tryOptimizeStringCall(x, ctx, target);
      } else if (JProgram.isClinit(target)) {
        // Eliminate the call if the target is now empty.
        if (!targetType.hasClinit()) {
          ctx.replaceMe(program.getLiteralNull());
        } else if (targetType != targetType.getClinitTarget()) {
          // Tighten the target.
          ctx.replaceMe(createClinitCall(x.getSourceInfo(), targetType.getClinitTarget()));
        }
      } else if (target == isScriptMethod) {
        // optimize out in draftCompiles that don't do inlining
        ctx.replaceMe(JBooleanLiteral.TRUE);
      } else if (target == enumOrdinalMethod) {
        maybeReplaceWithOrdinalValue(instance, ctx);
      }
    }

    /**
     * Remove any parts of JMultiExpression that have no side-effect.
     */
    @Override
    public void endVisit(JMultiExpression x, Context ctx) {
      List<JExpression> exprs = x.getExpressions();
      if (exprs.size() > 0) {
        if (ignoringExpressionOutput.contains(x)) {
          // Remove all my children we previously added.
          ignoringExpressionOutput.removeAll(exprs);
        } else {
          // Remove the non-final children we previously added.
          List<JExpression> nonFinalChildren = exprs.subList(0, exprs.size() - 1);
          ignoringExpressionOutput.removeAll(nonFinalChildren);
        }
      }

      HashSet<JDeclaredType> clinitsCalled = new HashSet<JDeclaredType>();
      for (int i = 0; i < numRemovableExpressions(x); ++i) {
        JExpression expr = x.getExpression(i);
        if (!expr.hasSideEffects()) {
          x.removeExpression(i);
          --i;
          madeChanges();
          continue;
        }

        // Remove nested JMultiExpressions
        if (expr instanceof JMultiExpression) {
          x.removeExpression(i);
          x.addExpressions(i, ((JMultiExpression) expr).getExpressions());
          i--;
          madeChanges();
          continue;
        }

        // Remove redundant clinits
        if (expr instanceof JMethodCall && JProgram.isClinit(((JMethodCall) expr).getTarget())) {
          JDeclaredType enclosingType = ((JMethodCall) expr).getTarget().getEnclosingType();
          // If a clinit of enclosingType or a subclass of enclosingType has already been
          // called as part of this JMultiExpression then this clinit call is noop at runtime
          // and can be statically removed.
          if (enclosingType.findSubtype(clinitsCalled) != null) {
            x.removeExpression(i);
            --i;
            madeChanges();
            continue;
          } else {
            clinitsCalled.add(enclosingType);
          }
        }
      }

      if (x.getNumberOfExpressions() == 1) {
        maybeReplaceMe(x, x.getExpressions().get(0), ctx);
      }
    }

    @Override
    public void endVisit(JNewInstance x, Context ctx) {
      super.endVisit(x, ctx);
      /*
       * If the result of a new operation is ignored, we can remove it, provided
       * it has no side effects.
       */
      if (ignoringExpressionOutput.contains(x)) {
        if (!x.getTarget().isEmpty()) {
          return;
        }
        JMultiExpression multi = new JMultiExpression(x.getSourceInfo());
        multi.addExpressions(x.getArgs());
        // Determine whether a new Blah() in this method needs a clinit.
        if (getCurrentMethod().getEnclosingType().checkClinitTo(x.getTarget().getEnclosingType())) {
          multi.addExpressions(
              createClinitCall(x.getSourceInfo(), x.getTarget().getEnclosingType()));
        }
        ignoringExpressionOutput.add(multi);
        ctx.replaceMe(this.accept(multi));
        ignoringExpressionOutput.remove(multi);
      }
    }

    @Override
    public void endVisit(JParameterRef x, Context ctx) {
      JLiteral literal = tryGetConstant(x);
      if (literal != null) {
        assert (!x.hasSideEffects());
        ctx.replaceMe(literal);
      }
    }

    /**
     * Replace post-inc/dec with pre-inc/dec if the result doesn't matter.
     */
    @Override
    public void endVisit(JPostfixOperation x, Context ctx) {
      if (x.getOp().isModifying()) {
        lvalues.remove(x.getArg());
      }

      if (isNonEmptyMultiExpression(x.getArg())) {
        List<JExpression> expressions = ((JMultiExpression) x.getArg()).getExpressions();
        JMultiExpression result = new JMultiExpression(x.getArg().getSourceInfo(),
            expressions.subList(0, expressions.size() - 1));
        result.addExpressions(new JPostfixOperation(x.getSourceInfo(), x.getOp(),
            expressions.get(expressions.size() - 1)));
        ctx.replaceMe(result);
        return;
      }

      if (ignoringExpressionOutput.contains(x)) {
        JPrefixOperation newOp = new JPrefixOperation(x.getSourceInfo(), x.getOp(), x.getArg());
        ctx.replaceMe(newOp);
      }
    }

    /**
     * Simplify the ! operator if possible.
     */
    @Override
    public void endVisit(JPrefixOperation x, Context ctx) {
      if (x.getOp().isModifying()) {
        lvalues.remove(x.getArg());
      }

      // If the argument is a multiexpression restructure it if possible.
      if (isNonEmptyMultiExpression(x.getArg())) {
        List<JExpression> expressions = ((JMultiExpression) x.getArg()).getExpressions();
        JMultiExpression result = new JMultiExpression(x.getArg().getSourceInfo(),
            expressions.subList(0, expressions.size() - 1));
        result.addExpressions(new JPrefixOperation(x.getSourceInfo(), x.getOp(),
            expressions.get(expressions.size() - 1)));
        ctx.replaceMe(result);
        return;
      }

      if (x.getArg() instanceof JValueLiteral) {
        if (evalOpOnLiteral(x.getOp(), (JValueLiteral) x.getArg(), ctx)) {
          return;
        }
      }

      if (x.getOp() == JUnaryOperator.NOT) {
        maybeReplaceMe(x, Simplifier.simplifyNot(x), ctx);
        return;
      } else if (x.getOp() == JUnaryOperator.NEG) {
        maybeReplaceMe(x, simplifyNegate(x, x.getArg()), ctx);
      }
    }

    /**
     * Optimize switch statements.
     */
    @Override
    public void endVisit(JSwitchStatement x, Context ctx) {
      switchBlocks.remove(x.getBody());

      // If it returns true, it was reduced to nothing
      if (tryReduceSwitchWithConstantInput(x, ctx)) {
        return;
      }

      if (hasNoDefaultCase(x)) {
        removeEmptyCases(x);
      }
      removeDoubleBreaks(x);
      tryRemoveSwitch(x, ctx);
    }

    /**
     * 1) Remove catch blocks whose exception type is not instantiable. 2) Prune
     * try statements with no body. 3) Hoist up try statements with no catches
     * and an empty finally.
     */
    @Override
    public void endVisit(JTryStatement x, Context ctx) {
      // 1) Remove catch blocks whose exception type is not instantiable.
      List<JTryStatement.CatchClause> catchClauses = x.getCatchClauses();

      Iterator<JTryStatement.CatchClause> itClauses = catchClauses.iterator();
      while (itClauses.hasNext()) {
        JTryStatement.CatchClause clause = itClauses.next();
        // Go over the types in the multiexception and remove the ones that are not instantiable.
        Iterator<JType> itTypes = clause.getTypes().iterator();
        while (itTypes.hasNext()) {
          JReferenceType type = (JReferenceType) itTypes.next();
          if (!program.typeOracle.isInstantiatedType(type) || type.isNullType()) {
            itTypes.remove();
            madeChanges();
          }
        }

        // if all exception types are gone then remove whole clause.
        if (clause.getTypes().isEmpty()) {
          itClauses.remove();
          madeChanges();
        }
      }

      // Compute properties regarding the state of this try statement
      boolean noTry = JjsUtils.isEmptyBlock(x.getTryBlock());
      boolean noCatch = catchClauses.size() == 0;
      boolean noFinally = JjsUtils.isEmptyBlock(x.getFinallyBlock());

      if (noTry) {
        // 2) Prune try statements with no body.
        if (noFinally) {
          // if there's no finally, prune the whole thing
          removeMe(x, ctx);
        } else {
          // replace the try statement with just the contents of the finally
          replaceMe(x.getFinallyBlock(), ctx);
        }
      } else if (noCatch && noFinally) {
        // 3) Hoist up try statements with no catches and an empty finally.
        // If there's no catch or finally, there's no point in this even being
        // a try statement, replace myself with the try block
        replaceMe(x.getTryBlock(), ctx);
      }
    }

    /**
     * Prune while (false) statements.
     */
    @Override
    public void endVisit(JWhileStatement x, Context ctx) {
      JExpression expression = x.getTestExpr();
      if (expression instanceof JBooleanLiteral) {
        JBooleanLiteral booleanLiteral = (JBooleanLiteral) expression;

        // If false, prune the while statement
        if (!booleanLiteral.getValue()) {
          removeMe(x, ctx);
        }
      }
    }

    @Override
    public boolean visit(JBinaryOperation x, Context ctx) {
      if (x.getOp().isAssignment()) {
        lvalues.add(x.getLhs());
      }
      return true;
    }

    @Override
    public boolean visit(JClassType x, Context ctx) {
      // We can't eliminate code from an external type
      return !x.isExternal();
    }

    @Override
    public boolean visit(JDeclarationStatement x, Context ctx) {
      lvalues.add(x.getVariableRef());
      return true;
    }

    @Override
    public boolean visit(JExpressionStatement x, Context ctx) {
      ignoringExpressionOutput.add(x.getExpr());
      return true;
    }

    @Override
    public boolean visit(JMethodCall x, Context ctx) {
      JMethod target = x.getTarget();
      if (target.isStatic() && x.getInstance() != null) {
        ignoringExpressionOutput.add(x.getInstance());
      }
      return true;
    }

    @Override
    public boolean visit(JMultiExpression x, Context ctx) {
      List<JExpression> exprs = x.getExpressions();
      if (exprs.size() > 0) {
        if (ignoringExpressionOutput.contains(x)) {
          // None of my children matter.
          ignoringExpressionOutput.addAll(exprs);
        } else {
          // Only my final child matters.
          List<JExpression> nonFinalChildren = exprs.subList(0, exprs.size() - 1);
          ignoringExpressionOutput.addAll(nonFinalChildren);
        }
      }
      return true;
    }

    @Override
    public boolean visit(JPostfixOperation x, Context ctx) {
      if (x.getOp().isModifying()) {
        lvalues.add(x.getArg());
      }
      return true;
    }

    @Override
    public boolean visit(JPrefixOperation x, Context ctx) {
      if (x.getOp().isModifying()) {
        lvalues.add(x.getArg());
      }
      return true;
    }

    @Override
    public boolean visit(JSwitchStatement x, Context ctx) {
      switchBlocks.add(x.getBody());
      return true;
    }

    /**
     * Returns true if a block can be merged into its parent block. This is true
     * when the block contains no local declarations.
     */
    private boolean canPromoteBlock(JBlock block) {
      for (JStatement nestedStmt : block.getStatements()) {
        if (nestedStmt instanceof JDeclarationStatement) {
          JDeclarationStatement decl = (JDeclarationStatement) nestedStmt;
          if (decl.getVariableRef() instanceof JLocalRef) {
            return false;
          }
        }
      }
      return true;
    }

    private JMethodCall createClinitCall(SourceInfo sourceInfo, JDeclaredType targetType) {
      JMethod clinit = targetType.getClinitTarget().getClinitMethod();
      assert (JProgram.isClinit(clinit));
      return new JMethodCall(sourceInfo, null, clinit);
    }

    private void evalConcat(SourceInfo info, JExpression lhs, JExpression rhs, Context ctx) {
      if (lhs instanceof JValueLiteral && rhs instanceof JValueLiteral) {
        Object lhsObj = ((JValueLiteral) lhs).getValueObj();
        Object rhsObj = ((JValueLiteral) rhs).getValueObj();
        ctx.replaceMe(program.getStringLiteral(info, String.valueOf(lhsObj)
            + String.valueOf(rhsObj)));
      }
    }

    /**
     * Evaluate <code>lhs == rhs</code>.
     *
     * @param lhs Any literal.
     * @param rhs Any literal.
     * @return Whether <code>lhs == rhs</code> will evaluate to
     *         <code>true</code> at run time; string literal comparisons use .equals() semantics.
     */
    private boolean evalEq(JValueLiteral lhs, JValueLiteral rhs) {
      if (isTypeNull(lhs)) {
        return isTypeNull(rhs);
      }
      if (isTypeString(lhs)) {
        return isTypeString(rhs) &&
            ((JStringLiteral) lhs).getValue().equals(((JStringLiteral) rhs).getValue());
      }
      if (isTypeBoolean(lhs)) {
        return toBoolean(lhs) == toBoolean(rhs);
      }
      if (isTypeFloatingPoint(lhs) || isTypeFloatingPoint(rhs)) {
        return Ieee754_64_Arithmetic.eq(toDouble(lhs), toDouble(rhs));
      }
      if (isTypeLong(lhs) || isTypeLong(rhs)) {
        return toLong(lhs) == toLong(rhs);
      }
      return toInt(lhs) == toInt(rhs);
    }

    /**
     * Static evaluation of a unary operation on a literal.
     *
     * @return Whether a change was made
     */
    private boolean evalOpOnLiteral(JUnaryOperator op, JValueLiteral exp, Context ctx) {
      switch (op) {
        case BIT_NOT: {
          long value = toLong(exp);
          long res = ~value;
          if (isTypeLong(exp)) {
            ctx.replaceMe(program.getLiteralLong(res));
          } else {
            ctx.replaceMe(program.getLiteralInt((int) res));
          }
          return true;
        }

        case NEG:
          if (isTypeLong(exp)) {
            ctx.replaceMe(program.getLiteralLong(-toLong(exp)));
            return true;
          }
          if (isTypeIntegral(exp)) {
            ctx.replaceMe(program.getLiteralInt(-toInt(exp)));
            return true;
          }
          if (isTypeDouble(exp)) {
            ctx.replaceMe(program.getLiteralDouble(Ieee754_64_Arithmetic.neg(toDouble(exp))));
            return true;
          }
          if (isTypeFloat(exp)) {
            ctx.replaceMe(program.getLiteralFloat(Ieee754_64_Arithmetic.neg(toDouble(exp))));
            return true;
          }
          return false;

        case NOT: {
          JBooleanLiteral booleanLit = (JBooleanLiteral) exp;
          ctx.replaceMe(program.getLiteralBoolean(!booleanLit.getValue()));
          return true;
        }

        default:
          return false;
      }
    }

    /**
     * Static evaluation of a binary operation on two literals.
     *
     * @return Whether a change was made
     */
    private boolean evalOpOnLiterals(JBinaryOperator op, JValueLiteral lhs, JValueLiteral rhs,
        Context ctx) {
      switch (op) {
        case EQ: {
          ctx.replaceMe(program.getLiteralBoolean(evalEq(lhs, rhs)));
          return true;
        }

        case NEQ: {
          ctx.replaceMe(program.getLiteralBoolean(!evalEq(lhs, rhs)));
          return true;
        }

        case ADD:
        case SUB:
        case MUL:
        case DIV:
        case MOD: {
          if (isTypeFloatingPoint(lhs) || isTypeFloatingPoint(rhs)) {
            // do the op on doubles and cast back
            double left = toDouble(lhs);
            double right = toDouble(rhs);
            double res;
            switch (op) {
              case ADD:
                res = Ieee754_64_Arithmetic.add(left, right);
                break;
              case SUB:
                res = Ieee754_64_Arithmetic.subtract(left, right);
                break;
              case MUL:
                res = Ieee754_64_Arithmetic.multiply(left, right);
                break;
              case DIV:
                res = Ieee754_64_Arithmetic.divide(left, right);
                break;
              case MOD:
                res = Ieee754_64_Arithmetic.mod(left, right);
                break;
              default:
                assert false;
                return false;
            }
            if (isTypeDouble(lhs) || isTypeDouble(rhs)) {
              ctx.replaceMe(program.getLiteralDouble(res));
            } else {
              ctx.replaceMe(program.getLiteralFloat(res));
            }
            return true;
          } else if (isTypeIntegral(lhs) && isTypeIntegral(rhs)) {
            // do the op on longs and cast to the correct
            // result type at the end
            long left = toLong(lhs);
            long right = toLong(rhs);

            long res;
            switch (op) {
              case ADD:
                res = left + right;
                break;
              case SUB:
                res = left - right;
                break;
              case MUL:
                res = left * right;
                break;
              case DIV:
                if (right == 0) {
                  // Don't divide by zero
                  return false;
                }
                res = left / right;
                break;
              case MOD:
                if (right == 0) {
                  // Don't divide by zero
                  return false;
                }
                res = left % right;
                break;
              default:
                assert false;
                return false;
            }
            if (isTypeLong(lhs) || isTypeLong(rhs)) {
              ctx.replaceMe(program.getLiteralLong(res));
            } else {
              ctx.replaceMe(program.getLiteralInt((int) res));
            }
            return true;
          }
          return false;
        }
        case LT:
        case LTE:
        case GT:
        case GTE: {
          if (isTypeFloatingPoint(lhs) || isTypeFloatingPoint(rhs)) {
            // operate on doubles
            double left = toDouble(lhs);
            double right = toDouble(rhs);
            boolean res;
            switch (op) {
              case LT:
                res = Ieee754_64_Arithmetic.lt(left, right);
                break;
              case LTE:
                res = Ieee754_64_Arithmetic.le(left, right);
                break;
              case GT:
                res = Ieee754_64_Arithmetic.gt(left, right);
                break;
              case GTE:
                res = Ieee754_64_Arithmetic.ge(left, right);
                break;
              default:
                assert false;
                return false;
            }
            ctx.replaceMe(program.getLiteralBoolean(res));
            return true;
          } else if (isTypeIntegral(lhs) && isTypeIntegral(rhs)) {
            // operate on longs
            long left = toLong(lhs);
            long right = toLong(rhs);
            boolean res;
            switch (op) {
              case LT:
                res = left < right;
                break;
              case LTE:
                res = left <= right;
                break;
              case GT:
                res = left > right;
                break;
              case GTE:
                res = left >= right;
                break;
              default:
                assert false;
                return false;
            }
            ctx.replaceMe(program.getLiteralBoolean(res));
            return true;
          }
          return false;
        }
        case BIT_AND:
        case BIT_OR:
        case BIT_XOR:
          if (isTypeBoolean(lhs)) {
            // TODO: maybe eval non-short-circuit boolean operators.
            return false;
          } else if (isTypeIntegral(lhs) && isTypeIntegral(rhs)) {
            // operate on longs and then cast down
            long left = toLong(lhs);
            long right = toLong(rhs);
            long res;
            switch (op) {
              case BIT_AND:
                res = left & right;
                break;

              case BIT_OR:
                res = left | right;
                break;

              case BIT_XOR:
                res = left ^ right;
                break;

              default:
                assert false;
                return false;
            }
            if (isTypeLong(lhs) || isTypeLong(rhs)) {
              ctx.replaceMe(program.getLiteralLong(res));
            } else {
              ctx.replaceMe(program.getLiteralInt((int) res));
            }
            return true;
          }
          return false;
        case SHL:
        case SHR:
        case SHRU: {
          if (isTypeLong(lhs)) {
            long left = toLong(lhs);
            int right = toInt(rhs);
            long res;
            switch (op) {
              case SHL:
                res = left << right;
                break;

              case SHR:
                res = left >> right;
                break;

              case SHRU:
                res = left >>> right;
                break;

              default:
                assert false;
                return false;
            }

            ctx.replaceMe(program.getLiteralLong(res));
            return true;
          } else if (isTypeIntegral(lhs) && isTypeIntegral(rhs)) {
            int left = toInt(lhs);
            int right = toInt(rhs);
            int res;
            switch (op) {
              case SHL:
                res = left << right;
                break;

              case SHR:
                res = left >> right;
                break;

              case SHRU:
                res = left >>> right;
                break;

              default:
                assert false;
                return false;
            }

            ctx.replaceMe(program.getLiteralInt(res));
            return true;
          }
          return false;
        }
        default:
          return false;
      }
    }

    /**
     * If the effect of <code>statement</code> is to immediately do a break,
     * then return the {@link JBreakStatement} corresponding to that break.
     */
    private JBreakStatement findUnconditionalBreak(JStatement statement) {
      if (statement instanceof JBreakStatement) {
        return (JBreakStatement) statement;
      } else if (statement instanceof JBlock) {
        JBlock block = (JBlock) statement;
        List<JStatement> blockStmts = block.getStatements();
        if (blockStmts.size() > 0 && isUnconditionalBreak(blockStmts.get(0))) {
          return (JBreakStatement) blockStmts.get(0);
        }
      }
      return null;
    }

    /**
     * Tries to removes cases and statements from switches whose expression is a
     * constant value.
     *
     * @return true, if the switch was completely eliminated
     */
    private boolean tryReduceSwitchWithConstantInput(JSwitchStatement s, Context ctx) {
      if (!(s.getExpr() instanceof JValueLiteral)) {
        // the input is not a constant
        return false;
      }
      JValueLiteral targetValue = (JValueLiteral) s.getExpr();

      // Find the matching case
      JCaseStatement matchingCase = null;
      for (JStatement subStatement : s.getBody().getStatements()) {
        if (subStatement instanceof JCaseStatement) {
          JCaseStatement caseStatement = (JCaseStatement) subStatement;
          if (caseStatement.getExpr() == null) {
            // speculatively put the default case into the matching case
            matchingCase = caseStatement;
          } else if (caseStatement.getExpr() instanceof JValueLiteral) {
            JValueLiteral caseValue = (JValueLiteral) caseStatement.getExpr();
            if (caseValue.getValueObj().equals(targetValue.getValueObj())) {
              matchingCase = caseStatement;
              break;
            }
          }
        }
      }

      if (matchingCase == null) {
        // the switch has no default and no matching cases
        // the expression is a value literal, so it can go away completely
        removeMe(s, ctx);
        return true;
      }

      Iterator<JStatement> it = s.getBody().getStatements().iterator();

      // Remove things until we find the matching case
      while (it.hasNext() && (it.next() != matchingCase)) {
        it.remove();
        madeChanges();
      }

      // Until an unconditional control break, preserve everything that isn't a case
      // or default.
      while (it.hasNext()) {
        JStatement statement = it.next();
        if (statement.unconditionalControlBreak()) {
          break;
        } else if (statement instanceof JCaseStatement) {
          it.remove();
        }
      }

      // having found a break or return (or reached the end), remove all remaining
      while (it.hasNext()) {
        it.next();
        it.remove();
        madeChanges();
      }

      return false;
    }

    private boolean hasNoDefaultCase(JSwitchStatement x) {
      JBlock body = x.getBody();
      boolean inDefault = false;
      for (JStatement statement : body.getStatements()) {
        if (statement instanceof JCaseStatement) {
          JCaseStatement caseStmt = (JCaseStatement) statement;
          if (caseStmt.getExpr() == null) {
            inDefault = true;
          }
        } else if (isUnconditionalUnlabeledBreak(statement)) {
          inDefault = false;
        } else {
          // We have some code to execute other than a break.
          if (inDefault) {
            // We have a default case with real code.
            return false;
          }
        }
      }
      // We found no default case that wasn't empty.
      return true;
    }

    private boolean isLiteralNegativeOne(JExpression exp) {
      if (!(exp instanceof JValueLiteral)) {
        return false;
      }
      JValueLiteral lit = (JValueLiteral) exp;
      if (isTypeIntegral(lit) && toLong(lit) == -1) {
        return true;
      }
      if (isTypeFloatingPoint(lit) && toDouble(lit) == -1.0) {
        return true;
      }
      return false;
    }

    private boolean isLiteralOne(JExpression exp) {
      if (!(exp instanceof JValueLiteral)) {
        return false;
      }
      JValueLiteral lit = (JValueLiteral) exp;
      if (isTypeIntegral(lit) && toLong(lit) == 1) {
        return true;
      }
      return isTypeFloatingPoint(lit) && toDouble(lit) == 1.0;
    }

    private boolean isLiteralZero(JExpression exp) {
      if (exp instanceof JValueLiteral) {
        JValueLiteral lit = (JValueLiteral) exp;
        if (toDouble(lit) == 0.0) {
          // Using toDouble only is safe even for integer types. All types but
          // long will keep full precision. Longs will lose precision, but
          // it will not affect whether the resulting double is zero or not.
          return true;
        }
      }
      return false;
    }

    private boolean isTypeBoolean(JExpression lhs) {
      return lhs.getType() == program.getTypePrimitiveBoolean();
    }

    private boolean isTypeDouble(JExpression exp) {
      return isTypeDouble(exp.getType());
    }

    private boolean isTypeDouble(JType type) {
      return type == program.getTypePrimitiveDouble();
    }

    private boolean isTypeFloat(JExpression exp) {
      return isTypeFloat(exp.getType());
    }

    private boolean isTypeFloat(JType type) {
      return type == program.getTypePrimitiveFloat();
    }

    /**
     * Return whether the type of the expression is float or double.
     */
    private boolean isTypeFloatingPoint(JExpression exp) {
      return isTypeFloatingPoint(exp.getType());
    }

    private boolean isTypeFloatingPoint(JType type) {
      return ((type == program.getTypePrimitiveDouble()) || (type == program
          .getTypePrimitiveFloat()));
    }

    /**
     * Return whether the type of the expression is byte, char, short, int, or
     * long.
     */
    private boolean isTypeIntegral(JExpression exp) {
      return isTypeIntegral(exp.getType());
    }

    private boolean isTypeIntegral(JType type) {
      return ((type == program.getTypePrimitiveInt()) || (type == program.getTypePrimitiveLong())
          || (type == program.getTypePrimitiveChar()) || (type == program.getTypePrimitiveByte())
          || (type == program.getTypePrimitiveShort()));
    }

    private boolean isTypeLong(JExpression exp) {
      return isTypeLong(exp.getType());
    }

    private boolean isTypeLong(JType type) {
      return type == program.getTypePrimitiveLong();
    }

    private boolean isTypeNull(JExpression exp) {
      return isTypeNull(exp.getType());
    }

    private boolean isTypeNull(JType type) {
      return type.isNullType();
    }

    private boolean isTypeString(JExpression exp) {
      return program.isJavaLangString(exp.getType());
    }

    private boolean isUnconditionalBreak(JStatement statement) {
      return findUnconditionalBreak(statement) != null;
    }

    private boolean isUnconditionalUnlabeledBreak(JStatement statement) {
      JBreakStatement breakStat = findUnconditionalBreak(statement);
      return (breakStat != null) && (breakStat.getLabel() == null);
    }

    private <T> T last(List<T> statements) {
      return statements.get(statements.size() - 1);
    }

    private Class<?> classObjectForType(JType type) {
      return classObjectsByType.get(type);
    }

    /**
     * Replace me only if the updated expression is different.
     */
    private void maybeReplaceMe(JExpression x, JExpression updated, Context ctx) {
      if (updated != x) {
        ctx.replaceMe(updated);
      }
    }

    private void maybeReplaceMe(JStatement x, JStatement updated, Context ctx) {
      if (updated != x) {
        replaceMe(updated, ctx);
      }
    }

    private void maybeReplaceWithOrdinalValue(JExpression instanceExpr, Context ctx) {
      if (!(instanceExpr instanceof JFieldRef)) {
        return;
      }

      JFieldRef fieldRef = (JFieldRef) instanceExpr;
      if (!(fieldRef.getField() instanceof JEnumField)) {
        return;
      }

      assert fieldRef.getInstance() == null;
      JEnumField enumField = (JEnumField) fieldRef.getField();
      ctx.replaceMe(program.getLiteralInt(enumField.ordinal()));
    }

    private int numRemovableExpressions(JMultiExpression x) {
      if (ignoringExpressionOutput.contains(x)) {
        // The result doesn't matter: all expressions can be removed.
        return x.getNumberOfExpressions();
      } else {
        // The last expression cannot be removed.
        return x.getNumberOfExpressions() - 1;
      }
    }

    /**
     * Removes any break statements that appear one after another.
     */
    private void removeDoubleBreaks(JSwitchStatement x) {
      JBlock body = x.getBody();
      boolean lastWasBreak = true;
      for (int i = 0; i < body.getStatements().size(); ++i) {
        JStatement statement = body.getStatements().get(i);
        boolean isBreak = isUnconditionalBreak(statement);
        if (isBreak && lastWasBreak) {
          body.removeStmt(i--);
          madeChanges();
        }
        lastWasBreak = isBreak;
      }

      // Remove a trailing break statement from a case block
      if (body.getStatements().size() > 0
          && isUnconditionalUnlabeledBreak(last(body.getStatements()))) {
        body.removeStmt(body.getStatements().size() - 1);
        madeChanges();
      }
    }

    /**
     * A switch with no default case can have its empty cases pruned.
     */
    private void removeEmptyCases(JSwitchStatement x) {
      JBlock body = x.getBody();
      List<JStatement> noOpCaseStatements = new ArrayList<JStatement>();
      List<JStatement> potentialNoOpCaseStatements = new ArrayList<JStatement>();
      /*
       * A case statement has no effect if there is no code between it and
       * either an unconditional break or the end of the switch.
       */
      for (JStatement statement : body.getStatements()) {
        if (statement instanceof JCaseStatement) {
          potentialNoOpCaseStatements.add(statement);
        } else if (isUnconditionalUnlabeledBreak(statement)) {
          // If we have any potential no-ops, they now become real no-ops.
          noOpCaseStatements.addAll(potentialNoOpCaseStatements);
          potentialNoOpCaseStatements.clear();
        } else {
          // Any other kind of statement makes these case statements are useful.
          potentialNoOpCaseStatements.clear();
        }
      }
      // None of the remaining case statements have any effect
      noOpCaseStatements.addAll(potentialNoOpCaseStatements);

      if (noOpCaseStatements.size() > 0) {
        for (JStatement statement : noOpCaseStatements) {
          body.removeStmt(body.getStatements().indexOf(statement));
          madeChanges();
        }
      }
    }

    /**
     * Call this instead of directly calling <code>ctx.removeMe()</code> for
     * Statements.
     */
    private void removeMe(JStatement stmt, Context ctx) {
      if (ctx.canRemove()) {
        ctx.removeMe();
      } else {
        // empty block statement
        ctx.replaceMe(new JBlock(stmt.getSourceInfo()));
      }
    }

    /**
     *
     * Call this instead of directly calling <code>ctx.replaceMe()</code> for
     * Statements.
     */
    private void replaceMe(JStatement stmt, Context ctx) {
      stmt = this.accept(stmt, ctx.canRemove());
      if (stmt == null) {
        ctx.removeMe();
      } else {
        ctx.replaceMe(stmt);
      }
    }

    private boolean simplifyAdd(JExpression lhs, JExpression rhs, Context ctx, JType type) {
      if (isLiteralZero(rhs)) {
        ctx.replaceMe(Simplifier.cast(type, lhs));
        return true;
      }
      if (isLiteralZero(lhs)) {
        ctx.replaceMe(Simplifier.cast(type, rhs));
        return true;
      }

      return false;
    }

    /**
     * Simplify <code>exp == bool</code>, where <code>bool</code> is a boolean
     * literal.
     */
    private void simplifyBooleanEq(JExpression exp, boolean bool, Context ctx) {
      if (bool) {
        ctx.replaceMe(exp);
      } else {
        ctx.replaceMe(new JPrefixOperation(exp.getSourceInfo(), JUnaryOperator.NOT, exp));
      }
    }

    /**
     * Simplify <code>lhs == rhs</code>, where <code>lhs</code> and
     * <code>rhs</code> are known to be boolean. If <code>negate</code> is
     * <code>true</code>, then treat it as <code>lhs != rhs</code> instead of
     * <code>lhs == rhs</code>. Assumes that the case where both sides are
     * literals has already been checked.
     */
    private void simplifyBooleanEq(JExpression lhs, JExpression rhs, Context ctx, boolean negate) {
      if (lhs instanceof JBooleanLiteral) {
        boolean left = ((JBooleanLiteral) lhs).getValue();
        simplifyBooleanEq(rhs, left ^ negate, ctx);
        return;
      }
      if (rhs instanceof JBooleanLiteral) {
        boolean right = ((JBooleanLiteral) rhs).getValue();
        simplifyBooleanEq(lhs, right ^ negate, ctx);
        return;
      }
    }

    private boolean simplifyDiv(JExpression lhs, JExpression rhs, Context ctx, JType type) {
      if (isLiteralOne(rhs)) {
        ctx.replaceMe(Simplifier.cast(type, lhs));
        return true;
      }
      if (isLiteralNegativeOne(rhs)) {
        ctx.replaceMe(simplifyNegate(Simplifier.cast(type, lhs)));
        return true;
      }

      return false;
    }

    private AnalysisResult staticallyEvaluateEq(JExpression lhs, JExpression rhs) {
      JType lhsType = lhs.getType();
      JType rhsType = rhs.getType();
      if (lhsType.isNullType() && rhsType.isNullType()) {
        return AnalysisResult.TRUE;
      }
      if (lhsType.isNullType() && !rhsType.canBeNull() ||
          rhsType.isNullType() && !lhsType.canBeNull()) {
        return AnalysisResult.FALSE;
      }
      if (!lhsType.canBeSubclass() && !rhsType.canBeSubclass() &&
          !lhsType.canBeNull() && !rhsType.canBeNull() && lhsType instanceof JReferenceType &&
          lhsType.getUnderlyingType() != rhsType.getUnderlyingType()) {
        // We can conclude that lhs != rhs via type compatibility. If both lhs and rhs are typed
        // as exact and not null then if the underlying types are different the comparison clearly
        // fails.
        return AnalysisResult.FALSE;
      }
      return AnalysisResult.UNKNOWN;
    }

    /**
     * Tries to statically evaluate the instanceof operation. Returning TRUE if it can be determined
     * statically that it is true when not null, FALSE if it can be determined that is false and
     * UNKNOWN if the* result can not be determined statically.
     */
    private AnalysisResult staticallyEvaluateInstanceOf(JReferenceType fromType,
        JReferenceType toType) {
      if (fromType.isNullType()) {
        // null is never instanceof anything
        return AnalysisResult.FALSE;
      } else if (program.typeOracle.castSucceedsTrivially(fromType, toType)) {
        return AnalysisResult.TRUE;
      } else if (!program.typeOracle.isInstantiatedType(toType)) {
        return AnalysisResult.FALSE;
      } else if (program.typeOracle.castFailsTrivially(fromType, toType)) {
        return AnalysisResult.FALSE;
      }
      return AnalysisResult.UNKNOWN;
    }

    /**
     * Simplify <code>lhs == rhs</code>. If <code>negate</code> is true, then
     * it's actually static evaluation of <code>lhs != rhs</code>.
     */
    private void simplifyEq(JExpression lhs, JExpression rhs, Context ctx, boolean negate) {
      // simplify: null == null -> true
      AnalysisResult analysisResult = staticallyEvaluateEq(lhs, rhs);
      if (analysisResult != AnalysisResult.UNKNOWN) {
        ctx.replaceMe(JjsUtils.createOptimizedMultiExpression(
            lhs, rhs, program.getLiteralBoolean(negate ^ (analysisResult == AnalysisResult.TRUE))));
        return;
      }

      if (isTypeBoolean(lhs) && isTypeBoolean(rhs)) {
        simplifyBooleanEq(lhs, rhs, ctx, negate);
        return;
      }
    }

    private boolean simplifyMul(JExpression lhs, JExpression rhs, Context ctx, JType type) {
      if (isLiteralOne(rhs)) {
        ctx.replaceMe(Simplifier.cast(type, lhs));
        return true;
      }
      if (isLiteralOne(lhs)) {
        ctx.replaceMe(Simplifier.cast(type, rhs));
        return true;
      }
      if (isLiteralNegativeOne(rhs)) {
        ctx.replaceMe(simplifyNegate(Simplifier.cast(type, lhs)));
        return true;
      }
      if (isLiteralNegativeOne(lhs)) {
        ctx.replaceMe(simplifyNegate(Simplifier.cast(type, rhs)));
        return true;
      }
      if (isLiteralZero(rhs) && !lhs.hasSideEffects()) {
        ctx.replaceMe(Simplifier.cast(type, rhs));
        return true;
      }
      if (isLiteralZero(lhs) && !rhs.hasSideEffects()) {
        ctx.replaceMe(Simplifier.cast(type, lhs));
        return true;
      }
      return false;
    }

    private JExpression simplifyNegate(JExpression exp) {
      return simplifyNegate(null, exp);
    }

    /**
     * Simplify the expression <code>-exp</code>.
     *
     * @param original An expression equivalent to <code>-exp</code>.
     * @param exp The expression to negate.
     *
     * @return A simplified expression equivalent to <code>- exp</code>.
     */
    private JExpression simplifyNegate(JExpression original, JExpression exp) {
      // - -x -> x
      if (exp instanceof JPrefixOperation) {
        JPrefixOperation prefarg = (JPrefixOperation) exp;
        if (prefarg.getOp() == JUnaryOperator.NEG) {
          return prefarg.getArg();
        }
      }

      // no change
      if (original != null) {
        return original;
      }
      return new JPrefixOperation(exp.getSourceInfo(), JUnaryOperator.NEG, exp);
    }

    private boolean simplifySub(JExpression lhs, JExpression rhs, Context ctx, JType type) {
      if (isLiteralZero(rhs)) {
        ctx.replaceMe(Simplifier.cast(type, lhs));
        return true;
      }
      if (isLiteralZero(lhs) && !isTypeFloatingPoint(type)) {
        ctx.replaceMe(simplifyNegate(Simplifier.cast(type, rhs)));
        return true;
      }
      return false;
    }

    private void simplifyXor(JExpression lhs, JBooleanLiteral rhs, Context ctx) {
      if (rhs.getValue()) {
        ctx.replaceMe(new JPrefixOperation(lhs.getSourceInfo(), JUnaryOperator.NOT, lhs));
      } else {
        ctx.replaceMe(lhs);
      }
    }

    /**
     * Simplify XOR expressions.
     *
     * <pre>
     * true ^ x     -> !x
     * false ^ x    ->  x
     * y ^ true     -> !y
     * y ^ false    -> y
     * </pre>
     */
    private void simplifyXor(JExpression lhs, JExpression rhs, Context ctx) {
      if (lhs instanceof JBooleanLiteral) {
        JBooleanLiteral booleanLiteral = (JBooleanLiteral) lhs;
        simplifyXor(rhs, booleanLiteral, ctx);
      } else if (rhs instanceof JBooleanLiteral) {
        JBooleanLiteral booleanLiteral = (JBooleanLiteral) rhs;
        simplifyXor(lhs, booleanLiteral, ctx);
      }
    }

    private boolean toBoolean(JValueLiteral x) {
      return ((JBooleanLiteral) x).getValue();
    }

    /**
     * Cast a Java wrapper class (Integer, Double, Float, etc.) to a double.
     */
    private double toDouble(JValueLiteral literal) {
      Object valueObj = literal.getValueObj();
      if (valueObj instanceof Number) {
        return ((Number) valueObj).doubleValue();
      } else {
        return ((Character) valueObj).charValue();
      }
    }

    /**
     * Cast a Java wrapper class (Integer, Double, Float, etc.) to a long.
     */
    private int toInt(JValueLiteral literal) {
      Object valueObj = literal.getValueObj();
      if (valueObj instanceof Number) {
        return ((Number) valueObj).intValue();
      } else {
        return ((Character) valueObj).charValue();
      }
    }

    /**
     * Cast a Java wrapper class (Integer, Double, Float, etc.) to a long.
     */
    private long toLong(JValueLiteral literal) {
      Object valueObj = literal.getValueObj();
      if (valueObj instanceof Number) {
        return ((Number) valueObj).longValue();
      } else {
        return ((Character) valueObj).charValue();
      }
    }

    private JLiteral tryGetConstant(JVariableRef x) {
      if (!lvalues.contains(x)) {
        JLiteral lit = x.getTarget().getConstInitializer();
        if (lit != null) {
          /*
           * Upcast the initializer so that the semantics of any arithmetic on
           * this value is not changed.
           */
          // TODO(spoon): use Simplifier.cast to shorten this
          if (x.getType().isPrimitiveType() && (lit instanceof JValueLiteral)) {
            JPrimitiveType xTypePrim = (JPrimitiveType) x.getType();
            lit = xTypePrim.coerce((JValueLiteral) lit);
          }
          return lit;
        }
      }
      return null;
    }

    /**
     * Replace String methods having literal args with the static result.
     */
    private void tryOptimizeStringCall(JMethodCall x, Context ctx, JMethod method) {

      if (method.getType() == program.getTypeVoid()) {
        return;
      }

      if (method.getOriginalParamTypes().size() != method.getParams().size()) {
        // One or more parameters were pruned, abort.
        return;
      }

      if (method.getName().endsWith("hashCode")) {
        // This cannot be computed at compile time because our implementation
        // differs from the JRE.
        // TODO: actually, I think it DOES match now, so we can remove this?
        return;
      }

      boolean isStaticImplMethod = program.isStaticImpl(method);
      JExpression instance = isStaticImplMethod ? x.getArgs().get(0) : x.getInstance();
      // drop the instance argument if the call was devirtualized as the compile time evaluation
      // will use the real Java String class.
      List<JExpression> arguments = isStaticImplMethod
          ? x.getArgs().subList(1, x.getArgs().size())
          : x.getArgs();

      // Handle toString specially to make sure it is a noop on non null string objects.
      if (method.getName().endsWith("toString")) {
        // replaces s.toString() with s
        if (!instance.getType().canBeNull()) {
          // Only replace when it known to be non null, otherwise it should follow the normal path
          // and throw an NPE if null at runtime.
          ctx.replaceMe(instance);
        }
        return;
      }

      Object instanceLiteral = tryTranslateLiteral(instance, String.class);
      method = isStaticImplMethod ? program.instanceMethodForStaticImpl(method) : method;

      if (instanceLiteral == null && !method.isStatic()) {
        // Instance method on an instance that was not a literal.
        return;
      }

      // Extract constant values from arguments or bail out if not possible, and also extract the
      // declared parameter types that will be used to get the correct override.
      int numberOfParameters = method.getOriginalParamTypes().size();
      Object[] argumentConstantValues = new Object[numberOfParameters];
      Class<?>[] parametersClasses = new Class<?>[numberOfParameters];
      for (int i = 0; i < numberOfParameters; i++) {
        parametersClasses[i] = classObjectForType(method.getOriginalParamTypes().get(i));
        argumentConstantValues[i] = tryTranslateLiteral(arguments.get(i), parametersClasses[i]);
        if (parametersClasses[i] == null || argumentConstantValues[i] == null) {
          //  not a literal, cannot evaluate statically.
          return;
        }
      }

      // Finally invoke the method statically.
      JLiteral resultValue = staticallyInvokeStringMethod(
          method.getName(), instanceLiteral, parametersClasses, argumentConstantValues);
      if (resultValue != null) {
        ctx.replaceMe(resultValue);
      }
    }

    private JLiteral staticallyInvokeStringMethod(
        String methodName, Object instance, Class<?>[] parameterClasses, Object[] argumentValues) {
      Method actualMethod = getMethod(methodName, String.class, parameterClasses);
      if (actualMethod == null) {
        // Convert all parameters types to Object to find a more generic applicable method.
        Arrays.fill(parameterClasses, Object.class);
        actualMethod = getMethod(methodName, String.class, parameterClasses);
      }
      if (actualMethod == null) {
        return null;
      }

      try {
        return program.getLiteral(actualMethod.invoke(instance, argumentValues));
      } catch (Exception e) {
        // couldn't evaluate statically or convert the result to a JLiteral
        return  null;
      }
    }

    private Method getMethod(String name, Class<?> enclosingClass, Class<?>[] parameterTypes) {
      try {
        return enclosingClass.getMethod(name, parameterTypes);
      } catch (NoSuchMethodException e) {
        return null;
      }
    }

    private void tryRemoveSwitch(JSwitchStatement x, Context ctx) {
      JBlock body = x.getBody();
      if (body.getStatements().size() == 0) {
        // Empty switch; just run the switch condition.
        replaceMe(x.getExpr().makeStatement(), ctx);
      } else if (body.getStatements().size() == 2) {
        /*
         * If there are only two statements, we know it's a case statement and
         * something with an effect.
         *
         * TODO: make this more sophisticated; what we should really care about
         * is how many case statements it contains, not how many statements:
         *
         * switch(i) { default: a(); b(); c(); }
         *
         * becomes { a(); b(); c(); }
         *
         * switch(i) { case 1: a(); b(); c(); }
         *
         * becomes if (i == 1) { a(); b(); c(); }
         *
         * switch(i) { case 1: a(); b(); break; default: c(); d(); }
         *
         * becomes if (i == 1) { a(); b(); } else { c(); d(); }
         */
        JCaseStatement caseStatement = (JCaseStatement) body.getStatements().get(0);
        JStatement statement = body.getStatements().get(1);

        FindBreakContinueStatementsVisitor visitor = new FindBreakContinueStatementsVisitor();
        visitor.accept(statement);
        if (visitor.hasBreakContinueStatements()) {
          // Cannot optimize.
          return;
        }

        if (caseStatement.getExpr() != null) {
          // Create an if statement equivalent to the single-case switch.
          JBinaryOperation compareOperation =
              new JBinaryOperation(x.getSourceInfo(), program.getTypePrimitiveBoolean(),
                  JBinaryOperator.EQ, x.getExpr(), caseStatement.getExpr());
          JBlock block = new JBlock(x.getSourceInfo());
          block.addStmt(statement);
          JIfStatement ifStatement =
              new JIfStatement(x.getSourceInfo(), compareOperation, block, null);
          replaceMe(ifStatement, ctx);
        } else {
          // All we have is a default case; convert to a JBlock.
          JBlock block = new JBlock(x.getSourceInfo());
          block.addStmt(x.getExpr().makeStatement());
          block.addStmt(statement);
          replaceMe(block, ctx);
        }
      }
    }

    private Object tryTranslateLiteral(JExpression maybeLiteral, Class<?> type) {
      if (!(maybeLiteral instanceof JValueLiteral)) {
        return null;
      }
      // TODO: make this way better by a mile
      if (type == boolean.class && maybeLiteral instanceof JBooleanLiteral) {
        return Boolean.valueOf(((JBooleanLiteral) maybeLiteral).getValue());
      }
      if (type == char.class && maybeLiteral instanceof JCharLiteral) {
        return Character.valueOf(((JCharLiteral) maybeLiteral).getValue());
      }
      if (type == double.class && maybeLiteral instanceof JFloatLiteral) {
        return new Double(((JFloatLiteral) maybeLiteral).getValue());
      }
      if (type == double.class && maybeLiteral instanceof JDoubleLiteral) {
        return new Double(((JDoubleLiteral) maybeLiteral).getValue());
      }
      if (type == int.class && maybeLiteral instanceof JIntLiteral) {
        return Integer.valueOf(((JIntLiteral) maybeLiteral).getValue());
      }
      if (type == long.class && maybeLiteral instanceof JLongLiteral) {
        return Long.valueOf(((JLongLiteral) maybeLiteral).getValue());
      }
      if (type == String.class && maybeLiteral instanceof JStringLiteral) {
        return ((JStringLiteral) maybeLiteral).getValue();
      }
      if (type == Object.class) {
        // We already know it is a JValueLiteral instance
        return ((JValueLiteral) maybeLiteral).getValueObj();
      }
      return null;
    }
  }

  /**
   * Examines code to find out whether it contains any break or continue
   * statements.
   *
   * TODO: We could be more sophisticated with this. A nested while loop with an
   * unlabeled break should not cause this visitor to return false. Nor should a
   * labeled break break to another context.
   */
  public static class FindBreakContinueStatementsVisitor extends JVisitor {
    private boolean hasBreakContinueStatements = false;

    @Override
    public void endVisit(JBreakStatement x, Context ctx) {
      hasBreakContinueStatements = true;
    }

    @Override
    public void endVisit(JContinueStatement x, Context ctx) {
      hasBreakContinueStatements = true;
    }

    protected boolean hasBreakContinueStatements() {
      return hasBreakContinueStatements;
    }
  }

  public static final String NAME = DeadCodeElimination.class.getSimpleName();

  @VisibleForTesting
  public static OptimizerStats exec(JProgram program) {
    return new DeadCodeElimination(program).execImpl(Collections.singleton(program),
        OptimizerContext.NULL_OPTIMIZATION_CONTEXT);
  }

  // TODO(leafwang): Mark this as @VisibleForTesting eventually; this code path is also used
  // by DataflowOptimizer for now.
  public static OptimizerStats exec(JProgram program, JMethod method) {
    return new DeadCodeElimination(program).execImpl(Collections.singleton(method),
        OptimizerContext.NULL_OPTIMIZATION_CONTEXT);
  }

  /**
   * Apply DeadCodeElimination on the set of newly modified methods (obtained from the optimzer
   * context).
   */
  public static OptimizerStats exec(JProgram program, OptimizerContext optimizerCtx) {
    Set<JMethod> affectedMethods = affectedMethods(optimizerCtx);
    OptimizerStats stats = new DeadCodeElimination(program).execImpl(affectedMethods, optimizerCtx);
    optimizerCtx.setLastStepFor(NAME, optimizerCtx.getOptimizationStep());
    optimizerCtx.incOptimizationStep();
    JavaAstVerifier.assertProgramIsConsistent(program);
    return stats;
  }

  /**
   * Return the set of methods affected (because they are or callers of) by the modifications to the
   * given set functions.
   */
  private static Set<JMethod> affectedMethods(OptimizerContext optimizerCtx) {
    Set<JMethod> modifiedMethods =
        optimizerCtx.getModifiedMethodsSince(optimizerCtx.getLastStepFor(NAME));
    Set<JMethod> affectedMethods = Sets.newLinkedHashSet();
    affectedMethods.addAll(modifiedMethods);
    affectedMethods.addAll(optimizerCtx.getCallers(modifiedMethods));
    affectedMethods.addAll(optimizerCtx.getMethodsByReferencedFields(
        optimizerCtx.getModifiedFieldsSince(optimizerCtx.getLastStepFor(NAME))));
    return affectedMethods;
  }

  private final JProgram program;

  private final Map<JType, Class<?>> classObjectsByType;

  public DeadCodeElimination(JProgram program) {
    this.program = program;
    classObjectsByType = new ImmutableMap.Builder()
        .put(program.getTypeJavaLangObject(), Object.class)
        .put(program.getTypeJavaLangString(), String.class)
        .put(program.getTypePrimitiveBoolean(), boolean.class)
        .put(program.getTypePrimitiveByte(), byte.class)
        .put(program.getTypePrimitiveChar(), char.class)
        .put(program.getTypePrimitiveDouble(), double.class)
        .put(program.getTypePrimitiveFloat(), float.class)
        .put(program.getTypePrimitiveInt(), int.class)
        .put(program.getTypePrimitiveLong(), long.class)
        .put(program.getTypePrimitiveShort(), short.class)
        .build();
  }

  private OptimizerStats execImpl(Iterable<? extends JNode> nodes, OptimizerContext optimizerCtx) {
    OptimizerStats stats = new OptimizerStats(NAME);
    Event optimizeEvent = SpeedTracerLogger.start(CompilerEventType.OPTIMIZE, "optimizer", NAME);

    DeadCodeVisitor deadCodeVisitor = new DeadCodeVisitor(optimizerCtx);
    for (JNode node : nodes) {
      deadCodeVisitor.accept(node);
    }
    stats.recordModified(deadCodeVisitor.getNumMods());
    optimizeEvent.end("didChange", "" + stats.didChange());
    return stats;
  }

  private enum AnalysisResult { TRUE, FALSE, UNKNOWN }
}
