From 606c8f04d45df8f09f56cbce9881a57a4ae43174 Mon Sep 17 00:00:00 2001 From: Vladimir Marko Date: Thu, 3 Nov 2016 13:01:28 +0000 Subject: Fix SimplifyIfs() trying to redirect exception handler edges. Test: 622-simplifyifs-exception-edges Test: m test-art-host Bug: 32545860 Bug: 32546110 Bug: 18051191 Change-Id: I641ed73baace840411fc5651937bbc80e79b0c46 --- compiler/optimizing/dead_code_elimination.cc | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) (limited to 'compiler/optimizing') diff --git a/compiler/optimizing/dead_code_elimination.cc b/compiler/optimizing/dead_code_elimination.cc index 9de521ad8d..c31c66a056 100644 --- a/compiler/optimizing/dead_code_elimination.cc +++ b/compiler/optimizing/dead_code_elimination.cc @@ -161,8 +161,21 @@ static HConstant* Evaluate(HCondition* condition, HInstruction* left, HInstructi // | | | // B4 B5 B? // -// This simplification cannot be applied for loop headers, as they -// contain a suspend check. +// Note that individual edges can be redirected (for example B2->B3 +// can be redirected as B2->B5) without applying this optimization +// to other incoming edges. +// +// This simplification cannot be applied to catch blocks, because +// exception handler edges do not represent normal control flow. +// Though in theory this could still apply to normal control flow +// going directly to a catch block, we cannot support it at the +// moment because the catch Phi's inputs do not correspond to the +// catch block's predecessors, so we cannot identify which +// predecessor corresponds to a given statically evaluated input. +// +// We do not apply this optimization to loop headers as this could +// create irreducible loops. We rely on the suspend check in the +// loop header to prevent the pattern match. // // Note that we rely on the dead code elimination to get rid of B3. bool HDeadCodeElimination::SimplifyIfs() { @@ -172,7 +185,8 @@ bool HDeadCodeElimination::SimplifyIfs() { for (HBasicBlock* block : graph_->GetReversePostOrder()) { HInstruction* last = block->GetLastInstruction(); HInstruction* first = block->GetFirstInstruction(); - if (last->IsIf() && + if (!block->IsCatchBlock() && + last->IsIf() && block->HasSinglePhi() && block->GetFirstPhi()->HasOnlyOneNonEnvironmentUse()) { bool has_only_phi_and_if = (last == first) && (last->InputAt(0) == block->GetFirstPhi()); -- cgit v1.2.3-59-g8ed1b