diff options
Diffstat (limited to 'compiler/optimizing/graph_visualizer.cc')
-rw-r--r-- | compiler/optimizing/graph_visualizer.cc | 112 |
1 files changed, 85 insertions, 27 deletions
diff --git a/compiler/optimizing/graph_visualizer.cc b/compiler/optimizing/graph_visualizer.cc index 5f1328f545..b3eff1460d 100644 --- a/compiler/optimizing/graph_visualizer.cc +++ b/compiler/optimizing/graph_visualizer.cc @@ -21,6 +21,8 @@ #include <cctype> #include <sstream> +#include "bounds_check_elimination.h" +#include "builder.h" #include "code_generator.h" #include "dead_code_elimination.h" #include "disassembler.h" @@ -30,7 +32,6 @@ #include "optimization.h" #include "reference_type_propagation.h" #include "register_allocator.h" -#include "ssa_builder.h" #include "ssa_liveness_analysis.h" #include "utils/assembler.h" @@ -177,41 +178,47 @@ class HGraphVisualizerPrinter : public HGraphDelegateVisitor { : nullptr), indent_(0) {} + void Flush() { + // We use "\n" instead of std::endl to avoid implicit flushing which + // generates too many syscalls during debug-GC tests (b/27826765). + output_ << std::flush; + } + void StartTag(const char* name) { AddIndent(); - output_ << "begin_" << name << std::endl; + output_ << "begin_" << name << "\n"; indent_++; } void EndTag(const char* name) { indent_--; AddIndent(); - output_ << "end_" << name << std::endl; + output_ << "end_" << name << "\n"; } void PrintProperty(const char* name, const char* property) { AddIndent(); - output_ << name << " \"" << property << "\"" << std::endl; + output_ << name << " \"" << property << "\"\n"; } void PrintProperty(const char* name, const char* property, int id) { AddIndent(); - output_ << name << " \"" << property << id << "\"" << std::endl; + output_ << name << " \"" << property << id << "\"\n"; } void PrintEmptyProperty(const char* name) { AddIndent(); - output_ << name << std::endl; + output_ << name << "\n"; } void PrintTime(const char* name) { AddIndent(); - output_ << name << " " << time(nullptr) << std::endl; + output_ << name << " " << time(nullptr) << "\n"; } void PrintInt(const char* name, int value) { AddIndent(); - output_ << name << " " << value << std::endl; + output_ << name << " " << value << "\n"; } void AddIndent() { @@ -248,7 +255,7 @@ class HGraphVisualizerPrinter : public HGraphDelegateVisitor { if (block->IsEntryBlock() && (disasm_info_ != nullptr)) { output_ << " \"" << kDisassemblyBlockFrameEntry << "\" "; } - output_<< std::endl; + output_<< "\n"; } void PrintSuccessors(HBasicBlock* block) { @@ -257,7 +264,7 @@ class HGraphVisualizerPrinter : public HGraphDelegateVisitor { for (HBasicBlock* successor : block->GetNormalSuccessors()) { output_ << " \"B" << successor->GetBlockId() << "\" "; } - output_<< std::endl; + output_<< "\n"; } void PrintExceptionHandlers(HBasicBlock* block) { @@ -271,7 +278,7 @@ class HGraphVisualizerPrinter : public HGraphDelegateVisitor { !disasm_info_->GetSlowPathIntervals().empty()) { output_ << " \"" << kDisassemblyBlockSlowPaths << "\" "; } - output_<< std::endl; + output_<< "\n"; } void DumpLocation(std::ostream& stream, const Location& location) { @@ -367,11 +374,13 @@ class HGraphVisualizerPrinter : public HGraphDelegateVisitor { } void VisitCheckCast(HCheckCast* check_cast) OVERRIDE { + StartAttributeStream("check_kind") << check_cast->GetTypeCheckKind(); StartAttributeStream("must_do_null_check") << std::boolalpha << check_cast->MustDoNullCheck() << std::noboolalpha; } void VisitInstanceOf(HInstanceOf* instance_of) OVERRIDE { + StartAttributeStream("check_kind") << instance_of->GetTypeCheckKind(); StartAttributeStream("must_do_null_check") << std::boolalpha << instance_of->MustDoNullCheck() << std::noboolalpha; } @@ -379,6 +388,15 @@ class HGraphVisualizerPrinter : public HGraphDelegateVisitor { void VisitArraySet(HArraySet* array_set) OVERRIDE { StartAttributeStream("value_can_be_null") << std::boolalpha << array_set->GetValueCanBeNull() << std::noboolalpha; + StartAttributeStream("needs_type_check") << std::boolalpha + << array_set->NeedsTypeCheck() << std::noboolalpha; + } + + void VisitCompare(HCompare* compare) OVERRIDE { + ComparisonBias bias = compare->GetBias(); + StartAttributeStream("bias") << (bias == ComparisonBias::kGtBias + ? "gt" + : (bias == ComparisonBias::kLtBias ? "lt" : "none")); } void VisitInvoke(HInvoke* invoke) OVERRIDE { @@ -406,6 +424,20 @@ class HGraphVisualizerPrinter : public HGraphDelegateVisitor { StartAttributeStream("intrinsic") << invoke->GetIntrinsic(); } + void VisitInstanceFieldGet(HInstanceFieldGet* iget) OVERRIDE { + StartAttributeStream("field_name") << PrettyField(iget->GetFieldInfo().GetFieldIndex(), + iget->GetFieldInfo().GetDexFile(), + /* with type */ false); + StartAttributeStream("field_type") << iget->GetFieldType(); + } + + void VisitInstanceFieldSet(HInstanceFieldSet* iset) OVERRIDE { + StartAttributeStream("field_name") << PrettyField(iset->GetFieldInfo().GetFieldIndex(), + iset->GetFieldInfo().GetDexFile(), + /* with type */ false); + StartAttributeStream("field_type") << iset->GetFieldType(); + } + void VisitUnresolvedInstanceFieldGet(HUnresolvedInstanceFieldGet* field_access) OVERRIDE { StartAttributeStream("field_type") << field_access->GetFieldType(); } @@ -426,6 +458,16 @@ class HGraphVisualizerPrinter : public HGraphDelegateVisitor { StartAttributeStream("kind") << (try_boundary->IsEntry() ? "entry" : "exit"); } +#if defined(ART_ENABLE_CODEGEN_arm) || defined(ART_ENABLE_CODEGEN_arm64) + void VisitMultiplyAccumulate(HMultiplyAccumulate* instruction) OVERRIDE { + StartAttributeStream("kind") << instruction->GetOpKind(); + } + + void VisitBitwiseNegatedRight(HBitwiseNegatedRight* instruction) OVERRIDE { + StartAttributeStream("kind") << instruction->GetOpKind(); + } +#endif + #ifdef ART_ENABLE_CODEGEN_arm64 void VisitArm64DataProcWithShifterOp(HArm64DataProcWithShifterOp* instruction) OVERRIDE { StartAttributeStream("kind") << instruction->GetInstrKind() << "+" << instruction->GetOpKind(); @@ -433,10 +475,6 @@ class HGraphVisualizerPrinter : public HGraphDelegateVisitor { StartAttributeStream("shift") << instruction->GetShiftAmount(); } } - - void VisitArm64MultiplyAccumulate(HArm64MultiplyAccumulate* instruction) OVERRIDE { - StartAttributeStream("kind") << instruction->GetOpKind(); - } #endif bool IsPass(const char* name) { @@ -486,7 +524,9 @@ class HGraphVisualizerPrinter : public HGraphDelegateVisitor { StartAttributeStream("is_low") << interval->IsLowInterval(); StartAttributeStream("is_high") << interval->IsHighInterval(); } - } else if (IsPass(RegisterAllocator::kRegisterAllocatorPassName) && is_after_pass_) { + } + + if (IsPass(RegisterAllocator::kRegisterAllocatorPassName) && is_after_pass_) { StartAttributeStream("liveness") << instruction->GetLifetimePosition(); LocationSummary* locations = instruction->GetLocations(); if (locations != nullptr) { @@ -498,15 +538,31 @@ class HGraphVisualizerPrinter : public HGraphDelegateVisitor { attr << inputs << "->"; DumpLocation(attr, locations->Out()); } - } else if (IsPass(LICM::kLoopInvariantCodeMotionPassName) - || IsPass(HDeadCodeElimination::kFinalDeadCodeEliminationPassName)) { + } + + if (IsPass(LICM::kLoopInvariantCodeMotionPassName) + || IsPass(HDeadCodeElimination::kFinalDeadCodeEliminationPassName) + || IsPass(HDeadCodeElimination::kInitialDeadCodeEliminationPassName) + || IsPass(BoundsCheckElimination::kBoundsCheckEliminationPassName) + || IsPass(RegisterAllocator::kRegisterAllocatorPassName) + || IsPass(HGraphBuilder::kBuilderPassName)) { HLoopInformation* info = instruction->GetBlock()->GetLoopInformation(); if (info == nullptr) { StartAttributeStream("loop") << "none"; } else { StartAttributeStream("loop") << "B" << info->GetHeader()->GetBlockId(); + HLoopInformation* outer = info->GetPreHeader()->GetLoopInformation(); + if (outer != nullptr) { + StartAttributeStream("outer_loop") << "B" << outer->GetHeader()->GetBlockId(); + } else { + StartAttributeStream("outer_loop") << "none"; + } + StartAttributeStream("irreducible") + << std::boolalpha << info->IsIrreducible() << std::noboolalpha; } - } else if ((IsPass(SsaBuilder::kSsaBuilderPassName) + } + + if ((IsPass(HGraphBuilder::kBuilderPassName) || IsPass(HInliner::kInlinerPassName)) && (instruction->GetType() == Primitive::kPrimNot)) { ReferenceTypeInfo info = instruction->IsLoadClass() @@ -526,7 +582,7 @@ class HGraphVisualizerPrinter : public HGraphDelegateVisitor { // doesn't run or doesn't inline anything, the NullConstant remains untyped. // So we should check NullConstants for validity only after reference type propagation. DCHECK(graph_in_bad_state_ || - (!is_after_pass_ && IsPass(SsaBuilder::kSsaBuilderPassName))) + (!is_after_pass_ && IsPass(HGraphBuilder::kBuilderPassName))) << instruction->DebugName() << instruction->GetId() << " has invalid rti " << (is_after_pass_ ? "after" : "before") << " pass " << pass_name_; } @@ -538,7 +594,7 @@ class HGraphVisualizerPrinter : public HGraphDelegateVisitor { auto it = disasm_info_->GetInstructionIntervals().find(instruction); if (it != disasm_info_->GetInstructionIntervals().end() && it->second.start != it->second.end) { - output_ << std::endl; + output_ << "\n"; disassembler_->Disassemble(output_, it->second.start, it->second.end); } } @@ -558,7 +614,7 @@ class HGraphVisualizerPrinter : public HGraphDelegateVisitor { output_ << bci << " " << num_uses << " " << GetTypeId(instruction->GetType()) << instruction->GetId() << " "; PrintInstruction(instruction); - output_ << " " << kEndInstructionMarker << std::endl; + output_ << " " << kEndInstructionMarker << "\n"; } } @@ -602,10 +658,10 @@ class HGraphVisualizerPrinter : public HGraphDelegateVisitor { output_ << " 0 0 disasm " << kDisassemblyBlockFrameEntry << " "; GeneratedCodeInterval frame_entry = disasm_info_->GetFrameEntryInterval(); if (frame_entry.start != frame_entry.end) { - output_ << std::endl; + output_ << "\n"; disassembler_->Disassemble(output_, frame_entry.start, frame_entry.end); } - output_ << kEndInstructionMarker << std::endl; + output_ << kEndInstructionMarker << "\n"; DumpEndOfDisassemblyBlock(); } @@ -621,9 +677,9 @@ class HGraphVisualizerPrinter : public HGraphDelegateVisitor { GetGraph()->HasExitBlock() ? GetGraph()->GetExitBlock()->GetBlockId() : -1, -1); for (SlowPathCodeInfo info : disasm_info_->GetSlowPathIntervals()) { - output_ << " 0 0 disasm " << info.slow_path->GetDescription() << std::endl; + output_ << " 0 0 disasm " << info.slow_path->GetDescription() << "\n"; disassembler_->Disassemble(output_, info.code_interval.start, info.code_interval.end); - output_ << kEndInstructionMarker << std::endl; + output_ << kEndInstructionMarker << "\n"; } DumpEndOfDisassemblyBlock(); } @@ -644,6 +700,7 @@ class HGraphVisualizerPrinter : public HGraphDelegateVisitor { DumpDisassemblyBlockForSlowPaths(); } EndTag("cfg"); + Flush(); } void VisitBasicBlock(HBasicBlock* block) OVERRIDE { @@ -683,7 +740,7 @@ class HGraphVisualizerPrinter : public HGraphDelegateVisitor { for (HInputIterator inputs(instruction); !inputs.Done(); inputs.Advance()) { output_ << inputs.Current()->GetId() << " "; } - output_ << "]" << std::endl; + output_ << "]\n"; } EndTag("locals"); EndTag("states"); @@ -725,6 +782,7 @@ void HGraphVisualizer::PrintHeader(const char* method_name) const { printer.PrintProperty("method", method_name); printer.PrintTime("date"); printer.EndTag("compilation"); + printer.Flush(); } void HGraphVisualizer::DumpGraph(const char* pass_name, |