diff options
Diffstat (limited to 'compiler/optimizing/optimizing_compiler.cc')
-rw-r--r-- | compiler/optimizing/optimizing_compiler.cc | 195 |
1 files changed, 122 insertions, 73 deletions
diff --git a/compiler/optimizing/optimizing_compiler.cc b/compiler/optimizing/optimizing_compiler.cc index deebaf7414..1e0d65a945 100644 --- a/compiler/optimizing/optimizing_compiler.cc +++ b/compiler/optimizing/optimizing_compiler.cc @@ -25,6 +25,7 @@ #include "compiler.h" #include "constant_folding.h" #include "dead_code_elimination.h" +#include "dex/quick/dex_file_to_method_inliner_map.h" #include "driver/compiler_driver.h" #include "driver/dex_compilation_unit.h" #include "elf_writer_quick.h" @@ -32,6 +33,7 @@ #include "gvn.h" #include "inliner.h" #include "instruction_simplifier.h" +#include "intrinsics.h" #include "jni/quick/jni_compiler.h" #include "mirror/art_method-inl.h" #include "nodes.h" @@ -68,13 +70,8 @@ class CodeVectorAllocator FINAL : public CodeAllocator { }; /** - * If set to true, generates a file suitable for the c1visualizer tool and IRHydra. - */ -static bool kIsVisualizerEnabled = false; - -/** * Filter to apply to the visualizer. Methods whose name contain that filter will - * be in the file. + * be dumped. */ static const char* kStringFilter = ""; @@ -114,7 +111,7 @@ class OptimizingCompiler FINAL : public Compiler { void InitCompilationUnit(CompilationUnit& cu ATTRIBUTE_UNUSED) const OVERRIDE {} - void Init() const OVERRIDE {} + void Init() OVERRIDE; void UnInit() const OVERRIDE {} @@ -123,6 +120,18 @@ class OptimizingCompiler FINAL : public Compiler { // just run the code generation after the graph was built. const bool run_optimizations_; + // Optimize and compile `graph`. + CompiledMethod* CompileOptimized(HGraph* graph, + CodeGenerator* codegen, + CompilerDriver* driver, + const DexCompilationUnit& dex_compilation_unit, + const HGraphVisualizer& visualizer) const; + + // Just compile without doing optimizations. + CompiledMethod* CompileBaseline(CodeGenerator* codegen, + CompilerDriver* driver, + const DexCompilationUnit& dex_compilation_unit) const; + mutable OptimizingCompilerStats compilation_stats_; std::unique_ptr<std::ostream> visualizer_output_; @@ -136,9 +145,18 @@ OptimizingCompiler::OptimizingCompiler(CompilerDriver* driver) : Compiler(driver, kMaximumCompilationTimeBeforeWarning), run_optimizations_( driver->GetCompilerOptions().GetCompilerFilter() != CompilerOptions::kTime), - compilation_stats_() { - if (kIsVisualizerEnabled) { - visualizer_output_.reset(new std::ofstream("art.cfg")); + compilation_stats_() {} + +void OptimizingCompiler::Init() { + // Enable C1visualizer output. Must be done in Init() because the compiler + // driver is not fully initialized when passed to the compiler's constructor. + CompilerDriver* driver = GetCompilerDriver(); + const std::string cfg_file_name = driver->GetDumpCfgFileName(); + if (!cfg_file_name.empty()) { + CHECK_EQ(driver->GetThreadCount(), 1U) + << "Graph visualizer requires the compiler to run single-threaded. " + << "Invoke the compiler with '-j1'."; + visualizer_output_.reset(new std::ofstream(cfg_file_name)); } } @@ -190,22 +208,27 @@ static void RunOptimizations(HGraph* graph, SsaRedundantPhiElimination redundant_phi(graph); SsaDeadPhiElimination dead_phi(graph); HDeadCodeElimination dce(graph); - HConstantFolding fold(graph); + HConstantFolding fold1(graph); InstructionSimplifier simplify1(graph); HInliner inliner(graph, dex_compilation_unit, driver, stats); + HConstantFolding fold2(graph); GVNOptimization gvn(graph); BoundsCheckElimination bce(graph); InstructionSimplifier simplify2(graph); + IntrinsicsRecognizer intrinsics(graph, dex_compilation_unit.GetDexFile(), driver); + HOptimization* optimizations[] = { &redundant_phi, &dead_phi, + &intrinsics, &dce, - &fold, + &fold1, &simplify1, &inliner, + &fold2, &gvn, &bce, &simplify2 @@ -213,21 +236,89 @@ static void RunOptimizations(HGraph* graph, for (size_t i = 0; i < arraysize(optimizations); ++i) { HOptimization* optimization = optimizations[i]; + visualizer.DumpGraph(optimization->GetPassName(), /*is_after=*/false); optimization->Run(); - visualizer.DumpGraph(optimization->GetPassName()); + visualizer.DumpGraph(optimization->GetPassName(), /*is_after=*/true); optimization->Check(); } } // The stack map we generate must be 4-byte aligned on ARM. Since existing // maps are generated alongside these stack maps, we must also align them. -static std::vector<uint8_t>& AlignVectorSize(std::vector<uint8_t>& vector) { +static ArrayRef<const uint8_t> AlignVectorSize(std::vector<uint8_t>& vector) { size_t size = vector.size(); size_t aligned_size = RoundUp(size, 4); for (; size < aligned_size; ++size) { vector.push_back(0); } - return vector; + return ArrayRef<const uint8_t>(vector); +} + + +CompiledMethod* OptimizingCompiler::CompileOptimized(HGraph* graph, + CodeGenerator* codegen, + CompilerDriver* compiler_driver, + const DexCompilationUnit& dex_compilation_unit, + const HGraphVisualizer& visualizer) const { + RunOptimizations( + graph, compiler_driver, &compilation_stats_, dex_compilation_unit, visualizer); + + PrepareForRegisterAllocation(graph).Run(); + SsaLivenessAnalysis liveness(*graph, codegen); + liveness.Analyze(); + visualizer.DumpGraph(kLivenessPassName); + + RegisterAllocator register_allocator(graph->GetArena(), codegen, liveness); + register_allocator.AllocateRegisters(); + visualizer.DumpGraph(kRegisterAllocatorPassName); + + CodeVectorAllocator allocator; + codegen->CompileOptimized(&allocator); + + std::vector<uint8_t> stack_map; + codegen->BuildStackMaps(&stack_map); + + compilation_stats_.RecordStat(MethodCompilationStat::kCompiledOptimized); + + return CompiledMethod::SwapAllocCompiledMethodStackMap( + compiler_driver, + codegen->GetInstructionSet(), + ArrayRef<const uint8_t>(allocator.GetMemory()), + codegen->GetFrameSize(), + codegen->GetCoreSpillMask(), + 0, /* FPR spill mask, unused */ + ArrayRef<const uint8_t>(stack_map)); +} + + +CompiledMethod* OptimizingCompiler::CompileBaseline( + CodeGenerator* codegen, + CompilerDriver* compiler_driver, + const DexCompilationUnit& dex_compilation_unit) const { + CodeVectorAllocator allocator; + codegen->CompileBaseline(&allocator); + + std::vector<uint8_t> mapping_table; + DefaultSrcMap src_mapping_table; + bool include_debug_symbol = compiler_driver->GetCompilerOptions().GetIncludeDebugSymbols(); + codegen->BuildMappingTable(&mapping_table, include_debug_symbol ? &src_mapping_table : nullptr); + std::vector<uint8_t> vmap_table; + codegen->BuildVMapTable(&vmap_table); + std::vector<uint8_t> gc_map; + codegen->BuildNativeGCMap(&gc_map, dex_compilation_unit); + + compilation_stats_.RecordStat(MethodCompilationStat::kCompiledBaseline); + return CompiledMethod::SwapAllocCompiledMethod(compiler_driver, + codegen->GetInstructionSet(), + ArrayRef<const uint8_t>(allocator.GetMemory()), + codegen->GetFrameSize(), + codegen->GetCoreSpillMask(), + 0, /* FPR spill mask, unused */ + &src_mapping_table, + AlignVectorSize(mapping_table), + AlignVectorSize(vmap_table), + AlignVectorSize(gc_map), + ArrayRef<const uint8_t>()); } CompiledMethod* OptimizingCompiler::Compile(const DexFile::CodeItem* code_item, @@ -239,7 +330,8 @@ CompiledMethod* OptimizingCompiler::Compile(const DexFile::CodeItem* code_item, const DexFile& dex_file) const { UNUSED(invoke_type); compilation_stats_.RecordStat(MethodCompilationStat::kAttemptCompilation); - InstructionSet instruction_set = GetCompilerDriver()->GetInstructionSet(); + CompilerDriver* compiler_driver = GetCompilerDriver(); + InstructionSet instruction_set = compiler_driver->GetInstructionSet(); // Always use the thumb2 assembler: some runtime functionality (like implicit stack // overflow checks) assume thumb2. if (instruction_set == kArm) { @@ -260,7 +352,7 @@ CompiledMethod* OptimizingCompiler::Compile(const DexFile::CodeItem* code_item, DexCompilationUnit dex_compilation_unit( nullptr, class_loader, art::Runtime::Current()->GetClassLinker(), dex_file, code_item, class_def_idx, method_idx, access_flags, - GetCompilerDriver()->GetVerifiedMethod(&dex_file, method_idx)); + compiler_driver->GetVerifiedMethod(&dex_file, method_idx)); std::string method_name = PrettyMethod(method_idx, dex_file); @@ -275,7 +367,7 @@ CompiledMethod* OptimizingCompiler::Compile(const DexFile::CodeItem* code_item, &dex_compilation_unit, &dex_compilation_unit, &dex_file, - GetCompilerDriver(), + compiler_driver, &compilation_stats_); VLOG(compiler) << "Building " << PrettyMethod(method_idx, dex_file); @@ -285,21 +377,24 @@ CompiledMethod* OptimizingCompiler::Compile(const DexFile::CodeItem* code_item, return nullptr; } - CodeGenerator* codegen = CodeGenerator::Create(&arena, graph, instruction_set); - if (codegen == nullptr) { + std::unique_ptr<CodeGenerator> codegen( + CodeGenerator::Create(graph, + instruction_set, + *compiler_driver->GetInstructionSetFeatures(), + compiler_driver->GetCompilerOptions())); + if (codegen.get() == nullptr) { CHECK(!shouldCompile) << "Could not find code generator for optimizing compiler"; compilation_stats_.RecordStat(MethodCompilationStat::kNotCompiledNoCodegen); return nullptr; } HGraphVisualizer visualizer( - visualizer_output_.get(), graph, kStringFilter, *codegen, method_name.c_str()); + visualizer_output_.get(), graph, kStringFilter, *codegen.get(), method_name.c_str()); visualizer.DumpGraph("builder"); - CodeVectorAllocator allocator; - 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); if (!graph->TryBuildingSsa()) { @@ -308,33 +403,9 @@ CompiledMethod* OptimizingCompiler::Compile(const DexFile::CodeItem* code_item, << ": it contains a non natural loop"; // We could not transform the graph to SSA, bailout. compilation_stats_.RecordStat(MethodCompilationStat::kNotCompiledCannotBuildSSA); - return nullptr; + } else { + result = CompileOptimized(graph, codegen.get(), compiler_driver, dex_compilation_unit, visualizer); } - RunOptimizations( - graph, GetCompilerDriver(), &compilation_stats_, dex_compilation_unit, visualizer); - - PrepareForRegisterAllocation(graph).Run(); - SsaLivenessAnalysis liveness(*graph, codegen); - liveness.Analyze(); - visualizer.DumpGraph(kLivenessPassName); - - RegisterAllocator register_allocator(graph->GetArena(), codegen, liveness); - register_allocator.AllocateRegisters(); - - visualizer.DumpGraph(kRegisterAllocatorPassName); - codegen->CompileOptimized(&allocator); - - std::vector<uint8_t> stack_map; - codegen->BuildStackMaps(&stack_map); - - compilation_stats_.RecordStat(MethodCompilationStat::kCompiledOptimized); - return new CompiledMethod(GetCompilerDriver(), - instruction_set, - allocator.GetMemory(), - codegen->GetFrameSize(), - codegen->GetCoreSpillMask(), - 0, /* FPR spill mask, unused */ - stack_map); } else if (shouldOptimize && RegisterAllocator::Supports(instruction_set)) { LOG(FATAL) << "Could not allocate registers in optimizing compiler"; UNREACHABLE(); @@ -349,31 +420,9 @@ CompiledMethod* OptimizingCompiler::Compile(const DexFile::CodeItem* code_item, compilation_stats_.RecordStat(MethodCompilationStat::kNotOptimizedRegisterAllocator); } - codegen->CompileBaseline(&allocator); - - std::vector<uint8_t> mapping_table; - SrcMap src_mapping_table; - codegen->BuildMappingTable(&mapping_table, - GetCompilerDriver()->GetCompilerOptions().GetIncludeDebugSymbols() ? - &src_mapping_table : nullptr); - std::vector<uint8_t> vmap_table; - codegen->BuildVMapTable(&vmap_table); - std::vector<uint8_t> gc_map; - codegen->BuildNativeGCMap(&gc_map, dex_compilation_unit); - - compilation_stats_.RecordStat(MethodCompilationStat::kCompiledBaseline); - return new CompiledMethod(GetCompilerDriver(), - instruction_set, - allocator.GetMemory(), - codegen->GetFrameSize(), - codegen->GetCoreSpillMask(), - 0, /* FPR spill mask, unused */ - &src_mapping_table, - AlignVectorSize(mapping_table), - AlignVectorSize(vmap_table), - AlignVectorSize(gc_map), - nullptr); + result = CompileBaseline(codegen.get(), compiler_driver, dex_compilation_unit); } + return result; } Compiler* CreateOptimizingCompiler(CompilerDriver* driver) { |