Added pass framework

The patch adds a Middle-End pass system and normalizes the current
 passes into the pass framework.

Passes have:
 - A start, work, and end functions.
 - A gate to determine to apply the pass.
 - Can provide a CFG dump folder.

mir_dataflow.cc, mir_graph.cc, mir_optimization.cc, ssa_transformation.cc:
 - Changed due to moving code into bb_optimizations.cc.
 - Moved certain functions from private to public due to needed from the passes.

pass.cc, pass.h:
 - Pass base class

pass_driver.cc, pass_driver.h:
 - The pass driver implementation.

frontend.cc:
 - Replace the function calls to the passes with the pass driver.

Change-Id: I88cd82efbf6499df9e6c7f135d7e294dd724a079
Signed-off-by: Jean Christophe Beyler <jean.christophe.beyler@intel.com>
diff --git a/compiler/Android.mk b/compiler/Android.mk
index d9a573f..4340929 100644
--- a/compiler/Android.mk
+++ b/compiler/Android.mk
@@ -54,6 +54,8 @@
 	dex/dex_to_dex_compiler.cc \
 	dex/mir_dataflow.cc \
 	dex/mir_optimization.cc \
+	dex/pass_driver.cc \
+	dex/bb_optimizations.cc \
 	dex/frontend.cc \
 	dex/mir_graph.cc \
 	dex/mir_analysis.cc \
diff --git a/compiler/dex/bb_optimizations.cc b/compiler/dex/bb_optimizations.cc
new file mode 100644
index 0000000..f013067
--- /dev/null
+++ b/compiler/dex/bb_optimizations.cc
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "bb_optimizations.h"
+#include "dataflow_iterator.h"
+#include "dataflow_iterator-inl.h"
+
+namespace art {
+
+/*
+ * Code Layout pass implementation start.
+ */
+bool CodeLayout::WalkBasicBlocks(CompilationUnit *cUnit, BasicBlock *bb) const {
+  cUnit->mir_graph->LayoutBlocks(bb);
+  // No need of repeating, so just return false.
+  return false;
+}
+
+/*
+ * SSATransformation pass implementation start.
+ */
+bool SSATransformation::WalkBasicBlocks(CompilationUnit *cUnit, BasicBlock *bb) const {
+  cUnit->mir_graph->InsertPhiNodeOperands(bb);
+  // No need of repeating, so just return false.
+  return false;
+}
+
+void SSATransformation::End(CompilationUnit *cUnit) const {
+  // Verify the dataflow information after the pass.
+  if (cUnit->enable_debug & (1 << kDebugVerifyDataflow)) {
+    cUnit->mir_graph->VerifyDataflow();
+  }
+}
+
+/*
+ * ConstantPropagation pass implementation start
+ */
+bool ConstantPropagation::WalkBasicBlocks(CompilationUnit *cUnit, BasicBlock *bb) const {
+  cUnit->mir_graph->DoConstantPropagation(bb);
+  // No need of repeating, so just return false.
+  return false;
+}
+
+/*
+ * MethodUseCount pass implementation start.
+ */
+bool MethodUseCount::Gate(const CompilationUnit *cUnit) const {
+  // First initialize the data.
+  cUnit->mir_graph->InitializeMethodUses();
+
+  // Now check if the pass is to be ignored.
+  bool res = ((cUnit->disable_opt & (1 << kPromoteRegs)) == 0);
+
+  return res;
+}
+
+bool MethodUseCount::WalkBasicBlocks(CompilationUnit *cUnit, BasicBlock *bb) const {
+  cUnit->mir_graph->CountUses(bb);
+  // No need of repeating, so just return false.
+  return false;
+}
+
+/*
+ * Null Check Elimination and Type Inference Initialization pass implementation start.
+ */
+
+bool NullCheckEliminationAndTypeInferenceInit::Gate(const CompilationUnit *cUnit) const {
+  // First check the ssa register vector
+  cUnit->mir_graph->CheckSSARegisterVector();
+
+  // Did we disable the pass?
+  bool performInit = ((cUnit->disable_opt & (1 << kNullCheckElimination)) == 0);
+
+  return performInit;
+}
+
+bool NullCheckEliminationAndTypeInferenceInit::WalkBasicBlocks(CompilationUnit *cUnit, BasicBlock *bb) const {
+  cUnit->mir_graph->NullCheckEliminationInit(bb);
+  // No need of repeating, so just return false.
+  return false;
+}
+
+/*
+ * BasicBlock Combine pass implementation start.
+ */
+bool BBCombine::WalkBasicBlocks(CompilationUnit *cUnit, BasicBlock *bb) const {
+  cUnit->mir_graph->CombineBlocks(bb);
+
+  // No need of repeating, so just return false.
+  return false;
+}
+
+/*
+ * BasicBlock Optimization pass implementation start.
+ */
+void BBOptimizations::Start(CompilationUnit *cUnit) const {
+  DCHECK_EQ(cUnit->num_compiler_temps, 0);
+
+  /*
+   * This pass has a different ordering depEnding on the suppress exception,
+   * so do the pass here for now:
+   *   - Later, the Start should just change the ordering and we can move the extended
+   *     creation into the pass driver's main job with a new iterator
+   */
+  cUnit->mir_graph->BasicBlockOptimization();
+}
+
+}  // namespace art
diff --git a/compiler/dex/bb_optimizations.h b/compiler/dex/bb_optimizations.h
new file mode 100644
index 0000000..768b273
--- /dev/null
+++ b/compiler/dex/bb_optimizations.h
@@ -0,0 +1,165 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ART_COMPILER_DEX_BB_OPTIMIZATIONS_H_
+#define ART_COMPILER_DEX_BB_OPTIMIZATIONS_H_
+
+#include "compiler_internals.h"
+#include "pass.h"
+
+namespace art {
+
+/**
+ * @class CodeLayout
+ * @brief Perform the code layout pass.
+ */
+class CodeLayout : public Pass {
+ public:
+  CodeLayout():Pass("CodeLayout", "2_post_layout_cfg") {
+  }
+
+  void Start(CompilationUnit *cUnit) const {
+    cUnit->mir_graph->VerifyDataflow();
+  }
+
+  bool WalkBasicBlocks(CompilationUnit *cUnit, BasicBlock *bb) const;
+};
+
+/**
+ * @class SSATransformation
+ * @brief Perform an SSA representation pass on the CompilationUnit.
+ */
+class SSATransformation : public Pass {
+ public:
+  SSATransformation():Pass("SSATransformation", kPreOrderDFSTraversal, "3_post_ssa_cfg") {
+  }
+
+  bool WalkBasicBlocks(CompilationUnit *cUnit, BasicBlock *bb) const;
+
+  void Start(CompilationUnit *cUnit) const {
+    cUnit->mir_graph->InitializeSSATransformation();
+  }
+
+  void End(CompilationUnit *cUnit) const;
+};
+
+/**
+ * @class ConstantPropagation
+ * @brief Perform a constant propagation pass.
+ */
+class ConstantPropagation : public Pass {
+ public:
+  ConstantPropagation():Pass("ConstantPropagation") {
+  }
+
+  bool WalkBasicBlocks(CompilationUnit *cUnit, BasicBlock *bb) const;
+
+  void Start(CompilationUnit *cUnit) const {
+    cUnit->mir_graph->InitializeConstantPropagation();
+  }
+};
+
+/**
+ * @class InitRegLocations
+ * @brief Initialize Register Locations.
+ */
+class InitRegLocations : public Pass {
+ public:
+  InitRegLocations():Pass("InitRegLocation") {
+  }
+
+  void Start(CompilationUnit *cUnit) const {
+    cUnit->mir_graph->InitRegLocations();
+  }
+};
+
+/**
+ * @class MethodUseCount
+ * @brief Count the register uses of the method
+ */
+class MethodUseCount : public Pass {
+ public:
+  MethodUseCount():Pass("UseCount") {
+  }
+
+  bool WalkBasicBlocks(CompilationUnit *cUnit, BasicBlock *bb) const;
+
+  bool Gate(const CompilationUnit *cUnit) const;
+};
+
+/**
+ * @class NullCheckEliminationAndTypeInferenceInit
+ * @brief Null check elimination and type inference initialization step.
+ */
+class NullCheckEliminationAndTypeInferenceInit : public Pass {
+ public:
+  NullCheckEliminationAndTypeInferenceInit():Pass("NCE_TypeInferenceInit") {
+  }
+
+  bool WalkBasicBlocks(CompilationUnit *cUnit, BasicBlock *bb) const;
+
+  bool Gate(const CompilationUnit *cUnit) const;
+};
+
+/**
+ * @class NullCheckEliminationAndTypeInference
+ * @brief Null check elimination and type inference.
+ */
+class NullCheckEliminationAndTypeInference : public Pass {
+ public:
+  NullCheckEliminationAndTypeInference():Pass("NCE_TypeInference", kRepeatingPreOrderDFSTraversal, "4_post_nce_cfg") {
+  }
+
+  bool WalkBasicBlocks(CompilationUnit *cUnit, BasicBlock *bb) const {
+    return cUnit->mir_graph->EliminateNullChecksAndInferTypes(bb);
+  }
+};
+
+/**
+ * @class NullCheckEliminationAndTypeInference
+ * @brief Null check elimination and type inference.
+ */
+class BBCombine : public Pass {
+ public:
+  BBCombine():Pass("BBCombine", kPreOrderDFSTraversal, "5_post_bbcombine_cfg") {
+  }
+
+  bool Gate(const CompilationUnit *cUnit) const {
+    return ((cUnit->disable_opt & (1 << kSuppressExceptionEdges)) != 0);
+  }
+
+  bool WalkBasicBlocks(CompilationUnit *cUnit, BasicBlock *bb) const;
+};
+
+/**
+ * @class BasicBlock Optimizations
+ * @brief Any simple BasicBlock optimization can be put here.
+ */
+class BBOptimizations : public Pass {
+ public:
+  BBOptimizations():Pass("BBOptimizations", "5_post_bbo_cfg") {
+  }
+
+  bool Gate(const CompilationUnit *cUnit) const {
+    return ((cUnit->disable_opt & (1 << kBBOpt)) == 0);
+  }
+
+  void Start(CompilationUnit *cUnit) const;
+};
+
+}  // namespace art
+
+#endif  // ART_COMPILER_DEX_BB_OPTIMIZATIONS_H_
diff --git a/compiler/dex/dataflow_iterator.h b/compiler/dex/dataflow_iterator.h
index 12f924e..658a9b1 100644
--- a/compiler/dex/dataflow_iterator.h
+++ b/compiler/dex/dataflow_iterator.h
@@ -138,6 +138,21 @@
 
         return ForwardSingleNext();
       }
+
+      /**
+       * @brief Redefine the new operator to use the arena
+       * @param size actually unused, we use our own class size
+       * @param arena the arena to perform the actual allocation
+       * @return the pointer to the newly allocated object
+       */
+      static void* operator new(size_t size, ArenaAllocator* arena) {
+        return arena->Alloc(sizeof(PreOrderDfsIterator), ArenaAllocator::kAllocGrowableBitMap);
+      }
+
+      /**
+       * @brief Redefine delete to not actually delete anything since we are using the arena
+       */
+      static void operator delete(void* p) {}
   };
 
   /**
@@ -169,6 +184,21 @@
 
         return ForwardRepeatNext();
       }
+
+      /**
+       * @brief Redefine the new operator to use the arena
+       * @param size actually unused, we use our own class size
+       * @param arena the arena to perform the actual allocation
+       * @return the pointer to the newly allocated object
+       */
+      static void* operator new(size_t size, ArenaAllocator* arena) {
+        return arena->Alloc(sizeof(RepeatingPreOrderDfsIterator), ArenaAllocator::kAllocGrowableBitMap);
+      }
+
+      /**
+       * @brief Redefine delete to not actually delete anything since we are using the arena
+       */
+      static void operator delete(void* p) {}
   };
 
   /**
@@ -200,6 +230,21 @@
 
         return ForwardRepeatNext();
       }
+
+      /**
+       * @brief Redefine the new operator to use the arena
+       * @param size actually unused, we use our own class size
+       * @param arena the arena to perform the actual allocation
+       * @return the pointer to the newly allocated object
+       */
+      static void* operator new(size_t size, ArenaAllocator* arena) {
+        return arena->Alloc(sizeof(RepeatingPostOrderDfsIterator), ArenaAllocator::kAllocGrowableBitMap);
+      }
+
+      /**
+       * @brief Redefine delete to not actually delete anything since we are using the arena
+       */
+      static void operator delete(void* p) {}
   };
 
   /**
@@ -230,6 +275,21 @@
 
         return ReverseSingleNext();
       }
+
+      /**
+       * @brief Redefine the new operator to use the arena
+       * @param size actually unused, we use our own class size
+       * @param arena the arena to perform the actual allocation
+       * @return the pointer to the newly allocated object
+       */
+      static void* operator new(size_t size, ArenaAllocator* arena) {
+        return arena->Alloc(sizeof(ReversePostOrderDfsIterator), ArenaAllocator::kAllocGrowableBitMap);
+      }
+
+      /**
+       * @brief Redefine delete to not actually delete anything since we are using the arena
+       */
+      static void operator delete(void* p) {}
   };
 
   /**
@@ -261,6 +321,21 @@
 
         return ReverseRepeatNext();
       }
+
+      /**
+       * @brief Redefine the new operator to use the arena
+       * @param size actually unused, we use our own class size
+       * @param arena the arena to perform the actual allocation
+       * @return the pointer to the newly allocated object
+       */
+      static void* operator new(size_t size, ArenaAllocator* arena) {
+        return arena->Alloc(sizeof(RepeatingReversePostOrderDfsIterator), ArenaAllocator::kAllocGrowableBitMap);
+      }
+
+      /**
+       * @brief Redefine delete to not actually delete anything since we are using the arena
+       */
+      static void operator delete(void* p) {}
   };
 
   /**
@@ -291,6 +366,21 @@
 
         return ForwardSingleNext();
       }
+
+      /**
+       * @brief Redefine the new operator to use the arena
+       * @param size actually unused, we use our own class size
+       * @param arena the arena to perform the actual allocation
+       * @return the pointer to the newly allocated object
+       */
+      static void* operator new(size_t size, ArenaAllocator* arena) {
+        return arena->Alloc(sizeof(PostOrderDOMIterator), ArenaAllocator::kAllocGrowableBitMap);
+      }
+
+      /**
+       * @brief Redefine delete to not actually delete anything since we are using the arena
+       */
+      static void operator delete(void* p) {}
   };
 
   /**
@@ -323,6 +413,21 @@
        */
       virtual BasicBlock* Next(bool had_change = false) ALWAYS_INLINE;
 
+      /**
+       * @brief Redefine the new operator to use the arena
+       * @param size actually unused, we use our own class size
+       * @param arena the arena to perform the actual allocation
+       * @return the pointer to the newly allocated object
+       */
+      static void* operator new(size_t size, ArenaAllocator* arena) {
+        return arena->Alloc(sizeof(AllNodesIterator), ArenaAllocator::kAllocGrowableBitMap);
+      }
+
+      /**
+       * @brief Redefine delete to not actually delete anything since we are using the arena
+       */
+      static void operator delete(void* p) {}
+
     private:
       GrowableArray<BasicBlock*>::Iterator* all_nodes_iterator_;    /**< @brief The list of all the nodes */
   };
diff --git a/compiler/dex/frontend.cc b/compiler/dex/frontend.cc
index adfbf2f..f5bb85a 100644
--- a/compiler/dex/frontend.cc
+++ b/compiler/dex/frontend.cc
@@ -21,6 +21,7 @@
 #include "dataflow_iterator-inl.h"
 #include "leb128.h"
 #include "mirror/object.h"
+#include "pass_driver.h"
 #include "runtime.h"
 #include "backend.h"
 #include "base/logging.h"
@@ -251,36 +252,9 @@
   }
 #endif
 
-  /* Do a code layout pass */
-  cu.NewTimingSplit("MIROpt:CodeLayout");
-  cu.mir_graph->CodeLayout();
-
-  /* Perform SSA transformation for the whole method */
-  cu.NewTimingSplit("MIROpt:SSATransform");
-  cu.mir_graph->SSATransformation();
-
-  /* Do constant propagation */
-  cu.NewTimingSplit("MIROpt:ConstantProp");
-  cu.mir_graph->PropagateConstants();
-
-  cu.NewTimingSplit("MIROpt:InitRegLoc");
-  cu.mir_graph->InitRegLocations();
-
-  /* Count uses */
-  cu.NewTimingSplit("MIROpt:UseCount");
-  cu.mir_graph->MethodUseCount();
-
-  /* Perform null check elimination and type inference*/
-  cu.NewTimingSplit("MIROpt:NCE_TypeInference");
-  cu.mir_graph->NullCheckEliminationAndTypeInference();
-
-  /* Combine basic blocks where possible */
-  cu.NewTimingSplit("MIROpt:BBCombine");
-  cu.mir_graph->BasicBlockCombine();
-
-  /* Do some basic block optimizations */
-  cu.NewTimingSplit("MIROpt:BBOpt");
-  cu.mir_graph->BasicBlockOptimization();
+  /* Create the pass driver and launch it */
+  PassDriver driver(&cu);
+  driver.Launch();
 
   if (cu.enable_debug & (1 << kDebugDumpCheckStats)) {
     cu.mir_graph->DumpCheckStats();
diff --git a/compiler/dex/mir_dataflow.cc b/compiler/dex/mir_dataflow.cc
index 728d48ad..c235448 100644
--- a/compiler/dex/mir_dataflow.cc
+++ b/compiler/dex/mir_dataflow.cc
@@ -1235,9 +1235,9 @@
  * counts explicitly used s_regs.  A later phase will add implicit
  * counts for things such as Method*, null-checked references, etc.
  */
-bool MIRGraph::CountUses(struct BasicBlock* bb) {
+void MIRGraph::CountUses(struct BasicBlock* bb) {
   if (bb->block_type != kDalvikByteCode) {
-    return false;
+    return;
   }
   // Each level of nesting adds *100 to count, up to 3 levels deep.
   uint32_t depth = std::min(3U, static_cast<uint32_t>(bb->nesting_depth));
@@ -1269,26 +1269,6 @@
       }
     }
   }
-  return false;
-}
-
-void MIRGraph::MethodUseCount() {
-  // Now that we know, resize the lists.
-  int num_ssa_regs = GetNumSSARegs();
-  use_counts_.Resize(num_ssa_regs + 32);
-  raw_use_counts_.Resize(num_ssa_regs + 32);
-  // Initialize list
-  for (int i = 0; i < num_ssa_regs; i++) {
-    use_counts_.Insert(0);
-    raw_use_counts_.Insert(0);
-  }
-  if (cu_->disable_opt & (1 << kPromoteRegs)) {
-    return;
-  }
-  AllNodesIterator iter(this);
-  for (BasicBlock* bb = iter.Next(); bb != NULL; bb = iter.Next()) {
-    CountUses(bb);
-  }
 }
 
 /* Verify if all the successor is connected with all the claimed predecessors */
diff --git a/compiler/dex/mir_graph.cc b/compiler/dex/mir_graph.cc
index b1c0b28..8d1653f 100644
--- a/compiler/dex/mir_graph.cc
+++ b/compiler/dex/mir_graph.cc
@@ -1147,4 +1147,53 @@
   return bb;
 }
 
+void MIRGraph::InitializeConstantPropagation() {
+  is_constant_v_ = new (arena_) ArenaBitVector(arena_, GetNumSSARegs(), false);
+  constant_values_ = static_cast<int*>(arena_->Alloc(sizeof(int) * GetNumSSARegs(), ArenaAllocator::kAllocDFInfo));
+}
+
+void MIRGraph::InitializeMethodUses() {
+  // The gate starts by initializing the use counts
+  int num_ssa_regs = GetNumSSARegs();
+  use_counts_.Resize(num_ssa_regs + 32);
+  raw_use_counts_.Resize(num_ssa_regs + 32);
+  // Initialize list
+  for (int i = 0; i < num_ssa_regs; i++) {
+    use_counts_.Insert(0);
+    raw_use_counts_.Insert(0);
+  }
+}
+
+void MIRGraph::InitializeSSATransformation() {
+  /* Compute the DFS order */
+  ComputeDFSOrders();
+
+  /* Compute the dominator info */
+  ComputeDominators();
+
+  /* Allocate data structures in preparation for SSA conversion */
+  CompilerInitializeSSAConversion();
+
+  /* Find out the "Dalvik reg def x block" relation */
+  ComputeDefBlockMatrix();
+
+  /* Insert phi nodes to dominance frontiers for all variables */
+  InsertPhiNodes();
+
+  /* Rename register names by local defs and phi nodes */
+  ClearAllVisitedFlags();
+  DoDFSPreOrderSSARename(GetEntryBlock());
+
+  /*
+   * Shared temp bit vector used by each block to count the number of defs
+   * from all the predecessor blocks.
+   */
+  temp_ssa_register_v_ =
+    new (arena_) ArenaBitVector(arena_, GetNumSSARegs(), false, kBitMapTempSSARegisterV);
+}
+
+void MIRGraph::CheckSSARegisterVector() {
+  DCHECK(temp_ssa_register_v_ != nullptr);
+}
+
 }  // namespace art
diff --git a/compiler/dex/mir_graph.h b/compiler/dex/mir_graph.h
index d080e39..b68e699 100644
--- a/compiler/dex/mir_graph.h
+++ b/compiler/dex/mir_graph.h
@@ -615,17 +615,12 @@
     return opcode >= static_cast<int>(kMirOpFirst);
   }
 
-  void BasicBlockCombine();
-  void CodeLayout();
   void DumpCheckStats();
-  void PropagateConstants();
   MIR* FindMoveResult(BasicBlock* bb, MIR* mir);
   int SRegToVReg(int ssa_reg) const;
   void VerifyDataflow();
-  void MethodUseCount();
-  void SSATransformation();
   void CheckForDominanceFrontier(BasicBlock* dom_bb, const BasicBlock* succ_bb);
-  void NullCheckEliminationAndTypeInference();
+  bool EliminateNullChecksAndInferTypes(BasicBlock *bb);
   /*
    * Type inference handling helpers.  Because Dalvik's bytecode is not fully typed,
    * we have to do some work to figure out the sreg type.  For some operations it is
@@ -670,6 +665,58 @@
   BasicBlock* NextDominatedBlock(BasicBlock* bb);
   bool LayoutBlocks(BasicBlock* bb);
 
+  /**
+   * @brief Perform the initial preparation for the Method Uses.
+   */
+  void InitializeMethodUses();
+
+  /**
+   * @brief Perform the initial preparation for the Constant Propagation.
+   */
+  void InitializeConstantPropagation();
+
+  /**
+   * @brief Perform the initial preparation for the SSA Transformation.
+   */
+  void InitializeSSATransformation();
+
+  /**
+   * @brief Insert a the operands for the Phi nodes.
+   * @param bb the considered BasicBlock.
+   * @return true
+   */
+  bool InsertPhiNodeOperands(BasicBlock* bb);
+
+  /**
+   * @brief Perform constant propagation on a BasicBlock.
+   * @param bb the considered BasicBlock.
+   */
+  void DoConstantPropagation(BasicBlock* bb);
+
+  /**
+   * @brief Count the uses in the BasicBlock
+   * @param bb the BasicBlock
+   */
+  void CountUses(struct BasicBlock* bb);
+
+  /**
+   * @brief Initialize the data structures with Null Check data
+   * @param bb the considered BasicBlock
+   */
+  void NullCheckEliminationInit(BasicBlock* bb);
+
+  /**
+   * @brief Check if the temporary ssa register vector is allocated
+   */
+  void CheckSSARegisterVector();
+
+  /**
+   * @brief Combine BasicBlocks
+   * @param the BasicBlock we are considering
+   */
+  void CombineBlocks(BasicBlock* bb);
+
+  void ClearAllVisitedFlags();
   /*
    * IsDebugBuild sanity check: keep track of the Dex PCs for catch entries so that later on
    * we can verify that all catch entries have native PC entries.
@@ -715,8 +762,6 @@
   void DataFlowSSAFormat35C(MIR* mir);
   void DataFlowSSAFormat3RC(MIR* mir);
   bool FindLocalLiveIn(BasicBlock* bb);
-  void ClearAllVisitedFlags();
-  bool CountUses(struct BasicBlock* bb);
   bool InferTypeAndSize(BasicBlock* bb, MIR* mir, bool changed);
   bool VerifyPredInfo(BasicBlock* bb);
   BasicBlock* NeedsVisit(BasicBlock* bb);
@@ -733,8 +778,6 @@
   void SetConstantWide(int ssa_reg, int64_t value);
   int GetSSAUseCount(int s_reg);
   bool BasicBlockOpt(BasicBlock* bb);
-  bool EliminateNullChecksAndInferTypes(BasicBlock* bb);
-  void NullCheckEliminationInit(BasicBlock* bb);
   bool BuildExtendedBBList(struct BasicBlock* bb);
   bool FillDefBlockMatrix(BasicBlock* bb);
   void InitializeDominationInfo(BasicBlock* bb);
@@ -742,11 +785,9 @@
   bool ComputeBlockDominators(BasicBlock* bb);
   bool SetDominators(BasicBlock* bb);
   bool ComputeBlockLiveIns(BasicBlock* bb);
-  bool InsertPhiNodeOperands(BasicBlock* bb);
   bool ComputeDominanceFrontier(BasicBlock* bb);
-  void DoConstantPropogation(BasicBlock* bb);
+
   void CountChecks(BasicBlock* bb);
-  bool CombineBlocks(BasicBlock* bb);
   void AnalyzeBlock(BasicBlock* bb, struct MethodStats* stats);
   bool ComputeSkipCompilation(struct MethodStats* stats, bool skip_default);
 
diff --git a/compiler/dex/mir_optimization.cc b/compiler/dex/mir_optimization.cc
index 5d83991..ee9f28e 100644
--- a/compiler/dex/mir_optimization.cc
+++ b/compiler/dex/mir_optimization.cc
@@ -36,7 +36,7 @@
   constant_values_[ssa_reg + 1] = High32Bits(value);
 }
 
-void MIRGraph::DoConstantPropogation(BasicBlock* bb) {
+void MIRGraph::DoConstantPropagation(BasicBlock* bb) {
   MIR* mir;
 
   for (mir = bb->first_mir_insn; mir != NULL; mir = mir->next) {
@@ -92,16 +92,6 @@
   /* TODO: implement code to handle arithmetic operations */
 }
 
-void MIRGraph::PropagateConstants() {
-  is_constant_v_ = new (arena_) ArenaBitVector(arena_, GetNumSSARegs(), false);
-  constant_values_ = static_cast<int*>(arena_->Alloc(sizeof(int) * GetNumSSARegs(),
-                                                     ArenaAllocator::kAllocDFInfo));
-  AllNodesIterator iter(this);
-  for (BasicBlock* bb = iter.Next(); bb != NULL; bb = iter.Next()) {
-    DoConstantPropogation(bb);
-  }
-}
-
 /* Advance to next strictly dominated MIR node in an extended basic block */
 MIR* MIRGraph::AdvanceMIR(BasicBlock** p_bb, MIR* mir) {
   BasicBlock* bb = *p_bb;
@@ -557,7 +547,7 @@
 }
 
 /* Combine any basic blocks terminated by instructions that we now know can't throw */
-bool MIRGraph::CombineBlocks(struct BasicBlock* bb) {
+void MIRGraph::CombineBlocks(struct BasicBlock* bb) {
   // Loop here to allow combining a sequence of blocks
   while (true) {
     // Check termination conditions
@@ -621,14 +611,13 @@
 
     // Now, loop back and see if we can keep going
   }
-  return false;
 }
 
 /*
  * Eliminate unnecessary null checks for a basic block.   Also, while we're doing
  * an iterative walk go ahead and perform type and size inference.
  */
-bool MIRGraph::EliminateNullChecksAndInferTypes(struct BasicBlock* bb) {
+bool MIRGraph::EliminateNullChecksAndInferTypes(BasicBlock* bb) {
   if (bb->data_flow_info == NULL) return false;
   bool infer_changed = false;
   bool do_nce = ((cu_->disable_opt & (1 << kNullCheckElimination)) == 0);
@@ -810,49 +799,6 @@
   return infer_changed | nce_changed;
 }
 
-void MIRGraph::NullCheckEliminationAndTypeInference() {
-  DCHECK(temp_ssa_register_v_ != NULL);
-  if ((cu_->disable_opt & (1 << kNullCheckElimination)) == 0) {
-    AllNodesIterator iter(this);
-    for (BasicBlock* bb = iter.Next(); bb != NULL; bb = iter.Next()) {
-      NullCheckEliminationInit(bb);
-    }
-  }
-  RepeatingPreOrderDfsIterator iter2(this);
-  bool change = false;
-  for (BasicBlock* bb = iter2.Next(change); bb != NULL; bb = iter2.Next(change)) {
-    change = EliminateNullChecksAndInferTypes(bb);
-  }
-  if (cu_->enable_debug & (1 << kDebugDumpCFG)) {
-    DumpCFG("/sdcard/4_post_nce_cfg/", false);
-  }
-}
-
-void MIRGraph::BasicBlockCombine() {
-  if ((cu_->disable_opt & (1 << kSuppressExceptionEdges)) != 0) {
-    PreOrderDfsIterator iter(this);
-    for (BasicBlock* bb = iter.Next(); bb != NULL; bb = iter.Next()) {
-      CombineBlocks(bb);
-    }
-    if (cu_->enable_debug & (1 << kDebugDumpCFG)) {
-      DumpCFG("/sdcard/5_post_bbcombine_cfg/", false);
-    }
-  }
-}
-
-void MIRGraph::CodeLayout() {
-  if (cu_->enable_debug & (1 << kDebugVerifyDataflow)) {
-    VerifyDataflow();
-  }
-  AllNodesIterator iter(this);
-  for (BasicBlock* bb = iter.Next(); bb != NULL; bb = iter.Next()) {
-    LayoutBlocks(bb);
-  }
-  if (cu_->enable_debug & (1 << kDebugDumpCFG)) {
-    DumpCFG("/sdcard/2_post_layout_cfg/", true);
-  }
-}
-
 void MIRGraph::DumpCheckStats() {
   Checkstats* stats =
       static_cast<Checkstats*>(arena_->Alloc(sizeof(Checkstats), ArenaAllocator::kAllocDFInfo));
@@ -909,29 +855,22 @@
   return false;  // Not iterative - return value will be ignored
 }
 
-
 void MIRGraph::BasicBlockOptimization() {
-  if (!(cu_->disable_opt & (1 << kBBOpt))) {
-    DCHECK_EQ(cu_->num_compiler_temps, 0);
-    if ((cu_->disable_opt & (1 << kSuppressExceptionEdges)) != 0) {
-      ClearAllVisitedFlags();
-      PreOrderDfsIterator iter2(this);
-      for (BasicBlock* bb = iter2.Next(); bb != NULL; bb = iter2.Next()) {
-        BuildExtendedBBList(bb);
-      }
-      // Perform extended basic block optimizations.
-      for (unsigned int i = 0; i < extended_basic_blocks_.size(); i++) {
-        BasicBlockOpt(GetBasicBlock(extended_basic_blocks_[i]));
-      }
-    } else {
-      PreOrderDfsIterator iter(this);
-      for (BasicBlock* bb = iter.Next(); bb != NULL; bb = iter.Next()) {
-        BasicBlockOpt(bb);
-      }
+  if ((cu_->disable_opt & (1 << kSuppressExceptionEdges)) != 0) {
+    ClearAllVisitedFlags();
+    PreOrderDfsIterator iter2(this);
+    for (BasicBlock* bb = iter2.Next(); bb != NULL; bb = iter2.Next()) {
+      BuildExtendedBBList(bb);
     }
-  }
-  if (cu_->enable_debug & (1 << kDebugDumpCFG)) {
-    DumpCFG("/sdcard/6_post_bbo_cfg/", false);
+    // Perform extended basic block optimizations.
+    for (unsigned int i = 0; i < extended_basic_blocks_.size(); i++) {
+      BasicBlockOpt(GetBasicBlock(extended_basic_blocks_[i]));
+    }
+  } else {
+    PreOrderDfsIterator iter(this);
+    for (BasicBlock* bb = iter.Next(); bb != NULL; bb = iter.Next()) {
+      BasicBlockOpt(bb);
+    }
   }
 }
 
diff --git a/compiler/dex/pass.h b/compiler/dex/pass.h
new file mode 100644
index 0000000..c52ddf5
--- /dev/null
+++ b/compiler/dex/pass.h
@@ -0,0 +1,145 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ART_COMPILER_DEX_PASS_H_
+#define ART_COMPILER_DEX_PASS_H_
+
+#include <string>
+
+namespace art {
+
+// Forward declarations.
+class BasicBlock;
+class CompilationUnit;
+class Pass;
+
+/**
+ * @brief OptimizationFlag is an enumeration to perform certain tasks for a given pass.
+ * @details Each enum should be a power of 2 to be correctly used.
+ */
+enum OptimizationFlag {
+};
+
+enum DataFlowAnalysisMode {
+  kAllNodes = 0,                           /**< @brief All nodes. */
+  kPreOrderDFSTraversal,                   /**< @brief Depth-First-Search / Pre-Order. */
+  kRepeatingPreOrderDFSTraversal,          /**< @brief Depth-First-Search / Repeating Pre-Order. */
+  kReversePostOrderDFSTraversal,           /**< @brief Depth-First-Search / Reverse Post-Order. */
+  kRepeatingPostOrderDFSTraversal,         /**< @brief Depth-First-Search / Repeating Post-Order. */
+  kRepeatingReversePostOrderDFSTraversal,  /**< @brief Depth-First-Search / Repeating Reverse Post-Order. */
+  kPostOrderDOMTraversal,                  /**< @brief Dominator tree / Post-Order. */
+};
+
+/**
+ * @class Pass
+ * @brief Pass is the Pass structure for the optimizations.
+ * @details The following structure has the different optimization passes that we are going to do.
+ */
+class Pass {
+ public:
+  Pass(const char *name, DataFlowAnalysisMode type, bool freed, const unsigned int f, const char *dump): pass_name_(name), traversal_type_(type), flags_(f), dump_cfg_folder_(dump) {
+  }
+
+  Pass(const char *name, const char *dump): pass_name_(name), traversal_type_(kAllNodes), flags_(0), dump_cfg_folder_(dump) {
+  }
+
+  explicit Pass(const char *name):pass_name_(name), traversal_type_(kAllNodes), flags_(0), dump_cfg_folder_("") {
+  }
+
+  Pass(const char *name, DataFlowAnalysisMode type, const char *dump):pass_name_(name), traversal_type_(type), flags_(false), dump_cfg_folder_(dump) {
+  }
+
+  virtual ~Pass() {}
+
+  virtual const char* GetName() const {
+    return pass_name_;
+  }
+
+  virtual DataFlowAnalysisMode GetTraversal() const {
+    return traversal_type_;
+  }
+
+  virtual bool GetFlag(OptimizationFlag flag) const {
+    return (flags_ & flag);
+  }
+
+  const char* GetDumpCFGFolder() const {return dump_cfg_folder_;}
+
+  /**
+   * @brief Gate for the pass: determines whether to execute the pass or not considering a CompilationUnit
+   * @param c_unit the CompilationUnit.
+   * @return whether or not to execute the pass
+   */
+  virtual bool Gate(const CompilationUnit *c_unit) const {
+    // Unused parameter.
+    UNUSED(c_unit);
+
+    // Base class says yes.
+    return true;
+  }
+
+  /**
+   * @brief Start of the pass: called before the WalkBasicBlocks function
+   * @param c_unit the considered CompilationUnit.
+   */
+  virtual void Start(CompilationUnit *c_unit) const {
+    // Unused parameter.
+    UNUSED(c_unit);
+  }
+
+  /**
+   * @brief End of the pass: called after the WalkBasicBlocks function
+   * @param c_unit the considered CompilationUnit.
+   */
+  virtual void End(CompilationUnit *c_unit) const {
+    // Unused parameter.
+    UNUSED(c_unit);
+  }
+
+  /**
+   * @brief Actually walk the BasicBlocks following a particular traversal type.
+   * @param c_unit the CompilationUnit.
+   * @param bb the BasicBlock.
+   * @return whether or not there is a change when walking the BasicBlock
+   */
+  virtual bool WalkBasicBlocks(CompilationUnit *c_unit, BasicBlock *bb) const {
+    // Unused parameters.
+    UNUSED(c_unit);
+    UNUSED(bb);
+
+    // BasicBlock did not change.
+    return false;
+  }
+
+ protected:
+  /** @brief The pass name: used for searching for a pass when running a particular pass or debugging. */
+  const char* const pass_name_;
+
+  /** @brief Type of traversal: determines the order to execute the pass on the BasicBlocks. */
+  const DataFlowAnalysisMode traversal_type_;
+
+  /** @brief Flags for additional directives: used to determine if a particular clean-up is necessary post pass. */
+  const unsigned int flags_;
+
+  /** @brief CFG Dump Folder: what sub-folder to use for dumping the CFGs post pass. */
+  const char* const dump_cfg_folder_;
+
+ private:
+  // In order to make the all passes not copy-friendly.
+  DISALLOW_COPY_AND_ASSIGN(Pass);
+};
+}  // namespace art
+#endif  // ART_COMPILER_DEX_PASS_H_
diff --git a/compiler/dex/pass_driver.cc b/compiler/dex/pass_driver.cc
new file mode 100644
index 0000000..b20d728
--- /dev/null
+++ b/compiler/dex/pass_driver.cc
@@ -0,0 +1,241 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <dlfcn.h>
+
+#include "bb_optimizations.h"
+#include "compiler_internals.h"
+#include "dataflow_iterator.h"
+#include "dataflow_iterator-inl.h"
+#include "pass.h"
+#include "pass_driver.h"
+
+namespace art {
+
+PassDriver::PassDriver(CompilationUnit* const cu, bool create_default_passes) : cu_(cu) {
+  dump_cfg_folder_ = "/sdcard/";
+
+  // If need be, create the default passes.
+  if (create_default_passes == true) {
+    CreatePasses();
+  }
+}
+
+PassDriver::~PassDriver() {
+  // Clear the map: done to remove any chance of having a pointer after freeing below
+  pass_map_.clear();
+}
+
+void PassDriver::InsertPass(Pass* new_pass, bool warn_override) {
+  assert(new_pass != 0);
+
+  // Get name here to not do it all over the method.
+  const std::string& name = new_pass->GetName();
+
+  // Do we want to warn the user about squashing a pass?
+  if (warn_override == false) {
+    SafeMap<std::string, Pass* >::iterator it = pass_map_.find(name);
+
+    if (it != pass_map_.end()) {
+      LOG(INFO) << "Pass name " << name << " already used, overwriting pass";
+    }
+  }
+
+  // Now add to map and list.
+  pass_map_.Put(name, new_pass);
+  pass_list_.push_back(new_pass);
+}
+
+void PassDriver::CreatePasses() {
+  /*
+   * Create the pass list:
+   *   - These passes are immutable and are shared across the threads:
+   *    - This is achieved via:
+   *     - The UniquePtr used here.
+   *     - DISALLOW_COPY_AND_ASSIGN in the base Pass class.
+   *
+   * Advantage is that there will be no race conditions here.
+   * Disadvantage is the passes can't change their internal states depending on CompilationUnit:
+   *   - This is not yet an issue: no current pass would require it.
+   */
+  static UniquePtr<Pass> *passes[] = {
+      new UniquePtr<Pass>(new CodeLayout()),
+      new UniquePtr<Pass>(new SSATransformation()),
+      new UniquePtr<Pass>(new ConstantPropagation()),
+      new UniquePtr<Pass>(new InitRegLocations()),
+      new UniquePtr<Pass>(new MethodUseCount()),
+      new UniquePtr<Pass>(new NullCheckEliminationAndTypeInferenceInit()),
+      new UniquePtr<Pass>(new NullCheckEliminationAndTypeInference()),
+      new UniquePtr<Pass>(new BBCombine()),
+      new UniquePtr<Pass>(new BBOptimizations()),
+  };
+
+  // Get number of elements in the array.
+  unsigned int nbr = (sizeof(passes) / sizeof(passes[0]));
+
+  // Insert each pass into the map and into the list via the InsertPass method:
+  //   - Map is used for the lookup
+  //   - List is used for the pass walk
+  for (unsigned int i = 0; i < nbr; i++) {
+    InsertPass(passes[i]->get());
+  }
+}
+
+void PassDriver::HandlePassFlag(CompilationUnit* c_unit, Pass* pass) {
+  // Unused parameters for the moment.
+  UNUSED(c_unit);
+  UNUSED(pass);
+}
+
+void PassDriver::DispatchPass(CompilationUnit* c_unit, Pass* curPass) {
+  DataflowIterator* iterator = 0;
+
+  LOG(DEBUG) << "Dispatching " << curPass->GetName();
+
+  MIRGraph* mir_graph = c_unit->mir_graph.get();
+  ArenaAllocator *arena = &(c_unit->arena);
+
+  // Let us start by getting the right iterator.
+  DataFlowAnalysisMode mode = curPass->GetTraversal();
+
+  switch (mode) {
+    case kPreOrderDFSTraversal:
+      iterator = new (arena) PreOrderDfsIterator(mir_graph);
+      break;
+    case kRepeatingPreOrderDFSTraversal:
+      iterator = new (arena) RepeatingPreOrderDfsIterator(mir_graph);
+      break;
+    case kRepeatingPostOrderDFSTraversal:
+      iterator = new (arena) RepeatingPostOrderDfsIterator(mir_graph);
+      break;
+    case kReversePostOrderDFSTraversal:
+      iterator = new (arena) ReversePostOrderDfsIterator(mir_graph);
+      break;
+    case kRepeatingReversePostOrderDFSTraversal:
+      iterator = new (arena) RepeatingReversePostOrderDfsIterator(mir_graph);
+      break;
+    case kPostOrderDOMTraversal:
+      iterator = new (arena) PostOrderDOMIterator(mir_graph);
+      break;
+    case kAllNodes:
+      iterator = new (arena) AllNodesIterator(mir_graph);
+      break;
+    default:
+      LOG(DEBUG) << "Iterator mode not handled in dispatcher: " << mode;
+      return;
+  }
+
+  // Paranoid: Check the iterator before walking the BasicBlocks.
+  assert(iterator != 0);
+
+  bool change = false;
+  for (BasicBlock *bb = iterator->Next(change); bb != 0; bb = iterator->Next(change)) {
+    change = curPass->WalkBasicBlocks(c_unit, bb);
+  }
+}
+
+void PassDriver::ApplyPass(CompilationUnit* c_unit, Pass* curPass) {
+  curPass->Start(c_unit);
+  DispatchPass(c_unit, curPass);
+  curPass->End(c_unit);
+}
+
+bool PassDriver::RunPass(CompilationUnit* c_unit, Pass* curPass, bool time_split) {
+  // Paranoid: c_unit or curPass cannot be 0, and the pass should have a name.
+  if (c_unit == 0 || curPass == 0 || (strcmp(curPass->GetName(), "") == 0)) {
+    return false;
+  }
+
+  // Do we perform a time split
+  if (time_split == true) {
+    std::string name = "MIROpt:";
+    name += curPass->GetName();
+    c_unit->NewTimingSplit(name.c_str());
+  }
+
+  // Check the pass gate first.
+  bool shouldApplyPass = curPass->Gate(c_unit);
+
+  if (shouldApplyPass == true) {
+    // Applying the pass: first start, doWork, and end calls.
+    ApplyPass(c_unit, curPass);
+
+    // Clean up if need be.
+    HandlePassFlag(c_unit, curPass);
+
+    // Do we want to log it?
+    if ((c_unit->enable_debug&  (1 << kDebugDumpCFG)) != 0) {
+      // Do we have a pass folder?
+      const std::string& passFolder = curPass->GetDumpCFGFolder();
+
+      if (passFolder != "") {
+        // Create directory prefix.
+        std::string prefix = GetDumpCFGFolder();
+        prefix += passFolder;
+        prefix += "/";
+
+        c_unit->mir_graph->DumpCFG(prefix.c_str(), false);
+      }
+    }
+  }
+
+  // If the pass gate passed, we can declare success.
+  return shouldApplyPass;
+}
+
+bool PassDriver::RunPass(CompilationUnit* c_unit, const std::string& pass_name) {
+  // Paranoid: c_unit cannot be 0 and we need a pass name.
+  if (c_unit == 0 || pass_name == "") {
+    return false;
+  }
+
+  Pass* curPass = GetPass(pass_name);
+
+  if (curPass != 0) {
+    return RunPass(c_unit, curPass);
+  }
+
+  // Return false, we did not find the pass.
+  return false;
+}
+
+void PassDriver::Launch() {
+  for (std::list<Pass* >::iterator it = pass_list_.begin(); it != pass_list_.end(); it++) {
+    Pass* curPass = *it;
+    RunPass(cu_, curPass, true);
+  }
+}
+
+void PassDriver::PrintPassNames() const {
+  LOG(INFO) << "Loop Passes are:";
+
+  for (std::list<Pass* >::const_iterator it = pass_list_.begin(); it != pass_list_.end(); it++) {
+    const Pass* curPass = *it;
+    LOG(INFO) << "\t-" << curPass->GetName();
+  }
+}
+
+Pass* PassDriver::GetPass(const std::string& name) const {
+  SafeMap<std::string, Pass*>::const_iterator it = pass_map_.find(name);
+
+  if (it != pass_map_.end()) {
+    return it->second;
+  }
+
+  return 0;
+}
+
+}  // namespace art
diff --git a/compiler/dex/pass_driver.h b/compiler/dex/pass_driver.h
new file mode 100644
index 0000000..29da351
--- /dev/null
+++ b/compiler/dex/pass_driver.h
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ART_COMPILER_DEX_PASS_DRIVER_H_
+#define ART_COMPILER_DEX_PASS_DRIVER_H_
+
+#include <list>
+#include "pass.h"
+#include "safe_map.h"
+
+// Forward Declarations.
+class CompilationUnit;
+class Pass;
+
+namespace art {
+
+/**
+ * @class PassDriver
+ * @brief PassDriver is the wrapper around all Pass instances in order to execute them from the Middle-End
+ */
+class PassDriver {
+ public:
+  explicit PassDriver(CompilationUnit* const cu, bool create_default_passes = true);
+
+  ~PassDriver();
+
+  /**
+   * @brief Insert a Pass: can warn if multiple passes have the same name.
+   * @param new_pass the new Pass to insert in the map and list.
+   * @param warn_override warn if the name of the Pass is already used.
+   */
+  void InsertPass(Pass *new_pass, bool warn_override = true);
+
+  /**
+   * @brief Run a pass using the name as key.
+   * @param c_unit the considered CompilationUnit.
+   * @param pass_name the Pass name.
+   * @return whether the pass was applied.
+   */
+  bool RunPass(CompilationUnit* c_unit, const std::string& pass_name);
+
+  /**
+   * @brief Run a pass using the Pass itself.
+   * @param time_split do we want a time split request(default: false)?
+   * @return whether the pass was applied.
+   */
+  bool RunPass(CompilationUnit* c_unit, Pass* pass, bool time_split = false);
+
+  void Launch();
+
+  void HandlePassFlag(CompilationUnit* c_unit, Pass* pass);
+
+  /**
+   * @brief Apply a patch: perform start/work/end functions.
+   */
+  void ApplyPass(CompilationUnit* c_unit, Pass* pass);
+
+  /**
+   * @brief Dispatch a patch: walk the BasicBlocks depending on the traversal mode
+   */
+  void DispatchPass(CompilationUnit* c_unit, Pass* pass);
+
+  void PrintPassNames() const;
+
+  Pass* GetPass(const std::string& name) const;
+
+  const char *GetDumpCFGFolder() const {
+    return dump_cfg_folder_;
+  }
+
+ protected:
+  void CreatePasses();
+
+  /** @brief The Pass Map: contains name -> pass for quick lookup. */
+  SafeMap<std::string, Pass*> pass_map_;
+
+  /** @brief List of passes: provides the order to execute the passes. */
+  std::list<Pass*> pass_list_;
+
+  /** @brief The CompilationUnit on which to execute the passes on. */
+  CompilationUnit* const cu_;
+
+  /** @brief Dump CFG base folder: where is the base folder for dumping CFGs. */
+  const char* dump_cfg_folder_;
+};
+
+}  // namespace art
+#endif  // ART_COMPILER_DEX_PASS_DRIVER_H_
diff --git a/compiler/dex/ssa_transformation.cc b/compiler/dex/ssa_transformation.cc
index 0d8bd07..502df1e 100644
--- a/compiler/dex/ssa_transformation.cc
+++ b/compiler/dex/ssa_transformation.cc
@@ -669,46 +669,4 @@
   return;
 }
 
-/* Perform SSA transformation for the whole method */
-void MIRGraph::SSATransformation() {
-  /* Compute the DFS order */
-  ComputeDFSOrders();
-
-  /* Compute the dominator info */
-  ComputeDominators();
-
-  /* Allocate data structures in preparation for SSA conversion */
-  CompilerInitializeSSAConversion();
-
-  /* Find out the "Dalvik reg def x block" relation */
-  ComputeDefBlockMatrix();
-
-  /* Insert phi nodes to dominance frontiers for all variables */
-  InsertPhiNodes();
-
-  /* Rename register names by local defs and phi nodes */
-  ClearAllVisitedFlags();
-  DoDFSPreOrderSSARename(GetEntryBlock());
-
-  /*
-   * Shared temp bit vector used by each block to count the number of defs
-   * from all the predecessor blocks.
-   */
-  temp_ssa_register_v_ =
-      new (arena_) ArenaBitVector(arena_, GetNumSSARegs(), false, kBitMapTempSSARegisterV);
-
-  /* Insert phi-operands with latest SSA names from predecessor blocks */
-  PreOrderDfsIterator iter2(this);
-  for (BasicBlock* bb = iter2.Next(); bb != NULL; bb = iter2.Next()) {
-    InsertPhiNodeOperands(bb);
-  }
-
-  if (cu_->enable_debug & (1 << kDebugDumpCFG)) {
-    DumpCFG("/sdcard/3_post_ssa_cfg/", false);
-  }
-  if (cu_->enable_debug & (1 << kDebugVerifyDataflow)) {
-    VerifyDataflow();
-  }
-}
-
 }  // namespace art