OSDN Git Service

ART: Enable more passes under try/catch
authorDavid Brazdil <dbrazdil@google.com>
Mon, 26 Oct 2015 19:34:30 +0000 (14:34 -0500)
committerDavid Brazdil <dbrazdil@google.com>
Thu, 29 Oct 2015 17:07:27 +0000 (12:07 -0500)
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

compiler/optimizing/licm.cc
compiler/optimizing/nodes.cc
compiler/optimizing/optimizing_compiler.cc

index c38bbe3..27442d4 100644 (file)
@@ -122,6 +122,9 @@ void LICM::Run() {
           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
index 3480265..4345d55 100644 (file)
@@ -1129,6 +1129,14 @@ std::ostream& operator<<(std::ostream& os, const HInstruction::InstructionKind&
 }
 
 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_;
index 6632f95..98acc34 100644 (file)
@@ -494,43 +494,31 @@ static void RunOptimizations(HGraph* graph,
 
   // 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);
 }