diff options
author | David Brazdil <dbrazdil@google.com> | 2015-01-23 14:39:08 +0000 |
---|---|---|
committer | David Brazdil <dbrazdil@google.com> | 2015-02-04 13:47:49 +0000 |
commit | 5e8b137d28c840b128e2488f954cccee3e86db14 (patch) | |
tree | c56e4c709ce07d605ab4b754e89f7739264feb73 | |
parent | f9af19413333c271192c3b11425f865bd8054c0c (diff) | |
download | android_art-5e8b137d28c840b128e2488f954cccee3e86db14.tar.gz android_art-5e8b137d28c840b128e2488f954cccee3e86db14.tar.bz2 android_art-5e8b137d28c840b128e2488f954cccee3e86db14.zip |
Create HGraph outside Builder, print timings
This patch refactors the way HGraph objects are created, moving the
instantiation out of the Builder class and creating the CodeGenerator
earlier. The patch uses this to build a single interface for printing
timings info and dumping the CFG.
Change-Id: I2eb63eabf28e2d0f5cdc7affaa690c3a4b1bdd21
-rw-r--r-- | compiler/optimizing/builder.cc | 12 | ||||
-rw-r--r-- | compiler/optimizing/builder.h | 24 | ||||
-rw-r--r-- | compiler/optimizing/codegen_test.cc | 14 | ||||
-rw-r--r-- | compiler/optimizing/dominator_test.cc | 7 | ||||
-rw-r--r-- | compiler/optimizing/find_loops_test.cc | 5 | ||||
-rw-r--r-- | compiler/optimizing/graph_visualizer.cc | 16 | ||||
-rw-r--r-- | compiler/optimizing/graph_visualizer.h | 5 | ||||
-rw-r--r-- | compiler/optimizing/inliner.cc | 8 | ||||
-rw-r--r-- | compiler/optimizing/linearize_test.cc | 7 | ||||
-rw-r--r-- | compiler/optimizing/live_ranges_test.cc | 5 | ||||
-rw-r--r-- | compiler/optimizing/liveness_test.cc | 7 | ||||
-rw-r--r-- | compiler/optimizing/optimization.h | 2 | ||||
-rw-r--r-- | compiler/optimizing/optimizing_compiler.cc | 158 | ||||
-rw-r--r-- | compiler/optimizing/optimizing_unit_test.h | 7 | ||||
-rw-r--r-- | compiler/optimizing/pretty_printer_test.cc | 7 | ||||
-rw-r--r-- | compiler/optimizing/register_allocator_test.cc | 10 | ||||
-rw-r--r-- | compiler/optimizing/ssa_test.cc | 7 | ||||
-rw-r--r-- | compiler/optimizing/suspend_check_test.cc | 7 |
18 files changed, 199 insertions, 109 deletions
diff --git a/compiler/optimizing/builder.cc b/compiler/optimizing/builder.cc index c50960666a..20a1b03a67 100644 --- a/compiler/optimizing/builder.cc +++ b/compiler/optimizing/builder.cc @@ -259,13 +259,14 @@ bool HGraphBuilder::SkipCompilation(size_t number_of_dex_instructions, return false; } -HGraph* HGraphBuilder::BuildGraph(const DexFile::CodeItem& code_item, int start_instruction_id) { +bool HGraphBuilder::BuildGraph(const DexFile::CodeItem& code_item) { + DCHECK(graph_->GetBlocks().IsEmpty()); + const uint16_t* code_ptr = code_item.insns_; const uint16_t* code_end = code_item.insns_ + code_item.insns_size_in_code_units_; code_start_ = code_ptr; // Setup the graph with the entry block and exit block. - graph_ = new (arena_) HGraph(arena_, start_instruction_id); entry_block_ = new (arena_) HBasicBlock(graph_, 0); graph_->AddBlock(entry_block_); exit_block_ = new (arena_) HBasicBlock(graph_, kNoDexPc); @@ -289,7 +290,7 @@ HGraph* HGraphBuilder::BuildGraph(const DexFile::CodeItem& code_item, int start_ // Note that the compiler driver is null when unit testing. if ((compiler_driver_ != nullptr) && SkipCompilation(number_of_dex_instructions, number_of_blocks, number_of_branches)) { - return nullptr; + return false; } // Also create blocks for catch handlers. @@ -319,7 +320,7 @@ HGraph* HGraphBuilder::BuildGraph(const DexFile::CodeItem& code_item, int start_ MaybeUpdateCurrentBlock(dex_pc); const Instruction& instruction = *Instruction::At(code_ptr); if (!AnalyzeDexInstruction(instruction, dex_pc)) { - return nullptr; + return false; } dex_pc += instruction.SizeInCodeUnits(); code_ptr += instruction.SizeInCodeUnits(); @@ -331,7 +332,8 @@ HGraph* HGraphBuilder::BuildGraph(const DexFile::CodeItem& code_item, int start_ // Add the suspend check to the entry block. entry_block_->AddInstruction(new (arena_) HSuspendCheck(0)); entry_block_->AddInstruction(new (arena_) HGoto()); - return graph_; + + return true; } void HGraphBuilder::MaybeUpdateCurrentBlock(size_t index) { diff --git a/compiler/optimizing/builder.h b/compiler/optimizing/builder.h index 8ee27a1b35..c5101363ee 100644 --- a/compiler/optimizing/builder.h +++ b/compiler/optimizing/builder.h @@ -34,19 +34,19 @@ class SwitchTable; class HGraphBuilder : public ValueObject { public: - HGraphBuilder(ArenaAllocator* arena, + HGraphBuilder(HGraph* graph, DexCompilationUnit* dex_compilation_unit, const DexCompilationUnit* const outer_compilation_unit, const DexFile* dex_file, CompilerDriver* driver, OptimizingCompilerStats* compiler_stats) - : arena_(arena), - branch_targets_(arena, 0), - locals_(arena, 0), + : arena_(graph->GetArena()), + branch_targets_(graph->GetArena(), 0), + locals_(graph->GetArena(), 0), entry_block_(nullptr), exit_block_(nullptr), current_block_(nullptr), - graph_(nullptr), + graph_(graph), constant0_(nullptr), constant1_(nullptr), dex_file_(dex_file), @@ -59,14 +59,14 @@ class HGraphBuilder : public ValueObject { compilation_stats_(compiler_stats) {} // Only for unit testing. - HGraphBuilder(ArenaAllocator* arena, Primitive::Type return_type = Primitive::kPrimInt) - : arena_(arena), - branch_targets_(arena, 0), - locals_(arena, 0), + HGraphBuilder(HGraph* graph, Primitive::Type return_type = Primitive::kPrimInt) + : arena_(graph->GetArena()), + branch_targets_(graph->GetArena(), 0), + locals_(graph->GetArena(), 0), entry_block_(nullptr), exit_block_(nullptr), current_block_(nullptr), - graph_(nullptr), + graph_(graph), constant0_(nullptr), constant1_(nullptr), dex_file_(nullptr), @@ -78,7 +78,7 @@ class HGraphBuilder : public ValueObject { latest_result_(nullptr), compilation_stats_(nullptr) {} - HGraph* BuildGraph(const DexFile::CodeItem& code, int start_instruction_id = 0); + bool BuildGraph(const DexFile::CodeItem& code); private: // Analyzes the dex instruction and adds HInstruction to the graph @@ -249,7 +249,7 @@ class HGraphBuilder : public ValueObject { HBasicBlock* entry_block_; HBasicBlock* exit_block_; HBasicBlock* current_block_; - HGraph* graph_; + HGraph* const graph_; HIntConstant* constant0_; HIntConstant* constant1_; diff --git a/compiler/optimizing/codegen_test.cc b/compiler/optimizing/codegen_test.cc index dfa4748811..e0e0b4c3e8 100644 --- a/compiler/optimizing/codegen_test.cc +++ b/compiler/optimizing/codegen_test.cc @@ -180,10 +180,11 @@ static void RunCodeOptimized(HGraph* graph, static void TestCode(const uint16_t* data, bool has_result = false, int32_t expected = 0) { ArenaPool pool; ArenaAllocator arena(&pool); - HGraphBuilder builder(&arena); + HGraph* graph = new (&arena) HGraph(&arena); + HGraphBuilder builder(graph); const DexFile::CodeItem* item = reinterpret_cast<const DexFile::CodeItem*>(data); - HGraph* graph = builder.BuildGraph(*item); - ASSERT_NE(graph, nullptr); + bool graph_built = builder.BuildGraph(*item); + ASSERT_TRUE(graph_built); // Remove suspend checks, they cannot be executed in this context. RemoveSuspendChecks(graph); RunCodeBaseline(graph, has_result, expected); @@ -192,10 +193,11 @@ static void TestCode(const uint16_t* data, bool has_result = false, int32_t expe static void TestCodeLong(const uint16_t* data, bool has_result, int64_t expected) { ArenaPool pool; ArenaAllocator arena(&pool); - HGraphBuilder builder(&arena, Primitive::kPrimLong); + HGraph* graph = new (&arena) HGraph(&arena); + HGraphBuilder builder(graph, Primitive::kPrimLong); const DexFile::CodeItem* item = reinterpret_cast<const DexFile::CodeItem*>(data); - HGraph* graph = builder.BuildGraph(*item); - ASSERT_NE(graph, nullptr); + bool graph_built = builder.BuildGraph(*item); + ASSERT_TRUE(graph_built); // Remove suspend checks, they cannot be executed in this context. RemoveSuspendChecks(graph); RunCodeBaseline(graph, has_result, expected); diff --git a/compiler/optimizing/dominator_test.cc b/compiler/optimizing/dominator_test.cc index 3062e3751d..b246c6f98d 100644 --- a/compiler/optimizing/dominator_test.cc +++ b/compiler/optimizing/dominator_test.cc @@ -27,10 +27,11 @@ namespace art { static void TestCode(const uint16_t* data, const int* blocks, size_t blocks_length) { ArenaPool pool; ArenaAllocator allocator(&pool); - HGraphBuilder builder(&allocator); + HGraph* graph = new (&allocator) HGraph(&allocator); + HGraphBuilder builder(graph); const DexFile::CodeItem* item = reinterpret_cast<const DexFile::CodeItem*>(data); - HGraph* graph = builder.BuildGraph(*item); - ASSERT_NE(graph, nullptr); + bool graph_built = builder.BuildGraph(*item); + ASSERT_TRUE(graph_built); graph->BuildDominatorTree(); ASSERT_EQ(graph->GetBlocks().Size(), blocks_length); for (size_t i = 0, e = blocks_length; i < e; ++i) { diff --git a/compiler/optimizing/find_loops_test.cc b/compiler/optimizing/find_loops_test.cc index 82fe03caa2..e05d9b3b0f 100644 --- a/compiler/optimizing/find_loops_test.cc +++ b/compiler/optimizing/find_loops_test.cc @@ -28,9 +28,10 @@ namespace art { static HGraph* TestCode(const uint16_t* data, ArenaAllocator* allocator) { - HGraphBuilder builder(allocator); + HGraph* graph = new (allocator) HGraph(allocator); + HGraphBuilder builder(graph); const DexFile::CodeItem* item = reinterpret_cast<const DexFile::CodeItem*>(data); - HGraph* graph = builder.BuildGraph(*item); + builder.BuildGraph(*item); graph->BuildDominatorTree(); graph->AnalyzeNaturalLoops(); return graph; diff --git a/compiler/optimizing/graph_visualizer.cc b/compiler/optimizing/graph_visualizer.cc index 22a3d124f1..9383d31e8f 100644 --- a/compiler/optimizing/graph_visualizer.cc +++ b/compiler/optimizing/graph_visualizer.cc @@ -194,7 +194,9 @@ class HGraphVisualizerPrinter : public HGraphVisitor { } output_ << "]"; } - if (pass_name_ == kLivenessPassName && instruction->GetLifetimePosition() != kNoLifetime) { + if (pass_name_ == kLivenessPassName + && is_after_pass_ + && instruction->GetLifetimePosition() != kNoLifetime) { output_ << " (liveness: " << instruction->GetLifetimePosition(); if (instruction->HasLiveInterval()) { output_ << " "; @@ -202,7 +204,7 @@ class HGraphVisualizerPrinter : public HGraphVisitor { interval.Dump(output_); } output_ << ")"; - } else if (pass_name_ == kRegisterAllocatorPassName) { + } else if (pass_name_ == kRegisterAllocatorPassName && is_after_pass_) { LocationSummary* locations = instruction->GetLocations(); if (locations != nullptr) { output_ << " ( "; @@ -310,18 +312,13 @@ class HGraphVisualizerPrinter : public HGraphVisitor { HGraphVisualizer::HGraphVisualizer(std::ostream* output, HGraph* graph, - const char* string_filter, const CodeGenerator& codegen, const char* method_name) - : output_(output), graph_(graph), codegen_(codegen), is_enabled_(false) { + : output_(output), graph_(graph), codegen_(codegen) { if (output == nullptr) { return; } - if (strstr(method_name, string_filter) == nullptr) { - return; - } - is_enabled_ = true; HGraphVisualizerPrinter printer(graph_, *output_, "", true, codegen_); printer.StartTag("compilation"); printer.PrintProperty("name", method_name); @@ -331,7 +328,8 @@ HGraphVisualizer::HGraphVisualizer(std::ostream* output, } void HGraphVisualizer::DumpGraph(const char* pass_name, bool is_after_pass) const { - if (is_enabled_) { + DCHECK(output_ != nullptr); + if (!graph_->GetBlocks().IsEmpty()) { HGraphVisualizerPrinter printer(graph_, *output_, pass_name, is_after_pass, codegen_); printer.Run(); } diff --git a/compiler/optimizing/graph_visualizer.h b/compiler/optimizing/graph_visualizer.h index 8d6fe04c2b..bc553aed74 100644 --- a/compiler/optimizing/graph_visualizer.h +++ b/compiler/optimizing/graph_visualizer.h @@ -35,7 +35,6 @@ class HGraphVisualizer : public ValueObject { public: HGraphVisualizer(std::ostream* output, HGraph* graph, - const char* string_filter, const CodeGenerator& codegen, const char* method_name); @@ -46,10 +45,6 @@ class HGraphVisualizer : public ValueObject { HGraph* const graph_; const CodeGenerator& codegen_; - // Is true when `output_` is not null, and the compiled method's name - // contains the string_filter given in the constructor. - bool is_enabled_; - DISALLOW_COPY_AND_ASSIGN(HGraphVisualizer); }; diff --git a/compiler/optimizing/inliner.cc b/compiler/optimizing/inliner.cc index 41e516492a..32f6972c84 100644 --- a/compiler/optimizing/inliner.cc +++ b/compiler/optimizing/inliner.cc @@ -124,16 +124,18 @@ bool HInliner::TryInline(HInvoke* invoke_instruction, resolved_method->GetAccessFlags(), nullptr); + HGraph* callee_graph = + new (graph_->GetArena()) HGraph(graph_->GetArena(), graph_->GetCurrentInstructionId()); + OptimizingCompilerStats inline_stats; - HGraphBuilder builder(graph_->GetArena(), + HGraphBuilder builder(callee_graph, &dex_compilation_unit, &outer_compilation_unit_, &outer_dex_file, compiler_driver_, &inline_stats); - HGraph* callee_graph = builder.BuildGraph(*code_item, graph_->GetCurrentInstructionId()); - if (callee_graph == nullptr) { + if (!builder.BuildGraph(*code_item)) { VLOG(compiler) << "Method " << PrettyMethod(method_index, outer_dex_file) << " could not be built, so cannot be inlined"; return false; diff --git a/compiler/optimizing/linearize_test.cc b/compiler/optimizing/linearize_test.cc index 2ab9b571ff..eb27965c79 100644 --- a/compiler/optimizing/linearize_test.cc +++ b/compiler/optimizing/linearize_test.cc @@ -38,10 +38,11 @@ namespace art { static void TestCode(const uint16_t* data, const int* expected_order, size_t number_of_blocks) { ArenaPool pool; ArenaAllocator allocator(&pool); - HGraphBuilder builder(&allocator); + HGraph* graph = new (&allocator) HGraph(&allocator); + HGraphBuilder builder(graph); const DexFile::CodeItem* item = reinterpret_cast<const DexFile::CodeItem*>(data); - HGraph* graph = builder.BuildGraph(*item); - ASSERT_NE(graph, nullptr); + bool graph_built = builder.BuildGraph(*item); + ASSERT_TRUE(graph_built); graph->TryBuildingSsa(); diff --git a/compiler/optimizing/live_ranges_test.cc b/compiler/optimizing/live_ranges_test.cc index 92742f9a06..0558b85b47 100644 --- a/compiler/optimizing/live_ranges_test.cc +++ b/compiler/optimizing/live_ranges_test.cc @@ -31,9 +31,10 @@ namespace art { static HGraph* BuildGraph(const uint16_t* data, ArenaAllocator* allocator) { - HGraphBuilder builder(allocator); + HGraph* graph = new (allocator) HGraph(allocator); + HGraphBuilder builder(graph); const DexFile::CodeItem* item = reinterpret_cast<const DexFile::CodeItem*>(data); - HGraph* graph = builder.BuildGraph(*item); + builder.BuildGraph(*item); // Suspend checks implementation may change in the future, and this test relies // on how instructions are ordered. RemoveSuspendChecks(graph); diff --git a/compiler/optimizing/liveness_test.cc b/compiler/optimizing/liveness_test.cc index f2d49ac397..c9be570c73 100644 --- a/compiler/optimizing/liveness_test.cc +++ b/compiler/optimizing/liveness_test.cc @@ -45,10 +45,11 @@ static void DumpBitVector(BitVector* vector, static void TestCode(const uint16_t* data, const char* expected) { ArenaPool pool; ArenaAllocator allocator(&pool); - HGraphBuilder builder(&allocator); + HGraph* graph = new (&allocator) HGraph(&allocator); + HGraphBuilder builder(graph); const DexFile::CodeItem* item = reinterpret_cast<const DexFile::CodeItem*>(data); - HGraph* graph = builder.BuildGraph(*item); - ASSERT_NE(graph, nullptr); + bool graph_built = builder.BuildGraph(*item); + ASSERT_TRUE(graph_built); graph->TryBuildingSsa(); // `Inline` conditions into ifs. PrepareForRegisterAllocation(graph).Run(); diff --git a/compiler/optimizing/optimization.h b/compiler/optimizing/optimization.h index 9315d89a4a..d9e082a7f3 100644 --- a/compiler/optimizing/optimization.h +++ b/compiler/optimizing/optimization.h @@ -21,6 +21,8 @@ namespace art { +static const char* kBuilderPassName = "builder"; +static const char* kSsaBuilderPassName = "ssa_builder"; static const char* kLivenessPassName = "liveness"; static const char* kRegisterAllocatorPassName = "register"; static const char* kLoopInvariantCodeMotionPassName = "licm"; diff --git a/compiler/optimizing/optimizing_compiler.cc b/compiler/optimizing/optimizing_compiler.cc index 50d7924186..38f7daac40 100644 --- a/compiler/optimizing/optimizing_compiler.cc +++ b/compiler/optimizing/optimizing_compiler.cc @@ -19,6 +19,8 @@ #include <fstream> #include <stdint.h> +#include "base/dumpable.h" +#include "base/timing_logger.h" #include "bounds_check_elimination.h" #include "builder.h" #include "code_generator.h" @@ -78,6 +80,70 @@ class CodeVectorAllocator FINAL : public CodeAllocator { */ static const char* kStringFilter = ""; +class PassInfoPrinter : public ValueObject { + public: + PassInfoPrinter(HGraph* graph, + const char* method_name, + const CodeGenerator& codegen, + std::ostream* visualizer_output, + bool timing_logger_enabled, + bool visualizer_enabled) + : method_name_(method_name), + timing_logger_enabled_(timing_logger_enabled), + timing_logger_running_(false), + timing_logger_(method_name, true, true), + visualizer_enabled_(visualizer_enabled), + visualizer_(visualizer_output, graph, codegen, method_name_) { + if (strstr(method_name, kStringFilter) == nullptr) { + timing_logger_enabled_ = visualizer_enabled_ = false; + } + } + + void BeforePass(const char* pass_name) { + // Dump graph first, then start timer. + if (visualizer_enabled_) { + visualizer_.DumpGraph(pass_name, /* is_after_pass */ false); + } + if (timing_logger_enabled_) { + DCHECK(!timing_logger_running_); + timing_logger_running_ = true; + timing_logger_.StartTiming(pass_name); + } + } + + void AfterPass(const char* pass_name) { + // Pause timer first, then dump graph. + if (timing_logger_enabled_) { + DCHECK(timing_logger_running_); + timing_logger_.EndTiming(); + timing_logger_running_ = false; + } + if (visualizer_enabled_) { + visualizer_.DumpGraph(pass_name, /* is_after_pass */ true); + } + } + + ~PassInfoPrinter() { + if (timing_logger_enabled_) { + DCHECK(!timing_logger_running_); + LOG(INFO) << "TIMINGS " << method_name_; + LOG(INFO) << Dumpable<TimingLogger>(timing_logger_); + } + } + + private: + const char* method_name_; + + bool timing_logger_enabled_; + bool timing_logger_running_; + TimingLogger timing_logger_; + + bool visualizer_enabled_; + HGraphVisualizer visualizer_; + + DISALLOW_COPY_AND_ASSIGN(PassInfoPrinter); +}; + class OptimizingCompiler FINAL : public Compiler { public: explicit OptimizingCompiler(CompilerDriver* driver); @@ -123,7 +189,7 @@ class OptimizingCompiler FINAL : public Compiler { CodeGenerator* codegen, CompilerDriver* driver, const DexCompilationUnit& dex_compilation_unit, - const HGraphVisualizer& visualizer) const; + PassInfoPrinter* pass_info) const; // Just compile without doing optimizations. CompiledMethod* CompileBaseline(CodeGenerator* codegen, @@ -200,12 +266,12 @@ static bool CanOptimize(const DexFile::CodeItem& code_item) { static void RunOptimizations(HOptimization* optimizations[], size_t length, - const HGraphVisualizer& visualizer) { + PassInfoPrinter* pass_info) { for (size_t i = 0; i < length; ++i) { HOptimization* optimization = optimizations[i]; - visualizer.DumpGraph(optimization->GetPassName(), /*is_after=*/false); + pass_info->BeforePass(optimization->GetPassName()); optimization->Run(); - visualizer.DumpGraph(optimization->GetPassName(), /*is_after=*/true); + pass_info->AfterPass(optimization->GetPassName()); optimization->Check(); } } @@ -214,7 +280,7 @@ static void RunOptimizations(HGraph* graph, CompilerDriver* driver, OptimizingCompilerStats* stats, const DexCompilationUnit& dex_compilation_unit, - const HGraphVisualizer& visualizer) { + PassInfoPrinter* pass_info) { SsaRedundantPhiElimination redundant_phi(graph); SsaDeadPhiElimination dead_phi(graph); HDeadCodeElimination dce(graph); @@ -250,7 +316,7 @@ static void RunOptimizations(HGraph* graph, &simplify2 }; - RunOptimizations(optimizations, arraysize(optimizations), visualizer); + RunOptimizations(optimizations, arraysize(optimizations), pass_info); } // The stack map we generate must be 4-byte aligned on ARM. Since existing @@ -269,18 +335,20 @@ CompiledMethod* OptimizingCompiler::CompileOptimized(HGraph* graph, CodeGenerator* codegen, CompilerDriver* compiler_driver, const DexCompilationUnit& dex_compilation_unit, - const HGraphVisualizer& visualizer) const { + PassInfoPrinter* pass_info) const { RunOptimizations( - graph, compiler_driver, &compilation_stats_, dex_compilation_unit, visualizer); + graph, compiler_driver, &compilation_stats_, dex_compilation_unit, pass_info); + pass_info->BeforePass(kLivenessPassName); PrepareForRegisterAllocation(graph).Run(); SsaLivenessAnalysis liveness(*graph, codegen); liveness.Analyze(); - visualizer.DumpGraph(kLivenessPassName); + pass_info->AfterPass(kLivenessPassName); + pass_info->BeforePass(kRegisterAllocatorPassName); RegisterAllocator register_allocator(graph->GetArena(), codegen, liveness); register_allocator.AllocateRegisters(); - visualizer.DumpGraph(kRegisterAllocatorPassName); + pass_info->AfterPass(kRegisterAllocatorPassName); CodeVectorAllocator allocator; codegen->CompileOptimized(&allocator); @@ -339,6 +407,7 @@ CompiledMethod* OptimizingCompiler::Compile(const DexFile::CodeItem* code_item, jobject class_loader, const DexFile& dex_file) const { UNUSED(invoke_type); + std::string method_name = PrettyMethod(method_idx, dex_file); compilation_stats_.RecordStat(MethodCompilationStat::kAttemptCompilation); CompilerDriver* compiler_driver = GetCompilerDriver(); InstructionSet instruction_set = compiler_driver->GetInstructionSet(); @@ -364,29 +433,15 @@ CompiledMethod* OptimizingCompiler::Compile(const DexFile::CodeItem* code_item, class_def_idx, method_idx, access_flags, compiler_driver->GetVerifiedMethod(&dex_file, method_idx)); - std::string method_name = PrettyMethod(method_idx, dex_file); + ArenaPool pool; + ArenaAllocator arena(&pool); + HGraph* graph = new (&arena) HGraph(&arena); // For testing purposes, we put a special marker on method names that should be compiled // with this compiler. This makes sure we're not regressing. bool shouldCompile = method_name.find("$opt$") != std::string::npos; bool shouldOptimize = method_name.find("$opt$reg$") != std::string::npos; - ArenaPool pool; - ArenaAllocator arena(&pool); - HGraphBuilder builder(&arena, - &dex_compilation_unit, - &dex_compilation_unit, - &dex_file, - compiler_driver, - &compilation_stats_); - - VLOG(compiler) << "Building " << PrettyMethod(method_idx, dex_file); - HGraph* graph = builder.BuildGraph(*code_item); - if (graph == nullptr) { - CHECK(!shouldCompile) << "Could not build graph in optimizing compiler"; - return nullptr; - } - std::unique_ptr<CodeGenerator> codegen( CodeGenerator::Create(graph, instruction_set, @@ -398,29 +453,53 @@ CompiledMethod* OptimizingCompiler::Compile(const DexFile::CodeItem* code_item, return nullptr; } - HGraphVisualizer visualizer( - visualizer_output_.get(), graph, kStringFilter, *codegen.get(), method_name.c_str()); - visualizer.DumpGraph("builder"); + PassInfoPrinter pass_info(graph, + method_name.c_str(), + *codegen.get(), + visualizer_output_.get(), + GetCompilerDriver()->GetDumpPasses(), + !GetCompilerDriver()->GetDumpCfgFileName().empty()); + + HGraphBuilder builder(graph, + &dex_compilation_unit, + &dex_compilation_unit, + &dex_file, + compiler_driver, + &compilation_stats_); + + VLOG(compiler) << "Building " << method_name; + + pass_info.BeforePass(kBuilderPassName); + if (!builder.BuildGraph(*code_item)) { + CHECK(!shouldCompile) << "Could not build graph in optimizing compiler"; + return nullptr; + } + pass_info.AfterPass(kBuilderPassName); bool can_optimize = CanOptimize(*code_item); bool can_allocate_registers = RegisterAllocator::CanAllocateRegistersFor(*graph, instruction_set); - CompiledMethod* result = nullptr; if (run_optimizations_ && can_optimize && can_allocate_registers) { - VLOG(compiler) << "Optimizing " << PrettyMethod(method_idx, dex_file); + VLOG(compiler) << "Optimizing " << method_name; + + pass_info.BeforePass(kSsaBuilderPassName); if (!graph->TryBuildingSsa()) { - LOG(INFO) << "Skipping compilation of " - << PrettyMethod(method_idx, dex_file) - << ": it contains a non natural loop"; // We could not transform the graph to SSA, bailout. + LOG(INFO) << "Skipping compilation of " << method_name << ": it contains a non natural loop"; compilation_stats_.RecordStat(MethodCompilationStat::kNotCompiledCannotBuildSSA); - } else { - result = CompileOptimized(graph, codegen.get(), compiler_driver, dex_compilation_unit, visualizer); + return nullptr; } + pass_info.AfterPass(kSsaBuilderPassName); + + return CompileOptimized(graph, + codegen.get(), + compiler_driver, + dex_compilation_unit, + &pass_info); } else if (shouldOptimize && RegisterAllocator::Supports(instruction_set)) { LOG(FATAL) << "Could not allocate registers in optimizing compiler"; UNREACHABLE(); } else { - VLOG(compiler) << "Compile baseline " << PrettyMethod(method_idx, dex_file); + VLOG(compiler) << "Compile baseline " << method_name; if (!run_optimizations_) { compilation_stats_.RecordStat(MethodCompilationStat::kNotOptimizedDisabled); @@ -430,9 +509,8 @@ CompiledMethod* OptimizingCompiler::Compile(const DexFile::CodeItem* code_item, compilation_stats_.RecordStat(MethodCompilationStat::kNotOptimizedRegisterAllocator); } - result = CompileBaseline(codegen.get(), compiler_driver, dex_compilation_unit); + return CompileBaseline(codegen.get(), compiler_driver, dex_compilation_unit); } - return result; } Compiler* CreateOptimizingCompiler(CompilerDriver* driver) { diff --git a/compiler/optimizing/optimizing_unit_test.h b/compiler/optimizing/optimizing_unit_test.h index 29d47e13cc..6b236927da 100644 --- a/compiler/optimizing/optimizing_unit_test.h +++ b/compiler/optimizing/optimizing_unit_test.h @@ -76,11 +76,12 @@ void RemoveSuspendChecks(HGraph* graph) { inline HGraph* CreateCFG(ArenaAllocator* allocator, const uint16_t* data, Primitive::Type return_type = Primitive::kPrimInt) { - HGraphBuilder builder(allocator, return_type); + HGraph* graph = new (allocator) HGraph(allocator); + HGraphBuilder builder(graph, return_type); const DexFile::CodeItem* item = reinterpret_cast<const DexFile::CodeItem*>(data); - HGraph* graph = builder.BuildGraph(*item); - return graph; + bool graph_built = builder.BuildGraph(*item); + return graph_built ? graph : nullptr; } // Naive string diff data type. diff --git a/compiler/optimizing/pretty_printer_test.cc b/compiler/optimizing/pretty_printer_test.cc index a231a72f05..9cf8235d85 100644 --- a/compiler/optimizing/pretty_printer_test.cc +++ b/compiler/optimizing/pretty_printer_test.cc @@ -30,10 +30,11 @@ namespace art { static void TestCode(const uint16_t* data, const char* expected) { ArenaPool pool; ArenaAllocator allocator(&pool); - HGraphBuilder builder(&allocator); + HGraph* graph = new (&allocator) HGraph(&allocator); + HGraphBuilder builder(graph); const DexFile::CodeItem* item = reinterpret_cast<const DexFile::CodeItem*>(data); - HGraph* graph = builder.BuildGraph(*item); - ASSERT_NE(graph, nullptr); + bool graph_built = builder.BuildGraph(*item); + ASSERT_TRUE(graph_built); StringPrettyPrinter printer(graph); printer.VisitInsertionOrder(); ASSERT_STREQ(expected, printer.str().c_str()); diff --git a/compiler/optimizing/register_allocator_test.cc b/compiler/optimizing/register_allocator_test.cc index cb5010afcd..65456ae5bd 100644 --- a/compiler/optimizing/register_allocator_test.cc +++ b/compiler/optimizing/register_allocator_test.cc @@ -37,9 +37,10 @@ namespace art { static bool Check(const uint16_t* data) { ArenaPool pool; ArenaAllocator allocator(&pool); - HGraphBuilder builder(&allocator); + HGraph* graph = new (&allocator) HGraph(&allocator); + HGraphBuilder builder(graph); const DexFile::CodeItem* item = reinterpret_cast<const DexFile::CodeItem*>(data); - HGraph* graph = builder.BuildGraph(*item); + builder.BuildGraph(*item); graph->TryBuildingSsa(); x86::CodeGeneratorX86 codegen(graph, CompilerOptions()); SsaLivenessAnalysis liveness(*graph, &codegen); @@ -249,9 +250,10 @@ TEST(RegisterAllocatorTest, Loop2) { } static HGraph* BuildSSAGraph(const uint16_t* data, ArenaAllocator* allocator) { - HGraphBuilder builder(allocator); + HGraph* graph = new (allocator) HGraph(allocator); + HGraphBuilder builder(graph); const DexFile::CodeItem* item = reinterpret_cast<const DexFile::CodeItem*>(data); - HGraph* graph = builder.BuildGraph(*item); + builder.BuildGraph(*item); graph->TryBuildingSsa(); return graph; } diff --git a/compiler/optimizing/ssa_test.cc b/compiler/optimizing/ssa_test.cc index 6b6bf05053..7e90b37fe6 100644 --- a/compiler/optimizing/ssa_test.cc +++ b/compiler/optimizing/ssa_test.cc @@ -78,10 +78,11 @@ static void ReNumberInstructions(HGraph* graph) { static void TestCode(const uint16_t* data, const char* expected) { ArenaPool pool; ArenaAllocator allocator(&pool); - HGraphBuilder builder(&allocator); + HGraph* graph = new (&allocator) HGraph(&allocator); + HGraphBuilder builder(graph); const DexFile::CodeItem* item = reinterpret_cast<const DexFile::CodeItem*>(data); - HGraph* graph = builder.BuildGraph(*item); - ASSERT_NE(graph, nullptr); + bool graph_built = builder.BuildGraph(*item); + ASSERT_TRUE(graph_built); graph->BuildDominatorTree(); // Suspend checks implementation may change in the future, and this test relies diff --git a/compiler/optimizing/suspend_check_test.cc b/compiler/optimizing/suspend_check_test.cc index 2e48ee8e7e..a5a0eb2114 100644 --- a/compiler/optimizing/suspend_check_test.cc +++ b/compiler/optimizing/suspend_check_test.cc @@ -30,10 +30,11 @@ namespace art { static void TestCode(const uint16_t* data) { ArenaPool pool; ArenaAllocator allocator(&pool); - HGraphBuilder builder(&allocator); + HGraph* graph = new (&allocator) HGraph(&allocator); + HGraphBuilder builder(graph); const DexFile::CodeItem* item = reinterpret_cast<const DexFile::CodeItem*>(data); - HGraph* graph = builder.BuildGraph(*item); - ASSERT_NE(graph, nullptr); + bool graph_built = builder.BuildGraph(*item); + ASSERT_TRUE(graph_built); HBasicBlock* first_block = graph->GetEntryBlock()->GetSuccessors().Get(0); HInstruction* first_instruction = first_block->GetFirstInstruction(); |