diff options
author | Dragos Sbirlea <dragoss@google.com> | 2013-07-26 12:05:03 -0700 |
---|---|---|
committer | Dragos Sbirlea <dragoss@google.com> | 2013-07-26 16:14:20 -0700 |
commit | 6bee4459691c8e3b20fc706e74d52d08a4869731 (patch) | |
tree | a3d724b66f45b2cd37e3b3c5e7b29af8a0b50643 /compiler/sea_ir | |
parent | 0f055d11096cb02563e9c040cd03c791fd8f69a3 (diff) | |
download | art-6bee4459691c8e3b20fc706e74d52d08a4869731.zip art-6bee4459691c8e3b20fc706e74d52d08a4869731.tar.gz art-6bee4459691c8e3b20fc706e74d52d08a4869731.tar.bz2 |
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
Diffstat (limited to 'compiler/sea_ir')
-rw-r--r-- | compiler/sea_ir/frontend.cc | 2 | ||||
-rw-r--r-- | compiler/sea_ir/instruction_nodes.h | 12 | ||||
-rw-r--r-- | compiler/sea_ir/sea.cc | 56 | ||||
-rw-r--r-- | compiler/sea_ir/sea.h | 16 | ||||
-rw-r--r-- | compiler/sea_ir/sea_node.h | 5 |
5 files changed, 54 insertions, 37 deletions
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 @@ static CompiledMethod* CompileMethodWithSeaIr(CompilerDriver& compiler, // 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 @@ class InstructionNode: public SeaNode { // 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 @@ class UnnamedConstInstructionNode: public ConstInstructionNode { 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 @@ class UnnamedConstInstructionNode: public ConstInstructionNode { 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 @@ void IRVisitor::Traverse(SeaGraph* graph) { } } -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 @@ SeaNode* Region::GetLastChild() const { 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 @@ void Region::ToDot(std::string& result) const { " -> " + (*cit)->StringId() + " [color=gray]; // Dominance frontier.\n"; } - result += "// End Region.\n"; + */ } void Region::ComputeDownExposedDefs() { @@ -698,9 +712,9 @@ std::vector<InstructionNode*> InstructionNode::Create(const art::Instruction* in 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 @@ void InstructionNode::ToDot(std::string& result) const { 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 @@ std::vector<int> InstructionNode::GetUses() { 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 @@ void PhiInstructionNode::ToDot(std::string& result) const { 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 @@ class SignatureNode: public InstructionNode { 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 @@ class PhiInstructionNode: public InstructionNode { 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 @@ class Region : public SeaNode { 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 @@ class Region : public SeaNode { // 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 @@ class Region : public SeaNode { // 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 @@ class SeaGraph: IVisitable { 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 @@ class SeaGraph: IVisitable { 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 @@ class IVisitable { }; // 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 @@ class SeaNode: public IVisitable { 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 @@ class SeaNode: public IVisitable { // 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() { } |