Added SEA IR def -> use edges (along the use -> def).

The edges are stored in the "tail" object and will be used for type information propagation.
The .dot generation nowhas a switch to enable or disable displaying these edges.

Change-Id: Iaf3ce1d1efcda6f5d65c42c69bb1573786c90309
diff --git a/compiler/sea_ir/instruction_nodes.h b/compiler/sea_ir/instruction_nodes.h
index 103c16f..6f9bddd 100644
--- a/compiler/sea_ir/instruction_nodes.h
+++ b/compiler/sea_ir/instruction_nodes.h
@@ -57,6 +57,7 @@
   // essentially creating SSA form.
   void RenameToSSA(int reg_no, InstructionNode* definition) {
     definition_edges_.insert(std::pair<int, InstructionNode*>(reg_no, definition));
+    definition->AddSSAUse(this);
   }
   // Returns the ordered set of Instructions that define the input operands of this instruction.
   // Precondition: SeaGraph.ConvertToSSA().
@@ -69,6 +70,10 @@
     return ssa_uses;
   }
 
+  virtual void AddSSAUse(InstructionNode* use) {
+    used_in_.push_back(use);
+  }
+
   void Accept(IRVisitor* v) {
     v->Visit(this);
     v->Traverse(this);
@@ -85,11 +90,14 @@
 
  protected:
   explicit InstructionNode(const art::Instruction* in):
-      SeaNode(), instruction_(in), de_def_(false), region_(NULL) { }
+      SeaNode(), instruction_(in), used_in_(), de_def_(false), region_(NULL) { }
+  void ToDotSSAEdges(std::string& result) const;
 
  protected:
   const art::Instruction* const instruction_;
   std::map<int, InstructionNode* > definition_edges_;
+  // Stores pointers to instructions that use the result of the current instruction.
+  std::vector<InstructionNode*> used_in_;
   bool de_def_;
   Region* region_;
 };
@@ -136,15 +144,7 @@
       result += "style=bold";
     }
     result += "];\n";
-    // SSA definitions:
-    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=gray,label=\"";
-        result += art::StringPrintf("vR = %d", def_it->first);
-        result += "\"] ; // ssa edge\n";
-      }
-    }
+    ToDotSSAEdges(result);
   }
 
  private:
diff --git a/compiler/sea_ir/sea.cc b/compiler/sea_ir/sea.cc
index e9a3e1c..9056935 100644
--- a/compiler/sea_ir/sea.cc
+++ b/compiler/sea_ir/sea.cc
@@ -692,6 +692,27 @@
   return sea_instructions;
 }
 
+void InstructionNode::ToDotSSAEdges(std::string& result) const {
+  // SSA definitions:
+  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=gray,label=\"";
+      result += art::StringPrintf("vR = %d", def_it->first);
+      result += "\"] ; // ssa edge\n";
+    }
+  }
+
+  // SSA used-by:
+  if (DotConversion::SaveUseEdges()) {
+    for (std::vector<InstructionNode*>::const_iterator cit = used_in_.begin(); cit != used_in_.end();
+        cit++) {
+      result += (*cit)->StringId() + " -> " + StringId() + "[color=gray,label=\"";
+      result += "\"] ; // SSA used-by edge\n";
+    }
+  }
+}
+
 void InstructionNode::ToDot(std::string& result, const art::DexFile& dex_file) const {
   result += "// Instruction ("+StringId()+"): \n" + StringId() +
       " [label=\"" + instruction_->DumpString(&dex_file) + "\"";
@@ -699,15 +720,8 @@
     result += "style=bold";
   }
   result += "];\n";
-  // SSA definitions:
-  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=gray,label=\"";
-      result += art::StringPrintf("vR = %d", def_it->first);
-      result += "\"] ; // ssa edge\n";
-    }
-  }
+
+  ToDotSSAEdges(result);
 }
 
 void InstructionNode::MarkAsDEDef() {
@@ -756,17 +770,6 @@
   result += art::StringPrintf("%d", register_no_);
   result += ")\"";
   result += "];\n";
-
-  for (std::vector<std::vector<InstructionNode*>*>::const_iterator pred_it =
-      definition_edges_.begin();
-      pred_it != definition_edges_.end(); pred_it++) {
-    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=gray,label=\"vR = ";
-        result += art::StringPrintf("%d", GetRegisterNumber());
-        result += "\"] ;  // phi-ssa edge\n";
-    }
-  }
+  ToDotSSAEdges(result);
 }
 }  // namespace sea_ir
diff --git a/compiler/sea_ir/sea.h b/compiler/sea_ir/sea.h
index c64703a..040ad8a 100644
--- a/compiler/sea_ir/sea.h
+++ b/compiler/sea_ir/sea.h
@@ -35,6 +35,17 @@
   VISITING = -2
 };
 
+// Stores options for turning a SEA IR graph to a .dot file.
+class DotConversion {
+ public:
+  static bool SaveUseEdges() {
+    return save_use_edges_;
+  }
+
+ private:
+  static const bool save_use_edges_ =  false; // TODO: Enable per-sea graph configuration.
+};
+
 class Region;
 
 class InstructionNode;
@@ -53,6 +64,7 @@
     result += StringId() +" [label=\"signature:";
     result += art::StringPrintf("r%d", GetResultRegister());
     result += "\"] // signature node\n";
+    ToDotSSAEdges(result);
   }
 
   int GetResultRegister() const {
@@ -98,6 +110,7 @@
       definition_edges_[predecessor_id] = new std::vector<InstructionNode*>();
     }
     definition_edges_[predecessor_id]->push_back(definition);
+    definition->AddSSAUse(this);
   }
 
   // Returns the instruction that defines the phi register from predecessor