diff options
author | 2014-09-12 10:40:47 -0700 | |
---|---|---|
committer | 2014-09-12 12:36:19 -0700 | |
commit | 98216e53f8d538b4386b80b896edfa20e9734827 (patch) | |
tree | 613750f3dd0f5cdb3fd3996a0660cde004c8c6ed | |
parent | 3892cf8da7d5e76c0dee585fc8f69df773680525 (diff) |
Quick compiler (arm64) Fix inline Math.round()
Math.round is detected and inlined for arm64. However, the
arm64 backend incorrectly modified a source operand in place
during the round sequence. Depending on how registers are
allocated, that modification could persist. Changed to use a
temp register for the intermediate result.
Internal b/17411468
Change-Id: I7c636f985e193f8ff838768fde3b741e443bb1bb
-rw-r--r-- | compiler/dex/quick/arm64/fp_arm64.cc | 7 | ||||
-rw-r--r-- | test/083-compiler-regressions/expected.txt | 1 | ||||
-rw-r--r-- | test/083-compiler-regressions/src/Main.java | 12 |
3 files changed, 17 insertions, 3 deletions
diff --git a/compiler/dex/quick/arm64/fp_arm64.cc b/compiler/dex/quick/arm64/fp_arm64.cc index d0b2636453..7268d707d9 100644 --- a/compiler/dex/quick/arm64/fp_arm64.cc +++ b/compiler/dex/quick/arm64/fp_arm64.cc @@ -424,11 +424,12 @@ bool Arm64Mir2Lir::GenInlinedRound(CallInfo* info, bool is_double) { RegLocation rl_dest = (is_double) ? InlineTargetWide(info) : InlineTarget(info); rl_src = (is_double) ? LoadValueWide(rl_src, kFPReg) : LoadValue(rl_src, kFPReg); RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true); + RegStorage r_imm_point5 = (is_double) ? AllocTempDouble() : AllocTempSingle(); RegStorage r_tmp = (is_double) ? AllocTempDouble() : AllocTempSingle(); // 0.5f and 0.5d are encoded in the same way. - NewLIR2(kA64Fmov2fI | wide, r_tmp.GetReg(), encoded_imm); - NewLIR3(kA64Fadd3fff | wide, rl_src.reg.GetReg(), rl_src.reg.GetReg(), r_tmp.GetReg()); - NewLIR2((is_double) ? kA64Fcvtms2xS : kA64Fcvtms2ws, rl_result.reg.GetReg(), rl_src.reg.GetReg()); + NewLIR2(kA64Fmov2fI | wide, r_imm_point5.GetReg(), encoded_imm); + NewLIR3(kA64Fadd3fff | wide, r_tmp.GetReg(), rl_src.reg.GetReg(), r_imm_point5.GetReg()); + NewLIR2((is_double) ? kA64Fcvtms2xS : kA64Fcvtms2ws, rl_result.reg.GetReg(), r_tmp.GetReg()); (is_double) ? StoreValueWide(rl_dest, rl_result) : StoreValue(rl_dest, rl_result); return true; } diff --git a/test/083-compiler-regressions/expected.txt b/test/083-compiler-regressions/expected.txt index f8d92cc221..e907fd1d58 100644 --- a/test/083-compiler-regressions/expected.txt +++ b/test/083-compiler-regressions/expected.txt @@ -1,3 +1,4 @@ +b17411468 passes b2296099 passes b2302318 passes b2487514 passes diff --git a/test/083-compiler-regressions/src/Main.java b/test/083-compiler-regressions/src/Main.java index c089c527ab..8d7bf01192 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 { + b17411468(); b2296099Test(); b2302318Test(); b2487514Test(); @@ -61,6 +62,17 @@ public class Main { minDoubleWith3ConstsTest(); } + public static void b17411468() { + // b/17411468 - inline Math.round failure. + double d1 = 1.0; + double d2 = Math.round(d1); + if (d1 == d2) { + System.out.println("b17411468 passes"); + } else { + System.out.println("b17411468 fails: Math.round(" + d1 + ") returned " + d2); + } + } + public static double minDouble(double a, double b, double c) { return Math.min(Math.min(a, b), c); } |