Quick compiler: fix x86 special identity
The Quick compiler recognizes and specially handles a set of
small methods - including those that simply return one of their
arguments. For x86, special identity was broken if the returned
argument was a double that was passed half in register and half
in memory.
internal b/17325447
(cherry picked from commit e8f74e58b476520cfc53970304c67b800994e33d)
Change-Id: I9afea5ef34498306528e0804489b5144e9e9aec3
diff --git a/compiler/dex/quick/mir_to_lir.cc b/compiler/dex/quick/mir_to_lir.cc
index e519011..6e0fe02 100644
--- a/compiler/dex/quick/mir_to_lir.cc
+++ b/compiler/dex/quick/mir_to_lir.cc
@@ -200,6 +200,16 @@
RegStorage reg_arg_low = GetArgMappingToPhysicalReg(in_position);
RegStorage reg_arg_high = GetArgMappingToPhysicalReg(in_position + 1);
+ if (cu_->instruction_set == kX86) {
+ // Can't handle double split between reg & memory. Flush reg half to memory.
+ if (rl_dest.reg.IsDouble() && (reg_arg_low.Valid() != reg_arg_high.Valid())) {
+ DCHECK(reg_arg_low.Valid());
+ DCHECK(!reg_arg_high.Valid());
+ Store32Disp(TargetPtrReg(kSp), offset, reg_arg_low);
+ reg_arg_low = RegStorage::InvalidReg();
+ }
+ }
+
if (reg_arg_low.Valid() && reg_arg_high.Valid()) {
OpRegCopyWide(rl_dest.reg, RegStorage::MakeRegPair(reg_arg_low, reg_arg_high));
} else if (reg_arg_low.Valid() && !reg_arg_high.Valid()) {
diff --git a/test/083-compiler-regressions/expected.txt b/test/083-compiler-regressions/expected.txt
index 5251c17..82d36e3 100644
--- a/test/083-compiler-regressions/expected.txt
+++ b/test/083-compiler-regressions/expected.txt
@@ -1,3 +1,4 @@
+b17325447 passes
b17630605 passes
b17411468 passes
b2296099 passes
diff --git a/test/083-compiler-regressions/src/Main.java b/test/083-compiler-regressions/src/Main.java
index 8010711..ab0febf 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 {
+ b17325447();
b17630605();
b17411468();
b2296099Test();
@@ -63,6 +64,31 @@
minDoubleWith3ConstsTest();
}
+ public static double b17325447_i1(int i1, double f) {
+ return f;
+ }
+
+ public static double b17325447_i2(int i1, int i2, double f) {
+ return f;
+ }
+
+ public static double b17325447_i3(int i1, int i2, int i3, double f) {
+ return f;
+ }
+
+ public static void b17325447() {
+ // b/17325447 - x86 handling of special identity method w/ double spanning reg/mem.
+ double d = 0.0;
+ d += b17325447_i1(123, 1.0);
+ d += b17325447_i2(123, 456, 2.0);
+ d += b17325447_i3(123, 456, 789, 3.0);
+ if (d == 6.0) {
+ System.out.println("b17325447 passes");
+ } else {
+ System.out.println("b17325447 fails: " + d);
+ }
+ }
+
public static void b17630605() {
// b/17630605 - failure to properly handle min long immediates.
long a1 = 40455547223404749L;