Quick compiler, out of registers fix
It turns out that the register pool sanity checker was not
working as expected, leaving some inconsistencies unreported.
This could result in "out of registers" failures, as well
as other more subtle problems.
This CL fixes the sanity checker, adds a lot more check and cleans
up the previously undetected episodes of insanity.
Cherry-pick of internal change 468162
Change-Id: Id2da97e99105a4c272c5fd256205a94b904ecea8
diff --git a/compiler/dex/quick/arm/codegen_arm.h b/compiler/dex/quick/arm/codegen_arm.h
index 1ee59c6..876419c 100644
--- a/compiler/dex/quick/arm/codegen_arm.h
+++ b/compiler/dex/quick/arm/codegen_arm.h
@@ -68,7 +68,6 @@
void AdjustSpillMask();
void ClobberCallerSave();
void FreeCallTemps();
- void FreeRegLocTemps(RegLocation rl_keep, RegLocation rl_free);
void LockCallTemps();
void MarkPreservedSingle(int v_reg, RegStorage reg);
void MarkPreservedDouble(int v_reg, RegStorage reg);
diff --git a/compiler/dex/quick/arm/int_arm.cc b/compiler/dex/quick/arm/int_arm.cc
index 2d4834c..384a008 100644
--- a/compiler/dex/quick/arm/int_arm.cc
+++ b/compiler/dex/quick/arm/int_arm.cc
@@ -284,10 +284,10 @@
ccode = FlipComparisonOrder(ccode);
}
if (rl_src2.is_const) {
- RegLocation rl_temp = UpdateLocWide(rl_src2);
+ rl_src2 = UpdateLocWide(rl_src2);
// Do special compare/branch against simple const operand if not already in registers.
int64_t val = mir_graph_->ConstantValueWide(rl_src2);
- if ((rl_temp.location != kLocPhysReg) &&
+ if ((rl_src2.location != kLocPhysReg) &&
((ModifiedImmediate(Low32Bits(val)) >= 0) && (ModifiedImmediate(High32Bits(val)) >= 0))) {
GenFusedLongCmpImmBranch(bb, rl_src1, val, ccode);
return;
@@ -1092,6 +1092,8 @@
DCHECK(!res_hi.Valid());
DCHECK_NE(rl_src1.reg.GetLowReg(), rl_src2.reg.GetLowReg());
DCHECK_NE(rl_src1.reg.GetHighReg(), rl_src2.reg.GetHighReg());
+ // Will force free src1_hi, so must clobber.
+ Clobber(rl_src1.reg);
FreeTemp(rl_src1.reg.GetHigh());
res_hi = AllocTemp();
}
@@ -1103,9 +1105,7 @@
tmp1.GetReg());
NewLIR4(kThumb2AddRRR, res_hi.GetReg(), tmp1.GetReg(), res_hi.GetReg(), 0);
if (reg_status == 2) {
- // Clobber rl_src1 since it was corrupted.
- FreeTemp(rl_src1.reg);
- Clobber(rl_src1.reg);
+ FreeTemp(rl_src1.reg.GetLow());
}
}
diff --git a/compiler/dex/quick/arm/target_arm.cc b/compiler/dex/quick/arm/target_arm.cc
index 8cf1f86..f7a7fe8 100644
--- a/compiler/dex/quick/arm/target_arm.cc
+++ b/compiler/dex/quick/arm/target_arm.cc
@@ -609,18 +609,6 @@
reg_pool_->next_dp_reg_ = 0;
}
-void ArmMir2Lir::FreeRegLocTemps(RegLocation rl_keep, RegLocation rl_free) {
- DCHECK(rl_keep.wide);
- DCHECK(rl_free.wide);
- if ((rl_free.reg.GetLowReg() != rl_keep.reg.GetLowReg()) &&
- (rl_free.reg.GetLowReg() != rl_keep.reg.GetHighReg()) &&
- (rl_free.reg.GetHighReg() != rl_keep.reg.GetLowReg()) &&
- (rl_free.reg.GetHighReg() != rl_keep.reg.GetHighReg())) {
- // No overlap, free.
- FreeTemp(rl_free.reg);
- }
-}
-
/*
* TUNING: is true leaf? Can't just use METHOD_IS_LEAF to determine as some
* instructions might call out to C/assembly helper functions. Until
diff --git a/compiler/dex/quick/arm/utility_arm.cc b/compiler/dex/quick/arm/utility_arm.cc
index b0211d6..86d32f4 100644
--- a/compiler/dex/quick/arm/utility_arm.cc
+++ b/compiler/dex/quick/arm/utility_arm.cc
@@ -853,7 +853,7 @@
load = NewLIR4(kThumb2LdrdI8, r_dest.GetLowReg(), r_dest.GetHighReg(), r_ptr.GetReg(),
encoded_disp);
}
- if ((displacement & ~1020) != 0 && !r_dest.IsFloat()) {
+ if ((displacement & ~1020) != 0 && r_dest.IsFloat()) {
FreeTemp(r_ptr);
}
already_generated = true;