summaryrefslogtreecommitdiffstats
path: root/compiler/optimizing/optimizing_compiler.cc
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/optimizing/optimizing_compiler.cc')
-rw-r--r--compiler/optimizing/optimizing_compiler.cc195
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) {