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/bounds_check_elimination.h b/compiler/optimizing/bounds_check_elimination.h
index 6dc5320..79c67a8 100644
--- a/compiler/optimizing/bounds_check_elimination.h
+++ b/compiler/optimizing/bounds_check_elimination.h
@@ -28,8 +28,9 @@
  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 ba0cdb8..f14e07b 100644
--- a/compiler/optimizing/cha_guard_optimization.h
+++ b/compiler/optimizing/cha_guard_optimization.h
@@ -26,8 +26,9 @@
  */
 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 59cda52..836d9d4 100644
--- a/compiler/optimizing/code_sinking.h
+++ b/compiler/optimizing/code_sinking.h
@@ -28,8 +28,10 @@
  */
 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 d89210c..f4b06d5 100644
--- a/compiler/optimizing/constructor_fence_redundancy_elimination.h
+++ b/compiler/optimizing/constructor_fence_redundancy_elimination.h
@@ -48,12 +48,13 @@
 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 e2747af..ad29ba5 100644
--- a/compiler/optimizing/induction_var_analysis.cc
+++ b/compiler/optimizing/induction_var_analysis.cc
@@ -97,8 +97,8 @@
 // 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 a2d302a..8737b89 100644
--- a/compiler/optimizing/induction_var_analysis.h
+++ b/compiler/optimizing/induction_var_analysis.h
@@ -35,7 +35,7 @@
  */
 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 c4b3a32..042eee3 100644
--- a/compiler/optimizing/inliner.h
+++ b/compiler/optimizing/inliner.h
@@ -44,8 +44,9 @@
            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 707ff34..818d7f6 100644
--- a/compiler/optimizing/intrinsics.h
+++ b/compiler/optimizing/intrinsics.h
@@ -37,8 +37,10 @@
 // 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 bf56f53..ee567ae 100644
--- a/compiler/optimizing/licm.h
+++ b/compiler/optimizing/licm.h
@@ -26,8 +26,11 @@
 
 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 aa8b5bb..437e6be 100644
--- a/compiler/optimizing/load_store_analysis.h
+++ b/compiler/optimizing/load_store_analysis.h
@@ -564,8 +564,8 @@
 
 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 20a8a76..7153541 100644
--- a/compiler/optimizing/load_store_elimination.h
+++ b/compiler/optimizing/load_store_elimination.h
@@ -29,8 +29,9 @@
   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 fcc59ea..1ca0960 100644
--- a/compiler/optimizing/loop_optimization.cc
+++ b/compiler/optimizing/loop_optimization.cc
@@ -448,8 +448,9 @@
 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 51e0a98..a707ad1 100644
--- a/compiler/optimizing/loop_optimization.h
+++ b/compiler/optimizing/loop_optimization.h
@@ -37,7 +37,8 @@
   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 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
diff --git a/compiler/optimizing/optimization.h b/compiler/optimizing/optimization.h
index ce41a2e..c170f15 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 @@
   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 4974ed0..53f9ec4 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 @@
  private:
   void RunOptimizations(HGraph* graph,
                         CodeGenerator* codegen,
-                        CompilerDriver* driver,
+                        const DexCompilationUnit& dex_compilation_unit,
+                        PassObserver* pass_observer,
+                        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();
+    }
+  }
+
+  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;
 
-  void RunOptimizations(HOptimization* optimizations[],
-                        size_t length,
-                        PassObserver* pass_observer) 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 @@
 
   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 @@
       || 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 @@
   }
 }
 
+// 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 @@
 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 @@
                           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 @@
 
   RunOptimizations(graph,
                    codegen.get(),
-                   compiler_driver,
                    dex_compilation_unit,
                    &pass_observer,
                    handles);
@@ -1140,20 +948,20 @@
     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 @@
       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* 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 5a7397b..ec2c711 100644
--- a/compiler/optimizing/pc_relative_fixups_mips.h
+++ b/compiler/optimizing/pc_relative_fixups_mips.h
@@ -29,7 +29,7 @@
 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 a6e1603..bb7c353 100644
--- a/compiler/optimizing/scheduler.h
+++ b/compiler/optimizing/scheduler.h
@@ -495,8 +495,11 @@
 
 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 @@
   }
   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 77ec9a6..66e5142 100644
--- a/compiler/optimizing/select_generator.cc
+++ b/compiler/optimizing/select_generator.cc
@@ -24,8 +24,9 @@
 
 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 f8cf00e..bda57fd 100644
--- a/compiler/optimizing/select_generator.h
+++ b/compiler/optimizing/select_generator.h
@@ -65,7 +65,8 @@
  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 f74b0af..bb1954e 100644
--- a/compiler/optimizing/sharpening.h
+++ b/compiler/optimizing/sharpening.h
@@ -36,8 +36,9 @@
               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),