diff options
author | 2025-02-24 12:12:09 +0000 | |
---|---|---|
committer | 2025-02-27 22:58:08 -0800 | |
commit | 22cfc7f2de1f4de1616e2b2bca30e71a5b1d2748 (patch) | |
tree | 3786448ab5b170c93de485c16094aecc7f774961 | |
parent | 12f7d1eb0ff3fe0126d8dadd6bbfa8b797718e9c (diff) |
Speed up DCE, CFRE and `ReplaceUsesDominatedBy()`...
... by using `BitViewVector<>`.
Test: m test-art-host-gtest
Test: testrunner.py --host --optimizing
Bug: 331194861
Change-Id: If22934aeae82b21ebf9fc20e817d0958bd6edec8
-rw-r--r-- | compiler/optimizing/constructor_fence_redundancy_elimination.cc | 31 | ||||
-rw-r--r-- | compiler/optimizing/dead_code_elimination.cc | 13 | ||||
-rw-r--r-- | compiler/optimizing/nodes.cc | 19 |
3 files changed, 33 insertions, 30 deletions
diff --git a/compiler/optimizing/constructor_fence_redundancy_elimination.cc b/compiler/optimizing/constructor_fence_redundancy_elimination.cc index 71fc39a956..c89ec171d9 100644 --- a/compiler/optimizing/constructor_fence_redundancy_elimination.cc +++ b/compiler/optimizing/constructor_fence_redundancy_elimination.cc @@ -33,7 +33,7 @@ class CFREVisitor final : public HGraphVisitor { : HGraphVisitor(graph), scoped_allocator_(graph->GetArenaStack()), candidate_fences_(scoped_allocator_.Adapter(kArenaAllocCFRE)), - candidate_fence_targets_(std::nullopt), + candidate_fence_targets_(), stats_(stats) {} void VisitBasicBlock(HBasicBlock* block) override { @@ -48,14 +48,17 @@ class CFREVisitor final : public HGraphVisitor { void VisitConstructorFence(HConstructorFence* constructor_fence) override { candidate_fences_.push_back(constructor_fence); - if (!candidate_fence_targets_.has_value()) { + if (candidate_fence_targets_.SizeInBits() == 0u) { size_t number_of_instructions = GetGraph()->GetCurrentInstructionId(); - candidate_fence_targets_.emplace( - &scoped_allocator_, number_of_instructions, /*expandable=*/ false, kArenaAllocCFRE); + candidate_fence_targets_ = ArenaBitVector::CreateFixedSize( + &scoped_allocator_, number_of_instructions, kArenaAllocCFRE); + } else { + DCHECK_EQ(candidate_fence_targets_.SizeInBits(), + static_cast<size_t>(GetGraph()->GetCurrentInstructionId())); } for (HInstruction* input : constructor_fence->GetInputs()) { - candidate_fence_targets_->SetBit(input->GetId()); + candidate_fence_targets_.SetBit(input->GetId()); } } @@ -162,8 +165,7 @@ class CFREVisitor final : public HGraphVisitor { void VisitSetLocation([[maybe_unused]] HInstruction* inst, HInstruction* store_input) { if (candidate_fences_.empty()) { // There is no need to look at inputs if there are no candidate fence targets. - DCHECK_IMPLIES(candidate_fence_targets_.has_value(), - !candidate_fence_targets_->IsAnyBitSet()); + DCHECK(!candidate_fence_targets_.IsAnyBitSet()); return; } // An object is considered "published" if it's stored onto the heap. @@ -179,8 +181,7 @@ class CFREVisitor final : public HGraphVisitor { bool HasInterestingPublishTargetAsInput(HInstruction* inst) { if (candidate_fences_.empty()) { // There is no need to look at inputs if there are no candidate fence targets. - DCHECK_IMPLIES(candidate_fence_targets_.has_value(), - !candidate_fence_targets_->IsAnyBitSet()); + DCHECK(!candidate_fence_targets_.IsAnyBitSet()); return false; } for (HInstruction* input : inst->GetInputs()) { @@ -221,15 +222,17 @@ class CFREVisitor final : public HGraphVisitor { // there is no benefit to this extra complexity unless we also reordered // the stores to come later. candidate_fences_.clear(); - DCHECK(candidate_fence_targets_.has_value()); - candidate_fence_targets_->ClearAllBits(); + DCHECK_EQ(candidate_fence_targets_.SizeInBits(), + static_cast<size_t>(GetGraph()->GetCurrentInstructionId())); + candidate_fence_targets_.ClearAllBits(); } // A publishing 'store' is only interesting if the value being stored // is one of the fence `targets` in `candidate_fences`. bool IsInterestingPublishTarget(HInstruction* store_input) const { - DCHECK(candidate_fence_targets_.has_value()); - return candidate_fence_targets_->IsBitSet(store_input->GetId()); + DCHECK_EQ(candidate_fence_targets_.SizeInBits(), + static_cast<size_t>(GetGraph()->GetCurrentInstructionId())); + return candidate_fence_targets_.IsBitSet(store_input->GetId()); } // Phase-local heap memory allocator for CFRE optimizer. @@ -245,7 +248,7 @@ class CFREVisitor final : public HGraphVisitor { // Stores a set of the fence targets, to allow faster lookup of whether // a detected publish is a target of one of the candidate fences. - std::optional<ArenaBitVector> candidate_fence_targets_; + BitVectorView<size_t> candidate_fence_targets_; // Used to record stats about the optimization. OptimizingCompilerStats* const stats_; diff --git a/compiler/optimizing/dead_code_elimination.cc b/compiler/optimizing/dead_code_elimination.cc index 9955982309..486625a71e 100644 --- a/compiler/optimizing/dead_code_elimination.cc +++ b/compiler/optimizing/dead_code_elimination.cc @@ -591,14 +591,15 @@ void HDeadCodeElimination::ConnectSuccessiveBlocks() { struct HDeadCodeElimination::TryBelongingInformation { TryBelongingInformation(HGraph* graph, ScopedArenaAllocator* allocator) - : blocks_in_try(allocator, graph->GetBlocks().size(), /*expandable=*/false, kArenaAllocDCE), - coalesced_try_entries( - allocator, graph->GetBlocks().size(), /*expandable=*/false, kArenaAllocDCE) {} + : blocks_in_try(ArenaBitVector::CreateFixedSize( + allocator, graph->GetBlocks().size(), kArenaAllocDCE)), + coalesced_try_entries(ArenaBitVector::CreateFixedSize( + allocator, graph->GetBlocks().size(), kArenaAllocDCE)) {} // Which blocks belong in the try. - ArenaBitVector blocks_in_try; + BitVectorView<size_t> blocks_in_try; // Which other try entries are referencing this same try. - ArenaBitVector coalesced_try_entries; + BitVectorView<size_t> coalesced_try_entries; }; bool HDeadCodeElimination::CanPerformTryRemoval(const TryBelongingInformation& try_belonging_info) { @@ -725,7 +726,7 @@ bool HDeadCodeElimination::RemoveUnneededTries() { if (try_boundary->HasSameExceptionHandlersAs(*other_try_boundary)) { // Merge the entries as they are really the same one. // Block merging. - it->second.blocks_in_try.Union(&other_it->second.blocks_in_try); + it->second.blocks_in_try.Union(other_it->second.blocks_in_try); // Add the coalesced try entry to update it too. it->second.coalesced_try_entries.SetBit(other_block->GetBlockId()); diff --git a/compiler/optimizing/nodes.cc b/compiler/optimizing/nodes.cc index 752e8b10d1..6b74e7246e 100644 --- a/compiler/optimizing/nodes.cc +++ b/compiler/optimizing/nodes.cc @@ -1457,18 +1457,17 @@ void HInstruction::ReplaceUsesDominatedBy(HInstruction* dominator, HInstruction* replacement, bool strictly_dominated) { HBasicBlock* dominator_block = dominator->GetBlock(); - std::optional<ArenaBitVector> visited_blocks; + BitVectorView<size_t> visited_blocks; // 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()) { + if (visited_blocks.SizeInBits() != 0u) { + DCHECK_EQ(visited_blocks.SizeInBits(), GetBlock()->GetGraph()->GetBlocks().size()); return; } HGraph* graph = GetBlock()->GetGraph(); - visited_blocks.emplace(graph->GetAllocator(), - graph->GetBlocks().size(), - /* expandable= */ false, - kArenaAllocMisc); + visited_blocks = ArenaBitVector::CreateFixedSize( + graph->GetAllocator(), graph->GetBlocks().size(), kArenaAllocMisc); ScopedArenaAllocator allocator(graph->GetArenaStack()); ScopedArenaQueue<const HBasicBlock*> worklist(allocator.Adapter(kArenaAllocMisc)); worklist.push(dominator_block); @@ -1476,9 +1475,9 @@ void HInstruction::ReplaceUsesDominatedBy(HInstruction* dominator, while (!worklist.empty()) { const HBasicBlock* current = worklist.front(); worklist.pop(); - visited_blocks->SetBit(current->GetBlockId()); + visited_blocks.SetBit(current->GetBlockId()); for (HBasicBlock* dominated : current->GetDominatedBlocks()) { - if (visited_blocks->IsBitSet(dominated->GetBlockId())) { + if (visited_blocks.IsBitSet(dominated->GetBlockId())) { continue; } worklist.push(dominated); @@ -1501,7 +1500,7 @@ void HInstruction::ReplaceUsesDominatedBy(HInstruction* dominator, } else { // Block domination. maybe_generate_visited_blocks(); - dominated = visited_blocks->IsBitSet(block->GetBlockId()); + dominated = visited_blocks.IsBitSet(block->GetBlockId()); } if (dominated) { @@ -1512,7 +1511,7 @@ void HInstruction::ReplaceUsesDominatedBy(HInstruction* dominator, // for their inputs. HBasicBlock* predecessor = block->GetPredecessors()[index]; maybe_generate_visited_blocks(); - if (visited_blocks->IsBitSet(predecessor->GetBlockId())) { + if (visited_blocks.IsBitSet(predecessor->GetBlockId())) { user->ReplaceInput(replacement, index); } } |