ART: Implement scalar loop peeling.

Implement scalar loop peeling for invariant exits elimination
(on arm64). If the loop exit condition is loop invariant then
loop peeling + GVN + DCE can eliminate this exit in the loop
body. Note: GVN and DCE aren't applied during loop optimizations.

Note: this functionality is turned off by default now.

Test: test-art-host, test-art-target, boot-to-gui.

Change-Id: I98d20054a431838b452dc06bd25c075eb445960c
diff --git a/compiler/optimizing/superblock_cloner.cc b/compiler/optimizing/superblock_cloner.cc
index ee74f10..fad7729 100644
--- a/compiler/optimizing/superblock_cloner.cc
+++ b/compiler/optimizing/superblock_cloner.cc
@@ -28,11 +28,6 @@
 using HBasicBlockSet = SuperblockCloner::HBasicBlockSet;
 using HEdgeSet = SuperblockCloner::HEdgeSet;
 
-// When doing peeling we can choose whether to keep original loop (made of original basic blocks)
-// and form a peeled iteration of the copy blocks (preserve the header) or transfer original loop
-// blocks to the peeled iteration and create new loop from the copy blocks. Similar for unrolling.
-static const bool kPeelUnrollPreserveHeader = true;
-
 void HEdge::Dump(std::ostream& stream) const {
   stream << "(" << from_ << "->" << to_ << ")";
 }
@@ -926,16 +921,12 @@
       remap_orig_internal->Insert(e);
       remap_copy_internal->Insert(e);
     } else {
-      if (kPeelUnrollPreserveHeader) {
-        remap_copy_internal->Insert(e);
-      } else {
-        remap_orig_internal->Insert(e);
-      }
+      remap_copy_internal->Insert(e);
     }
   }
 
   // Set up remap_incoming edges set.
-  if (to_unroll != kPeelUnrollPreserveHeader) {
+  if (!to_unroll) {
     remap_incoming->Insert(HEdge(loop_info->GetPreHeader(), loop_header));
   }
 }
@@ -992,6 +983,9 @@
   DCHECK(!loop_info_->IsIrreducible());
 
   HBasicBlock* loop_header = loop_info_->GetHeader();
+  // Check that loop info is up-to-date.
+  DCHECK(loop_info_ == loop_header->GetLoopInformation());
+
   HGraph* graph = loop_header->GetGraph();
   ArenaAllocator allocator(graph->GetAllocator()->GetArenaPool());
 
@@ -1009,7 +1003,10 @@
   cloner_.Run();
   cloner_.CleanUp();
 
-  return kPeelUnrollPreserveHeader ? loop_header : cloner_.GetBlockCopy(loop_header);
+  // Check that loop info is preserved.
+  DCHECK(loop_info_ == loop_header->GetLoopInformation());
+
+  return loop_header;
 }
 
 PeelUnrollSimpleHelper::PeelUnrollSimpleHelper(HLoopInformation* info)