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
diff --git a/compiler/optimizing/optimization.cc b/compiler/optimizing/optimization.cc
index 1e68ca2..7edb642 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