diff options
Diffstat (limited to 'compiler/optimizing/graph_visualizer.cc')
-rw-r--r-- | compiler/optimizing/graph_visualizer.cc | 205 |
1 files changed, 143 insertions, 62 deletions
diff --git a/compiler/optimizing/graph_visualizer.cc b/compiler/optimizing/graph_visualizer.cc index f011e85cc0..f5c630bf97 100644 --- a/compiler/optimizing/graph_visualizer.cc +++ b/compiler/optimizing/graph_visualizer.cc @@ -17,8 +17,11 @@ #include "graph_visualizer.h" #include "code_generator.h" -#include "driver/dex_compilation_unit.h" +#include "dead_code_elimination.h" +#include "licm.h" #include "nodes.h" +#include "optimization.h" +#include "register_allocator.h" #include "ssa_liveness_analysis.h" namespace art { @@ -31,10 +34,12 @@ class HGraphVisualizerPrinter : public HGraphVisitor { HGraphVisualizerPrinter(HGraph* graph, std::ostream& output, const char* pass_name, + bool is_after_pass, const CodeGenerator& codegen) : HGraphVisitor(graph), output_(output), pass_name_(pass_name), + is_after_pass_(is_after_pass), codegen_(codegen), indent_(0) {} @@ -67,7 +72,7 @@ class HGraphVisualizerPrinter : public HGraphVisitor { void PrintTime(const char* name) { AddIndent(); - output_ << name << " " << time(NULL) << std::endl; + output_ << name << " " << time(nullptr) << std::endl; } void PrintInt(const char* name, int value) { @@ -81,6 +86,25 @@ class HGraphVisualizerPrinter : public HGraphVisitor { } } + char GetTypeId(Primitive::Type type) { + // Note that Primitive::Descriptor would not work for us + // because it does not handle reference types (that is kPrimNot). + switch (type) { + case Primitive::kPrimBoolean: return 'z'; + case Primitive::kPrimByte: return 'b'; + case Primitive::kPrimChar: return 'c'; + case Primitive::kPrimShort: return 's'; + case Primitive::kPrimInt: return 'i'; + case Primitive::kPrimLong: return 'j'; + case Primitive::kPrimFloat: return 'f'; + case Primitive::kPrimDouble: return 'd'; + case Primitive::kPrimNot: return 'l'; + case Primitive::kPrimVoid: return 'v'; + } + LOG(FATAL) << "Unreachable"; + return 'v'; + } + void PrintPredecessors(HBasicBlock* block) { AddIndent(); output_ << "predecessors"; @@ -101,50 +125,113 @@ class HGraphVisualizerPrinter : public HGraphVisitor { output_<< std::endl; } - void DumpLocation(Location location, Primitive::Type type) { + void DumpLocation(Location location) { if (location.IsRegister()) { - if (type == Primitive::kPrimDouble || type == Primitive::kPrimFloat) { - codegen_.DumpFloatingPointRegister(output_, location.reg().RegId()); - } else { - codegen_.DumpCoreRegister(output_, location.reg().RegId()); - } + codegen_.DumpCoreRegister(output_, location.reg()); + } else if (location.IsFpuRegister()) { + codegen_.DumpFloatingPointRegister(output_, location.reg()); } else if (location.IsConstant()) { output_ << "constant"; + HConstant* constant = location.GetConstant(); + if (constant->IsIntConstant()) { + output_ << " " << constant->AsIntConstant()->GetValue(); + } else if (constant->IsLongConstant()) { + output_ << " " << constant->AsLongConstant()->GetValue(); + } } else if (location.IsInvalid()) { output_ << "invalid"; } else if (location.IsStackSlot()) { output_ << location.GetStackIndex() << "(sp)"; + } else if (location.IsFpuRegisterPair()) { + codegen_.DumpFloatingPointRegister(output_, location.low()); + output_ << " and "; + codegen_.DumpFloatingPointRegister(output_, location.high()); + } else if (location.IsRegisterPair()) { + codegen_.DumpCoreRegister(output_, location.low()); + output_ << " and "; + codegen_.DumpCoreRegister(output_, location.high()); + } else if (location.IsUnallocated()) { + output_ << "<U>"; } else { DCHECK(location.IsDoubleStackSlot()); output_ << "2x" << location.GetStackIndex() << "(sp)"; } } - void VisitParallelMove(HParallelMove* instruction) { - output_ << instruction->DebugName(); + void VisitParallelMove(HParallelMove* instruction) OVERRIDE { output_ << " ("; for (size_t i = 0, e = instruction->NumMoves(); i < e; ++i) { MoveOperands* move = instruction->MoveOperandsAt(i); - DumpLocation(move->GetSource(), Primitive::kPrimInt); + DumpLocation(move->GetSource()); output_ << " -> "; - DumpLocation(move->GetDestination(), Primitive::kPrimInt); + DumpLocation(move->GetDestination()); if (i + 1 != e) { output_ << ", "; } } output_ << ")"; + output_ << " (liveness: " << instruction->GetLifetimePosition() << ")"; + } + + void VisitIntConstant(HIntConstant* instruction) OVERRIDE { + output_ << " " << instruction->GetValue(); + } + + void VisitLongConstant(HLongConstant* instruction) OVERRIDE { + output_ << " " << instruction->GetValue(); + } + + void VisitFloatConstant(HFloatConstant* instruction) OVERRIDE { + output_ << " " << instruction->GetValue(); + } + + void VisitDoubleConstant(HDoubleConstant* instruction) OVERRIDE { + output_ << " " << instruction->GetValue(); + } + + void VisitPhi(HPhi* phi) OVERRIDE { + output_ << " " << phi->GetRegNumber(); + } + + void VisitMemoryBarrier(HMemoryBarrier* barrier) OVERRIDE { + output_ << " " << barrier->GetBarrierKind(); + } + + bool IsPass(const char* name) { + return strcmp(pass_name_, name) == 0; } - void VisitInstruction(HInstruction* instruction) { + void PrintInstruction(HInstruction* instruction) { output_ << instruction->DebugName(); + instruction->Accept(this); if (instruction->InputCount() > 0) { output_ << " [ "; for (HInputIterator inputs(instruction); !inputs.Done(); inputs.Advance()) { - output_ << "v" << inputs.Current()->GetId() << " "; + output_ << GetTypeId(inputs.Current()->GetType()) << inputs.Current()->GetId() << " "; } output_ << "]"; } - if (pass_name_ == kLivenessPassName && instruction->GetLifetimePosition() != kNoLifetime) { + if (instruction->HasEnvironment()) { + output_ << " (env:"; + for (HEnvironment* environment = instruction->GetEnvironment(); + environment != nullptr; + environment = environment->GetParent()) { + output_ << " [ "; + for (size_t i = 0, e = environment->Size(); i < e; ++i) { + HInstruction* insn = environment->GetInstructionAt(i); + if (insn != nullptr) { + output_ << GetTypeId(insn->GetType()) << insn->GetId() << " "; + } else { + output_ << " _ "; + } + } + output_ << "]"; + } + output_ << ")"; + } + if (IsPass(SsaLivenessAnalysis::kLivenessPassName) + && is_after_pass_ + && instruction->GetLifetimePosition() != kNoLifetime) { output_ << " (liveness: " << instruction->GetLifetimePosition(); if (instruction->HasLiveInterval()) { output_ << " "; @@ -152,20 +239,30 @@ class HGraphVisualizerPrinter : public HGraphVisitor { interval.Dump(output_); } output_ << ")"; - } else if (pass_name_ == kRegisterAllocatorPassName) { + } else if (IsPass(RegisterAllocator::kRegisterAllocatorPassName) && is_after_pass_) { 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()); + DumpLocation(locations->InAt(i)); output_ << " "; } output_ << ")"; if (locations->Out().IsValid()) { output_ << " -> "; - DumpLocation(locations->Out(), instruction->GetType()); + DumpLocation(locations->Out()); } } + output_ << " (liveness: " << instruction->GetLifetimePosition() << ")"; + } else if (IsPass(LICM::kLoopInvariantCodeMotionPassName) + || IsPass(HDeadCodeElimination::kFinalDeadCodeEliminationPassName)) { + output_ << " ( loop_header:"; + HLoopInformation* info = instruction->GetBlock()->GetLoopInformation(); + if (info == nullptr) { + output_ << "null )"; + } else { + output_ << "B" << info->GetHeader()->GetBlockId() << " )"; + } } } @@ -173,22 +270,30 @@ class HGraphVisualizerPrinter : public HGraphVisitor { const char* kEndInstructionMarker = "<|@"; for (HInstructionIterator it(list); !it.Done(); it.Advance()) { HInstruction* instruction = it.Current(); - AddIndent(); int bci = 0; - output_ << bci << " " << instruction->NumberOfUses() << " v" << instruction->GetId() << " "; - instruction->Accept(this); + size_t num_uses = 0; + for (HUseIterator<HInstruction*> use_it(instruction->GetUses()); + !use_it.Done(); + use_it.Advance()) { + ++num_uses; + } + AddIndent(); + output_ << bci << " " << num_uses << " " + << GetTypeId(instruction->GetType()) << instruction->GetId() << " "; + PrintInstruction(instruction); output_ << kEndInstructionMarker << std::endl; } } void Run() { StartTag("cfg"); - PrintProperty("name", pass_name_); + std::string pass_desc = std::string(pass_name_) + (is_after_pass_ ? " (after)" : " (before)"); + PrintProperty("name", pass_desc.c_str()); VisitInsertionOrder(); EndTag("cfg"); } - void VisitBasicBlock(HBasicBlock* block) { + void VisitBasicBlock(HBasicBlock* block) OVERRIDE { StartTag("block"); PrintProperty("name", "B", block->GetBlockId()); if (block->GetLifetimeStart() != kNoLifetime) { @@ -214,7 +319,8 @@ class HGraphVisualizerPrinter : public HGraphVisitor { for (HInstructionIterator it(block->GetPhis()); !it.Done(); it.Advance()) { AddIndent(); HInstruction* instruction = it.Current(); - output_ << instruction->GetId() << " v" << instruction->GetId() << "[ "; + output_ << instruction->GetId() << " " << GetTypeId(instruction->GetType()) + << instruction->GetId() << "[ "; for (HInputIterator inputs(instruction); !inputs.Done(); inputs.Advance()) { output_ << inputs.Current()->GetId() << " "; } @@ -233,6 +339,7 @@ class HGraphVisualizerPrinter : public HGraphVisitor { private: std::ostream& output_; const char* pass_name_; + const bool is_after_pass_; const CodeGenerator& codegen_; size_t indent_; @@ -241,51 +348,25 @@ class HGraphVisualizerPrinter : public HGraphVisitor { HGraphVisualizer::HGraphVisualizer(std::ostream* output, HGraph* graph, - const char* string_filter, - const CodeGenerator& codegen, - const DexCompilationUnit& cu) - : output_(output), graph_(graph), codegen_(codegen), is_enabled_(false) { - if (output == nullptr) { - return; - } - std::string pretty_name = PrettyMethod(cu.GetDexMethodIndex(), *cu.GetDexFile()); - if (pretty_name.find(string_filter) == std::string::npos) { - return; - } - - is_enabled_ = true; - HGraphVisualizerPrinter printer(graph, *output_, "", codegen_); - printer.StartTag("compilation"); - printer.PrintProperty("name", pretty_name.c_str()); - printer.PrintProperty("method", pretty_name.c_str()); - printer.PrintTime("date"); - printer.EndTag("compilation"); -} - -HGraphVisualizer::HGraphVisualizer(std::ostream* output, - HGraph* graph, - const CodeGenerator& codegen, - const char* name) - : output_(output), graph_(graph), codegen_(codegen), is_enabled_(false) { - if (output == nullptr) { - return; - } + const CodeGenerator& codegen) + : output_(output), graph_(graph), codegen_(codegen) {} - is_enabled_ = true; - HGraphVisualizerPrinter printer(graph, *output_, "", codegen_); +void HGraphVisualizer::PrintHeader(const char* method_name) const { + DCHECK(output_ != nullptr); + HGraphVisualizerPrinter printer(graph_, *output_, "", true, codegen_); printer.StartTag("compilation"); - printer.PrintProperty("name", name); - printer.PrintProperty("method", name); + printer.PrintProperty("name", method_name); + printer.PrintProperty("method", method_name); printer.PrintTime("date"); printer.EndTag("compilation"); } -void HGraphVisualizer::DumpGraph(const char* pass_name) { - if (!is_enabled_) { - return; +void HGraphVisualizer::DumpGraph(const char* pass_name, bool is_after_pass) const { + DCHECK(output_ != nullptr); + if (!graph_->GetBlocks().IsEmpty()) { + HGraphVisualizerPrinter printer(graph_, *output_, pass_name, is_after_pass, codegen_); + printer.Run(); } - HGraphVisualizerPrinter printer(graph_, *output_, pass_name, codegen_); - printer.Run(); } } // namespace art |