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);
}