Support for promoting Method* and compiler temps

This CL completes the support for allowing compiler-generated
data to be treated as a Dalvik register and become subject to
the normal register promotion and live temp tracking machinery.

Also:
   o Removes some vestigal and useless Method* loads from
     range argument setup.
   o Changes the Method* pseudo vReg number from -1 to -2 to
     avoid a conflict with the 0xffff marker in the register map.
   o Removes some experimental code for CSE at the basic block
     level.

Change-Id: I112a8bbe20f95a8d789f63908c84e5fa167c74ac
diff --git a/src/compiler/Compiler.h b/src/compiler/Compiler.h
index 94d20e5..68a38a5 100644
--- a/src/compiler/Compiler.h
+++ b/src/compiler/Compiler.h
@@ -51,6 +51,7 @@
     kSkipLargeMethodOptimization,
     kSafeOptimizations,
     kBBOpt,
+    kPromoteCompilerTemps,
 };
 
 /* Type of allocation for memory tuning */
diff --git a/src/compiler/CompilerIR.h b/src/compiler/CompilerIR.h
index 8a3fa09..b512c5b 100644
--- a/src/compiler/CompilerIR.h
+++ b/src/compiler/CompilerIR.h
@@ -107,9 +107,9 @@
 #define INVALID_OFFSET (-1)
 
 /* SSA encodings for special registers */
-#define SSA_METHOD_BASEREG (-1)
+#define SSA_METHOD_BASEREG (-2)
 /* First compiler temp basereg, grows smaller */
-#define SSA_CTEMP_BASEREG (-2)
+#define SSA_CTEMP_BASEREG (SSA_METHOD_BASEREG - 1)
 
 /*
  * Some code patterns cause the generation of excessively large
diff --git a/src/compiler/Dataflow.cc b/src/compiler/Dataflow.cc
index 7b05a66..a87c401 100644
--- a/src/compiler/Dataflow.cc
+++ b/src/compiler/Dataflow.cc
@@ -123,31 +123,31 @@
     DF_UA | DF_NULL_CHK_0 | DF_CORE_A,
 
     // 1F CHK_CAST vAA, type@BBBB
-    DF_UA | DF_CORE_A,
+    DF_UA | DF_CORE_A | DF_UMS,
 
     // 20 INSTANCE_OF vA, vB, type@CCCC
-    DF_DA | DF_UB | DF_CORE_A | DF_CORE_B,
+    DF_DA | DF_UB | DF_CORE_A | DF_CORE_B | DF_UMS,
 
     // 21 ARRAY_LENGTH vA, vB
     DF_DA | DF_UB | DF_NULL_CHK_0 | DF_CORE_A | DF_CORE_B,
 
     // 22 NEW_INSTANCE vAA, type@BBBB
-    DF_DA | DF_NON_NULL_DST | DF_CORE_A,
+    DF_DA | DF_NON_NULL_DST | DF_CORE_A | DF_UMS,
 
     // 23 NEW_ARRAY vA, vB, type@CCCC
-    DF_DA | DF_UB | DF_NON_NULL_DST | DF_CORE_A | DF_CORE_B,
+    DF_DA | DF_UB | DF_NON_NULL_DST | DF_CORE_A | DF_CORE_B | DF_UMS,
 
     // 24 FILLED_NEW_ARRAY {vD, vE, vF, vG, vA}
-    DF_FORMAT_35C | DF_NON_NULL_RET,
+    DF_FORMAT_35C | DF_NON_NULL_RET | DF_UMS,
 
     // 25 FILLED_NEW_ARRAY_RANGE {vCCCC .. vNNNN}, type@BBBB
-    DF_FORMAT_3RC | DF_NON_NULL_RET,
+    DF_FORMAT_3RC | DF_NON_NULL_RET | DF_UMS,
 
     // 26 FILL_ARRAY_DATA vAA, +BBBBBBBB
-    DF_UA | DF_CORE_A,
+    DF_UA | DF_CORE_A | DF_UMS,
 
     // 27 THROW vAA
-    DF_UA | DF_CORE_A,
+    DF_UA | DF_CORE_A | DF_UMS,
 
     // 28 GOTO
     DF_NOP,
@@ -235,163 +235,163 @@
     DF_NOP,
 
     // 44 AGET vAA, vBB, vCC
-    DF_DA | DF_UB | DF_UC | DF_NULL_CHK_0 | DF_RANGE_CHK_1 | DF_IS_GETTER | DF_CORE_B | DF_CORE_C,
+    DF_DA | DF_UB | DF_UC | DF_NULL_CHK_0 | DF_RANGE_CHK_1 | DF_CORE_B | DF_CORE_C,
 
     // 45 AGET_WIDE vAA, vBB, vCC
-    DF_DA_WIDE | DF_UB | DF_UC | DF_NULL_CHK_0 | DF_RANGE_CHK_1 | DF_IS_GETTER | DF_CORE_B | DF_CORE_C,
+    DF_DA_WIDE | DF_UB | DF_UC | DF_NULL_CHK_0 | DF_RANGE_CHK_1 | DF_CORE_B | DF_CORE_C,
 
     // 46 AGET_OBJECT vAA, vBB, vCC
-    DF_DA | DF_UB | DF_UC | DF_NULL_CHK_0 | DF_RANGE_CHK_1 | DF_IS_GETTER | DF_CORE_B | DF_CORE_C,
+    DF_DA | DF_UB | DF_UC | DF_NULL_CHK_0 | DF_RANGE_CHK_1 | DF_CORE_B | DF_CORE_C,
 
     // 47 AGET_BOOLEAN vAA, vBB, vCC
-    DF_DA | DF_UB | DF_UC | DF_NULL_CHK_0 | DF_RANGE_CHK_1 | DF_IS_GETTER | DF_CORE_B | DF_CORE_C,
+    DF_DA | DF_UB | DF_UC | DF_NULL_CHK_0 | DF_RANGE_CHK_1 | DF_CORE_B | DF_CORE_C,
 
     // 48 AGET_BYTE vAA, vBB, vCC
-    DF_DA | DF_UB | DF_UC | DF_NULL_CHK_0 | DF_RANGE_CHK_1 | DF_IS_GETTER | DF_CORE_B | DF_CORE_C,
+    DF_DA | DF_UB | DF_UC | DF_NULL_CHK_0 | DF_RANGE_CHK_1 | DF_CORE_B | DF_CORE_C,
 
     // 49 AGET_CHAR vAA, vBB, vCC
-    DF_DA | DF_UB | DF_UC | DF_NULL_CHK_0 | DF_RANGE_CHK_1 | DF_IS_GETTER | DF_CORE_B | DF_CORE_C,
+    DF_DA | DF_UB | DF_UC | DF_NULL_CHK_0 | DF_RANGE_CHK_1 | DF_CORE_B | DF_CORE_C,
 
     // 4A AGET_SHORT vAA, vBB, vCC
-    DF_DA | DF_UB | DF_UC | DF_NULL_CHK_0 | DF_RANGE_CHK_1 | DF_IS_GETTER | DF_CORE_B | DF_CORE_C,
+    DF_DA | DF_UB | DF_UC | DF_NULL_CHK_0 | DF_RANGE_CHK_1 | DF_CORE_B | DF_CORE_C,
 
     // 4B APUT vAA, vBB, vCC
-    DF_UA | DF_UB | DF_UC | DF_NULL_CHK_1 | DF_RANGE_CHK_2 | DF_IS_SETTER | DF_CORE_B | DF_CORE_C,
+    DF_UA | DF_UB | DF_UC | DF_NULL_CHK_1 | DF_RANGE_CHK_2 | DF_CORE_B | DF_CORE_C,
 
     // 4C APUT_WIDE vAA, vBB, vCC
-    DF_UA_WIDE | DF_UB | DF_UC | DF_NULL_CHK_2 | DF_RANGE_CHK_2 | DF_IS_SETTER | DF_CORE_B | DF_CORE_C,
+    DF_UA_WIDE | DF_UB | DF_UC | DF_NULL_CHK_2 | DF_RANGE_CHK_3 | DF_CORE_B | DF_CORE_C,
 
     // 4D APUT_OBJECT vAA, vBB, vCC
-    DF_UA | DF_UB | DF_UC | DF_NULL_CHK_1 | DF_RANGE_CHK_2 | DF_IS_SETTER | DF_CORE_B | DF_CORE_C,
+    DF_UA | DF_UB | DF_UC | DF_NULL_CHK_1 | DF_RANGE_CHK_2 | DF_CORE_B | DF_CORE_C,
 
     // 4E APUT_BOOLEAN vAA, vBB, vCC
-    DF_UA | DF_UB | DF_UC | DF_NULL_CHK_1 | DF_RANGE_CHK_2 | DF_IS_SETTER | DF_CORE_B | DF_CORE_C,
+    DF_UA | DF_UB | DF_UC | DF_NULL_CHK_1 | DF_RANGE_CHK_2 | DF_CORE_B | DF_CORE_C,
 
     // 4F APUT_BYTE vAA, vBB, vCC
-    DF_UA | DF_UB | DF_UC | DF_NULL_CHK_1 | DF_RANGE_CHK_2 | DF_IS_SETTER | DF_CORE_B | DF_CORE_C,
+    DF_UA | DF_UB | DF_UC | DF_NULL_CHK_1 | DF_RANGE_CHK_2 | DF_CORE_B | DF_CORE_C,
 
     // 50 APUT_CHAR vAA, vBB, vCC
-    DF_UA | DF_UB | DF_UC | DF_NULL_CHK_1 | DF_RANGE_CHK_2 | DF_IS_SETTER | DF_CORE_B | DF_CORE_C,
+    DF_UA | DF_UB | DF_UC | DF_NULL_CHK_1 | DF_RANGE_CHK_2 | DF_CORE_B | DF_CORE_C,
 
     // 51 APUT_SHORT vAA, vBB, vCC
-    DF_UA | DF_UB | DF_UC | DF_NULL_CHK_1 | DF_RANGE_CHK_2 | DF_IS_SETTER | DF_CORE_B | DF_CORE_C,
+    DF_UA | DF_UB | DF_UC | DF_NULL_CHK_1 | DF_RANGE_CHK_2 | DF_CORE_B | DF_CORE_C,
 
     // 52 IGET vA, vB, field@CCCC
-    DF_DA | DF_UB | DF_NULL_CHK_0 | DF_IS_GETTER | DF_CORE_B,
+    DF_DA | DF_UB | DF_NULL_CHK_0 | DF_CORE_B,
 
     // 53 IGET_WIDE vA, vB, field@CCCC
-    DF_DA_WIDE | DF_UB | DF_NULL_CHK_0 | DF_IS_GETTER | DF_CORE_B,
+    DF_DA_WIDE | DF_UB | DF_NULL_CHK_0 | DF_CORE_B,
 
     // 54 IGET_OBJECT vA, vB, field@CCCC
-    DF_DA | DF_UB | DF_NULL_CHK_0 | DF_IS_GETTER | DF_CORE_B,
+    DF_DA | DF_UB | DF_NULL_CHK_0 | DF_CORE_B,
 
     // 55 IGET_BOOLEAN vA, vB, field@CCCC
-    DF_DA | DF_UB | DF_NULL_CHK_0 | DF_IS_GETTER | DF_CORE_B,
+    DF_DA | DF_UB | DF_NULL_CHK_0 | DF_CORE_B,
 
     // 56 IGET_BYTE vA, vB, field@CCCC
-    DF_DA | DF_UB | DF_NULL_CHK_0 | DF_IS_GETTER | DF_CORE_B,
+    DF_DA | DF_UB | DF_NULL_CHK_0 | DF_CORE_B,
 
     // 57 IGET_CHAR vA, vB, field@CCCC
-    DF_DA | DF_UB | DF_NULL_CHK_0 | DF_IS_GETTER | DF_CORE_B,
+    DF_DA | DF_UB | DF_NULL_CHK_0 | DF_CORE_B,
 
     // 58 IGET_SHORT vA, vB, field@CCCC
-    DF_DA | DF_UB | DF_NULL_CHK_0 | DF_IS_GETTER | DF_CORE_B,
+    DF_DA | DF_UB | DF_NULL_CHK_0 | DF_CORE_B,
 
     // 59 IPUT vA, vB, field@CCCC
-    DF_UA | DF_UB | DF_NULL_CHK_1 | DF_IS_SETTER | DF_CORE_B,
+    DF_UA | DF_UB | DF_NULL_CHK_1 | DF_CORE_B,
 
     // 5A IPUT_WIDE vA, vB, field@CCCC
-    DF_UA_WIDE | DF_UB | DF_NULL_CHK_2 | DF_IS_SETTER | DF_CORE_B,
+    DF_UA_WIDE | DF_UB | DF_NULL_CHK_2 | DF_CORE_B,
 
     // 5B IPUT_OBJECT vA, vB, field@CCCC
-    DF_UA | DF_UB | DF_NULL_CHK_1 | DF_IS_SETTER | DF_CORE_B,
+    DF_UA | DF_UB | DF_NULL_CHK_1 | DF_CORE_B,
 
     // 5C IPUT_BOOLEAN vA, vB, field@CCCC
-    DF_UA | DF_UB | DF_NULL_CHK_1 | DF_IS_SETTER | DF_CORE_B,
+    DF_UA | DF_UB | DF_NULL_CHK_1 | DF_CORE_B,
 
     // 5D IPUT_BYTE vA, vB, field@CCCC
-    DF_UA | DF_UB | DF_NULL_CHK_1 | DF_IS_SETTER | DF_CORE_B,
+    DF_UA | DF_UB | DF_NULL_CHK_1 | DF_CORE_B,
 
     // 5E IPUT_CHAR vA, vB, field@CCCC
-    DF_UA | DF_UB | DF_NULL_CHK_1 | DF_IS_SETTER | DF_CORE_B,
+    DF_UA | DF_UB | DF_NULL_CHK_1 | DF_CORE_B,
 
     // 5F IPUT_SHORT vA, vB, field@CCCC
-    DF_UA | DF_UB | DF_NULL_CHK_1 | DF_IS_SETTER | DF_CORE_B,
+    DF_UA | DF_UB | DF_NULL_CHK_1 | DF_CORE_B,
 
     // 60 SGET vAA, field@BBBB
-    DF_DA | DF_IS_GETTER,
+    DF_DA | DF_UMS,
 
     // 61 SGET_WIDE vAA, field@BBBB
-    DF_DA_WIDE | DF_IS_GETTER,
+    DF_DA_WIDE | DF_UMS,
 
     // 62 SGET_OBJECT vAA, field@BBBB
-    DF_DA | DF_IS_GETTER | DF_CORE_A,
+    DF_DA | DF_CORE_A | DF_UMS,
 
     // 63 SGET_BOOLEAN vAA, field@BBBB
-    DF_DA | DF_IS_GETTER,
+    DF_DA | DF_UMS,
 
     // 64 SGET_BYTE vAA, field@BBBB
-    DF_DA | DF_IS_GETTER,
+    DF_DA | DF_UMS,
 
     // 65 SGET_CHAR vAA, field@BBBB
-    DF_DA | DF_IS_GETTER,
+    DF_DA | DF_UMS,
 
     // 66 SGET_SHORT vAA, field@BBBB
-    DF_DA | DF_IS_GETTER,
+    DF_DA | DF_UMS,
 
     // 67 SPUT vAA, field@BBBB
-    DF_UA | DF_IS_SETTER,
+    DF_UA | DF_UMS,
 
     // 68 SPUT_WIDE vAA, field@BBBB
-    DF_UA_WIDE | DF_IS_SETTER,
+    DF_UA_WIDE | DF_UMS,
 
     // 69 SPUT_OBJECT vAA, field@BBBB
-    DF_UA | DF_IS_SETTER | DF_CORE_A,
+    DF_UA | DF_CORE_A | DF_UMS,
 
     // 6A SPUT_BOOLEAN vAA, field@BBBB
-    DF_UA | DF_IS_SETTER,
+    DF_UA | DF_UMS,
 
     // 6B SPUT_BYTE vAA, field@BBBB
-    DF_UA | DF_IS_SETTER,
+    DF_UA | DF_UMS,
 
     // 6C SPUT_CHAR vAA, field@BBBB
-    DF_UA | DF_IS_SETTER,
+    DF_UA | DF_UMS,
 
     // 6D SPUT_SHORT vAA, field@BBBB
-    DF_UA | DF_IS_SETTER,
+    DF_UA | DF_UMS,
 
     // 6E INVOKE_VIRTUAL {vD, vE, vF, vG, vA}
-    DF_FORMAT_35C | DF_NULL_CHK_OUT0,
+    DF_FORMAT_35C | DF_NULL_CHK_OUT0 | DF_UMS,
 
     // 6F INVOKE_SUPER {vD, vE, vF, vG, vA}
-    DF_FORMAT_35C | DF_NULL_CHK_OUT0,
+    DF_FORMAT_35C | DF_NULL_CHK_OUT0 | DF_UMS,
 
     // 70 INVOKE_DIRECT {vD, vE, vF, vG, vA}
-    DF_FORMAT_35C | DF_NULL_CHK_OUT0,
+    DF_FORMAT_35C | DF_NULL_CHK_OUT0 | DF_UMS,
 
     // 71 INVOKE_STATIC {vD, vE, vF, vG, vA}
-    DF_FORMAT_35C,
+    DF_FORMAT_35C | DF_UMS,
 
     // 72 INVOKE_INTERFACE {vD, vE, vF, vG, vA}
-    DF_FORMAT_35C,
+    DF_FORMAT_35C | DF_UMS,
 
     // 73 UNUSED_73
     DF_NOP,
 
     // 74 INVOKE_VIRTUAL_RANGE {vCCCC .. vNNNN}
-    DF_FORMAT_3RC | DF_NULL_CHK_OUT0,
+    DF_FORMAT_3RC | DF_NULL_CHK_OUT0 | DF_UMS,
 
     // 75 INVOKE_SUPER_RANGE {vCCCC .. vNNNN}
-    DF_FORMAT_3RC | DF_NULL_CHK_OUT0,
+    DF_FORMAT_3RC | DF_NULL_CHK_OUT0 | DF_UMS,
 
     // 76 INVOKE_DIRECT_RANGE {vCCCC .. vNNNN}
-    DF_FORMAT_3RC | DF_NULL_CHK_OUT0,
+    DF_FORMAT_3RC | DF_NULL_CHK_OUT0 | DF_UMS,
 
     // 77 INVOKE_STATIC_RANGE {vCCCC .. vNNNN}
-    DF_FORMAT_3RC,
+    DF_FORMAT_3RC | DF_UMS,
 
     // 78 INVOKE_INTERFACE_RANGE {vCCCC .. vNNNN}
-    DF_FORMAT_3RC,
+    DF_FORMAT_3RC | DF_UMS,
 
     // 79 UNUSED_79
     DF_NOP,
@@ -718,10 +718,10 @@
     DF_UA | DF_UB | DF_NULL_CHK_1 | DF_CORE_B,
 
     // E5 SGET_VOLATILE
-    DF_DA,
+    DF_DA | DF_UMS,
 
     // E6 SPUT_VOLATILE
-    DF_UA,
+    DF_UA | DF_UMS,
 
     // E7 IGET_OBJECT_VOLATILE
     DF_DA | DF_UB | DF_NULL_CHK_0 | DF_CORE_A | DF_CORE_B,
@@ -733,16 +733,16 @@
     DF_UA_WIDE | DF_UB | DF_NULL_CHK_2 | DF_CORE_B,
 
     // EA SGET_WIDE_VOLATILE
-    DF_DA_WIDE,
+    DF_DA_WIDE | DF_UMS,
 
     // EB SPUT_WIDE_VOLATILE
-    DF_UA_WIDE,
+    DF_UA_WIDE | DF_UMS,
 
     // EC BREAKPOINT
     DF_NOP,
 
     // ED THROW_VERIFICATION_ERROR
-    DF_NOP,
+    DF_NOP | DF_UMS,
 
     // EE EXECUTE_INLINE
     DF_FORMAT_35C,
@@ -757,43 +757,43 @@
     DF_NOP,
 
     // F2 IGET_QUICK
-    DF_DA | DF_UB | DF_NULL_CHK_0 | DF_IS_GETTER,
+    DF_DA | DF_UB | DF_NULL_CHK_0,
 
     // F3 IGET_WIDE_QUICK
-    DF_DA_WIDE | DF_UB | DF_NULL_CHK_0 | DF_IS_GETTER,
+    DF_DA_WIDE | DF_UB | DF_NULL_CHK_0,
 
     // F4 IGET_OBJECT_QUICK
-    DF_DA | DF_UB | DF_NULL_CHK_0 | DF_IS_GETTER,
+    DF_DA | DF_UB | DF_NULL_CHK_0,
 
     // F5 IPUT_QUICK
-    DF_UA | DF_UB | DF_NULL_CHK_1 | DF_IS_SETTER,
+    DF_UA | DF_UB | DF_NULL_CHK_1,
 
     // F6 IPUT_WIDE_QUICK
-    DF_UA_WIDE | DF_UB | DF_NULL_CHK_2 |DF_IS_SETTER,
+    DF_UA_WIDE | DF_UB | DF_NULL_CHK_2,
 
     // F7 IPUT_OBJECT_QUICK
-    DF_UA | DF_UB | DF_NULL_CHK_1 | DF_IS_SETTER,
+    DF_UA | DF_UB | DF_NULL_CHK_1,
 
     // F8 INVOKE_VIRTUAL_QUICK
-    DF_FORMAT_35C | DF_NULL_CHK_OUT0,
+    DF_FORMAT_35C | DF_NULL_CHK_OUT0 | DF_UMS,
 
     // F9 INVOKE_VIRTUAL_QUICK_RANGE
-    DF_FORMAT_3RC | DF_NULL_CHK_OUT0,
+    DF_FORMAT_3RC | DF_NULL_CHK_OUT0 | DF_UMS,
 
     // FA INVOKE_SUPER_QUICK
-    DF_FORMAT_35C | DF_NULL_CHK_OUT0,
+    DF_FORMAT_35C | DF_NULL_CHK_OUT0 | DF_UMS,
 
     // FB INVOKE_SUPER_QUICK_RANGE
-    DF_FORMAT_3RC | DF_NULL_CHK_OUT0,
+    DF_FORMAT_3RC | DF_NULL_CHK_OUT0 | DF_UMS,
 
     // FC IPUT_OBJECT_VOLATILE
     DF_UA | DF_UB | DF_NULL_CHK_1 | DF_CORE_A | DF_CORE_B,
 
     // FD SGET_OBJECT_VOLATILE
-    DF_DA | DF_CORE_A,
+    DF_DA | DF_CORE_A | DF_UMS,
 
     // FE SPUT_OBJECT_VOLATILE
-    DF_UA | DF_CORE_A,
+    DF_UA | DF_CORE_A | DF_UMS,
 
     // FF UNUSED_FF
     DF_NOP,
@@ -1655,38 +1655,6 @@
     return mir;
 }
 
-/*
- * For the rest of the extended run, replace uses of rOld with rNew.
- */
-void replaceOperands(CompilationUnit* cUnit, BasicBlock** pBp, MIR* mir,
-                     int rOld, int rNew)
-{
-    while (true) {
-       mir = advanceMIR(cUnit, pBp, mir, NULL, false);
-       if (mir == NULL) {
-           break;
-       }
-       if (mir->ssaRep == NULL) {
-           continue;
-       }
-       if (mir->optimizationFlags & MIR_MARK) {
-           LOG(INFO) << "recursive replace";
-           mir->dalvikInsn.opcode = (Instruction::Code)kMirOpCopy;
-           mir->ssaRep->uses[0] = rNew;
-           mir->ssaRep->numUses = 1;
-           replaceOperands(cUnit, pBp, mir, mir->ssaRep->defs[0], rNew);
-           mir->optimizationFlags &= ~MIR_MARK;
-       } else {
-           for (int i = 0; i < mir->ssaRep->numUses; i++) {
-               if (mir->ssaRep->uses[i] == rOld) {
-                   mir->optimizationFlags |= MIR_IGNORE_NULL_CHECK;
-                   mir->ssaRep->uses[i] = rNew;
-               }
-           }
-       }
-    }
-}
-
 void squashDupRangeChecks(CompilationUnit* cUnit, BasicBlock** pBp, MIR* mir,
                           int arraySreg, int indexSreg)
 {
@@ -1825,66 +1793,6 @@
                     squashDupRangeChecks(cUnit, &tbb, mir, arrSreg, idxSreg);
                 }
                 break;
-#if 0
-            // Probably not worthwhile.
-            case Instruction::IGET_OBJECT: {
-                // TODO: look for CSE
-                    if (mir->optimizationFlags & MIR_DUP) {
-                        break;
-                    }
-                    ArenaBitVector* tempBlockV = cUnit->tempBlockV;
-                    oatClearAllBits(tempBlockV);
-                    oatSetBit(cUnit, tempBlockV, bb->id);
-                    int objSreg = mir->ssaRep->uses[0];
-                    int dstSreg = mir->ssaRep->defs[0];
-                    uint32_t fieldIdx = mir->dalvikInsn.vC;
-                    int matches = 0;
-                    BasicBlock* tbb = bb;
-                    MIR* tm = mir;
-                    while (true) {
-                        tm = advanceMIR(cUnit, &tbb, tm, tempBlockV, true);
-                        if ((tm == NULL) || (tm == mir)) {
-                            break;
-                        }
-                        Instruction::Code opcode = tm->dalvikInsn.opcode;
-                        if ((opcode == Instruction::IGET_OBJECT)
-                            && (tm->ssaRep->uses[0] == objSreg)
-                            && (tm->dalvikInsn.vC == fieldIdx)) {
-                            if (cUnit->printMe) {
-                                LOG(INFO) << "Got DUP IGET_OBJECT @ 0x"
-                                          << std::hex << tm->offset
-                                          << ", from 0x" << std::hex
-                                          << mir->offset;
-                            }
-                            tm->optimizationFlags |= MIR_MARK;
-                            matches++;
-                        } else if ((opcode == Instruction::IPUT_OBJECT)
-                            && (tm->ssaRep->uses[0] == objSreg)
-                            && (tm->dalvikInsn.vC == fieldIdx)) {
-                            if (cUnit->printMe) {
-                                LOG(INFO) << "Clobbered IGET_OBJECT @ 0x"
-                                          << std::hex << tm->offset;
-                            }
-                            break;
-                        }
-                    }
-                    if (matches >= 2) {
-                        // Allocate compiler temp, redirect 1st load to temp,
-                        // insert copy to real target. Convert all dups to
-                        // copies and rename all uses.
-                        int tmpSreg = allocCompilerTempSreg(cUnit, tempBlockV);
-                        MIR* newMir = rawMIR(cUnit, (Instruction::Code)kMirOpCopy, 1, 1);
-                        newMir->ssaRep->defs[0] = dstSreg;
-                        newMir->ssaRep->uses[0] = tmpSreg;
-                        mir->ssaRep->defs[0] = tmpSreg;
-                        mir->optimizationFlags &= ~MIR_MARK;
-                        oatInsertMIRAfter(bb, mir, newMir);
-                        BasicBlock* tbb = bb;
-                        replaceOperands(cUnit, &tbb, mir, dstSreg, tmpSreg);
-                    }
-                }
-                break;
-#endif
             case Instruction::CMPL_FLOAT:
             case Instruction::CMPL_DOUBLE:
             case Instruction::CMPG_FLOAT:
@@ -2224,6 +2132,58 @@
 }
 
 /*
+ * This function will make a best guess at whether the invoke will
+ * end up using Method*.  It isn't critical to get it exactly right,
+ * and attempting to do would involve more complexity than it's
+ * worth.
+ */
+bool invokeUsesMethodStar(CompilationUnit* cUnit, MIR* mir)
+{
+    InvokeType type;
+    Instruction::Code opcode = mir->dalvikInsn.opcode;
+    switch(opcode) {
+        case Instruction::INVOKE_STATIC:
+        case Instruction::INVOKE_STATIC_RANGE:
+            type = kStatic;
+            break;
+        case Instruction::INVOKE_DIRECT:
+        case Instruction::INVOKE_DIRECT_RANGE:
+            type = kDirect;
+            break;
+        case Instruction::INVOKE_VIRTUAL:
+        case Instruction::INVOKE_VIRTUAL_RANGE:
+            type = kVirtual;
+            break;
+        case Instruction::INVOKE_INTERFACE:
+        case Instruction::INVOKE_INTERFACE_RANGE:
+            return false;
+        case Instruction::INVOKE_SUPER_RANGE:
+        case Instruction::INVOKE_SUPER:
+            type = kSuper;
+            break;
+        default:
+            LOG(WARNING) << "Unexpected invoke op: " << (int)opcode;
+            return false;
+    }
+    OatCompilationUnit mUnit(cUnit->class_loader, cUnit->class_linker,
+                             *cUnit->dex_file, *cUnit->dex_cache,
+                             cUnit->code_item, cUnit->method_idx,
+                             cUnit->access_flags);
+    // TODO: add a flag so we don't counts the stats for this twice
+    uint32_t dexMethodIdx = mir->dalvikInsn.vB;
+    int vtableIdx;
+    uintptr_t directCode;
+    uintptr_t directMethod;
+    bool fastPath =
+        cUnit->compiler->ComputeInvokeInfo(dexMethodIdx, &mUnit, type,
+                                           vtableIdx, directCode,
+                                           directMethod) &&
+        !SLOW_INVOKE_PATH;
+    return (((type == kDirect) || (type == kStatic)) &&
+            fastPath && ((directCode == 0) || (directMethod == 0)));
+}
+
+/*
  * Count uses, weighting by loop nesting depth.  This code only
  * counts explicitly used sRegs.  A later phase will add implicit
  * counts for things such as Method*, null-checked references, etc.
@@ -2237,12 +2197,32 @@
         if (mir->ssaRep == NULL) {
             continue;
         }
+        uint32_t weight = std::min(16U, (uint32_t)bb->nestingDepth);
         for (int i = 0; i < mir->ssaRep->numUses; i++) {
             int sReg = mir->ssaRep->uses[i];
-            uint32_t weight = std::min(16U, (uint32_t)bb->nestingDepth);
             DCHECK_LT(sReg, (int)cUnit->useCounts.numUsed);
             cUnit->useCounts.elemList[sReg] += (1 << weight);
         }
+        if (!(cUnit->disableOpt & (1 << kPromoteCompilerTemps))) {
+            int dfAttributes = oatDataFlowAttributes[mir->dalvikInsn.opcode];
+            // Implicit use of Method* ? */
+            if (dfAttributes & DF_UMS) {
+                /*
+                 * Some invokes will not use Method* - need to perform test similar
+                 * to that found in genInvoke() to decide whether to count refs
+                 * for Method* on invoke-class opcodes.
+                 * TODO: refactor for common test here, save results for genInvoke
+                 */
+                int usesMethodStar = true;
+                if ((dfAttributes & (DF_FORMAT_35C | DF_FORMAT_3RC)) &&
+                    !(dfAttributes & DF_NON_NULL_RET)) {
+                    usesMethodStar &= invokeUsesMethodStar(cUnit, mir);
+                }
+                if (usesMethodStar) {
+                    cUnit->useCounts.elemList[cUnit->methodSReg] += (1 << weight);
+                }
+            }
+        }
     }
     return false;
 }
diff --git a/src/compiler/Dataflow.h b/src/compiler/Dataflow.h
index 77bf756..a51173f 100644
--- a/src/compiler/Dataflow.h
+++ b/src/compiler/Dataflow.h
@@ -47,14 +47,14 @@
     kNullTransferSrcN,     // Phi null check state transfer
     kRangeCheckSrc1,       // Range check of uses[1]
     kRangeCheckSrc2,       // Range check of uses[2]
+    kRangeCheckSrc3,       // Range check of uses[3]
     kFPA,
     kFPB,
     kFPC,
     kCoreA,
     kCoreB,
     kCoreC,
-    kGetter,
-    kSetter,
+    kUsesMethodStar,       // Implicit use of Method*
 };
 
 #define DF_NOP                  0
@@ -82,14 +82,14 @@
 #define DF_NULL_TRANSFER_N      (1 << kNullTransferSrcN)
 #define DF_RANGE_CHK_1          (1 << kRangeCheckSrc1)
 #define DF_RANGE_CHK_2          (1 << kRangeCheckSrc2)
+#define DF_RANGE_CHK_3          (1 << kRangeCheckSrc3)
 #define DF_FP_A                 (1 << kFPA)
 #define DF_FP_B                 (1 << kFPB)
 #define DF_FP_C                 (1 << kFPC)
 #define DF_CORE_A               (1 << kCoreA)
 #define DF_CORE_B               (1 << kCoreB)
 #define DF_CORE_C               (1 << kCoreC)
-#define DF_IS_GETTER            (1 << kGetter)
-#define DF_IS_SETTER            (1 << kSetter)
+#define DF_UMS                  (1 << kUsesMethodStar)
 
 #define DF_HAS_USES             (DF_UA | DF_UB | DF_UC | DF_UA_WIDE | \
                                  DF_UB_WIDE | DF_UC_WIDE)
diff --git a/src/compiler/Frontend.cc b/src/compiler/Frontend.cc
index d97c20f..71435eb 100644
--- a/src/compiler/Frontend.cc
+++ b/src/compiler/Frontend.cc
@@ -35,6 +35,7 @@
      //(1 << kSkipLargeMethodOptimization) |
      //(1 << kSafeOptimizations) |
      //(1 << kBBOpt) |
+     //(1 << kPromoteCompilerTemps) |
      0;
 
 uint32_t compilerDebugFlags = 0 |     // Enable debug/testing modes
diff --git a/src/compiler/Ralloc.cc b/src/compiler/Ralloc.cc
index b170d81..872adae 100644
--- a/src/compiler/Ralloc.cc
+++ b/src/compiler/Ralloc.cc
@@ -323,21 +323,21 @@
 
     /* Patch up the locations for Method* and the compiler temps */
     loc[cUnit->methodSReg].location = kLocCompilerTemp;
+    loc[cUnit->methodSReg].defined = true;
     for (i = 0; i < cUnit->numCompilerTemps; i++) {
         CompilerTemp* ct = (CompilerTemp*)cUnit->compilerTemps.elemList[i];
         loc[ct->sReg].location = kLocCompilerTemp;
+        loc[ct->sReg].defined = true;
     }
 
     cUnit->regLocation = loc;
 
     /* Allocation the promotion map */
     int numRegs = cUnit->numDalvikRegisters;
-    PromotionMap* tMap =
+    cUnit->promotionMap =
         (PromotionMap*)oatNew(cUnit, (numRegs + cUnit->numCompilerTemps + 1) *
                               sizeof(cUnit->promotionMap[0]), true,
                               kAllocRegAlloc);
-    // Bias the promotion map
-    cUnit->promotionMap = &tMap[cUnit->numCompilerTemps + 1];
 
     /* Add types of incoming arguments based on signature */
     int numIns = cUnit->numIns;
diff --git a/src/compiler/codegen/CodegenFactory.cc b/src/compiler/codegen/CodegenFactory.cc
index 5f525a7..e1df1a5 100644
--- a/src/compiler/codegen/CodegenFactory.cc
+++ b/src/compiler/codegen/CodegenFactory.cc
@@ -302,5 +302,10 @@
     return loadValue(cUnit, cUnit->regLocation[cUnit->methodSReg], kCoreReg);
 }
 
+bool methodStarInReg(CompilationUnit* cUnit)
+{
+     return (cUnit->regLocation[cUnit->methodSReg].location == kLocPhysReg);
+}
+
 
 }  // namespace art
diff --git a/src/compiler/codegen/CodegenUtil.cc b/src/compiler/codegen/CodegenUtil.cc
index 8b324ed..d4b8eea 100644
--- a/src/compiler/codegen/CodegenUtil.cc
+++ b/src/compiler/codegen/CodegenUtil.cc
@@ -326,18 +326,29 @@
     }
 }
 
+#define BSZ 100
 void oatDumpPromotionMap(CompilationUnit *cUnit)
 {
-    for (int i = 0; i < cUnit->numDalvikRegisters; i++) {
+    int numRegs = cUnit->numDalvikRegisters + cUnit->numCompilerTemps + 1;
+    for (int i = 0; i < numRegs; i++) {
         PromotionMap vRegMap = cUnit->promotionMap[i];
-        char buf[100];
+        char buf[BSZ];
         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,
+        char buf2[BSZ];
+        char buf3[BSZ];
+        if (i < cUnit->numDalvikRegisters) {
+            snprintf(buf3, BSZ, "%02d", i);
+        } else if (i == cUnit->methodSReg) {
+            strncpy(buf3, "Method*", BSZ);
+        } else {
+            snprintf(buf3, BSZ, "ct%d", i - cUnit->numDalvikRegisters);
+        }
+
+        snprintf(buf2, BSZ, "V[%s] -> %s%d%s", buf3,
                  vRegMap.coreLocation == kLocPhysReg ?
                  "r" : "SP+", vRegMap.coreLocation == kLocPhysReg ?
                  vRegMap.coreReg : oatSRegOffset(cUnit, i), buf);
@@ -345,17 +356,6 @@
     }
 }
 
-void oatDumpFullPromotionMap(CompilationUnit *cUnit)
-{
-    for (int i = 0; i < cUnit->numDalvikRegisters; 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)
 {
diff --git a/src/compiler/codegen/CompilerCodegen.h b/src/compiler/codegen/CompilerCodegen.h
index 571d6da..1137db3 100644
--- a/src/compiler/codegen/CompilerCodegen.h
+++ b/src/compiler/codegen/CompilerCodegen.h
@@ -39,7 +39,6 @@
 /* Implemented in the codegen/<target>/ArchUtility.c */
 void oatCodegenDump(CompilationUnit* cUnit);
 void oatDumpPromotionMap(CompilationUnit* cUnit);
-void oatDumpFullPromotionMap(CompilationUnit* cUnit);
 std::string buildInsnString(const char* fmt, LIR* lir,
                             unsigned char* baseAddr);
 
diff --git a/src/compiler/codegen/GenInvoke.cc b/src/compiler/codegen/GenInvoke.cc
index 90e2267..c2023ff 100644
--- a/src/compiler/codegen/GenInvoke.cc
+++ b/src/compiler/codegen/GenInvoke.cc
@@ -33,6 +33,23 @@
  */
 void flushIns(CompilationUnit* cUnit)
 {
+    /*
+     * Dummy up a RegLocation for the incoming Method*
+     * It will attempt to keep rARG0 live (or copy it to home location
+     * if promoted).
+     */
+    RegLocation rlSrc = cUnit->regLocation[cUnit->methodSReg];
+    RegLocation rlMethod = cUnit->regLocation[cUnit->methodSReg];
+    rlSrc.location = kLocPhysReg;
+    rlSrc.lowReg = rARG0;
+    rlSrc.home = false;
+    oatMarkLive(cUnit, rlSrc.lowReg, rlSrc.sRegLow);
+    storeValue(cUnit, rlMethod, rlSrc);
+    // If Method* has been promoted, explicitly flush
+    if (rlMethod.location == kLocPhysReg) {
+        storeWordDisp(cUnit, rSP, 0, rARG0);
+    }
+
     if (cUnit->numIns == 0)
         return;
     int firstArgReg = rARG1;
@@ -161,6 +178,7 @@
     } else {
         switch(state) {
         case 0:  // Get the current Method* [sets rARG0]
+            // TUNING: we can save a reg copy if Method* has been promoted
             loadCurrMethodDirect(cUnit, rARG0);
             break;
         case 1:  // Get method->dex_cache_resolved_methods_
@@ -537,8 +555,6 @@
     opRegRegImm(cUnit, kOpAdd, rARG1, rSP, startOffset);
     callRuntimeHelperRegRegImm(cUnit, OFFSETOF_MEMBER(Thread, pMemcpy),
                                rARG0, rARG1, (numArgs - 3) * 4);
-    // Restore Method*
-    loadCurrMethodDirect(cUnit, rARG0);
 #else
     if (numArgs >= 20) {
         // Generate memcpy
@@ -546,8 +562,6 @@
         opRegRegImm(cUnit, kOpAdd, rARG1, rSP, startOffset);
         callRuntimeHelperRegRegImm(cUnit, OFFSETOF_MEMBER(Thread, pMemcpy),
                                    rARG0, rARG1, (numArgs - 3) * 4);
-        // Restore Method*
-        loadCurrMethodDirect(cUnit, rARG0);
     } else {
         // Use vldm/vstm pair using rARG3 as a temp
         int regsLeft = std::min(numArgs - 3, 16);
diff --git a/src/compiler/codegen/Ralloc.h b/src/compiler/codegen/Ralloc.h
index aa5439a..2169082 100644
--- a/src/compiler/codegen/Ralloc.h
+++ b/src/compiler/codegen/Ralloc.h
@@ -233,7 +233,7 @@
 extern bool oatIsFPReg(int reg);
 extern uint32_t oatFPRegMask(void);
 extern void oatAdjustSpillMask(CompilationUnit* cUnit);
-void oatMarkPreservedSingle(CompilationUnit* cUnit, int sReg, int reg);
+void oatMarkPreservedSingle(CompilationUnit* cUnit, int vReg, int reg);
 void oatRegCopy(CompilationUnit* cUnit, int rDest, int rSrc);
 
 }  // namespace art
diff --git a/src/compiler/codegen/RallocUtil.cc b/src/compiler/codegen/RallocUtil.cc
index c08b2e8..ffff7d2 100644
--- a/src/compiler/codegen/RallocUtil.cc
+++ b/src/compiler/codegen/RallocUtil.cc
@@ -153,17 +153,28 @@
                     sReg);
 }
 
-/* Sanity check */
-bool validSreg(CompilationUnit* cUnit, int sReg)
+/*
+ * SSA names associated with the initial definitions of Dalvik
+ * registers are the same as the Dalvik register number (and
+ * thus take the same position in the promotionMap.  However,
+ * the special Method* and compiler temp resisters use negative
+ * vReg numbers to distinquish them and can have an arbitrary
+ * ssa name (above the last original Dalvik register).  This function
+ * maps SSA names to positions in the promotionMap array.
+ */
+int SRegToPMap(CompilationUnit* cUnit, int sReg)
 {
-    bool res = ((-(cUnit->numCompilerTemps + 1) <= sReg) &&
-                (sReg < cUnit->numDalvikRegisters));
-    if (!res) {
-        LOG(WARNING) << "Bad sreg: " << sReg;
-        LOG(WARNING) << "  low = " << -(cUnit->numCompilerTemps + 1);
-        LOG(WARNING) << "  high = " << cUnit->numRegs;
+    DCHECK_LT(sReg, cUnit->numSSARegs);
+    DCHECK_GE(sReg, 0);
+    int vReg = SRegToVReg(cUnit, sReg);
+    if (vReg >= 0) {
+        DCHECK_LT(vReg, cUnit->numDalvikRegisters);
+        return vReg;
+    } else {
+        int pos = std::abs(vReg) - std::abs(SSA_METHOD_BASEREG);
+        DCHECK_LE(pos, cUnit->numCompilerTemps);
+        return cUnit->numDalvikRegisters + pos;
     }
-    return res;
 }
 
 /* Reserve a callee-save register.  Return -1 if none available */
@@ -173,16 +184,15 @@
     RegisterInfo* coreRegs = cUnit->regPool->coreRegs;
     for (int i = 0; i < cUnit->regPool->numCoreRegs; i++) {
         if (!coreRegs[i].isTemp && !coreRegs[i].inUse) {
+            int vReg = SRegToVReg(cUnit, sReg);
+            int pMapIdx = SRegToPMap(cUnit, sReg);
             res = coreRegs[i].reg;
             coreRegs[i].inUse = true;
             cUnit->coreSpillMask |= (1 << res);
-            cUnit->coreVmapTable.push_back(sReg);
+            cUnit->coreVmapTable.push_back(vReg);
             cUnit->numCoreSpills++;
-            //  Should be promoting based on initial sReg set
-            DCHECK_EQ(sReg, SRegToVReg(cUnit, sReg));
-            DCHECK(validSreg(cUnit,sReg));
-            cUnit->promotionMap[sReg].coreLocation = kLocPhysReg;
-            cUnit->promotionMap[sReg].coreReg = res;
+            cUnit->promotionMap[pMapIdx].coreLocation = kLocPhysReg;
+            cUnit->promotionMap[pMapIdx].coreReg = res;
             break;
         }
     }
@@ -201,14 +211,13 @@
     for (int i = 0; i < cUnit->regPool->numFPRegs; i++) {
         if (!FPRegs[i].isTemp && !FPRegs[i].inUse &&
             ((FPRegs[i].reg & 0x1) == 0) == even) {
+            int vReg = SRegToVReg(cUnit, sReg);
+            int pMapIdx = SRegToPMap(cUnit, sReg);
             res = FPRegs[i].reg;
             FPRegs[i].inUse = true;
-            //  Should be promoting based on initial sReg set
-            DCHECK_EQ(sReg, SRegToVReg(cUnit, sReg));
-            oatMarkPreservedSingle(cUnit, sReg, res);
-            DCHECK(validSreg(cUnit,sReg));
-            cUnit->promotionMap[sReg].fpLocation = kLocPhysReg;
-            cUnit->promotionMap[sReg].fpReg = res;
+            oatMarkPreservedSingle(cUnit, vReg, res);
+            cUnit->promotionMap[pMapIdx].fpLocation = kLocPhysReg;
+            cUnit->promotionMap[pMapIdx].fpReg = res;
             break;
         }
     }
@@ -226,12 +235,11 @@
 int allocPreservedDouble(CompilationUnit* cUnit, int sReg)
 {
     int res = -1; // Assume failure
-    //  Should be promoting based on initial sReg set
-    DCHECK_EQ(sReg, SRegToVReg(cUnit, sReg));
-    DCHECK(validSreg(cUnit,sReg+1));
-    if (cUnit->promotionMap[sReg+1].fpLocation == kLocPhysReg) {
+    int vReg = SRegToVReg(cUnit, sReg);
+    int pMapIdx = SRegToPMap(cUnit, sReg);
+    if (cUnit->promotionMap[pMapIdx+1].fpLocation == kLocPhysReg) {
         // Upper reg is already allocated.  Can we fit?
-        int highReg = cUnit->promotionMap[sReg+1].fpReg;
+        int highReg = cUnit->promotionMap[pMapIdx+1].fpReg;
         if ((highReg & 1) == 0) {
             // High reg is even - fail.
             return res;
@@ -246,7 +254,7 @@
         res = p->reg;
         p->inUse = true;
         DCHECK_EQ((res & 1), 0);
-        oatMarkPreservedSingle(cUnit, sReg, res);
+        oatMarkPreservedSingle(cUnit, vReg, res);
     } else {
         RegisterInfo* FPRegs = cUnit->regPool->FPRegs;
         for (int i = 0; i < cUnit->regPool->numFPRegs; i++) {
@@ -257,21 +265,19 @@
                 (FPRegs[i].reg + 1) == FPRegs[i+1].reg) {
                 res = FPRegs[i].reg;
                 FPRegs[i].inUse = true;
-                oatMarkPreservedSingle(cUnit, sReg, res);
+                oatMarkPreservedSingle(cUnit, vReg, res);
                 FPRegs[i+1].inUse = true;
                 DCHECK_EQ(res + 1, FPRegs[i+1].reg);
-                oatMarkPreservedSingle(cUnit, sReg+1, res+1);
+                oatMarkPreservedSingle(cUnit, vReg+1, res+1);
                 break;
             }
         }
     }
     if (res != -1) {
-        DCHECK(validSreg(cUnit,sReg));
-        cUnit->promotionMap[sReg].fpLocation = kLocPhysReg;
-        cUnit->promotionMap[sReg].fpReg = res;
-        DCHECK(validSreg(cUnit,sReg+1));
-        cUnit->promotionMap[sReg+1].fpLocation = kLocPhysReg;
-        cUnit->promotionMap[sReg+1].fpReg = res + 1;
+        cUnit->promotionMap[pMapIdx].fpLocation = kLocPhysReg;
+        cUnit->promotionMap[pMapIdx].fpReg = res;
+        cUnit->promotionMap[pMapIdx+1].fpLocation = kLocPhysReg;
+        cUnit->promotionMap[pMapIdx+1].fpReg = res + 1;
     }
     return res;
 }
@@ -1051,18 +1057,15 @@
     for (int i = 0; i < cUnit->numSSARegs;) {
         RegLocation loc = cUnit->regLocation[i];
         RefCounts* counts = loc.fp ? fpCounts : coreCounts;
-        int vReg = SRegToVReg(cUnit, loc.sRegLow);
-        if (vReg < 0) {
-            vReg = cUnit->numDalvikRegisters - (vReg + 1);
-        }
+        int pMapIdx = SRegToPMap(cUnit, loc.sRegLow);
         if (loc.defined) {
-            counts[vReg].count += cUnit->useCounts.elemList[i];
+            counts[pMapIdx].count += cUnit->useCounts.elemList[i];
         }
         if (loc.wide) {
             if (loc.defined) {
                 if (loc.fp) {
-                    counts[vReg].doubleStart = true;
-                counts[vReg+1].count += cUnit->useCounts.elemList[i+1];
+                    counts[pMapIdx].doubleStart = true;
+                counts[pMapIdx+1].count += cUnit->useCounts.elemList[i+1];
                 }
             }
             i += 2;
@@ -1120,10 +1123,16 @@
     for (int i = 0; i < dalvikRegs; i++) {
         coreRegs[i].sReg = fpRegs[i].sReg = i;
     }
-    // Set ssa names for Method* and compiler temps
-    for (int i = 0; i < regBias; i++) {
-        coreRegs[dalvikRegs + i].sReg = fpRegs[dalvikRegs + i].sReg = (-1 - i);
+    // Set ssa name for Method*
+    coreRegs[dalvikRegs].sReg = cUnit->methodSReg;
+    fpRegs[dalvikRegs].sReg = cUnit->methodSReg;  // For consistecy
+    // Set ssa names for compilerTemps
+    for (int i = 1; i <= cUnit->numCompilerTemps; i++) {
+        CompilerTemp* ct = (CompilerTemp*)cUnit->compilerTemps.elemList[i];
+        coreRegs[dalvikRegs + i].sReg = ct->sReg;
+        fpRegs[dalvikRegs + i].sReg = ct->sReg;
     }
+
     GrowableListIterator iterator;
     oatGrowableListIteratorInit(&cUnit->blockList, &iterator);
     while (true) {
@@ -1156,8 +1165,8 @@
     if (!(cUnit->disableOpt & (1 << kPromoteRegs))) {
         // Promote fpRegs
         for (int i = 0; (i < numRegs) && (fpRegs[i].count > 0); i++) {
-            DCHECK(validSreg(cUnit,fpRegs[i].sReg));
-            if (cUnit->promotionMap[fpRegs[i].sReg].fpLocation != kLocPhysReg) {
+            int pMapIdx = SRegToPMap(cUnit, fpRegs[i].sReg);
+            if (cUnit->promotionMap[pMapIdx].fpLocation != kLocPhysReg) {
                 int reg = oatAllocPreservedFPReg(cUnit, fpRegs[i].sReg,
                     fpRegs[i].doubleStart);
                 if (reg < 0) {
@@ -1168,8 +1177,8 @@
 
         // Promote core regs
         for (int i = 0; (i < numRegs) && (coreRegs[i].count > 0); i++) {
-            DCHECK(validSreg(cUnit,coreRegs[i].sReg));
-            if (cUnit->promotionMap[coreRegs[i].sReg].coreLocation !=
+            int pMapIdx = SRegToPMap(cUnit, coreRegs[i].sReg);
+            if (cUnit->promotionMap[pMapIdx].coreLocation !=
                     kLocPhysReg) {
                 int reg = oatAllocPreservedCoreReg(cUnit, coreRegs[i].sReg);
                 if (reg < 0) {
@@ -1182,20 +1191,18 @@
     // Now, update SSA names to new home locations
     for (int i = 0; i < cUnit->numSSARegs; i++) {
         RegLocation *curr = &cUnit->regLocation[i];
-        int baseVReg = SRegToVReg(cUnit, curr->sRegLow);
+        int pMapIdx = SRegToPMap(cUnit, curr->sRegLow);
         if (!curr->wide) {
             if (curr->fp) {
-                DCHECK(validSreg(cUnit,baseVReg));
-                if (cUnit->promotionMap[baseVReg].fpLocation == kLocPhysReg) {
+                if (cUnit->promotionMap[pMapIdx].fpLocation == kLocPhysReg) {
                     curr->location = kLocPhysReg;
-                    curr->lowReg = cUnit->promotionMap[baseVReg].fpReg;
+                    curr->lowReg = cUnit->promotionMap[pMapIdx].fpReg;
                     curr->home = true;
                 }
             } else {
-                DCHECK(validSreg(cUnit,baseVReg));
-                if (cUnit->promotionMap[baseVReg].coreLocation == kLocPhysReg) {
+                if (cUnit->promotionMap[pMapIdx].coreLocation == kLocPhysReg) {
                     curr->location = kLocPhysReg;
-                    curr->lowReg = cUnit->promotionMap[baseVReg].coreReg;
+                    curr->lowReg = cUnit->promotionMap[pMapIdx].coreReg;
                     curr->home = true;
                 }
             }
@@ -1205,13 +1212,11 @@
                 continue;
             }
             if (curr->fp) {
-                DCHECK(validSreg(cUnit,baseVReg));
-                DCHECK(validSreg(cUnit,baseVReg+1));
-                if ((cUnit->promotionMap[baseVReg].fpLocation == kLocPhysReg) &&
-                    (cUnit->promotionMap[baseVReg+1].fpLocation ==
+                if ((cUnit->promotionMap[pMapIdx].fpLocation == kLocPhysReg) &&
+                    (cUnit->promotionMap[pMapIdx+1].fpLocation ==
                     kLocPhysReg)) {
-                    int lowReg = cUnit->promotionMap[baseVReg].fpReg;
-                    int highReg = cUnit->promotionMap[baseVReg+1].fpReg;
+                    int lowReg = cUnit->promotionMap[pMapIdx].fpReg;
+                    int highReg = cUnit->promotionMap[pMapIdx+1].fpReg;
                     // Doubles require pair of singles starting at even reg
                     if (((lowReg & 0x1) == 0) && ((lowReg + 1) == highReg)) {
                         curr->location = kLocPhysReg;
@@ -1221,14 +1226,12 @@
                     }
                 }
             } else {
-                DCHECK(validSreg(cUnit,baseVReg));
-                DCHECK(validSreg(cUnit,baseVReg+1));
-                if ((cUnit->promotionMap[baseVReg].coreLocation == kLocPhysReg)
-                     && (cUnit->promotionMap[baseVReg+1].coreLocation ==
+                if ((cUnit->promotionMap[pMapIdx].coreLocation == kLocPhysReg)
+                     && (cUnit->promotionMap[pMapIdx+1].coreLocation ==
                      kLocPhysReg)) {
                     curr->location = kLocPhysReg;
-                    curr->lowReg = cUnit->promotionMap[baseVReg].coreReg;
-                    curr->highReg = cUnit->promotionMap[baseVReg+1].coreReg;
+                    curr->lowReg = cUnit->promotionMap[pMapIdx].coreReg;
+                    curr->highReg = cUnit->promotionMap[pMapIdx+1].coreReg;
                     curr->home = true;
                 }
             }
diff --git a/src/compiler/codegen/arm/ArchFactory.cc b/src/compiler/codegen/arm/ArchFactory.cc
index da5de52..c24b856 100644
--- a/src/compiler/codegen/arm/ArchFactory.cc
+++ b/src/compiler/codegen/arm/ArchFactory.cc
@@ -107,20 +107,6 @@
                  cUnit->frameSize - (spillCount * 4));
     }
 
-    /*
-     * Dummy up a RegLocation for the incoming Method*
-     * It will attempt to keep r0 live (or copy it to home location
-     * if promoted).
-     */
-    RegLocation rlSrc = cUnit->regLocation[cUnit->methodSReg];
-    RegLocation rlMethod = cUnit->regLocation[cUnit->methodSReg];
-    rlSrc.location = kLocPhysReg;
-    rlSrc.lowReg = r0;
-    rlSrc.home = false;
-    oatMarkLive(cUnit, rlSrc.lowReg, rlSrc.sRegLow);
-    storeValue(cUnit, rlMethod, rlSrc);
-
-    /* Flush the rest of the ins */
     flushIns(cUnit);
 
     if (cUnit->genDebugger) {
diff --git a/src/compiler/codegen/arm/ArmRallocUtil.cc b/src/compiler/codegen/arm/ArmRallocUtil.cc
index e7627f2..89bff5e 100644
--- a/src/compiler/codegen/arm/ArmRallocUtil.cc
+++ b/src/compiler/codegen/arm/ArmRallocUtil.cc
@@ -45,7 +45,7 @@
  * include any holes in the mask.  Associate holes with
  * Dalvik register INVALID_VREG (0xFFFFU).
  */
-void oatMarkPreservedSingle(CompilationUnit* cUnit, int sReg, int reg)
+void oatMarkPreservedSingle(CompilationUnit* cUnit, int vReg, int reg)
 {
     DCHECK_GE(reg, FP_REG_MASK + FP_CALLEE_SAVE_BASE);
     reg = (reg & FP_REG_MASK) - FP_CALLEE_SAVE_BASE;
@@ -55,7 +55,7 @@
         cUnit->fpVmapTable.push_back(INVALID_VREG);
     }
     // Add the current mapping
-    cUnit->fpVmapTable[reg] = sReg;
+    cUnit->fpVmapTable[reg] = vReg;
     // Size of fpVmapTable is high-water mark, use to set mask
     cUnit->numFPSpills = cUnit->fpVmapTable.size();
     cUnit->fpSpillMask = ((1 << cUnit->numFPSpills) - 1) << FP_CALLEE_SAVE_BASE;
diff --git a/src/compiler/codegen/mips/ArchFactory.cc b/src/compiler/codegen/mips/ArchFactory.cc
index 9050cf9..b7f055d 100644
--- a/src/compiler/codegen/mips/ArchFactory.cc
+++ b/src/compiler/codegen/mips/ArchFactory.cc
@@ -185,7 +185,7 @@
         opRegImm(cUnit, kOpSub, rSP,
                  cUnit->frameSize - (spillCount * 4));
     }
-    storeBaseDisp(cUnit, rSP, 0, rARG0, kWord);
+
     flushIns(cUnit);
 
     if (cUnit->genDebugger) {
diff --git a/src/compiler/codegen/x86/ArchFactory.cc b/src/compiler/codegen/x86/ArchFactory.cc
index be0c9f4..efa54e0 100644
--- a/src/compiler/codegen/x86/ArchFactory.cc
+++ b/src/compiler/codegen/x86/ArchFactory.cc
@@ -164,8 +164,7 @@
         // Remember branch target - will process later
         oatInsertGrowableList(cUnit, &cUnit->throwLaunchpads, (intptr_t)tgt);
     }
-    /* Spill Method* */
-    storeBaseDisp(cUnit, rSP, 0, rARG0, kWord);
+
     flushIns(cUnit);
 
     if (cUnit->genDebugger) {
diff --git a/src/compiler/codegen/x86/X86RallocUtil.cc b/src/compiler/codegen/x86/X86RallocUtil.cc
index 466faa4..156a2d5 100644
--- a/src/compiler/codegen/x86/X86RallocUtil.cc
+++ b/src/compiler/codegen/x86/X86RallocUtil.cc
@@ -39,7 +39,7 @@
  * include any holes in the mask.  Associate holes with
  * Dalvik register INVALID_VREG (0xFFFFU).
  */
-void oatMarkPreservedSingle(CompilationUnit* cUnit, int sReg, int reg)
+void oatMarkPreservedSingle(CompilationUnit* cUnit, int vReg, int reg)
 {
     UNIMPLEMENTED(WARNING) << "oatMarkPreservedSingle";
 #if 0
diff --git a/src/context.h b/src/context.h
index 478d11e..82e8315 100644
--- a/src/context.h
+++ b/src/context.h
@@ -62,6 +62,18 @@
     return table_[0];
   }
 
+  /*
+   * WARNING: This code should be changed or renamed.  The "reg"
+   * argument is a Dalvik virtual register number, but the way
+   * the vmap and register promotion works a Dalvik vReg can have
+   * neither, one or both of core register and floating point register
+   * identities. The "INVALID_VREG" marker of 0xffff below separates the
+   * core promoted registers from the floating point promoted registers,
+   * and thus terminates the search before reaching the fp section.
+   * This is likely the desired behavior for GC, as references won't
+   * ever be promoted to float registers - but we'll probably want to
+   * rework this shared code to make it useful for the debugger as well.
+   */
   // Is register 'reg' in the context or on the stack?
   bool IsInContext(size_t reg, uint32_t& vmap_offset) const {
     vmap_offset = 0xEBAD0FF5;
diff --git a/src/stack.cc b/src/stack.cc
index 83169fd..83df5ad 100644
--- a/src/stack.cc
+++ b/src/stack.cc
@@ -52,8 +52,8 @@
 /*
  * Return sp-relative offset for a Dalvik virtual register, compiler
  * spill or Method* in bytes using Method*.
- * Note that (reg >= 0) refers to a Dalvik register, (reg == -1)
- * denotes Method* and (reg <= -2) denotes a compiler temp.
+ * Note that (reg >= 0) refers to a Dalvik register, (reg == -2)
+ * denotes Method* and (reg <= -3) denotes a compiler temp.
  *
  *     +------------------------+
  *     | IN[ins-1]              |  {Note: resides in caller's frame}
@@ -96,9 +96,9 @@
   int num_ins = code_item->ins_size_;
   int num_regs = code_item->registers_size_ - num_ins;
   int locals_start = frame_size - ((num_spills + num_regs) * sizeof(uint32_t));
-  if (reg == -1) {
+  if (reg == -2) {
     return 0;  // Method*
-  } else if (reg <= -2) {
+  } else if (reg <= -3) {
     return locals_start - ((reg + 1) * sizeof(uint32_t));  // Compiler temp
   } else if (reg < num_regs) {
     return locals_start + (reg * sizeof(uint32_t));        // Dalvik local reg