summaryrefslogtreecommitdiff
path: root/src/compiler/codegen
diff options
context:
space:
mode:
Diffstat (limited to 'src/compiler/codegen')
-rw-r--r--src/compiler/codegen/CodegenFactory.cc14
-rw-r--r--src/compiler/codegen/CompilerCodegen.h2
-rw-r--r--src/compiler/codegen/Ralloc.h1
-rw-r--r--src/compiler/codegen/RallocUtil.cc31
-rw-r--r--src/compiler/codegen/arm/ArchUtility.cc50
-rw-r--r--src/compiler/codegen/arm/ArmLIR.h15
-rw-r--r--src/compiler/codegen/arm/ArmRallocUtil.cc185
-rw-r--r--src/compiler/codegen/arm/MethodCodegenDriver.cc107
8 files changed, 203 insertions, 202 deletions
diff --git a/src/compiler/codegen/CodegenFactory.cc b/src/compiler/codegen/CodegenFactory.cc
index 55ed8af080..5dbcd9769a 100644
--- a/src/compiler/codegen/CodegenFactory.cc
+++ b/src/compiler/codegen/CodegenFactory.cc
@@ -58,7 +58,7 @@ STATIC void loadValueDirect(CompilationUnit* cUnit, RegLocation rlSrc,
genRegCopy(cUnit, reg1, rlSrc.lowReg);
} else {
DCHECK(rlSrc.location == kLocDalvikFrame);
- loadWordDisp(cUnit, rSP, rlSrc.spOffset, reg1);
+ loadWordDisp(cUnit, rSP, oatSRegOffset(cUnit, rlSrc.sRegLow), reg1);
}
}
@@ -88,7 +88,8 @@ STATIC void loadValueDirectWide(CompilationUnit* cUnit, RegLocation rlSrc,
genRegCopyWide(cUnit, regLo, regHi, rlSrc.lowReg, rlSrc.highReg);
} else {
DCHECK(rlSrc.location == kLocDalvikFrame);
- loadBaseDispWide(cUnit, NULL, rSP, rlSrc.spOffset,
+ loadBaseDispWide(cUnit, NULL, rSP,
+ oatSRegOffset(cUnit, rlSrc.sRegLow),
regLo, regHi, INVALID_SREG);
}
}
@@ -156,7 +157,8 @@ STATIC void storeValue(CompilationUnit* cUnit, RegLocation rlDest,
if (oatIsDirty(cUnit, rlDest.lowReg) &&
oatLiveOut(cUnit, rlDest.sRegLow)) {
defStart = (LIR* )cUnit->lastLIRInsn;
- storeBaseDisp(cUnit, rSP, rlDest.spOffset, rlDest.lowReg, kWord);
+ storeBaseDisp(cUnit, rSP, oatSRegOffset(cUnit, rlDest.sRegLow),
+ rlDest.lowReg, kWord);
oatMarkClean(cUnit, rlDest);
defEnd = (LIR* )cUnit->lastLIRInsn;
oatMarkDef(cUnit, rlDest, defStart, defEnd);
@@ -183,10 +185,6 @@ STATIC void storeValueWide(CompilationUnit* cUnit, RegLocation rlDest,
{
LIR* defStart;
LIR* defEnd;
- if (FPREG(rlSrc.lowReg)!=FPREG(rlSrc.highReg)) {
- LOG(WARNING) << "rlSrc.lowreg:" << rlSrc.lowReg << ", rlSrc.highReg:"
- << rlSrc.highReg;
- }
DCHECK_EQ(FPREG(rlSrc.lowReg), FPREG(rlSrc.highReg));
DCHECK(rlDest.wide);
DCHECK(rlSrc.wide);
@@ -230,7 +228,7 @@ STATIC void storeValueWide(CompilationUnit* cUnit, RegLocation rlDest,
defStart = (LIR*)cUnit->lastLIRInsn;
DCHECK_EQ((oatS2VReg(cUnit, rlDest.sRegLow)+1),
oatS2VReg(cUnit, oatSRegHi(rlDest.sRegLow)));
- storeBaseDispWide(cUnit, rSP, rlDest.spOffset,
+ storeBaseDispWide(cUnit, rSP, oatSRegOffset(cUnit, rlDest.sRegLow),
rlDest.lowReg, rlDest.highReg);
oatMarkClean(cUnit, rlDest);
defEnd = (LIR*)cUnit->lastLIRInsn;
diff --git a/src/compiler/codegen/CompilerCodegen.h b/src/compiler/codegen/CompilerCodegen.h
index 58ab1d3b97..d2e5f0a631 100644
--- a/src/compiler/codegen/CompilerCodegen.h
+++ b/src/compiler/codegen/CompilerCodegen.h
@@ -27,6 +27,8 @@ void oatAssembleLIR(CompilationUnit* cUnit);
/* Implemented in the codegen/<target>/ArchUtility.c */
void oatCodegenDump(CompilationUnit* cUnit);
+void oatDumpPromotionMap(CompilationUnit* cUnit);
+void oatDumpFullPromotionMap(CompilationUnit* cUnit);
/* Implemented in codegen/<target>/Ralloc.c */
void oatSimpleRegAlloc(CompilationUnit* cUnit);
diff --git a/src/compiler/codegen/Ralloc.h b/src/compiler/codegen/Ralloc.h
index e343ec5682..fee0e9a913 100644
--- a/src/compiler/codegen/Ralloc.h
+++ b/src/compiler/codegen/Ralloc.h
@@ -232,6 +232,7 @@ extern void oatFlushRegWideImpl(CompilationUnit* cUnit, int rBase,
extern void oatDoPromotion(CompilationUnit* cUnit);
extern int oatVRegOffset(CompilationUnit* cUnit, int reg);
+extern int oatSRegOffset(CompilationUnit* cUnit, int reg);
extern void oatDumpCoreRegPool(CompilationUnit* cUint);
extern void oatDumpFPRegPool(CompilationUnit* cUint);
extern bool oatCheckCorePoolSanity(CompilationUnit* cUnit);
diff --git a/src/compiler/codegen/RallocUtil.cc b/src/compiler/codegen/RallocUtil.cc
index 7fd062d5a5..1b0fb90e35 100644
--- a/src/compiler/codegen/RallocUtil.cc
+++ b/src/compiler/codegen/RallocUtil.cc
@@ -186,9 +186,10 @@ extern int oatAllocPreservedCoreReg(CompilationUnit* cUnit, int sReg)
cUnit->coreSpillMask |= (1 << res);
cUnit->coreVmapTable.push_back(sReg);
cUnit->numCoreSpills++;
- cUnit->regLocation[sReg].location = kLocPhysReg;
- cUnit->regLocation[sReg].lowReg = res;
- cUnit->regLocation[sReg].home = true;
+ // Should be promoting based on initial sReg set
+ DCHECK_EQ(sReg, oatS2VReg(cUnit, sReg));
+ cUnit->promotionMap[sReg].coreLocation = kLocPhysReg;
+ cUnit->promotionMap[sReg].coreReg = res;
break;
}
}
@@ -231,10 +232,11 @@ STATIC int allocPreservedSingle(CompilationUnit* cUnit, int sReg, bool even)
((FPRegs[i].reg & 0x1) == 0) == even) {
res = FPRegs[i].reg;
FPRegs[i].inUse = true;
+ // Should be promoting based on initial sReg set
+ DCHECK_EQ(sReg, oatS2VReg(cUnit, sReg));
markPreservedSingle(cUnit, sReg, res);
- cUnit->regLocation[sReg].fpLocation = kLocPhysReg;
- cUnit->regLocation[sReg].fpLowReg = res;
- cUnit->regLocation[sReg].home = true;
+ cUnit->promotionMap[sReg].fpLocation = kLocPhysReg;
+ cUnit->promotionMap[sReg].fpReg = res;
break;
}
}
@@ -252,9 +254,11 @@ STATIC int allocPreservedSingle(CompilationUnit* cUnit, int sReg, bool even)
STATIC int allocPreservedDouble(CompilationUnit* cUnit, int sReg)
{
int res = -1; // Assume failure
- if (cUnit->regLocation[sReg+1].fpLocation == kLocPhysReg) {
+ // Should be promoting based on initial sReg set
+ DCHECK_EQ(sReg, oatS2VReg(cUnit, sReg));
+ if (cUnit->promotionMap[sReg+1].fpLocation == kLocPhysReg) {
// Upper reg is already allocated. Can we fit?
- int highReg = cUnit->regLocation[sReg+1].fpLowReg;
+ int highReg = cUnit->promotionMap[sReg+1].fpReg;
if ((highReg & 1) == 0) {
// High reg is even - fail.
return res;
@@ -289,12 +293,10 @@ STATIC int allocPreservedDouble(CompilationUnit* cUnit, int sReg)
}
}
if (res != -1) {
- cUnit->regLocation[sReg].fpLocation = kLocPhysReg;
- cUnit->regLocation[sReg].fpLowReg = res;
- cUnit->regLocation[sReg].home = true;
- cUnit->regLocation[sReg+1].fpLocation = kLocPhysReg;
- cUnit->regLocation[sReg+1].fpLowReg = res + 1;
- cUnit->regLocation[sReg+1].home = true;
+ cUnit->promotionMap[sReg].fpLocation = kLocPhysReg;
+ cUnit->promotionMap[sReg].fpReg = res;
+ cUnit->promotionMap[sReg+1].fpLocation = kLocPhysReg;
+ cUnit->promotionMap[sReg+1].fpReg = res + 1;
}
return res;
}
@@ -312,7 +314,6 @@ extern int oatAllocPreservedFPReg(CompilationUnit* cUnit, int sReg,
int res = -1;
if (doubleStart) {
res = allocPreservedDouble(cUnit, sReg);
- } else {
}
if (res == -1) {
res = allocPreservedSingle(cUnit, sReg, false /* try odd # */);
diff --git a/src/compiler/codegen/arm/ArchUtility.cc b/src/compiler/codegen/arm/ArchUtility.cc
index aef98faff5..c4d3b6d780 100644
--- a/src/compiler/codegen/arm/ArchUtility.cc
+++ b/src/compiler/codegen/arm/ArchUtility.cc
@@ -16,6 +16,7 @@
#include "../../CompilerInternals.h"
#include "ArmLIR.h"
+#include "../Ralloc.h"
static const char* coreRegNames[16] = {
"r0",
@@ -391,6 +392,38 @@ void oatDumpLIRInsn(CompilationUnit* cUnit, LIR* arg, unsigned char* baseAddr)
}
}
+void oatDumpPromotionMap(CompilationUnit *cUnit)
+{
+ const Method *method = cUnit->method;
+ for (int i = 0; i < method->NumRegisters(); i++) {
+ PromotionMap vRegMap = cUnit->promotionMap[i];
+ char buf[100];
+ if (vRegMap.fpLocation == kLocPhysReg) {
+ snprintf(buf, 100, " : s%d", vRegMap.fpReg & FP_REG_MASK);
+ } else {
+ buf[0] = 0;
+ }
+ char buf2[100];
+ snprintf(buf2, 100, "V[%02d] -> %s%d%s", i,
+ vRegMap.coreLocation == kLocPhysReg ?
+ "r" : "SP+", vRegMap.coreLocation == kLocPhysReg ?
+ vRegMap.coreReg : oatSRegOffset(cUnit, i), buf);
+ LOG(INFO) << buf2;
+ }
+}
+
+void oatDumpFullPromotionMap(CompilationUnit *cUnit)
+{
+ const Method *method = cUnit->method;
+ for (int i = 0; i < method->NumRegisters(); i++) {
+ PromotionMap vRegMap = cUnit->promotionMap[i];
+ LOG(INFO) << i << " -> " << "CL:" << (int)vRegMap.coreLocation <<
+ ", CR:" << (int)vRegMap.coreReg << ", FL:" <<
+ (int)vRegMap.fpLocation << ", FR:" << (int)vRegMap.fpReg <<
+ ", - " << (int)vRegMap.firstInPair;
+ }
+}
+
/* Dump instructions and constant pool contents */
void oatCodegenDump(CompilationUnit* cUnit)
{
@@ -414,22 +447,7 @@ void oatCodegenDump(CompilationUnit* cUnit)
" bytes, Dalvik size is " << insnsSize * 2;
LOG(INFO) << "expansion factor: " <<
(float)cUnit->totalSize / (float)(insnsSize * 2);
- for (int i = 0; i < method->NumRegisters(); i++) {
- RegLocation loc = cUnit->regLocation[i];
- char buf[100];
- if (loc.fpLocation == kLocPhysReg) {
- snprintf(buf, 100, " : s%d", loc.fpLowReg & FP_REG_MASK);
- } else {
- buf[0] = 0;
- }
- char buf2[100];
- snprintf(buf2, 100, "V[%02d] -> %s%d%s", i,
- loc.location == kLocPhysReg ?
- "r" : "SP+", loc.location == kLocPhysReg ?
- loc.lowReg : loc.spOffset, buf);
- LOG(INFO) << buf2;
-
- }
+ oatDumpPromotionMap(cUnit);
for (lirInsn = cUnit->firstLIRInsn; lirInsn; lirInsn = lirInsn->next) {
oatDumpLIRInsn(cUnit, lirInsn, 0);
}
diff --git a/src/compiler/codegen/arm/ArmLIR.h b/src/compiler/codegen/arm/ArmLIR.h
index 1e4022ee4b..729e708fad 100644
--- a/src/compiler/codegen/arm/ArmLIR.h
+++ b/src/compiler/codegen/arm/ArmLIR.h
@@ -123,16 +123,13 @@
#define rNone (-1)
/* RegisterLocation templates return values (r0, or r0/r1) */
-#define LOC_C_RETURN {kLocPhysReg, 0, 0, r0, INVALID_REG, INVALID_SREG, \
- 1, kLocPhysReg, r0, INVALID_REG, INVALID_OFFSET}
-#define LOC_C_RETURN_WIDE {kLocPhysReg, 1, 0, r0, r1, INVALID_SREG, \
- 1, kLocPhysReg, r0, r1, INVALID_OFFSET}
+#define LOC_C_RETURN {kLocPhysReg, 0, 0, 0, 0, 0, 1, r0, INVALID_REG, INVALID_SREG}
+#define LOC_C_RETURN_WIDE {kLocPhysReg, 1, 0, 0, 0, 0, 1, r0, r1, INVALID_SREG}
/* RegisterLocation templates for interpState->retVal; */
-#define LOC_DALVIK_RETURN_VAL {kLocPhysReg, 0, 0, r0, INVALID_REG, \
- INVALID_SREG, 1, kLocPhysReg, r0, INVALID_REG, \
- INVALID_OFFSET}
-#define LOC_DALVIK_RETURN_VAL_WIDE {kLocPhysReg, 1, 0, r0, r1, \
- INVALID_SREG, 1, kLocPhysReg, r0, r1, INVALID_OFFSET}
+#define LOC_DALVIK_RETURN_VAL {kLocPhysReg, 0, 0, 0, 0, 0, 1, r0, INVALID_REG, \
+ INVALID_SREG}
+#define LOC_DALVIK_RETURN_VAL_WIDE {kLocPhysReg, 1, 0, 0, 0, 0, 1, r0, r1, \
+ INVALID_SREG}
/*
* Data structure tracking the mapping between a Dalvik register (pair) and a
diff --git a/src/compiler/codegen/arm/ArmRallocUtil.cc b/src/compiler/codegen/arm/ArmRallocUtil.cc
index ed8a5b2ab3..4af3d0713a 100644
--- a/src/compiler/codegen/arm/ArmRallocUtil.cc
+++ b/src/compiler/codegen/arm/ArmRallocUtil.cc
@@ -37,7 +37,7 @@ typedef struct RefCounts {
/* USE SSA names to count references of base Dalvik vRegs. */
STATIC void countRefs(CompilationUnit *cUnit, BasicBlock* bb,
- RefCounts* counts, bool fp)
+ RefCounts* coreCounts, RefCounts* fpCounts)
{
MIR* mir;
if (bb->blockType != kDalvikByteCode && bb->blockType != kEntryBlock &&
@@ -47,59 +47,42 @@ STATIC void countRefs(CompilationUnit *cUnit, BasicBlock* bb,
for (mir = bb->firstMIRInsn; mir; mir = mir->next) {
SSARepresentation *ssaRep = mir->ssaRep;
if (ssaRep) {
- int i;
- int attrs = oatDataFlowAttributes[mir->dalvikInsn.opcode];
- if (fp) {
- // Mark 1st reg of double pairs
- int first = 0;
- int sReg;
- if ((attrs & (DF_DA_WIDE|DF_FP_A)) == (DF_DA_WIDE|DF_FP_A)) {
- sReg = DECODE_REG(
- oatConvertSSARegToDalvik(cUnit, ssaRep->defs[0]));
- counts[sReg].doubleStart = true;
+ for (int i = 0; i < ssaRep->numDefs;) {
+ RegLocation loc = cUnit->regLocation[ssaRep->defs[i]];
+ RefCounts* counts = loc.fp ? fpCounts : coreCounts;
+ int vReg = oatS2VReg(cUnit, ssaRep->defs[i]);
+ if (loc.defined) {
+ counts[vReg].count++;
}
- if ((attrs & (DF_UA_WIDE|DF_FP_A)) == (DF_UA_WIDE|DF_FP_A)) {
- sReg = DECODE_REG(
- oatConvertSSARegToDalvik(cUnit, ssaRep->uses[first]));
- counts[sReg].doubleStart = true;
- }
- if (attrs & DF_UA_WIDE) {
- first += 2;
- }
- if ((attrs & (DF_UB_WIDE|DF_FP_B)) == (DF_UB_WIDE|DF_FP_B)) {
- sReg = DECODE_REG(
- oatConvertSSARegToDalvik(cUnit, ssaRep->uses[first]));
- counts[sReg].doubleStart = true;
- }
- if (attrs & DF_UB_WIDE) {
- first += 2;
- }
- if ((attrs & (DF_UC_WIDE|DF_FP_C)) == (DF_UC_WIDE|DF_FP_C)) {
- sReg = DECODE_REG(
- oatConvertSSARegToDalvik(cUnit, ssaRep->uses[first]));
- counts[sReg].doubleStart = true;
- }
- }
- for (i=0; i< ssaRep->numUses; i++) {
- int origSreg = DECODE_REG(
- oatConvertSSARegToDalvik(cUnit, ssaRep->uses[i]));
- DCHECK_LT(origSreg, cUnit->method->NumRegisters());
- bool fpUse = ssaRep->fpUse ? ssaRep->fpUse[i] : false;
- if (fp == fpUse) {
- counts[origSreg].count++;
+ if (loc.wide) {
+ if (loc.defined) {
+ if (loc.fp) {
+ counts[vReg].doubleStart = true;
+ }
+ counts[vReg+1].count++;
+ }
+ i += 2;
+ } else {
+ i++;
}
}
- for (i=0; i< ssaRep->numDefs; i++) {
- if (attrs & DF_SETS_CONST) {
- // CONST opcodes are untyped - don't pollute the counts
- continue;
+ for (int i = 0; i < ssaRep->numUses;) {
+ RegLocation loc = cUnit->regLocation[ssaRep->uses[i]];
+ RefCounts* counts = loc.fp ? fpCounts : coreCounts;
+ int vReg = oatS2VReg(cUnit, ssaRep->uses[i]);
+ if (loc.defined) {
+ counts[vReg].count++;
}
- int origSreg = DECODE_REG(
- oatConvertSSARegToDalvik(cUnit, ssaRep->defs[i]));
- DCHECK_LT(origSreg, cUnit->method->NumRegisters());
- bool fpDef = ssaRep->fpDef ? ssaRep->fpDef[i] : false;
- if (fp == fpDef) {
- counts[origSreg].count++;
+ if (loc.wide) {
+ if (loc.defined) {
+ if (loc.fp) {
+ counts[vReg].doubleStart = true;
+ }
+ counts[vReg+1].count++;
+ }
+ i += 2;
+ } else {
+ i++;
}
}
}
@@ -159,8 +142,7 @@ extern void oatDoPromotion(CompilationUnit* cUnit)
BasicBlock* bb;
bb = (BasicBlock*)oatGrowableListIteratorNext(&iterator);
if (bb == NULL) break;
- countRefs(cUnit, bb, coreRegs, false);
- countRefs(cUnit, bb, fpRegs, true);
+ countRefs(cUnit, bb, coreRegs, fpRegs);
}
/*
@@ -178,21 +160,27 @@ extern void oatDoPromotion(CompilationUnit* cUnit)
qsort(coreRegs, numRegs, sizeof(RefCounts), sortCounts);
qsort(fpRegs, numRegs, sizeof(RefCounts), sortCounts);
+ if (cUnit->printMe) {
+ dumpCounts(coreRegs, numRegs, "Core regs after sort");
+ dumpCounts(fpRegs, numRegs, "Fp regs after sort");
+ }
+
if (!(cUnit->disableOpt & (1 << kPromoteRegs))) {
// Promote fpRegs
for (int i = 0; (fpRegs[i].count > 0) && (i < numRegs); i++) {
- if (cUnit->regLocation[fpRegs[i].sReg].fpLocation != kLocPhysReg) {
+ if (cUnit->promotionMap[fpRegs[i].sReg].fpLocation != kLocPhysReg) {
int reg = oatAllocPreservedFPReg(cUnit, fpRegs[i].sReg,
fpRegs[i].doubleStart);
if (reg < 0) {
- break; // No more left
+ break; // No more left
}
}
}
// Promote core regs
for (int i = 0; (coreRegs[i].count > 0) && i < numRegs; i++) {
- if (cUnit->regLocation[i].location != kLocPhysReg) {
+ if (cUnit->promotionMap[coreRegs[i].sReg].coreLocation !=
+ kLocPhysReg) {
int reg = oatAllocPreservedCoreReg(cUnit, coreRegs[i].sReg);
if (reg < 0) {
break; // No more left
@@ -203,58 +191,69 @@ extern void oatDoPromotion(CompilationUnit* cUnit)
// Now, update SSA names to new home locations
for (int i = 0; i < cUnit->numSSARegs; i++) {
- int baseSreg = cUnit->regLocation[i].sRegLow;
- RegLocation *base = &cUnit->regLocation[baseSreg];
- RegLocation *baseNext = &cUnit->regLocation[baseSreg+1];
RegLocation *curr = &cUnit->regLocation[i];
- if (curr->fp) {
- /* Single or double, check fpLocation of base */
- if (base->fpLocation == kLocPhysReg) {
- if (curr->wide) {
- /* TUNING: consider alignment during allocation */
- if ((base->fpLowReg & 1) ||
- (baseNext->fpLocation != kLocPhysReg)) {
- /* Half-promoted or bad alignment - demote */
- curr->location = kLocDalvikFrame;
- curr->lowReg = INVALID_REG;
- curr->highReg = INVALID_REG;
- continue;
- }
- curr->highReg = baseNext->fpLowReg;
+ int baseVReg = oatS2VReg(cUnit, curr->sRegLow);
+ if (!curr->wide) {
+ if (curr->fp) {
+ if (cUnit->promotionMap[baseVReg].fpLocation == kLocPhysReg) {
+ curr->location = kLocPhysReg;
+ curr->lowReg = cUnit->promotionMap[baseVReg].fpReg;
+ curr->home = true;
+ }
+ } else {
+ if (cUnit->promotionMap[baseVReg].coreLocation == kLocPhysReg) {
+ curr->location = kLocPhysReg;
+ curr->lowReg = cUnit->promotionMap[baseVReg].coreReg;
+ curr->home = true;
}
- curr->location = kLocPhysReg;
- curr->lowReg = base->fpLowReg;
- curr->home = true;
}
+ curr->highReg = INVALID_REG;
} else {
- /* Core or wide */
- if (base->location == kLocPhysReg) {
- if (curr->wide) {
- /* Make sure upper half is also in reg or skip */
- if (baseNext->location != kLocPhysReg) {
- /* Only half promoted; demote to frame */
- curr->location = kLocDalvikFrame;
- curr->lowReg = INVALID_REG;
- curr->highReg = INVALID_REG;
- continue;
+ if (curr->highWord) {
+ continue;
+ }
+ if (curr->fp) {
+ if ((cUnit->promotionMap[baseVReg].fpLocation == kLocPhysReg) &&
+ (cUnit->promotionMap[baseVReg+1].fpLocation ==
+ kLocPhysReg)) {
+ int lowReg = cUnit->promotionMap[baseVReg].fpReg;
+ int highReg = cUnit->promotionMap[baseVReg+1].fpReg;
+ // Doubles require pair of singles starting at even reg
+ if (((lowReg & 0x1) == 0) && ((lowReg + 1) == highReg)) {
+ curr->location = kLocPhysReg;
+ curr->lowReg = lowReg;
+ curr->highReg = highReg;
+ curr->home = true;
}
- curr->highReg = baseNext->lowReg;
}
- curr->location = kLocPhysReg;
- curr->lowReg = base->lowReg;
- curr->home = true;
+ } else {
+ if ((cUnit->promotionMap[baseVReg].coreLocation == kLocPhysReg)
+ && (cUnit->promotionMap[baseVReg+1].coreLocation ==
+ kLocPhysReg)) {
+ curr->location = kLocPhysReg;
+ curr->lowReg = cUnit->promotionMap[baseVReg].coreReg;
+ curr->highReg = cUnit->promotionMap[baseVReg+1].coreReg;
+ curr->home = true;
+ }
}
}
}
}
-/* Returns sp-relative offset in bytes */
-extern int oatVRegOffset(CompilationUnit* cUnit, int reg)
+/* Returns sp-relative offset in bytes for a VReg */
+extern int oatVRegOffset(CompilationUnit* cUnit, int vReg)
{
- return (reg < cUnit->numRegs) ? cUnit->regsOffset + (reg << 2) :
- cUnit->insOffset + ((reg - cUnit->numRegs) << 2);
+ return (vReg < cUnit->numRegs) ? cUnit->regsOffset + (vReg << 2) :
+ cUnit->insOffset + ((vReg - cUnit->numRegs) << 2);
}
+/* Returns sp-relative offset in bytes for a SReg */
+extern int oatSRegOffset(CompilationUnit* cUnit, int sReg)
+{
+ return oatVRegOffset(cUnit, oatS2VReg(cUnit, sReg));
+}
+
+
/* Return sp-relative offset in bytes using Method* */
extern int oatVRegOffsetFromMethod(Method* method, int reg)
{
diff --git a/src/compiler/codegen/arm/MethodCodegenDriver.cc b/src/compiler/codegen/arm/MethodCodegenDriver.cc
index 633125443b..4a657718fd 100644
--- a/src/compiler/codegen/arm/MethodCodegenDriver.cc
+++ b/src/compiler/codegen/arm/MethodCodegenDriver.cc
@@ -17,10 +17,8 @@
#define DISPLAY_MISSING_TARGETS (cUnit->enableDebug & \
(1 << kDebugDisplayMissingTargets))
-STATIC const RegLocation badLoc = {kLocDalvikFrame, 0, 0, INVALID_REG,
- INVALID_REG, INVALID_SREG, 0,
- kLocDalvikFrame, INVALID_REG, INVALID_REG,
- INVALID_OFFSET};
+STATIC const RegLocation badLoc = {kLocDalvikFrame, 0, 0, 0, 0, 0, 0, INVALID_REG,
+ INVALID_REG, INVALID_SREG};
/* Mark register usage state and return long retloc */
STATIC RegLocation getRetLocWide(CompilationUnit* cUnit)
@@ -99,7 +97,8 @@ STATIC void genFilledNewArray(CompilationUnit* cUnit, MIR* mir, bool isRange)
RegLocation loc = oatUpdateLoc(cUnit,
oatGetSrc(cUnit, mir, i));
if (loc.location == kLocPhysReg) {
- storeBaseDisp(cUnit, rSP, loc.spOffset, loc.lowReg, kWord);
+ storeBaseDisp(cUnit, rSP, oatSRegOffset(cUnit, loc.sRegLow),
+ loc.lowReg, kWord);
}
}
/*
@@ -113,7 +112,8 @@ STATIC void genFilledNewArray(CompilationUnit* cUnit, MIR* mir, bool isRange)
int rVal = rLR; // Using a lot of temps, rLR is known free here
// Set up source pointer
RegLocation rlFirst = oatGetSrc(cUnit, mir, 0);
- opRegRegImm(cUnit, kOpAdd, rSrc, rSP, rlFirst.spOffset);
+ opRegRegImm(cUnit, kOpAdd, rSrc, rSP,
+ oatSRegOffset(cUnit, rlFirst.sRegLow));
// Set up the target pointer
opRegRegImm(cUnit, kOpAdd, rDst, r0,
Array::DataOffset().Int32Value());
@@ -773,7 +773,8 @@ STATIC int genDalvikArgsNoRange(CompilationUnit* cUnit, MIR* mir,
} else {
// r2 & r3 can safely be used here
reg = r3;
- loadWordDisp(cUnit, rSP, rlArg.spOffset + 4, reg);
+ loadWordDisp(cUnit, rSP,
+ oatSRegOffset(cUnit, rlArg.sRegLow) + 4, reg);
callState = nextCallInsn(cUnit, mir, dInsn, callState,
rollback);
}
@@ -872,20 +873,23 @@ STATIC int genDalvikArgsRange(CompilationUnit* cUnit, MIR* mir,
if (loc.wide) {
loc = oatUpdateLocWide(cUnit, loc);
if ((nextArg >= 2) && (loc.location == kLocPhysReg)) {
- storeBaseDispWide(cUnit, rSP, loc.spOffset, loc.lowReg,
- loc.highReg);
+ storeBaseDispWide(cUnit, rSP,
+ oatSRegOffset(cUnit, loc.sRegLow),
+ loc.lowReg, loc.highReg);
}
nextArg += 2;
} else {
loc = oatUpdateLoc(cUnit, loc);
if ((nextArg >= 3) && (loc.location == kLocPhysReg)) {
- storeBaseDisp(cUnit, rSP, loc.spOffset, loc.lowReg, kWord);
+ storeBaseDisp(cUnit, rSP, oatSRegOffset(cUnit, loc.sRegLow),
+ loc.lowReg, kWord);
}
nextArg++;
}
}
- int startOffset = cUnit->regLocation[mir->ssaRep->uses[3]].spOffset;
+ int startOffset = oatSRegOffset(cUnit,
+ cUnit->regLocation[mir->ssaRep->uses[3]].sRegLow);
int outsOffset = 4 /* Method* */ + (3 * 4);
if (numArgs >= 20) {
// Generate memcpy
@@ -1790,63 +1794,44 @@ STATIC void handleExtendedMethodMIR(CompilationUnit* cUnit, MIR* mir)
}
}
-/* If there are any ins passed in registers that have not been promoted
- * to a callee-save register, flush them to the frame.
- * Note: at this pointCopy any ins that are passed in register to their
- * home location */
+/*
+ * If there are any ins passed in registers that have not been promoted
+ * to a callee-save register, flush them to the frame. Perform intial
+ * assignment of promoted arguments.
+ */
STATIC void flushIns(CompilationUnit* cUnit)
{
if (cUnit->method->NumIns() == 0)
return;
- int inRegs = (cUnit->method->NumIns() > 2) ? 3
- : cUnit->method->NumIns();
- int startReg = r1;
- int startLoc = cUnit->method->NumRegisters() -
+ int firstArgReg = r1;
+ int lastArgReg = r3;
+ int startVReg = cUnit->method->NumRegisters() -
cUnit->method->NumIns();
- for (int i = 0; i < inRegs; i++) {
- RegLocation loc = cUnit->regLocation[startLoc + i];
- //TUNING: be smarter about flushing ins to frame
- storeBaseDisp(cUnit, rSP, loc.spOffset, startReg + i, kWord);
- if (loc.location == kLocPhysReg) {
- genRegCopy(cUnit, loc.lowReg, startReg + i);
- }
- }
-
- // Handle special case of wide argument half in regs, half in frame
- if (inRegs == 3) {
- RegLocation loc = cUnit->regLocation[startLoc + 2];
- if (loc.wide && loc.location == kLocPhysReg) {
- // Load the other half of the arg into the promoted pair
- loadWordDisp(cUnit, rSP, loc.spOffset + 4, loc.highReg);
- inRegs++;
- }
- }
-
- // Now, do initial assignment of all promoted arguments passed in frame
- for (int i = inRegs; i < cUnit->method->NumIns();) {
- RegLocation loc = cUnit->regLocation[startLoc + i];
- if (loc.fpLocation == kLocPhysReg) {
- loc.location = kLocPhysReg;
- loc.fp = true;
- loc.lowReg = loc.fpLowReg;
- loc.highReg = loc.fpHighReg;
- }
- if (loc.location == kLocPhysReg) {
- if (loc.wide) {
- if (loc.fp && (loc.lowReg & 1) != 0) {
- // Misaligned - need to load as a pair of singles
- loadWordDisp(cUnit, rSP, loc.spOffset, loc.lowReg);
- loadWordDisp(cUnit, rSP, loc.spOffset + 4, loc.highReg);
- } else {
- loadBaseDispWide(cUnit, NULL, rSP, loc.spOffset,
- loc.lowReg, loc.highReg, INVALID_SREG);
- }
- i++;
- } else {
- loadWordDisp(cUnit, rSP, loc.spOffset, loc.lowReg);
+ for (int i = 0; i < cUnit->method->NumIns(); i++) {
+ PromotionMap vMap = cUnit->promotionMap[startVReg + i];
+ // For arguments only, should have at most one promotion kind
+ DCHECK(!((vMap.coreLocation == kLocPhysReg) &&
+ (vMap.fpLocation == kLocPhysReg)));
+ if (i <= (lastArgReg - firstArgReg)) {
+ // If arriving in register, copy or flush
+ if (vMap.coreLocation == kLocPhysReg) {
+ genRegCopy(cUnit, vMap.coreReg, firstArgReg + i);
+ } else if (vMap.fpLocation == kLocPhysReg) {
+ genRegCopy(cUnit, vMap.fpReg, firstArgReg + i);
+ }
+ // Also put a copy in memory in case we're partially promoted
+ storeBaseDisp(cUnit, rSP, oatSRegOffset(cUnit, startVReg + i),
+ firstArgReg + i, kWord);
+ } else {
+ // If arriving in frame, initialize promoted target regs
+ if (vMap.coreLocation == kLocPhysReg) {
+ loadWordDisp(cUnit, rSP, oatSRegOffset(cUnit, startVReg + i),
+ vMap.coreReg);
+ } else if (vMap.fpLocation == kLocPhysReg) {
+ loadWordDisp(cUnit, rSP, oatSRegOffset(cUnit, startVReg + i),
+ vMap.fpReg);
}
}
- i++;
}
}