[Compiler] Add object ref discovery

Previously, the compiler ran a type inference pass to identify floating
point uses for register allocation.  The grand plan involves moving
all type inference into the Art compiler driver (using the results from
verification).  As a short-term workaround, this CL adds object reference
discovery to the type inference pass.  This is needed for LLVM-IR generation.

Change-Id: I655806264181bfd26ab9340582a02c657cd3f678
diff --git a/src/compiler/Ralloc.cc b/src/compiler/Ralloc.cc
index 54728db..480a96d 100644
--- a/src/compiler/Ralloc.cc
+++ b/src/compiler/Ralloc.cc
@@ -47,6 +47,19 @@
   return change;
 }
 
+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;
+    change = true;
+  }
+  return change;
+}
+
 bool remapNames(CompilationUnit* cUnit, BasicBlock* bb)
 {
   if (bb->blockType != kDalvikByteCode && bb->blockType != kEntryBlock &&
@@ -101,11 +114,14 @@
       int attrs = oatDataFlowAttributes[mir->dalvikInsn.opcode];
 
       // Handle defs
-      if (attrs & (DF_DA | DF_DA_WIDE)) {
+      if (attrs & DF_DA) {
         if (attrs & DF_CORE_A) {
           changed |= setCore(cUnit, ssaRep->defs[0], true);
         }
-        if (attrs & DF_DA_WIDE) {
+        if (attrs & DF_REF_A) {
+          changed |= setRef(cUnit, ssaRep->defs[0], true);
+        }
+        if (attrs & DF_A_WIDE) {
           cUnit->regLocation[ssaRep->defs[0]].wide = true;
           cUnit->regLocation[ssaRep->defs[1]].highWord = true;
           DCHECK_EQ(SRegToVReg(cUnit, ssaRep->defs[0])+1,
@@ -115,11 +131,14 @@
 
       // Handles uses
       int next = 0;
-      if (attrs & (DF_UA | DF_UA_WIDE)) {
+      if (attrs & DF_UA) {
         if (attrs & DF_CORE_A) {
           changed |= setCore(cUnit, ssaRep->uses[next], true);
         }
-        if (attrs & DF_UA_WIDE) {
+        if (attrs & DF_REF_A) {
+          changed |= setRef(cUnit, ssaRep->uses[next], true);
+        }
+        if (attrs & DF_A_WIDE) {
           cUnit->regLocation[ssaRep->uses[next]].wide = true;
           cUnit->regLocation[ssaRep->uses[next + 1]].highWord = true;
           DCHECK_EQ(SRegToVReg(cUnit, ssaRep->uses[next])+1,
@@ -129,11 +148,14 @@
           next++;
         }
       }
-      if (attrs & (DF_UB | DF_UB_WIDE)) {
+      if (attrs & DF_UB) {
         if (attrs & DF_CORE_B) {
           changed |= setCore(cUnit, ssaRep->uses[next], true);
         }
-        if (attrs & DF_UB_WIDE) {
+        if (attrs & DF_REF_B) {
+          changed |= setRef(cUnit, ssaRep->uses[next], true);
+        }
+        if (attrs & DF_B_WIDE) {
           cUnit->regLocation[ssaRep->uses[next]].wide = true;
           cUnit->regLocation[ssaRep->uses[next + 1]].highWord = true;
           DCHECK_EQ(SRegToVReg(cUnit, ssaRep->uses[next])+1,
@@ -143,11 +165,14 @@
           next++;
         }
       }
-      if (attrs & (DF_UC | DF_UC_WIDE)) {
+      if (attrs & DF_UC) {
         if (attrs & DF_CORE_C) {
           changed |= setCore(cUnit, ssaRep->uses[next], true);
         }
-        if (attrs & DF_UC_WIDE) {
+        if (attrs & DF_REF_C) {
+          changed |= setRef(cUnit, ssaRep->uses[next], true);
+        }
+        if (attrs & DF_C_WIDE) {
           cUnit->regLocation[ssaRep->uses[next]].wide = true;
           cUnit->regLocation[ssaRep->uses[next + 1]].highWord = true;
           DCHECK_EQ(SRegToVReg(cUnit, ssaRep->uses[next])+1,
@@ -183,11 +208,11 @@
           }
         }
         int numUses = mir->dalvikInsn.vA;
-        // If this is a non-static invoke, skip implicit "this"
+        // If this is a non-static invoke, mark implicit "this"
         if (((mir->dalvikInsn.opcode != Instruction::INVOKE_STATIC) &&
             (mir->dalvikInsn.opcode != Instruction::INVOKE_STATIC_RANGE))) {
           cUnit->regLocation[ssaRep->uses[next]].defined = true;
-          cUnit->regLocation[ssaRep->uses[next]].core = true;
+          cUnit->regLocation[ssaRep->uses[next]].ref = true;
           next++;
         }
         uint32_t cpos = 1;
@@ -215,6 +240,9 @@
               case 'F':
                 ssaRep->fpUse[i] = true;
                 break;
+              case 'L':
+                changed |= setRef(cUnit,ssaRep->uses[i], true);
+                break;
               default:
                 changed |= setCore(cUnit,ssaRep->uses[i], true);
                 break;
@@ -237,15 +265,20 @@
         // 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);
         }
         /*
          * TODO: cleaner fix
@@ -261,18 +294,20 @@
          * disable register promotion (which is the only thing that
          * relies on distinctions between core and fp usages.
          */
-        if ((definedFP && definedCore) &&
+        if ((definedFP && (definedCore | definedRef)) &&
             ((cUnit->disableOpt & (1 << kPromoteRegs)) == 0)) {
           LOG(WARNING) << PrettyMethod(cUnit->method_idx, *cUnit->dex_file)
                        << " op at block " << bb->id
-                       << " has both fp and core uses for same def.";
+                       << " has both fp and core/ref uses for same def.";
           cUnit->disableOpt |= (1 << kPromoteRegs);
         }
         changed |= setFp(cUnit, ssaRep->defs[0], definedFP);
         changed |= setCore(cUnit, ssaRep->defs[0], definedCore);
+        changed |= setRef(cUnit, ssaRep->defs[0], definedRef);
         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);
         }
       }
     }
@@ -296,7 +331,7 @@
   }
 }
 
-static const RegLocation freshLoc = {kLocDalvikFrame, 0, 0, 0, 0, 0, 0,
+static const RegLocation freshLoc = {kLocDalvikFrame, 0, 0, 0, 0, 0, 0, 0,
                                      INVALID_REG, INVALID_REG, INVALID_SREG};
 
 /*
@@ -343,7 +378,7 @@
     if ((cUnit->access_flags & kAccStatic) == 0) {
       // For non-static, skip past "this"
       cUnit->regLocation[sReg].defined = true;
-      cUnit->regLocation[sReg].core = true;
+      cUnit->regLocation[sReg].ref = true;
       sReg++;
     }
     const char* shorty = cUnit->shorty;