diff options
-rw-r--r-- | compiler/dex/quick/mir_to_lir-inl.h | 3 | ||||
-rw-r--r-- | compiler/dex/quick/mir_to_lir.cc | 6 | ||||
-rw-r--r-- | compiler/dex/quick/mir_to_lir.h | 10 | ||||
-rw-r--r-- | compiler/dex/quick/ralloc_util.cc | 63 |
4 files changed, 54 insertions, 28 deletions
diff --git a/compiler/dex/quick/mir_to_lir-inl.h b/compiler/dex/quick/mir_to_lir-inl.h index b5b50a4..2973e14 100644 --- a/compiler/dex/quick/mir_to_lir-inl.h +++ b/compiler/dex/quick/mir_to_lir-inl.h @@ -25,7 +25,8 @@ namespace art { /* Mark a temp register as dead. Does not affect allocation state. */ inline void Mir2Lir::ClobberBody(RegisterInfo* p) { - if (p->IsTemp()) { + DCHECK(p->IsTemp()); + if (!p->IsDead()) { DCHECK(!(p->IsLive() && p->IsDirty())) << "Live & dirty temp in clobber"; p->MarkDead(); p->ResetDefBody(); diff --git a/compiler/dex/quick/mir_to_lir.cc b/compiler/dex/quick/mir_to_lir.cc index 0ffd189..77119a4 100644 --- a/compiler/dex/quick/mir_to_lir.cc +++ b/compiler/dex/quick/mir_to_lir.cc @@ -979,7 +979,7 @@ bool Mir2Lir::MethodBlockCodeGen(BasicBlock* bb) { } // Free temp registers and reset redundant store tracking. - ClobberAllRegs(); + ClobberAllTemps(); if (bb->block_type == kEntryBlock) { ResetRegPool(); @@ -994,7 +994,7 @@ bool Mir2Lir::MethodBlockCodeGen(BasicBlock* bb) { for (mir = bb->first_mir_insn; mir != NULL; mir = mir->next) { ResetRegPool(); if (cu_->disable_opt & (1 << kTrackLiveTemps)) { - ClobberAllRegs(); + ClobberAllTemps(); // Reset temp allocation to minimize differences when A/B testing. reg_pool_->ResetNextTemp(); } @@ -1074,7 +1074,7 @@ bool Mir2Lir::SpecialMIR2LIR(const InlineMethod& special) { // Free temp registers and reset redundant store tracking. ResetRegPool(); ResetDefTracking(); - ClobberAllRegs(); + ClobberAllTemps(); return GenSpecialCase(bb, mir, special); } diff --git a/compiler/dex/quick/mir_to_lir.h b/compiler/dex/quick/mir_to_lir.h index 5a824e7..3016cd1 100644 --- a/compiler/dex/quick/mir_to_lir.h +++ b/compiler/dex/quick/mir_to_lir.h @@ -333,6 +333,9 @@ class Mir2Lir : public Backend { bool InUse() { return (storage_mask_ & master_->used_storage_) != 0; } void MarkInUse() { master_->used_storage_ |= storage_mask_; } void MarkFree() { master_->used_storage_ &= ~storage_mask_; } + // No part of the containing storage is live in this view. + 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 MarkDead() { @@ -358,9 +361,13 @@ class Mir2Lir : public Backend { master_ = master; if (master != this) { master_->aliased_ = true; + DCHECK(alias_chain_ == nullptr); + alias_chain_ = master_->alias_chain_; + master_->alias_chain_ = this; } } bool IsAliased() { return aliased_; } + RegisterInfo* GetAliasChain() { return alias_chain_; } uint32_t StorageMask() { return storage_mask_; } void SetStorageMask(uint32_t storage_mask) { storage_mask_ = storage_mask; } LIR* DefStart() { return def_start_; } @@ -385,6 +392,7 @@ class Mir2Lir : public Backend { uint32_t storage_mask_; // Track allocation of sub-units. LIR *def_start_; // Starting inst in last def sequence. LIR *def_end_; // Ending inst in last def sequence. + RegisterInfo* alias_chain_; // Chain of aliased registers. }; class RegisterPool { @@ -655,7 +663,7 @@ class Mir2Lir : public Backend { void ResetDefLoc(RegLocation rl); void ResetDefLocWide(RegLocation rl); void ResetDefTracking(); - void ClobberAllRegs(); + void ClobberAllTemps(); void FlushSpecificReg(RegisterInfo* info); void FlushAllRegs(); bool RegClassMatches(int reg_class, RegStorage reg); diff --git a/compiler/dex/quick/ralloc_util.cc b/compiler/dex/quick/ralloc_util.cc index 04de286..bcc077b 100644 --- a/compiler/dex/quick/ralloc_util.cc +++ b/compiler/dex/quick/ralloc_util.cc @@ -40,7 +40,8 @@ void Mir2Lir::ResetRegPool() { Mir2Lir::RegisterInfo::RegisterInfo(RegStorage r, uint64_t mask) : reg_(r), is_temp_(false), wide_value_(false), dirty_(false), aliased_(false), partner_(r), - s_reg_(INVALID_SREG), def_use_mask_(mask), master_(this) { + s_reg_(INVALID_SREG), def_use_mask_(mask), master_(this), def_start_(nullptr), + def_end_(nullptr), alias_chain_(nullptr) { switch (r.StorageSize()) { case 0: storage_mask_ = 0xffffffff; break; case 4: storage_mask_ = 0x00000001; break; @@ -66,9 +67,13 @@ Mir2Lir::RegisterPool::RegisterPool(Mir2Lir* m2l, ArenaAllocator* arena, next_sp_reg_(0), dp_regs_(arena, dp_regs.size()), next_dp_reg_(0), m2l_(m2l) { // Initialize the fast lookup map. m2l_->reginfo_map_.Reset(); - m2l_->reginfo_map_.Resize(RegStorage::kMaxRegs); - for (unsigned i = 0; i < RegStorage::kMaxRegs; i++) { - m2l_->reginfo_map_.Insert(nullptr); + if (kIsDebugBuild) { + m2l_->reginfo_map_.Resize(RegStorage::kMaxRegs); + for (unsigned i = 0; i < RegStorage::kMaxRegs; i++) { + m2l_->reginfo_map_.Insert(nullptr); + } + } else { + m2l_->reginfo_map_.SetSize(RegStorage::kMaxRegs); } // Construct the register pool. @@ -139,29 +144,43 @@ void Mir2Lir::DumpRegPools() { } void Mir2Lir::Clobber(RegStorage reg) { - if (reg.IsPair()) { + if (UNLIKELY(reg.IsPair())) { DCHECK(!GetRegInfo(reg.GetLow())->IsAliased()); - ClobberBody(GetRegInfo(reg.GetLow())); + Clobber(reg.GetLow()); DCHECK(!GetRegInfo(reg.GetHigh())->IsAliased()); - ClobberBody(GetRegInfo(reg.GetHigh())); + Clobber(reg.GetHigh()); } else { RegisterInfo* info = GetRegInfo(reg); - if (info->IsAliased()) { - ClobberAliases(info); - } else if (info != info->Master() && info->Master()->SReg() != INVALID_SREG) { - ClobberBody(info->Master()); + if (info->IsTemp() && !info->IsDead()) { + ClobberBody(info); + if (info->IsAliased()) { + ClobberAliases(info); + } else { + RegisterInfo* master = info->Master(); + if (info != master) { + ClobberBody(info->Master()); + } + } } - ClobberBody(info); } } void Mir2Lir::ClobberAliases(RegisterInfo* info) { - DCHECK(info->IsAliased()); - GrowableArray<RegisterInfo*>::Iterator iter(&tempreg_info_); - for (RegisterInfo* tmpreg_info = iter.Next(); tmpreg_info != NULL; tmpreg_info = iter.Next()) { - if (tmpreg_info->Master() == info) { - // tmpreg_info is an alias of info. - ClobberBody(tmpreg_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(); + } + } } } } @@ -185,11 +204,10 @@ 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) { + ClobberBody(info); if (info->IsAliased()) { - // TUNING: if this gets hot, we could add links to follow - aliasing is static. ClobberAliases(info); } - ClobberBody(info); } } } @@ -645,7 +663,7 @@ void Mir2Lir::ResetDefTracking() { } } -void Mir2Lir::ClobberAllRegs() { +void Mir2Lir::ClobberAllTemps() { GrowableArray<RegisterInfo*>::Iterator iter(&tempreg_info_); for (RegisterInfo* info = iter.Next(); info != NULL; info = iter.Next()) { ClobberBody(info); @@ -703,10 +721,9 @@ void Mir2Lir::FlushSpecificReg(RegisterInfo* info) { void Mir2Lir::FlushAllRegs() { GrowableArray<RegisterInfo*>::Iterator it(&tempreg_info_); for (RegisterInfo* info = it.Next(); info != nullptr; info = it.Next()) { - if (info->IsLive() && info->IsDirty()) { + if (info->IsDirty() && info->IsLive()) { FlushSpecificReg(info); } - DCHECK(info->IsTemp()); info->MarkDead(); info->SetSReg(INVALID_SREG); info->ResetDefBody(); |