diff options
Diffstat (limited to 'compiler/optimizing/optimizing_compiler.cc')
-rw-r--r-- | compiler/optimizing/optimizing_compiler.cc | 122 |
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; } |