Properly scope HLoopOptimization's allocator.

HOptimization classes do not get their destructor called,
as they are arena objects. So the scope for the optimization
allocator needs to be the Run method.

Also anticipate bisection search breakage by adding
HLoopOptimization to the list of recognized optimizations.

Change-Id: I7770989c39d5700a3b6b0a20af5d4b874dfde111
diff --git a/compiler/optimizing/loop_optimization.cc b/compiler/optimizing/loop_optimization.cc
index 7dfa4f1..383a027 100644
--- a/compiler/optimizing/loop_optimization.cc
+++ b/compiler/optimizing/loop_optimization.cc
@@ -128,7 +128,7 @@
                                      HInductionVarAnalysis* induction_analysis)
     : HOptimization(graph, kLoopOptimizationPassName),
       induction_range_(induction_analysis),
-      loop_allocator_(graph_->GetArena()->GetArenaPool()),  // phase-local allocator on global pool
+      loop_allocator_(nullptr),
       top_loop_(nullptr),
       last_loop_(nullptr) {
 }
@@ -140,6 +140,9 @@
     return;
   }
 
+  ArenaAllocator allocator(graph_->GetArena()->GetArenaPool());
+  loop_allocator_ = &allocator;
+
   // Build the linear order. This step enables building a loop hierarchy that
   // properly reflects the outer-inner and previous-next relation.
   graph_->Linearize();
@@ -150,16 +153,16 @@
       AddLoop(block->GetLoopInformation());
     }
   }
-  if (top_loop_ == nullptr) {
-    return;  // no loops
+  if (top_loop_ != nullptr) {
+    // Traverse the loop hierarchy inner-to-outer and optimize.
+    TraverseLoopsInnerToOuter(top_loop_);
   }
-  // Traverse the loop hierarchy inner-to-outer and optimize.
-  TraverseLoopsInnerToOuter(top_loop_);
+  loop_allocator_ = nullptr;
 }
 
 void HLoopOptimization::AddLoop(HLoopInformation* loop_info) {
   DCHECK(loop_info != nullptr);
-  LoopNode* node = new (&loop_allocator_) LoopNode(loop_info);  // phase-local allocator
+  LoopNode* node = new (loop_allocator_) LoopNode(loop_info);  // phase-local allocator
   if (last_loop_ == nullptr) {
     // First loop.
     DCHECK(top_loop_ == nullptr);
diff --git a/compiler/optimizing/loop_optimization.h b/compiler/optimizing/loop_optimization.h
index e7980ce..d12fe5e 100644
--- a/compiler/optimizing/loop_optimization.h
+++ b/compiler/optimizing/loop_optimization.h
@@ -72,7 +72,7 @@
 
   // Phase-local heap memory allocator for the loop optimizer. Storage obtained
   // through this allocator is released when the loop optimizer is done.
-  ArenaAllocator loop_allocator_;
+  ArenaAllocator* loop_allocator_;
 
   // Entries into the loop hierarchy representation.
   LoopNode* top_loop_;
diff --git a/compiler/optimizing/optimizing_compiler.cc b/compiler/optimizing/optimizing_compiler.cc
index c2fe1b1..52d6e0b 100644
--- a/compiler/optimizing/optimizing_compiler.cc
+++ b/compiler/optimizing/optimizing_compiler.cc
@@ -488,6 +488,8 @@
     return new (arena) LoadStoreElimination(graph, *most_recent_side_effects);
   } else if (opt_name == SideEffectsAnalysis::kSideEffectsAnalysisPassName) {
     return new (arena) SideEffectsAnalysis(graph);
+  } else if (opt_name == HLoopOptimization::kLoopOptimizationPassName) {
+    return new (arena) HLoopOptimization(graph, most_recent_induction);
 #ifdef ART_ENABLE_CODEGEN_arm
   } else if (opt_name == arm::DexCacheArrayFixups::kDexCacheArrayFixupsArmPassName) {
     return new (arena) arm::DexCacheArrayFixups(graph, codegen, stats);