diff options
Diffstat (limited to 'compiler/optimizing/nodes.cc')
-rw-r--r-- | compiler/optimizing/nodes.cc | 52 |
1 files changed, 31 insertions, 21 deletions
diff --git a/compiler/optimizing/nodes.cc b/compiler/optimizing/nodes.cc index 833b7e9ca2..94f197d8f1 100644 --- a/compiler/optimizing/nodes.cc +++ b/compiler/optimizing/nodes.cc @@ -18,6 +18,7 @@ #include <algorithm> #include <cfloat> #include <functional> +#include <optional> #include "art_method-inl.h" #include "base/arena_allocator.h" @@ -1410,29 +1411,36 @@ void HInstruction::ReplaceWith(HInstruction* other) { void HInstruction::ReplaceUsesDominatedBy(HInstruction* dominator, HInstruction* replacement, bool strictly_dominated) { - // Get the dominated blocks first to faster calculation of domination afterwards. - HGraph* graph = GetBlock()->GetGraph(); - ArenaBitVector visited_blocks(graph->GetAllocator(), - graph->GetBlocks().size(), - /* expandable= */ false, - kArenaAllocMisc); - visited_blocks.ClearAllBits(); - ScopedArenaAllocator allocator(graph->GetArenaStack()); - ScopedArenaQueue<const HBasicBlock*> worklist(allocator.Adapter(kArenaAllocMisc)); HBasicBlock* dominator_block = dominator->GetBlock(); - worklist.push(dominator_block); + std::optional<ArenaBitVector> visited_blocks; - while (!worklist.empty()) { - const HBasicBlock* current = worklist.front(); - worklist.pop(); - visited_blocks.SetBit(current->GetBlockId()); - for (HBasicBlock* dominated : current->GetDominatedBlocks()) { - if (visited_blocks.IsBitSet(dominated->GetBlockId())) { - continue; + // Lazily compute the dominated blocks to faster calculation of domination afterwards. + auto maybe_generate_visited_blocks = [&visited_blocks, this, dominator_block]() { + if (visited_blocks.has_value()) { + return; + } + HGraph* graph = GetBlock()->GetGraph(); + visited_blocks.emplace(graph->GetAllocator(), + graph->GetBlocks().size(), + /* expandable= */ false, + kArenaAllocMisc); + visited_blocks->ClearAllBits(); + ScopedArenaAllocator allocator(graph->GetArenaStack()); + ScopedArenaQueue<const HBasicBlock*> worklist(allocator.Adapter(kArenaAllocMisc)); + worklist.push(dominator_block); + + while (!worklist.empty()) { + const HBasicBlock* current = worklist.front(); + worklist.pop(); + visited_blocks->SetBit(current->GetBlockId()); + for (HBasicBlock* dominated : current->GetDominatedBlocks()) { + if (visited_blocks->IsBitSet(dominated->GetBlockId())) { + continue; + } + worklist.push(dominated); } - worklist.push(dominated); } - } + }; const HUseList<HInstruction*>& uses = GetUses(); for (auto it = uses.begin(), end = uses.end(); it != end; /* ++it below */) { @@ -1448,7 +1456,8 @@ void HInstruction::ReplaceUsesDominatedBy(HInstruction* dominator, strictly_dominated ? dominator->StrictlyDominates(user) : dominator->Dominates(user); } else { // Block domination. - dominated = visited_blocks.IsBitSet(block->GetBlockId()); + maybe_generate_visited_blocks(); + dominated = visited_blocks->IsBitSet(block->GetBlockId()); } if (dominated) { @@ -1458,7 +1467,8 @@ void HInstruction::ReplaceUsesDominatedBy(HInstruction* dominator, // We do not perform this for catch phis as we don't have control flow support // for their inputs. HBasicBlock* predecessor = block->GetPredecessors()[index]; - if (visited_blocks.IsBitSet(predecessor->GetBlockId())) { + maybe_generate_visited_blocks(); + if (visited_blocks->IsBitSet(predecessor->GetBlockId())) { user->ReplaceInput(replacement, index); } } |