Optimization fixes

Two primary fixes.  First, the save/restore mechanism for FP callee saves
was broken if there were any holes in the save mask (the Arm ld/store
multiple instructions for floating point use a start + count mechanism,
rather than the bit-mask mechanism used for core registers).

The second fix corrects a problem introduced by the recent enhancements
to loading floating point literals.  The load->copy optimization mechanism
for literal loads used the value of the loaded literal to identify
redundant loads.  However, it used only the first 32 bits of the
literal - which worked fine previously because 64-bit literal loads
were treated as a pair of 32-bit loads.  The fix was to use the
label of the literal rather than the value in the aliasInfo - which
works for all sizes.

Change-Id: Ic4779adf73b2c7d80059a988b0ecdef39921a81f
diff --git a/src/compiler/codegen/RallocUtil.cc b/src/compiler/codegen/RallocUtil.cc
index 9df80bd..9690287 100644
--- a/src/compiler/codegen/RallocUtil.cc
+++ b/src/compiler/codegen/RallocUtil.cc
@@ -227,7 +227,7 @@
             coreRegs[i].inUse = true;
             cUnit->coreSpillMask |= (1 << res);
             cUnit->coreVmapTable.push_back(sReg);
-            cUnit->numSpills++;
+            cUnit->numCoreSpills++;
             cUnit->regLocation[sReg].location = kLocPhysReg;
             cUnit->regLocation[sReg].lowReg = res;
             cUnit->regLocation[sReg].home = true;
@@ -238,6 +238,28 @@
 }
 
 /*
+ * Mark a callee-save fp register as promoted.  Note that
+ * vpush/vpop uses contiguous register lists so we must
+ * include any holes in the mask.  Associate holes with
+ * Dalvik register INVALID_REG (-1).
+ */
+STATIC void markPreservedSingle(CompilationUnit* cUnit, int sReg, int reg)
+{
+    DCHECK_GE(reg, FP_REG_MASK + FP_CALLEE_SAVE_BASE);
+    reg = (reg & FP_REG_MASK) - FP_CALLEE_SAVE_BASE;
+    // Ensure fpVmapTable is large enough
+    int tableSize = cUnit->fpVmapTable.size();
+    for (int i = tableSize; i < (reg + 1); i++) {
+        cUnit->fpVmapTable.push_back(INVALID_REG);
+    }
+    // Add the current mapping
+    cUnit->fpVmapTable[reg] = sReg;
+    // 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;
+}
+
+/*
  * Reserve a callee-save fp single register.  Try to fullfill request for
  * even/odd  allocation, but go ahead and allocate anything if not
  * available.  If nothing's available, return -1.
@@ -251,10 +273,7 @@
             ((FPRegs[i].reg & 0x1) == 0) == even) {
             res = FPRegs[i].reg;
             FPRegs[i].inUse = true;
-            cUnit->fpSpillMask |= (1 << (res & FP_REG_MASK));
-            cUnit->fpVmapTable.push_back(sReg);
-            cUnit->numSpills++;
-            cUnit->numFPSpills++;
+            markPreservedSingle(cUnit, sReg, res);
             cUnit->regLocation[sReg].fpLocation = kLocPhysReg;
             cUnit->regLocation[sReg].fpLowReg = res;
             cUnit->regLocation[sReg].home = true;
@@ -292,10 +311,7 @@
         res = p->reg;
         p->inUse = true;
         DCHECK_EQ((res & 1), 0);
-        cUnit->fpSpillMask |= (1 << (res & FP_REG_MASK));
-        cUnit->fpVmapTable.push_back(sReg);
-        cUnit->numSpills++;
-        cUnit->numFPSpills ++;
+        markPreservedSingle(cUnit, sReg, res);
     } else {
         RegisterInfo* FPRegs = cUnit->regPool->FPRegs;
         for (int i = 0; i < cUnit->regPool->numFPRegs; i++) {
@@ -306,13 +322,10 @@
                 (FPRegs[i].reg + 1) == FPRegs[i+1].reg) {
                 res = FPRegs[i].reg;
                 FPRegs[i].inUse = true;
-                cUnit->fpSpillMask |= (1 << (res & FP_REG_MASK));
-                cUnit->fpVmapTable.push_back(sReg);
+                markPreservedSingle(cUnit, sReg, res);
                 FPRegs[i+1].inUse = true;
-                cUnit->fpSpillMask |= (1 << ((res+1) & FP_REG_MASK));
-                cUnit->fpVmapTable.push_back(sReg);
-                cUnit->numSpills += 2;
-                cUnit->numFPSpills += 2;
+                DCHECK_EQ(res + 1, FPRegs[i+1].reg);
+                markPreservedSingle(cUnit, sReg+1, res+1);
                 break;
             }
         }