// Copyright (c) 2016, the R8 project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.smali;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

import com.android.tools.r8.code.Const4;
import com.android.tools.r8.code.DivIntLit8;
import com.android.tools.r8.code.Instruction;
import com.android.tools.r8.code.RemIntLit8;
import com.android.tools.r8.code.Return;
import com.android.tools.r8.code.ReturnWide;
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.graph.DexCode;
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.ir.code.Cmp.Bias;
import com.android.tools.r8.ir.code.If.Type;
import com.android.tools.r8.ir.code.SingleConstant;
import com.android.tools.r8.ir.code.WideConstant;
import com.android.tools.r8.utils.AndroidApp;
import com.android.tools.r8.utils.codeinspector.ClassSubject;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
import com.google.common.collect.ImmutableList;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.function.BiConsumer;
import org.junit.Test;

public class ConstantFoldingTest extends SmaliTestBase {

  @FunctionalInterface
  public interface TriConsumer<T, U, V> {
    public void accept(T t, U u, V v);
  }

  private class SmaliBuilderWithCheckers {
    List<Object> values = new ArrayList<>();
    List<BiConsumer<DexEncodedMethod, Object>> checkers = new ArrayList<>();

    private final SmaliBuilder builder = new SmaliBuilder(DEFAULT_CLASS_NAME);

    public void addTest(
        TriConsumer<SmaliBuilder, String, Object> methodBilder,
        BiConsumer<DexEncodedMethod, Object> methodChecker,
        Object value) {
      methodBilder.accept(builder, "m" + values.size(), value);
      values.add(value);
      checkers.add(methodChecker);
    }

    public void run() throws Exception {
      AndroidApp processdApplication = processApplication(buildApplication(builder));
      assertEquals(1, getNumberOfProgramClasses(processdApplication));
      CodeInspector inspector = new CodeInspector(processdApplication);
      ClassSubject clazz = inspector.clazz(DEFAULT_CLASS_NAME);
      clazz.forAllMethods(method -> {
        int index = Integer.parseInt(method.getMethod().method.name.toString().substring(1));
        checkers.get(index).accept(method.getMethod(), values.get(index));
      });
    }
  }

  public class BinopTestData {
    public final String type;
    public final String op;
    public final List<Long> values;
    public final Long result;

    BinopTestData(String type, String op, List<Long> values, Long result) {
      this.type = type;
      this.op = op;
      this.values = values;
      this.result = result;
    }
  }

  private long floatBits(float f) {
    return Float.floatToIntBits(f);
  }

  private long doubleBits(double d) {
    return Double.doubleToLongBits(d);
  }

  private ImmutableList<Long> arguments = ImmutableList.of(1L, 2L, 3L, 4L);
  private ImmutableList<Long> floatArguments = ImmutableList.of(
      floatBits(1.0f), floatBits(2.0f), floatBits(3.0f), floatBits(4.0f));
  private ImmutableList<Long> doubleArguments = ImmutableList.of(
      doubleBits(1.0), doubleBits(2.0), doubleBits(3.0), doubleBits(4.0));

  private void binopMethodBuilder(SmaliBuilder builder, String name, Object parameters) {
    BinopTestData test = (BinopTestData) parameters;
    boolean wide = test.type.equals("long") || test.type.equals("double");
    StringBuilder source = new StringBuilder();
    int factor = wide ? 2 : 1;
    for (int i = 0; i < test.values.size(); i++) {
      source.append("    ");
      source.append(wide ? "const-wide " : "const ");
      source.append("v" + (i * factor));
      source.append(", ");
      source.append("0x" + Long.toHexString(test.values.get(i)));
      source.append(wide ? "L" : "");
      source.append("\n");
    }

    for (int i = 0; i < test.values.size() - 1; i++) {
      source.append("    ");
      source.append(test.op + "-" + test.type + "/2addr ");
      source.append("v" + ((i + 1) * factor));
      source.append(", ");
      source.append("v" + (i * factor));
      source.append("\n");
    }

    source.append("    ");
    source.append(wide ? "return-wide " : "return ");
    source.append("v" + ((test.values.size() - 1) * factor));

    builder.addStaticMethod(
        test.type, name, Collections.singletonList(test.type),
        test.values.size() * factor,
        source.toString());
  }

  private void binopMethodChecker(DexEncodedMethod method, Object parameters) {
    BinopTestData test = (BinopTestData) parameters;
    boolean wide = test.type.equals("long") || test.type.equals("double");
    DexCode code = method.getCode().asDexCode();
    assertEquals(2, code.instructions.length);
    if (wide) {
      assertTrue(code.instructions[0] instanceof WideConstant);
      assertEquals(test.result.longValue(),
          ((WideConstant) code.instructions[0]).decodedValue());
      assertTrue(code.instructions[1] instanceof ReturnWide);
    } else {
      assertTrue(code.instructions[0] instanceof SingleConstant);
      assertEquals(
          test.result.longValue(),
          (long) ((SingleConstant) code.instructions[0]).decodedValue());
      assertTrue(code.instructions[1] instanceof Return);
    }
  }

  private void addBinopTest(SmaliBuilderWithCheckers testBuilder, BinopTestData test) {
    testBuilder.addTest(this::binopMethodBuilder, this::binopMethodChecker, test);
  }

  private void addBinopFoldingTests(SmaliBuilderWithCheckers testBuilder) {
    // Add tests.
    addBinopTest(testBuilder, new BinopTestData("int", "add", arguments, 10L));
    addBinopTest(testBuilder, new BinopTestData("long", "add", arguments, 10L));
    addBinopTest(testBuilder,
        new BinopTestData("float", "add", floatArguments, floatBits(10.0f)));
    addBinopTest(testBuilder,
        new BinopTestData("double", "add", doubleArguments, doubleBits(10.0)));

    // Mul tests.
    addBinopTest(testBuilder, new BinopTestData("int", "mul", arguments, 24L));
    addBinopTest(testBuilder, new BinopTestData("long", "mul", arguments, 24L));
    addBinopTest(testBuilder,
        new BinopTestData("float", "mul", floatArguments, floatBits(24.0f)));
    addBinopTest(testBuilder,
        new BinopTestData("double", "mul", doubleArguments, doubleBits(24.0)));

    // Sub tests.
    addBinopTest(testBuilder, new BinopTestData("int", "sub", arguments.reverse(), -2L));
    addBinopTest(testBuilder, new BinopTestData("long", "sub", arguments.reverse(), -2L));
    addBinopTest(testBuilder,
        new BinopTestData("float", "sub", floatArguments.reverse(), floatBits(-2.0f)));
    addBinopTest(testBuilder,
        new BinopTestData("double", "sub", doubleArguments.reverse(), doubleBits(-2.0)));

    // Div tests.
    {
      ImmutableList<Long> arguments = ImmutableList.of(2L, 24L, 48L, 4L);
      ImmutableList<Long> floatArguments = ImmutableList.of(
          floatBits(2.0f), floatBits(24.0f), floatBits(48.0f), floatBits(4.0f));
      ImmutableList<Long> doubleArguments = ImmutableList.of(
          doubleBits(2.0), doubleBits(24.0), doubleBits(48.0), doubleBits(4.0));

      addBinopTest(testBuilder, new BinopTestData("int", "div", arguments, 1L));
      addBinopTest(testBuilder, new BinopTestData("long", "div", arguments, 1L));
      addBinopTest(testBuilder,
          new BinopTestData("float", "div", floatArguments, floatBits(1.0f)));
      addBinopTest(testBuilder,
          new BinopTestData("double", "div", doubleArguments, doubleBits(1.0)));
    }

    // Rem tests.
    {
      ImmutableList<Long> arguments = ImmutableList.of(10L, 6L, 3L, 2L);
      ImmutableList<Long> floatArguments = ImmutableList.of(
          floatBits(10.0f), floatBits(6.0f), floatBits(3.0f), floatBits(2.0f));
      ImmutableList<Long> doubleArguments = ImmutableList.of(
          doubleBits(10.0), doubleBits(6.0), doubleBits(3.0), doubleBits(2.0));

      addBinopTest(testBuilder, new BinopTestData("int", "rem", arguments, 2L));
      addBinopTest(testBuilder, new BinopTestData("long", "rem", arguments, 2L));
      addBinopTest(testBuilder,
          new BinopTestData("float", "rem", floatArguments, floatBits(2.0f)));
      addBinopTest(testBuilder,
          new BinopTestData("double", "rem", doubleArguments, doubleBits(2.0)));
    }
  }

  private void addDivIntFoldDivByZero(SmaliBuilderWithCheckers testBuilder) {
    testBuilder.addTest(
        (builder, name, parameters) -> {
          builder.addStaticMethod(
              "int", name, Collections.singletonList("int"),
              2,
              "    const/4 v0, 1           ",
              "    const/4 v1, 0           ",
              "    div-int/2addr v0, v1    ",
              "    return v0\n             "
          );
        },
        (method, parameters) -> {
          DexCode code = method.getCode().asDexCode();
          // Division by zero is not folded, but div-int/lit8 is used.
          assertEquals(3, code.instructions.length);
          assertTrue(code.instructions[0] instanceof Const4);
          assertTrue(code.instructions[1] instanceof DivIntLit8);
          assertEquals(0, ((DivIntLit8) code.instructions[1]).CC);
          assertTrue(code.instructions[2] instanceof Return);
        },
        null
    );
  }

  private void addDivIntFoldRemByZero(SmaliBuilderWithCheckers testBuilder) {
    testBuilder.addTest(
        (builder, name, parameters) -> {
          builder.addStaticMethod(
            "int", name, Collections.singletonList("int"),
            2,
            "    const/4 v0, 1           ",
            "    const/4 v1, 0           ",
            "    rem-int/2addr v0, v1    ",
            "    return v0\n             "
          );
        },
        (method, parameters) -> {
          DexCode code = method.getCode().asDexCode();
          // Division by zero is not folded, but rem-int/lit8 is used.
          assertEquals(3, code.instructions.length);
          assertTrue(code.instructions[0] instanceof Const4);
          assertTrue(code.instructions[1] instanceof RemIntLit8);
          assertEquals(0, ((RemIntLit8) code.instructions[1]).CC);
          assertTrue(code.instructions[2] instanceof Return);
        },
        null
    );
  }

  public class UnopTestData {
    public final String type;
    public final String op;
    public final Long value;
    public final Long result;

    UnopTestData(String type, String op, Long value, Long result) {
      this.type = type;
      this.op = op;
      this.value = value;
      this.result = result;
    }
  }

  private void unopMethodBuilder(SmaliBuilder builder, String name, Object parameters) {
    UnopTestData test = (UnopTestData) parameters;
    boolean wide = test.type.equals("long") || test.type.equals("double");
    StringBuilder source = new StringBuilder();
    source.append("    ");
    source.append(wide ? "const-wide " : "const ");
    source.append("v0 , ");
    source.append("0x" + Long.toHexString(test.value));
    source.append(wide ? "L" : "");
    source.append("\n");

    source.append("    ");
    source.append(test.op + "-" + test.type + " v0, v0\n");

    source.append("    ");
    source.append(wide ? "return-wide v0" : "return v0");

    builder.addStaticMethod(
        test.type, name, Collections.singletonList(test.type),
        wide ? 2 : 1,
        source.toString());
  }

  private void unopMethodChecker(DexEncodedMethod method, Object parameters) {
    UnopTestData test = (UnopTestData) parameters;
    boolean wide = test.type.equals("long") || test.type.equals("double");
    DexCode code = method.getCode().asDexCode();
    assertEquals(2, code.instructions.length);
    if (wide) {
      assertTrue(code.instructions[0] instanceof WideConstant);
      assertEquals(test.result.longValue(), ((WideConstant) code.instructions[0]).decodedValue());
      assertTrue(code.instructions[1] instanceof ReturnWide);
    } else {
      assertTrue(code.instructions[0] instanceof SingleConstant);
      assertEquals(
          test.result.longValue(), (long) ((SingleConstant) code.instructions[0]).decodedValue());
      assertTrue(code.instructions[1] instanceof Return);
    }
  }

  private void addUnopTest(SmaliBuilderWithCheckers testBuilder, UnopTestData test) {
    testBuilder.addTest(this::unopMethodBuilder, this::unopMethodChecker, test);
  }

  private void addNegFoldingTest(SmaliBuilderWithCheckers testBuilder) throws Exception {
    addUnopTest(testBuilder, new UnopTestData("int", "neg", 2L, -2L));
    addUnopTest(testBuilder, new UnopTestData("int", "neg", -2L, 2L));
    addUnopTest(testBuilder, new UnopTestData("long", "neg", 2L, -2L));
    addUnopTest(testBuilder, new UnopTestData("long", "neg", -2L, 2L));
    addUnopTest(testBuilder, new UnopTestData("float", "neg", floatBits(2.0f), floatBits(-2.0f)));
    addUnopTest(testBuilder, new UnopTestData("float", "neg", floatBits(-2.0f), floatBits(2.0f)));
    addUnopTest(testBuilder, new UnopTestData("float", "neg", floatBits(0.0f), floatBits(-0.0f)));
    addUnopTest(testBuilder, new UnopTestData("float", "neg", floatBits(-0.0f), floatBits(0.0f)));
    addUnopTest(testBuilder, new UnopTestData("double", "neg", doubleBits(2.0), doubleBits(-2.0)));
    addUnopTest(testBuilder, new UnopTestData("double", "neg", doubleBits(-2.0), doubleBits(2.0)));
    addUnopTest(testBuilder, new UnopTestData("double", "neg", doubleBits(0.0), doubleBits(-0.0)));
    addUnopTest(testBuilder, new UnopTestData("double", "neg", doubleBits(-0.0), doubleBits(0.0)));
  }

  private void assertConstValue(int expected, Instruction insn) {
    assertTrue(insn instanceof SingleConstant);
    assertEquals(expected, ((SingleConstant) insn).decodedValue());
  }

  private void assertConstValue(long expected, Instruction insn) {
    assertTrue(insn instanceof WideConstant);
    assertEquals(expected, ((WideConstant) insn).decodedValue());
  }

  class LogicalOperatorTestData {
    final String op;
    final int[] values;
    final int expected;

    LogicalOperatorTestData(String op, int[] values) {
      this.op = op;
      this.values = values;

      int v0 = values[0];
      int v1 = values[1];
      int v2 = values[2];
      int v3 = values[3];

      switch (op) {
        case "and":
          this.expected = v0 & v1 & v2 & v3;
          break;
        case "or":
          this.expected = v0 | v1 | v2 | v3;
          break;
        case "xor":
          this.expected = v0 ^ v1 ^ v2 ^ v3;
          break;
        default:
          this.expected = 0;
          throw new Unreachable("Unsupported logical binop " + op);
      }
    }
  }

  private void logicalOperatorMethodBuilder(SmaliBuilder builder, String name, Object parameters) {
    LogicalOperatorTestData test = (LogicalOperatorTestData) parameters;
    builder.addStaticMethod(
        "int", name, Collections.singletonList("int"),
        4,
        "    const v0, " + test.values[0],
        "    const v1, " + test.values[1],
        "    const v2, " + test.values[2],
        "    const v3, " + test.values[3],
        // E.g. and-int//2addr v1, v0
        "    " + test.op + "-int/2addr v1, v0    ",
        "    " + test.op + "-int/2addr v2, v1    ",
        "    " + test.op + "-int/2addr v3, v2    ",
        "    return v3\n                    ");
  }

  private void logicalOperatorMethodChecker(DexEncodedMethod method, Object parameters) {
    LogicalOperatorTestData test = (LogicalOperatorTestData) parameters;
    DexCode code = method.getCode().asDexCode();
    // Test that this just returns a constant.
    assertEquals(2, code.instructions.length);
    assertConstValue(test.expected, code.instructions[0]);
    assertTrue(code.instructions[1] instanceof Return);
  }

  private void addLogicalOperatorsFoldTests(SmaliBuilderWithCheckers testBuilder) {
    int[][] testValues = new int[][]{
        new int[]{0x00, 0x00, 0x00, 0x00},
        new int[]{0x0b, 0x06, 0x03, 0x00},
        new int[]{0x0f, 0x07, 0x03, 0x01},
        new int[]{0x08, 0x04, 0x02, 0x01},
    };

    for (int[] values : testValues) {
      for (String op : new String[]{"and", "or", "xor"}) {
        testBuilder.addTest(
            this::logicalOperatorMethodBuilder,
            this::logicalOperatorMethodChecker,
            new LogicalOperatorTestData(op, values));
      }
    }
  }

  class ShiftTestData {
    final int[] values;
    final String op;
    final int expected;

    ShiftTestData(String op, int[] values) {
      this.values = values;
      this.op = op;


      int v0 = values[0];
      int v1 = values[1];
      int v2 = values[2];
      int v3 = values[3];

      switch (op) {
        case "shl":
          v0 = v0 << v1;
          v0 = v0 << v2;
          v0 = v0 << v3;
          break;
        case "shr":
          v0 = v0 >> v1;
          v0 = v0 >> v2;
          v0 = v0 >> v3;
          break;
        case "ushr":
          v0 = v0 >>> v1;
          v0 = v0 >>> v2;
          v0 = v0 >>> v3;
          break;
        default:
          throw new Unreachable("Unsupported shift " + op);
      }

      this.expected = v0;
    }
  }

  private void shiftOperatorMethodBuilder(SmaliBuilder builder, String name, Object parameters) {
    ShiftTestData data = (ShiftTestData) parameters;
    builder.addStaticMethod(
        "int", name, Collections.singletonList("int"),
        4,
        "    const v0, " + data.values[0],
        "    const v1, " + data.values[1],
        "    const v2, " + data.values[2],
        "    const v3, " + data.values[3],
        // E.g. and-int//2addr v1, v0
        "    " + data.op + "-int/2addr v0, v1    ",
        "    " + data.op + "-int/2addr v0, v2    ",
        "    " + data.op + "-int/2addr v0, v3    ",
        "    return v0\n                    "
    );
  }

  private void shiftOperatorMethodChecker(DexEncodedMethod method, Object parameters) {
    ShiftTestData data = (ShiftTestData) parameters;
    DexCode code = method.getCode().asDexCode();
    // Test that this just returns a constant.
    assertEquals(2, code.instructions.length);
    assertConstValue(data.expected, code.instructions[0]);
    assertTrue(code.instructions[1] instanceof Return);
  }

  public void addShiftOperatorsFolding(SmaliBuilderWithCheckers testBuilder) {
    int[][] testValues = new int[][]{
        new int[]{0x01, 0x01, 0x01, 0x01},
        new int[]{0x01, 0x02, 0x03, 0x04},
        new int[]{0x7f000000, 0x01, 0x2, 0x03},
        new int[]{0x80000000, 0x01, 0x2, 0x03},
        new int[]{0xffffffff, 0x01, 0x2, 0x03},
    };

    for (int[] values : testValues) {
      for (String op : new String[]{"shl", "shr", "ushr"}) {
        testBuilder.addTest(
            this::shiftOperatorMethodBuilder,
            this::shiftOperatorMethodChecker,
            new ShiftTestData(op, values));
      }
    }
  }

  class ShiftWideTestData {
    final long[] values;
    final String op;
    final long expected;

    ShiftWideTestData(String op, long[] values) {
      this.values = values;
      this.op = op;

      long v0 = values[0];
      int v2 = (int) values[1];
      int v4 = (int) values[2];
      int v6 = (int) values[3];

      switch (op) {
        case "shl":
          v0 = v0 << v2;
          v0 = v0 << v4;
          v0 = v0 << v6;
          break;
        case "shr":
          v0 = v0 >> v2;
          v0 = v0 >> v4;
          v0 = v0 >> v6;
          break;
        case "ushr":
          v0 = v0 >>> v2;
          v0 = v0 >>> v4;
          v0 = v0 >>> v6;
          break;
        default:
          throw new Unreachable("Unsupported shift " + op);
      }

      this.expected = v0;
    }
  }

  private void shiftOperatorWideMethodBuilder(
      SmaliBuilder builder, String name, Object parameters) {
    ShiftWideTestData data = (ShiftWideTestData) parameters;
    builder.addStaticMethod(
    "long", name, Collections.singletonList("long"),
        5,
        "    const-wide v0, 0x" + Long.toHexString(data.values[0]) + "L",
        "    const v2, " + data.values[1],
        "    const v3, " + data.values[2],
        "    const v4, " + data.values[3],
        // E.g. and-long//2addr v1, v0
        "    " + data.op + "-long/2addr v0, v2    ",
        "    " + data.op + "-long/2addr v0, v3    ",
        "    " + data.op + "-long/2addr v0, v4    ",
        "    return-wide v0\n                    "
    );
  }

  private void shiftOperatorWideMethodChecker(DexEncodedMethod method, Object parameters) {
    ShiftWideTestData data = (ShiftWideTestData) parameters;
    DexCode code = method.getCode().asDexCode();
    // Test that this just returns a constant.
    assertEquals(2, code.instructions.length);
    assertConstValue(data.expected, code.instructions[0]);
    assertTrue(code.instructions[1] instanceof ReturnWide);
  }

  public void addShiftOperatorsFoldingWide(SmaliBuilderWithCheckers testBuilder) {
    long[][] testValues = new long[][]{
        new long[]{0x01, 0x01, 0x01, 0x01},
        new long[]{0x01, 0x02, 0x03, 0x04},
        new long[]{0x7f0000000000L, 0x01, 0x2, 0x03},
        new long[]{0x800000000000L, 0x01, 0x2, 0x03},
        new long[]{0x7f00000000000000L, 0x01, 0x2, 0x03},
        new long[]{0x8000000000000000L, 0x01, 0x2, 0x03},
        new long[]{0xffffffffffffffffL, 0x01, 0x2, 0x03},
    };

    for (long[] values : testValues) {
      for (String op : new String[]{"shl", "shr", "ushr"}) {
        testBuilder.addTest(
            this::shiftOperatorWideMethodBuilder,
            this::shiftOperatorWideMethodChecker,
            new ShiftWideTestData(op, values));
      }
    }
  }

  private void notIntMethodBuilder(SmaliBuilder builder, String name, Object parameters) {
    Integer value = (Integer) parameters;
    builder.addStaticMethod("int", name, Collections.emptyList(),
        1,
        "    const v0, " + value,
        "    not-int v0, v0",
        "    return v0");
  }

  private void notIntMethodChecker(DexEncodedMethod method, Object parameters) {
    Integer value = (Integer) parameters;
    DexCode code = method.getCode().asDexCode();
    assertEquals(2, code.instructions.length);
    assertConstValue(~value, code.instructions[0]);
    assertTrue(code.instructions[1] instanceof Return);
  }

  private void addNotIntFoldTests(SmaliBuilderWithCheckers testBuilder) throws Exception {
    ImmutableList.of(0, 1, 0xff, 0xffffffff, 0xff000000, 0x80000000)
        .forEach(v -> testBuilder.addTest(this::notIntMethodBuilder, this::notIntMethodChecker, v));
  }

  private void notLongMethodBuilder(SmaliBuilder builder, String name, Object parameters) {
    Long value = (Long) parameters;
    builder.addStaticMethod("long", name, Collections.emptyList(),
        2,
        "    const-wide v0, 0x" + Long.toHexString(value) + "L",
        "    not-long v0, v0",
        "    return-wide v0");
  }

  private void notLongMethodChecker(DexEncodedMethod method, Object parameters) {
    Long value = (Long) parameters;
    DexCode code = method.getCode().asDexCode();
    assertEquals(2, code.instructions.length);
    assertConstValue(~value, code.instructions[0]);
    assertTrue(code.instructions[1] instanceof ReturnWide);
  }


  private void addNotLongFoldTests(SmaliBuilderWithCheckers testBuilder) throws Exception {
    ImmutableList.of(
        0L,
        1L,
        0xffL,
        0xffffffffffffffffL,
        0x00ffffffffffffffL,
        0xff00000000000000L,
        0x8000000000000000L
    ).forEach(v -> testBuilder.addTest(this::notLongMethodBuilder, this::notLongMethodChecker, v));
  }

  private void negIntMethodBuilder(SmaliBuilder builder, String name, Object parameters) {
    Integer value = (Integer) parameters;
    builder.addStaticMethod("int", name, Collections.emptyList(),
        1,
        "    const v0, " + value,
        "    neg-int v0, v0",
        "    return v0");
  }

  private void negIntMethodChecker(DexEncodedMethod method, Object parameters) {
    Integer value = (Integer) parameters;
    DexCode code = method.getCode().asDexCode();
    assertEquals(2, code.instructions.length);
    assertConstValue(-value, code.instructions[0]);
    assertTrue(code.instructions[1] instanceof Return);
  }

  private void addNegIntFoldTests(SmaliBuilderWithCheckers testBuilder) throws Exception {
    ImmutableList.of(0, 1, 0xff, 0xffffffff, 0xff000000, 0x80000000)
        .forEach(v -> testBuilder.addTest(this::negIntMethodBuilder, this::negIntMethodChecker, v));
  }

  private void negLongMethodBuilder(SmaliBuilder builder, String name, Object parameters) {
    Long value = (Long) parameters;
    builder.addStaticMethod(
        "long", name, Collections.emptyList(),
        2,
        "    const-wide v0, 0x" + Long.toHexString(value) + "L",
        "    neg-long v0, v0",
        "    return-wide v0");
  }

  private void negLongMethodChecker(DexEncodedMethod method, Object parameters) {
    Long value = (Long) parameters;
    DexCode code = method.getCode().asDexCode();
    assertEquals(2, code.instructions.length);
    assertConstValue(-value, code.instructions[0]);
    assertTrue(code.instructions[1] instanceof ReturnWide);
  }

  private void addNegLongFoldTests(SmaliBuilderWithCheckers testBuilder) throws Exception {
    ImmutableList.of(
        0L,
        1L,
        0xffL,
        0xffffffffffffffffL,
        0x00ffffffffffffffL,
        0xff00000000000000L,
        0x8000000000000000L
    ).forEach(v -> testBuilder.addTest(this::negLongMethodBuilder, this::negLongMethodChecker, v));
  }

  class FloatTestData {

    final float a;
    final float b;
    final Type type;
    final Bias bias;
    final boolean expected;

    FloatTestData(float a, float b, Type type, Bias bias) {
      this.a = a;
      this.b = b;
      this.type = type;
      this.bias = bias;
      switch (type) {
        case EQ: expected = a == b; break;
        case NE: expected = a != b; break;
        case LE: expected = a <= b; break;
        case GE: expected = a >= b; break;
        case LT: expected = a < b; break;
        case GT: expected = a > b; break;
        default: expected = false; assert false;
      }
    }
  }

  private void cmpFloatMethodBuilder(SmaliBuilder builder, String name, Object parameters) {
    String[] ifOpcode = new String[6];
    ifOpcode[Type.EQ.ordinal()] = "if-eqz";
    ifOpcode[Type.NE.ordinal()] = "if-nez";
    ifOpcode[Type.LE.ordinal()] = "if-lez";
    ifOpcode[Type.GE.ordinal()] = "if-gez";
    ifOpcode[Type.LT.ordinal()] = "if-ltz";
    ifOpcode[Type.GT.ordinal()] = "if-gtz";

    FloatTestData test = (FloatTestData) parameters;
    String cmpInstruction;
    if (test.bias == Bias.LT) {
      cmpInstruction = "    cmpl-float v0, v0, v1";
    } else {
      cmpInstruction = "    cmpg-float v0, v0, v1";
    }
    builder.addStaticMethod("int", name, Collections.emptyList(), 2,
        "    const v0, 0x" + Integer.toHexString(Float.floatToRawIntBits(test.a)),
        "    const v1, 0x" + Integer.toHexString(Float.floatToRawIntBits(test.b)),
        cmpInstruction,
        "    " + ifOpcode[test.type.ordinal()] + " v0, :label_2",
        "    const v0, 0",
        ":label_1",
        "    return v0",
        ":label_2",
        "  const v0, 1",
        "  goto :label_1"
    );
  }

  private void cmpFloatMethodChecker(DexEncodedMethod method, Object parameters) {
    FloatTestData test = (FloatTestData) parameters;
    DexCode code = method.getCode().asDexCode();
    assertEquals(2, code.instructions.length);
    assertConstValue(test.expected ? 1: 0, code.instructions[0]);
    assertTrue(code.instructions[1] instanceof Return);
  }

  private void addCmpFloatFoldTests(SmaliBuilderWithCheckers testBuilder) throws Exception {
    float[] testValues = new float[]{
        Float.NEGATIVE_INFINITY,
        -100.0f,
        -0.0f,
        0.0f,
        100.0f,
        Float.POSITIVE_INFINITY,
        Float.NaN
    };

    // Build the test configuration.
    for (int i = 0; i < testValues.length; i++) {
      for (int j = 0; j < testValues.length; j++) {
        for (Type type : Type.values()) {
          for (Bias bias : Bias.values()) {
            if (bias == Bias.NONE) {
              // Bias NONE is only for long comparison.
              continue;
            }
            // If no NaNs are involved either bias produce the same result.
            if (Float.isNaN(testValues[i]) || Float.isNaN(testValues[j])) {
              // For NaN comparison only test with the bias that provide Java semantics.
              // The Java Language Specification 4.2.3. Floating-Point Types, Formats, and Values
              // says:
              //
              // The numerical comparison operators <, <=, >, and >= return false if either or both
              // operands are NaN
              if ((type == Type.GE || type == Type.GT) && bias == Bias.GT) {
                continue;
              }
              if ((type == Type.LE || type == Type.LT) && bias == Bias.LT) {
                continue;
              }
            }
            testBuilder.addTest(
                this::cmpFloatMethodBuilder,
                this::cmpFloatMethodChecker,
                new FloatTestData(testValues[i], testValues[j], type, bias));
          }
        }
      }
    }
  }

  class DoubleTestData {

    final double a;
    final double b;
    final Type type;
    final Bias bias;
    final boolean expected;

    DoubleTestData(double a, double b, Type type, Bias bias) {
      this.a = a;
      this.b = b;
      this.type = type;
      this.bias = bias;
      switch (type) {
        case EQ: expected = a == b; break;
        case NE: expected = a != b; break;
        case LE: expected = a <= b; break;
        case GE: expected = a >= b; break;
        case LT: expected = a < b; break;
        case GT: expected = a > b; break;
        default: expected = false; assert false;
      }
    }
  }

  private void cmpDoubleMethodBuilder(SmaliBuilder builder, String name, Object parameters) {
    String[] ifOpcode = new String[6];
    ifOpcode[Type.EQ.ordinal()] = "if-eqz";
    ifOpcode[Type.NE.ordinal()] = "if-nez";
    ifOpcode[Type.LE.ordinal()] = "if-lez";
    ifOpcode[Type.GE.ordinal()] = "if-gez";
    ifOpcode[Type.LT.ordinal()] = "if-ltz";
    ifOpcode[Type.GT.ordinal()] = "if-gtz";

    DoubleTestData test = (DoubleTestData) parameters;
    String cmpInstruction;
    if (test.bias == Bias.LT) {
      cmpInstruction = "    cmpl-double v0, v0, v2";
    } else {
      cmpInstruction = "    cmpg-double v0, v0, v2";
    }
    builder.addStaticMethod("int", name, Collections.emptyList(), 4,
        "    const-wide v0, 0x" + Long.toHexString(Double.doubleToRawLongBits(test.a)) + "L",
        "    const-wide v2, 0x" + Long.toHexString(Double.doubleToRawLongBits(test.b)) + "L",
        cmpInstruction,
        "    " + ifOpcode[test.type.ordinal()] + " v0, :label_2",
        "    const v0, 0",
        ":label_1",
        "    return v0",
        ":label_2",
        "  const v0, 1",
        "  goto :label_1"
    );
  }

  private void cmpDoubleMethodChecker(DexEncodedMethod method, Object parameters) {
    DoubleTestData test = (DoubleTestData) parameters;
    DexCode code = method.getCode().asDexCode();
    assertEquals(2, code.instructions.length);
    assertConstValue(test.expected ? 1: 0, code.instructions[0]);
    assertTrue(code.instructions[1] instanceof Return);
  }


  private void addCmpDoubleFoldTests(SmaliBuilderWithCheckers testBuilder) throws Exception {
    double[] testValues = new double[]{
        Double.NEGATIVE_INFINITY,
        -100.0f,
        -0.0f,
        0.0f,
        100.0f,
        Double.POSITIVE_INFINITY,
        Double.NaN
    };

    // Build the test configuration.
    for (int i = 0; i < testValues.length; i++) {
      for (int j = 0; j < testValues.length; j++) {
        for (Type type : Type.values()) {
          for (Bias bias : Bias.values()) {
            if (bias == Bias.NONE) {
              // Bias NONE is only for long comparison.
              continue;
            }
            if (Double.isNaN(testValues[i]) || Double.isNaN(testValues[j])) {
              // For NaN comparison only test with the bias that provide Java semantics.
              // The Java Language Specification 4.2.3. Doubleing-Point Types, Formats, and Values
              // says:
              //
              // The numerical comparison operators <, <=, >, and >= return false if either or both
              // operands are NaN
              if ((type == Type.GE || type == Type.GT) && bias == Bias.GT) {
                continue;
              }
              if ((type == Type.LE || type == Type.LT) && bias == Bias.LT) {
                continue;
              }
            }
            testBuilder.addTest(
                this::cmpDoubleMethodBuilder,
                this::cmpDoubleMethodChecker,
                new DoubleTestData(testValues[i], testValues[j], type, bias));
          }
        }
      }
    }
  }

  private void cmpLongMethodBuilder(SmaliBuilder builder, String name, Object parameters) {
    long[] values = (long[]) (parameters);
    builder.addStaticMethod(
        "int", name, Collections.emptyList(),
        4,
        "    const-wide v0, 0x" + Long.toHexString(values[0]) + "L",
        "    const-wide v2, 0x" + Long.toHexString(values[1]) + "L",
        "    cmp-long v0, v0, v2",
        "    return v0");
  }

  private void cmpLongMethodChecker(DexEncodedMethod method, Object parameters) {
    long[] values = (long[]) (parameters);
    DexCode code = method.getCode().asDexCode();
    assertEquals(2, code.instructions.length);
    assertConstValue(Long.compare(values[0], values[1]), code.instructions[0]);
    assertTrue(code.instructions[1] instanceof Return);
  }

  private void addCmpLongFold(SmaliBuilderWithCheckers testBuilder) throws Exception {
    ImmutableList.of(
        new long[]{Long.MIN_VALUE, 1L},
        new long[]{Long.MAX_VALUE, 1L},
        new long[]{Long.MIN_VALUE, 0L},
        new long[]{Long.MAX_VALUE, 0L},
        new long[]{Long.MIN_VALUE, -1L},
        new long[]{Long.MAX_VALUE, -1L}
    ).forEach(v -> testBuilder.addTest(this::cmpLongMethodBuilder, this::cmpLongMethodChecker, v));
  }

  @Test
  public void foldingTest() throws Exception {
    SmaliBuilderWithCheckers testBuilder = new SmaliBuilderWithCheckers();
    addBinopFoldingTests(testBuilder);
    addDivIntFoldDivByZero(testBuilder);
    addDivIntFoldRemByZero(testBuilder);
    addNegFoldingTest(testBuilder);
    addShiftOperatorsFolding(testBuilder);
    addShiftOperatorsFoldingWide(testBuilder);
    addLogicalOperatorsFoldTests(testBuilder);
    addNotIntFoldTests(testBuilder);
    addNotLongFoldTests(testBuilder);
    addNegIntFoldTests(testBuilder);
    addNegLongFoldTests(testBuilder);
    addCmpFloatFoldTests(testBuilder);
    addCmpDoubleFoldTests(testBuilder);
    addCmpLongFold(testBuilder);
    runDex2Oat(testBuilder.builder.build());
    testBuilder.run();
  }

}
