/*
 * 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.and(x), ctx);
          break;
        case OR:
          maybeReplaceMe(x, Simplifier.or(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.cast(x), ctx);
    }

    @Override
    public void endVisit(JConditional x, Context ctx) {
      maybeReplaceMe(x, Simplifier.conditional(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 (Simplifier.isEmpty(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) {
      maybeReplaceMe(x, Simplifier.ifStatement(x, getCurrentMethod()), 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.not(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 = Simplifier.isEmpty(x.getTryBlock());
      boolean noCatch = catchClauses.size() == 0;
      boolean noFinally = Simplifier.isEmpty(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 }
}
