From 8958f7f8702327e713264d0538ab5dec586f3738 Mon Sep 17 00:00:00 2001 From: Vladimir Marko Date: Fri, 19 Jun 2015 14:56:38 +0100 Subject: Quick: Handle total high/low register overlap on arm/mips. OpRegCopyWide() in arm and mips backends didn't handle the total register overlap when the registers holding the source and destination pairs are the same but in reverse order. Bug: 21897012 Change-Id: Ia1f0005cbf5cc1c2d30899575dea21b3efa20ae6 --- compiler/dex/quick/arm/int_arm.cc | 11 ++++++++--- compiler/dex/quick/mips/int_mips.cc | 12 +++++++++--- 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/compiler/dex/quick/arm/int_arm.cc b/compiler/dex/quick/arm/int_arm.cc index 6d30e72f86..cf0188456d 100644 --- a/compiler/dex/quick/arm/int_arm.cc +++ b/compiler/dex/quick/arm/int_arm.cc @@ -471,13 +471,18 @@ void ArmMir2Lir::OpRegCopyWide(RegStorage r_dest, RegStorage r_src) { NewLIR3(kThumb2Fmrrd, r_dest.GetLowReg(), r_dest.GetHighReg(), r_src.GetReg()); } else { // Handle overlap - if (r_src.GetHighReg() == r_dest.GetLowReg()) { - DCHECK_NE(r_src.GetLowReg(), r_dest.GetHighReg()); + if (r_src.GetHighReg() != r_dest.GetLowReg()) { + OpRegCopy(r_dest.GetLow(), r_src.GetLow()); + OpRegCopy(r_dest.GetHigh(), r_src.GetHigh()); + } else if (r_src.GetLowReg() != r_dest.GetHighReg()) { OpRegCopy(r_dest.GetHigh(), r_src.GetHigh()); OpRegCopy(r_dest.GetLow(), r_src.GetLow()); } else { + RegStorage r_tmp = AllocTemp(); + OpRegCopy(r_tmp, r_src.GetHigh()); OpRegCopy(r_dest.GetLow(), r_src.GetLow()); - OpRegCopy(r_dest.GetHigh(), r_src.GetHigh()); + OpRegCopy(r_dest.GetHigh(), r_tmp); + FreeTemp(r_tmp); } } } diff --git a/compiler/dex/quick/mips/int_mips.cc b/compiler/dex/quick/mips/int_mips.cc index 9319c64784..f5ad7c7c33 100644 --- a/compiler/dex/quick/mips/int_mips.cc +++ b/compiler/dex/quick/mips/int_mips.cc @@ -258,13 +258,19 @@ void MipsMir2Lir::OpRegCopyWide(RegStorage r_dest, RegStorage r_src) { } } else { // Here if both src and dest are core registers. - // Handle overlap. - if (r_src.GetHighReg() == r_dest.GetLowReg()) { + // Handle overlap + if (r_src.GetHighReg() != r_dest.GetLowReg()) { + OpRegCopy(r_dest.GetLow(), r_src.GetLow()); + OpRegCopy(r_dest.GetHigh(), r_src.GetHigh()); + } else if (r_src.GetLowReg() != r_dest.GetHighReg()) { OpRegCopy(r_dest.GetHigh(), r_src.GetHigh()); OpRegCopy(r_dest.GetLow(), r_src.GetLow()); } else { + RegStorage r_tmp = AllocTemp(); + OpRegCopy(r_tmp, r_src.GetHigh()); OpRegCopy(r_dest.GetLow(), r_src.GetLow()); - OpRegCopy(r_dest.GetHigh(), r_src.GetHigh()); + OpRegCopy(r_dest.GetHigh(), r_tmp); + FreeTemp(r_tmp); } } } -- cgit v1.2.3-59-g8ed1b