summaryrefslogtreecommitdiff
path: root/compiler/optimizing/optimizing_compiler.cc
diff options
context:
space:
mode:
authorDavid Brazdil <dbrazdil@google.com>2015-06-23 18:27:30 +0100
committerDavid Brazdil <dbrazdil@google.com>2015-06-24 15:02:15 +0100
commit69ba7b7112c2277ac225615b37e6df74c055740d (patch)
tree3177340740abfabd80f055b17ab92fb6e740bd87 /compiler/optimizing/optimizing_compiler.cc
parentb809daaffdd42dc01457ae06ae83f2d7ebdb5e65 (diff)
ART: Run GraphChecker after Builder and SsaBuilder
This patch refactors the way GraphChecker is invoked, utilizing the same scoping mechanism as pass timing and graph visualizer. Therefore, GraphChecker will now run not just after instances of HOptimization but after the builders and reg alloc, too. Change-Id: I8173b98b79afa95e1fcbf3ac9630a873d7f6c1d4
Diffstat (limited to 'compiler/optimizing/optimizing_compiler.cc')
-rw-r--r--compiler/optimizing/optimizing_compiler.cc122
1 files changed, 74 insertions, 48 deletions
diff --git a/compiler/optimizing/optimizing_compiler.cc b/compiler/optimizing/optimizing_compiler.cc
index 0c7b6f7093..146636675a 100644
--- a/compiler/optimizing/optimizing_compiler.cc
+++ b/compiler/optimizing/optimizing_compiler.cc
@@ -38,6 +38,7 @@
#include "driver/compiler_options.h"
#include "driver/dex_compilation_unit.h"
#include "elf_writer_quick.h"
+#include "graph_checker.h"
#include "graph_visualizer.h"
#include "gvn.h"
#include "inliner.h"
@@ -86,21 +87,23 @@ class CodeVectorAllocator FINAL : public CodeAllocator {
*/
static const char* kStringFilter = "";
-class PassInfo;
+class PassScope;
-class PassInfoPrinter : public ValueObject {
+class PassObserver : public ValueObject {
public:
- PassInfoPrinter(HGraph* graph,
- const char* method_name,
- CodeGenerator* codegen,
- std::ostream* visualizer_output,
- CompilerDriver* compiler_driver)
- : method_name_(method_name),
+ PassObserver(HGraph* graph,
+ const char* method_name,
+ CodeGenerator* codegen,
+ std::ostream* visualizer_output,
+ CompilerDriver* compiler_driver)
+ : graph_(graph),
+ method_name_(method_name),
timing_logger_enabled_(compiler_driver->GetDumpPasses()),
timing_logger_(method_name, true, true),
disasm_info_(graph->GetArena()),
visualizer_enabled_(!compiler_driver->GetDumpCfgFileName().empty()),
- visualizer_(visualizer_output, graph, *codegen) {
+ visualizer_(visualizer_output, graph, *codegen),
+ graph_in_bad_state_(false) {
if (strstr(method_name, kStringFilter) == nullptr) {
timing_logger_enabled_ = visualizer_enabled_ = false;
}
@@ -110,7 +113,7 @@ class PassInfoPrinter : public ValueObject {
}
}
- ~PassInfoPrinter() {
+ ~PassObserver() {
if (timing_logger_enabled_) {
LOG(INFO) << "TIMINGS " << method_name_;
LOG(INFO) << Dumpable<TimingLogger>(timing_logger_);
@@ -123,6 +126,8 @@ class PassInfoPrinter : public ValueObject {
}
}
+ void SetGraphInBadState() { graph_in_bad_state_ = true; }
+
private:
void StartPass(const char* pass_name) {
// Dump graph first, then start timer.
@@ -142,8 +147,28 @@ class PassInfoPrinter : public ValueObject {
if (visualizer_enabled_) {
visualizer_.DumpGraph(pass_name, /* is_after_pass */ true);
}
+
+ // Validate the HGraph if running in debug mode.
+ if (kIsDebugBuild) {
+ if (!graph_in_bad_state_) {
+ if (graph_->IsInSsaForm()) {
+ SSAChecker checker(graph_->GetArena(), graph_);
+ checker.Run();
+ if (!checker.IsValid()) {
+ LOG(FATAL) << "Error after " << pass_name << ": " << Dumpable<SSAChecker>(checker);
+ }
+ } else {
+ GraphChecker checker(graph_->GetArena(), graph_);
+ checker.Run();
+ if (!checker.IsValid()) {
+ LOG(FATAL) << "Error after " << pass_name << ": " << Dumpable<GraphChecker>(checker);
+ }
+ }
+ }
+ }
}
+ HGraph* const graph_;
const char* method_name_;
bool timing_logger_enabled_;
@@ -154,26 +179,30 @@ class PassInfoPrinter : public ValueObject {
bool visualizer_enabled_;
HGraphVisualizer visualizer_;
- friend PassInfo;
+ // Flag to be set by the compiler if the pass failed and the graph is not
+ // expected to validate.
+ bool graph_in_bad_state_;
- DISALLOW_COPY_AND_ASSIGN(PassInfoPrinter);
+ friend PassScope;
+
+ DISALLOW_COPY_AND_ASSIGN(PassObserver);
};
-class PassInfo : public ValueObject {
+class PassScope : public ValueObject {
public:
- PassInfo(const char *pass_name, PassInfoPrinter* pass_info_printer)
+ PassScope(const char *pass_name, PassObserver* pass_observer)
: pass_name_(pass_name),
- pass_info_printer_(pass_info_printer) {
- pass_info_printer_->StartPass(pass_name_);
+ pass_observer_(pass_observer) {
+ pass_observer_->StartPass(pass_name_);
}
- ~PassInfo() {
- pass_info_printer_->EndPass(pass_name_);
+ ~PassScope() {
+ pass_observer_->EndPass(pass_name_);
}
private:
const char* const pass_name_;
- PassInfoPrinter* const pass_info_printer_;
+ PassObserver* const pass_observer_;
};
class OptimizingCompiler FINAL : public Compiler {
@@ -234,13 +263,13 @@ class OptimizingCompiler FINAL : public Compiler {
CodeGenerator* codegen,
CompilerDriver* driver,
const DexCompilationUnit& dex_compilation_unit,
- PassInfoPrinter* pass_info_printer) const;
+ PassObserver* pass_observer) const;
// Just compile without doing optimizations.
CompiledMethod* CompileBaseline(CodeGenerator* codegen,
CompilerDriver* driver,
const DexCompilationUnit& dex_compilation_unit,
- PassInfoPrinter* pass_info_printer) const;
+ PassObserver* pass_observer) const;
std::unique_ptr<OptimizingCompilerStats> compilation_stats_;
@@ -313,14 +342,10 @@ static bool CanOptimize(const DexFile::CodeItem& code_item) {
static void RunOptimizations(HOptimization* optimizations[],
size_t length,
- PassInfoPrinter* pass_info_printer) {
+ PassObserver* pass_observer) {
for (size_t i = 0; i < length; ++i) {
- HOptimization* optimization = optimizations[i];
- {
- PassInfo pass_info(optimization->GetPassName(), pass_info_printer);
- optimization->Run();
- }
- optimization->Check();
+ PassScope scope(optimizations[i]->GetPassName(), pass_observer);
+ optimizations[i]->Run();
}
}
@@ -328,7 +353,7 @@ static void RunOptimizations(HGraph* graph,
CompilerDriver* driver,
OptimizingCompilerStats* stats,
const DexCompilationUnit& dex_compilation_unit,
- PassInfoPrinter* pass_info_printer,
+ PassObserver* pass_observer,
StackHandleScopeCollection* handles) {
ArenaAllocator* arena = graph->GetArena();
HDeadCodeElimination* dce1 = new (arena) HDeadCodeElimination(
@@ -387,7 +412,7 @@ static void RunOptimizations(HGraph* graph,
simplify4,
};
- RunOptimizations(optimizations, arraysize(optimizations), pass_info_printer);
+ RunOptimizations(optimizations, arraysize(optimizations), pass_observer);
}
// The stack map we generate must be 4-byte aligned on ARM. Since existing
@@ -403,15 +428,15 @@ static ArrayRef<const uint8_t> AlignVectorSize(std::vector<uint8_t>& vector) {
static void AllocateRegisters(HGraph* graph,
CodeGenerator* codegen,
- PassInfoPrinter* pass_info_printer) {
+ PassObserver* pass_observer) {
PrepareForRegisterAllocation(graph).Run();
SsaLivenessAnalysis liveness(graph, codegen);
{
- PassInfo pass_info(SsaLivenessAnalysis::kLivenessPassName, pass_info_printer);
+ PassScope scope(SsaLivenessAnalysis::kLivenessPassName, pass_observer);
liveness.Analyze();
}
{
- PassInfo pass_info(RegisterAllocator::kRegisterAllocatorPassName, pass_info_printer);
+ PassScope scope(RegisterAllocator::kRegisterAllocatorPassName, pass_observer);
RegisterAllocator(graph->GetArena(), codegen, liveness).AllocateRegisters();
}
}
@@ -420,12 +445,12 @@ CompiledMethod* OptimizingCompiler::CompileOptimized(HGraph* graph,
CodeGenerator* codegen,
CompilerDriver* compiler_driver,
const DexCompilationUnit& dex_compilation_unit,
- PassInfoPrinter* pass_info_printer) const {
+ PassObserver* pass_observer) const {
StackHandleScopeCollection handles(Thread::Current());
RunOptimizations(graph, compiler_driver, compilation_stats_.get(),
- dex_compilation_unit, pass_info_printer, &handles);
+ dex_compilation_unit, pass_observer, &handles);
- AllocateRegisters(graph, codegen, pass_info_printer);
+ AllocateRegisters(graph, codegen, pass_observer);
CodeVectorAllocator allocator;
codegen->CompileOptimized(&allocator);
@@ -456,7 +481,7 @@ CompiledMethod* OptimizingCompiler::CompileOptimized(HGraph* graph,
ArrayRef<const uint8_t>(), // native_gc_map.
ArrayRef<const uint8_t>(*codegen->GetAssembler()->cfi().data()),
ArrayRef<const LinkerPatch>());
- pass_info_printer->DumpDisassembly();
+ pass_observer->DumpDisassembly();
return compiled_method;
}
@@ -464,7 +489,7 @@ CompiledMethod* OptimizingCompiler::CompileBaseline(
CodeGenerator* codegen,
CompilerDriver* compiler_driver,
const DexCompilationUnit& dex_compilation_unit,
- PassInfoPrinter* pass_info_printer) const {
+ PassObserver* pass_observer) const {
CodeVectorAllocator allocator;
codegen->CompileBaseline(&allocator);
@@ -496,7 +521,7 @@ CompiledMethod* OptimizingCompiler::CompileBaseline(
AlignVectorSize(gc_map),
ArrayRef<const uint8_t>(*codegen->GetAssembler()->cfi().data()),
ArrayRef<const LinkerPatch>());
- pass_info_printer->DumpDisassembly();
+ pass_observer->DumpDisassembly();
return compiled_method;
}
@@ -571,11 +596,11 @@ CompiledMethod* OptimizingCompiler::TryCompile(const DexFile::CodeItem* code_ite
codegen->GetAssembler()->cfi().SetEnabled(
compiler_driver->GetCompilerOptions().GetGenerateDebugInfo());
- PassInfoPrinter pass_info_printer(graph,
- method_name.c_str(),
- codegen.get(),
- visualizer_output_.get(),
- compiler_driver);
+ PassObserver pass_observer(graph,
+ method_name.c_str(),
+ codegen.get(),
+ visualizer_output_.get(),
+ compiler_driver);
HGraphBuilder builder(graph,
&dex_compilation_unit,
@@ -587,9 +612,10 @@ CompiledMethod* OptimizingCompiler::TryCompile(const DexFile::CodeItem* code_ite
VLOG(compiler) << "Building " << method_name;
{
- PassInfo pass_info(HGraphBuilder::kBuilderPassName, &pass_info_printer);
+ PassScope scope(HGraphBuilder::kBuilderPassName, &pass_observer);
if (!builder.BuildGraph(*code_item)) {
CHECK(!shouldCompile) << "Could not build graph in optimizing compiler";
+ pass_observer.SetGraphInBadState();
return nullptr;
}
}
@@ -605,7 +631,7 @@ CompiledMethod* OptimizingCompiler::TryCompile(const DexFile::CodeItem* code_ite
VLOG(compiler) << "Optimizing " << method_name;
{
- PassInfo pass_info(SsaBuilder::kSsaBuilderPassName, &pass_info_printer);
+ PassScope scope(SsaBuilder::kSsaBuilderPassName, &pass_observer);
if (!graph->TryBuildingSsa()) {
// We could not transform the graph to SSA, bailout.
LOG(INFO) << "Skipping compilation of " << method_name << ": it contains a non natural loop";
@@ -618,7 +644,7 @@ CompiledMethod* OptimizingCompiler::TryCompile(const DexFile::CodeItem* code_ite
codegen.get(),
compiler_driver,
dex_compilation_unit,
- &pass_info_printer);
+ &pass_observer);
} else if (shouldOptimize && can_allocate_registers) {
LOG(FATAL) << "Could not allocate registers in optimizing compiler";
UNREACHABLE();
@@ -636,7 +662,7 @@ CompiledMethod* OptimizingCompiler::TryCompile(const DexFile::CodeItem* code_ite
return CompileBaseline(codegen.get(),
compiler_driver,
dex_compilation_unit,
- &pass_info_printer);
+ &pass_observer);
} else {
return nullptr;
}