ART: x86 specific clearing higher bits when converting long to int
The following problem description is taken from
https://android-review.googlesource.com/107261
If destination and source of long-to-int is the same physical
register on 64-bit then we do not emit any instructions but
consider that destination is a 32-bit view of source register.
As a result high part contains garbage. If the destination is
used later as index to array access then this garbage is used
in computation of address because address is 64-bit. For all
other cases garbage is just ignored.
A generic solution (113023) for all hw platforms was suggested
but rejected later for the sake of HW specific solution:
https://android-review.googlesource.com/113023
https://android-review.googlesource.com/114436
This patch is a rework of patch 113023 to stick with x86_64
specific changes: for 64-bit target this patch forces generating
reg-to-reg copy if the src and dest are the same physical
registers. This makes the higher bits be zeroed by 32-bit move
instruction.
Change-Id: Id29af839506ff9319ffba08b2e86e240fef4dafd
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 a063ce1..80cdc83 100755
--- a/compiler/dex/quick/x86/int_x86.cc
+++ b/compiler/dex/quick/x86/int_x86.cc
@@ -3213,6 +3213,26 @@
StoreValueWide(rl_dest, rl_result);
}
+void X86Mir2Lir::GenLongToInt(RegLocation rl_dest, RegLocation rl_src) {
+ rl_src = UpdateLocWide(rl_src);
+ rl_src = NarrowRegLoc(rl_src);
+ StoreValue(rl_dest, rl_src);
+
+ if (cu_->target64) {
+ // if src and dest are in the same phys reg then StoreValue generates
+ // no operation but we need explicit 32-bit mov R, R to clear
+ // the higher 32-bits
+ rl_dest = UpdateLoc(rl_dest);
+ if (rl_src.location == kLocPhysReg && rl_dest.location == kLocPhysReg
+ && IsSameReg(rl_src.reg, rl_dest.reg)) {
+ LIR* copy_lir = OpRegCopyNoInsert(rl_dest.reg, rl_dest.reg);
+ // remove nop flag set by OpRegCopyNoInsert if src == dest
+ copy_lir->flags.is_nop = false;
+ AppendLIR(copy_lir);
+ }
+ }
+}
+
void X86Mir2Lir::GenShiftOpLong(Instruction::Code opcode, RegLocation rl_dest,
RegLocation rl_src1, RegLocation rl_shift) {
if (!cu_->target64) {