Quick compiler, fix wide bug
In Dalvik, 64-bit data items are represented as a pair of 32-bit
registers. The Art compiler maintained this notation, while llvm
expects properly typed data. During the conversion to bitcode, we
must drop the high word of pairs, while correctly typing the low.
This CL fixes several bugs related to this. "Placeholder" llvm
Values are created only for the low word of pairs, and we now skip
Phi node generation for high words. Doing this required a bit
of tightening up of the size & type inference code (which previously
was able to get away with ignoring high words).
Also, I've moved shift operations into intrinics because Dalvik
and llvm have different ideas about what a shift means.
Bitcode generation is only supported for the Arm target at the
moment. With this CL, all target tests pass and the phone boots.
Some caveats:
o Performance data is not yet meaningful, either compile or
run times.
o When configured for Quick, we run single-threaded.
o In a small percentage of methods, we generate invalid llvm
bitcode (missing exception edges). As-checked-in, llvm
function generation is turned off to avoid missing edge
complaints (to enable testing of the Quick backend).
Change-Id: I66932ffb44d299fcaf0a112e0d1c217c49341ccf
diff --git a/src/compiler/Ralloc.cc b/src/compiler/Ralloc.cc
index ea4d6c1..500b1b2 100644
--- a/src/compiler/Ralloc.cc
+++ b/src/compiler/Ralloc.cc
@@ -23,9 +23,6 @@
bool setFp(CompilationUnit* cUnit, int index, bool isFP) {
bool change = false;
- if (cUnit->regLocation[index].highWord) {
- return change;
- }
if (isFP && !cUnit->regLocation[index].fp) {
cUnit->regLocation[index].fp = true;
cUnit->regLocation[index].defined = true;
@@ -36,9 +33,6 @@
bool setCore(CompilationUnit* cUnit, int index, bool isCore) {
bool change = false;
- if (cUnit->regLocation[index].highWord) {
- return change;
- }
if (isCore && !cUnit->regLocation[index].defined) {
cUnit->regLocation[index].core = true;
cUnit->regLocation[index].defined = true;
@@ -49,9 +43,6 @@
bool setRef(CompilationUnit* cUnit, int index, bool isRef) {
bool change = false;
- if (cUnit->regLocation[index].highWord) {
- return change;
- }
if (isRef && !cUnit->regLocation[index].defined) {
cUnit->regLocation[index].ref = true;
cUnit->regLocation[index].defined = true;
@@ -60,6 +51,24 @@
return change;
}
+bool setWide(CompilationUnit* cUnit, int index, bool isWide) {
+ bool change = false;
+ if (isWide && !cUnit->regLocation[index].wide) {
+ cUnit->regLocation[index].wide = true;
+ change = true;
+ }
+ return change;
+}
+
+bool setHigh(CompilationUnit* cUnit, int index, bool isHigh) {
+ bool change = false;
+ if (isHigh && !cUnit->regLocation[index].highWord) {
+ cUnit->regLocation[index].highWord = true;
+ change = true;
+ }
+ return change;
+}
+
bool remapNames(CompilationUnit* cUnit, BasicBlock* bb)
{
if (bb->blockType != kDalvikByteCode && bb->blockType != kEntryBlock &&
@@ -123,6 +132,7 @@
}
if (attrs & DF_A_WIDE) {
cUnit->regLocation[ssaRep->defs[0]].wide = true;
+ cUnit->regLocation[ssaRep->defs[1]].wide = true;
cUnit->regLocation[ssaRep->defs[1]].highWord = true;
DCHECK_EQ(SRegToVReg(cUnit, ssaRep->defs[0])+1,
SRegToVReg(cUnit, ssaRep->defs[1]));
@@ -140,6 +150,7 @@
}
if (attrs & DF_A_WIDE) {
cUnit->regLocation[ssaRep->uses[next]].wide = true;
+ cUnit->regLocation[ssaRep->uses[next + 1]].wide = true;
cUnit->regLocation[ssaRep->uses[next + 1]].highWord = true;
DCHECK_EQ(SRegToVReg(cUnit, ssaRep->uses[next])+1,
SRegToVReg(cUnit, ssaRep->uses[next + 1]));
@@ -157,6 +168,7 @@
}
if (attrs & DF_B_WIDE) {
cUnit->regLocation[ssaRep->uses[next]].wide = true;
+ cUnit->regLocation[ssaRep->uses[next + 1]].wide = true;
cUnit->regLocation[ssaRep->uses[next + 1]].highWord = true;
DCHECK_EQ(SRegToVReg(cUnit, ssaRep->uses[next])+1,
SRegToVReg(cUnit, ssaRep->uses[next + 1]));
@@ -174,6 +186,7 @@
}
if (attrs & DF_C_WIDE) {
cUnit->regLocation[ssaRep->uses[next]].wide = true;
+ cUnit->regLocation[ssaRep->uses[next + 1]].wide = true;
cUnit->regLocation[ssaRep->uses[next + 1]].highWord = true;
DCHECK_EQ(SRegToVReg(cUnit, ssaRep->uses[next])+1,
SRegToVReg(cUnit, ssaRep->uses[next + 1]));
@@ -192,6 +205,7 @@
changed |= setCore(cUnit, ssaRep->uses[0], true);
changed |= setCore(cUnit, ssaRep->uses[1], true);
cUnit->regLocation[ssaRep->uses[0]].wide = true;
+ cUnit->regLocation[ssaRep->uses[1]].wide = true;
cUnit->regLocation[ssaRep->uses[1]].highWord = true;
break;
case 'F':
@@ -201,6 +215,7 @@
changed |= setFp(cUnit, ssaRep->uses[0], true);
changed |= setFp(cUnit, ssaRep->uses[1], true);
cUnit->regLocation[ssaRep->uses[0]].wide = true;
+ cUnit->regLocation[ssaRep->uses[1]].wide = true;
cUnit->regLocation[ssaRep->uses[1]].highWord = true;
break;
case 'L':
@@ -254,6 +269,7 @@
ssaRep->fpUse[i] = true;
ssaRep->fpUse[i+1] = true;
cUnit->regLocation[ssaRep->uses[i]].wide = true;
+ cUnit->regLocation[ssaRep->uses[i+1]].wide = true;
cUnit->regLocation[ssaRep->uses[i+1]].highWord = true;
DCHECK_EQ(SRegToVReg(cUnit, ssaRep->uses[i])+1,
SRegToVReg(cUnit, ssaRep->uses[i+1]));
@@ -261,6 +277,7 @@
break;
case 'J':
cUnit->regLocation[ssaRep->uses[i]].wide = true;
+ cUnit->regLocation[ssaRep->uses[i+1]].wide = true;
cUnit->regLocation[ssaRep->uses[i+1]].highWord = true;
DCHECK_EQ(SRegToVReg(cUnit, ssaRep->uses[i])+1,
SRegToVReg(cUnit, ssaRep->uses[i+1]));
@@ -292,23 +309,27 @@
}
// Special-case handling for moves & Phi
if (attrs & (DF_IS_MOVE | DF_NULL_TRANSFER_N)) {
- // If any of our inputs or outputs is defined, set all
- bool definedFP = false;
- bool definedCore = false;
- bool definedRef = false;
- definedFP |= (cUnit->regLocation[ssaRep->defs[0]].defined &&
- cUnit->regLocation[ssaRep->defs[0]].fp);
- definedCore |= (cUnit->regLocation[ssaRep->defs[0]].defined &&
- cUnit->regLocation[ssaRep->defs[0]].core);
- definedRef |= (cUnit->regLocation[ssaRep->defs[0]].defined &&
- cUnit->regLocation[ssaRep->defs[0]].ref);
- for (int i = 0; i < ssaRep->numUses; i++) {
- definedFP |= (cUnit->regLocation[ssaRep->uses[i]].defined &&
- cUnit->regLocation[ssaRep->uses[i]].fp);
- definedCore |= (cUnit->regLocation[ssaRep->uses[i]].defined
- && cUnit->regLocation[ssaRep->uses[i]].core);
- definedRef |= (cUnit->regLocation[ssaRep->uses[i]].defined
- && cUnit->regLocation[ssaRep->uses[i]].ref);
+ /*
+ * If any of our inputs or outputs is defined, set all.
+ * Some ugliness related to Phi nodes and wide values.
+ * The Phi set will include all low words or all high
+ * words, so we have to treat them specially.
+ */
+ bool isPhi = (static_cast<int>(mir->dalvikInsn.opcode) ==
+ kMirOpPhi);
+ RegLocation rlTemp = cUnit->regLocation[ssaRep->defs[0]];
+ bool definedFP = rlTemp.defined && rlTemp.fp;
+ bool definedCore = rlTemp.defined && rlTemp.core;
+ bool definedRef = rlTemp.defined && rlTemp.ref;
+ bool isWide = rlTemp.wide || ((attrs & DF_A_WIDE) != 0);
+ bool isHigh = isPhi && rlTemp.wide && rlTemp.highWord;
+ for (int i = 0; i < ssaRep->numUses;i++) {
+ rlTemp = cUnit->regLocation[ssaRep->uses[i]];
+ definedFP |= rlTemp.defined && rlTemp.fp;
+ definedCore |= rlTemp.defined && rlTemp.core;
+ definedRef |= rlTemp.defined && rlTemp.ref;
+ isWide |= rlTemp.wide;
+ isHigh |= isPhi && rlTemp.wide && rlTemp.highWord;
}
/*
* TODO: cleaner fix
@@ -334,10 +355,23 @@
changed |= setFp(cUnit, ssaRep->defs[0], definedFP);
changed |= setCore(cUnit, ssaRep->defs[0], definedCore);
changed |= setRef(cUnit, ssaRep->defs[0], definedRef);
+ changed |= setWide(cUnit, ssaRep->defs[0], isWide);
+ changed |= setHigh(cUnit, ssaRep->defs[0], isHigh);
+ if (attrs & DF_A_WIDE) {
+ changed |= setWide(cUnit, ssaRep->defs[1], true);
+ changed |= setHigh(cUnit, ssaRep->defs[1], true);
+ }
for (int i = 0; i < ssaRep->numUses; i++) {
- changed |= setFp(cUnit, ssaRep->uses[i], definedFP);
- changed |= setCore(cUnit, ssaRep->uses[i], definedCore);
- changed |= setRef(cUnit, ssaRep->uses[i], definedRef);
+ changed |= setFp(cUnit, ssaRep->uses[i], definedFP);
+ changed |= setCore(cUnit, ssaRep->uses[i], definedCore);
+ changed |= setRef(cUnit, ssaRep->uses[i], definedRef);
+ changed |= setWide(cUnit, ssaRep->uses[i], isWide);
+ changed |= setHigh(cUnit, ssaRep->uses[i], isHigh);
+ }
+ if (attrs & DF_A_WIDE) {
+ DCHECK_EQ(ssaRep->numUses, 2);
+ changed |= setWide(cUnit, ssaRep->uses[1], true);
+ changed |= setHigh(cUnit, ssaRep->uses[1], true);
}
}
}