Quick compiler, out of registers fix
Fixes b/15024623
It turns out that the register pool sanity checker was not
working as expected, leaving some inconsistencies unreported.
This CL fixes the sanity checker, adds a lot more check and cleans
up the previously undetected episodes of insanity.
Change-Id: I4d67db864ca5926a1975db251e7e631b65a86275
diff --git a/compiler/dex/quick/arm/codegen_arm.h b/compiler/dex/quick/arm/codegen_arm.h
index 6696cf7..e67f967 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 2e0e559..59d4b24 100644
--- a/compiler/dex/quick/arm/int_arm.cc
+++ b/compiler/dex/quick/arm/int_arm.cc
@@ -256,10 +256,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;
@@ -1058,6 +1058,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();
}
@@ -1069,9 +1071,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;
diff --git a/compiler/dex/quick/arm64/codegen_arm64.h b/compiler/dex/quick/arm64/codegen_arm64.h
index af0029c..e8b228c 100644
--- a/compiler/dex/quick/arm64/codegen_arm64.h
+++ b/compiler/dex/quick/arm64/codegen_arm64.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/arm64/target_arm64.cc b/compiler/dex/quick/arm64/target_arm64.cc
index 6caacc8..ee6d4ed 100644
--- a/compiler/dex/quick/arm64/target_arm64.cc
+++ b/compiler/dex/quick/arm64/target_arm64.cc
@@ -621,10 +621,6 @@
reg_pool_->next_dp_reg_ = 0;
}
-void Arm64Mir2Lir::FreeRegLocTemps(RegLocation rl_keep, RegLocation rl_free) {
- LOG(FATAL) << "Unexpected call to FreeRegLocTemps for Arm64";
-}
-
/*
* 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/gen_invoke.cc b/compiler/dex/quick/gen_invoke.cc
index 24ed4a3..3662592 100644
--- a/compiler/dex/quick/gen_invoke.cc
+++ b/compiler/dex/quick/gen_invoke.cc
@@ -1368,6 +1368,7 @@
OpRegRegReg(kOpAdc, rl_result.reg.GetHigh(), rl_src.reg.GetHigh(), sign_reg);
OpRegReg(kOpXor, rl_result.reg.GetLow(), sign_reg);
OpRegReg(kOpXor, rl_result.reg.GetHigh(), sign_reg);
+ FreeTemp(sign_reg);
StoreValueWide(rl_dest, rl_result);
return true;
}
diff --git a/compiler/dex/quick/gen_loadstore.cc b/compiler/dex/quick/gen_loadstore.cc
index 8fcb09b..f5e7e63 100644
--- a/compiler/dex/quick/gen_loadstore.cc
+++ b/compiler/dex/quick/gen_loadstore.cc
@@ -145,10 +145,11 @@
// Wrong register class, realloc, copy and transfer ownership.
RegStorage new_reg = AllocTypedTemp(rl_src.fp, op_kind);
OpRegCopy(new_reg, rl_src.reg);
- // Associate the old sreg with the new register and clobber the old register.
- GetRegInfo(new_reg)->SetSReg(GetRegInfo(rl_src.reg)->SReg());
+ // Clobber the old reg.
Clobber(rl_src.reg);
+ // ...and mark the new one live.
rl_src.reg = new_reg;
+ MarkLive(rl_src);
}
return rl_src;
}
@@ -222,10 +223,11 @@
// Wrong register class, realloc, copy and transfer ownership.
RegStorage new_regs = AllocTypedTempWide(rl_src.fp, op_kind);
OpRegCopyWide(new_regs, rl_src.reg);
- // Associate the old sreg with the new register and clobber the old register.
- GetRegInfo(new_regs)->SetSReg(GetRegInfo(rl_src.reg)->SReg());
+ // Clobber the old regs.
Clobber(rl_src.reg);
+ // ...and mark the new ones live.
rl_src.reg = new_regs;
+ MarkLive(rl_src);
}
return rl_src;
}
diff --git a/compiler/dex/quick/mips/codegen_mips.h b/compiler/dex/quick/mips/codegen_mips.h
index b7ea34f..fb74e80 100644
--- a/compiler/dex/quick/mips/codegen_mips.h
+++ b/compiler/dex/quick/mips/codegen_mips.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/mips/target_mips.cc b/compiler/dex/quick/mips/target_mips.cc
index 2821209..93b5e98 100644
--- a/compiler/dex/quick/mips/target_mips.cc
+++ b/compiler/dex/quick/mips/target_mips.cc
@@ -489,17 +489,6 @@
reg_pool_->next_dp_reg_ = 1;
}
-void MipsMir2Lir::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);
- }
-}
/*
* In the Arm code a it is typical to use the link register
* to hold the target address. However, for Mips we must
diff --git a/compiler/dex/quick/mir_to_lir-inl.h b/compiler/dex/quick/mir_to_lir-inl.h
index 2973e14..ba6865d 100644
--- a/compiler/dex/quick/mir_to_lir-inl.h
+++ b/compiler/dex/quick/mir_to_lir-inl.h
@@ -26,10 +26,9 @@
/* Mark a temp register as dead. Does not affect allocation state. */
inline void Mir2Lir::ClobberBody(RegisterInfo* p) {
DCHECK(p->IsTemp());
- if (!p->IsDead()) {
+ if (p->SReg() != INVALID_SREG) {
DCHECK(!(p->IsLive() && p->IsDirty())) << "Live & dirty temp in clobber";
p->MarkDead();
- p->ResetDefBody();
if (p->IsWide()) {
p->SetIsWide(false);
if (p->GetReg() != p->Partner()) {
@@ -37,7 +36,6 @@
p = GetRegInfo(p->Partner());
p->SetIsWide(false);
p->MarkDead();
- p->ResetDefBody();
}
}
}
diff --git a/compiler/dex/quick/mir_to_lir.cc b/compiler/dex/quick/mir_to_lir.cc
index 2c4ca88..3c6aef1 100644
--- a/compiler/dex/quick/mir_to_lir.cc
+++ b/compiler/dex/quick/mir_to_lir.cc
@@ -318,6 +318,8 @@
int opt_flags = mir->optimization_flags;
uint32_t vB = mir->dalvikInsn.vB;
uint32_t vC = mir->dalvikInsn.vC;
+ DCHECK(CheckCorePoolSanity()) << PrettyMethod(cu_->method_idx, *cu_->dex_file) << " @ 0x:"
+ << std::hex << current_dalvik_offset_;
// Prep Src and Dest locations.
int next_sreg = 0;
@@ -946,6 +948,7 @@
default:
LOG(FATAL) << "Unexpected opcode: " << opcode;
}
+ DCHECK(CheckCorePoolSanity());
} // NOLINT(readability/fn_size)
// Process extended MIR instructions
diff --git a/compiler/dex/quick/mir_to_lir.h b/compiler/dex/quick/mir_to_lir.h
index 6a0f3b2..eddf180 100644
--- a/compiler/dex/quick/mir_to_lir.h
+++ b/compiler/dex/quick/mir_to_lir.h
@@ -337,23 +337,35 @@
bool IsDead() { return (master_->liveness_ & storage_mask_) == 0; }
// Liveness of this view matches. Note: not equivalent to !IsDead().
bool IsLive() { return (master_->liveness_ & storage_mask_) == storage_mask_; }
- void MarkLive() { master_->liveness_ |= storage_mask_; }
+ void MarkLive(int s_reg) {
+ // TODO: Anything useful to assert here?
+ s_reg_ = s_reg;
+ master_->liveness_ |= storage_mask_;
+ }
void MarkDead() {
- master_->liveness_ &= ~storage_mask_;
- SetSReg(INVALID_SREG);
+ if (SReg() != INVALID_SREG) {
+ s_reg_ = INVALID_SREG;
+ master_->liveness_ &= ~storage_mask_;
+ ResetDefBody();
+ }
}
RegStorage GetReg() { return reg_; }
void SetReg(RegStorage reg) { reg_ = reg; }
bool IsTemp() { return is_temp_; }
void SetIsTemp(bool val) { is_temp_ = val; }
bool IsWide() { return wide_value_; }
- void SetIsWide(bool val) { wide_value_ = val; }
+ void SetIsWide(bool val) {
+ wide_value_ = val;
+ if (!val) {
+ // If not wide, reset partner to self.
+ SetPartner(GetReg());
+ }
+ }
bool IsDirty() { return dirty_; }
void SetIsDirty(bool val) { dirty_ = val; }
RegStorage Partner() { return partner_; }
void SetPartner(RegStorage partner) { partner_ = partner; }
- int SReg() { return s_reg_; }
- void SetSReg(int s_reg) { s_reg_ = s_reg; }
+ int SReg() { return (!IsTemp() || IsLive()) ? s_reg_ : INVALID_SREG; }
uint64_t DefUseMask() { return def_use_mask_; }
void SetDefUseMask(uint64_t def_use_mask) { def_use_mask_ = def_use_mask; }
RegisterInfo* Master() { return master_; }
@@ -651,6 +663,7 @@
RegStorage AllocLiveReg(int s_reg, int reg_class, bool wide);
RegStorage FindLiveReg(GrowableArray<RegisterInfo*> ®s, int s_reg);
void FreeTemp(RegStorage reg);
+ void FreeRegLocTemps(RegLocation rl_keep, RegLocation rl_free);
bool IsLive(RegStorage reg);
bool IsTemp(RegStorage reg);
bool IsPromoted(RegStorage reg);
@@ -669,10 +682,10 @@
void FlushAllRegs();
bool RegClassMatches(int reg_class, RegStorage reg);
void MarkLive(RegLocation loc);
- void MarkLiveReg(RegStorage reg, int s_reg);
void MarkTemp(RegStorage reg);
void UnmarkTemp(RegStorage reg);
void MarkWide(RegStorage reg);
+ void MarkNarrow(RegStorage reg);
void MarkClean(RegLocation loc);
void MarkDirty(RegLocation loc);
void MarkInUse(RegStorage reg);
@@ -1072,7 +1085,6 @@
virtual void AdjustSpillMask() = 0;
virtual void ClobberCallerSave() = 0;
virtual void FreeCallTemps() = 0;
- virtual void FreeRegLocTemps(RegLocation rl_keep, RegLocation rl_free) = 0;
virtual void LockCallTemps() = 0;
virtual void MarkPreservedSingle(int v_reg, RegStorage reg) = 0;
virtual void MarkPreservedDouble(int v_reg, RegStorage reg) = 0;
diff --git a/compiler/dex/quick/ralloc_util.cc b/compiler/dex/quick/ralloc_util.cc
index bcc077b..06d05e2 100644
--- a/compiler/dex/quick/ralloc_util.cc
+++ b/compiler/dex/quick/ralloc_util.cc
@@ -152,6 +152,9 @@
} else {
RegisterInfo* info = GetRegInfo(reg);
if (info->IsTemp() && !info->IsDead()) {
+ if (info->GetReg() != info->Partner()) {
+ ClobberBody(GetRegInfo(info->Partner()));
+ }
ClobberBody(info);
if (info->IsAliased()) {
ClobberAliases(info);
@@ -169,19 +172,7 @@
for (RegisterInfo* alias = info->GetAliasChain(); alias != nullptr;
alias = alias->GetAliasChain()) {
DCHECK(!alias->IsAliased()); // Only the master should be marked as alised.
- if (alias->SReg() != INVALID_SREG) {
- alias->SetSReg(INVALID_SREG);
- alias->ResetDefBody();
- if (alias->IsWide()) {
- alias->SetIsWide(false);
- if (alias->GetReg() != alias->Partner()) {
- RegisterInfo* p = GetRegInfo(alias->Partner());
- p->SetIsWide(false);
- p->MarkDead();
- p->ResetDefBody();
- }
- }
- }
+ ClobberBody(alias);
}
}
@@ -204,6 +195,11 @@
GrowableArray<RegisterInfo*>::Iterator iter(&tempreg_info_);
for (RegisterInfo* info = iter.Next(); info != NULL; info = iter.Next()) {
if (info->SReg() == s_reg) {
+ if (info->GetReg() != info->Partner()) {
+ // Dealing with a pair - clobber the other half.
+ DCHECK(!info->IsAliased());
+ ClobberBody(GetRegInfo(info->Partner()));
+ }
ClobberBody(info);
if (info->IsAliased()) {
ClobberAliases(info);
@@ -325,7 +321,7 @@
next = 0;
RegisterInfo* info = regs.Get(next);
// Try to allocate a register that doesn't hold a live value.
- if (info->IsTemp() && !info->InUse() && !info->IsLive()) {
+ if (info->IsTemp() && !info->InUse() && info->IsDead()) {
Clobber(info->GetReg());
info->MarkInUse();
/*
@@ -349,7 +345,13 @@
ClobberSReg(info->SReg());
Clobber(info->GetReg());
info->MarkInUse();
- info->SetIsWide(false);
+ if (info->IsWide()) {
+ RegisterInfo* partner = GetRegInfo(info->Partner());
+ DCHECK_EQ(info->GetReg().GetRegNum(), partner->Partner().GetRegNum());
+ DCHECK(partner->IsWide());
+ info->SetIsWide(false);
+ partner->SetIsWide(false);
+ }
*next_temp = next + 1;
return info->GetReg();
}
@@ -463,6 +465,20 @@
}
}
+void Mir2Lir::FreeRegLocTemps(RegLocation rl_keep, RegLocation rl_free) {
+ DCHECK(rl_keep.wide);
+ DCHECK(rl_free.wide);
+ int free_low = rl_free.reg.GetLowReg();
+ int free_high = rl_free.reg.GetHighReg();
+ int keep_low = rl_keep.reg.GetLowReg();
+ int keep_high = rl_keep.reg.GetHighReg();
+ if ((free_low != keep_low) && (free_low != keep_high) &&
+ (free_high != keep_low) && (free_high != keep_high)) {
+ // No overlap, free both
+ FreeTemp(rl_free.reg);
+ }
+}
+
bool Mir2Lir::IsLive(RegStorage reg) {
bool res;
if (reg.IsPair()) {
@@ -725,8 +741,6 @@
FlushSpecificReg(info);
}
info->MarkDead();
- info->SetSReg(INVALID_SREG);
- info->ResetDefBody();
info->SetIsWide(false);
}
}
@@ -742,35 +756,48 @@
}
}
-void Mir2Lir::MarkLiveReg(RegStorage reg, int s_reg) {
- RegisterInfo* info = GetRegInfo(reg);
- if ((info->SReg() == s_reg) && info->IsLive()) {
- return; // Already live.
- }
- if (s_reg != INVALID_SREG) {
- ClobberSReg(s_reg);
- if (info->IsTemp()) {
- info->MarkLive();
- }
- } else {
- // Can't be live if no associated s_reg.
- DCHECK(info->IsTemp());
- info->MarkDead();
- }
- info->SetSReg(s_reg);
-}
-
void Mir2Lir::MarkLive(RegLocation loc) {
RegStorage reg = loc.reg;
+ if (!IsTemp(reg)) {
+ return;
+ }
int s_reg = loc.s_reg_low;
- if (reg.IsPair()) {
- MarkLiveReg(reg.GetLow(), s_reg);
- MarkLiveReg(reg.GetHigh(), s_reg+1);
- } else {
- if (loc.wide) {
- ClobberSReg(s_reg + 1);
+ if (s_reg == INVALID_SREG) {
+ // Can't be live if no associated sreg.
+ if (reg.IsPair()) {
+ GetRegInfo(reg.GetLow())->MarkDead();
+ GetRegInfo(reg.GetHigh())->MarkDead();
+ } else {
+ GetRegInfo(reg)->MarkDead();
}
- MarkLiveReg(reg, s_reg);
+ } else {
+ if (reg.IsPair()) {
+ RegisterInfo* info_lo = GetRegInfo(reg.GetLow());
+ RegisterInfo* info_hi = GetRegInfo(reg.GetHigh());
+ if (info_lo->IsLive() && (info_lo->SReg() == s_reg) && info_hi->IsLive() &&
+ (info_hi->SReg() == s_reg)) {
+ return; // Already live.
+ }
+ ClobberSReg(s_reg);
+ ClobberSReg(s_reg + 1);
+ info_lo->MarkLive(s_reg);
+ info_hi->MarkLive(s_reg + 1);
+ } else {
+ RegisterInfo* info = GetRegInfo(reg);
+ if (info->IsLive() && (info->SReg() == s_reg)) {
+ return; // Already live.
+ }
+ ClobberSReg(s_reg);
+ if (loc.wide) {
+ ClobberSReg(s_reg + 1);
+ }
+ info->MarkLive(s_reg);
+ }
+ if (loc.wide) {
+ MarkWide(reg);
+ } else {
+ MarkNarrow(reg);
+ }
}
}
@@ -792,6 +819,13 @@
if (reg.IsPair()) {
RegisterInfo* info_lo = GetRegInfo(reg.GetLow());
RegisterInfo* info_hi = GetRegInfo(reg.GetHigh());
+ // Unpair any old partners.
+ if (info_lo->IsWide() && info_lo->Partner() != info_hi->GetReg()) {
+ GetRegInfo(info_lo->Partner())->SetIsWide(false);
+ }
+ if (info_hi->IsWide() && info_hi->Partner() != info_lo->GetReg()) {
+ GetRegInfo(info_hi->Partner())->SetIsWide(false);
+ }
info_lo->SetIsWide(true);
info_hi->SetIsWide(true);
info_lo->SetPartner(reg.GetHigh());
@@ -803,6 +837,13 @@
}
}
+void Mir2Lir::MarkNarrow(RegStorage reg) {
+ DCHECK(!reg.IsPair());
+ RegisterInfo* info = GetRegInfo(reg);
+ info->SetIsWide(false);
+ info->SetPartner(reg);
+}
+
void Mir2Lir::MarkClean(RegLocation loc) {
if (loc.reg.IsPair()) {
RegisterInfo* info = GetRegInfo(loc.reg.GetLow());
@@ -842,16 +883,17 @@
}
bool Mir2Lir::CheckCorePoolSanity() {
- GrowableArray<RegisterInfo*>::Iterator it(®_pool_->core_regs_);
+ GrowableArray<RegisterInfo*>::Iterator it(&tempreg_info_);
for (RegisterInfo* info = it.Next(); info != nullptr; info = it.Next()) {
- RegStorage my_reg = info->GetReg();
- if (info->IsWide() && my_reg.IsPair()) {
+ if (info->IsTemp() && info->IsLive() && info->IsWide()) {
+ RegStorage my_reg = info->GetReg();
int my_sreg = info->SReg();
RegStorage partner_reg = info->Partner();
RegisterInfo* partner = GetRegInfo(partner_reg);
DCHECK(partner != NULL);
DCHECK(partner->IsWide());
DCHECK_EQ(my_reg.GetReg(), partner->Partner().GetReg());
+ DCHECK(partner->IsLive());
int partner_sreg = partner->SReg();
if (my_sreg == INVALID_SREG) {
DCHECK_EQ(partner_sreg, INVALID_SREG);
@@ -859,13 +901,41 @@
int diff = my_sreg - partner_sreg;
DCHECK((diff == 0) || (diff == -1) || (diff == 1));
}
- } else {
- // TODO: add whatever sanity checks might be useful for 64BitSolo regs here.
- // TODO: sanity checks for floating point pools?
}
- if (!info->IsLive()) {
- DCHECK(info->DefStart() == NULL);
- DCHECK(info->DefEnd() == NULL);
+ if (info->Master() != info) {
+ // Aliased.
+ if (info->IsLive() && (info->SReg() != INVALID_SREG)) {
+ // If I'm live, master should not be live, but should show liveness in alias set.
+ DCHECK_EQ(info->Master()->SReg(), INVALID_SREG);
+ DCHECK(!info->Master()->IsDead());
+ } else if (!info->IsDead()) {
+ // If I'm not live, but there is liveness in the set master must be live.
+ DCHECK_EQ(info->SReg(), INVALID_SREG);
+ DCHECK(info->Master()->IsLive());
+ }
+ }
+ if (info->IsAliased()) {
+ // Has child aliases.
+ DCHECK_EQ(info->Master(), info);
+ if (info->IsLive() && (info->SReg() != INVALID_SREG)) {
+ // Master live, no child should be dead - all should show liveness in set.
+ for (RegisterInfo* p = info->GetAliasChain(); p != nullptr; p = p->GetAliasChain()) {
+ DCHECK(!p->IsDead());
+ DCHECK_EQ(p->SReg(), INVALID_SREG);
+ }
+ } else if (!info->IsDead()) {
+ // Master not live, one or more aliases must be.
+ bool live_alias = false;
+ for (RegisterInfo* p = info->GetAliasChain(); p != nullptr; p = p->GetAliasChain()) {
+ live_alias |= p->IsLive();
+ }
+ DCHECK(live_alias);
+ }
+ }
+ if (info->IsLive() && (info->SReg() == INVALID_SREG)) {
+ // If not fully live, should have INVALID_SREG and def's should be null.
+ DCHECK(info->DefStart() == nullptr);
+ DCHECK(info->DefEnd() == nullptr);
}
}
return true;
@@ -956,11 +1026,12 @@
if (!RegClassMatches(reg_class, loc.reg)) {
// Wrong register class. Reallocate and transfer ownership.
RegStorage new_regs = AllocTypedTempWide(loc.fp, reg_class);
- // Associate the old sreg with the new register and clobber the old register.
- GetRegInfo(new_regs)->SetSReg(GetRegInfo(loc.reg)->SReg());
+ // Clobber the old regs.
Clobber(loc.reg);
+ // ...and mark the new ones live.
loc.reg = new_regs;
MarkWide(loc.reg);
+ MarkLive(loc);
}
return loc;
}
@@ -989,10 +1060,11 @@
if (!RegClassMatches(reg_class, loc.reg)) {
// Wrong register class. Reallocate and transfer ownership.
RegStorage new_reg = AllocTypedTemp(loc.fp, reg_class);
- // Associate the old sreg with the new register and clobber the old register.
- GetRegInfo(new_reg)->SetSReg(GetRegInfo(loc.reg)->SReg());
+ // Clobber the old reg.
Clobber(loc.reg);
+ // ...and mark the new one live.
loc.reg = new_reg;
+ MarkLive(loc);
}
return loc;
}
@@ -1220,19 +1292,9 @@
RegLocation gpr_res = LocCReturnWide();
RegLocation fpr_res = LocCReturnDouble();
RegLocation res = is_double ? fpr_res : gpr_res;
- if (res.reg.IsPair()) {
- Clobber(res.reg);
- LockTemp(res.reg);
- // Does this wide value live in two registers or one vector register?
- if (res.reg.GetLowReg() != res.reg.GetHighReg()) {
- // FIXME: I think we want to mark these as wide as well.
- MarkWide(res.reg);
- }
- } else {
- Clobber(res.reg);
- LockTemp(res.reg);
- MarkWide(res.reg);
- }
+ Clobber(res.reg);
+ LockTemp(res.reg);
+ MarkWide(res.reg);
return res;
}
diff --git a/compiler/dex/quick/x86/codegen_x86.h b/compiler/dex/quick/x86/codegen_x86.h
index 11e7ff9..10ee651 100644
--- a/compiler/dex/quick/x86/codegen_x86.h
+++ b/compiler/dex/quick/x86/codegen_x86.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/x86/int_x86.cc b/compiler/dex/quick/x86/int_x86.cc
index 368234e..4613c79 100644
--- a/compiler/dex/quick/x86/int_x86.cc
+++ b/compiler/dex/quick/x86/int_x86.cc
@@ -1522,7 +1522,6 @@
LoadConstant(rl_result.reg.GetLow(), 0);
} else if (shift_amount > 31) {
OpRegCopy(rl_result.reg.GetHigh(), rl_src.reg.GetLow());
- FreeTemp(rl_src.reg.GetHigh());
NewLIR2(kX86Sal32RI, rl_result.reg.GetHighReg(), shift_amount - 32);
LoadConstant(rl_result.reg.GetLow(), 0);
} else {
diff --git a/compiler/dex/quick/x86/target_x86.cc b/compiler/dex/quick/x86/target_x86.cc
index 2db9845..dc60142 100644
--- a/compiler/dex/quick/x86/target_x86.cc
+++ b/compiler/dex/quick/x86/target_x86.cc
@@ -497,20 +497,6 @@
reg_pool_->next_dp_reg_ = 1;
}
-void X86Mir2Lir::FreeRegLocTemps(RegLocation rl_keep, RegLocation rl_free) {
- DCHECK(rl_keep.wide);
- DCHECK(rl_free.wide);
- int free_low = rl_free.reg.GetLowReg();
- int free_high = rl_free.reg.GetHighReg();
- int keep_low = rl_keep.reg.GetLowReg();
- int keep_high = rl_keep.reg.GetHighReg();
- if ((free_low != keep_low) && (free_low != keep_high) &&
- (free_high != keep_low) && (free_high != keep_high)) {
- // No overlap, free both
- FreeTemp(rl_free.reg);
- }
-}
-
void X86Mir2Lir::SpillCoreRegs() {
if (num_core_spills_ == 0) {
return;