Support hints for register pairs.

Change-Id: Ia49dc5bf3e9a2bd481425bfe7fbeea9feb66c8e6
diff --git a/compiler/optimizing/locations.h b/compiler/optimizing/locations.h
index 9ce8d35..ebca1cc 100644
--- a/compiler/optimizing/locations.h
+++ b/compiler/optimizing/locations.h
@@ -151,6 +151,10 @@
     return GetKind() == kFpuRegisterPair;
   }
 
+  bool IsRegisterKind() const {
+    return IsRegister() || IsFpuRegister() || IsRegisterPair() || IsFpuRegisterPair();
+  }
+
   int reg() const {
     DCHECK(IsRegister() || IsFpuRegister());
     return GetPayload();
diff --git a/compiler/optimizing/ssa_liveness_analysis.cc b/compiler/optimizing/ssa_liveness_analysis.cc
index 2a84735..bebb73b 100644
--- a/compiler/optimizing/ssa_liveness_analysis.cc
+++ b/compiler/optimizing/ssa_liveness_analysis.cc
@@ -311,7 +311,12 @@
   return live_in->UnionIfNotIn(live_out, kill);
 }
 
+static int RegisterOrLowRegister(Location location) {
+  return location.IsPair() ? location.low() : location.reg();
+}
+
 int LiveInterval::FindFirstRegisterHint(size_t* free_until) const {
+  DCHECK(!IsHighInterval());
   if (GetParent() == this && defined_by_ != nullptr) {
     // This is the first interval for the instruction. Try to find
     // a register based on its definition.
@@ -333,8 +338,12 @@
       if (user->IsPhi()) {
         // If the phi has a register, try to use the same.
         Location phi_location = user->GetLiveInterval()->ToLocation();
-        if (SameRegisterKind(phi_location) && free_until[phi_location.reg()] >= use_position) {
-          return phi_location.reg();
+        if (phi_location.IsRegisterKind()) {
+          DCHECK(SameRegisterKind(phi_location));
+          int reg = RegisterOrLowRegister(phi_location);
+          if (free_until[reg] >= use_position) {
+            return reg;
+          }
         }
         const GrowableArray<HBasicBlock*>& predecessors = user->GetBlock()->GetPredecessors();
         // If the instruction dies at the phi assignment, we can try having the
@@ -347,8 +356,11 @@
             HInstruction* input = user->InputAt(i);
             Location location = input->GetLiveInterval()->GetLocationAt(
                 predecessors.Get(i)->GetLifetimeEnd() - 1);
-            if (location.IsRegister() && free_until[location.reg()] >= use_position) {
-              return location.reg();
+            if (location.IsRegisterKind()) {
+              int reg = RegisterOrLowRegister(location);
+              if (free_until[reg] >= use_position) {
+                return reg;
+              }
             }
           }
         }
@@ -359,8 +371,12 @@
         // We use the user's lifetime position - 1 (and not `use_position`) because the
         // register is blocked at the beginning of the user.
         size_t position = user->GetLifetimePosition() - 1;
-        if (SameRegisterKind(expected) && free_until[expected.reg()] >= position) {
-          return expected.reg();
+        if (expected.IsRegisterKind()) {
+          DCHECK(SameRegisterKind(expected));
+          int reg = RegisterOrLowRegister(expected);
+          if (free_until[reg] >= position) {
+            return reg;
+          }
         }
       }
     }
@@ -382,8 +398,9 @@
         // If the input dies at the end of the predecessor, we know its register can
         // be reused.
         Location input_location = input_interval.ToLocation();
-        if (SameRegisterKind(input_location)) {
-          return input_location.reg();
+        if (input_location.IsRegisterKind()) {
+          DCHECK(SameRegisterKind(input_location));
+          return RegisterOrLowRegister(input_location);
         }
       }
     }
@@ -398,8 +415,9 @@
         // If the input dies at the start of this instruction, we know its register can
         // be reused.
         Location location = input_interval.ToLocation();
-        if (SameRegisterKind(location)) {
-          return location.reg();
+        if (location.IsRegisterKind()) {
+          DCHECK(SameRegisterKind(location));
+          return RegisterOrLowRegister(location);
         }
       }
     }
@@ -408,9 +426,19 @@
 }
 
 bool LiveInterval::SameRegisterKind(Location other) const {
-  return IsFloatingPoint()
-      ? other.IsFpuRegister()
-      : other.IsRegister();
+  if (IsFloatingPoint()) {
+    if (IsLowInterval() || IsHighInterval()) {
+      return other.IsFpuRegisterPair();
+    } else {
+      return other.IsFpuRegister();
+    }
+  } else {
+    if (IsLowInterval() || IsHighInterval()) {
+      return other.IsRegisterPair();
+    } else {
+      return other.IsRegister();
+    }
+  }
 }
 
 bool LiveInterval::NeedsTwoSpillSlots() const {