summaryrefslogtreecommitdiffstats
path: root/compiler/sea_ir
diff options
context:
space:
mode:
authorDragos Sbirlea <dragoss@google.com>2013-07-26 12:05:03 -0700
committerDragos Sbirlea <dragoss@google.com>2013-07-26 16:14:20 -0700
commit6bee4459691c8e3b20fc706e74d52d08a4869731 (patch)
treea3d724b66f45b2cd37e3b3c5e7b29af8a0b50643 /compiler/sea_ir
parent0f055d11096cb02563e9c040cd03c791fd8f69a3 (diff)
downloadart-6bee4459691c8e3b20fc706e74d52d08a4869731.tar.gz
art-6bee4459691c8e3b20fc706e74d52d08a4869731.tar.bz2
art-6bee4459691c8e3b20fc706e74d52d08a4869731.zip
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.cc2
-rw-r--r--compiler/sea_ir/instruction_nodes.h12
-rw-r--r--compiler/sea_ir/sea.cc56
-rw-r--r--compiler/sea_ir/sea.h16
-rw-r--r--compiler/sea_ir/sea_node.h5
5 files changed, 54 insertions, 37 deletions
diff --git a/compiler/sea_ir/frontend.cc b/compiler/sea_ir/frontend.cc
index 8fc1cf8315..ebc767ccbc 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 5c9cfe19dc..103c16f8ac 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 3488afd5be..7a1894b26e 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 25ab1fed10..c64703afff 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 5d28f8aa72..c13e5d6aba 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() { }