Quick compiler: Single .so for all targets
With this CL, all targets can be built into a single .so (but
we're not yet doing so - the compiler driver needs to be reworked).
A new Codgen class is introduced (see compiler/codegen/codegen.h),
along with target-specific sub-classes ArmCodegen, MipsCodegens and
X86Codegen (see compiler/codegen/*/codegen_[Arm|Mips|X86].h).
Additional minor code, comment and format refactoring. Some source
files combined, temporary header files deleted and a few file
renames to better identify their function.
Next up is combining the Quick and Portable .so files.
Note: building all targets into libdvm-compiler.so increases its
size by 140K bytes. I'm inclined to not bother introducing conditional
compilation to limit code to the specific target - the added build and
testing complexity doesn't doesn't seem worth such a modest size savings.
Change-Id: Id9c5b4502ad6b77cdb31f71d3126f51a4f2e9dfe
diff --git a/src/compiler/codegen/ralloc_util.cc b/src/compiler/codegen/ralloc_util.cc
index a26e0cd..7cc3fad 100644
--- a/src/compiler/codegen/ralloc_util.cc
+++ b/src/compiler/codegen/ralloc_util.cc
@@ -24,6 +24,10 @@
namespace art {
+static const RegLocation bad_loc = {kLocDalvikFrame, 0, 0, 0, 0, 0, 0, 0, 0,
+ INVALID_REG, INVALID_REG, INVALID_SREG,
+ INVALID_SREG};
+
/*
* Free all allocated temps in the temp pools. Note that this does
* not affect the "liveness" of a temp register, which will stay
@@ -102,7 +106,8 @@
/* Mark a temp register as dead. Does not affect allocation state. */
void Clobber(CompilationUnit* cu, int reg)
{
- ClobberBody(cu, GetRegInfo(cu, reg));
+ Codegen* cg = cu->cg.get();
+ ClobberBody(cu, cg->GetRegInfo(cu, reg));
}
static void ClobberSRegBody(RegisterInfo* p, int num_regs, int s_reg)
@@ -158,9 +163,10 @@
void RecordCorePromotion(CompilationUnit* cu, int reg, int s_reg)
{
+ Codegen* cg = cu->cg.get();
int p_map_idx = SRegToPMap(cu, s_reg);
int v_reg = SRegToVReg(cu, s_reg);
- GetRegInfo(cu, reg)->in_use = true;
+ cg->GetRegInfo(cu, reg)->in_use = true;
cu->core_spill_mask |= (1 << reg);
// Include reg for later sort
cu->core_vmap_table.push_back(reg << VREG_NUM_WIDTH |
@@ -187,10 +193,11 @@
void RecordFpPromotion(CompilationUnit* cu, int reg, int s_reg)
{
+ Codegen* cg = cu->cg.get();
int p_map_idx = SRegToPMap(cu, s_reg);
int v_reg = SRegToVReg(cu, s_reg);
- GetRegInfo(cu, reg)->in_use = true;
- MarkPreservedSingle(cu, v_reg, reg);
+ cg->GetRegInfo(cu, reg)->in_use = true;
+ cg->MarkPreservedSingle(cu, v_reg, reg);
cu->promotion_map[p_map_idx].fp_location = kLocPhysReg;
cu->promotion_map[p_map_idx].FpReg = reg;
}
@@ -225,6 +232,7 @@
*/
static int AllocPreservedDouble(CompilationUnit* cu, int s_reg)
{
+ Codegen* cg = cu->cg.get();
int res = -1; // Assume failure
int v_reg = SRegToVReg(cu, s_reg);
int p_map_idx = SRegToPMap(cu, s_reg);
@@ -236,7 +244,7 @@
return res;
}
// Is the low reg of the pair free?
- RegisterInfo* p = GetRegInfo(cu, high_reg-1);
+ RegisterInfo* p = cg->GetRegInfo(cu, high_reg-1);
if (p->in_use || p->is_temp) {
// Already allocated or not preserved - fail.
return res;
@@ -245,7 +253,7 @@
res = p->reg;
p->in_use = true;
DCHECK_EQ((res & 1), 0);
- MarkPreservedSingle(cu, v_reg, res);
+ cg->MarkPreservedSingle(cu, v_reg, res);
} else {
RegisterInfo* FPRegs = cu->reg_pool->FPRegs;
for (int i = 0; i < cu->reg_pool->num_fp_regs; i++) {
@@ -256,10 +264,10 @@
(FPRegs[i].reg + 1) == FPRegs[i+1].reg) {
res = FPRegs[i].reg;
FPRegs[i].in_use = true;
- MarkPreservedSingle(cu, v_reg, res);
+ cg->MarkPreservedSingle(cu, v_reg, res);
FPRegs[i+1].in_use = true;
DCHECK_EQ(res + 1, FPRegs[i+1].reg);
- MarkPreservedSingle(cu, v_reg+1, res+1);
+ cg->MarkPreservedSingle(cu, v_reg+1, res+1);
break;
}
}
@@ -498,19 +506,22 @@
RegisterInfo* IsTemp(CompilationUnit* cu, int reg)
{
- RegisterInfo* p = GetRegInfo(cu, reg);
+ Codegen* cg = cu->cg.get();
+ RegisterInfo* p = cg->GetRegInfo(cu, reg);
return (p->is_temp) ? p : NULL;
}
RegisterInfo* IsPromoted(CompilationUnit* cu, int reg)
{
- RegisterInfo* p = GetRegInfo(cu, reg);
+ Codegen* cg = cu->cg.get();
+ RegisterInfo* p = cg->GetRegInfo(cu, reg);
return (p->is_temp) ? NULL : p;
}
bool IsDirty(CompilationUnit* cu, int reg)
{
- RegisterInfo* p = GetRegInfo(cu, reg);
+ Codegen* cg = cu->cg.get();
+ RegisterInfo* p = cg->GetRegInfo(cu, reg);
return p->dirty;
}
@@ -553,7 +564,8 @@
void ResetDef(CompilationUnit* cu, int reg)
{
- ResetDefBody(GetRegInfo(cu, reg));
+ Codegen* cg = cu->cg.get();
+ ResetDefBody(cg->GetRegInfo(cu, reg));
}
static void NullifyRange(CompilationUnit* cu, LIR *start, LIR *finish, int s_reg1, int s_reg2)
@@ -580,7 +592,8 @@
DCHECK(!rl.wide);
DCHECK(start && start->next);
DCHECK(finish);
- RegisterInfo* p = GetRegInfo(cu, rl.low_reg);
+ Codegen* cg = cu->cg.get();
+ RegisterInfo* p = cg->GetRegInfo(cu, rl.low_reg);
p->def_start = start->next;
p->def_end = finish;
}
@@ -596,7 +609,8 @@
DCHECK(rl.wide);
DCHECK(start && start->next);
DCHECK(finish);
- RegisterInfo* p = GetRegInfo(cu, rl.low_reg);
+ Codegen* cg = cu->cg.get();
+ RegisterInfo* p = cg->GetRegInfo(cu, rl.low_reg);
ResetDef(cu, rl.high_reg); // Only track low of pair
p->def_start = start->next;
p->def_end = finish;
@@ -605,9 +619,10 @@
RegLocation WideToNarrow(CompilationUnit* cu, RegLocation rl)
{
DCHECK(rl.wide);
+ Codegen* cg = cu->cg.get();
if (rl.location == kLocPhysReg) {
- RegisterInfo* info_lo = GetRegInfo(cu, rl.low_reg);
- RegisterInfo* info_hi = GetRegInfo(cu, rl.high_reg);
+ RegisterInfo* info_lo = cg->GetRegInfo(cu, rl.low_reg);
+ RegisterInfo* info_hi = cg->GetRegInfo(cu, rl.high_reg);
if (info_lo->is_temp) {
info_lo->pair = false;
info_lo->def_start = NULL;
@@ -675,13 +690,14 @@
// Make sure nothing is live and dirty
static void FlushAllRegsBody(CompilationUnit* cu, RegisterInfo* info, int num_regs)
{
+ Codegen* cg = cu->cg.get();
int i;
for (i=0; i < num_regs; i++) {
if (info[i].live && info[i].dirty) {
if (info[i].pair) {
- FlushRegWide(cu, info[i].reg, info[i].partner);
+ cg->FlushRegWide(cu, info[i].reg, info[i].partner);
} else {
- FlushReg(cu, info[i].reg);
+ cg->FlushReg(cu, info[i].reg);
}
}
}
@@ -698,20 +714,22 @@
//TUNING: rewrite all of this reg stuff. Probably use an attribute table
-static bool RegClassMatches(int reg_class, int reg)
+static bool RegClassMatches(CompilationUnit* cu, int reg_class, int reg)
{
+ Codegen* cg = cu->cg.get();
if (reg_class == kAnyReg) {
return true;
} else if (reg_class == kCoreReg) {
- return !IsFpReg(reg);
+ return !cg->IsFpReg(reg);
} else {
- return IsFpReg(reg);
+ return cg->IsFpReg(reg);
}
}
void MarkLive(CompilationUnit* cu, int reg, int s_reg)
{
- RegisterInfo* info = GetRegInfo(cu, reg);
+ Codegen* cg = cu->cg.get();
+ RegisterInfo* info = cg->GetRegInfo(cu, reg);
if ((info->reg == reg) && (info->s_reg == s_reg) && info->live) {
return; /* already live */
} else if (s_reg != INVALID_SREG) {
@@ -729,20 +747,23 @@
void MarkTemp(CompilationUnit* cu, int reg)
{
- RegisterInfo* info = GetRegInfo(cu, reg);
+ Codegen* cg = cu->cg.get();
+ RegisterInfo* info = cg->GetRegInfo(cu, reg);
info->is_temp = true;
}
void UnmarkTemp(CompilationUnit* cu, int reg)
{
- RegisterInfo* info = GetRegInfo(cu, reg);
+ Codegen* cg = cu->cg.get();
+ RegisterInfo* info = cg->GetRegInfo(cu, reg);
info->is_temp = false;
}
void MarkPair(CompilationUnit* cu, int low_reg, int high_reg)
{
- RegisterInfo* info_lo = GetRegInfo(cu, low_reg);
- RegisterInfo* info_hi = GetRegInfo(cu, high_reg);
+ Codegen* cg = cu->cg.get();
+ RegisterInfo* info_lo = cg->GetRegInfo(cu, low_reg);
+ RegisterInfo* info_hi = cg->GetRegInfo(cu, high_reg);
info_lo->pair = info_hi->pair = true;
info_lo->partner = high_reg;
info_hi->partner = low_reg;
@@ -750,10 +771,11 @@
void MarkClean(CompilationUnit* cu, RegLocation loc)
{
- RegisterInfo* info = GetRegInfo(cu, loc.low_reg);
+ Codegen* cg = cu->cg.get();
+ RegisterInfo* info = cg->GetRegInfo(cu, loc.low_reg);
info->dirty = false;
if (loc.wide) {
- info = GetRegInfo(cu, loc.high_reg);
+ info = cg->GetRegInfo(cu, loc.high_reg);
info->dirty = false;
}
}
@@ -764,24 +786,27 @@
// If already home, can't be dirty
return;
}
- RegisterInfo* info = GetRegInfo(cu, loc.low_reg);
+ Codegen* cg = cu->cg.get();
+ RegisterInfo* info = cg->GetRegInfo(cu, loc.low_reg);
info->dirty = true;
if (loc.wide) {
- info = GetRegInfo(cu, loc.high_reg);
+ info = cg->GetRegInfo(cu, loc.high_reg);
info->dirty = true;
}
}
void MarkInUse(CompilationUnit* cu, int reg)
{
- RegisterInfo* info = GetRegInfo(cu, reg);
+ Codegen* cg = cu->cg.get();
+ RegisterInfo* info = cg->GetRegInfo(cu, reg);
info->in_use = true;
}
static void CopyRegInfo(CompilationUnit* cu, int new_reg, int old_reg)
{
- RegisterInfo* new_info = GetRegInfo(cu, new_reg);
- RegisterInfo* old_info = GetRegInfo(cu, old_reg);
+ Codegen* cg = cu->cg.get();
+ RegisterInfo* new_info = cg->GetRegInfo(cu, new_reg);
+ RegisterInfo* old_info = cg->GetRegInfo(cu, old_reg);
// Target temp status must not change
bool is_temp = new_info->is_temp;
*new_info = *old_info;
@@ -792,12 +817,13 @@
static bool CheckCorePoolSanity(CompilationUnit* cu)
{
+ Codegen* cg = cu->cg.get();
for (static int i = 0; i < cu->reg_pool->num_core_regs; i++) {
if (cu->reg_pool->core_regs[i].pair) {
static int my_reg = cu->reg_pool->core_regs[i].reg;
static int my_sreg = cu->reg_pool->core_regs[i].s_reg;
static int partner_reg = cu->reg_pool->core_regs[i].partner;
- static RegisterInfo* partner = GetRegInfo(cu, partner_reg);
+ static RegisterInfo* partner = cg->GetRegInfo(cu, partner_reg);
DCHECK(partner != NULL);
DCHECK(partner->pair);
DCHECK_EQ(my_reg, partner->partner);
@@ -855,6 +881,7 @@
{
DCHECK(loc.wide);
DCHECK(CheckCorePoolSanity(cu));
+ Codegen* cg = cu->cg.get();
if (loc.location != kLocPhysReg) {
DCHECK((loc.location == kLocDalvikFrame) ||
(loc.location == kLocCompilerTemp));
@@ -866,9 +893,9 @@
match = match && (info_lo != NULL);
match = match && (info_hi != NULL);
// Are they both core or both FP?
- match = match && (IsFpReg(info_lo->reg) == IsFpReg(info_hi->reg));
+ match = match && (cg->IsFpReg(info_lo->reg) == cg->IsFpReg(info_hi->reg));
// If a pair of floating point singles, are they properly aligned?
- if (match && IsFpReg(info_lo->reg)) {
+ if (match && cg->IsFpReg(info_lo->reg)) {
match &= ((info_lo->reg & 0x1) == 0);
match &= ((info_hi->reg - info_lo->reg) == 1);
}
@@ -884,7 +911,7 @@
loc.high_reg = info_hi->reg;
loc.location = kLocPhysReg;
MarkPair(cu, loc.low_reg, loc.high_reg);
- DCHECK(!IsFpReg(loc.low_reg) || ((loc.low_reg & 0x1) == 0));
+ DCHECK(!cg->IsFpReg(loc.low_reg) || ((loc.low_reg & 0x1) == 0));
return loc;
}
// Can't easily reuse - clobber and free any overlaps
@@ -920,20 +947,20 @@
int new_regs;
int low_reg;
int high_reg;
+ Codegen* cg = cu->cg.get();
loc = UpdateLocWide(cu, loc);
/* 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(cg->IsFpReg(loc.low_reg), cg->IsFpReg(loc.high_reg));
+ DCHECK(!cg->IsFpReg(loc.low_reg) || ((loc.low_reg & 0x1) == 0));
+ if (!RegClassMatches(cu, reg_class, loc.low_reg)) {
/* Wrong register class. Reallocate and copy */
- new_regs = AllocTypedTempPair(cu, loc.fp, reg_class);
+ new_regs = cg->AllocTypedTempPair(cu, loc.fp, reg_class);
low_reg = new_regs & 0xff;
high_reg = (new_regs >> 8) & 0xff;
- OpRegCopyWide(cu, low_reg, high_reg, loc.low_reg,
- loc.high_reg);
+ cg->OpRegCopyWide(cu, low_reg, high_reg, loc.low_reg, loc.high_reg);
CopyRegInfo(cu, low_reg, loc.low_reg);
CopyRegInfo(cu, high_reg, loc.high_reg);
Clobber(cu, loc.low_reg);
@@ -941,7 +968,7 @@
loc.low_reg = low_reg;
loc.high_reg = high_reg;
MarkPair(cu, loc.low_reg, loc.high_reg);
- DCHECK(!IsFpReg(loc.low_reg) || ((loc.low_reg & 0x1) == 0));
+ DCHECK(!cg->IsFpReg(loc.low_reg) || ((loc.low_reg & 0x1) == 0));
}
return loc;
}
@@ -949,7 +976,7 @@
DCHECK_NE(loc.s_reg_low, INVALID_SREG);
DCHECK_NE(GetSRegHi(loc.s_reg_low), INVALID_SREG);
- new_regs = AllocTypedTempPair(cu, loc.fp, reg_class);
+ new_regs = cg->AllocTypedTempPair(cu, loc.fp, reg_class);
loc.low_reg = new_regs & 0xff;
loc.high_reg = (new_regs >> 8) & 0xff;
@@ -959,7 +986,7 @@
MarkLive(cu, loc.low_reg, loc.s_reg_low);
MarkLive(cu, loc.high_reg, GetSRegHi(loc.s_reg_low));
}
- DCHECK(!IsFpReg(loc.low_reg) || ((loc.low_reg & 0x1) == 0));
+ DCHECK(!cg->IsFpReg(loc.low_reg) || ((loc.low_reg & 0x1) == 0));
return loc;
}
@@ -971,13 +998,14 @@
if (loc.wide)
return EvalLocWide(cu, loc, reg_class, update);
+ Codegen* cg = cu->cg.get();
loc = UpdateLoc(cu, loc);
if (loc.location == kLocPhysReg) {
- if (!RegClassMatches(reg_class, loc.low_reg)) {
+ if (!RegClassMatches(cu, reg_class, loc.low_reg)) {
/* Wrong register class. Realloc, copy and transfer ownership */
- new_reg = AllocTypedTemp(cu, loc.fp, reg_class);
- OpRegCopy(cu, new_reg, loc.low_reg);
+ new_reg = cg->AllocTypedTemp(cu, loc.fp, reg_class);
+ cg->OpRegCopy(cu, new_reg, loc.low_reg);
CopyRegInfo(cu, new_reg, loc.low_reg);
Clobber(cu, loc.low_reg);
loc.low_reg = new_reg;
@@ -987,7 +1015,7 @@
DCHECK_NE(loc.s_reg_low, INVALID_SREG);
- new_reg = AllocTypedTemp(cu, loc.fp, reg_class);
+ new_reg = cg->AllocTypedTemp(cu, loc.fp, reg_class);
loc.low_reg = new_reg;
if (update) {
@@ -1092,13 +1120,14 @@
*/
void DoPromotion(CompilationUnit* cu)
{
+ Codegen* cg = cu->cg.get();
int reg_bias = cu->num_compiler_temps + 1;
int dalvik_regs = cu->num_dalvik_registers;
int num_regs = dalvik_regs + reg_bias;
const int promotion_threshold = 2;
// Allow target code to add any special registers
- AdjustSpillMask(cu);
+ cg->AdjustSpillMask(cu);
/*
* Simple register promotion. Just do a static count of the uses
@@ -1262,4 +1291,40 @@
return VRegOffset(cu, SRegToVReg(cu, s_reg));
}
+RegLocation GetBadLoc()
+{
+ RegLocation res = bad_loc;
+ return res;
+}
+
+/* Mark register usage state and return long retloc */
+RegLocation GetReturnWide(CompilationUnit* cu, bool is_double)
+{
+ Codegen* cg = cu->cg.get();
+ RegLocation gpr_res = cg->LocCReturnWide();
+ RegLocation fpr_res = cg->LocCReturnDouble();
+ RegLocation res = is_double ? fpr_res : gpr_res;
+ Clobber(cu, res.low_reg);
+ Clobber(cu, res.high_reg);
+ LockTemp(cu, res.low_reg);
+ LockTemp(cu, res.high_reg);
+ MarkPair(cu, res.low_reg, res.high_reg);
+ return res;
+}
+
+RegLocation GetReturn(CompilationUnit* cu, bool is_float)
+{
+ Codegen* cg = cu->cg.get();
+ RegLocation gpr_res = cg->LocCReturn();
+ RegLocation fpr_res = cg->LocCReturnFloat();
+ RegLocation res = is_float ? fpr_res : gpr_res;
+ Clobber(cu, res.low_reg);
+ if (cu->instruction_set == kMips) {
+ MarkInUse(cu, res.low_reg);
+ } else {
+ LockTemp(cu, res.low_reg);
+ }
+ return res;
+}
+
} // namespace art