diff options
Diffstat (limited to 'compiler/optimizing')
| -rw-r--r-- | compiler/optimizing/inliner.cc | 22 | ||||
| -rw-r--r-- | compiler/optimizing/nodes.cc | 14 | ||||
| -rw-r--r-- | compiler/optimizing/nodes.h | 2 |
3 files changed, 32 insertions, 6 deletions
diff --git a/compiler/optimizing/inliner.cc b/compiler/optimizing/inliner.cc index 9e816237dd..7fe54b9045 100644 --- a/compiler/optimizing/inliner.cc +++ b/compiler/optimizing/inliner.cc @@ -1226,12 +1226,22 @@ bool HInliner::TryBuildAndInlineHelper(HInvoke* invoke_instruction, // Skip the entry block, it does not contain instructions that prevent inlining. for (HBasicBlock* block : callee_graph->GetReversePostOrderSkipEntryBlock()) { - if (block->IsLoopHeader() && block->GetLoopInformation()->IsIrreducible()) { - // Don't inline methods with irreducible loops, they could prevent some - // optimizations to run. - VLOG(compiler) << "Method " << callee_dex_file.PrettyMethod(method_index) - << " could not be inlined because it contains an irreducible loop"; - return false; + if (block->IsLoopHeader()) { + if (block->GetLoopInformation()->IsIrreducible()) { + // Don't inline methods with irreducible loops, they could prevent some + // optimizations to run. + VLOG(compiler) << "Method " << callee_dex_file.PrettyMethod(method_index) + << " could not be inlined because it contains an irreducible loop"; + return false; + } + if (!block->GetLoopInformation()->HasExitEdge()) { + // Don't inline methods with loops without exit, since they cause the + // loop information to be computed incorrectly when updating after + // inlining. + VLOG(compiler) << "Method " << callee_dex_file.PrettyMethod(method_index) + << " could not be inlined because it contains a loop with no exit"; + return false; + } } for (HInstructionIterator instr_it(block->GetInstructions()); diff --git a/compiler/optimizing/nodes.cc b/compiler/optimizing/nodes.cc index 91553226c6..680381a548 100644 --- a/compiler/optimizing/nodes.cc +++ b/compiler/optimizing/nodes.cc @@ -735,6 +735,20 @@ bool HLoopInformation::DominatesAllBackEdges(HBasicBlock* block) { return true; } + +bool HLoopInformation::HasExitEdge() const { + // Determine if this loop has at least one exit edge. + HBlocksInLoopReversePostOrderIterator it_loop(*this); + for (; !it_loop.Done(); it_loop.Advance()) { + for (HBasicBlock* successor : it_loop.Current()->GetSuccessors()) { + if (!Contains(*successor)) { + return true; + } + } + } + return false; +} + bool HBasicBlock::Dominates(HBasicBlock* other) const { // Walk up the dominator tree from `other`, to find out if `this` // is an ancestor. diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h index 883ac65c9c..e0c582a76d 100644 --- a/compiler/optimizing/nodes.h +++ b/compiler/optimizing/nodes.h @@ -769,6 +769,8 @@ class HLoopInformation : public ArenaObject<kArenaAllocLoopInfo> { bool DominatesAllBackEdges(HBasicBlock* block); + bool HasExitEdge() const; + private: // Internal recursive implementation of `Populate`. void PopulateRecursive(HBasicBlock* block); |