Refined range rule for ABS(x)

Rationale;
ABS(minint) = minint prevents assuming >=0 always.
With a fail-before(sig11)/pass-after regression test.

Test: 623
Change-Id: If5fb1580b207c7cdd964f7498849d1768bb1589d
diff --git a/compiler/optimizing/induction_var_range.cc b/compiler/optimizing/induction_var_range.cc
index f35aace..089340e 100644
--- a/compiler/optimizing/induction_var_range.cc
+++ b/compiler/optimizing/induction_var_range.cc
@@ -87,8 +87,10 @@
                IsGEZero(instruction->InputAt(1));
       case Intrinsics::kMathAbsInt:
       case Intrinsics::kMathAbsLong:
-        // Instruction ABS(x) is >= 0.
-        return true;
+        // Instruction ABS(>=0) is >= 0.
+        // NOTE: ABS(minint) = minint prevents assuming
+        //       >= 0 without looking at the argument.
+        return IsGEZero(instruction->InputAt(0));
       default:
         break;
     }
diff --git a/test/620-checker-bce-intrinsics/src/Main.java b/test/620-checker-bce-intrinsics/src/Main.java
index afc3c65..e0b5986 100644
--- a/test/620-checker-bce-intrinsics/src/Main.java
+++ b/test/620-checker-bce-intrinsics/src/Main.java
@@ -34,15 +34,15 @@
     return x;
   }
 
-  /// CHECK-START: int Main.oneArrayAbs(int[], int) BCE (before)
+  /// CHECK-START: int Main.oneArrayAbs(int[], int[]) BCE (before)
   /// CHECK-DAG: BoundsCheck loop:<<Loop:B\d+>> outer_loop:none
   //
-  /// CHECK-START: int Main.oneArrayAbs(int[], int) BCE (after)
+  /// CHECK-START: int Main.oneArrayAbs(int[], int[]) BCE (after)
   /// CHECK-NOT: BoundsCheck
   /// CHECK-NOT: Deoptimize
-  static int oneArrayAbs(int[] a, int lo) {
+  static int oneArrayAbs(int[] a, int[] b) {
     int x = 0;
-    for (int i = Math.abs(lo); i < a.length; i++) {
+    for (int i = Math.abs(b.length); i < a.length; i++) {
       x += a[i];
     }
     return x;
@@ -221,15 +221,15 @@
     int[] b = { 6, 7, 8, 9, 4, 2 };
     int[] c = { 1, 2, 3 };
     int[] d = { 8, 5, 3, 2 };
+    int[] e = { };
 
     expectEquals(15, oneArray(a));
     expectEquals(36, oneArray(b));
     expectEquals(6,  oneArray(c));
     expectEquals(18, oneArray(d));
 
-    expectEquals(5,  oneArrayAbs(a, -4));
-    expectEquals(15, oneArrayAbs(a, 0));
-    expectEquals(5,  oneArrayAbs(a, 4));
+    expectEquals(15, oneArrayAbs(a, e));
+    expectEquals(5,  oneArrayAbs(a, d));
 
     expectEquals(30, twoArrays(a, a));
     expectEquals(49, twoArrays(a, b));
diff --git a/test/623-checker-loop-regressions/src/Main.java b/test/623-checker-loop-regressions/src/Main.java
index 0e85612..056ed91 100644
--- a/test/623-checker-loop-regressions/src/Main.java
+++ b/test/623-checker-loop-regressions/src/Main.java
@@ -464,6 +464,15 @@
     return r;
   }
 
+  static int absCanBeNegative(int x) {
+    int a[] = { 1, 2, 3 };
+    int y = 0;
+    for (int i = Math.abs(x); i < a.length; i++) {
+      y += a[i];
+    }
+    return y;
+  }
+
   public static void main(String[] args) {
     expectEquals(10, earlyExitFirst(-1));
     for (int i = 0; i <= 10; i++) {
@@ -586,6 +595,24 @@
       expectEquals(11, f[i]);
     }
 
+    expectEquals(0, absCanBeNegative(-3));
+    expectEquals(3, absCanBeNegative(-2));
+    expectEquals(5, absCanBeNegative(-1));
+    expectEquals(6, absCanBeNegative(0));
+    expectEquals(5, absCanBeNegative(1));
+    expectEquals(3, absCanBeNegative(2));
+    expectEquals(0, absCanBeNegative(3));
+    expectEquals(0, absCanBeNegative(Integer.MAX_VALUE));
+    // Abs(min_int) = min_int.
+    int verify = 0;
+    try {
+      absCanBeNegative(Integer.MIN_VALUE);
+      verify = 1;
+    } catch (ArrayIndexOutOfBoundsException e) {
+      verify = 2;
+    }
+    expectEquals(2, verify);
+
     System.out.println("passed");
   }