diff options
author | David Brazdil <dbrazdil@google.com> | 2015-02-04 13:51:17 +0000 |
---|---|---|
committer | Gerrit Code Review <noreply-gerritcodereview@google.com> | 2015-02-04 13:51:18 +0000 |
commit | c2024144da54504d819869dc928ce4ac975634d4 (patch) | |
tree | 13948cf9a32333337655f1ea4c3a2886bcea25cb | |
parent | 53150eb4fb5c3bbcb0138b8dccb481726299f6ab (diff) | |
parent | 5e8b137d28c840b128e2488f954cccee3e86db14 (diff) | |
download | art-c2024144da54504d819869dc928ce4ac975634d4.zip art-c2024144da54504d819869dc928ce4ac975634d4.tar.gz art-c2024144da54504d819869dc928ce4ac975634d4.tar.bz2 |
Merge "Create HGraph outside Builder, print timings"
-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 c509606..20a1b03 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 8ee27a1..c510136 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 dfa4748..e0e0b4c 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 3062e37..b246c6f 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 82fe03c..e05d9b3 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 22a3d12..9383d31 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 8d6fe04..bc553ae 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 41e5164..32f6972 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 2ab9b57..eb27965 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 92742f9..0558b85 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 f2d49ac..c9be570 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 9315d89..d9e082a 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 50d7924..38f7daa 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 29d47e1..6b23692 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 a231a72..9cf8235 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 0e49bf2..0cc00c0 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 6b6bf05..7e90b37 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 2e48ee8..a5a0eb2 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(); |