Merge "Reuse promoted register temporarily"
diff --git a/compiler/dex/quick/x86/int_x86.cc b/compiler/dex/quick/x86/int_x86.cc
index 1fe0af9..c929265 100644
--- a/compiler/dex/quick/x86/int_x86.cc
+++ b/compiler/dex/quick/x86/int_x86.cc
@@ -734,6 +734,10 @@
   NewLIR2(kX86Cmp16TI8, offset.Int32Value(), val);
 }
 
+static bool IsInReg(X86Mir2Lir *pMir2Lir, const RegLocation &rl, int reg) {
+  return !rl.reg.IsInvalid() && rl.reg.GetReg() == reg && (pMir2Lir->IsLive(reg) || rl.home);
+}
+
 bool X86Mir2Lir::GenInlinedCas(CallInfo* info, bool is_long, bool is_object) {
   DCHECK_EQ(cu_->instruction_set, kX86);
   // Unused - RegLocation rl_src_unsafe = info->args[0];
@@ -746,6 +750,8 @@
   // If is_long, high half is in info->args[7]
 
   if (is_long) {
+    // TODO: avoid unnecessary loads of SI and DI when the values are in registers.
+    // TODO: CFI support.
     FlushAllRegs();
     LockCallTemps();
     LoadValueDirectWideFixed(rl_src_expected, rAX, rDX);
@@ -757,8 +763,14 @@
     MarkTemp(rSI);
     LockTemp(rSI);
     const int push_offset = 4 /* push edi */ + 4 /* push esi */;
-    LoadWordDisp(TargetReg(kSp), SRegOffset(rl_src_obj.s_reg_low) + push_offset, rDI);
-    LoadWordDisp(TargetReg(kSp), SRegOffset(rl_src_offset.s_reg_low) + push_offset, rSI);
+    int srcObjSp = IsInReg(this, rl_src_obj, rSI) ? 0
+                : (IsInReg(this, rl_src_obj, rDI) ? 4
+                : (SRegOffset(rl_src_obj.s_reg_low) + push_offset));
+    LoadWordDisp(TargetReg(kSp), srcObjSp, rDI);
+    int srcOffsetSp = IsInReg(this, rl_src_offset, rSI) ? 0
+                   : (IsInReg(this, rl_src_offset, rDI) ? 4
+                   : (SRegOffset(rl_src_offset.s_reg_low) + push_offset));
+    LoadWordDisp(TargetReg(kSp), srcOffsetSp, rSI);
     NewLIR4(kX86LockCmpxchg8bA, rDI, rSI, 0, 0);
     FreeTemp(rSI);
     UnmarkTemp(rSI);
diff --git a/test/083-compiler-regressions/expected.txt b/test/083-compiler-regressions/expected.txt
index 90d8634..f6de0e7 100644
--- a/test/083-compiler-regressions/expected.txt
+++ b/test/083-compiler-regressions/expected.txt
@@ -16,3 +16,4 @@
 longModTest passes
 testIfCcz passes
 ManyFloatArgs passes
+atomicLong passes
diff --git a/test/083-compiler-regressions/src/Main.java b/test/083-compiler-regressions/src/Main.java
index 96c71cf..2745c27 100644
--- a/test/083-compiler-regressions/src/Main.java
+++ b/test/083-compiler-regressions/src/Main.java
@@ -15,6 +15,7 @@
  */
 
 import java.util.concurrent.*;
+import java.util.concurrent.atomic.AtomicLong;
 
 /**
  * Test for Jit regressions.
@@ -47,6 +48,18 @@
         ZeroTests.longModTest();
         MirOpSelectTests.testIfCcz();
         ManyFloatArgs();
+        atomicLong();
+    }
+
+    public static void atomicLong() {
+        AtomicLong atomicLong = new AtomicLong();
+        atomicLong.addAndGet(3);
+        atomicLong.addAndGet(2);
+        atomicLong.addAndGet(1);
+        long result = atomicLong.get();
+        System.out.println(result == 6L ? "atomicLong passes" :
+          ("atomicLong failes: returns " + result + ", expected 6")
+        );
     }
 
     public static void returnConstantTest() {