diff options
Diffstat (limited to 'compiler/optimizing/nodes.cc')
-rw-r--r-- | compiler/optimizing/nodes.cc | 62 |
1 files changed, 46 insertions, 16 deletions
diff --git a/compiler/optimizing/nodes.cc b/compiler/optimizing/nodes.cc index 1086cbf503..1afa36a89c 100644 --- a/compiler/optimizing/nodes.cc +++ b/compiler/optimizing/nodes.cc @@ -535,11 +535,16 @@ void HLoopInformation::PopulateRecursive(HBasicBlock* block) { } } -void HLoopInformation::PopulateIrreducibleRecursive(HBasicBlock* block) { - if (blocks_.IsBitSet(block->GetBlockId())) { +void HLoopInformation::PopulateIrreducibleRecursive(HBasicBlock* block, ArenaBitVector* finalized) { + size_t block_id = block->GetBlockId(); + + // If `block` is in `finalized`, we know its membership in the loop has been + // decided and it does not need to be revisited. + if (finalized->IsBitSet(block_id)) { return; } + bool is_finalized = false; if (block->IsLoopHeader()) { // If we hit a loop header in an irreducible loop, we first check if the // pre header of that loop belongs to the currently analyzed loop. If it does, @@ -547,26 +552,36 @@ void HLoopInformation::PopulateIrreducibleRecursive(HBasicBlock* block) { // Note that we cannot use GetPreHeader, as the loop may have not been populated // yet. HBasicBlock* pre_header = block->GetPredecessors()[0]; - PopulateIrreducibleRecursive(pre_header); + PopulateIrreducibleRecursive(pre_header, finalized); if (blocks_.IsBitSet(pre_header->GetBlockId())) { - blocks_.SetBit(block->GetBlockId()); block->SetInLoop(this); + blocks_.SetBit(block_id); + finalized->SetBit(block_id); + is_finalized = true; + HLoopInformation* info = block->GetLoopInformation(); for (HBasicBlock* back_edge : info->GetBackEdges()) { - PopulateIrreducibleRecursive(back_edge); + PopulateIrreducibleRecursive(back_edge, finalized); } } } else { // Visit all predecessors. If one predecessor is part of the loop, this // block is also part of this loop. for (HBasicBlock* predecessor : block->GetPredecessors()) { - PopulateIrreducibleRecursive(predecessor); - if (blocks_.IsBitSet(predecessor->GetBlockId())) { - blocks_.SetBit(block->GetBlockId()); + PopulateIrreducibleRecursive(predecessor, finalized); + if (!is_finalized && blocks_.IsBitSet(predecessor->GetBlockId())) { block->SetInLoop(this); + blocks_.SetBit(block_id); + finalized->SetBit(block_id); + is_finalized = true; } } } + + // All predecessors have been recursively visited. Mark finalized if not marked yet. + if (!is_finalized) { + finalized->SetBit(block_id); + } } void HLoopInformation::Populate() { @@ -576,22 +591,37 @@ void HLoopInformation::Populate() { // to end the recursion. // This is a recursive implementation of the algorithm described in // "Advanced Compiler Design & Implementation" (Muchnick) p192. + HGraph* graph = header_->GetGraph(); blocks_.SetBit(header_->GetBlockId()); header_->SetInLoop(this); + + bool is_irreducible_loop = false; for (HBasicBlock* back_edge : GetBackEdges()) { DCHECK(back_edge->GetDominator() != nullptr); if (!header_->Dominates(back_edge)) { - irreducible_ = true; - header_->GetGraph()->SetHasIrreducibleLoops(true); - PopulateIrreducibleRecursive(back_edge); - } else { - if (header_->GetGraph()->IsCompilingOsr()) { - irreducible_ = true; - header_->GetGraph()->SetHasIrreducibleLoops(true); - } + is_irreducible_loop = true; + break; + } + } + + if (is_irreducible_loop) { + ArenaBitVector visited(graph->GetArena(), + graph->GetBlocks().size(), + /* expandable */ false, + kArenaAllocGraphBuilder); + for (HBasicBlock* back_edge : GetBackEdges()) { + PopulateIrreducibleRecursive(back_edge, &visited); + } + } else { + for (HBasicBlock* back_edge : GetBackEdges()) { PopulateRecursive(back_edge); } } + + if (is_irreducible_loop || graph->IsCompilingOsr()) { + irreducible_ = true; + graph->SetHasIrreducibleLoops(true); + } } HBasicBlock* HLoopInformation::GetPreHeader() const { |