summaryrefslogtreecommitdiffstats
path: root/compiler
diff options
context:
space:
mode:
authorbuzbee <buzbee@google.com>2014-05-17 23:16:26 -0700
committerbuzbee <buzbee@google.com>2014-05-19 20:02:10 -0700
commit082833c8d577db0b2bebc100602f31e4e971613e (patch)
treea92e43ebea394629dfb43adcce878404de5bc330 /compiler
parent6b522855f913617e00c1783264436145d00cc533 (diff)
downloadandroid_art-082833c8d577db0b2bebc100602f31e4e971613e.tar.gz
android_art-082833c8d577db0b2bebc100602f31e4e971613e.tar.bz2
android_art-082833c8d577db0b2bebc100602f31e4e971613e.zip
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
Diffstat (limited to 'compiler')
-rw-r--r--compiler/dex/quick/arm/codegen_arm.h1
-rw-r--r--compiler/dex/quick/arm/int_arm.cc10
-rw-r--r--compiler/dex/quick/arm/target_arm.cc12
-rw-r--r--compiler/dex/quick/arm/utility_arm.cc2
-rw-r--r--compiler/dex/quick/arm64/codegen_arm64.h1
-rw-r--r--compiler/dex/quick/arm64/target_arm64.cc4
-rw-r--r--compiler/dex/quick/gen_invoke.cc1
-rw-r--r--compiler/dex/quick/gen_loadstore.cc10
-rw-r--r--compiler/dex/quick/mips/codegen_mips.h1
-rw-r--r--compiler/dex/quick/mips/target_mips.cc11
-rw-r--r--compiler/dex/quick/mir_to_lir-inl.h4
-rw-r--r--compiler/dex/quick/mir_to_lir.cc3
-rw-r--r--compiler/dex/quick/mir_to_lir.h28
-rw-r--r--compiler/dex/quick/ralloc_util.cc194
-rw-r--r--compiler/dex/quick/x86/codegen_x86.h1
-rw-r--r--compiler/dex/quick/x86/int_x86.cc1
-rw-r--r--compiler/dex/quick/x86/target_x86.cc14
17 files changed, 165 insertions, 133 deletions
diff --git a/compiler/dex/quick/arm/codegen_arm.h b/compiler/dex/quick/arm/codegen_arm.h
index 1ee59c6558..876419c8b4 100644
--- a/compiler/dex/quick/arm/codegen_arm.h
+++ b/compiler/dex/quick/arm/codegen_arm.h
@@ -68,7 +68,6 @@ class ArmMir2Lir FINAL : public Mir2Lir {
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 2d4834c77c..384a008668 100644
--- a/compiler/dex/quick/arm/int_arm.cc
+++ b/compiler/dex/quick/arm/int_arm.cc
@@ -284,10 +284,10 @@ void ArmMir2Lir::GenFusedLongCmpBranch(BasicBlock* bb, MIR* mir) {
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 @@ void ArmMir2Lir::GenMulLong(Instruction::Code opcode, RegLocation rl_dest,
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 @@ void ArmMir2Lir::GenMulLong(Instruction::Code opcode, RegLocation rl_dest,
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 8cf1f86024..f7a7fe89f9 100644
--- a/compiler/dex/quick/arm/target_arm.cc
+++ b/compiler/dex/quick/arm/target_arm.cc
@@ -609,18 +609,6 @@ void ArmMir2Lir::CompilerInitializeRegAlloc() {
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 b0211d6388..86d32f4d72 100644
--- a/compiler/dex/quick/arm/utility_arm.cc
+++ b/compiler/dex/quick/arm/utility_arm.cc
@@ -853,7 +853,7 @@ LIR* ArmMir2Lir::LoadBaseDispBody(RegStorage r_base, int displacement, RegStorag
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 418a989064..6a27a7e702 100644
--- a/compiler/dex/quick/arm64/codegen_arm64.h
+++ b/compiler/dex/quick/arm64/codegen_arm64.h
@@ -68,7 +68,6 @@ class Arm64Mir2Lir : public Mir2Lir {
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 10be0d641f..18e605c253 100644
--- a/compiler/dex/quick/arm64/target_arm64.cc
+++ b/compiler/dex/quick/arm64/target_arm64.cc
@@ -632,10 +632,6 @@ void Arm64Mir2Lir::CompilerInitializeRegAlloc() {
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 24ed4a3346..3662592a02 100644
--- a/compiler/dex/quick/gen_invoke.cc
+++ b/compiler/dex/quick/gen_invoke.cc
@@ -1368,6 +1368,7 @@ bool Mir2Lir::GenInlinedAbsLong(CallInfo* info) {
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 8fcb09b955..f5e7e635de 100644
--- a/compiler/dex/quick/gen_loadstore.cc
+++ b/compiler/dex/quick/gen_loadstore.cc
@@ -145,10 +145,11 @@ RegLocation Mir2Lir::LoadValue(RegLocation rl_src, RegisterClass op_kind) {
// 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 @@ RegLocation Mir2Lir::LoadValueWide(RegLocation rl_src, RegisterClass op_kind) {
// 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 c5b40dadb3..0c59465260 100644
--- a/compiler/dex/quick/mips/codegen_mips.h
+++ b/compiler/dex/quick/mips/codegen_mips.h
@@ -68,7 +68,6 @@ class MipsMir2Lir FINAL : public Mir2Lir {
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 35345e8400..7a3da717c2 100644
--- a/compiler/dex/quick/mips/target_mips.cc
+++ b/compiler/dex/quick/mips/target_mips.cc
@@ -492,17 +492,6 @@ void MipsMir2Lir::CompilerInitializeRegAlloc() {
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 2973e149e6..ba6865d73c 100644
--- a/compiler/dex/quick/mir_to_lir-inl.h
+++ b/compiler/dex/quick/mir_to_lir-inl.h
@@ -26,10 +26,9 @@ namespace art {
/* 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 @@ inline void Mir2Lir::ClobberBody(RegisterInfo* p) {
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 10c245976a..ea8071d11a 100644
--- a/compiler/dex/quick/mir_to_lir.cc
+++ b/compiler/dex/quick/mir_to_lir.cc
@@ -318,6 +318,8 @@ void Mir2Lir::CompileDalvikInstruction(MIR* mir, BasicBlock* bb, LIR* label_list
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 @@ void Mir2Lir::CompileDalvikInstruction(MIR* mir, BasicBlock* bb, LIR* label_list
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 3201b60d12..687c41dffd 100644
--- a/compiler/dex/quick/mir_to_lir.h
+++ b/compiler/dex/quick/mir_to_lir.h
@@ -339,23 +339,35 @@ class Mir2Lir : public Backend {
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_; }
@@ -653,6 +665,7 @@ class Mir2Lir : public Backend {
RegStorage AllocLiveReg(int s_reg, int reg_class, bool wide);
RegStorage FindLiveReg(GrowableArray<RegisterInfo*> &regs, 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);
@@ -671,10 +684,10 @@ class Mir2Lir : public Backend {
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);
@@ -1074,7 +1087,6 @@ class Mir2Lir : public Backend {
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 bcc077bc18..06d05e2274 100644
--- a/compiler/dex/quick/ralloc_util.cc
+++ b/compiler/dex/quick/ralloc_util.cc
@@ -152,6 +152,9 @@ void Mir2Lir::Clobber(RegStorage reg) {
} 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 @@ void Mir2Lir::ClobberAliases(RegisterInfo* info) {
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 @@ void Mir2Lir::ClobberSReg(int s_reg) {
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 @@ RegStorage Mir2Lir::AllocTempBody(GrowableArray<RegisterInfo*> &regs, int* next_
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 @@ RegStorage Mir2Lir::AllocTempBody(GrowableArray<RegisterInfo*> &regs, int* next_
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::FreeTemp(RegStorage reg) {
}
}
+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 @@ void Mir2Lir::FlushAllRegs() {
FlushSpecificReg(info);
}
info->MarkDead();
- info->SetSReg(INVALID_SREG);
- info->ResetDefBody();
info->SetIsWide(false);
}
}
@@ -742,35 +756,48 @@ bool Mir2Lir::RegClassMatches(int reg_class, RegStorage reg) {
}
}
-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);
+ 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();
+ }
} else {
- if (loc.wide) {
+ 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);
}
- MarkLiveReg(reg, s_reg);
}
}
@@ -792,6 +819,13 @@ void Mir2Lir::MarkWide(RegStorage reg) {
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::MarkWide(RegStorage reg) {
}
}
+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 @@ void Mir2Lir::MarkInUse(RegStorage reg) {
}
bool Mir2Lir::CheckCorePoolSanity() {
- GrowableArray<RegisterInfo*>::Iterator it(&reg_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 @@ bool Mir2Lir::CheckCorePoolSanity() {
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 @@ RegLocation Mir2Lir::EvalLocWide(RegLocation loc, int reg_class, bool update) {
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 @@ RegLocation Mir2Lir::EvalLoc(RegLocation loc, int reg_class, bool update) {
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 Mir2Lir::GetReturnWide(bool is_double) {
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 cc0e1f23c0..52c870b1e7 100644
--- a/compiler/dex/quick/x86/codegen_x86.h
+++ b/compiler/dex/quick/x86/codegen_x86.h
@@ -68,7 +68,6 @@ class X86Mir2Lir FINAL : public Mir2Lir {
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 fbb17853e0..71a396241e 100644
--- a/compiler/dex/quick/x86/int_x86.cc
+++ b/compiler/dex/quick/x86/int_x86.cc
@@ -1542,7 +1542,6 @@ RegLocation X86Mir2Lir::GenShiftImmOpLong(Instruction::Code opcode, RegLocation
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 237c68c188..8f06791a91 100644
--- a/compiler/dex/quick/x86/target_x86.cc
+++ b/compiler/dex/quick/x86/target_x86.cc
@@ -572,20 +572,6 @@ void X86Mir2Lir::CompilerInitializeRegAlloc() {
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;