Quick compiler: aarch64 codegen & long_min literal

Int64 overflow during instruction selection caused incorrect
code patterns to emitted in some cases of long operations with
an immediate value of 0x8000000000000000.

The code in question was attempting to determine if the immediate
operand would fit in aarch64 immediate instruction variants.

Internal b/17630605

Change-Id: I8177021b73e51302bc1032387d83b1dd567ed6db
diff --git a/compiler/dex/quick/arm64/utility_arm64.cc b/compiler/dex/quick/arm64/utility_arm64.cc
index 5326e74..f58f830 100644
--- a/compiler/dex/quick/arm64/utility_arm64.cc
+++ b/compiler/dex/quick/arm64/utility_arm64.cc
@@ -345,7 +345,7 @@
   case Instruction::SUB_INT_2ADDR:
     // The code below is consistent with the implementation of OpRegRegImm().
     {
-      int32_t abs_value = std::abs(value);
+      uint32_t abs_value = (value == INT_MIN) ? value : std::abs(value);
       if (abs_value < 0x1000) {
         return true;
       } else if ((abs_value & UINT64_C(0xfff)) == 0 && ((abs_value >> 12) < 0x1000)) {
@@ -809,7 +809,7 @@
 LIR* Arm64Mir2Lir::OpRegRegImm64(OpKind op, RegStorage r_dest, RegStorage r_src1, int64_t value) {
   LIR* res;
   bool neg = (value < 0);
-  int64_t abs_value = (neg) ? -value : value;
+  uint64_t abs_value = (neg & !(value == LLONG_MIN)) ? -value : value;
   ArmOpcode opcode = kA64Brk1d;
   ArmOpcode alt_opcode = kA64Brk1d;
   bool is_logical = false;
@@ -942,7 +942,7 @@
   ArmOpcode neg_opcode = kA64Brk1d;
   bool shift;
   bool neg = (value < 0);
-  uint64_t abs_value = (neg) ? -value : value;
+  uint64_t abs_value = (neg & !(value == LLONG_MIN)) ? -value : value;
 
   if (LIKELY(abs_value < 0x1000)) {
     // abs_value is a 12-bit immediate.
diff --git a/test/083-compiler-regressions/expected.txt b/test/083-compiler-regressions/expected.txt
index e907fd1..5251c17 100644
--- a/test/083-compiler-regressions/expected.txt
+++ b/test/083-compiler-regressions/expected.txt
@@ -1,3 +1,4 @@
+b17630605 passes
 b17411468 passes
 b2296099 passes
 b2302318 passes
diff --git a/test/083-compiler-regressions/src/Main.java b/test/083-compiler-regressions/src/Main.java
index 8d7bf01..8010711 100644
--- a/test/083-compiler-regressions/src/Main.java
+++ b/test/083-compiler-regressions/src/Main.java
@@ -30,6 +30,7 @@
     }
 
     public static void main(String args[]) throws Exception {
+        b17630605();
         b17411468();
         b2296099Test();
         b2302318Test();
@@ -62,6 +63,18 @@
         minDoubleWith3ConstsTest();
     }
 
+    public static void b17630605() {
+      // b/17630605 - failure to properly handle min long immediates.
+      long a1 = 40455547223404749L;
+      long a2 = Long.MIN_VALUE;
+      long answer = a1 + a2;
+      if (answer == -9182916489631371059L) {
+          System.out.println("b17630605 passes");
+      } else {
+          System.out.println("b17630605 fails: " + answer);
+      }
+    }
+
     public static void b17411468() {
       // b/17411468 - inline Math.round failure.
       double d1 = 1.0;