diff options
author | buzbee <buzbee@google.com> | 2014-02-20 11:48:04 -0800 |
---|---|---|
committer | buzbee <buzbee@google.com> | 2014-02-26 10:24:52 -0800 |
commit | 2c1ed456dcdb027d097825dd98dbe48c71599b6c (patch) | |
tree | 280b229d3495c8f7cccd23540144cd142a4dd068 /compiler/dex/quick/ralloc_util.cc | |
parent | 504e6997501aa19c7e7973e70f187314af95602c (diff) | |
download | android_art-2c1ed456dcdb027d097825dd98dbe48c71599b6c.tar.gz android_art-2c1ed456dcdb027d097825dd98dbe48c71599b6c.tar.bz2 android_art-2c1ed456dcdb027d097825dd98dbe48c71599b6c.zip |
Rework Quick compiler's register handling
For historical reasons, the Quick backend found it convenient
to consider all 64-bit Dalvik values held in registers
to be contained in a pair of 32-bit registers. Though this
worked well for ARM (with double-precision registers also
treated as a pair of 32-bit single-precision registers) it doesn't
play well with other targets. And, it is somewhat problematic
for 64-bit architectures.
This is the first of several CLs that will rework the way the
Quick backend deals with physical registers. The goal is to
eliminate the "64-bit value backed with 32-bit register pair"
requirement from the target-indendent portions of the backend
and support 64-bit registers throughout.
The key RegLocation struct, which describes the location of
Dalvik virtual register & register pairs, previously contained
fields for high and low physical registers. The low_reg and
high_reg fields are being replaced with a new type: RegStorage.
There will be a single instance of RegStorage for each RegLocation.
Note that RegStorage does not increase the space used. It is
16 bits wide, the same as the sum of the 8-bit low_reg and
high_reg fields.
At a target-independent level, it will describe whether the physical
register storage associated with the Dalvik value is a single 32
bit, single 64 bit, pair of 32 bit or vector. The actual register
number encoding is left to the target-dependent code layer.
Because physical register handling is pervasive throughout the
backend, this restructuring necessarily involves large CLs with
lots of changes. I'm going to roll these out in stages, and
attempt to segregate the CLs with largely mechanical changes from
those which restructure or rework the logic.
This CL is of the mechanical change variety - it replaces low_reg
and high_reg from RegLocation and introduces RegStorage. It also
includes a lot of new code (such as many calls to GetReg())
that should go away in upcoming CLs.
The tentative plan for the subsequent CLs is:
o Rework standard register utilities such as AllocReg() and
FreeReg() to use RegStorage instead of ints.
o Rework the target-independent GenXXX, OpXXX, LoadValue,
StoreValue, etc. routines to take RegStorage rather than
int register encodings.
o Take advantage of the vector representation and eliminate
the current vector field in RegLocation.
o Replace the "wide" variants of codegen utilities that take
low_reg/high_reg pairs with versions that use RegStorage.
o Add 64-bit register target independent codegen utilities
where possible, and where not virtualize with 32-bit general
register and 64-bit general register variants in the target
dependent layer.
o Expand/rework the LIR def/use flags to allow for more registers
(currently, we lose out on 16 MIPS floating point regs as
well as ARM's D16..D31 for lack of space in the masks).
o [Possibly] move the float/non-float determination of a register
from the target-dependent encoding to RegStorage. In other
words, replace IsFpReg(register_encoding_bits).
At the end of the day, all code in the target independent layer
should be using RegStorage, as should much of the target dependent
layer. Ideally, we won't be using the physical register number
encoding extracted from RegStorage (i.e. GetReg()) until the
NewLIRx() layer.
Change-Id: Idc5c741478f720bdd1d7123b94e4288be5ce52cb
Diffstat (limited to 'compiler/dex/quick/ralloc_util.cc')
-rw-r--r-- | compiler/dex/quick/ralloc_util.cc | 130 |
1 files changed, 61 insertions, 69 deletions
diff --git a/compiler/dex/quick/ralloc_util.cc b/compiler/dex/quick/ralloc_util.cc index 0a651713ab..3a8942e46e 100644 --- a/compiler/dex/quick/ralloc_util.cc +++ b/compiler/dex/quick/ralloc_util.cc @@ -460,7 +460,7 @@ void Mir2Lir::MarkDef(RegLocation rl, LIR *start, LIR *finish) { DCHECK(!rl.wide); DCHECK(start && start->next); DCHECK(finish); - RegisterInfo* p = GetRegInfo(rl.low_reg); + RegisterInfo* p = GetRegInfo(rl.reg.GetReg()); p->def_start = start->next; p->def_end = finish; } @@ -474,8 +474,8 @@ void Mir2Lir::MarkDefWide(RegLocation rl, LIR *start, LIR *finish) { DCHECK(rl.wide); DCHECK(start && start->next); DCHECK(finish); - RegisterInfo* p = GetRegInfo(rl.low_reg); - ResetDef(rl.high_reg); // Only track low of pair + RegisterInfo* p = GetRegInfo(rl.reg.GetReg()); + ResetDef(rl.reg.GetHighReg()); // Only track low of pair p->def_start = start->next; p->def_end = finish; } @@ -483,8 +483,8 @@ void Mir2Lir::MarkDefWide(RegLocation rl, LIR *start, LIR *finish) { RegLocation Mir2Lir::WideToNarrow(RegLocation rl) { DCHECK(rl.wide); if (rl.location == kLocPhysReg) { - RegisterInfo* info_lo = GetRegInfo(rl.low_reg); - RegisterInfo* info_hi = GetRegInfo(rl.high_reg); + RegisterInfo* info_lo = GetRegInfo(rl.reg.GetReg()); + RegisterInfo* info_hi = GetRegInfo(rl.reg.GetHighReg()); if (info_lo->is_temp) { info_lo->pair = false; info_lo->def_start = NULL; @@ -502,18 +502,18 @@ RegLocation Mir2Lir::WideToNarrow(RegLocation rl) { void Mir2Lir::ResetDefLoc(RegLocation rl) { DCHECK(!rl.wide); - RegisterInfo* p = IsTemp(rl.low_reg); + RegisterInfo* p = IsTemp(rl.reg.GetReg()); if (p && !(cu_->disable_opt & (1 << kSuppressLoads))) { DCHECK(!p->pair); NullifyRange(p->def_start, p->def_end, p->s_reg, rl.s_reg_low); } - ResetDef(rl.low_reg); + ResetDef(rl.reg.GetReg()); } void Mir2Lir::ResetDefLocWide(RegLocation rl) { DCHECK(rl.wide); - RegisterInfo* p_low = IsTemp(rl.low_reg); - RegisterInfo* p_high = IsTemp(rl.high_reg); + RegisterInfo* p_low = IsTemp(rl.reg.GetReg()); + RegisterInfo* p_high = IsTemp(rl.reg.GetHighReg()); if (p_low && !(cu_->disable_opt & (1 << kSuppressLoads))) { DCHECK(p_low->pair); NullifyRange(p_low->def_start, p_low->def_end, p_low->s_reg, rl.s_reg_low); @@ -521,8 +521,8 @@ void Mir2Lir::ResetDefLocWide(RegLocation rl) { if (p_high && !(cu_->disable_opt & (1 << kSuppressLoads))) { DCHECK(p_high->pair); } - ResetDef(rl.low_reg); - ResetDef(rl.high_reg); + ResetDef(rl.reg.GetReg()); + ResetDef(rl.reg.GetHighReg()); } void Mir2Lir::ResetDefTracking() { @@ -621,10 +621,10 @@ void Mir2Lir::MarkPair(int low_reg, int high_reg) { } void Mir2Lir::MarkClean(RegLocation loc) { - RegisterInfo* info = GetRegInfo(loc.low_reg); + RegisterInfo* info = GetRegInfo(loc.reg.GetReg()); info->dirty = false; if (loc.wide) { - info = GetRegInfo(loc.high_reg); + info = GetRegInfo(loc.reg.GetHighReg()); info->dirty = false; } } @@ -634,10 +634,10 @@ void Mir2Lir::MarkDirty(RegLocation loc) { // If already home, can't be dirty return; } - RegisterInfo* info = GetRegInfo(loc.low_reg); + RegisterInfo* info = GetRegInfo(loc.reg.GetReg()); info->dirty = true; if (loc.wide) { - info = GetRegInfo(loc.high_reg); + info = GetRegInfo(loc.reg.GetHighReg()); info->dirty = true; } } @@ -707,7 +707,7 @@ RegLocation Mir2Lir::UpdateLoc(RegLocation loc) { Clobber(info_lo->partner); FreeTemp(info_lo->reg); } else { - loc.low_reg = info_lo->reg; + loc.reg = RegStorage(RegStorage::k32BitSolo, info_lo->reg); loc.location = kLocPhysReg; } } @@ -744,11 +744,10 @@ RegLocation Mir2Lir::UpdateLocWide(RegLocation loc) { } if (match) { // Can reuse - update the register usage info - loc.low_reg = info_lo->reg; - loc.high_reg = info_hi->reg; loc.location = kLocPhysReg; - MarkPair(loc.low_reg, loc.high_reg); - DCHECK(!IsFpReg(loc.low_reg) || ((loc.low_reg & 0x1) == 0)); + loc.reg = RegStorage(RegStorage::k64BitPair, info_lo->reg, info_hi->reg); + MarkPair(loc.reg.GetReg(), loc.reg.GetHighReg()); + DCHECK(!IsFpReg(loc.reg.GetReg()) || ((loc.reg.GetReg() & 0x1) == 0)); return loc; } // Can't easily reuse - clobber and free any overlaps @@ -779,7 +778,6 @@ RegLocation Mir2Lir::UpdateRawLoc(RegLocation loc) { RegLocation Mir2Lir::EvalLocWide(RegLocation loc, int reg_class, bool update) { DCHECK(loc.wide); - int32_t new_regs; int32_t low_reg; int32_t high_reg; @@ -787,22 +785,21 @@ RegLocation Mir2Lir::EvalLocWide(RegLocation loc, int reg_class, bool update) { /* If already in registers, we can assume proper form. Right reg class? */ if (loc.location == kLocPhysReg) { - DCHECK_EQ(IsFpReg(loc.low_reg), IsFpReg(loc.high_reg)); - DCHECK(!IsFpReg(loc.low_reg) || ((loc.low_reg & 0x1) == 0)); - if (!RegClassMatches(reg_class, loc.low_reg)) { + DCHECK_EQ(IsFpReg(loc.reg.GetReg()), IsFpReg(loc.reg.GetHighReg())); + DCHECK(!IsFpReg(loc.reg.GetReg()) || ((loc.reg.GetReg() & 0x1) == 0)); + if (!RegClassMatches(reg_class, loc.reg.GetReg())) { /* Wrong register class. Reallocate and copy */ - new_regs = AllocTypedTempPair(loc.fp, reg_class); - low_reg = new_regs & 0xff; - high_reg = (new_regs >> 8) & 0xff; - OpRegCopyWide(low_reg, high_reg, loc.low_reg, loc.high_reg); - CopyRegInfo(low_reg, loc.low_reg); - CopyRegInfo(high_reg, loc.high_reg); - Clobber(loc.low_reg); - Clobber(loc.high_reg); - loc.low_reg = low_reg; - loc.high_reg = high_reg; - MarkPair(loc.low_reg, loc.high_reg); - DCHECK(!IsFpReg(loc.low_reg) || ((loc.low_reg & 0x1) == 0)); + RegStorage new_regs = AllocTypedTempWide(loc.fp, reg_class); + low_reg = new_regs.GetReg(); + high_reg = new_regs.GetHighReg(); + OpRegCopyWide(low_reg, high_reg, loc.reg.GetReg(), loc.reg.GetHighReg()); + CopyRegInfo(low_reg, loc.reg.GetReg()); + CopyRegInfo(high_reg, loc.reg.GetHighReg()); + Clobber(loc.reg.GetReg()); + Clobber(loc.reg.GetHighReg()); + loc.reg = new_regs; + MarkPair(loc.reg.GetReg(), loc.reg.GetHighReg()); + DCHECK(!IsFpReg(loc.reg.GetReg()) || ((loc.reg.GetReg() & 0x1) == 0)); } return loc; } @@ -810,20 +807,18 @@ RegLocation Mir2Lir::EvalLocWide(RegLocation loc, int reg_class, bool update) { DCHECK_NE(loc.s_reg_low, INVALID_SREG); DCHECK_NE(GetSRegHi(loc.s_reg_low), INVALID_SREG); - new_regs = AllocTypedTempPair(loc.fp, reg_class); - loc.low_reg = new_regs & 0xff; - loc.high_reg = (new_regs >> 8) & 0xff; + loc.reg = AllocTypedTempWide(loc.fp, reg_class); - MarkPair(loc.low_reg, loc.high_reg); + MarkPair(loc.reg.GetReg(), loc.reg.GetHighReg()); if (update) { loc.location = kLocPhysReg; - MarkLive(loc.low_reg, loc.s_reg_low); + MarkLive(loc.reg.GetReg(), loc.s_reg_low); // Does this wide value live in two registers or one vector register? - if (loc.low_reg != loc.high_reg) { - MarkLive(loc.high_reg, GetSRegHi(loc.s_reg_low)); + if (loc.reg.GetReg() != loc.reg.GetHighReg()) { + MarkLive(loc.reg.GetHighReg(), GetSRegHi(loc.s_reg_low)); } } - DCHECK(!IsFpReg(loc.low_reg) || ((loc.low_reg & 0x1) == 0)); + DCHECK(!IsFpReg(loc.reg.GetReg()) || ((loc.reg.GetReg() & 0x1) == 0)); return loc; } @@ -836,13 +831,13 @@ RegLocation Mir2Lir::EvalLoc(RegLocation loc, int reg_class, bool update) { loc = UpdateLoc(loc); if (loc.location == kLocPhysReg) { - if (!RegClassMatches(reg_class, loc.low_reg)) { + if (!RegClassMatches(reg_class, loc.reg.GetReg())) { /* Wrong register class. Realloc, copy and transfer ownership */ new_reg = AllocTypedTemp(loc.fp, reg_class); - OpRegCopy(new_reg, loc.low_reg); - CopyRegInfo(new_reg, loc.low_reg); - Clobber(loc.low_reg); - loc.low_reg = new_reg; + OpRegCopy(new_reg, loc.reg.GetReg()); + CopyRegInfo(new_reg, loc.reg.GetReg()); + Clobber(loc.reg.GetReg()); + loc.reg = RegStorage(RegStorage::k32BitSolo, new_reg); } return loc; } @@ -850,11 +845,11 @@ RegLocation Mir2Lir::EvalLoc(RegLocation loc, int reg_class, bool update) { DCHECK_NE(loc.s_reg_low, INVALID_SREG); new_reg = AllocTypedTemp(loc.fp, reg_class); - loc.low_reg = new_reg; + loc.reg = RegStorage(RegStorage::k32BitSolo, new_reg); if (update) { loc.location = kLocPhysReg; - MarkLive(loc.low_reg, loc.s_reg_low); + MarkLive(loc.reg.GetReg(), loc.s_reg_low); } return loc; } @@ -1006,32 +1001,29 @@ void Mir2Lir::DoPromotion() { if (curr->fp) { if (promotion_map_[p_map_idx].fp_location == kLocPhysReg) { curr->location = kLocPhysReg; - curr->low_reg = promotion_map_[p_map_idx].FpReg; + curr->reg = RegStorage(RegStorage::k32BitSolo, promotion_map_[p_map_idx].FpReg); curr->home = true; } } else { if (promotion_map_[p_map_idx].core_location == kLocPhysReg) { curr->location = kLocPhysReg; - curr->low_reg = promotion_map_[p_map_idx].core_reg; + curr->reg = RegStorage(RegStorage::k32BitSolo, promotion_map_[p_map_idx].core_reg); curr->home = true; } } - curr->high_reg = INVALID_REG; } else { if (curr->high_word) { continue; } if (curr->fp) { if ((promotion_map_[p_map_idx].fp_location == kLocPhysReg) && - (promotion_map_[p_map_idx+1].fp_location == - kLocPhysReg)) { + (promotion_map_[p_map_idx+1].fp_location == kLocPhysReg)) { int low_reg = promotion_map_[p_map_idx].FpReg; int high_reg = promotion_map_[p_map_idx+1].FpReg; // Doubles require pair of singles starting at even reg if (((low_reg & 0x1) == 0) && ((low_reg + 1) == high_reg)) { curr->location = kLocPhysReg; - curr->low_reg = low_reg; - curr->high_reg = high_reg; + curr->reg = RegStorage(RegStorage::k64BitPair, low_reg, high_reg); curr->home = true; } } @@ -1040,8 +1032,8 @@ void Mir2Lir::DoPromotion() { && (promotion_map_[p_map_idx+1].core_location == kLocPhysReg)) { curr->location = kLocPhysReg; - curr->low_reg = promotion_map_[p_map_idx].core_reg; - curr->high_reg = promotion_map_[p_map_idx+1].core_reg; + curr->reg = RegStorage(RegStorage::k64BitPair, promotion_map_[p_map_idx].core_reg, + promotion_map_[p_map_idx+1].core_reg); curr->home = true; } } @@ -1068,13 +1060,13 @@ RegLocation Mir2Lir::GetReturnWide(bool is_double) { RegLocation gpr_res = LocCReturnWide(); RegLocation fpr_res = LocCReturnDouble(); RegLocation res = is_double ? fpr_res : gpr_res; - Clobber(res.low_reg); - Clobber(res.high_reg); - LockTemp(res.low_reg); - LockTemp(res.high_reg); + Clobber(res.reg.GetReg()); + Clobber(res.reg.GetHighReg()); + LockTemp(res.reg.GetReg()); + LockTemp(res.reg.GetHighReg()); // Does this wide value live in two registers or one vector register? - if (res.low_reg != res.high_reg) { - MarkPair(res.low_reg, res.high_reg); + if (res.reg.GetReg() != res.reg.GetHighReg()) { + MarkPair(res.reg.GetReg(), res.reg.GetHighReg()); } return res; } @@ -1083,11 +1075,11 @@ RegLocation Mir2Lir::GetReturn(bool is_float) { RegLocation gpr_res = LocCReturn(); RegLocation fpr_res = LocCReturnFloat(); RegLocation res = is_float ? fpr_res : gpr_res; - Clobber(res.low_reg); + Clobber(res.reg.GetReg()); if (cu_->instruction_set == kMips) { - MarkInUse(res.low_reg); + MarkInUse(res.reg.GetReg()); } else { - LockTemp(res.low_reg); + LockTemp(res.reg.GetReg()); } return res; } |