Revert "Revert "Introduce a class to implement optimization passes.""

This reverts commit 1ddbf6d4b37979a9f11a203c12befd5ae8b65df4.

Change-Id: I110a14668d1564ee0604dc958b91394b40da89fc
diff --git a/build/Android.gtest.mk b/build/Android.gtest.mk
index 38d3f1c..f782d5c 100644
--- a/build/Android.gtest.mk
+++ b/build/Android.gtest.mk
@@ -141,7 +141,7 @@
   compiler/oat_test.cc \
   compiler/optimizing/codegen_test.cc \
   compiler/optimizing/dead_code_elimination_test.cc \
-  compiler/optimizing/constant_propagation_test.cc \
+  compiler/optimizing/constant_folding_test.cc \
   compiler/optimizing/dominator_test.cc \
   compiler/optimizing/find_loops_test.cc \
   compiler/optimizing/graph_checker_test.cc \
diff --git a/compiler/Android.mk b/compiler/Android.mk
index f413576..25b23a2 100644
--- a/compiler/Android.mk
+++ b/compiler/Android.mk
@@ -90,7 +90,7 @@
 	optimizing/code_generator_arm.cc \
 	optimizing/code_generator_x86.cc \
 	optimizing/code_generator_x86_64.cc \
-	optimizing/constant_propagation.cc \
+	optimizing/constant_folding.cc \
 	optimizing/dead_code_elimination.cc \
 	optimizing/graph_checker.cc \
 	optimizing/graph_visualizer.cc \
@@ -98,6 +98,7 @@
 	optimizing/instruction_simplifier.cc \
 	optimizing/locations.cc \
 	optimizing/nodes.cc \
+	optimizing/optimization.cc \
 	optimizing/optimizing_compiler.cc \
 	optimizing/parallel_move_resolver.cc \
 	optimizing/prepare_for_register_allocation.cc \
diff --git a/compiler/optimizing/constant_propagation.cc b/compiler/optimizing/constant_folding.cc
similarity index 95%
rename from compiler/optimizing/constant_propagation.cc
rename to compiler/optimizing/constant_folding.cc
index d675164..0b3ad98 100644
--- a/compiler/optimizing/constant_propagation.cc
+++ b/compiler/optimizing/constant_folding.cc
@@ -14,11 +14,11 @@
  * limitations under the License.
  */
 
-#include "constant_propagation.h"
+#include "constant_folding.h"
 
 namespace art {
 
-void ConstantPropagation::Run() {
+void HConstantFolding::Run() {
   // Process basic blocks in reverse post-order in the dominator tree,
   // so that an instruction turned into a constant, used as input of
   // another instruction, may possibly be used to turn that second
diff --git a/compiler/optimizing/constant_folding.h b/compiler/optimizing/constant_folding.h
new file mode 100644
index 0000000..d2acfa6
--- /dev/null
+++ b/compiler/optimizing/constant_folding.h
@@ -0,0 +1,48 @@
+/*
+ * 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_OPTIMIZING_CONSTANT_FOLDING_H_
+#define ART_COMPILER_OPTIMIZING_CONSTANT_FOLDING_H_
+
+#include "nodes.h"
+#include "optimization.h"
+
+namespace art {
+
+/**
+ * Optimization pass performing a simple constant-expression
+ * evaluation on the SSA form.
+ *
+ * This class is named art::HConstantFolding to avoid name
+ * clashes with the art::ConstantPropagation class defined in
+ * compiler/dex/post_opt_passes.h.
+ */
+class HConstantFolding : public HOptimization {
+ public:
+  HConstantFolding(HGraph* graph, const HGraphVisualizer& visualizer)
+      : HOptimization(graph, true, kConstantFoldingPassName, visualizer) {}
+
+  virtual void Run() OVERRIDE;
+
+  static constexpr const char* kConstantFoldingPassName = "constant_folding";
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(HConstantFolding);
+};
+
+}  // namespace art
+
+#endif  // ART_COMPILER_OPTIMIZING_CONSTANT_FOLDING_H_
diff --git a/compiler/optimizing/constant_propagation_test.cc b/compiler/optimizing/constant_folding_test.cc
similarity index 84%
rename from compiler/optimizing/constant_propagation_test.cc
rename to compiler/optimizing/constant_folding_test.cc
index ff44805..ec2ff33 100644
--- a/compiler/optimizing/constant_propagation_test.cc
+++ b/compiler/optimizing/constant_folding_test.cc
@@ -16,11 +16,12 @@
 
 #include <functional>
 
-#include "constant_propagation.h"
+#include "code_generator_x86.h"
+#include "constant_folding.h"
 #include "dead_code_elimination.h"
-#include "pretty_printer.h"
 #include "graph_checker.h"
 #include "optimizing_unit_test.h"
+#include "pretty_printer.h"
 
 #include "gtest/gtest.h"
 
@@ -28,9 +29,9 @@
 
 static void TestCode(const uint16_t* data,
                      const std::string& expected_before,
-                     const std::string& expected_after_cp,
+                     const std::string& expected_after_cf,
                      const std::string& expected_after_dce,
-                     std::function<void(HGraph*)> check_after_cp,
+                     std::function<void(HGraph*)> check_after_cf,
                      Primitive::Type return_type = Primitive::kPrimInt) {
   ArenaPool pool;
   ArenaAllocator allocator(&pool);
@@ -45,25 +46,28 @@
   std::string actual_before = printer_before.str();
   ASSERT_EQ(expected_before, actual_before);
 
-  ConstantPropagation(graph).Run();
+  x86::CodeGeneratorX86 codegen(graph);
+  HGraphVisualizer visualizer(nullptr, graph, codegen, "");
+  HConstantFolding(graph, visualizer).Run();
+  SSAChecker ssa_checker(&allocator, graph);
+  ssa_checker.Run();
+  ASSERT_TRUE(ssa_checker.IsValid());
 
-  StringPrettyPrinter printer_after_cp(graph);
-  printer_after_cp.VisitInsertionOrder();
-  std::string actual_after_cp = printer_after_cp.str();
-  ASSERT_EQ(expected_after_cp, actual_after_cp);
+  StringPrettyPrinter printer_after_cf(graph);
+  printer_after_cf.VisitInsertionOrder();
+  std::string actual_after_cf = printer_after_cf.str();
+  ASSERT_EQ(expected_after_cf, actual_after_cf);
 
-  check_after_cp(graph);
+  check_after_cf(graph);
 
-  DeadCodeElimination(graph).Run();
+  HDeadCodeElimination(graph, visualizer).Run();
+  ssa_checker.Run();
+  ASSERT_TRUE(ssa_checker.IsValid());
 
   StringPrettyPrinter printer_after_dce(graph);
   printer_after_dce.VisitInsertionOrder();
   std::string actual_after_dce = printer_after_dce.str();
   ASSERT_EQ(expected_after_dce, actual_after_dce);
-
-  SSAChecker ssa_checker(&allocator, graph);
-  ssa_checker.Run();
-  ASSERT_TRUE(ssa_checker.IsValid());
 }
 
 
@@ -78,7 +82,7 @@
  *     v2 <- v0 + v1            2.      add-int v2, v0, v1
  *     return v2                4.      return v2
  */
-TEST(ConstantPropagation, IntConstantFoldingOnAddition1) {
+TEST(ConstantFolding, IntConstantFoldingOnAddition1) {
   const uint16_t data[] = THREE_REGISTERS_CODE_ITEM(
     Instruction::CONST_4 | 0 << 8 | 1 << 12,
     Instruction::CONST_4 | 1 << 8 | 2 << 12,
@@ -97,17 +101,17 @@
     "BasicBlock 2, pred: 1\n"
     "  13: Exit\n";
 
-  // Expected difference after constant propagation.
-  diff_t expected_cp_diff = {
+  // Expected difference after constant folding.
+  diff_t expected_cf_diff = {
     { "  3: IntConstant [9]\n", "  3: IntConstant\n" },
     { "  5: IntConstant [9]\n", "  5: IntConstant\n" },
     { "  9: Add(3, 5) [12]\n",  "  16: IntConstant [12]\n" },
     { "  12: Return(9)\n",      "  12: Return(16)\n" }
   };
-  std::string expected_after_cp = Patch(expected_before, expected_cp_diff);
+  std::string expected_after_cf = Patch(expected_before, expected_cf_diff);
 
   // Check the value of the computed constant.
-  auto check_after_cp = [](HGraph* graph) {
+  auto check_after_cf = [](HGraph* graph) {
     HInstruction* inst = graph->GetBlock(1)->GetFirstInstruction();
     ASSERT_TRUE(inst->IsIntConstant());
     ASSERT_EQ(inst->AsIntConstant()->GetValue(), 3);
@@ -118,13 +122,13 @@
     { "  3: IntConstant\n", removed },
     { "  5: IntConstant\n", removed }
   };
-  std::string expected_after_dce = Patch(expected_after_cp, expected_dce_diff);
+  std::string expected_after_dce = Patch(expected_after_cf, expected_dce_diff);
 
   TestCode(data,
            expected_before,
-           expected_after_cp,
+           expected_after_cf,
            expected_after_dce,
-           check_after_cp);
+           check_after_cf);
 }
 
 /**
@@ -142,7 +146,7 @@
  *     v2 <- v0 + v1            6.      add-int v2, v0, v1
  *     return v2                8.      return v2
  */
-TEST(ConstantPropagation, IntConstantFoldingOnAddition2) {
+TEST(ConstantFolding, IntConstantFoldingOnAddition2) {
   const uint16_t data[] = THREE_REGISTERS_CODE_ITEM(
     Instruction::CONST_4 | 0 << 8 | 1 << 12,
     Instruction::CONST_4 | 1 << 8 | 2 << 12,
@@ -169,8 +173,8 @@
     "BasicBlock 2, pred: 1\n"
     "  25: Exit\n";
 
-  // Expected difference after constant propagation.
-  diff_t expected_cp_diff = {
+  // Expected difference after constant folding.
+  diff_t expected_cf_diff = {
     { "  3: IntConstant [9]\n",   "  3: IntConstant\n" },
     { "  5: IntConstant [9]\n",   "  5: IntConstant\n" },
     { "  11: IntConstant [17]\n", "  11: IntConstant\n" },
@@ -180,10 +184,10 @@
     { "  21: Add(9, 17) [24]\n",  "  30: IntConstant [24]\n" },
     { "  24: Return(21)\n",       "  24: Return(30)\n" }
   };
-  std::string expected_after_cp = Patch(expected_before, expected_cp_diff);
+  std::string expected_after_cf = Patch(expected_before, expected_cf_diff);
 
   // Check the values of the computed constants.
-  auto check_after_cp = [](HGraph* graph) {
+  auto check_after_cf = [](HGraph* graph) {
     HInstruction* inst1 = graph->GetBlock(1)->GetFirstInstruction();
     ASSERT_TRUE(inst1->IsIntConstant());
     ASSERT_EQ(inst1->AsIntConstant()->GetValue(), 3);
@@ -204,13 +208,13 @@
     { "  28: IntConstant\n", removed },
     { "  29: IntConstant\n", removed }
   };
-  std::string expected_after_dce = Patch(expected_after_cp, expected_dce_diff);
+  std::string expected_after_dce = Patch(expected_after_cf, expected_dce_diff);
 
   TestCode(data,
            expected_before,
-           expected_after_cp,
+           expected_after_cf,
            expected_after_dce,
-           check_after_cp);
+           check_after_cf);
 }
 
 /**
@@ -224,7 +228,7 @@
  *     v2 <- v0 - v1            2.      sub-int v2, v0, v1
  *     return v2                4.      return v2
  */
-TEST(ConstantPropagation, IntConstantFoldingOnSubtraction) {
+TEST(ConstantFolding, IntConstantFoldingOnSubtraction) {
   const uint16_t data[] = THREE_REGISTERS_CODE_ITEM(
     Instruction::CONST_4 | 0 << 8 | 3 << 12,
     Instruction::CONST_4 | 1 << 8 | 2 << 12,
@@ -243,17 +247,17 @@
     "BasicBlock 2, pred: 1\n"
     "  13: Exit\n";
 
-  // Expected difference after constant propagation.
-  diff_t expected_cp_diff = {
+  // Expected difference after constant folding.
+  diff_t expected_cf_diff = {
     { "  3: IntConstant [9]\n", "  3: IntConstant\n" },
     { "  5: IntConstant [9]\n", "  5: IntConstant\n" },
     { "  9: Sub(3, 5) [12]\n",  "  16: IntConstant [12]\n" },
     { "  12: Return(9)\n",      "  12: Return(16)\n" }
   };
-  std::string expected_after_cp = Patch(expected_before, expected_cp_diff);
+  std::string expected_after_cf = Patch(expected_before, expected_cf_diff);
 
   // Check the value of the computed constant.
-  auto check_after_cp = [](HGraph* graph) {
+  auto check_after_cf = [](HGraph* graph) {
     HInstruction* inst = graph->GetBlock(1)->GetFirstInstruction();
     ASSERT_TRUE(inst->IsIntConstant());
     ASSERT_EQ(inst->AsIntConstant()->GetValue(), 1);
@@ -264,13 +268,13 @@
     { "  3: IntConstant\n", removed },
     { "  5: IntConstant\n", removed }
   };
-  std::string expected_after_dce = Patch(expected_after_cp, expected_dce_diff);
+  std::string expected_after_dce = Patch(expected_after_cf, expected_dce_diff);
 
   TestCode(data,
            expected_before,
-           expected_after_cp,
+           expected_after_cf,
            expected_after_dce,
-           check_after_cp);
+           check_after_cf);
 }
 
 #define SIX_REGISTERS_CODE_ITEM(...)                                     \
@@ -289,7 +293,7 @@
  *       (v0, v1) + (v1, v2)    4.      add-long v4, v0, v2
  *     return (v4, v5)          6.      return-wide v4
  */
-TEST(ConstantPropagation, LongConstantFoldingOnAddition) {
+TEST(ConstantFolding, LongConstantFoldingOnAddition) {
   const uint16_t data[] = SIX_REGISTERS_CODE_ITEM(
     Instruction::CONST_WIDE_16 | 0 << 8, 1,
     Instruction::CONST_WIDE_16 | 2 << 8, 2,
@@ -308,17 +312,17 @@
     "BasicBlock 2, pred: 1\n"
     "  16: Exit\n";
 
-  // Expected difference after constant propagation.
-  diff_t expected_cp_diff = {
+  // Expected difference after constant folding.
+  diff_t expected_cf_diff = {
     { "  6: LongConstant [12]\n", "  6: LongConstant\n" },
     { "  8: LongConstant [12]\n", "  8: LongConstant\n" },
     { "  12: Add(6, 8) [15]\n",   "  19: LongConstant [15]\n" },
     { "  15: Return(12)\n",       "  15: Return(19)\n" }
   };
-  std::string expected_after_cp = Patch(expected_before, expected_cp_diff);
+  std::string expected_after_cf = Patch(expected_before, expected_cf_diff);
 
   // Check the value of the computed constant.
-  auto check_after_cp = [](HGraph* graph) {
+  auto check_after_cf = [](HGraph* graph) {
     HInstruction* inst = graph->GetBlock(1)->GetFirstInstruction();
     ASSERT_TRUE(inst->IsLongConstant());
     ASSERT_EQ(inst->AsLongConstant()->GetValue(), 3);
@@ -329,13 +333,13 @@
     { "  6: LongConstant\n", removed },
     { "  8: LongConstant\n", removed }
   };
-  std::string expected_after_dce = Patch(expected_after_cp, expected_dce_diff);
+  std::string expected_after_dce = Patch(expected_after_cf, expected_dce_diff);
 
   TestCode(data,
            expected_before,
-           expected_after_cp,
+           expected_after_cf,
            expected_after_dce,
-           check_after_cp,
+           check_after_cf,
            Primitive::kPrimLong);
 }
 
@@ -352,7 +356,7 @@
  *       (v0, v1) - (v1, v2)    4.      sub-long v4, v0, v2
  *     return (v4, v5)          6.      return-wide v4
  */
-TEST(ConstantPropagation, LongConstantFoldingOnSubtraction) {
+TEST(ConstantFolding, LongConstantFoldingOnSubtraction) {
   const uint16_t data[] = SIX_REGISTERS_CODE_ITEM(
     Instruction::CONST_WIDE_16 | 0 << 8, 3,
     Instruction::CONST_WIDE_16 | 2 << 8, 2,
@@ -371,17 +375,17 @@
     "BasicBlock 2, pred: 1\n"
     "  16: Exit\n";
 
-  // Expected difference after constant propagation.
-  diff_t expected_cp_diff = {
+  // Expected difference after constant folding.
+  diff_t expected_cf_diff = {
     { "  6: LongConstant [12]\n", "  6: LongConstant\n" },
     { "  8: LongConstant [12]\n", "  8: LongConstant\n" },
     { "  12: Sub(6, 8) [15]\n",   "  19: LongConstant [15]\n" },
     { "  15: Return(12)\n",       "  15: Return(19)\n" }
   };
-  std::string expected_after_cp = Patch(expected_before, expected_cp_diff);
+  std::string expected_after_cf = Patch(expected_before, expected_cf_diff);
 
   // Check the value of the computed constant.
-  auto check_after_cp = [](HGraph* graph) {
+  auto check_after_cf = [](HGraph* graph) {
     HInstruction* inst = graph->GetBlock(1)->GetFirstInstruction();
     ASSERT_TRUE(inst->IsLongConstant());
     ASSERT_EQ(inst->AsLongConstant()->GetValue(), 1);
@@ -392,13 +396,13 @@
     { "  6: LongConstant\n", removed },
     { "  8: LongConstant\n", removed }
   };
-  std::string expected_after_dce = Patch(expected_after_cp, expected_dce_diff);
+  std::string expected_after_dce = Patch(expected_after_cf, expected_dce_diff);
 
   TestCode(data,
            expected_before,
-           expected_after_cp,
+           expected_after_cf,
            expected_after_dce,
-           check_after_cp,
+           check_after_cf,
            Primitive::kPrimLong);
 }
 
@@ -424,7 +428,7 @@
  * L3: v2 <- v1 + 4             11.     add-int/lit16 v2, v1, #+4
  *     return v2                13.     return v2
  */
-TEST(ConstantPropagation, IntConstantFoldingAndJumps) {
+TEST(ConstantFolding, IntConstantFoldingAndJumps) {
   const uint16_t data[] = THREE_REGISTERS_CODE_ITEM(
     Instruction::CONST_4 | 0 << 8 | 0 << 12,
     Instruction::CONST_4 | 1 << 8 | 1 << 12,
@@ -462,8 +466,8 @@
     "BasicBlock 5, pred: 4\n"
     "  29: Exit\n";
 
-  // Expected difference after constant propagation.
-  diff_t expected_cp_diff = {
+  // Expected difference after constant folding.
+  diff_t expected_cf_diff = {
     { "  3: IntConstant [9]\n",   "  3: IntConstant\n" },
     { "  5: IntConstant [9]\n",   "  5: IntConstant []\n" },
     { "  13: IntConstant [14]\n", "  13: IntConstant\n" },
@@ -475,10 +479,10 @@
     { "  25: Add(14, 24) [28]\n", "  35: IntConstant [28]\n" },
     { "  28: Return(25)\n",       "  28: Return(35)\n"}
   };
-  std::string expected_after_cp = Patch(expected_before, expected_cp_diff);
+  std::string expected_after_cf = Patch(expected_before, expected_cf_diff);
 
   // Check the values of the computed constants.
-  auto check_after_cp = [](HGraph* graph) {
+  auto check_after_cf = [](HGraph* graph) {
     HInstruction* inst1 = graph->GetBlock(1)->GetFirstInstruction();
     ASSERT_TRUE(inst1->IsIntConstant());
     ASSERT_EQ(inst1->AsIntConstant()->GetValue(), 1);
@@ -501,13 +505,13 @@
     { "  24: IntConstant\n",    removed },
     { "  34: IntConstant\n",    removed },
   };
-  std::string expected_after_dce = Patch(expected_after_cp, expected_dce_diff);
+  std::string expected_after_dce = Patch(expected_after_cf, expected_dce_diff);
 
   TestCode(data,
            expected_before,
-           expected_after_cp,
+           expected_after_cf,
            expected_after_dce,
-           check_after_cp);
+           check_after_cf);
 }
 
 
@@ -524,7 +528,7 @@
  * L1: v2 <- v0 + v1            5.      add-int v2, v0, v1
  *     return-void              7.      return
  */
-TEST(ConstantPropagation, ConstantCondition) {
+TEST(ConstantFolding, ConstantCondition) {
   const uint16_t data[] = THREE_REGISTERS_CODE_ITEM(
     Instruction::CONST_4 | 1 << 8 | 1 << 12,
     Instruction::CONST_4 | 0 << 8 | 0 << 12,
@@ -553,17 +557,17 @@
     "BasicBlock 5, pred: 1, succ: 3\n"
     "  21: Goto 3\n";
 
-  // Expected difference after constant propagation.
-  diff_t expected_cp_diff = {
+  // Expected difference after constant folding.
+  diff_t expected_cf_diff = {
     { "  3: IntConstant [15, 22, 8]\n",      "  3: IntConstant [15, 22]\n" },
     { "  5: IntConstant [22, 8]\n",          "  5: IntConstant [22]\n" },
     { "  8: GreaterThanOrEqual(3, 5) [9]\n", "  23: IntConstant [9]\n" },
     { "  9: If(8)\n",                        "  9: If(23)\n" }
   };
-  std::string expected_after_cp = Patch(expected_before, expected_cp_diff);
+  std::string expected_after_cf = Patch(expected_before, expected_cf_diff);
 
   // Check the values of the computed constants.
-  auto check_after_cp = [](HGraph* graph) {
+  auto check_after_cf = [](HGraph* graph) {
     HInstruction* inst = graph->GetBlock(1)->GetFirstInstruction();
     ASSERT_TRUE(inst->IsIntConstant());
     ASSERT_EQ(inst->AsIntConstant()->GetValue(), 1);
@@ -575,13 +579,13 @@
     { "  22: Phi(3, 5) [15]\n",      "  22: Phi(3, 5)\n" },
     { "  15: Add(22, 3)\n",          removed }
   };
-  std::string expected_after_dce = Patch(expected_after_cp, expected_dce_diff);
+  std::string expected_after_dce = Patch(expected_after_cf, expected_dce_diff);
 
   TestCode(data,
            expected_before,
-           expected_after_cp,
+           expected_after_cf,
            expected_after_dce,
-           check_after_cp);
+           check_after_cf);
 }
 
 }  // namespace art
diff --git a/compiler/optimizing/constant_propagation.h b/compiler/optimizing/constant_propagation.h
deleted file mode 100644
index 0729881..0000000
--- a/compiler/optimizing/constant_propagation.h
+++ /dev/null
@@ -1,43 +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.
- */
-
-#ifndef ART_COMPILER_OPTIMIZING_CONSTANT_PROPAGATION_H_
-#define ART_COMPILER_OPTIMIZING_CONSTANT_PROPAGATION_H_
-
-#include "nodes.h"
-
-namespace art {
-
-/**
- * Optimization pass performing a simple constant propagation on the
- * SSA form.
- */
-class ConstantPropagation : public ValueObject {
- public:
-  explicit ConstantPropagation(HGraph* graph)
-    : graph_(graph) {}
-
-  void Run();
-
- private:
-  HGraph* const graph_;
-
-  DISALLOW_COPY_AND_ASSIGN(ConstantPropagation);
-};
-
-}  // namespace art
-
-#endif  // ART_COMPILER_OPTIMIZING_CONSTANT_PROPAGATION_H_
diff --git a/compiler/optimizing/dead_code_elimination.cc b/compiler/optimizing/dead_code_elimination.cc
index 5655544..fc3dd01 100644
--- a/compiler/optimizing/dead_code_elimination.cc
+++ b/compiler/optimizing/dead_code_elimination.cc
@@ -20,7 +20,7 @@
 
 namespace art {
 
-void DeadCodeElimination::Run() {
+void HDeadCodeElimination::Run() {
   // Process basic blocks in post-order in the dominator tree, so that
   // a dead instruction depending on another dead instruction is
   // removed.
diff --git a/compiler/optimizing/dead_code_elimination.h b/compiler/optimizing/dead_code_elimination.h
index 48739be..a4446ae 100644
--- a/compiler/optimizing/dead_code_elimination.h
+++ b/compiler/optimizing/dead_code_elimination.h
@@ -18,6 +18,7 @@
 #define ART_COMPILER_OPTIMIZING_DEAD_CODE_ELIMINATION_H_
 
 #include "nodes.h"
+#include "optimization.h"
 
 namespace art {
 
@@ -25,17 +26,18 @@
  * Optimization pass performing dead code elimination (removal of
  * unused variables/instructions) on the SSA form.
  */
-class DeadCodeElimination : public ValueObject {
+class HDeadCodeElimination : public HOptimization {
  public:
-  explicit DeadCodeElimination(HGraph* graph)
-      : graph_(graph) {}
+  HDeadCodeElimination(HGraph* graph, const HGraphVisualizer& visualizer)
+      : HOptimization(graph, true, kDeadCodeEliminationPassName, visualizer) {}
 
-  void Run();
+  virtual void Run() OVERRIDE;
+
+  static constexpr const char* kDeadCodeEliminationPassName =
+    "dead_code_elimination";
 
  private:
-  HGraph* const graph_;
-
-  DISALLOW_COPY_AND_ASSIGN(DeadCodeElimination);
+  DISALLOW_COPY_AND_ASSIGN(HDeadCodeElimination);
 };
 
 }  // namespace art
diff --git a/compiler/optimizing/dead_code_elimination_test.cc b/compiler/optimizing/dead_code_elimination_test.cc
index 3e0ba3a..0c68074 100644
--- a/compiler/optimizing/dead_code_elimination_test.cc
+++ b/compiler/optimizing/dead_code_elimination_test.cc
@@ -14,10 +14,11 @@
  * limitations under the License.
  */
 
+#include "code_generator_x86.h"
 #include "dead_code_elimination.h"
-#include "pretty_printer.h"
 #include "graph_checker.h"
 #include "optimizing_unit_test.h"
+#include "pretty_printer.h"
 
 #include "gtest/gtest.h"
 
@@ -39,16 +40,17 @@
   std::string actual_before = printer_before.str();
   ASSERT_EQ(actual_before, expected_before);
 
-  DeadCodeElimination(graph).Run();
+  x86::CodeGeneratorX86 codegen(graph);
+  HGraphVisualizer visualizer(nullptr, graph, codegen, "");
+  HDeadCodeElimination(graph, visualizer).Run();
+  SSAChecker ssa_checker(&allocator, graph);
+  ssa_checker.Run();
+  ASSERT_TRUE(ssa_checker.IsValid());
 
   StringPrettyPrinter printer_after(graph);
   printer_after.VisitInsertionOrder();
   std::string actual_after = printer_after.str();
   ASSERT_EQ(actual_after, expected_after);
-
-  SSAChecker ssa_checker(&allocator, graph);
-  ssa_checker.Run();
-  ASSERT_TRUE(ssa_checker.IsValid());
 }
 
 
@@ -94,6 +96,7 @@
     "BasicBlock 5, pred: 1, succ: 3\n"
     "  21: Goto 3\n";
 
+  // Expected difference after dead code elimination.
   diff_t expected_diff = {
     { "  3: IntConstant [15, 22, 8]\n", "  3: IntConstant [22, 8]\n" },
     { "  22: Phi(3, 5) [15]\n",         "  22: Phi(3, 5)\n" },
@@ -164,7 +167,7 @@
     "BasicBlock 5, pred: 4\n"
     "  28: Exit\n";
 
-  // Expected difference after constant propagation.
+  // Expected difference after dead code elimination.
   diff_t expected_diff = {
     { "  13: IntConstant [14]\n", removed },
     { "  24: IntConstant [25]\n", removed },
diff --git a/compiler/optimizing/graph_checker.h b/compiler/optimizing/graph_checker.h
index 862f1b6..db31306 100644
--- a/compiler/optimizing/graph_checker.h
+++ b/compiler/optimizing/graph_checker.h
@@ -19,15 +19,19 @@
 
 #include "nodes.h"
 
+#include <ostream>
+
 namespace art {
 
 // A control-flow graph visitor performing various checks.
 class GraphChecker : public HGraphVisitor {
  public:
-  GraphChecker(ArenaAllocator* allocator, HGraph* graph)
+  GraphChecker(ArenaAllocator* allocator, HGraph* graph,
+               const char* dump_prefix = "art::GraphChecker: ")
     : HGraphVisitor(graph),
       allocator_(allocator),
-      errors_(allocator, 0) {}
+      errors_(allocator, 0),
+      dump_prefix_(dump_prefix) {}
 
   // Check the whole graph (in insertion order).
   virtual void Run() { VisitInsertionOrder(); }
@@ -48,6 +52,13 @@
     return errors_;
   }
 
+  // Print detected errors on output stream `os`.
+  void Dump(std::ostream& os) {
+    for (size_t i = 0, e = errors_.Size(); i < e; ++i) {
+      os << dump_prefix_ << errors_.Get(i) << std::endl;
+    }
+  }
+
  protected:
   ArenaAllocator* const allocator_;
   // The block currently visited.
@@ -56,6 +67,9 @@
   GrowableArray<std::string> errors_;
 
  private:
+  // String displayed before dumped errors.
+  const char* dump_prefix_;
+
   DISALLOW_COPY_AND_ASSIGN(GraphChecker);
 };
 
@@ -66,7 +80,7 @@
   typedef GraphChecker super_type;
 
   SSAChecker(ArenaAllocator* allocator, HGraph* graph)
-    : GraphChecker(allocator, graph) {}
+    : GraphChecker(allocator, graph, "art::SSAChecker: ") {}
 
   // Check the whole graph (in reverse post-order).
   virtual void Run() {
diff --git a/compiler/optimizing/graph_visualizer.cc b/compiler/optimizing/graph_visualizer.cc
index b4eb89d..459010d 100644
--- a/compiler/optimizing/graph_visualizer.cc
+++ b/compiler/optimizing/graph_visualizer.cc
@@ -309,7 +309,7 @@
   printer.EndTag("compilation");
 }
 
-void HGraphVisualizer::DumpGraph(const char* pass_name) {
+void HGraphVisualizer::DumpGraph(const char* pass_name) const {
   if (!is_enabled_) {
     return;
   }
diff --git a/compiler/optimizing/graph_visualizer.h b/compiler/optimizing/graph_visualizer.h
index f17ba3b..05984a0 100644
--- a/compiler/optimizing/graph_visualizer.h
+++ b/compiler/optimizing/graph_visualizer.h
@@ -61,7 +61,7 @@
    * If this visualizer is enabled, emit the compilation information
    * in `output_`.
    */
-  void DumpGraph(const char* pass_name);
+  void DumpGraph(const char* pass_name) const;
 
  private:
   std::ostream* const output_;
diff --git a/compiler/optimizing/optimization.cc b/compiler/optimizing/optimization.cc
new file mode 100644
index 0000000..33dc040
--- /dev/null
+++ b/compiler/optimizing/optimization.cc
@@ -0,0 +1,47 @@
+/*
+ * 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 "optimization.h"
+
+#include "graph_checker.h"
+
+namespace art {
+
+void HOptimization::Execute() {
+  Run();
+  visualizer_.DumpGraph(pass_name_);
+  Check();
+}
+
+void HOptimization::Check() {
+  if (kIsDebugBuild) {
+    if (is_in_ssa_form_) {
+      SSAChecker checker(graph_->GetArena(), graph_);
+      checker.Run();
+      if (!checker.IsValid()) {
+        LOG(FATAL) << Dumpable<SSAChecker>(checker);
+      }
+    } else {
+      GraphChecker checker(graph_->GetArena(), graph_);
+      checker.Run();
+      if (!checker.IsValid()) {
+        LOG(FATAL) << Dumpable<GraphChecker>(checker);
+      }
+    }
+  }
+}
+
+}  // namespace art
diff --git a/compiler/optimizing/optimization.h b/compiler/optimizing/optimization.h
new file mode 100644
index 0000000..59683e2
--- /dev/null
+++ b/compiler/optimizing/optimization.h
@@ -0,0 +1,71 @@
+/*
+ * 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_OPTIMIZING_OPTIMIZATION_H_
+#define ART_COMPILER_OPTIMIZING_OPTIMIZATION_H_
+
+#include "graph_visualizer.h"
+#include "nodes.h"
+
+namespace art {
+
+/**
+ * Abstraction to implement an optimization pass.
+ */
+class HOptimization : public ValueObject {
+ public:
+  HOptimization(HGraph* graph,
+                bool is_in_ssa_form,
+                const char* pass_name,
+                const HGraphVisualizer& visualizer)
+      : graph_(graph),
+        is_in_ssa_form_(is_in_ssa_form),
+        pass_name_(pass_name),
+        visualizer_(visualizer) {}
+
+  virtual ~HOptimization() {}
+
+  // Execute the optimization pass.
+  void Execute();
+
+  // Return the name of the pass.
+  const char* GetPassName() const { return pass_name_; }
+
+  // Peform the analysis itself.
+  virtual void Run() = 0;
+
+ private:
+  // Verify the graph; abort if it is not valid.
+  void Check();
+
+ protected:
+  HGraph* const graph_;
+
+ private:
+  // Does the analyzed graph use the SSA form?
+  const bool is_in_ssa_form_;
+  // Optimization pass name.
+  const char* pass_name_;
+  // A graph visualiser invoked after the execution of the optimization
+  // pass if enabled.
+  const HGraphVisualizer& visualizer_;
+
+  DISALLOW_COPY_AND_ASSIGN(HOptimization);
+};
+
+}  // namespace art
+
+#endif  // ART_COMPILER_OPTIMIZING_OPTIMIZATION_H_
diff --git a/compiler/optimizing/optimizing_compiler.cc b/compiler/optimizing/optimizing_compiler.cc
index 3cf5a0b..dce8e6d 100644
--- a/compiler/optimizing/optimizing_compiler.cc
+++ b/compiler/optimizing/optimizing_compiler.cc
@@ -22,6 +22,8 @@
 #include "builder.h"
 #include "code_generator.h"
 #include "compiler.h"
+#include "constant_folding.h"
+#include "dead_code_elimination.h"
 #include "driver/compiler_driver.h"
 #include "driver/dex_compilation_unit.h"
 #include "graph_visualizer.h"
@@ -261,6 +263,9 @@
     visualizer.DumpGraph("ssa");
     graph->FindNaturalLoops();
 
+    HDeadCodeElimination(graph, visualizer).Execute();
+    HConstantFolding(graph, visualizer).Execute();
+
     SsaRedundantPhiElimination(graph).Run();
     SsaDeadPhiElimination(graph).Run();
     InstructionSimplifier(graph).Run();