From 69ba7b7112c2277ac225615b37e6df74c055740d Mon Sep 17 00:00:00 2001 From: David Brazdil Date: Tue, 23 Jun 2015 18:27:30 +0100 Subject: 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 --- compiler/optimizing/optimizing_compiler.cc | 122 +++++++++++++++++------------ 1 file changed, 74 insertions(+), 48 deletions(-) (limited to 'compiler/optimizing/optimizing_compiler.cc') 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(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(checker); + } + } else { + GraphChecker checker(graph_->GetArena(), graph_); + checker.Run(); + if (!checker.IsValid()) { + LOG(FATAL) << "Error after " << pass_name << ": " << Dumpable(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 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 AlignVectorSize(std::vector& 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(), // native_gc_map. ArrayRef(*codegen->GetAssembler()->cfi().data()), ArrayRef()); - 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(*codegen->GetAssembler()->cfi().data()), ArrayRef()); - 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; } -- cgit v1.2.3-59-g8ed1b