summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--compiler/optimizing/builder.cc12
-rw-r--r--compiler/optimizing/builder.h24
-rw-r--r--compiler/optimizing/codegen_test.cc14
-rw-r--r--compiler/optimizing/dominator_test.cc7
-rw-r--r--compiler/optimizing/find_loops_test.cc5
-rw-r--r--compiler/optimizing/graph_visualizer.cc16
-rw-r--r--compiler/optimizing/graph_visualizer.h5
-rw-r--r--compiler/optimizing/inliner.cc8
-rw-r--r--compiler/optimizing/linearize_test.cc7
-rw-r--r--compiler/optimizing/live_ranges_test.cc5
-rw-r--r--compiler/optimizing/liveness_test.cc7
-rw-r--r--compiler/optimizing/optimization.h2
-rw-r--r--compiler/optimizing/optimizing_compiler.cc158
-rw-r--r--compiler/optimizing/optimizing_unit_test.h7
-rw-r--r--compiler/optimizing/pretty_printer_test.cc7
-rw-r--r--compiler/optimizing/register_allocator_test.cc10
-rw-r--r--compiler/optimizing/ssa_test.cc7
-rw-r--r--compiler/optimizing/suspend_check_test.cc7
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 cb5010a..65456ae 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();