Improvements and clustering for the .dot file generation.

Dot clusters are used to show SEA IR regions.
Passing around dex_file for improved instruction  text representation.
SeaGraph now stores the dex file.
Removed all .dot edges except ssa edges and inter-region control flow.
Changed color to gray for ssa edges and kept black for control flow.
Consistently labeled SSA edges with virtual register number.
Replaced stringstream with StringPrintf.

Change-Id: I67d9d92e594d3f2de94eec1c78a64f3972ae60b1
diff --git a/compiler/sea_ir/frontend.cc b/compiler/sea_ir/frontend.cc
index 8fc1cf8..ebc767c 100644
--- a/compiler/sea_ir/frontend.cc
+++ b/compiler/sea_ir/frontend.cc
@@ -40,7 +40,7 @@
   // NOTE: Instead of keeping the convention from the Dalvik frontend.cc
   //       and silencing the cpplint.py warning, I just corrected the formatting.
   VLOG(compiler) << "Compiling " << PrettyMethod(method_idx, dex_file) << "...";
-  sea_ir::SeaGraph* sg = sea_ir::SeaGraph::GetCurrentGraph();
+  sea_ir::SeaGraph* sg = sea_ir::SeaGraph::GetCurrentGraph(dex_file);
   sg->CompileMethod(code_item, class_def_idx, method_idx, dex_file);
   sg->DumpSea("/tmp/temp.dot");
   CHECK(0 && "No SEA compiled function exists yet.");
diff --git a/compiler/sea_ir/instruction_nodes.h b/compiler/sea_ir/instruction_nodes.h
index 5c9cfe1..103c16f 100644
--- a/compiler/sea_ir/instruction_nodes.h
+++ b/compiler/sea_ir/instruction_nodes.h
@@ -50,7 +50,7 @@
   // Returns the set of register numbers that are used by the instruction.
   virtual std::vector<int> GetUses();
   // Appends to @result the .dot string representation of the instruction.
-  virtual void ToDot(std::string& result) const;
+  virtual void ToDot(std::string& result, const art::DexFile& dex_file) const;
   // Mark the current instruction as a downward exposed definition.
   void MarkAsDEDef();
   // Rename the use of @reg_no to refer to the instruction @definition,
@@ -126,7 +126,7 @@
     return value_;
   }
 
-  void ToDot(std::string& result) const {
+  void ToDot(std::string& result, const art::DexFile& dex_file) const {
     std::ostringstream sstream;
     sstream << GetConstValue();
     const std::string value_as_string(sstream.str());
@@ -140,11 +140,9 @@
     for (std::map<int, InstructionNode* >::const_iterator def_it = definition_edges_.begin();
         def_it != definition_edges_.end(); def_it++) {
       if (NULL != def_it->second) {
-        result += def_it->second->StringId() + " -> " + StringId() +"[color=red,label=\"";
-        std::stringstream ss;
-        ss << def_it->first;
-        result.append(ss.str());
-        result += "\"] ;  // ssa edge\n";
+        result += def_it->second->StringId() + " -> " + StringId() +"[color=gray,label=\"";
+        result += art::StringPrintf("vR = %d", def_it->first);
+        result += "\"] ; // ssa edge\n";
       }
     }
   }
diff --git a/compiler/sea_ir/sea.cc b/compiler/sea_ir/sea.cc
index 3488afd..7a1894b 100644
--- a/compiler/sea_ir/sea.cc
+++ b/compiler/sea_ir/sea.cc
@@ -27,7 +27,6 @@
 
 namespace sea_ir {
 
-SeaGraph SeaGraph::graph_;
 int SeaNode::current_max_node_id_ = 0;
 
 void IRVisitor::Traverse(Region* region) {
@@ -51,16 +50,16 @@
   }
 }
 
-SeaGraph* SeaGraph::GetCurrentGraph() {
-  return &sea_ir::SeaGraph::graph_;
+SeaGraph* SeaGraph::GetCurrentGraph(const art::DexFile& dex_file) {
+  return new SeaGraph(dex_file);
 }
 
 void SeaGraph::DumpSea(std::string filename) const {
   LOG(INFO) << "Starting to write SEA string to file.";
   std::string result;
-  result += "digraph seaOfNodes {\n";
+  result += "digraph seaOfNodes {\ncompound=true\n";
   for (std::vector<Region*>::const_iterator cit = regions_.begin(); cit != regions_.end(); cit++) {
-    (*cit)->ToDot(result);
+    (*cit)->ToDot(result, dex_file_);
   }
   result += "}\n";
   art::File* file = art::OS::OpenFile(filename.c_str(), true, true);
@@ -490,33 +489,48 @@
   return NULL;
 }
 
-void Region::ToDot(std::string& result) const {
-  result += "\n// Region: \n" + StringId() + " [label=\"region " + StringId() + "(rpo=";
+void Region::ToDot(std::string& result, const art::DexFile& dex_file) const {
+  result += "\n// Region: \nsubgraph " + StringId() + " { label=\"region " + StringId() + "(rpo=";
   result += art::StringPrintf("%d", rpo_number_);
   if (NULL != GetIDominator()) {
     result += " dom=" + GetIDominator()->StringId();
   }
-  result += ")\"];\n";
+  result += ")\";\n";
+
+  for (std::vector<PhiInstructionNode*>::const_iterator cit = phi_instructions_.begin();
+        cit != phi_instructions_.end(); cit++) {
+    result += (*cit)->StringId() +";\n";
+  }
+
+  for (std::vector<InstructionNode*>::const_iterator cit = instructions_.begin();
+        cit != instructions_.end(); cit++) {
+      result += (*cit)->StringId() +";\n";
+      // result += StringId() + " -> " + (*cit)->StringId() + "; // region -> instruction \n";
+    }
+
+  result += "} // End Region.\n";
 
   // Save phi-nodes.
   for (std::vector<PhiInstructionNode*>::const_iterator cit = phi_instructions_.begin();
       cit != phi_instructions_.end(); cit++) {
-    (*cit)->ToDot(result);
-    result += StringId() + " -> " + (*cit)->StringId() + ";  // phi-function \n";
+    (*cit)->ToDot(result, dex_file);
+    // result += StringId() + " -> " + (*cit)->StringId() + "; // region -> phi-function \n";
   }
 
   // Save instruction nodes.
   for (std::vector<InstructionNode*>::const_iterator cit = instructions_.begin();
       cit != instructions_.end(); cit++) {
-    (*cit)->ToDot(result);
-    result += StringId() + " -> " + (*cit)->StringId() + ";  // region -> instruction \n";
+    (*cit)->ToDot(result, dex_file);
+    //result += StringId() + " -> " + (*cit)->StringId() + "; // region -> instruction \n";
   }
 
   for (std::vector<Region*>::const_iterator cit = successors_.begin(); cit != successors_.end();
       cit++) {
     DCHECK(NULL != *cit) << "Null successor found for SeaNode" << GetLastChild()->StringId() << ".";
-    result += GetLastChild()->StringId() + " -> " + (*cit)->StringId() + ";\n\n";
+    result += GetLastChild()->StringId() + " -> " + (*cit)->GetLastChild()->StringId() +
+         "[lhead=" + (*cit)->StringId() + ", " + "ltail=" + StringId() + "];\n\n";
   }
+  /*
   // Save reaching definitions.
   for (std::map<int, std::set<sea_ir::InstructionNode*>* >::const_iterator cit =
       reaching_defs_.begin();
@@ -536,7 +550,7 @@
         " -> " + (*cit)->StringId() +
         " [color=gray];  // Dominance frontier.\n";
   }
-  result += "// End Region.\n";
+  */
 }
 
 void Region::ComputeDownExposedDefs() {
@@ -698,9 +712,9 @@
   return sea_instructions;
 }
 
-void InstructionNode::ToDot(std::string& result) const {
+void InstructionNode::ToDot(std::string& result, const art::DexFile& dex_file) const {
   result += "// Instruction ("+StringId()+"): \n" + StringId() +
-      " [label=\"" + instruction_->DumpString(NULL) + "\"";
+      " [label=\"" + instruction_->DumpString(&dex_file) + "\"";
   if (de_def_) {
     result += "style=bold";
   }
@@ -709,9 +723,9 @@
   for (std::map<int, InstructionNode* >::const_iterator def_it = definition_edges_.begin();
       def_it != definition_edges_.end(); def_it++) {
     if (NULL != def_it->second) {
-      result += def_it->second->StringId() + " -> " + StringId() +"[color=red,label=\"";
-      result += art::StringPrintf("%d", def_it->first);
-      result += "\"] ;  // ssa edge\n";
+      result += def_it->second->StringId() + " -> " + StringId() +"[color=gray,label=\"";
+      result += art::StringPrintf("vR = %d", def_it->first);
+      result += "\"] ; // ssa edge\n";
     }
   }
 }
@@ -756,7 +770,7 @@
   return uses;
 }
 
-void PhiInstructionNode::ToDot(std::string& result) const {
+void PhiInstructionNode::ToDot(std::string& result, const art::DexFile& dex_file) const {
   result += "// PhiInstruction: \n" + StringId() +
       " [label=\"" + "PHI(";
   result += art::StringPrintf("%d", register_no_);
@@ -768,7 +782,7 @@
     std::vector<InstructionNode*>* defs_from_pred = *pred_it;
     for (std::vector<InstructionNode* >::const_iterator def_it = defs_from_pred->begin();
         def_it != defs_from_pred->end(); def_it++) {
-        result += (*def_it)->StringId() + " -> " + StringId() +"[color=red,label=\"vR = ";
+        result += (*def_it)->StringId() + " -> " + StringId() +"[color=gray,label=\"vR = ";
         result += art::StringPrintf("%d", GetRegisterNumber());
         result += "\"] ;  // phi-ssa edge\n";
     }
diff --git a/compiler/sea_ir/sea.h b/compiler/sea_ir/sea.h
index 25ab1fe..c64703a 100644
--- a/compiler/sea_ir/sea.h
+++ b/compiler/sea_ir/sea.h
@@ -49,7 +49,7 @@
   explicit SignatureNode(unsigned int parameter_register):InstructionNode(NULL),
     parameter_register_(parameter_register) { }
 
-  void ToDot(std::string& result) const {
+  void ToDot(std::string& result, const art::DexFile& dex_file) const {
     result += StringId() +" [label=\"signature:";
     result += art::StringPrintf("r%d", GetResultRegister());
     result += "\"] // signature node\n";
@@ -77,7 +77,7 @@
   explicit PhiInstructionNode(int register_no):
     InstructionNode(NULL), register_no_(register_no), definition_edges_() {}
   // Appends to @result the .dot string representation of the instruction.
-  void ToDot(std::string& result) const;
+  void ToDot(std::string& result, const art::DexFile& dex_file) const;
   // Returns the register on which this phi-function is used.
   int GetRegisterNumber() const {
     return register_no_;
@@ -125,7 +125,9 @@
  public:
   explicit Region():
     SeaNode(), successors_(), predecessors_(), reaching_defs_size_(0),
-    rpo_number_(NOT_VISITED), idom_(NULL), idominated_set_(), df_(), phi_set_() {}
+    rpo_number_(NOT_VISITED), idom_(NULL), idominated_set_(), df_(), phi_set_() {
+    string_id_ = "cluster_" + string_id_;
+  }
   // Adds @instruction as an instruction node child in the current region.
   void AddChild(sea_ir::InstructionNode* instruction);
   // Returns the last instruction node child of the current region.
@@ -138,7 +140,7 @@
   // Appends to @result a dot language formatted string representing the node and
   //    (by convention) outgoing edges, so that the composition of theToDot() of all nodes
   //    builds a complete dot graph (without prolog and epilog though).
-  virtual void ToDot(std::string& result) const;
+  virtual void ToDot(std::string& result, const art::DexFile& dex_file) const;
   // Computes Downward Exposed Definitions for the current node.
   void ComputeDownExposedDefs();
   const std::map<int, sea_ir::InstructionNode*>* GetDownExposedDefs() const;
@@ -242,7 +244,7 @@
 // and acts as starting point for visitors (ex: during code generation).
 class SeaGraph: IVisitable {
  public:
-  static SeaGraph* GetCurrentGraph();
+  static SeaGraph* GetCurrentGraph(const art::DexFile&);
 
   void CompileMethod(const art::DexFile::CodeItem* code_item,
       uint32_t class_def_idx, uint32_t method_idx, const art::DexFile& dex_file);
@@ -264,7 +266,8 @@
   uint32_t method_idx_;
 
  private:
-  SeaGraph(): class_def_idx_(0), method_idx_(0), regions_(), parameters_() {
+  explicit SeaGraph(const art::DexFile& df):
+    class_def_idx_(0), method_idx_(0), regions_(), parameters_(), dex_file_(df) {
   }
   // Registers @childReg as a region belonging to the SeaGraph instance.
   void AddRegion(Region* childReg);
@@ -319,6 +322,7 @@
   static SeaGraph graph_;
   std::vector<Region*> regions_;
   std::vector<SignatureNode*> parameters_;
+  const art::DexFile& dex_file_;
 };
 }  // namespace sea_ir
 #endif  // ART_COMPILER_SEA_IR_SEA_H_
diff --git a/compiler/sea_ir/sea_node.h b/compiler/sea_ir/sea_node.h
index 5d28f8a..c13e5d6 100644
--- a/compiler/sea_ir/sea_node.h
+++ b/compiler/sea_ir/sea_node.h
@@ -30,7 +30,7 @@
 };
 
 // This abstract class provides the essential services that
-// we want each SEA IR element should have.
+// we want each SEA IR element to have.
 // At the moment, these are:
 // - an id and corresponding string representation.
 // - a .dot graph language representation for .dot output.
@@ -42,6 +42,7 @@
   explicit SeaNode():id_(GetNewId()), string_id_() {
     string_id_ = art::StringPrintf("%d", id_);
   }
+
   // Adds CFG predecessors and successors to each block.
   void AddSuccessor(Region* successor);
   void AddPredecessor(Region* predecesor);
@@ -58,7 +59,7 @@
   // Appends to @result a dot language formatted string representing the node and
   //    (by convention) outgoing edges, so that the composition of theToDot() of all nodes
   //    builds a complete dot graph, but without prolog ("digraph {") and epilog ("}").
-  virtual void ToDot(std::string& result) const = 0;
+  virtual void ToDot(std::string& result, const art::DexFile& dex_file) const = 0;
 
   virtual ~SeaNode() { }