ART: Fix clobbering low part in 32-bit version of X86Mir2Lir::GenNegDouble
If source registers overlap destination registers the low part of result can be clobbered in current implementation.
For example, for 'neg-double v5, v6' bytecode compiler can generates the following instructions:
lea ecx, [edx + 0x80000000]
mov eax, ecx
The fix forces source registers to be temp so there is no need to copy the low part.
Change-Id: I986ca17d1dc45c9e9d44a66e501cd354af496fde
Signed-off-by: Pavel Vyssotski <pavel.n.vyssotski@intel.com>
diff --git a/compiler/dex/quick/x86/fp_x86.cc b/compiler/dex/quick/x86/fp_x86.cc
index bc02eee..4825db6 100755
--- a/compiler/dex/quick/x86/fp_x86.cc
+++ b/compiler/dex/quick/x86/fp_x86.cc
@@ -584,16 +584,16 @@
void X86Mir2Lir::GenNegDouble(RegLocation rl_dest, RegLocation rl_src) {
RegLocation rl_result;
rl_src = LoadValueWide(rl_src, kCoreReg);
- rl_result = EvalLocWide(rl_dest, kCoreReg, true);
if (cu_->target64) {
+ rl_result = EvalLocWide(rl_dest, kCoreReg, true);
OpRegCopy(rl_result.reg, rl_src.reg);
// Flip sign bit.
NewLIR2(kX86Rol64RI, rl_result.reg.GetReg(), 1);
NewLIR2(kX86Xor64RI, rl_result.reg.GetReg(), 1);
NewLIR2(kX86Ror64RI, rl_result.reg.GetReg(), 1);
} else {
- OpRegRegImm(kOpAdd, rl_result.reg.GetHigh(), rl_src.reg.GetHigh(), 0x80000000);
- OpRegCopy(rl_result.reg, rl_src.reg);
+ rl_result = ForceTempWide(rl_src);
+ OpRegRegImm(kOpAdd, rl_result.reg.GetHigh(), rl_result.reg.GetHigh(), 0x80000000);
}
StoreValueWide(rl_dest, rl_result);
}