Inlining support in optimizing.

Currently only inlines simple things that don't require an
environment, such as:
- Returning a constant.
- Returning a parameter.
- Returning an arithmetic operation.

Change-Id: Ie844950cb44f69e104774a3cf7a8dea66bc85661
diff --git a/compiler/optimizing/optimizing_compiler.cc b/compiler/optimizing/optimizing_compiler.cc
index d47217f..deebaf7 100644
--- a/compiler/optimizing/optimizing_compiler.cc
+++ b/compiler/optimizing/optimizing_compiler.cc
@@ -30,6 +30,7 @@
 #include "elf_writer_quick.h"
 #include "graph_visualizer.h"
 #include "gvn.h"
+#include "inliner.h"
 #include "instruction_simplifier.h"
 #include "jni/quick/jni_compiler.h"
 #include "mirror/art_method-inl.h"
@@ -181,25 +182,33 @@
   return code_item.tries_size_ == 0;
 }
 
-static void RunOptimizations(HGraph* graph, const HGraphVisualizer& visualizer) {
-  HDeadCodeElimination opt1(graph);
-  HConstantFolding opt2(graph);
-  SsaRedundantPhiElimination opt3(graph);
-  SsaDeadPhiElimination opt4(graph);
-  InstructionSimplifier opt5(graph);
-  GVNOptimization opt6(graph);
+static void RunOptimizations(HGraph* graph,
+                             CompilerDriver* driver,
+                             OptimizingCompilerStats* stats,
+                             const DexCompilationUnit& dex_compilation_unit,
+                             const HGraphVisualizer& visualizer) {
+  SsaRedundantPhiElimination redundant_phi(graph);
+  SsaDeadPhiElimination dead_phi(graph);
+  HDeadCodeElimination dce(graph);
+  HConstantFolding fold(graph);
+  InstructionSimplifier simplify1(graph);
+
+  HInliner inliner(graph, dex_compilation_unit, driver, stats);
+
+  GVNOptimization gvn(graph);
   BoundsCheckElimination bce(graph);
-  InstructionSimplifier opt8(graph);
+  InstructionSimplifier simplify2(graph);
 
   HOptimization* optimizations[] = {
-    &opt1,
-    &opt2,
-    &opt3,
-    &opt4,
-    &opt5,
-    &opt6,
+    &redundant_phi,
+    &dead_phi,
+    &dce,
+    &fold,
+    &simplify1,
+    &inliner,
+    &gvn,
     &bce,
-    &opt8
+    &simplify2
   };
 
   for (size_t i = 0; i < arraysize(optimizations); ++i) {
@@ -210,23 +219,6 @@
   }
 }
 
-static bool TryBuildingSsa(HGraph* graph,
-                           const DexCompilationUnit& dex_compilation_unit,
-                           const HGraphVisualizer& visualizer) {
-  graph->BuildDominatorTree();
-  graph->TransformToSSA();
-
-  if (!graph->AnalyzeNaturalLoops()) {
-    LOG(INFO) << "Skipping compilation of "
-              << PrettyMethod(dex_compilation_unit.GetDexMethodIndex(),
-                              *dex_compilation_unit.GetDexFile())
-              << ": it contains a non natural loop";
-    return false;
-  }
-  visualizer.DumpGraph("ssa transform");
-  return true;
-}
-
 // The stack map we generate must be 4-byte aligned on ARM. Since existing
 // maps are generated alongside these stack maps, we must also align them.
 static std::vector<uint8_t>& AlignVectorSize(std::vector<uint8_t>& vector) {
@@ -270,19 +262,23 @@
     class_def_idx, method_idx, access_flags,
     GetCompilerDriver()->GetVerifiedMethod(&dex_file, method_idx));
 
+  std::string method_name = PrettyMethod(method_idx, dex_file);
+
   // For testing purposes, we put a special marker on method names that should be compiled
   // with this compiler. This makes sure we're not regressing.
-  bool shouldCompile = dex_compilation_unit.GetSymbol().find("00024opt_00024") != std::string::npos;
-  bool shouldOptimize =
-      dex_compilation_unit.GetSymbol().find("00024reg_00024") != std::string::npos;
+  bool shouldCompile = method_name.find("$opt$") != std::string::npos;
+  bool shouldOptimize = method_name.find("$opt$reg$") != std::string::npos;
 
   ArenaPool pool;
   ArenaAllocator arena(&pool);
   HGraphBuilder builder(&arena,
                         &dex_compilation_unit,
-                        &dex_file, GetCompilerDriver(),
+                        &dex_compilation_unit,
+                        &dex_file,
+                        GetCompilerDriver(),
                         &compilation_stats_);
 
+  VLOG(compiler) << "Building " << PrettyMethod(method_idx, dex_file);
   HGraph* graph = builder.BuildGraph(*code_item);
   if (graph == nullptr) {
     CHECK(!shouldCompile) << "Could not build graph in optimizing compiler";
@@ -297,7 +293,7 @@
   }
 
   HGraphVisualizer visualizer(
-      visualizer_output_.get(), graph, kStringFilter, *codegen, dex_compilation_unit);
+      visualizer_output_.get(), graph, kStringFilter, *codegen, method_name.c_str());
   visualizer.DumpGraph("builder");
 
   CodeVectorAllocator allocator;
@@ -306,12 +302,16 @@
   bool can_allocate_registers = RegisterAllocator::CanAllocateRegistersFor(*graph, instruction_set);
   if (run_optimizations_ && can_optimize && can_allocate_registers) {
     VLOG(compiler) << "Optimizing " << PrettyMethod(method_idx, dex_file);
-    if (!TryBuildingSsa(graph, dex_compilation_unit, visualizer)) {
+    if (!graph->TryBuildingSsa()) {
+      LOG(INFO) << "Skipping compilation of "
+                << PrettyMethod(method_idx, dex_file)
+                << ": it contains a non natural loop";
       // We could not transform the graph to SSA, bailout.
       compilation_stats_.RecordStat(MethodCompilationStat::kNotCompiledCannotBuildSSA);
       return nullptr;
     }
-    RunOptimizations(graph, visualizer);
+    RunOptimizations(
+        graph, GetCompilerDriver(), &compilation_stats_, dex_compilation_unit, visualizer);
 
     PrepareForRegisterAllocation(graph).Run();
     SsaLivenessAnalysis liveness(*graph, codegen);