ART: Setting up cleanup

- Moved code around to actually have the clean-up code in a PassDriver format.
    This allows us to better control what is being called after an optimization
    It also allows the use of a centralized pass system for both optimizations
      and cleanup.

Change-Id: I9d21e9bb9ee663739722f440d82adf04f73e380c
Signed-off-by: Jean Christophe Beyler <jean.christophe.beyler@intel.com>
Signed-off-by: Razvan A Lupusoru <razvan.a.lupusoru@intel.com>
Signed-off-by: Yixin Shou <yixin.shou@intel.com>
Signed-off-by: Chao-ying Fu <chao-ying.fu@intel.com>
Signed-off-by: Udayan Banerji <udayan.banerji@intel.com>
diff --git a/compiler/Android.mk b/compiler/Android.mk
index f297213..3bed01d 100644
--- a/compiler/Android.mk
+++ b/compiler/Android.mk
@@ -60,7 +60,9 @@
 	dex/mir_method_info.cc \
 	dex/mir_optimization.cc \
 	dex/bb_optimizations.cc \
-	dex/pass_driver_me.cc \
+	dex/post_opt_passes.cc \
+	dex/pass_driver_me_opts.cc \
+	dex/pass_driver_me_post_opt.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
index 8b5eba0..06e259a 100644
--- a/compiler/dex/bb_optimizations.cc
+++ b/compiler/dex/bb_optimizations.cc
@@ -26,83 +26,11 @@
 bool CodeLayout::Worker(const PassDataHolder* data) const {
   DCHECK(data != nullptr);
   const PassMEDataHolder* pass_me_data_holder = down_cast<const PassMEDataHolder*>(data);
-  CompilationUnit* cUnit = pass_me_data_holder->c_unit;
-  DCHECK(cUnit != nullptr);
+  CompilationUnit* c_unit = pass_me_data_holder->c_unit;
+  DCHECK(c_unit != nullptr);
   BasicBlock* bb = pass_me_data_holder->bb;
   DCHECK(bb != nullptr);
-  cUnit->mir_graph->LayoutBlocks(bb);
-  // No need of repeating, so just return false.
-  return false;
-}
-
-/*
- * SSATransformation pass implementation start.
- */
-void SSATransformation::Start(const PassDataHolder* data) const {
-  DCHECK(data != nullptr);
-  CompilationUnit* cUnit = down_cast<const PassMEDataHolder*>(data)->c_unit;
-  DCHECK(cUnit != nullptr);
-  cUnit->mir_graph->SSATransformationStart();
-}
-
-bool SSATransformation::Worker(const PassDataHolder* data) const {
-  DCHECK(data != nullptr);
-  const PassMEDataHolder* pass_me_data_holder = down_cast<const PassMEDataHolder*>(data);
-  CompilationUnit* cUnit = pass_me_data_holder->c_unit;
-  DCHECK(cUnit != nullptr);
-  BasicBlock* bb = pass_me_data_holder->bb;
-  DCHECK(bb != nullptr);
-  cUnit->mir_graph->InsertPhiNodeOperands(bb);
-  // No need of repeating, so just return false.
-  return false;
-}
-
-void SSATransformation::End(const PassDataHolder* data) const {
-  DCHECK(data != nullptr);
-  CompilationUnit* cUnit = down_cast<const PassMEDataHolder*>(data)->c_unit;
-  DCHECK(cUnit != nullptr);
-  cUnit->mir_graph->SSATransformationEnd();
-}
-
-/*
- * ConstantPropagation pass implementation start
- */
-bool ConstantPropagation::Worker(const PassDataHolder* data) const {
-  DCHECK(data != nullptr);
-  const PassMEDataHolder* pass_me_data_holder = down_cast<const PassMEDataHolder*>(data);
-  CompilationUnit* cUnit = pass_me_data_holder->c_unit;
-  DCHECK(cUnit != nullptr);
-  BasicBlock* bb = pass_me_data_holder->bb;
-  DCHECK(bb != nullptr);
-  cUnit->mir_graph->DoConstantPropagation(bb);
-  // No need of repeating, so just return false.
-  return false;
-}
-
-/*
- * MethodUseCount pass implementation start.
- */
-bool MethodUseCount::Gate(const PassDataHolder* data) const {
-  DCHECK(data != nullptr);
-  CompilationUnit* cUnit = down_cast<const PassMEDataHolder*>(data)->c_unit;
-  DCHECK(cUnit != nullptr);
-  // 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::Worker(const PassDataHolder* data) const {
-  DCHECK(data != nullptr);
-  const PassMEDataHolder* pass_me_data_holder = down_cast<const PassMEDataHolder*>(data);
-  CompilationUnit* cUnit = pass_me_data_holder->c_unit;
-  DCHECK(cUnit != nullptr);
-  BasicBlock* bb = pass_me_data_holder->bb;
-  DCHECK(bb != nullptr);
-  cUnit->mir_graph->CountUses(bb);
+  c_unit->mir_graph->LayoutBlocks(bb);
   // No need of repeating, so just return false.
   return false;
 }
@@ -113,11 +41,11 @@
 bool BBCombine::Worker(const PassDataHolder* data) const {
   DCHECK(data != nullptr);
   const PassMEDataHolder* pass_me_data_holder = down_cast<const PassMEDataHolder*>(data);
-  CompilationUnit* cUnit = pass_me_data_holder->c_unit;
-  DCHECK(cUnit != nullptr);
+  CompilationUnit* c_unit = pass_me_data_holder->c_unit;
+  DCHECK(c_unit != nullptr);
   BasicBlock* bb = pass_me_data_holder->bb;
   DCHECK(bb != nullptr);
-  cUnit->mir_graph->CombineBlocks(bb);
+  c_unit->mir_graph->CombineBlocks(bb);
 
   // No need of repeating, so just return false.
   return false;
@@ -128,15 +56,15 @@
  */
 void BBOptimizations::Start(const PassDataHolder* data) const {
   DCHECK(data != nullptr);
-  CompilationUnit* cUnit = down_cast<const PassMEDataHolder*>(data)->c_unit;
-  DCHECK(cUnit != nullptr);
+  CompilationUnit* c_unit = down_cast<const PassMEDataHolder*>(data)->c_unit;
+  DCHECK(c_unit != nullptr);
   /*
    * 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();
+  c_unit->mir_graph->BasicBlockOptimization();
 }
 
 }  // namespace art
diff --git a/compiler/dex/bb_optimizations.h b/compiler/dex/bb_optimizations.h
index 3a529f2..0094790 100644
--- a/compiler/dex/bb_optimizations.h
+++ b/compiler/dex/bb_optimizations.h
@@ -119,7 +119,7 @@
  */
 class CodeLayout : public PassME {
  public:
-  CodeLayout() : PassME("CodeLayout", "2_post_layout_cfg") {
+  CodeLayout() : PassME("CodeLayout", kAllNodes, kOptimizationBasicBlockChange, "2_post_layout_cfg") {
   }
 
   void Start(const PassDataHolder* data) const {
@@ -133,72 +133,6 @@
 };
 
 /**
- * @class SSATransformation
- * @brief Perform an SSA representation pass on the CompilationUnit.
- */
-class SSATransformation : public PassME {
- public:
-  SSATransformation() : PassME("SSATransformation", kPreOrderDFSTraversal, "3_post_ssa_cfg") {
-  }
-
-  bool Worker(const PassDataHolder* data) const;
-
-  void Start(const PassDataHolder* data) const;
-
-  void End(const PassDataHolder* data) const;
-};
-
-/**
- * @class ConstantPropagation
- * @brief Perform a constant propagation pass.
- */
-class ConstantPropagation : public PassME {
- public:
-  ConstantPropagation() : PassME("ConstantPropagation") {
-  }
-
-  bool Worker(const PassDataHolder* data) const;
-
-  void Start(const PassDataHolder* data) const {
-    DCHECK(data != nullptr);
-    CompilationUnit* cUnit = down_cast<const PassMEDataHolder*>(data)->c_unit;
-    DCHECK(cUnit != nullptr);
-    cUnit->mir_graph->InitializeConstantPropagation();
-  }
-};
-
-/**
- * @class InitRegLocations
- * @brief Initialize Register Locations.
- */
-class InitRegLocations : public PassME {
- public:
-  InitRegLocations() : PassME("InitRegLocation", kNoNodes) {
-  }
-
-  void Start(const PassDataHolder* data) const {
-    DCHECK(data != nullptr);
-    CompilationUnit* cUnit = down_cast<const PassMEDataHolder*>(data)->c_unit;
-    DCHECK(cUnit != nullptr);
-    cUnit->mir_graph->InitRegLocations();
-  }
-};
-
-/**
- * @class MethodUseCount
- * @brief Count the register uses of the method
- */
-class MethodUseCount : public PassME {
- public:
-  MethodUseCount() : PassME("UseCount") {
-  }
-
-  bool Worker(const PassDataHolder* data) const;
-
-  bool Gate(const PassDataHolder* data) const;
-};
-
-/**
  * @class NullCheckEliminationAndTypeInference
  * @brief Null check elimination and type inference.
  */
diff --git a/compiler/dex/frontend.cc b/compiler/dex/frontend.cc
index 1d4a9bb..1570c3a 100644
--- a/compiler/dex/frontend.cc
+++ b/compiler/dex/frontend.cc
@@ -21,7 +21,7 @@
 #include "dataflow_iterator-inl.h"
 #include "leb128.h"
 #include "mirror/object.h"
-#include "pass_driver_me.h"
+#include "pass_driver_me_opts.h"
 #include "runtime.h"
 #include "base/logging.h"
 #include "base/timing_logger.h"
@@ -750,7 +750,7 @@
     }
 
     for (int idx = 0; idx < cu.mir_graph->GetNumBlocks(); idx++) {
-      BasicBlock *bb = cu.mir_graph->GetBasicBlock(idx);
+      BasicBlock* bb = cu.mir_graph->GetBasicBlock(idx);
       if (bb == NULL) continue;
       if (bb->block_type == kDead) continue;
       for (MIR* mir = bb->first_mir_insn; mir != nullptr; mir = mir->next) {
@@ -926,7 +926,7 @@
   }
 
   /* Create the pass driver and launch it */
-  PassDriverME pass_driver(&cu);
+  PassDriverMEOpts pass_driver(&cu);
   pass_driver.Launch();
 
   if (cu.enable_debug & (1 << kDebugDumpCheckStats)) {
diff --git a/compiler/dex/mir_dataflow.cc b/compiler/dex/mir_dataflow.cc
index 47b233b..5ff6274 100644
--- a/compiler/dex/mir_dataflow.cc
+++ b/compiler/dex/mir_dataflow.cc
@@ -1282,7 +1282,7 @@
   GrowableArray<BasicBlockId>::Iterator iter(bb->predecessors);
 
   while (true) {
-    BasicBlock *pred_bb = GetBasicBlock(iter.Next());
+    BasicBlock* pred_bb = GetBasicBlock(iter.Next());
     if (!pred_bb) break;
     bool found = false;
     if (pred_bb->taken == bb->id) {
diff --git a/compiler/dex/mir_graph.cc b/compiler/dex/mir_graph.cc
index 0fffa01..99dd50a 100644
--- a/compiler/dex/mir_graph.cc
+++ b/compiler/dex/mir_graph.cc
@@ -26,6 +26,7 @@
 #include "dex/quick/dex_file_to_method_inliner_map.h"
 #include "dex/quick/dex_file_method_inliner.h"
 #include "leb128.h"
+#include "pass_driver_me_post_opt.h"
 
 namespace art {
 
@@ -353,7 +354,7 @@
 
   /* Always terminate the current block for conditional branches */
   if (flags & Instruction::kContinue) {
-    BasicBlock *fallthrough_block = FindBlock(cur_offset +  width,
+    BasicBlock* fallthrough_block = FindBlock(cur_offset +  width,
                                              /*
                                               * If the method is processed
                                               * in sequential order from the
@@ -541,7 +542,7 @@
    * Note also that the dex_pc_to_block_map_ entry for the potentially
    * throwing instruction will refer to the original basic block.
    */
-  BasicBlock *new_block = NewMemBB(kDalvikByteCode, num_blocks_++);
+  BasicBlock* new_block = NewMemBB(kDalvikByteCode, num_blocks_++);
   block_list_.Insert(new_block);
   new_block->start_offset = insn->offset;
   cur_block->fall_through = new_block->id;
@@ -724,7 +725,7 @@
       }
     }
     current_offset_ += width;
-    BasicBlock *next_block = FindBlock(current_offset_, /* split */ false, /* create */
+    BasicBlock* next_block = FindBlock(current_offset_, /* split */ false, /* create */
                                       false, /* immed_pred_block_p */ NULL);
     if (next_block) {
       /*
@@ -1418,25 +1419,6 @@
   temp_bit_vector_ = new (temp_scoped_alloc_.get()) ArenaBitVector(
       temp_scoped_alloc_.get(), temp_bit_vector_size_, false, kBitMapRegisterV);
 
-  /* 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());
-
   // Update the maximum number of reachable blocks.
   max_num_reachable_blocks_ = num_reachable_blocks_;
 }
@@ -1454,7 +1436,7 @@
 }
 
 void MIRGraph::ComputeTopologicalSortOrder() {
-  std::queue<BasicBlock *> q;
+  std::queue<BasicBlock*> q;
   std::map<int, int> visited_cnt_values;
 
   // Clear the nodes.
@@ -1510,7 +1492,7 @@
 
   while (q.size() > 0) {
     // Get top.
-    BasicBlock *bb = q.front();
+    BasicBlock* bb = q.front();
     q.pop();
 
     DCHECK_EQ(bb->hidden, false);
@@ -1528,7 +1510,7 @@
 
       // Reduce visitedCnt for all the successors and add into the queue ones with visitedCnt equals to zero.
       ChildBlockIterator succIter(bb, this);
-      BasicBlock *successor = succIter.Next();
+      BasicBlock* successor = succIter.Next();
       while (successor != nullptr) {
         // one more predecessor was visited.
         visited_cnt_values[successor->id]--;
@@ -1914,4 +1896,13 @@
   return res;
 }
 
+void MIRGraph::CalculateBasicBlockInformation() {
+  PassDriverMEPostOpt driver(cu_);
+  driver.Launch();
+}
+
+void MIRGraph::InitializeBasicBlockData() {
+  num_blocks_ = block_list_.Size();
+}
+
 }  // namespace art
diff --git a/compiler/dex/mir_graph.h b/compiler/dex/mir_graph.h
index 3655125..b04c16e 100644
--- a/compiler/dex/mir_graph.h
+++ b/compiler/dex/mir_graph.h
@@ -924,7 +924,7 @@
   void VerifyDataflow();
   void CheckForDominanceFrontier(BasicBlock* dom_bb, const BasicBlock* succ_bb);
   void EliminateNullChecksAndInferTypesStart();
-  bool EliminateNullChecksAndInferTypes(BasicBlock *bb);
+  bool EliminateNullChecksAndInferTypes(BasicBlock* bb);
   void EliminateNullChecksAndInferTypesEnd();
   bool EliminateClassInitChecksGate();
   bool EliminateClassInitChecks(BasicBlock* bb);
@@ -1030,6 +1030,14 @@
 
   void AllocateSSAUseData(MIR *mir, int num_uses);
   void AllocateSSADefData(MIR *mir, int num_defs);
+  void CalculateBasicBlockInformation();
+  void InitializeBasicBlockData();
+  void ComputeDFSOrders();
+  void ComputeDefBlockMatrix();
+  void ComputeDominators();
+  void CompilerInitializeSSAConversion();
+  void InsertPhiNodes();
+  void DoDFSPreOrderSSARename(BasicBlock* block);
 
   /*
    * IsDebugBuild sanity check: keep track of the Dex PCs for catch entries so that later on
@@ -1046,7 +1054,6 @@
 
   void HandleSSADef(int* defs, int dalvik_reg, int reg_index);
   bool InferTypeAndSize(BasicBlock* bb, MIR* mir, bool changed);
-  void ComputeDFSOrders();
 
  protected:
   int FindCommonParent(int block1, int block2);
@@ -1055,7 +1062,6 @@
   void HandleLiveInUse(ArenaBitVector* use_v, ArenaBitVector* def_v,
                        ArenaBitVector* live_in_v, int dalvik_reg_id);
   void HandleDef(ArenaBitVector* def_v, int dalvik_reg_id);
-  void CompilerInitializeSSAConversion();
   bool DoSSAConversion(BasicBlock* bb);
   bool InvokeUsesMethodStar(MIR* mir);
   int ParseInsn(const uint16_t* code_ptr, MIR::DecodedInstruction* decoded_instruction);
@@ -1082,11 +1088,7 @@
   BasicBlock* NextUnvisitedSuccessor(BasicBlock* bb);
   void MarkPreOrder(BasicBlock* bb);
   void RecordDFSOrders(BasicBlock* bb);
-  void ComputeDefBlockMatrix();
   void ComputeDomPostOrderTraversal(BasicBlock* bb);
-  void ComputeDominators();
-  void InsertPhiNodes();
-  void DoDFSPreOrderSSARename(BasicBlock* block);
   void SetConstant(int32_t ssa_reg, int value);
   void SetConstantWide(int ssa_reg, int64_t value);
   int GetSSAUseCount(int s_reg);
diff --git a/compiler/dex/mir_optimization_test.cc b/compiler/dex/mir_optimization_test.cc
index 86092b6..69c394f 100644
--- a/compiler/dex/mir_optimization_test.cc
+++ b/compiler/dex/mir_optimization_test.cc
@@ -193,7 +193,7 @@
     ASSERT_TRUE(gate_result);
     RepeatingPreOrderDfsIterator iterator(cu_.mir_graph.get());
     bool change = false;
-    for (BasicBlock *bb = iterator.Next(change); bb != 0; bb = iterator.Next(change)) {
+    for (BasicBlock* bb = iterator.Next(change); bb != nullptr; bb = iterator.Next(change)) {
       change = cu_.mir_graph->EliminateClassInitChecks(bb);
     }
     cu_.mir_graph->EliminateClassInitChecksEnd();
diff --git a/compiler/dex/pass_driver_me.cc b/compiler/dex/pass_driver_me.cc
deleted file mode 100644
index e6d90e0..0000000
--- a/compiler/dex/pass_driver_me.cc
+++ /dev/null
@@ -1,208 +0,0 @@
-/*
- * 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 "base/macros.h"
-#include "bb_optimizations.h"
-#include "compiler_internals.h"
-#include "dataflow_iterator.h"
-#include "dataflow_iterator-inl.h"
-#include "pass_driver_me.h"
-
-namespace art {
-
-namespace {  // anonymous namespace
-
-void DoWalkBasicBlocks(PassMEDataHolder* data, const PassME* pass, DataflowIterator* iterator) {
-  // Paranoid: Check the iterator before walking the BasicBlocks.
-  DCHECK(iterator != nullptr);
-  bool change = false;
-  for (BasicBlock *bb = iterator->Next(change); bb != 0; bb = iterator->Next(change)) {
-    data->bb = bb;
-    change = pass->Worker(data);
-  }
-}
-
-template <typename Iterator>
-inline void DoWalkBasicBlocks(PassMEDataHolder* data, const PassME* pass) {
-  DCHECK(data != nullptr);
-  CompilationUnit* c_unit = data->c_unit;
-  DCHECK(c_unit != nullptr);
-  Iterator iterator(c_unit->mir_graph.get());
-  DoWalkBasicBlocks(data, pass, &iterator);
-}
-}  // anonymous namespace
-
-/*
- * Create the pass list. These passes are immutable and are shared across the threads.
- *
- * 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.
- */
-// The initial list of passes to be used by the PassDriveME.
-template<>
-const Pass* const PassDriver<PassDriverME>::g_passes[] = {
-  GetPassInstance<CacheFieldLoweringInfo>(),
-  GetPassInstance<CacheMethodLoweringInfo>(),
-  GetPassInstance<CallInlining>(),
-  GetPassInstance<CodeLayout>(),
-  GetPassInstance<SSATransformation>(),
-  GetPassInstance<ConstantPropagation>(),
-  GetPassInstance<InitRegLocations>(),
-  GetPassInstance<MethodUseCount>(),
-  GetPassInstance<NullCheckEliminationAndTypeInference>(),
-  GetPassInstance<ClassInitCheckElimination>(),
-  GetPassInstance<BBCombine>(),
-  GetPassInstance<BBOptimizations>(),
-};
-
-// The number of the passes in the initial list of Passes (g_passes).
-template<>
-uint16_t const PassDriver<PassDriverME>::g_passes_size = arraysize(PassDriver<PassDriverME>::g_passes);
-
-// The default pass list is used by the PassDriverME instance of PassDriver to initialize pass_list_.
-template<>
-std::vector<const Pass*> PassDriver<PassDriverME>::g_default_pass_list(PassDriver<PassDriverME>::g_passes, PassDriver<PassDriverME>::g_passes + PassDriver<PassDriverME>::g_passes_size);
-
-// By default, do not have a dump pass list.
-template<>
-std::string PassDriver<PassDriverME>::dump_pass_list_ = std::string();
-
-// By default, do not have a print pass list.
-template<>
-std::string PassDriver<PassDriverME>::print_pass_list_ = std::string();
-
-// By default, we do not print the pass' information.
-template<>
-bool PassDriver<PassDriverME>::default_print_passes_ = false;
-
-
-PassDriverME::PassDriverME(CompilationUnit* cu)
-    : PassDriver(), pass_me_data_holder_(), dump_cfg_folder_("/sdcard/") {
-  pass_me_data_holder_.bb = nullptr;
-  pass_me_data_holder_.c_unit = cu;
-}
-
-PassDriverME::~PassDriverME() {
-}
-
-void PassDriverME::DispatchPass(const Pass* pass) {
-  VLOG(compiler) << "Dispatching " << pass->GetName();
-  const PassME* me_pass = down_cast<const PassME*>(pass);
-
-  DataFlowAnalysisMode mode = me_pass->GetTraversal();
-
-  switch (mode) {
-    case kPreOrderDFSTraversal:
-      DoWalkBasicBlocks<PreOrderDfsIterator>(&pass_me_data_holder_, me_pass);
-      break;
-    case kRepeatingPreOrderDFSTraversal:
-      DoWalkBasicBlocks<RepeatingPreOrderDfsIterator>(&pass_me_data_holder_, me_pass);
-      break;
-    case kRepeatingPostOrderDFSTraversal:
-      DoWalkBasicBlocks<RepeatingPostOrderDfsIterator>(&pass_me_data_holder_, me_pass);
-      break;
-    case kReversePostOrderDFSTraversal:
-      DoWalkBasicBlocks<ReversePostOrderDfsIterator>(&pass_me_data_holder_, me_pass);
-      break;
-    case kRepeatingReversePostOrderDFSTraversal:
-      DoWalkBasicBlocks<RepeatingReversePostOrderDfsIterator>(&pass_me_data_holder_, me_pass);
-      break;
-    case kPostOrderDOMTraversal:
-      DoWalkBasicBlocks<PostOrderDOMIterator>(&pass_me_data_holder_, me_pass);
-      break;
-    case kAllNodes:
-      DoWalkBasicBlocks<AllNodesIterator>(&pass_me_data_holder_, me_pass);
-      break;
-    case kNoNodes:
-      break;
-    default:
-      LOG(FATAL) << "Iterator mode not handled in dispatcher: " << mode;
-      break;
-  }
-}
-
-bool PassDriverME::RunPass(const Pass* pass, bool time_split) {
-  // Paranoid: c_unit and pass cannot be nullptr, and the pass should have a name
-  DCHECK(pass != nullptr);
-  DCHECK(pass->GetName() != nullptr && pass->GetName()[0] != 0);
-  CompilationUnit* c_unit = pass_me_data_holder_.c_unit;
-  DCHECK(c_unit != nullptr);
-
-  // Do we perform a time split
-  if (time_split) {
-    c_unit->NewTimingSplit(pass->GetName());
-  }
-
-  // Check the pass gate first.
-  bool should_apply_pass = pass->Gate(&pass_me_data_holder_);
-
-  if (should_apply_pass) {
-    bool old_print_pass = c_unit->print_pass;
-
-    c_unit->print_pass = default_print_passes_;
-
-    const char* print_pass_list = print_pass_list_.c_str();
-
-    if (print_pass_list != nullptr && strstr(print_pass_list, pass->GetName()) != nullptr) {
-      c_unit->print_pass = true;
-    }
-
-    // Applying the pass: first start, doWork, and end calls.
-    ApplyPass(&pass_me_data_holder_, pass);
-
-    // Do we want to log it?
-    bool should_dump = ((c_unit->enable_debug & (1 << kDebugDumpCFG)) != 0);
-
-    const char* dump_pass_list = dump_pass_list_.c_str();
-
-    if (dump_pass_list != nullptr) {
-      bool found = strstr(dump_pass_list, pass->GetName());
-      should_dump = (should_dump || found);
-    }
-
-    if (should_dump) {
-      // Do we want to log it?
-      if ((c_unit->enable_debug&  (1 << kDebugDumpCFG)) != 0) {
-        // Do we have a pass folder?
-        const PassME* me_pass = (down_cast<const PassME*>(pass));
-        const char* passFolder = me_pass->GetDumpCFGFolder();
-        DCHECK(passFolder != nullptr);
-
-        if (passFolder[0] != 0) {
-          // Create directory prefix.
-          std::string prefix = GetDumpCFGFolder();
-          prefix += passFolder;
-          prefix += "/";
-
-          c_unit->mir_graph->DumpCFG(prefix.c_str(), false);
-        }
-      }
-    }
-
-    c_unit->print_pass = old_print_pass;
-  }
-
-  // If the pass gate passed, we can declare success.
-  return should_apply_pass;
-}
-
-const char* PassDriverME::GetDumpCFGFolder() const {
-  return dump_cfg_folder_;
-}
-
-
-}  // namespace art
diff --git a/compiler/dex/pass_driver_me.h b/compiler/dex/pass_driver_me.h
index 0142934..7d76fb8 100644
--- a/compiler/dex/pass_driver_me.h
+++ b/compiler/dex/pass_driver_me.h
@@ -18,28 +18,155 @@
 #define ART_COMPILER_DEX_PASS_DRIVER_ME_H_
 
 #include "bb_optimizations.h"
+#include "dataflow_iterator.h"
+#include "dataflow_iterator-inl.h"
 #include "pass_driver.h"
 #include "pass_me.h"
 
 namespace art {
 
-class PassDriverME: public PassDriver<PassDriverME> {
+template <typename PassDriverType>
+class PassDriverME: public PassDriver<PassDriverType> {
  public:
-  explicit PassDriverME(CompilationUnit* cu);
-  ~PassDriverME();
-  /**
-   * @brief Dispatch a patch: walk the BasicBlocks depending on the traversal mode
-   */
-  void DispatchPass(const Pass* pass);
-  bool RunPass(const Pass* pass, bool time_split = false);
-  const char* GetDumpCFGFolder() const;
+  explicit PassDriverME(CompilationUnit* cu)
+      : pass_me_data_holder_(), dump_cfg_folder_("/sdcard/") {
+        pass_me_data_holder_.bb = nullptr;
+        pass_me_data_holder_.c_unit = cu;
+  }
+
+  ~PassDriverME() {
+  }
+
+  void DispatchPass(const Pass* pass) {
+    VLOG(compiler) << "Dispatching " << pass->GetName();
+    const PassME* me_pass = down_cast<const PassME*>(pass);
+
+    DataFlowAnalysisMode mode = me_pass->GetTraversal();
+
+    switch (mode) {
+      case kPreOrderDFSTraversal:
+        DoWalkBasicBlocks<PreOrderDfsIterator>(&pass_me_data_holder_, me_pass);
+        break;
+      case kRepeatingPreOrderDFSTraversal:
+        DoWalkBasicBlocks<RepeatingPreOrderDfsIterator>(&pass_me_data_holder_, me_pass);
+        break;
+      case kRepeatingPostOrderDFSTraversal:
+        DoWalkBasicBlocks<RepeatingPostOrderDfsIterator>(&pass_me_data_holder_, me_pass);
+        break;
+      case kReversePostOrderDFSTraversal:
+        DoWalkBasicBlocks<ReversePostOrderDfsIterator>(&pass_me_data_holder_, me_pass);
+        break;
+      case kRepeatingReversePostOrderDFSTraversal:
+        DoWalkBasicBlocks<RepeatingReversePostOrderDfsIterator>(&pass_me_data_holder_, me_pass);
+        break;
+      case kPostOrderDOMTraversal:
+        DoWalkBasicBlocks<PostOrderDOMIterator>(&pass_me_data_holder_, me_pass);
+        break;
+      case kAllNodes:
+        DoWalkBasicBlocks<AllNodesIterator>(&pass_me_data_holder_, me_pass);
+        break;
+      case kNoNodes:
+        break;
+      default:
+        LOG(FATAL) << "Iterator mode not handled in dispatcher: " << mode;
+        break;
+    }
+  }
+
+  bool RunPass(const Pass* pass, bool time_split) {
+    // Paranoid: c_unit and pass cannot be nullptr, and the pass should have a name
+    DCHECK(pass != nullptr);
+    DCHECK(pass->GetName() != nullptr && pass->GetName()[0] != 0);
+    CompilationUnit* c_unit = pass_me_data_holder_.c_unit;
+    DCHECK(c_unit != nullptr);
+
+    // Do we perform a time split
+    if (time_split) {
+      c_unit->NewTimingSplit(pass->GetName());
+    }
+
+    // Check the pass gate first.
+    bool should_apply_pass = pass->Gate(&pass_me_data_holder_);
+    if (should_apply_pass) {
+      bool old_print_pass = c_unit->print_pass;
+
+      c_unit->print_pass = PassDriver<PassDriverType>::default_print_passes_;
+
+      const char* print_pass_list = PassDriver<PassDriverType>::print_pass_list_.c_str();
+
+      if (print_pass_list != nullptr && strstr(print_pass_list, pass->GetName()) != nullptr) {
+        c_unit->print_pass = true;
+      }
+
+      // Applying the pass: first start, doWork, and end calls.
+      this->ApplyPass(&pass_me_data_holder_, pass);
+
+      bool should_dump = ((c_unit->enable_debug & (1 << kDebugDumpCFG)) != 0);
+
+      const char* dump_pass_list = PassDriver<PassDriverType>::dump_pass_list_.c_str();
+
+      if (dump_pass_list != nullptr) {
+        bool found = strstr(dump_pass_list, pass->GetName());
+        should_dump = (should_dump || found);
+      }
+
+      if (should_dump) {
+        // Do we want to log it?
+        if ((c_unit->enable_debug&  (1 << kDebugDumpCFG)) != 0) {
+          // Do we have a pass folder?
+          const PassME* me_pass = (down_cast<const PassME*>(pass));
+          const char* passFolder = me_pass->GetDumpCFGFolder();
+          DCHECK(passFolder != nullptr);
+
+          if (passFolder[0] != 0) {
+            // Create directory prefix.
+            std::string prefix = GetDumpCFGFolder();
+            prefix += passFolder;
+            prefix += "/";
+
+            c_unit->mir_graph->DumpCFG(prefix.c_str(), false);
+          }
+        }
+      }
+
+      c_unit->print_pass = old_print_pass;
+    }
+
+    // If the pass gate passed, we can declare success.
+    return should_apply_pass;
+  }
+
+  const char* GetDumpCFGFolder() const {
+    return dump_cfg_folder_;
+  }
+
  protected:
   /** @brief The data holder that contains data needed for the PassDriverME. */
   PassMEDataHolder pass_me_data_holder_;
 
   /** @brief Dump CFG base folder: where is the base folder for dumping CFGs. */
   const char* dump_cfg_folder_;
-};
 
+  static void DoWalkBasicBlocks(PassMEDataHolder* data, const PassME* pass,
+                                DataflowIterator* iterator) {
+    // Paranoid: Check the iterator before walking the BasicBlocks.
+    DCHECK(iterator != nullptr);
+    bool change = false;
+    for (BasicBlock* bb = iterator->Next(change); bb != nullptr; bb = iterator->Next(change)) {
+      data->bb = bb;
+      change = pass->Worker(data);
+    }
+  }
+
+  template <typename Iterator>
+  inline static void DoWalkBasicBlocks(PassMEDataHolder* data, const PassME* pass) {
+      DCHECK(data != nullptr);
+      CompilationUnit* c_unit = data->c_unit;
+      DCHECK(c_unit != nullptr);
+      Iterator iterator(c_unit->mir_graph.get());
+      DoWalkBasicBlocks(data, pass, &iterator);
+    }
+};
 }  // namespace art
 #endif  // ART_COMPILER_DEX_PASS_DRIVER_ME_H_
+
diff --git a/compiler/dex/pass_driver_me_opts.cc b/compiler/dex/pass_driver_me_opts.cc
new file mode 100644
index 0000000..52a2273
--- /dev/null
+++ b/compiler/dex/pass_driver_me_opts.cc
@@ -0,0 +1,88 @@
+/*
+ * 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 "base/macros.h"
+#include "bb_optimizations.h"
+#include "compiler_internals.h"
+#include "dataflow_iterator.h"
+#include "dataflow_iterator-inl.h"
+#include "pass_driver_me_opts.h"
+
+namespace art {
+
+/*
+ * Create the pass list. These passes are immutable and are shared across the threads.
+ *
+ * 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.
+ */
+// The initial list of passes to be used by the PassDriveMEOpts.
+template<>
+const Pass* const PassDriver<PassDriverMEOpts>::g_passes[] = {
+  GetPassInstance<CacheFieldLoweringInfo>(),
+  GetPassInstance<CacheMethodLoweringInfo>(),
+  GetPassInstance<CallInlining>(),
+  GetPassInstance<CodeLayout>(),
+  GetPassInstance<NullCheckEliminationAndTypeInference>(),
+  GetPassInstance<ClassInitCheckElimination>(),
+  GetPassInstance<BBCombine>(),
+  GetPassInstance<BBOptimizations>(),
+};
+
+// The number of the passes in the initial list of Passes (g_passes).
+template<>
+uint16_t const PassDriver<PassDriverMEOpts>::g_passes_size =
+    arraysize(PassDriver<PassDriverMEOpts>::g_passes);
+
+// The default pass list is used by the PassDriverME instance of PassDriver
+// to initialize pass_list_.
+template<>
+std::vector<const Pass*> PassDriver<PassDriverMEOpts>::g_default_pass_list(
+    PassDriver<PassDriverMEOpts>::g_passes,
+    PassDriver<PassDriverMEOpts>::g_passes +
+    PassDriver<PassDriverMEOpts>::g_passes_size);
+
+// By default, do not have a dump pass list.
+template<>
+std::string PassDriver<PassDriverMEOpts>::dump_pass_list_ = std::string();
+
+// By default, do not have a print pass list.
+template<>
+std::string PassDriver<PassDriverMEOpts>::print_pass_list_ = std::string();
+
+// By default, we do not print the pass' information.
+template<>
+bool PassDriver<PassDriverMEOpts>::default_print_passes_ = false;
+
+void PassDriverMEOpts::ApplyPass(PassDataHolder* data, const Pass* pass) {
+  // First call the base class' version.
+  PassDriver::ApplyPass(data, pass);
+
+  const PassME* pass_me = down_cast<const PassME*> (pass);
+  DCHECK(pass_me != nullptr);
+
+  PassMEDataHolder* pass_me_data_holder = down_cast<PassMEDataHolder*>(data);
+
+  // Now we care about flags.
+  if ((pass_me->GetFlag(kOptimizationBasicBlockChange) == true) ||
+      (pass_me->GetFlag(kOptimizationDefUsesChange) == true)) {
+    CompilationUnit* c_unit = pass_me_data_holder->c_unit;
+    c_unit->mir_graph.get()->CalculateBasicBlockInformation();
+  }
+}
+
+}  // namespace art
diff --git a/compiler/dex/pass_driver_me_opts.h b/compiler/dex/pass_driver_me_opts.h
new file mode 100644
index 0000000..0a5b5ae
--- /dev/null
+++ b/compiler/dex/pass_driver_me_opts.h
@@ -0,0 +1,44 @@
+/*
+ * 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_ME_OPTS_H_
+#define ART_COMPILER_DEX_PASS_DRIVER_ME_OPTS_H_
+
+#include "pass_driver_me.h"
+
+namespace art {
+
+// Forward Declarations.
+struct CompilationUnit;
+class Pass;
+class PassDataHolder;
+
+class PassDriverMEOpts : public PassDriverME<PassDriverMEOpts> {
+ public:
+  explicit PassDriverMEOpts(CompilationUnit* cu):PassDriverME<PassDriverMEOpts>(cu) {
+  }
+
+  ~PassDriverMEOpts() {
+  }
+
+  /**
+   * @brief Apply a patch: perform start/work/end functions.
+   */
+  virtual void ApplyPass(PassDataHolder* data, const Pass* pass);
+};
+
+}  // namespace art
+#endif  // ART_COMPILER_DEX_PASS_DRIVER_ME_OPTS_H_
diff --git a/compiler/dex/pass_driver_me_post_opt.cc b/compiler/dex/pass_driver_me_post_opt.cc
new file mode 100644
index 0000000..cb63f41
--- /dev/null
+++ b/compiler/dex/pass_driver_me_post_opt.cc
@@ -0,0 +1,75 @@
+/*
+ * 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 "base/macros.h"
+#include "post_opt_passes.h"
+#include "compiler_internals.h"
+#include "pass_driver_me_post_opt.h"
+
+namespace art {
+
+/*
+ * Create the pass list. These passes are immutable and are shared across the threads.
+ *
+ * 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.
+ */
+// The initial list of passes to be used by the PassDriveMEPostOpt.
+template<>
+const Pass* const PassDriver<PassDriverMEPostOpt>::g_passes[] = {
+  GetPassInstance<InitializeData>(),
+  GetPassInstance<ClearPhiInstructions>(),
+  GetPassInstance<CalculatePredecessors>(),
+  GetPassInstance<DFSOrders>(),
+  GetPassInstance<BuildDomination>(),
+  GetPassInstance<DefBlockMatrix>(),
+  GetPassInstance<CreatePhiNodes>(),
+  GetPassInstance<ClearVisitedFlag>(),
+  GetPassInstance<SSAConversion>(),
+  GetPassInstance<PhiNodeOperands>(),
+  GetPassInstance<ConstantPropagation>(),
+  GetPassInstance<PerformInitRegLocations>(),
+  GetPassInstance<MethodUseCount>(),
+  GetPassInstance<FreeData>(),
+};
+
+// The number of the passes in the initial list of Passes (g_passes).
+template<>
+uint16_t const PassDriver<PassDriverMEPostOpt>::g_passes_size =
+    arraysize(PassDriver<PassDriverMEPostOpt>::g_passes);
+
+// The default pass list is used by the PassDriverME instance of PassDriver
+// to initialize pass_list_.
+template<>
+std::vector<const Pass*> PassDriver<PassDriverMEPostOpt>::g_default_pass_list(
+    PassDriver<PassDriverMEPostOpt>::g_passes,
+    PassDriver<PassDriverMEPostOpt>::g_passes +
+    PassDriver<PassDriverMEPostOpt>::g_passes_size);
+
+// By default, do not have a dump pass list.
+template<>
+std::string PassDriver<PassDriverMEPostOpt>::dump_pass_list_ = std::string();
+
+// By default, do not have a print pass list.
+template<>
+std::string PassDriver<PassDriverMEPostOpt>::print_pass_list_ = std::string();
+
+// By default, we do not print the pass' information.
+template<>
+bool PassDriver<PassDriverMEPostOpt>::default_print_passes_ = false;
+
+}  // namespace art
diff --git a/compiler/dex/pass_driver_me_post_opt.h b/compiler/dex/pass_driver_me_post_opt.h
new file mode 100644
index 0000000..adba363
--- /dev/null
+++ b/compiler/dex/pass_driver_me_post_opt.h
@@ -0,0 +1,39 @@
+/*
+ * 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_ME_CLEANUP_H_
+#define ART_COMPILER_DEX_PASS_DRIVER_ME_CLEANUP_H_
+
+#include "pass_driver_me.h"
+
+namespace art {
+
+// Forward Declarations.
+struct CompilationUnit;
+class Pass;
+class PassDataHolder;
+
+class PassDriverMEPostOpt : public PassDriverME<PassDriverMEPostOpt> {
+ public:
+  explicit PassDriverMEPostOpt(CompilationUnit* cu) : PassDriverME<PassDriverMEPostOpt>(cu) {
+  }
+
+  ~PassDriverMEPostOpt() {
+  }
+};
+
+}  // namespace art
+#endif  // ART_COMPILER_DEX_PASS_DRIVER_ME_CLEANUP_H_
diff --git a/compiler/dex/pass_me.h b/compiler/dex/pass_me.h
index 069fb45..9efd5ae 100644
--- a/compiler/dex/pass_me.h
+++ b/compiler/dex/pass_me.h
@@ -32,6 +32,9 @@
  * @details Each enum should be a power of 2 to be correctly used.
  */
 enum OptimizationFlag {
+  kOptimizationBasicBlockChange = 1,  /**< @brief Has there been a change to a BasicBlock? */
+  kOptimizationDefUsesChange = 2,     /**< @brief Has there been a change to a def-use? */
+  kLoopStructureChange = 4,           /**< @brief Has there been a loop structural change? */
 };
 
 // Data holder class.
@@ -93,7 +96,7 @@
   /** @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. */
+  /** @brief Flags for additional directives: used to determine if a particular post-optimization pass is necessary. */
   const unsigned int flags_;
 
   /** @brief CFG Dump Folder: what sub-folder to use for dumping the CFGs post pass. */
diff --git a/compiler/dex/post_opt_passes.cc b/compiler/dex/post_opt_passes.cc
new file mode 100644
index 0000000..58700a4
--- /dev/null
+++ b/compiler/dex/post_opt_passes.cc
@@ -0,0 +1,108 @@
+/*
+ * 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 "post_opt_passes.h"
+#include "dataflow_iterator.h"
+#include "dataflow_iterator-inl.h"
+
+namespace art {
+
+/*
+ * MethodUseCount pass implementation start.
+ */
+bool MethodUseCount::Gate(const PassDataHolder* data) const {
+  DCHECK(data != nullptr);
+  CompilationUnit* c_unit = down_cast<const PassMEDataHolder*>(data)->c_unit;
+  DCHECK(c_unit != nullptr);
+  // First initialize the data.
+  c_unit->mir_graph->InitializeMethodUses();
+
+  // Now check if the pass is to be ignored.
+  bool res = ((c_unit->disable_opt & (1 << kPromoteRegs)) == 0);
+
+  return res;
+}
+
+bool MethodUseCount::Worker(const PassDataHolder* data) const {
+  DCHECK(data != nullptr);
+  const PassMEDataHolder* pass_me_data_holder = down_cast<const PassMEDataHolder*>(data);
+  CompilationUnit* c_unit = pass_me_data_holder->c_unit;
+  DCHECK(c_unit != nullptr);
+  BasicBlock* bb = pass_me_data_holder->bb;
+  DCHECK(bb != nullptr);
+  c_unit->mir_graph->CountUses(bb);
+  // No need of repeating, so just return false.
+  return false;
+}
+
+
+bool ClearPhiInstructions::Worker(const PassDataHolder* data) const {
+  DCHECK(data != nullptr);
+  const PassMEDataHolder* pass_me_data_holder = down_cast<const PassMEDataHolder*>(data);
+  CompilationUnit* c_unit = pass_me_data_holder->c_unit;
+  DCHECK(c_unit != nullptr);
+  BasicBlock* bb = pass_me_data_holder->bb;
+  DCHECK(bb != nullptr);
+  MIR* mir = bb->first_mir_insn;
+
+  while (mir != nullptr) {
+    MIR* next = mir->next;
+
+    Instruction::Code opcode = mir->dalvikInsn.opcode;
+
+    if (opcode == static_cast<Instruction::Code> (kMirOpPhi)) {
+      bb->RemoveMIR(mir);
+    }
+
+    mir = next;
+  }
+
+  // We do not care in reporting a change or not in the MIR.
+  return false;
+}
+
+void CalculatePredecessors::Start(const PassDataHolder* data) const {
+  DCHECK(data != nullptr);
+  CompilationUnit* c_unit = down_cast<const PassMEDataHolder*>(data)->c_unit;
+  DCHECK(c_unit != nullptr);
+  // First get the MIRGraph here to factorize a bit the code.
+  MIRGraph *mir_graph = c_unit->mir_graph.get();
+
+  // First clear all predecessors.
+  AllNodesIterator first(mir_graph);
+  for (BasicBlock* bb = first.Next(); bb != nullptr; bb = first.Next()) {
+    bb->predecessors->Reset();
+  }
+
+  // Now calculate all predecessors.
+  AllNodesIterator second(mir_graph);
+  for (BasicBlock* bb = second.Next(); bb != nullptr; bb = second.Next()) {
+    // We only care about non hidden blocks.
+    if (bb->hidden == true) {
+      continue;
+    }
+
+    // Create iterator for visiting children.
+    ChildBlockIterator child_iter(bb, mir_graph);
+
+    // Now iterate through the children to set the predecessor bits.
+    for (BasicBlock* child = child_iter.Next(); child != nullptr; child = child_iter.Next()) {
+      child->predecessors->Insert(bb->id);
+    }
+  }
+}
+
+}  // namespace art
diff --git a/compiler/dex/post_opt_passes.h b/compiler/dex/post_opt_passes.h
new file mode 100644
index 0000000..e101fb5
--- /dev/null
+++ b/compiler/dex/post_opt_passes.h
@@ -0,0 +1,284 @@
+/*
+ * 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_CLEAN_UP_PASSES_H_
+#define ART_COMPILER_DEX_CLEAN_UP_PASSES_H_
+
+#include "compiler_internals.h"
+#include "pass_me.h"
+
+namespace art {
+
+/**
+ * @class InitializeData
+ * @brief There is some data that needs to be initialized before performing
+ * the post optimization passes.
+ */
+class InitializeData : public PassME {
+ public:
+  InitializeData() : PassME("InitializeData") {
+  }
+
+  void Start(const PassDataHolder* data) const {
+    // New blocks may have been inserted so the first thing we do is ensure that
+    // the c_unit's number of blocks matches the actual count of basic blocks.
+    DCHECK(data != nullptr);
+    CompilationUnit* c_unit = down_cast<const PassMEDataHolder*>(data)->c_unit;
+    DCHECK(c_unit != nullptr);
+    c_unit->mir_graph.get()->InitializeBasicBlockData();
+    c_unit->mir_graph.get()->SSATransformationStart();
+  }
+};
+
+/**
+ * @class MethodUseCount
+ * @brief Count the register uses of the method
+ */
+class MethodUseCount : public PassME {
+ public:
+  MethodUseCount() : PassME("UseCount") {
+  }
+
+  bool Worker(const PassDataHolder* data) const;
+
+  bool Gate(const PassDataHolder* data) const;
+};
+
+/**
+ * @class ClearPhiInformation
+ * @brief Clear the PHI nodes from the CFG.
+ */
+class ClearPhiInstructions : public PassME {
+ public:
+  ClearPhiInstructions() : PassME("ClearPhiInstructions") {
+  }
+
+  bool Worker(const PassDataHolder* data) const;
+};
+
+/**
+ * @class CalculatePredecessors
+ * @brief Calculate the predecessor BitVector of each Basicblock.
+ */
+class CalculatePredecessors : public PassME {
+ public:
+  CalculatePredecessors() : PassME("CalculatePredecessors") {
+  }
+
+  void Start(const PassDataHolder* data) const;
+};
+
+/**
+ * @class DFSOrders
+ * @brief Compute the DFS order of the MIR graph
+ */
+class DFSOrders : public PassME {
+ public:
+  DFSOrders() : PassME("DFSOrders") {
+  }
+
+  void Start(const PassDataHolder* data) const {
+    DCHECK(data != nullptr);
+    CompilationUnit* c_unit = down_cast<const PassMEDataHolder*>(data)->c_unit;
+    DCHECK(c_unit != nullptr);
+    c_unit->mir_graph.get()->ComputeDFSOrders();
+  }
+};
+
+/**
+ * @class BuildDomination
+ * @brief Build the domination information of the MIR Graph
+ */
+class BuildDomination : public PassME {
+ public:
+  BuildDomination() : PassME("BuildDomination") {
+  }
+
+  void Start(const PassDataHolder* data) const {
+    DCHECK(data != nullptr);
+    CompilationUnit* c_unit = down_cast<const PassMEDataHolder*>(data)->c_unit;
+    DCHECK(c_unit != nullptr);
+    c_unit->mir_graph.get()->ComputeDominators();
+    c_unit->mir_graph.get()->CompilerInitializeSSAConversion();
+  }
+
+  void End(const PassDataHolder* data) const {
+    DCHECK(data != nullptr);
+    CompilationUnit* c_unit = down_cast<const PassMEDataHolder*>(data)->c_unit;
+    DCHECK(c_unit != nullptr);
+    // Verify the dataflow information after the pass.
+    if (c_unit->enable_debug & (1 << kDebugVerifyDataflow)) {
+      c_unit->mir_graph->VerifyDataflow();
+    }
+  }
+};
+
+/**
+ * @class DefBlockMatrix
+ * @brief Calculate the matrix of definition per basic block
+ */
+class DefBlockMatrix : public PassME {
+ public:
+  DefBlockMatrix() : PassME("DefBlockMatrix") {
+  }
+
+  void Start(const PassDataHolder* data) const {
+    DCHECK(data != nullptr);
+    CompilationUnit* c_unit = down_cast<const PassMEDataHolder*>(data)->c_unit;
+    DCHECK(c_unit != nullptr);
+    c_unit->mir_graph.get()->ComputeDefBlockMatrix();
+  }
+};
+
+/**
+ * @class CreatePhiNodes
+ * @brief Pass to create the phi nodes after SSA calculation
+ */
+class CreatePhiNodes : public PassME {
+ public:
+  CreatePhiNodes() : PassME("CreatePhiNodes") {
+  }
+
+  void Start(const PassDataHolder* data) const {
+    DCHECK(data != nullptr);
+    CompilationUnit* c_unit = down_cast<const PassMEDataHolder*>(data)->c_unit;
+    DCHECK(c_unit != nullptr);
+    c_unit->mir_graph.get()->InsertPhiNodes();
+  }
+};
+
+/**
+ * @class ClearVisitedFlag
+ * @brief Pass to clear the visited flag for all basic blocks.
+ */
+
+class ClearVisitedFlag : public PassME {
+ public:
+  ClearVisitedFlag() : PassME("ClearVisitedFlag") {
+  }
+
+  void Start(const PassDataHolder* data) const {
+    DCHECK(data != nullptr);
+    CompilationUnit* c_unit = down_cast<const PassMEDataHolder*>(data)->c_unit;
+    DCHECK(c_unit != nullptr);
+    c_unit->mir_graph.get()->ClearAllVisitedFlags();
+  }
+};
+
+/**
+ * @class SSAConversion
+ * @brief Pass for SSA conversion of MIRs
+ */
+class SSAConversion : public PassME {
+ public:
+  SSAConversion() : PassME("SSAConversion") {
+  }
+
+  void Start(const PassDataHolder* data) const {
+    DCHECK(data != nullptr);
+    CompilationUnit* c_unit = down_cast<const PassMEDataHolder*>(data)->c_unit;
+    DCHECK(c_unit != nullptr);
+    MIRGraph *mir_graph = c_unit->mir_graph.get();
+    mir_graph->DoDFSPreOrderSSARename(mir_graph->GetEntryBlock());
+  }
+};
+
+/**
+ * @class PhiNodeOperands
+ * @brief Pass to insert the Phi node operands to basic blocks
+ */
+class PhiNodeOperands : public PassME {
+ public:
+  PhiNodeOperands() : PassME("PhiNodeOperands", kPreOrderDFSTraversal) {
+  }
+
+  bool Worker(const PassDataHolder* data) const {
+    DCHECK(data != nullptr);
+    CompilationUnit* c_unit = down_cast<const PassMEDataHolder*>(data)->c_unit;
+    DCHECK(c_unit != nullptr);
+    BasicBlock* bb = down_cast<const PassMEDataHolder*>(data)->bb;
+    DCHECK(bb != nullptr);
+    c_unit->mir_graph->InsertPhiNodeOperands(bb);
+    // No need of repeating, so just return false.
+    return false;
+  }
+};
+
+/**
+ * @class InitRegLocations
+ * @brief Initialize Register Locations.
+ */
+class PerformInitRegLocations : public PassME {
+ public:
+  PerformInitRegLocations() : PassME("PerformInitRegLocation") {
+  }
+
+  void Start(const PassDataHolder* data) const {
+    DCHECK(data != nullptr);
+    CompilationUnit* c_unit = down_cast<const PassMEDataHolder*>(data)->c_unit;
+    DCHECK(c_unit != nullptr);
+    c_unit->mir_graph->InitRegLocations();
+  }
+};
+
+/**
+ * @class ConstantPropagation
+ * @brief Perform a constant propagation pass.
+ */
+class ConstantPropagation : public PassME {
+ public:
+  ConstantPropagation() : PassME("ConstantPropagation") {
+  }
+
+  bool Worker(const PassDataHolder* data) const {
+    DCHECK(data != nullptr);
+    CompilationUnit* c_unit = down_cast<const PassMEDataHolder*>(data)->c_unit;
+    DCHECK(c_unit != nullptr);
+    BasicBlock* bb = down_cast<const PassMEDataHolder*>(data)->bb;
+    DCHECK(bb != nullptr);
+    c_unit->mir_graph->DoConstantPropagation(bb);
+    // No need of repeating, so just return false.
+    return false;
+  }
+
+  void Start(const PassDataHolder* data) const {
+    DCHECK(data != nullptr);
+    CompilationUnit* c_unit = down_cast<const PassMEDataHolder*>(data)->c_unit;
+    DCHECK(c_unit != nullptr);
+    c_unit->mir_graph->InitializeConstantPropagation();
+  }
+};
+
+/**
+ * @class FreeData
+ * @brief There is some data that needs to be freed after performing the post optimization passes.
+ */
+class FreeData : public PassME {
+ public:
+  FreeData() : PassME("FreeData") {
+  }
+
+  void End(const PassDataHolder* data) const {
+    DCHECK(data != nullptr);
+    CompilationUnit* c_unit = down_cast<const PassMEDataHolder*>(data)->c_unit;
+    DCHECK(c_unit != nullptr);
+    c_unit->mir_graph.get()->SSATransformationEnd();
+  }
+};
+
+}  // namespace art
+
+#endif  // ART_COMPILER_DEX_CLEAN_UP_PASSES_H_
diff --git a/compiler/dex/ssa_transformation.cc b/compiler/dex/ssa_transformation.cc
index 0c5a4ca..bd6bc225 100644
--- a/compiler/dex/ssa_transformation.cc
+++ b/compiler/dex/ssa_transformation.cc
@@ -244,9 +244,9 @@
 
   /* Calculate DF_up */
   for (uint32_t dominated_idx : bb->i_dominated->Indexes()) {
-    BasicBlock *dominated_bb = GetBasicBlock(dominated_idx);
+    BasicBlock* dominated_bb = GetBasicBlock(dominated_idx);
     for (uint32_t df_up_block_idx : dominated_bb->dom_frontier->Indexes()) {
-      BasicBlock *df_up_block = GetBasicBlock(df_up_block_idx);
+      BasicBlock* df_up_block = GetBasicBlock(df_up_block_idx);
       CheckForDominanceFrontier(bb, df_up_block);
     }
   }
diff --git a/dex2oat/dex2oat.cc b/dex2oat/dex2oat.cc
index 4d3d664..c6b1aa5 100644
--- a/dex2oat/dex2oat.cc
+++ b/dex2oat/dex2oat.cc
@@ -33,7 +33,7 @@
 #include "compiler.h"
 #include "compiler_callbacks.h"
 #include "dex_file-inl.h"
-#include "dex/pass_driver_me.h"
+#include "dex/pass_driver_me_opts.h"
 #include "dex/verification_results.h"
 #include "driver/compiler_callbacks_impl.h"
 #include "driver/compiler_driver.h"
@@ -919,18 +919,18 @@
     } else if (option == "--no-profile-file") {
       // No profile
     } else if (option == "--print-pass-names") {
-      PassDriverME::PrintPassNames();
+      PassDriverMEOpts::PrintPassNames();
     } else if (option.starts_with("--disable-passes=")) {
       std::string disable_passes = option.substr(strlen("--disable-passes=")).data();
-      PassDriverME::CreateDefaultPassList(disable_passes);
+      PassDriverMEOpts::CreateDefaultPassList(disable_passes);
     } else if (option.starts_with("--print-passes=")) {
       std::string print_passes = option.substr(strlen("--print-passes=")).data();
-      PassDriverME::SetPrintPassList(print_passes);
+      PassDriverMEOpts::SetPrintPassList(print_passes);
     } else if (option == "--print-all-passes") {
-      PassDriverME::SetPrintAllPasses();
+      PassDriverMEOpts::SetPrintAllPasses();
     } else if (option.starts_with("--dump-cfg-passes=")) {
       std::string dump_passes = option.substr(strlen("--dump-cfg-passes=")).data();
-      PassDriverME::SetDumpPassList(dump_passes);
+      PassDriverMEOpts::SetDumpPassList(dump_passes);
     } else {
       Usage("Unknown argument %s", option.data());
     }