ART: Preserve loop headers with try/catch

Algorithm for inserting HTryBoundary instructions would generate a
non-natural loop when a loop header block was covered by a TryItem.
This patch changes the approach to fix the issue.

Bug: 23895756
Change-Id: I0e1ee6cf135cea326a96c97954907d202c9793cc
diff --git a/compiler/optimizing/nodes.cc b/compiler/optimizing/nodes.cc
index 1ca9907..ef89932 100644
--- a/compiler/optimizing/nodes.cc
+++ b/compiler/optimizing/nodes.cc
@@ -1170,6 +1170,23 @@
   return new_block;
 }
 
+HBasicBlock* HBasicBlock::CreateImmediateDominator() {
+  DCHECK(!graph_->IsInSsaForm()) << "Support for SSA form not implemented";
+  DCHECK(!IsCatchBlock()) << "Support for updating try/catch information not implemented.";
+
+  HBasicBlock* new_block = new (GetGraph()->GetArena()) HBasicBlock(GetGraph(), GetDexPc());
+
+  for (HBasicBlock* predecessor : GetPredecessors()) {
+    new_block->predecessors_.push_back(predecessor);
+    predecessor->successors_[predecessor->GetSuccessorIndexOf(this)] = new_block;
+  }
+  predecessors_.clear();
+  AddPredecessor(new_block);
+
+  GetGraph()->AddBlock(new_block);
+  return new_block;
+}
+
 HBasicBlock* HBasicBlock::SplitAfter(HInstruction* cursor) {
   DCHECK(!cursor->IsControlFlow());
   DCHECK_NE(instructions_.last_instruction_, cursor);
@@ -1215,6 +1232,15 @@
   }
 }
 
+bool HBasicBlock::HasThrowingInstructions() const {
+  for (HInstructionIterator it(GetInstructions()); !it.Done(); it.Advance()) {
+    if (it.Current()->CanThrow()) {
+      return true;
+    }
+  }
+  return false;
+}
+
 static bool HasOnlyOneInstruction(const HBasicBlock& block) {
   return block.GetPhis().IsEmpty()
       && !block.GetInstructions().IsEmpty()