Reuse promoted register temporarily
AtomicLong (x86) is implemented as an intrinsic, which uses
the cmpxchng8b instruction.
This instruction requires 4 physical registers plus 2 more used for
the memory operand. On x86 we have only 4 temporaries. The code tried
to solve this by using MarkTemp utility, but this was not meant to be
used with promoted registers. The problem is that MarkTemp does not
spill anything and as a result we can lose VR.
If the registers are promoted this patch just reuses the values pushed
on the stack.
Change-Id: Ifec9183e2483cf704d0d1166a1004a9aa07b4f1d
Signed-off-by: Serguei Katkov <serguei.i.katkov@intel.com>
Signed-off-by: Yevgeny Rouban <yevgeny.y.rouban@intel.com>
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);