Final CL to enable register allocation on x86.

This CL implements:
1) Resolution after allocation: connecting the locations
   allocated to an interval within a block and between blocks.
2) Handling of fixed registers: some instructions require
   inputs/output to be at a specific location, and the allocator
   needs to deal with them in a special way.
3) ParallelMoveResolver::EmitNativeCode for x86.

Change-Id: I0da6bd7eb66877987148b87c3be6a983b4e3f858
diff --git a/compiler/optimizing/graph_visualizer.cc b/compiler/optimizing/graph_visualizer.cc
index 5c5042e..a49ce64 100644
--- a/compiler/optimizing/graph_visualizer.cc
+++ b/compiler/optimizing/graph_visualizer.cc
@@ -28,8 +28,15 @@
  */
 class HGraphVisualizerPrinter : public HGraphVisitor {
  public:
-  HGraphVisualizerPrinter(HGraph* graph, std::ostream& output, const CodeGenerator& codegen)
-      : HGraphVisitor(graph), output_(output), codegen_(codegen), indent_(0) {}
+  HGraphVisualizerPrinter(HGraph* graph,
+                          std::ostream& output,
+                          const char* pass_name,
+                          const CodeGenerator& codegen)
+      : HGraphVisitor(graph),
+        output_(output),
+        pass_name_(pass_name),
+        codegen_(codegen),
+        indent_(0) {}
 
   void StartTag(const char* name) {
     AddIndent();
@@ -94,6 +101,33 @@
     output_<< std::endl;
   }
 
+  void DumpLocation(Location location, Primitive::Type type) {
+    if (location.IsRegister()) {
+      if (type == Primitive::kPrimDouble || type == Primitive::kPrimFloat) {
+        codegen_.DumpFloatingPointRegister(output_, location.reg().RegId());
+      } else {
+        codegen_.DumpCoreRegister(output_, location.reg().RegId());
+      }
+    } else {
+      DCHECK(location.IsStackSlot());
+      output_ << location.GetStackIndex() << "(sp)";
+    }
+  }
+
+  void VisitParallelMove(HParallelMove* instruction) {
+    output_ << instruction->DebugName();
+    output_ << " (";
+    for (size_t i = 0, e = instruction->NumMoves(); i < e; ++i) {
+      MoveOperands* move = instruction->MoveOperandsAt(i);
+      DumpLocation(move->GetSource(), Primitive::kPrimInt);
+      output_ << " -> ";
+      DumpLocation(move->GetDestination(), Primitive::kPrimInt);
+      if (i + 1 != e) {
+        output_ << ", ";
+      }
+    }
+    output_ << ")";
+  }
 
   void VisitInstruction(HInstruction* instruction) {
     output_ << instruction->DebugName();
@@ -104,24 +138,28 @@
       }
       output_ << "]";
     }
-    if (instruction->GetLifetimePosition() != kNoLifetime) {
+    if (pass_name_ == kLivenessPassName && instruction->GetLifetimePosition() != kNoLifetime) {
       output_ << " (liveness: " << instruction->GetLifetimePosition();
       if (instruction->HasLiveInterval()) {
         output_ << " ";
         const LiveInterval& interval = *instruction->GetLiveInterval();
         interval.Dump(output_);
-        if (interval.HasRegister()) {
-          int reg = interval.GetRegister();
-          output_ << " ";
-          if (instruction->GetType() == Primitive::kPrimFloat
-              || instruction->GetType() == Primitive::kPrimDouble) {
-            codegen_.DumpFloatingPointRegister(output_, reg);
-          } else {
-            codegen_.DumpCoreRegister(output_, reg);
-          }
-        }
       }
       output_ << ")";
+    } else if (pass_name_ == kRegisterAllocatorPassName) {
+      LocationSummary* locations = instruction->GetLocations();
+      if (locations != nullptr) {
+        output_ << " ( ";
+        for (size_t i = 0; i < instruction->InputCount(); ++i) {
+          DumpLocation(locations->InAt(i), instruction->InputAt(i)->GetType());
+          output_ << " ";
+        }
+        output_ << ")";
+        if (locations->Out().IsValid()) {
+          output_ << " -> ";
+          DumpLocation(locations->Out(), instruction->GetType());
+        }
+      }
     }
   }
 
@@ -137,9 +175,9 @@
     }
   }
 
-  void Run(const char* pass_name) {
+  void Run() {
     StartTag("cfg");
-    PrintProperty("name", pass_name);
+    PrintProperty("name", pass_name_);
     VisitInsertionOrder();
     EndTag("cfg");
   }
@@ -188,6 +226,7 @@
 
  private:
   std::ostream& output_;
+  const char* pass_name_;
   const CodeGenerator& codegen_;
   size_t indent_;
 
@@ -209,7 +248,7 @@
   }
 
   is_enabled_ = true;
-  HGraphVisualizerPrinter printer(graph, *output_, codegen_);
+  HGraphVisualizerPrinter printer(graph, *output_, "", codegen_);
   printer.StartTag("compilation");
   printer.PrintProperty("name", pretty_name.c_str());
   printer.PrintProperty("method", pretty_name.c_str());
@@ -227,7 +266,7 @@
   }
 
   is_enabled_ = true;
-  HGraphVisualizerPrinter printer(graph, *output_, codegen_);
+  HGraphVisualizerPrinter printer(graph, *output_, "", codegen_);
   printer.StartTag("compilation");
   printer.PrintProperty("name", name);
   printer.PrintProperty("method", name);
@@ -239,8 +278,8 @@
   if (!is_enabled_) {
     return;
   }
-  HGraphVisualizerPrinter printer(graph_, *output_, codegen_);
-  printer.Run(pass_name);
+  HGraphVisualizerPrinter printer(graph_, *output_, pass_name, codegen_);
+  printer.Run();
 }
 
 }  // namespace art