diff options
author | 2017-11-15 15:17:53 -0800 | |
---|---|---|
committer | 2017-11-20 10:38:26 -0800 | |
commit | 2ca10eb3f47ef3c2535c137853f7a63d10bb908b (patch) | |
tree | 3684d1d5ef4791795b64620e97f952896c5a2011 | |
parent | 02f41015a0933f146b886c62bb5b02c322ddf882 (diff) |
Refactored optimization passes setup.
Rationale:
Refactors the way we set up optimization passes
in the compiler into a more centralized approach.
The refactoring also found some "holes" in the
existing mechanism (missing string lookup in
the debugging mechanism, or inablity to set
alternative name for optimizations that may repeat).
Bug: 64538565
Test: test-art-host test-art-target
Change-Id: Ie5e0b70f67ac5acc706db91f64612dff0e561f83
21 files changed, 646 insertions, 429 deletions
diff --git a/compiler/optimizing/bounds_check_elimination.h b/compiler/optimizing/bounds_check_elimination.h index 6dc53207ea..79c67a8c7a 100644 --- a/compiler/optimizing/bounds_check_elimination.h +++ b/compiler/optimizing/bounds_check_elimination.h @@ -28,8 +28,9 @@ class BoundsCheckElimination : public HOptimization { public: BoundsCheckElimination(HGraph* graph, const SideEffectsAnalysis& side_effects, - HInductionVarAnalysis* induction_analysis) - : HOptimization(graph, kBoundsCheckEliminationPassName), + HInductionVarAnalysis* induction_analysis, + const char* name = kBoundsCheckEliminationPassName) + : HOptimization(graph, name), side_effects_(side_effects), induction_analysis_(induction_analysis) {} diff --git a/compiler/optimizing/cha_guard_optimization.h b/compiler/optimizing/cha_guard_optimization.h index ba0cdb81fd..f14e07bd6c 100644 --- a/compiler/optimizing/cha_guard_optimization.h +++ b/compiler/optimizing/cha_guard_optimization.h @@ -26,8 +26,9 @@ namespace art { */ class CHAGuardOptimization : public HOptimization { public: - explicit CHAGuardOptimization(HGraph* graph) - : HOptimization(graph, kCHAGuardOptimizationPassName) {} + explicit CHAGuardOptimization(HGraph* graph, + const char* name = kCHAGuardOptimizationPassName) + : HOptimization(graph, name) {} void Run() OVERRIDE; diff --git a/compiler/optimizing/code_sinking.h b/compiler/optimizing/code_sinking.h index 59cda52a8c..836d9d4f67 100644 --- a/compiler/optimizing/code_sinking.h +++ b/compiler/optimizing/code_sinking.h @@ -28,8 +28,10 @@ namespace art { */ class CodeSinking : public HOptimization { public: - CodeSinking(HGraph* graph, OptimizingCompilerStats* stats) - : HOptimization(graph, kCodeSinkingPassName, stats) {} + CodeSinking(HGraph* graph, + OptimizingCompilerStats* stats, + const char* name = kCodeSinkingPassName) + : HOptimization(graph, name, stats) {} void Run() OVERRIDE; diff --git a/compiler/optimizing/constructor_fence_redundancy_elimination.h b/compiler/optimizing/constructor_fence_redundancy_elimination.h index d89210cd1c..f4b06d5544 100644 --- a/compiler/optimizing/constructor_fence_redundancy_elimination.h +++ b/compiler/optimizing/constructor_fence_redundancy_elimination.h @@ -48,12 +48,13 @@ namespace art { class ConstructorFenceRedundancyElimination : public HOptimization { public: ConstructorFenceRedundancyElimination(HGraph* graph, - OptimizingCompilerStats* stats) - : HOptimization(graph, kPassName, stats) {} + OptimizingCompilerStats* stats, + const char* name = kCFREPassName) + : HOptimization(graph, name, stats) {} void Run() OVERRIDE; - static constexpr const char* kPassName = "constructor_fence_redundancy_elimination"; + static constexpr const char* kCFREPassName = "constructor_fence_redundancy_elimination"; private: DISALLOW_COPY_AND_ASSIGN(ConstructorFenceRedundancyElimination); diff --git a/compiler/optimizing/induction_var_analysis.cc b/compiler/optimizing/induction_var_analysis.cc index e2747afd85..ad29ba56ab 100644 --- a/compiler/optimizing/induction_var_analysis.cc +++ b/compiler/optimizing/induction_var_analysis.cc @@ -97,8 +97,8 @@ static DataType::Type ImplicitConversion(DataType::Type type) { // Class methods. // -HInductionVarAnalysis::HInductionVarAnalysis(HGraph* graph) - : HOptimization(graph, kInductionPassName), +HInductionVarAnalysis::HInductionVarAnalysis(HGraph* graph, const char* name) + : HOptimization(graph, name), global_depth_(0), stack_(graph->GetAllocator()->Adapter(kArenaAllocInductionVarAnalysis)), map_(std::less<HInstruction*>(), diff --git a/compiler/optimizing/induction_var_analysis.h b/compiler/optimizing/induction_var_analysis.h index a2d302ae81..8737b890d9 100644 --- a/compiler/optimizing/induction_var_analysis.h +++ b/compiler/optimizing/induction_var_analysis.h @@ -35,7 +35,7 @@ namespace art { */ class HInductionVarAnalysis : public HOptimization { public: - explicit HInductionVarAnalysis(HGraph* graph); + explicit HInductionVarAnalysis(HGraph* graph, const char* name = kInductionPassName); void Run() OVERRIDE; diff --git a/compiler/optimizing/inliner.h b/compiler/optimizing/inliner.h index c4b3a32d91..042eee3204 100644 --- a/compiler/optimizing/inliner.h +++ b/compiler/optimizing/inliner.h @@ -44,8 +44,9 @@ class HInliner : public HOptimization { size_t total_number_of_dex_registers, size_t total_number_of_instructions, HInliner* parent, - size_t depth = 0) - : HOptimization(outer_graph, kInlinerPassName, stats), + size_t depth = 0, + const char* name = kInlinerPassName) + : HOptimization(outer_graph, name, stats), outermost_graph_(outermost_graph), outer_compilation_unit_(outer_compilation_unit), caller_compilation_unit_(caller_compilation_unit), diff --git a/compiler/optimizing/intrinsics.h b/compiler/optimizing/intrinsics.h index 707ff3408e..818d7f63a3 100644 --- a/compiler/optimizing/intrinsics.h +++ b/compiler/optimizing/intrinsics.h @@ -37,8 +37,10 @@ static constexpr uint64_t kNanDouble = 0x7ff8000000000000; // Recognize intrinsics from HInvoke nodes. class IntrinsicsRecognizer : public HOptimization { public: - IntrinsicsRecognizer(HGraph* graph, OptimizingCompilerStats* stats) - : HOptimization(graph, kIntrinsicsRecognizerPassName, stats) {} + IntrinsicsRecognizer(HGraph* graph, + OptimizingCompilerStats* stats, + const char* name = kIntrinsicsRecognizerPassName) + : HOptimization(graph, name, stats) {} void Run() OVERRIDE; diff --git a/compiler/optimizing/licm.h b/compiler/optimizing/licm.h index bf56f53d46..ee567aeb20 100644 --- a/compiler/optimizing/licm.h +++ b/compiler/optimizing/licm.h @@ -26,8 +26,11 @@ class SideEffectsAnalysis; class LICM : public HOptimization { public: - LICM(HGraph* graph, const SideEffectsAnalysis& side_effects, OptimizingCompilerStats* stats) - : HOptimization(graph, kLoopInvariantCodeMotionPassName, stats), + LICM(HGraph* graph, + const SideEffectsAnalysis& side_effects, + OptimizingCompilerStats* stats, + const char* name = kLoopInvariantCodeMotionPassName) + : HOptimization(graph, name, stats), side_effects_(side_effects) {} void Run() OVERRIDE; diff --git a/compiler/optimizing/load_store_analysis.h b/compiler/optimizing/load_store_analysis.h index aa8b5bbdc9..437e6be418 100644 --- a/compiler/optimizing/load_store_analysis.h +++ b/compiler/optimizing/load_store_analysis.h @@ -564,8 +564,8 @@ class HeapLocationCollector : public HGraphVisitor { class LoadStoreAnalysis : public HOptimization { public: - explicit LoadStoreAnalysis(HGraph* graph) - : HOptimization(graph, kLoadStoreAnalysisPassName), + explicit LoadStoreAnalysis(HGraph* graph, const char* name = kLoadStoreAnalysisPassName) + : HOptimization(graph, name), heap_location_collector_(graph) {} const HeapLocationCollector& GetHeapLocationCollector() const { diff --git a/compiler/optimizing/load_store_elimination.h b/compiler/optimizing/load_store_elimination.h index 20a8a769c0..7153541baf 100644 --- a/compiler/optimizing/load_store_elimination.h +++ b/compiler/optimizing/load_store_elimination.h @@ -29,8 +29,9 @@ class LoadStoreElimination : public HOptimization { LoadStoreElimination(HGraph* graph, const SideEffectsAnalysis& side_effects, const LoadStoreAnalysis& lsa, - OptimizingCompilerStats* stats) - : HOptimization(graph, kLoadStoreEliminationPassName, stats), + OptimizingCompilerStats* stats, + const char* name = kLoadStoreEliminationPassName) + : HOptimization(graph, name, stats), side_effects_(side_effects), lsa_(lsa) {} diff --git a/compiler/optimizing/loop_optimization.cc b/compiler/optimizing/loop_optimization.cc index fcc59ea3f9..1ca096035e 100644 --- a/compiler/optimizing/loop_optimization.cc +++ b/compiler/optimizing/loop_optimization.cc @@ -448,8 +448,9 @@ static bool CheckInductionSetFullyRemoved(ScopedArenaSet<HInstruction*>* iset) { HLoopOptimization::HLoopOptimization(HGraph* graph, CompilerDriver* compiler_driver, HInductionVarAnalysis* induction_analysis, - OptimizingCompilerStats* stats) - : HOptimization(graph, kLoopOptimizationPassName, stats), + OptimizingCompilerStats* stats, + const char* name) + : HOptimization(graph, name, stats), compiler_driver_(compiler_driver), induction_range_(induction_analysis), loop_allocator_(nullptr), diff --git a/compiler/optimizing/loop_optimization.h b/compiler/optimizing/loop_optimization.h index 51e0a986b8..a707ad1358 100644 --- a/compiler/optimizing/loop_optimization.h +++ b/compiler/optimizing/loop_optimization.h @@ -37,7 +37,8 @@ class HLoopOptimization : public HOptimization { HLoopOptimization(HGraph* graph, CompilerDriver* compiler_driver, HInductionVarAnalysis* induction_analysis, - OptimizingCompilerStats* stats); + OptimizingCompilerStats* stats, + const char* name = kLoopOptimizationPassName); void Run() OVERRIDE; diff --git a/compiler/optimizing/optimization.cc b/compiler/optimizing/optimization.cc index 1e68ca2802..7edb642c5b 100644 --- a/compiler/optimizing/optimization.cc +++ b/compiler/optimizing/optimization.cc @@ -16,5 +16,317 @@ #include "optimization.h" +#ifdef ART_ENABLE_CODEGEN_arm +#include "instruction_simplifier_arm.h" +#endif +#ifdef ART_ENABLE_CODEGEN_arm64 +#include "instruction_simplifier_arm64.h" +#endif +#ifdef ART_ENABLE_CODEGEN_mips +#include "instruction_simplifier_mips.h" +#include "pc_relative_fixups_mips.h" +#endif +#ifdef ART_ENABLE_CODEGEN_x86 +#include "pc_relative_fixups_x86.h" +#endif +#if defined(ART_ENABLE_CODEGEN_x86) || defined(ART_ENABLE_CODEGEN_x86_64) +#include "x86_memory_gen.h" +#endif + +#include "bounds_check_elimination.h" +#include "cha_guard_optimization.h" +#include "code_sinking.h" +#include "constant_folding.h" +#include "constructor_fence_redundancy_elimination.h" +#include "dead_code_elimination.h" +#include "driver/dex_compilation_unit.h" +#include "gvn.h" +#include "induction_var_analysis.h" +#include "inliner.h" +#include "instruction_simplifier.h" +#include "intrinsics.h" +#include "licm.h" +#include "load_store_analysis.h" +#include "load_store_elimination.h" +#include "loop_optimization.h" +#include "scheduler.h" +#include "select_generator.h" +#include "sharpening.h" +#include "side_effects_analysis.h" + +// Decide between default or alternative pass name. + namespace art { + +const char* OptimizationPassName(OptimizationPass pass) { + switch (pass) { + case OptimizationPass::kSideEffectsAnalysis: + return SideEffectsAnalysis::kSideEffectsAnalysisPassName; + case OptimizationPass::kInductionVarAnalysis: + return HInductionVarAnalysis::kInductionPassName; + case OptimizationPass::kLoadStoreAnalysis: + return LoadStoreAnalysis::kLoadStoreAnalysisPassName; + case OptimizationPass::kGlobalValueNumbering: + return GVNOptimization::kGlobalValueNumberingPassName; + case OptimizationPass::kInvariantCodeMotion: + return LICM::kLoopInvariantCodeMotionPassName; + case OptimizationPass::kLoopOptimization: + return HLoopOptimization::kLoopOptimizationPassName; + case OptimizationPass::kBoundsCheckElimination: + return BoundsCheckElimination::kBoundsCheckEliminationPassName; + case OptimizationPass::kLoadStoreElimination: + return LoadStoreElimination::kLoadStoreEliminationPassName; + case OptimizationPass::kConstantFolding: + return HConstantFolding::kConstantFoldingPassName; + case OptimizationPass::kDeadCodeElimination: + return HDeadCodeElimination::kDeadCodeEliminationPassName; + case OptimizationPass::kInliner: + return HInliner::kInlinerPassName; + case OptimizationPass::kSharpening: + return HSharpening::kSharpeningPassName; + case OptimizationPass::kSelectGenerator: + return HSelectGenerator::kSelectGeneratorPassName; + case OptimizationPass::kInstructionSimplifier: + return InstructionSimplifier::kInstructionSimplifierPassName; + case OptimizationPass::kIntrinsicsRecognizer: + return IntrinsicsRecognizer::kIntrinsicsRecognizerPassName; + case OptimizationPass::kCHAGuardOptimization: + return CHAGuardOptimization::kCHAGuardOptimizationPassName; + case OptimizationPass::kCodeSinking: + return CodeSinking::kCodeSinkingPassName; + case OptimizationPass::kConstructorFenceRedundancyElimination: + return ConstructorFenceRedundancyElimination::kCFREPassName; + case OptimizationPass::kScheduling: + return HInstructionScheduling::kInstructionSchedulingPassName; +#ifdef ART_ENABLE_CODEGEN_arm + case OptimizationPass::kInstructionSimplifierArm: + return arm::InstructionSimplifierArm::kInstructionSimplifierArmPassName; +#endif +#ifdef ART_ENABLE_CODEGEN_arm64 + case OptimizationPass::kInstructionSimplifierArm64: + return arm64::InstructionSimplifierArm64::kInstructionSimplifierArm64PassName; +#endif +#ifdef ART_ENABLE_CODEGEN_mips + case OptimizationPass::kPcRelativeFixupsMips: + return mips::PcRelativeFixups::kPcRelativeFixupsMipsPassName; + case OptimizationPass::kInstructionSimplifierMips: + return mips::InstructionSimplifierMips::kInstructionSimplifierMipsPassName; +#endif +#ifdef ART_ENABLE_CODEGEN_x86 + case OptimizationPass::kPcRelativeFixupsX86: + return x86::PcRelativeFixups::kPcRelativeFixupsX86PassName; +#endif +#if defined(ART_ENABLE_CODEGEN_x86) || defined(ART_ENABLE_CODEGEN_x86_64) + case OptimizationPass::kX86MemoryOperandGeneration: + return x86::X86MemoryOperandGeneration::kX86MemoryOperandGenerationPassName; +#endif + } +} + +#define X(x) if (name == OptimizationPassName((x))) return (x) + +OptimizationPass OptimizationPassByName(const std::string& name) { + X(OptimizationPass::kBoundsCheckElimination); + X(OptimizationPass::kCHAGuardOptimization); + X(OptimizationPass::kCodeSinking); + X(OptimizationPass::kConstantFolding); + X(OptimizationPass::kConstructorFenceRedundancyElimination); + X(OptimizationPass::kDeadCodeElimination); + X(OptimizationPass::kGlobalValueNumbering); + X(OptimizationPass::kInductionVarAnalysis); + X(OptimizationPass::kInliner); + X(OptimizationPass::kInstructionSimplifier); + X(OptimizationPass::kIntrinsicsRecognizer); + X(OptimizationPass::kInvariantCodeMotion); + X(OptimizationPass::kLoadStoreAnalysis); + X(OptimizationPass::kLoadStoreElimination); + X(OptimizationPass::kLoopOptimization); + X(OptimizationPass::kScheduling); + X(OptimizationPass::kSelectGenerator); + X(OptimizationPass::kSharpening); + X(OptimizationPass::kSideEffectsAnalysis); +#ifdef ART_ENABLE_CODEGEN_arm + X(OptimizationPass::kInstructionSimplifierArm); +#endif +#ifdef ART_ENABLE_CODEGEN_arm64 + X(OptimizationPass::kInstructionSimplifierArm64); +#endif +#ifdef ART_ENABLE_CODEGEN_mips + X(OptimizationPass::kPcRelativeFixupsMips); + X(OptimizationPass::kInstructionSimplifierMips); +#endif +#ifdef ART_ENABLE_CODEGEN_x86 + X(OptimizationPass::kPcRelativeFixupsX86); + X(OptimizationPass::kX86MemoryOperandGeneration); +#endif + LOG(FATAL) << "Cannot find optimization " << name; + UNREACHABLE(); +} + +#undef X + +ArenaVector<HOptimization*> ConstructOptimizations( + const OptimizationDef definitions[], + size_t length, + ArenaAllocator* allocator, + HGraph* graph, + OptimizingCompilerStats* stats, + CodeGenerator* codegen, + CompilerDriver* driver, + const DexCompilationUnit& dex_compilation_unit, + VariableSizedHandleScope* handles) { + ArenaVector<HOptimization*> optimizations(allocator->Adapter()); + + // Some optimizations require SideEffectsAnalysis or HInductionVarAnalysis + // instances. This method uses the nearest instance preceeding it in the pass + // name list or fails fatally if no such analysis can be found. + SideEffectsAnalysis* most_recent_side_effects = nullptr; + HInductionVarAnalysis* most_recent_induction = nullptr; + LoadStoreAnalysis* most_recent_lsa = nullptr; + + // Loop over the requested optimizations. + for (size_t i = 0; i < length; i++) { + OptimizationPass pass = definitions[i].first; + const char* alt_name = definitions[i].second; + const char* name = alt_name != nullptr + ? alt_name + : OptimizationPassName(pass); + HOptimization* opt = nullptr; + + switch (pass) { + // + // Analysis passes (kept in most recent for subsequent passes). + // + case OptimizationPass::kSideEffectsAnalysis: + opt = most_recent_side_effects = new (allocator) SideEffectsAnalysis(graph, name); + break; + case OptimizationPass::kInductionVarAnalysis: + opt = most_recent_induction = new (allocator) HInductionVarAnalysis(graph, name); + break; + case OptimizationPass::kLoadStoreAnalysis: + opt = most_recent_lsa = new (allocator) LoadStoreAnalysis(graph, name); + break; + // + // Passes that need prior analysis. + // + case OptimizationPass::kGlobalValueNumbering: + CHECK(most_recent_side_effects != nullptr); + opt = new (allocator) GVNOptimization(graph, *most_recent_side_effects, name); + break; + case OptimizationPass::kInvariantCodeMotion: + CHECK(most_recent_side_effects != nullptr); + opt = new (allocator) LICM(graph, *most_recent_side_effects, stats, name); + break; + case OptimizationPass::kLoopOptimization: + CHECK(most_recent_induction != nullptr); + opt = new (allocator) HLoopOptimization(graph, driver, most_recent_induction, stats, name); + break; + case OptimizationPass::kBoundsCheckElimination: + CHECK(most_recent_side_effects != nullptr && most_recent_induction != nullptr); + opt = new (allocator) BoundsCheckElimination( + graph, *most_recent_side_effects, most_recent_induction, name); + break; + case OptimizationPass::kLoadStoreElimination: + CHECK(most_recent_side_effects != nullptr && most_recent_induction != nullptr); + opt = new (allocator) LoadStoreElimination( + graph, *most_recent_side_effects, *most_recent_lsa, stats, name); + break; + // + // Regular passes. + // + case OptimizationPass::kConstantFolding: + opt = new (allocator) HConstantFolding(graph, name); + break; + case OptimizationPass::kDeadCodeElimination: + opt = new (allocator) HDeadCodeElimination(graph, stats, name); + break; + case OptimizationPass::kInliner: { + size_t number_of_dex_registers = dex_compilation_unit.GetCodeItem()->registers_size_; + opt = new (allocator) HInliner(graph, // outer_graph + graph, // outermost_graph + codegen, + dex_compilation_unit, // outer_compilation_unit + dex_compilation_unit, // outermost_compilation_unit + driver, + handles, + stats, + number_of_dex_registers, + /* total_number_of_instructions */ 0, + /* parent */ nullptr, + /* depth */ 0, + name); + break; + } + case OptimizationPass::kSharpening: + opt = new (allocator) HSharpening( + graph, codegen, dex_compilation_unit, driver, handles, name); + break; + case OptimizationPass::kSelectGenerator: + opt = new (allocator) HSelectGenerator(graph, handles, stats, name); + break; + case OptimizationPass::kInstructionSimplifier: + opt = new (allocator) InstructionSimplifier(graph, codegen, driver, stats, name); + break; + case OptimizationPass::kIntrinsicsRecognizer: + opt = new (allocator) IntrinsicsRecognizer(graph, stats, name); + break; + case OptimizationPass::kCHAGuardOptimization: + opt = new (allocator) CHAGuardOptimization(graph, name); + break; + case OptimizationPass::kCodeSinking: + opt = new (allocator) CodeSinking(graph, stats, name); + break; + case OptimizationPass::kConstructorFenceRedundancyElimination: + opt = new (allocator) ConstructorFenceRedundancyElimination(graph, stats, name); + break; + case OptimizationPass::kScheduling: + opt = new (allocator) HInstructionScheduling( + graph, driver->GetInstructionSet(), codegen, name); + break; + // + // Arch-specific passes. + // +#ifdef ART_ENABLE_CODEGEN_arm + case OptimizationPass::kInstructionSimplifierArm: + DCHECK(alt_name == nullptr) << "arch-specific pass does not support alternative name"; + opt = new (allocator) arm::InstructionSimplifierArm(graph, stats); + break; +#endif +#ifdef ART_ENABLE_CODEGEN_arm64 + case OptimizationPass::kInstructionSimplifierArm64: + DCHECK(alt_name == nullptr) << "arch-specific pass does not support alternative name"; + opt = new (allocator) arm64::InstructionSimplifierArm64(graph, stats); + break; +#endif +#ifdef ART_ENABLE_CODEGEN_mips + case OptimizationPass::kPcRelativeFixupsMips: + DCHECK(alt_name == nullptr) << "arch-specific pass does not support alternative name"; + opt = new (allocator) mips::PcRelativeFixups(graph, codegen, stats); + break; + case OptimizationPass::kInstructionSimplifierMips: + DCHECK(alt_name == nullptr) << "arch-specific pass does not support alternative name"; + opt = new (allocator) mips::InstructionSimplifierMips(graph, codegen, stats); + break; +#endif +#ifdef ART_ENABLE_CODEGEN_x86 + case OptimizationPass::kPcRelativeFixupsX86: + DCHECK(alt_name == nullptr) << "arch-specific pass does not support alternative name"; + opt = new (allocator) x86::PcRelativeFixups(graph, codegen, stats); + break; + case OptimizationPass::kX86MemoryOperandGeneration: + DCHECK(alt_name == nullptr) << "arch-specific pass does not support alternative name"; + opt = new (allocator) x86::X86MemoryOperandGeneration(graph, codegen, stats); + break; +#endif + } // switch + + // Add each next optimization to result vector. + CHECK(opt != nullptr); + DCHECK_STREQ(name, opt->GetPassName()); // sanity + optimizations.push_back(opt); + } + + return optimizations; +} + } // namespace art diff --git a/compiler/optimizing/optimization.h b/compiler/optimizing/optimization.h index ce41a2e512..c170f155fa 100644 --- a/compiler/optimizing/optimization.h +++ b/compiler/optimizing/optimization.h @@ -23,6 +23,10 @@ namespace art { +class CodeGenerator; +class CompilerDriver; +class DexCompilationUnit; + /** * Abstraction to implement an optimization pass. */ @@ -58,6 +62,81 @@ class HOptimization : public ArenaObject<kArenaAllocOptimization> { DISALLOW_COPY_AND_ASSIGN(HOptimization); }; +// Optimization passes that can be constructed by the helper method below. An enum +// field is preferred over a string lookup at places where performance matters. +// TODO: generate this table and lookup methods below automatically? +enum class OptimizationPass { + kBoundsCheckElimination, + kCHAGuardOptimization, + kCodeSinking, + kConstantFolding, + kConstructorFenceRedundancyElimination, + kDeadCodeElimination, + kGlobalValueNumbering, + kInductionVarAnalysis, + kInliner, + kInstructionSimplifier, + kIntrinsicsRecognizer, + kInvariantCodeMotion, + kLoadStoreAnalysis, + kLoadStoreElimination, + kLoopOptimization, + kScheduling, + kSelectGenerator, + kSharpening, + kSideEffectsAnalysis, +#ifdef ART_ENABLE_CODEGEN_arm + kInstructionSimplifierArm, +#endif +#ifdef ART_ENABLE_CODEGEN_arm64 + kInstructionSimplifierArm64, +#endif +#ifdef ART_ENABLE_CODEGEN_mips + kPcRelativeFixupsMips, + kInstructionSimplifierMips, +#endif +#ifdef ART_ENABLE_CODEGEN_x86 + kPcRelativeFixupsX86, +#endif +#if defined(ART_ENABLE_CODEGEN_x86) || defined(ART_ENABLE_CODEGEN_x86_64) + kX86MemoryOperandGeneration, +#endif +}; + +// Lookup name of optimization pass. +const char* OptimizationPassName(OptimizationPass pass); + +// Lookup optimization pass by name. +OptimizationPass OptimizationPassByName(const std::string& name); + +// Optimization definition consisting of an optimization pass +// and an optional alternative name (nullptr denotes default). +typedef std::pair<OptimizationPass, const char*> OptimizationDef; + +// Helper method for optimization definition array entries. +inline OptimizationDef OptDef(OptimizationPass pass, const char* name = nullptr) { + return std::make_pair(pass, name); +} + +// Helper method to construct series of optimization passes. +// The array should consist of the requested optimizations +// and optional alternative names for repeated passes. +// Example: +// { OptPass(kConstantFolding), +// OptPass(Inliner), +// OptPass(kConstantFolding, "constant_folding$after_inlining") +// } +ArenaVector<HOptimization*> ConstructOptimizations( + const OptimizationDef definitions[], + size_t length, + ArenaAllocator* allocator, + HGraph* graph, + OptimizingCompilerStats* stats, + CodeGenerator* codegen, + CompilerDriver* driver, + const DexCompilationUnit& dex_compilation_unit, + VariableSizedHandleScope* handles); + } // namespace art #endif // ART_COMPILER_OPTIMIZING_OPTIMIZATION_H_ diff --git a/compiler/optimizing/optimizing_compiler.cc b/compiler/optimizing/optimizing_compiler.cc index 4974ed0ec5..53f9ec413b 100644 --- a/compiler/optimizing/optimizing_compiler.cc +++ b/compiler/optimizing/optimizing_compiler.cc @@ -22,23 +22,6 @@ #include <stdint.h> -#ifdef ART_ENABLE_CODEGEN_arm64 -#include "instruction_simplifier_arm64.h" -#endif - -#ifdef ART_ENABLE_CODEGEN_mips -#include "instruction_simplifier_mips.h" -#include "pc_relative_fixups_mips.h" -#endif - -#ifdef ART_ENABLE_CODEGEN_x86 -#include "pc_relative_fixups_x86.h" -#endif - -#if defined(ART_ENABLE_CODEGEN_x86) || defined(ART_ENABLE_CODEGEN_x86_64) -#include "x86_memory_gen.h" -#endif - #include "art_method-inl.h" #include "base/arena_allocator.h" #include "base/arena_containers.h" @@ -47,16 +30,10 @@ #include "base/mutex.h" #include "base/scoped_arena_allocator.h" #include "base/timing_logger.h" -#include "bounds_check_elimination.h" #include "builder.h" -#include "cha_guard_optimization.h" #include "code_generator.h" -#include "code_sinking.h" #include "compiled_method.h" #include "compiler.h" -#include "constant_folding.h" -#include "constructor_fence_redundancy_elimination.h" -#include "dead_code_elimination.h" #include "debug/elf_debug_writer.h" #include "debug/method_debug_info.h" #include "dex/verification_results.h" @@ -67,31 +44,19 @@ #include "driver/dex_compilation_unit.h" #include "graph_checker.h" #include "graph_visualizer.h" -#include "gvn.h" -#include "induction_var_analysis.h" #include "inliner.h" -#include "instruction_simplifier.h" -#include "instruction_simplifier_arm.h" -#include "intrinsics.h" #include "jit/debugger_interface.h" #include "jit/jit.h" #include "jit/jit_code_cache.h" #include "jit/jit_logger.h" #include "jni/quick/jni_compiler.h" -#include "licm.h" #include "linker/linker_patch.h" -#include "load_store_analysis.h" -#include "load_store_elimination.h" -#include "loop_optimization.h" #include "nodes.h" #include "oat_quick_method_header.h" #include "prepare_for_register_allocation.h" #include "reference_type_propagation.h" #include "register_allocator_linear_scan.h" -#include "scheduler.h" #include "select_generator.h" -#include "sharpening.h" -#include "side_effects_analysis.h" #include "ssa_builder.h" #include "ssa_liveness_analysis.h" #include "ssa_phi_elimination.h" @@ -335,21 +300,52 @@ class OptimizingCompiler FINAL : public Compiler { private: void RunOptimizations(HGraph* graph, CodeGenerator* codegen, - CompilerDriver* driver, const DexCompilationUnit& dex_compilation_unit, PassObserver* pass_observer, - VariableSizedHandleScope* handles) const; + VariableSizedHandleScope* handles, + const OptimizationDef definitions[], + size_t length) const { + // Convert definitions to optimization passes. + ArenaVector<HOptimization*> optimizations = ConstructOptimizations( + definitions, + length, + graph->GetAllocator(), + graph, + compilation_stats_.get(), + codegen, + GetCompilerDriver(), + dex_compilation_unit, + handles); + DCHECK_EQ(length, optimizations.size()); + // Run the optimization passes one by one. + for (size_t i = 0; i < length; ++i) { + PassScope scope(optimizations[i]->GetPassName(), pass_observer); + optimizations[i]->Run(); + } + } - void RunOptimizations(HOptimization* optimizations[], - size_t length, - PassObserver* pass_observer) const; + template <size_t length> void RunOptimizations( + HGraph* graph, + CodeGenerator* codegen, + const DexCompilationUnit& dex_compilation_unit, + PassObserver* pass_observer, + VariableSizedHandleScope* handles, + const OptimizationDef (&definitions)[length]) const { + RunOptimizations( + graph, codegen, dex_compilation_unit, pass_observer, handles, definitions, length); + } + + void RunOptimizations(HGraph* graph, + CodeGenerator* codegen, + const DexCompilationUnit& dex_compilation_unit, + PassObserver* pass_observer, + VariableSizedHandleScope* handles) const; private: // Create a 'CompiledMethod' for an optimized graph. CompiledMethod* Emit(ArenaAllocator* allocator, CodeVectorAllocator* code_allocator, CodeGenerator* codegen, - CompilerDriver* driver, const DexFile::CodeItem* item) const; // Try compiling a method and return the code generator used for @@ -376,15 +372,15 @@ class OptimizingCompiler FINAL : public Compiler { void MaybeRunInliner(HGraph* graph, CodeGenerator* codegen, - CompilerDriver* driver, const DexCompilationUnit& dex_compilation_unit, PassObserver* pass_observer, VariableSizedHandleScope* handles) const; - void RunArchOptimizations(InstructionSet instruction_set, - HGraph* graph, + void RunArchOptimizations(HGraph* graph, CodeGenerator* codegen, - PassObserver* pass_observer) const; + const DexCompilationUnit& dex_compilation_unit, + PassObserver* pass_observer, + VariableSizedHandleScope* handles) const; std::unique_ptr<OptimizingCompilerStats> compilation_stats_; @@ -440,299 +436,130 @@ static bool IsInstructionSetSupported(InstructionSet instruction_set) { || instruction_set == InstructionSet::kX86_64; } -// Strip pass name suffix to get optimization name. -static std::string ConvertPassNameToOptimizationName(const std::string& pass_name) { - size_t pos = pass_name.find(kPassNameSeparator); - return pos == std::string::npos ? pass_name : pass_name.substr(0, pos); -} - -static HOptimization* BuildOptimization( - const std::string& pass_name, - ArenaAllocator* allocator, - HGraph* graph, - OptimizingCompilerStats* stats, - CodeGenerator* codegen, - CompilerDriver* driver, - const DexCompilationUnit& dex_compilation_unit, - VariableSizedHandleScope* handles, - SideEffectsAnalysis* most_recent_side_effects, - HInductionVarAnalysis* most_recent_induction, - LoadStoreAnalysis* most_recent_lsa) { - std::string opt_name = ConvertPassNameToOptimizationName(pass_name); - if (opt_name == BoundsCheckElimination::kBoundsCheckEliminationPassName) { - CHECK(most_recent_side_effects != nullptr && most_recent_induction != nullptr); - return new (allocator) BoundsCheckElimination(graph, - *most_recent_side_effects, - most_recent_induction); - } else if (opt_name == GVNOptimization::kGlobalValueNumberingPassName) { - CHECK(most_recent_side_effects != nullptr); - return new (allocator) GVNOptimization(graph, *most_recent_side_effects, pass_name.c_str()); - } else if (opt_name == HConstantFolding::kConstantFoldingPassName) { - return new (allocator) HConstantFolding(graph, pass_name.c_str()); - } else if (opt_name == HDeadCodeElimination::kDeadCodeEliminationPassName) { - return new (allocator) HDeadCodeElimination(graph, stats, pass_name.c_str()); - } else if (opt_name == HInliner::kInlinerPassName) { - size_t number_of_dex_registers = dex_compilation_unit.GetCodeItem()->registers_size_; - return new (allocator) HInliner(graph, // outer_graph - graph, // outermost_graph - codegen, - dex_compilation_unit, // outer_compilation_unit - dex_compilation_unit, // outermost_compilation_unit - driver, - handles, - stats, - number_of_dex_registers, - /* total_number_of_instructions */ 0, - /* parent */ nullptr); - } else if (opt_name == HSharpening::kSharpeningPassName) { - return new (allocator) HSharpening(graph, codegen, dex_compilation_unit, driver, handles); - } else if (opt_name == HSelectGenerator::kSelectGeneratorPassName) { - return new (allocator) HSelectGenerator(graph, handles, stats); - } else if (opt_name == HInductionVarAnalysis::kInductionPassName) { - return new (allocator) HInductionVarAnalysis(graph); - } else if (opt_name == InstructionSimplifier::kInstructionSimplifierPassName) { - return new (allocator) InstructionSimplifier(graph, codegen, driver, stats, pass_name.c_str()); - } else if (opt_name == IntrinsicsRecognizer::kIntrinsicsRecognizerPassName) { - return new (allocator) IntrinsicsRecognizer(graph, stats); - } else if (opt_name == LICM::kLoopInvariantCodeMotionPassName) { - CHECK(most_recent_side_effects != nullptr); - return new (allocator) LICM(graph, *most_recent_side_effects, stats); - } else if (opt_name == LoadStoreAnalysis::kLoadStoreAnalysisPassName) { - return new (allocator) LoadStoreAnalysis(graph); - } else if (opt_name == LoadStoreElimination::kLoadStoreEliminationPassName) { - CHECK(most_recent_side_effects != nullptr); - CHECK(most_recent_lsa != nullptr); - return new (allocator) LoadStoreElimination(graph, - *most_recent_side_effects, - *most_recent_lsa, stats); - } else if (opt_name == SideEffectsAnalysis::kSideEffectsAnalysisPassName) { - return new (allocator) SideEffectsAnalysis(graph); - } else if (opt_name == HLoopOptimization::kLoopOptimizationPassName) { - return new (allocator) HLoopOptimization(graph, driver, most_recent_induction, stats); - } else if (opt_name == CHAGuardOptimization::kCHAGuardOptimizationPassName) { - return new (allocator) CHAGuardOptimization(graph); - } else if (opt_name == CodeSinking::kCodeSinkingPassName) { - return new (allocator) CodeSinking(graph, stats); - } else if (opt_name == ConstructorFenceRedundancyElimination::kPassName) { - return new (allocator) ConstructorFenceRedundancyElimination(graph, stats); -#ifdef ART_ENABLE_CODEGEN_arm - } else if (opt_name == arm::InstructionSimplifierArm::kInstructionSimplifierArmPassName) { - return new (allocator) arm::InstructionSimplifierArm(graph, stats); -#endif -#ifdef ART_ENABLE_CODEGEN_arm64 - } else if (opt_name == arm64::InstructionSimplifierArm64::kInstructionSimplifierArm64PassName) { - return new (allocator) arm64::InstructionSimplifierArm64(graph, stats); -#endif -#ifdef ART_ENABLE_CODEGEN_mips - } else if (opt_name == mips::PcRelativeFixups::kPcRelativeFixupsMipsPassName) { - return new (allocator) mips::PcRelativeFixups(graph, codegen, stats); - } else if (opt_name == mips::InstructionSimplifierMips::kInstructionSimplifierMipsPassName) { - return new (allocator) mips::InstructionSimplifierMips(graph, codegen, stats); -#endif -#ifdef ART_ENABLE_CODEGEN_x86 - } else if (opt_name == x86::PcRelativeFixups::kPcRelativeFixupsX86PassName) { - return new (allocator) x86::PcRelativeFixups(graph, codegen, stats); - } else if (opt_name == x86::X86MemoryOperandGeneration::kX86MemoryOperandGenerationPassName) { - return new (allocator) x86::X86MemoryOperandGeneration(graph, codegen, stats); -#endif - } - return nullptr; -} - -static ArenaVector<HOptimization*> BuildOptimizations( - const std::vector<std::string>& pass_names, - ArenaAllocator* allocator, - HGraph* graph, - OptimizingCompilerStats* stats, - CodeGenerator* codegen, - CompilerDriver* driver, - const DexCompilationUnit& dex_compilation_unit, - VariableSizedHandleScope* handles) { - // Few HOptimizations constructors require SideEffectsAnalysis or HInductionVarAnalysis - // instances. This method assumes that each of them expects the nearest instance preceeding it - // in the pass name list. - SideEffectsAnalysis* most_recent_side_effects = nullptr; - HInductionVarAnalysis* most_recent_induction = nullptr; - LoadStoreAnalysis* most_recent_lsa = nullptr; - ArenaVector<HOptimization*> ret(allocator->Adapter()); - for (const std::string& pass_name : pass_names) { - HOptimization* opt = BuildOptimization( - pass_name, - allocator, - graph, - stats, - codegen, - driver, - dex_compilation_unit, - handles, - most_recent_side_effects, - most_recent_induction, - most_recent_lsa); - CHECK(opt != nullptr) << "Couldn't build optimization: \"" << pass_name << "\""; - ret.push_back(opt); - - std::string opt_name = ConvertPassNameToOptimizationName(pass_name); - if (opt_name == SideEffectsAnalysis::kSideEffectsAnalysisPassName) { - most_recent_side_effects = down_cast<SideEffectsAnalysis*>(opt); - } else if (opt_name == HInductionVarAnalysis::kInductionPassName) { - most_recent_induction = down_cast<HInductionVarAnalysis*>(opt); - } else if (opt_name == LoadStoreAnalysis::kLoadStoreAnalysisPassName) { - most_recent_lsa = down_cast<LoadStoreAnalysis*>(opt); - } - } - return ret; -} - -void OptimizingCompiler::RunOptimizations(HOptimization* optimizations[], - size_t length, - PassObserver* pass_observer) const { - for (size_t i = 0; i < length; ++i) { - PassScope scope(optimizations[i]->GetPassName(), pass_observer); - optimizations[i]->Run(); - } -} - void OptimizingCompiler::MaybeRunInliner(HGraph* graph, CodeGenerator* codegen, - CompilerDriver* driver, const DexCompilationUnit& dex_compilation_unit, PassObserver* pass_observer, VariableSizedHandleScope* handles) const { - OptimizingCompilerStats* stats = compilation_stats_.get(); - const CompilerOptions& compiler_options = driver->GetCompilerOptions(); + const CompilerOptions& compiler_options = GetCompilerDriver()->GetCompilerOptions(); bool should_inline = (compiler_options.GetInlineMaxCodeUnits() > 0); if (!should_inline) { return; } - size_t number_of_dex_registers = dex_compilation_unit.GetCodeItem()->registers_size_; - HInliner* inliner = new (graph->GetAllocator()) HInliner( - graph, // outer_graph - graph, // outermost_graph - codegen, - dex_compilation_unit, // outer_compilation_unit - dex_compilation_unit, // outermost_compilation_unit - driver, - handles, - stats, - number_of_dex_registers, - /* total_number_of_instructions */ 0, - /* parent */ nullptr); - HOptimization* optimizations[] = { inliner }; - - RunOptimizations(optimizations, arraysize(optimizations), pass_observer); + OptimizationDef optimizations[] = { + OptDef(OptimizationPass::kInliner) + }; + RunOptimizations(graph, + codegen, + dex_compilation_unit, + pass_observer, + handles, + optimizations); } -void OptimizingCompiler::RunArchOptimizations(InstructionSet instruction_set, - HGraph* graph, +void OptimizingCompiler::RunArchOptimizations(HGraph* graph, CodeGenerator* codegen, - PassObserver* pass_observer) const { - UNUSED(codegen); // To avoid compilation error when compiling for svelte - OptimizingCompilerStats* stats = compilation_stats_.get(); - ArenaAllocator* allocator = graph->GetAllocator(); - switch (instruction_set) { + const DexCompilationUnit& dex_compilation_unit, + PassObserver* pass_observer, + VariableSizedHandleScope* handles) const { + switch (GetCompilerDriver()->GetInstructionSet()) { #if defined(ART_ENABLE_CODEGEN_arm) case InstructionSet::kThumb2: case InstructionSet::kArm: { - arm::InstructionSimplifierArm* simplifier = - new (allocator) arm::InstructionSimplifierArm(graph, stats); - SideEffectsAnalysis* side_effects = new (allocator) SideEffectsAnalysis(graph); - GVNOptimization* gvn = - new (allocator) GVNOptimization(graph, *side_effects, "GVN$after_arch"); - HInstructionScheduling* scheduling = - new (allocator) HInstructionScheduling(graph, instruction_set, codegen); - HOptimization* arm_optimizations[] = { - simplifier, - side_effects, - gvn, - scheduling, + OptimizationDef arm_optimizations[] = { + OptDef(OptimizationPass::kInstructionSimplifierArm), + OptDef(OptimizationPass::kSideEffectsAnalysis), + OptDef(OptimizationPass::kGlobalValueNumbering, "GVN$after_arch"), + OptDef(OptimizationPass::kScheduling) }; - RunOptimizations(arm_optimizations, arraysize(arm_optimizations), pass_observer); + RunOptimizations(graph, + codegen, + dex_compilation_unit, + pass_observer, + handles, + arm_optimizations); break; } #endif #ifdef ART_ENABLE_CODEGEN_arm64 case InstructionSet::kArm64: { - arm64::InstructionSimplifierArm64* simplifier = - new (allocator) arm64::InstructionSimplifierArm64(graph, stats); - SideEffectsAnalysis* side_effects = new (allocator) SideEffectsAnalysis(graph); - GVNOptimization* gvn = - new (allocator) GVNOptimization(graph, *side_effects, "GVN$after_arch"); - HInstructionScheduling* scheduling = - new (allocator) HInstructionScheduling(graph, instruction_set); - HOptimization* arm64_optimizations[] = { - simplifier, - side_effects, - gvn, - scheduling, + OptimizationDef arm64_optimizations[] = { + OptDef(OptimizationPass::kInstructionSimplifierArm64), + OptDef(OptimizationPass::kSideEffectsAnalysis), + OptDef(OptimizationPass::kGlobalValueNumbering, "GVN$after_arch"), + OptDef(OptimizationPass::kScheduling) }; - RunOptimizations(arm64_optimizations, arraysize(arm64_optimizations), pass_observer); + RunOptimizations(graph, + codegen, + dex_compilation_unit, + pass_observer, + handles, + arm64_optimizations); break; } #endif #ifdef ART_ENABLE_CODEGEN_mips case InstructionSet::kMips: { - mips::InstructionSimplifierMips* simplifier = - new (allocator) mips::InstructionSimplifierMips(graph, codegen, stats); - SideEffectsAnalysis* side_effects = new (allocator) SideEffectsAnalysis(graph); - GVNOptimization* gvn = - new (allocator) GVNOptimization(graph, *side_effects, "GVN$after_arch"); - mips::PcRelativeFixups* pc_relative_fixups = - new (allocator) mips::PcRelativeFixups(graph, codegen, stats); - HOptimization* mips_optimizations[] = { - simplifier, - side_effects, - gvn, - pc_relative_fixups, + OptimizationDef mips_optimizations[] = { + OptDef(OptimizationPass::kInstructionSimplifierMips), + OptDef(OptimizationPass::kSideEffectsAnalysis), + OptDef(OptimizationPass::kGlobalValueNumbering, "GVN$after_arch"), + OptDef(OptimizationPass::kPcRelativeFixupsMips) }; - RunOptimizations(mips_optimizations, arraysize(mips_optimizations), pass_observer); + RunOptimizations(graph, + codegen, + dex_compilation_unit, + pass_observer, + handles, + mips_optimizations); break; } #endif #ifdef ART_ENABLE_CODEGEN_mips64 case InstructionSet::kMips64: { - SideEffectsAnalysis* side_effects = new (allocator) SideEffectsAnalysis(graph); - GVNOptimization* gvn = - new (allocator) GVNOptimization(graph, *side_effects, "GVN$after_arch"); - HOptimization* mips64_optimizations[] = { - side_effects, - gvn, + OptimizationDef mips64_optimizations[] = { + OptDef(OptimizationPass::kSideEffectsAnalysis), + OptDef(OptimizationPass::kGlobalValueNumbering, "GVN$after_arch") }; - RunOptimizations(mips64_optimizations, arraysize(mips64_optimizations), pass_observer); + RunOptimizations(graph, + codegen, + dex_compilation_unit, + pass_observer, + handles, + mips64_optimizations); break; } #endif #ifdef ART_ENABLE_CODEGEN_x86 case InstructionSet::kX86: { - SideEffectsAnalysis* side_effects = new (allocator) SideEffectsAnalysis(graph); - GVNOptimization* gvn = - new (allocator) GVNOptimization(graph, *side_effects, "GVN$after_arch"); - x86::PcRelativeFixups* pc_relative_fixups = - new (allocator) x86::PcRelativeFixups(graph, codegen, stats); - x86::X86MemoryOperandGeneration* memory_gen = - new (allocator) x86::X86MemoryOperandGeneration(graph, codegen, stats); - HOptimization* x86_optimizations[] = { - side_effects, - gvn, - pc_relative_fixups, - memory_gen + OptimizationDef x86_optimizations[] = { + OptDef(OptimizationPass::kSideEffectsAnalysis), + OptDef(OptimizationPass::kGlobalValueNumbering, "GVN$after_arch"), + OptDef(OptimizationPass::kPcRelativeFixupsX86), + OptDef(OptimizationPass::kX86MemoryOperandGeneration) }; - RunOptimizations(x86_optimizations, arraysize(x86_optimizations), pass_observer); + RunOptimizations(graph, + codegen, + dex_compilation_unit, + pass_observer, + handles, + x86_optimizations); break; } #endif #ifdef ART_ENABLE_CODEGEN_x86_64 case InstructionSet::kX86_64: { - SideEffectsAnalysis* side_effects = new (allocator) SideEffectsAnalysis(graph); - GVNOptimization* gvn = - new (allocator) GVNOptimization(graph, *side_effects, "GVN$after_arch"); - x86::X86MemoryOperandGeneration* memory_gen = - new (allocator) x86::X86MemoryOperandGeneration(graph, codegen, stats); - HOptimization* x86_64_optimizations[] = { - side_effects, - gvn, - memory_gen + OptimizationDef x86_64_optimizations[] = { + OptDef(OptimizationPass::kSideEffectsAnalysis), + OptDef(OptimizationPass::kGlobalValueNumbering, "GVN$after_arch"), + OptDef(OptimizationPass::kX86MemoryOperandGeneration) }; - RunOptimizations(x86_64_optimizations, arraysize(x86_64_optimizations), pass_observer); + RunOptimizations(graph, + codegen, + dex_compilation_unit, + pass_observer, + handles, + x86_64_optimizations); break; } #endif @@ -768,110 +595,93 @@ static void AllocateRegisters(HGraph* graph, } } +// Strip pass name suffix to get optimization name. +static std::string ConvertPassNameToOptimizationName(const std::string& pass_name) { + size_t pos = pass_name.find(kPassNameSeparator); + return pos == std::string::npos ? pass_name : pass_name.substr(0, pos); +} + void OptimizingCompiler::RunOptimizations(HGraph* graph, CodeGenerator* codegen, - CompilerDriver* driver, const DexCompilationUnit& dex_compilation_unit, PassObserver* pass_observer, VariableSizedHandleScope* handles) const { - OptimizingCompilerStats* stats = compilation_stats_.get(); - ArenaAllocator* allocator = graph->GetAllocator(); - if (driver->GetCompilerOptions().GetPassesToRun() != nullptr) { - ArenaVector<HOptimization*> optimizations = BuildOptimizations( - *driver->GetCompilerOptions().GetPassesToRun(), - allocator, - graph, - stats, - codegen, - driver, - dex_compilation_unit, - handles); - RunOptimizations(optimizations.data(), optimizations.size(), pass_observer); + const std::vector<std::string>* pass_names = + GetCompilerDriver()->GetCompilerOptions().GetPassesToRun(); + if (pass_names != nullptr) { + // If passes were defined on command-line, build the optimization + // passes and run these instead of the built-in optimizations. + const size_t length = pass_names->size(); + std::vector<OptimizationDef> optimizations; + for (const std::string& pass_name : *pass_names) { + std::string opt_name = ConvertPassNameToOptimizationName(pass_name); + optimizations.push_back(OptDef(OptimizationPassByName(opt_name.c_str()), pass_name.c_str())); + } + RunOptimizations(graph, + codegen, + dex_compilation_unit, + pass_observer, + handles, + optimizations.data(), + length); return; } - HDeadCodeElimination* dce1 = new (allocator) HDeadCodeElimination( - graph, stats, "dead_code_elimination$initial"); - HDeadCodeElimination* dce2 = new (allocator) HDeadCodeElimination( - graph, stats, "dead_code_elimination$after_inlining"); - HDeadCodeElimination* dce3 = new (allocator) HDeadCodeElimination( - graph, stats, "dead_code_elimination$final"); - HConstantFolding* fold1 = new (allocator) HConstantFolding(graph, "constant_folding"); - InstructionSimplifier* simplify1 = new (allocator) InstructionSimplifier( - graph, codegen, driver, stats); - HSelectGenerator* select_generator = new (allocator) HSelectGenerator(graph, handles, stats); - HConstantFolding* fold2 = new (allocator) HConstantFolding( - graph, "constant_folding$after_inlining"); - HConstantFolding* fold3 = new (allocator) HConstantFolding(graph, "constant_folding$after_bce"); - SideEffectsAnalysis* side_effects1 = new (allocator) SideEffectsAnalysis( - graph, "side_effects$before_gvn"); - SideEffectsAnalysis* side_effects2 = new (allocator) SideEffectsAnalysis( - graph, "side_effects$before_lse"); - GVNOptimization* gvn = new (allocator) GVNOptimization(graph, *side_effects1); - LICM* licm = new (allocator) LICM(graph, *side_effects1, stats); - HInductionVarAnalysis* induction = new (allocator) HInductionVarAnalysis(graph); - BoundsCheckElimination* bce = - new (allocator) BoundsCheckElimination(graph, *side_effects1, induction); - HLoopOptimization* loop = new (allocator) HLoopOptimization(graph, driver, induction, stats); - LoadStoreAnalysis* lsa = new (allocator) LoadStoreAnalysis(graph); - LoadStoreElimination* lse = - new (allocator) LoadStoreElimination(graph, *side_effects2, *lsa, stats); - HSharpening* sharpening = new (allocator) HSharpening( - graph, codegen, dex_compilation_unit, driver, handles); - InstructionSimplifier* simplify2 = new (allocator) InstructionSimplifier( - graph, codegen, driver, stats, "instruction_simplifier$after_inlining"); - InstructionSimplifier* simplify3 = new (allocator) InstructionSimplifier( - graph, codegen, driver, stats, "instruction_simplifier$after_bce"); - InstructionSimplifier* simplify4 = new (allocator) InstructionSimplifier( - graph, codegen, driver, stats, "instruction_simplifier$before_codegen"); - IntrinsicsRecognizer* intrinsics = new (allocator) IntrinsicsRecognizer(graph, stats); - CHAGuardOptimization* cha_guard = new (allocator) CHAGuardOptimization(graph); - CodeSinking* code_sinking = new (allocator) CodeSinking(graph, stats); - ConstructorFenceRedundancyElimination* cfre = - new (allocator) ConstructorFenceRedundancyElimination(graph, stats); - - HOptimization* optimizations1[] = { - intrinsics, - sharpening, - fold1, - simplify1, - dce1, + OptimizationDef optimizations1[] = { + OptDef(OptimizationPass::kIntrinsicsRecognizer), + OptDef(OptimizationPass::kSharpening), + OptDef(OptimizationPass::kConstantFolding), + OptDef(OptimizationPass::kInstructionSimplifier), + OptDef(OptimizationPass::kDeadCodeElimination, "dead_code_elimination$initial") }; - RunOptimizations(optimizations1, arraysize(optimizations1), pass_observer); + RunOptimizations(graph, + codegen, + dex_compilation_unit, + pass_observer, + handles, + optimizations1); - MaybeRunInliner(graph, codegen, driver, dex_compilation_unit, pass_observer, handles); + MaybeRunInliner(graph, codegen, dex_compilation_unit, pass_observer, handles); - HOptimization* optimizations2[] = { + OptimizationDef optimizations2[] = { // SelectGenerator depends on the InstructionSimplifier removing // redundant suspend checks to recognize empty blocks. - select_generator, - fold2, // TODO: if we don't inline we can also skip fold2. - simplify2, - dce2, - side_effects1, - gvn, - licm, - induction, - bce, - loop, - fold3, // evaluates code generated by dynamic bce - simplify3, - side_effects2, - lsa, - lse, - cha_guard, - dce3, - code_sinking, + OptDef(OptimizationPass::kSelectGenerator), + // TODO: if we don't inline we can also skip fold2. + OptDef(OptimizationPass::kConstantFolding, "constant_folding$after_inlining"), + OptDef(OptimizationPass::kInstructionSimplifier, "instruction_simplifier$after_inlining"), + OptDef(OptimizationPass::kDeadCodeElimination, "dead_code_elimination$after_inlining"), + OptDef(OptimizationPass::kSideEffectsAnalysis, "side_effects$before_gvn"), + OptDef(OptimizationPass::kGlobalValueNumbering), + OptDef(OptimizationPass::kInvariantCodeMotion), + OptDef(OptimizationPass::kInductionVarAnalysis), + OptDef(OptimizationPass::kBoundsCheckElimination), + OptDef(OptimizationPass::kLoopOptimization), + // Evaluates code generated by dynamic bce. + OptDef(OptimizationPass::kConstantFolding, "constant_folding$after_bce"), + OptDef(OptimizationPass::kInstructionSimplifier, "instruction_simplifier$after_bce"), + OptDef(OptimizationPass::kSideEffectsAnalysis, "side_effects$before_lse"), + OptDef(OptimizationPass::kLoadStoreAnalysis), + OptDef(OptimizationPass::kLoadStoreElimination), + OptDef(OptimizationPass::kCHAGuardOptimization), + OptDef(OptimizationPass::kDeadCodeElimination, "dead_code_elimination$final"), + OptDef(OptimizationPass::kCodeSinking), // The codegen has a few assumptions that only the instruction simplifier // can satisfy. For example, the code generator does not expect to see a // HTypeConversion from a type to the same type. - simplify4, - cfre, // Eliminate constructor fences after code sinking to avoid - // complicated sinking logic to split a fence with many inputs. + OptDef(OptimizationPass::kInstructionSimplifier, "instruction_simplifier$before_codegen"), + // Eliminate constructor fences after code sinking to avoid + // complicated sinking logic to split a fence with many inputs. + OptDef(OptimizationPass::kConstructorFenceRedundancyElimination) }; - RunOptimizations(optimizations2, arraysize(optimizations2), pass_observer); + RunOptimizations(graph, + codegen, + dex_compilation_unit, + pass_observer, + handles, + optimizations2); - RunArchOptimizations(driver->GetInstructionSet(), graph, codegen, pass_observer); + RunArchOptimizations(graph, codegen, dex_compilation_unit, pass_observer, handles); } static ArenaVector<linker::LinkerPatch> EmitAndSortLinkerPatches(CodeGenerator* codegen) { @@ -890,7 +700,6 @@ static ArenaVector<linker::LinkerPatch> EmitAndSortLinkerPatches(CodeGenerator* CompiledMethod* OptimizingCompiler::Emit(ArenaAllocator* allocator, CodeVectorAllocator* code_allocator, CodeGenerator* codegen, - CompilerDriver* compiler_driver, const DexFile::CodeItem* code_item_for_osr_check) const { ArenaVector<linker::LinkerPatch> linker_patches = EmitAndSortLinkerPatches(codegen); ArenaVector<uint8_t> stack_map(allocator->Adapter(kArenaAllocStackMaps)); @@ -905,7 +714,7 @@ CompiledMethod* OptimizingCompiler::Emit(ArenaAllocator* allocator, code_item_for_osr_check); CompiledMethod* compiled_method = CompiledMethod::SwapAllocCompiledMethod( - compiler_driver, + GetCompilerDriver(), codegen->GetInstructionSet(), ArrayRef<const uint8_t>(code_allocator->GetMemory()), // Follow Quick's behavior and set the frame size to zero if it is @@ -1049,7 +858,6 @@ CodeGenerator* OptimizingCompiler::TryCompile(ArenaAllocator* allocator, RunOptimizations(graph, codegen.get(), - compiler_driver, dex_compilation_unit, &pass_observer, handles); @@ -1140,20 +948,20 @@ CodeGenerator* OptimizingCompiler::TryCompileIntrinsic( builder.BuildIntrinsicGraph(method); } - OptimizingCompilerStats* stats = compilation_stats_.get(); - InstructionSimplifier* simplify = new (allocator) InstructionSimplifier( - graph, codegen.get(), compiler_driver, stats); - IntrinsicsRecognizer* intrinsics = new (allocator) IntrinsicsRecognizer(graph, stats); - - HOptimization* optimizations[] = { - intrinsics, - // Some intrinsics are converted to HIR by the simplifier and the codegen also - // has a few assumptions that only the instruction simplifier can satisfy. - simplify, + OptimizationDef optimizations[] = { + OptDef(OptimizationPass::kIntrinsicsRecognizer), + // Some intrinsics are converted to HIR by the simplifier and the codegen also + // has a few assumptions that only the instruction simplifier can satisfy. + OptDef(OptimizationPass::kInstructionSimplifier), }; - RunOptimizations(optimizations, arraysize(optimizations), &pass_observer); + RunOptimizations(graph, + codegen.get(), + dex_compilation_unit, + &pass_observer, + handles, + optimizations); - RunArchOptimizations(compiler_driver->GetInstructionSet(), graph, codegen.get(), &pass_observer); + RunArchOptimizations(graph, codegen.get(), dex_compilation_unit, &pass_observer, handles); AllocateRegisters(graph, codegen.get(), @@ -1243,7 +1051,6 @@ CompiledMethod* OptimizingCompiler::Compile(const DexFile::CodeItem* code_item, compiled_method = Emit(&allocator, &code_allocator, codegen.get(), - compiler_driver, compiled_intrinsic ? nullptr : code_item); if (compiled_intrinsic) { compiled_method->MarkAsIntrinsic(); @@ -1325,7 +1132,6 @@ CompiledMethod* OptimizingCompiler::JniCompile(uint32_t access_flags, CompiledMethod* compiled_method = Emit(&allocator, &code_allocator, codegen.get(), - GetCompilerDriver(), /* code_item_for_osr_check */ nullptr); compiled_method->MarkAsIntrinsic(); return compiled_method; diff --git a/compiler/optimizing/pc_relative_fixups_mips.h b/compiler/optimizing/pc_relative_fixups_mips.h index 5a7397bf9d..ec2c711f8d 100644 --- a/compiler/optimizing/pc_relative_fixups_mips.h +++ b/compiler/optimizing/pc_relative_fixups_mips.h @@ -29,7 +29,7 @@ namespace mips { class PcRelativeFixups : public HOptimization { public: PcRelativeFixups(HGraph* graph, CodeGenerator* codegen, OptimizingCompilerStats* stats) - : HOptimization(graph, "pc_relative_fixups_mips", stats), + : HOptimization(graph, kPcRelativeFixupsMipsPassName, stats), codegen_(codegen) {} static constexpr const char* kPcRelativeFixupsMipsPassName = "pc_relative_fixups_mips"; diff --git a/compiler/optimizing/scheduler.h b/compiler/optimizing/scheduler.h index a6e160379b..bb7c353bc2 100644 --- a/compiler/optimizing/scheduler.h +++ b/compiler/optimizing/scheduler.h @@ -495,8 +495,11 @@ inline bool SchedulingGraph::IsSchedulingBarrier(const HInstruction* instruction class HInstructionScheduling : public HOptimization { public: - HInstructionScheduling(HGraph* graph, InstructionSet instruction_set, CodeGenerator* cg = nullptr) - : HOptimization(graph, kInstructionScheduling), + HInstructionScheduling(HGraph* graph, + InstructionSet instruction_set, + CodeGenerator* cg = nullptr, + const char* name = kInstructionSchedulingPassName) + : HOptimization(graph, name), codegen_(cg), instruction_set_(instruction_set) {} @@ -505,7 +508,7 @@ class HInstructionScheduling : public HOptimization { } void Run(bool only_optimize_loop_blocks, bool schedule_randomly); - static constexpr const char* kInstructionScheduling = "scheduler"; + static constexpr const char* kInstructionSchedulingPassName = "scheduler"; private: CodeGenerator* const codegen_; diff --git a/compiler/optimizing/select_generator.cc b/compiler/optimizing/select_generator.cc index 77ec9a6285..66e51421ca 100644 --- a/compiler/optimizing/select_generator.cc +++ b/compiler/optimizing/select_generator.cc @@ -24,8 +24,9 @@ static constexpr size_t kMaxInstructionsInBranch = 1u; HSelectGenerator::HSelectGenerator(HGraph* graph, VariableSizedHandleScope* handles, - OptimizingCompilerStats* stats) - : HOptimization(graph, kSelectGeneratorPassName, stats), + OptimizingCompilerStats* stats, + const char* name) + : HOptimization(graph, name, stats), handle_scope_(handles) { } diff --git a/compiler/optimizing/select_generator.h b/compiler/optimizing/select_generator.h index f8cf00e35a..bda57fd5c8 100644 --- a/compiler/optimizing/select_generator.h +++ b/compiler/optimizing/select_generator.h @@ -65,7 +65,8 @@ class HSelectGenerator : public HOptimization { public: HSelectGenerator(HGraph* graph, VariableSizedHandleScope* handles, - OptimizingCompilerStats* stats); + OptimizingCompilerStats* stats, + const char* name = kSelectGeneratorPassName); void Run() OVERRIDE; diff --git a/compiler/optimizing/sharpening.h b/compiler/optimizing/sharpening.h index f74b0afdbf..bb1954eeeb 100644 --- a/compiler/optimizing/sharpening.h +++ b/compiler/optimizing/sharpening.h @@ -36,8 +36,9 @@ class HSharpening : public HOptimization { CodeGenerator* codegen, const DexCompilationUnit& compilation_unit, CompilerDriver* compiler_driver, - VariableSizedHandleScope* handles) - : HOptimization(graph, kSharpeningPassName), + VariableSizedHandleScope* handles, + const char* name = kSharpeningPassName) + : HOptimization(graph, name), codegen_(codegen), compilation_unit_(compilation_unit), compiler_driver_(compiler_driver), |