ART: Enable more passes under try/catch

LICM, BCE, LSE are all safe under try/catch. Inliner and DCE
need updating and will be enabled in follow-up CLs.

Change-Id: I86db5f811257d5e765fea91666a2a2af0fb24ec3
diff --git a/compiler/optimizing/licm.cc b/compiler/optimizing/licm.cc
index c38bbe3..27442d4 100644
--- a/compiler/optimizing/licm.cc
+++ b/compiler/optimizing/licm.cc
@@ -122,6 +122,9 @@
           if (instruction->NeedsEnvironment()) {
             UpdateLoopPhisIn(instruction->GetEnvironment(), loop_info);
           }
+          // Move instruction into the pre header. Note that this cannot move
+          // a throwing instruction out of its try block since these are hoisted
+          // only from the header block (and TryBoundary would start a new block).
           instruction->MoveBefore(pre_header->GetLastInstruction());
         } else if (instruction->CanThrow()) {
           // If `instruction` can throw, we cannot move further instructions
diff --git a/compiler/optimizing/nodes.cc b/compiler/optimizing/nodes.cc
index 3480265..4345d55 100644
--- a/compiler/optimizing/nodes.cc
+++ b/compiler/optimizing/nodes.cc
@@ -1129,6 +1129,14 @@
 }
 
 void HInstruction::MoveBefore(HInstruction* cursor) {
+  if (kIsDebugBuild && CanThrowIntoCatchBlock()) {
+    // Make sure we are not moving a throwing instruction out of its try block.
+    DCHECK(cursor->GetBlock()->IsTryBlock());
+    const HTryBoundary& current_try = block_->GetTryCatchInformation()->GetTryEntry();
+    const HTryBoundary& cursor_try = cursor->GetBlock()->GetTryCatchInformation()->GetTryEntry();
+    DCHECK(cursor_try.HasSameExceptionHandlersAs(current_try));
+  }
+
   next_->previous_ = previous_;
   if (previous_ != nullptr) {
     previous_->next_ = next_;
diff --git a/compiler/optimizing/optimizing_compiler.cc b/compiler/optimizing/optimizing_compiler.cc
index 6632f95..98acc34 100644
--- a/compiler/optimizing/optimizing_compiler.cc
+++ b/compiler/optimizing/optimizing_compiler.cc
@@ -494,43 +494,31 @@
 
   // TODO: Update passes incompatible with try/catch so we have the same
   //       pipeline for all methods.
-  if (graph->HasTryCatch()) {
-    HOptimization* optimizations2[] = {
-      side_effects,
-      gvn,
-      dce2,
-      // The codegen has a few assumptions that only the instruction simplifier
-      // can satisfy. For example, the code generator does not expect to see a
-      // HTypeConversion from a type to the same type.
-      simplify4,
-    };
-
-    RunOptimizations(optimizations2, arraysize(optimizations2), pass_observer);
-  } else {
+  if (!graph->HasTryCatch()) {
     MaybeRunInliner(graph, codegen, driver, stats, dex_compilation_unit, pass_observer, handles);
-
-    HOptimization* optimizations2[] = {
-      // BooleanSimplifier depends on the InstructionSimplifier removing
-      // redundant suspend checks to recognize empty blocks.
-      boolean_simplify,
-      fold2,  // TODO: if we don't inline we can also skip fold2.
-      side_effects,
-      gvn,
-      licm,
-      induction,
-      bce,
-      simplify3,
-      lse,
-      dce2,
-      // The codegen has a few assumptions that only the instruction simplifier
-      // can satisfy. For example, the code generator does not expect to see a
-      // HTypeConversion from a type to the same type.
-      simplify4,
-    };
-
-    RunOptimizations(optimizations2, arraysize(optimizations2), pass_observer);
   }
 
+  HOptimization* optimizations2[] = {
+    // BooleanSimplifier depends on the InstructionSimplifier removing
+    // redundant suspend checks to recognize empty blocks.
+    boolean_simplify,
+    fold2,  // TODO: if we don't inline we can also skip fold2.
+    side_effects,
+    gvn,
+    licm,
+    induction,
+    bce,
+    simplify3,
+    lse,
+    dce2,
+    // The codegen has a few assumptions that only the instruction simplifier
+    // can satisfy. For example, the code generator does not expect to see a
+    // HTypeConversion from a type to the same type.
+    simplify4,
+  };
+
+  RunOptimizations(optimizations2, arraysize(optimizations2), pass_observer);
+
   RunArchOptimizations(driver->GetInstructionSet(), graph, stats, pass_observer);
 }