summaryrefslogtreecommitdiff
path: root/src/compiler/codegen/GenInvoke.cc
diff options
context:
space:
mode:
author buzbee <buzbee@google.com> 2012-03-06 18:15:00 -0800
committer buzbee <buzbee@google.com> 2012-03-07 12:10:21 -0800
commit86a4bce32e2aaf3d377c0acf865f0630a7c30495 (patch)
tree98517211fdb1309f461e3fe3c41a34739ad121c1 /src/compiler/codegen/GenInvoke.cc
parent6150d9889b56e95f1267d9200c5702b16e0d32d5 (diff)
Fix branch bug (showed up in codegen for debug)
There are a few "safe" optimizations in the compiler - removing register copies where source and target are the same, deleting branches to the next instruction, etc. One of the redundant branch optimizations, however, was incorrect and resulted in a good branch being deleted. This one showed up in the debug build, and resulted in a failure to do a suspend check (because the branch to the suspend check was deleted). I had hoped that this but might also be the case of some other unexpected failures, but unfortunately I was only able to trigger it when doing a "codegen for debug" build. The source of the bug was a confusion around 16 v/ 32-bit unconditional branch encodings. For a 32-bit unconditional branch, going to the next instruction means an displacement of zero. However, for 16-bit branches, the next instruction is represented by a displacement of -1. To help track down this sort of thing in the future, this CL also adds a new optimization disable flag: kSafeOptimizations. This will allow us to really turn off all optimizations for A/B testing. Also in this CL we are re-enabling the ability to promote argument registers and improving somewhat the code sequence for suspend check when debug is enabled. Change-Id: Ib6b202746eac751cab3b4609805a389c18cb67b2
Diffstat (limited to 'src/compiler/codegen/GenInvoke.cc')
-rw-r--r--src/compiler/codegen/GenInvoke.cc54
1 files changed, 34 insertions, 20 deletions
diff --git a/src/compiler/codegen/GenInvoke.cc b/src/compiler/codegen/GenInvoke.cc
index 4698868ad2..c2d0d1880d 100644
--- a/src/compiler/codegen/GenInvoke.cc
+++ b/src/compiler/codegen/GenInvoke.cc
@@ -43,38 +43,52 @@ void flushIns(CompilationUnit* cUnit)
int lastArgReg = rARG3;
int startVReg = cUnit->numDalvikRegisters - cUnit->numIns;
/*
- * Arguments passed in registers should be flushed
- * to their backing locations in the frame for now.
- * Also, we need to do initial assignment for promoted
- * arguments. NOTE: an older version of dx had an issue
- * in which it would reuse static method argument registers.
+ * Copy incoming arguments to their proper home locations.
+ * NOTE: an older version of dx had an issue in which
+ * it would reuse static method argument registers.
* This could result in the same Dalvik virtual register
- * being promoted to both core and fp regs. In those
- * cases, copy argument to both. This will be uncommon
- * enough that it isn't worth attempting to optimize.
+ * being promoted to both core and fp regs. To account for this,
+ * we only copy to the corresponding promoted physical register
+ * if it matches the type of the SSA name for the incoming
+ * argument. It is also possible that long and double arguments
+ * end up half-promoted. In those cases, we must flush the promoted
+ * half to memory as well.
*/
for (int i = 0; i < cUnit->numIns; i++) {
- PromotionMap vMap = cUnit->promotionMap[startVReg + i];
+ PromotionMap* vMap = &cUnit->promotionMap[startVReg + i];
if (i <= (lastArgReg - firstArgReg)) {
// If arriving in register
- if (vMap.coreLocation == kLocPhysReg) {
- opRegCopy(cUnit, vMap.coreReg, firstArgReg + i);
+ bool needFlush = true;
+ RegLocation* tLoc = &cUnit->regLocation[startVReg + i];
+ if ((vMap->coreLocation == kLocPhysReg) && !tLoc->fp) {
+ opRegCopy(cUnit, vMap->coreReg, firstArgReg + i);
+ needFlush = false;
+ } else if ((vMap->fpLocation == kLocPhysReg) && tLoc->fp) {
+ opRegCopy(cUnit, vMap->fpReg, firstArgReg + i);
+ needFlush = false;
+ } else {
+ needFlush = true;
+ }
+
+ // For wide args, force flush if only half is promoted
+ if (tLoc->wide) {
+ PromotionMap* pMap = vMap + (tLoc->highWord ? -1 : +1);
+ needFlush |= (pMap->coreLocation != vMap->coreLocation) ||
+ (pMap->fpLocation != vMap->fpLocation);
}
- if (vMap.fpLocation == kLocPhysReg) {
- opRegCopy(cUnit, vMap.fpReg, firstArgReg + i);
+ if (needFlush) {
+ storeBaseDisp(cUnit, rSP, oatSRegOffset(cUnit, startVReg + i),
+ firstArgReg + i, kWord);
}
- // 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 & promoted
- if (vMap.coreLocation == kLocPhysReg) {
+ if (vMap->coreLocation == kLocPhysReg) {
loadWordDisp(cUnit, rSP, oatSRegOffset(cUnit, startVReg + i),
- vMap.coreReg);
+ vMap->coreReg);
}
- if (vMap.fpLocation == kLocPhysReg) {
+ if (vMap->fpLocation == kLocPhysReg) {
loadWordDisp(cUnit, rSP, oatSRegOffset(cUnit, startVReg + i),
- vMap.fpReg);
+ vMap->fpReg);
}
}
}