Improved induction var and range analysis around types.

Rationale:
Lots of code should not depend on int only. This CL generalizes
the kinds of types that can be optimized after analysis. As part
of the CL, however, a minor cleanup regarding type safety of the
stored induction var analysis results is required. This further
improved our int benchmark, and brings the long benchmark up-to-par.

Test: m test-art-host-run-test
Change-Id: I5dfb623dabf9113de90c2f6da99328dda8f8b60b
diff --git a/test/530-checker-loops3/src/Main.java b/test/530-checker-loops3/src/Main.java
index 209786a..dfc4a5f 100644
--- a/test/530-checker-loops3/src/Main.java
+++ b/test/530-checker-loops3/src/Main.java
@@ -235,6 +235,59 @@
     }
   }
 
+  /// CHECK-START: void Main.shortBound1(int[], short) BCE (before)
+  /// CHECK-DAG: BoundsCheck loop:{{B\d+}}
+  //
+  /// CHECK-START: void Main.shortBound1(int[], short) BCE (after)
+  /// CHECK-DAG: Deoptimize loop:none
+  /// CHECK-DAG: Deoptimize loop:none
+  /// CHECK-DAG: Deoptimize loop:none
+  /// CHECK-NOT: Deoptimize
+  //
+  /// CHECK-START: void Main.shortBound1(int[], short) BCE (after)
+  /// CHECK-NOT: BoundsCheck
+  public static void shortBound1(int[] array, short s) {
+    // Lower precision bound will appear in deopt arithmetic
+    // and follows normal implicit widening conversion.
+    for (int i = 0; i < s; i++) {
+      array[i] = 222;
+    }
+  }
+
+  /// CHECK-START: void Main.shortBound2(int[], short) BCE (before)
+  /// CHECK-DAG: BoundsCheck loop:{{B\d+}}
+  //
+  /// CHECK-START: void Main.shortBound2(int[], short) BCE (after)
+  /// CHECK-DAG: Deoptimize loop:none
+  /// CHECK-DAG: Deoptimize loop:none
+  /// CHECK-DAG: Deoptimize loop:none
+  /// CHECK-NOT: Deoptimize
+  //
+  /// CHECK-START: void Main.shortBound2(int[], short) BCE (after)
+  /// CHECK-NOT: BoundsCheck
+  public static void shortBound2(int[] array, short s) {
+    // Lower precision bound will appear in deopt arithmetic
+    // and follows normal implicit widening conversion.
+    for (int i = 0; s > i; i++) {
+      array[i] = 444;
+    }
+  }
+
+  /// CHECK-START: void Main.narrowingFromLong(int[], int) BCE (before)
+  /// CHECK-DAG: BoundsCheck loop:{{B\d+}}
+  //
+  /// CHECK-START: void Main.narrowingFromLong(int[], int) BCE (after)
+  /// CHECK-DAG: BoundsCheck loop:{{B\d+}}
+  public static void narrowingFromLong(int[] array, int n) {
+    // Parallel induction in long precision that is narrowed provides type
+    // conversion challenges for BCE in deopt arithmetic when combined
+    // with the int loop induction. Therefore, currently skipped.
+    long l = 0;
+    for (int i = 0; i < n; i++, l++) {
+      array[(int)l] = 888;
+    }
+  }
+
   //
   // Verifier.
   //
@@ -316,6 +369,38 @@
     } catch (ArrayIndexOutOfBoundsException e) {
     }
 
+    shortBound1(a, (short)a.length);
+    for (int i = 0; i < a.length; i++) {
+      expectEquals(222, a[i]);
+    }
+    shortBound2(a, (short)a.length);
+    for (int i = 0; i < a.length; i++) {
+      expectEquals(444, a[i]);
+    }
+
+    try {
+      shortBound1(a, (short)(a.length + 1));
+      throw new Error("Should throw AIOOBE");
+    } catch (ArrayIndexOutOfBoundsException e) {
+    }
+    for (int i = 0; i < a.length; i++) {
+      expectEquals(222, a[i]);
+    }
+
+    try {
+      shortBound2(a, (short)(a.length + 1));
+      throw new Error("Should throw AIOOBE");
+    } catch (ArrayIndexOutOfBoundsException e) {
+    }
+    for (int i = 0; i < a.length; i++) {
+      expectEquals(444, a[i]);
+    }
+
+    narrowingFromLong(a, a.length);
+    for (int i = 0; i < a.length; i++) {
+      expectEquals(888, a[i]);
+    }
+
     System.out.println("passed");
   }
 
diff --git a/test/618-checker-induction/src/Main.java b/test/618-checker-induction/src/Main.java
index ecc129a..ad3ff44 100644
--- a/test/618-checker-induction/src/Main.java
+++ b/test/618-checker-induction/src/Main.java
@@ -465,6 +465,20 @@
     return i;
   }
 
+  // TODO: handle as closed/empty eventually?
+  static int mainIndexShort1(short s) {
+    int i = 0;
+    for (i = 0; i < s; i++) { }
+    return i;
+  }
+
+  // TODO: handle as closed/empty eventually?
+  static int mainIndexShort2(short s) {
+    int i = 0;
+    for (i = 0; s > i; i++) { }
+    return i;
+  }
+
   /// CHECK-START: int Main.periodicReturnedN(int) loop_optimization (before)
   /// CHECK-DAG: <<Phi1:i\d+>> Phi               loop:<<Loop:B\d+>> outer_loop:none
   /// CHECK-DAG: <<Phi2:i\d+>> Phi               loop:<<Loop>>      outer_loop:none
@@ -693,6 +707,75 @@
     return x;
   }
 
+  /// CHECK-START: float Main.periodicFloat10() loop_optimization (before)
+  /// CHECK-DAG: <<Phi1:i\d+>> Phi               loop:<<Loop:B\d+>> outer_loop:none
+  /// CHECK-DAG: <<Phi2:f\d+>> Phi               loop:<<Loop>>      outer_loop:none
+  /// CHECK-DAG: <<Phi3:f\d+>> Phi               loop:<<Loop>>      outer_loop:none
+  /// CHECK-DAG: <<Phi4:f\d+>> Phi               loop:<<Loop>>      outer_loop:none
+  /// CHECK-DAG:               Return [<<Phi2>>] loop:none
+  //
+  /// CHECK-START: float Main.periodicFloat10() loop_optimization (after)
+  /// CHECK-NOT: Phi
+  //
+  /// CHECK-START: float Main.periodicFloat10() loop_optimization (after)
+  /// CHECK-DAG: <<Float:f\d+>>  FloatConstant 2    loop:none
+  /// CHECK-DAG:                 Return [<<Float>>] loop:none
+  private static float periodicFloat10() {
+    float r = 4.5f;
+    float s = 2.0f;
+    float t = -1.0f;
+    for (int i = 0; i < 10; i++) {
+      float tmp = t; t = r; r = s; s = tmp;
+    }
+    return r;
+  }
+
+  /// CHECK-START: float Main.periodicFloat11() loop_optimization (before)
+  /// CHECK-DAG: <<Phi1:i\d+>> Phi               loop:<<Loop:B\d+>> outer_loop:none
+  /// CHECK-DAG: <<Phi2:f\d+>> Phi               loop:<<Loop>>      outer_loop:none
+  /// CHECK-DAG: <<Phi3:f\d+>> Phi               loop:<<Loop>>      outer_loop:none
+  /// CHECK-DAG: <<Phi4:f\d+>> Phi               loop:<<Loop>>      outer_loop:none
+  /// CHECK-DAG:               Return [<<Phi2>>] loop:none
+  //
+  /// CHECK-START: float Main.periodicFloat11() loop_optimization (after)
+  /// CHECK-NOT: Phi
+  //
+  /// CHECK-START: float Main.periodicFloat11() loop_optimization (after)
+  /// CHECK-DAG: <<Float:f\d+>>  FloatConstant -1   loop:none
+  /// CHECK-DAG:                 Return [<<Float>>] loop:none
+  private static float periodicFloat11() {
+    float r = 4.5f;
+    float s = 2.0f;
+    float t = -1.0f;
+    for (int i = 0; i < 11; i++) {
+      float tmp = t; t = r; r = s; s = tmp;
+    }
+    return r;
+  }
+
+  /// CHECK-START: float Main.periodicFloat12() loop_optimization (before)
+  /// CHECK-DAG: <<Phi1:i\d+>> Phi               loop:<<Loop:B\d+>> outer_loop:none
+  /// CHECK-DAG: <<Phi2:f\d+>> Phi               loop:<<Loop>>      outer_loop:none
+  /// CHECK-DAG: <<Phi3:f\d+>> Phi               loop:<<Loop>>      outer_loop:none
+  /// CHECK-DAG: <<Phi4:f\d+>> Phi               loop:<<Loop>>      outer_loop:none
+  /// CHECK-DAG:               Return [<<Phi2>>] loop:none
+  //
+  /// CHECK-START: float Main.periodicFloat12() loop_optimization (after)
+  /// CHECK-NOT: Phi
+  //
+  /// CHECK-START: float Main.periodicFloat12() loop_optimization (after)
+  /// CHECK-DAG: <<Float:f\d+>>  FloatConstant 4.5  loop:none
+  /// CHECK-DAG:                 Return [<<Float>>] loop:none
+  private static float periodicFloat12() {
+    float r = 4.5f;
+    float s = 2.0f;
+    float t = -1.0f;
+    for (int i = 0; i < 12; i++) {
+      float tmp = t; t = r; r = s; s = tmp;
+    }
+    return r;
+  }
+
   private static int exceptionExitBeforeAdd() {
     int k = 0;
     try {
@@ -779,6 +862,8 @@
     for (int n = -4; n < 4; n++) {
       int tc = (n <= 0) ? 0 : n;
       expectEquals(tc, mainIndexReturnedN(n));
+      expectEquals(tc, mainIndexShort1((short) n));
+      expectEquals(tc, mainIndexShort2((short) n));
       expectEquals(tc & 1, periodicReturnedN(n));
       expectEquals((tc * (tc + 1)) / 2, getSumN(n));
     }
@@ -803,6 +888,10 @@
       expectEquals(!even, periodicBoolIdiom3N(false, n));
     }
 
+    expectEquals( 2.0f, periodicFloat10());
+    expectEquals(-1.0f, periodicFloat11());
+    expectEquals( 4.5f, periodicFloat12());
+
     expectEquals(100, exceptionExitBeforeAdd());
     expectEquals(100, exceptionExitAfterAdd());
     a = null;
@@ -815,6 +904,12 @@
     System.out.println("passed");
   }
 
+  private static void expectEquals(float expected, float result) {
+    if (expected != result) {
+      throw new Error("Expected: " + expected + ", found: " + result);
+    }
+  }
+
   private static void expectEquals(int expected, int result) {
     if (expected != result) {
       throw new Error("Expected: " + expected + ", found: " + result);