diff options
Diffstat (limited to 'compiler/dex/quick/ralloc_util.cc')
-rw-r--r-- | compiler/dex/quick/ralloc_util.cc | 108 |
1 files changed, 43 insertions, 65 deletions
diff --git a/compiler/dex/quick/ralloc_util.cc b/compiler/dex/quick/ralloc_util.cc index 058b89c499..2303c62992 100644 --- a/compiler/dex/quick/ralloc_util.cc +++ b/compiler/dex/quick/ralloc_util.cc @@ -128,6 +128,15 @@ Mir2Lir::RegisterPool::RegisterPool(Mir2Lir* m2l, ArenaAllocator* arena, // Add an entry for InvalidReg with zero'd mask. RegisterInfo* invalid_reg = new (arena) RegisterInfo(RegStorage::InvalidReg(), 0); m2l_->reginfo_map_.Put(RegStorage::InvalidReg().GetReg(), invalid_reg); + + // Existence of core64 registers implies wide references. + if (core64_regs_.Size() != 0) { + ref_regs_ = &core64_regs_; + next_ref_reg_ = &next_core64_reg_; + } else { + ref_regs_ = &core_regs_; + next_ref_reg_ = &next_core_reg_; + } } void Mir2Lir::DumpRegPool(GrowableArray<RegisterInfo*>* regs) { @@ -145,6 +154,7 @@ void Mir2Lir::DumpRegPool(GrowableArray<RegisterInfo*>* regs) { void Mir2Lir::DumpCoreRegPool() { DumpRegPool(®_pool_->core_regs_); + DumpRegPool(®_pool_->core64_regs_); } void Mir2Lir::DumpFpRegPool() { @@ -274,6 +284,7 @@ void Mir2Lir::RecordCorePromotion(RegStorage reg, int s_reg) { /* Reserve a callee-save register. Return InvalidReg if none available */ RegStorage Mir2Lir::AllocPreservedCoreReg(int s_reg) { + // TODO: 64-bit and refreg update RegStorage res; GrowableArray<RegisterInfo*>::Iterator it(®_pool_->core_regs_); for (RegisterInfo* info = it.Next(); info != nullptr; info = it.Next()) { @@ -406,17 +417,10 @@ RegStorage Mir2Lir::AllocTempWide() { return res; } -RegStorage Mir2Lir::AllocTempWord() { - // FIXME: temporary workaround. For bring-up purposes, x86_64 needs the ability - // to allocate wide values as a pair of core registers. However, we can't hold - // a reference in a register pair. This workaround will be removed when the - // reference handling code is reworked, or x86_64 backend starts using wide core - // registers - whichever happens first. - if (cu_->instruction_set == kX86_64) { - return AllocTemp(); - } else { - return (Is64BitInstructionSet(cu_->instruction_set)) ? AllocTempWide() : AllocTemp(); - } +RegStorage Mir2Lir::AllocTempRef() { + RegStorage res = AllocTempBody(*reg_pool_->ref_regs_, reg_pool_->next_ref_reg_, true); + DCHECK(!res.IsPair()); + return res; } RegStorage Mir2Lir::AllocTempSingle() { @@ -432,6 +436,7 @@ RegStorage Mir2Lir::AllocTempDouble() { } RegStorage Mir2Lir::AllocTypedTempWide(bool fp_hint, int reg_class) { + DCHECK_NE(reg_class, kRefReg); // NOTE: the Dalvik width of a reference is always 32 bits. if (((reg_class == kAnyReg) && fp_hint) || (reg_class == kFPReg)) { return AllocTempDouble(); } @@ -441,6 +446,8 @@ RegStorage Mir2Lir::AllocTypedTempWide(bool fp_hint, int reg_class) { RegStorage Mir2Lir::AllocTypedTemp(bool fp_hint, int reg_class) { if (((reg_class == kAnyReg) && fp_hint) || (reg_class == kFPReg)) { return AllocTempSingle(); + } else if (reg_class == kRefReg) { + return AllocTempRef(); } return AllocTemp(); } @@ -459,8 +466,10 @@ RegStorage Mir2Lir::FindLiveReg(GrowableArray<RegisterInfo*> ®s, int s_reg) { RegStorage Mir2Lir::AllocLiveReg(int s_reg, int reg_class, bool wide) { RegStorage reg; - // TODO: might be worth a sanity check here to verify at most 1 live reg per s_reg. - if ((reg_class == kAnyReg) || (reg_class == kFPReg)) { + if (reg_class == kRefReg) { + reg = FindLiveReg(*reg_pool_->ref_regs_, s_reg); + } + if (!reg.Valid() && ((reg_class == kAnyReg) || (reg_class == kFPReg))) { reg = FindLiveReg(wide ? reg_pool_->dp_regs_ : reg_pool_->sp_regs_, s_reg); } if (!reg.Valid() && (reg_class != kFPReg)) { @@ -675,39 +684,6 @@ void Mir2Lir::MarkDefWide(RegLocation rl, LIR *start, LIR *finish) { p->SetDefEnd(finish); } -RegLocation Mir2Lir::WideToNarrow(RegLocation rl) { - DCHECK(rl.wide); - if (rl.location == kLocPhysReg) { - if (rl.reg.IsPair()) { - RegisterInfo* info_lo = GetRegInfo(rl.reg.GetLow()); - RegisterInfo* info_hi = GetRegInfo(rl.reg.GetHigh()); - if (info_lo->IsTemp()) { - info_lo->SetIsWide(false); - info_lo->ResetDefBody(); - } - if (info_hi->IsTemp()) { - info_hi->SetIsWide(false); - info_hi->ResetDefBody(); - } - rl.reg = rl.reg.GetLow(); - } else { - /* - * TODO: If not a pair, we can't just drop the high register. On some targets, we may be - * able to re-cast the 64-bit register as 32 bits, so it might be worthwhile to revisit - * this code. Will probably want to make this a virtual function. - */ - // Can't narrow 64-bit register. Clobber. - if (GetRegInfo(rl.reg)->IsTemp()) { - Clobber(rl.reg); - FreeTemp(rl.reg); - } - rl.location = kLocDalvikFrame; - } - } - rl.wide = false; - return rl; -} - void Mir2Lir::ResetDefLoc(RegLocation rl) { DCHECK(!rl.wide); if (IsTemp(rl.reg) && !(cu_->disable_opt & (1 << kSuppressLoads))) { @@ -727,16 +703,8 @@ void Mir2Lir::ResetDefLocWide(RegLocation rl) { } void Mir2Lir::ResetDefTracking() { - GrowableArray<RegisterInfo*>::Iterator core_it(®_pool_->core_regs_); - for (RegisterInfo* info = core_it.Next(); info != nullptr; info = core_it.Next()) { - info->ResetDefBody(); - } - GrowableArray<RegisterInfo*>::Iterator sp_it(®_pool_->core_regs_); - for (RegisterInfo* info = sp_it.Next(); info != nullptr; info = sp_it.Next()) { - info->ResetDefBody(); - } - GrowableArray<RegisterInfo*>::Iterator dp_it(®_pool_->core_regs_); - for (RegisterInfo* info = dp_it.Next(); info != nullptr; info = dp_it.Next()) { + GrowableArray<RegisterInfo*>::Iterator iter(&tempreg_info_); + for (RegisterInfo* info = iter.Next(); info != NULL; info = iter.Next()) { info->ResetDefBody(); } } @@ -811,7 +779,11 @@ void Mir2Lir::FlushAllRegs() { bool Mir2Lir::RegClassMatches(int reg_class, RegStorage reg) { if (reg_class == kAnyReg) { return true; - } else if (reg_class == kCoreReg) { + } else if ((reg_class == kCoreReg) || (reg_class == kRefReg)) { + /* + * For this purpose, consider Core and Ref to be the same class. We aren't dealing + * with width here - that should be checked at a higher level (if needed). + */ return !reg.IsFloat(); } else { return reg.IsFloat(); @@ -1347,20 +1319,26 @@ int Mir2Lir::SRegOffset(int s_reg) { } /* Mark register usage state and return long retloc */ -RegLocation Mir2Lir::GetReturnWide(bool is_double) { - RegLocation gpr_res = LocCReturnWide(); - RegLocation fpr_res = LocCReturnDouble(); - RegLocation res = is_double ? fpr_res : gpr_res; +RegLocation Mir2Lir::GetReturnWide(RegisterClass reg_class) { + RegLocation res; + switch (reg_class) { + case kRefReg: LOG(FATAL); break; + case kFPReg: res = LocCReturnDouble(); break; + default: res = LocCReturnWide(); break; + } Clobber(res.reg); LockTemp(res.reg); MarkWide(res.reg); return res; } -RegLocation Mir2Lir::GetReturn(bool is_float) { - RegLocation gpr_res = LocCReturn(); - RegLocation fpr_res = LocCReturnFloat(); - RegLocation res = is_float ? fpr_res : gpr_res; +RegLocation Mir2Lir::GetReturn(RegisterClass reg_class) { + RegLocation res; + switch (reg_class) { + case kRefReg: res = LocCReturnRef(); break; + case kFPReg: res = LocCReturnFloat(); break; + default: res = LocCReturn(); break; + } Clobber(res.reg); if (cu_->instruction_set == kMips) { MarkInUse(res.reg); |