summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--compiler/dex/quick/mir_to_lir-inl.h3
-rw-r--r--compiler/dex/quick/mir_to_lir.cc6
-rw-r--r--compiler/dex/quick/mir_to_lir.h10
-rw-r--r--compiler/dex/quick/ralloc_util.cc63
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();