diff options
author | 2014-09-26 15:09:06 -0700 | |
---|---|---|
committer | 2014-09-26 15:09:06 -0700 | |
commit | b504d2f89fdd5c01816bcbad752797cb78de0e99 (patch) | |
tree | 621edb6674f4e46bf19584ef14f4380d7263c736 | |
parent | 266b4689731f2c69af0f2854aaab947cf6e89f84 (diff) |
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
-rw-r--r-- | compiler/dex/quick/arm64/utility_arm64.cc | 6 | ||||
-rw-r--r-- | test/083-compiler-regressions/expected.txt | 1 | ||||
-rw-r--r-- | test/083-compiler-regressions/src/Main.java | 13 |
3 files changed, 17 insertions, 3 deletions
diff --git a/compiler/dex/quick/arm64/utility_arm64.cc b/compiler/dex/quick/arm64/utility_arm64.cc index 5326e74e16..f58f83070b 100644 --- a/compiler/dex/quick/arm64/utility_arm64.cc +++ b/compiler/dex/quick/arm64/utility_arm64.cc @@ -345,7 +345,7 @@ bool Arm64Mir2Lir::InexpensiveConstantInt(int32_t value, Instruction::Code opcod 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::OpRegRegImm(OpKind op, RegStorage r_dest, RegStorage r_src1, 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 @@ LIR* Arm64Mir2Lir::OpRegImm64(OpKind op, RegStorage r_dest_src1, int64_t value) 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 e907fd1d58..5251c17335 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 8d7bf01192..8010711725 100644 --- a/test/083-compiler-regressions/src/Main.java +++ b/test/083-compiler-regressions/src/Main.java @@ -30,6 +30,7 @@ public class Main { } public static void main(String args[]) throws Exception { + b17630605(); b17411468(); b2296099Test(); b2302318Test(); @@ -62,6 +63,18 @@ public class Main { 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; |