diff options
-rw-r--r-- | compiler/optimizing/bounds_check_elimination.cc | 137 | ||||
-rw-r--r-- | compiler/optimizing/dead_code_elimination.cc | 14 | ||||
-rw-r--r-- | compiler/optimizing/graph_checker.cc | 18 | ||||
-rw-r--r-- | compiler/optimizing/graph_checker.h | 22 | ||||
-rw-r--r-- | compiler/optimizing/load_store_analysis.h | 10 | ||||
-rw-r--r-- | compiler/optimizing/load_store_elimination.cc | 62 | ||||
-rw-r--r-- | compiler/optimizing/reference_type_propagation.cc | 96 | ||||
-rw-r--r-- | compiler/optimizing/reference_type_propagation.h | 24 | ||||
-rw-r--r-- | compiler/optimizing/select_generator.cc | 2 | ||||
-rw-r--r-- | compiler/optimizing/select_generator.h | 1 | ||||
-rw-r--r-- | runtime/base/arena_allocator.cc | 1 | ||||
-rw-r--r-- | runtime/base/arena_allocator.h | 1 |
12 files changed, 204 insertions, 184 deletions
diff --git a/compiler/optimizing/bounds_check_elimination.cc b/compiler/optimizing/bounds_check_elimination.cc index 0255e7302c..9c2068ec5e 100644 --- a/compiler/optimizing/bounds_check_elimination.cc +++ b/compiler/optimizing/bounds_check_elimination.cc @@ -18,7 +18,8 @@ #include <limits> -#include "base/arena_containers.h" +#include "base/scoped_arena_allocator.h" +#include "base/scoped_arena_containers.h" #include "induction_var_range.h" #include "nodes.h" #include "side_effects_analysis.h" @@ -287,7 +288,7 @@ class ValueBound : public ValueObject { */ class ValueRange : public ArenaObject<kArenaAllocBoundsCheckElimination> { public: - ValueRange(ArenaAllocator* allocator, ValueBound lower, ValueBound upper) + ValueRange(ScopedArenaAllocator* allocator, ValueBound lower, ValueBound upper) : allocator_(allocator), lower_(lower), upper_(upper) {} virtual ~ValueRange() {} @@ -297,7 +298,7 @@ class ValueRange : public ArenaObject<kArenaAllocBoundsCheckElimination> { return AsMonotonicValueRange() != nullptr; } - ArenaAllocator* GetAllocator() const { return allocator_; } + ScopedArenaAllocator* GetAllocator() const { return allocator_; } ValueBound GetLower() const { return lower_; } ValueBound GetUpper() const { return upper_; } @@ -350,7 +351,7 @@ class ValueRange : public ArenaObject<kArenaAllocBoundsCheckElimination> { } private: - ArenaAllocator* const allocator_; + ScopedArenaAllocator* const allocator_; const ValueBound lower_; // inclusive const ValueBound upper_; // inclusive @@ -365,7 +366,7 @@ class ValueRange : public ArenaObject<kArenaAllocBoundsCheckElimination> { */ class MonotonicValueRange : public ValueRange { public: - MonotonicValueRange(ArenaAllocator* allocator, + MonotonicValueRange(ScopedArenaAllocator* allocator, HPhi* induction_variable, HInstruction* initial, int32_t increment, @@ -510,21 +511,19 @@ class BCEVisitor : public HGraphVisitor { const SideEffectsAnalysis& side_effects, HInductionVarAnalysis* induction_analysis) : HGraphVisitor(graph), + allocator_(graph->GetArenaStack()), maps_(graph->GetBlocks().size(), - ArenaSafeMap<int, ValueRange*>( + ScopedArenaSafeMap<int, ValueRange*>( std::less<int>(), - graph->GetAllocator()->Adapter(kArenaAllocBoundsCheckElimination)), - graph->GetAllocator()->Adapter(kArenaAllocBoundsCheckElimination)), - first_index_bounds_check_map_( - std::less<int>(), - graph->GetAllocator()->Adapter(kArenaAllocBoundsCheckElimination)), - early_exit_loop_( - std::less<uint32_t>(), - graph->GetAllocator()->Adapter(kArenaAllocBoundsCheckElimination)), - taken_test_loop_( - std::less<uint32_t>(), - graph->GetAllocator()->Adapter(kArenaAllocBoundsCheckElimination)), - finite_loop_(graph->GetAllocator()->Adapter(kArenaAllocBoundsCheckElimination)), + allocator_.Adapter(kArenaAllocBoundsCheckElimination)), + allocator_.Adapter(kArenaAllocBoundsCheckElimination)), + first_index_bounds_check_map_(std::less<int>(), + allocator_.Adapter(kArenaAllocBoundsCheckElimination)), + early_exit_loop_(std::less<uint32_t>(), + allocator_.Adapter(kArenaAllocBoundsCheckElimination)), + taken_test_loop_(std::less<uint32_t>(), + allocator_.Adapter(kArenaAllocBoundsCheckElimination)), + finite_loop_(allocator_.Adapter(kArenaAllocBoundsCheckElimination)), has_dom_based_dynamic_bce_(false), initial_block_size_(graph->GetBlocks().size()), side_effects_(side_effects), @@ -569,7 +568,7 @@ class BCEVisitor : public HGraphVisitor { private: // Return the map of proven value ranges at the beginning of a basic block. - ArenaSafeMap<int, ValueRange*>* GetValueRangeMap(HBasicBlock* basic_block) { + ScopedArenaSafeMap<int, ValueRange*>* GetValueRangeMap(HBasicBlock* basic_block) { if (IsAddedBlock(basic_block)) { // Added blocks don't keep value ranges. return nullptr; @@ -580,7 +579,7 @@ class BCEVisitor : public HGraphVisitor { // Traverse up the dominator tree to look for value range info. ValueRange* LookupValueRange(HInstruction* instruction, HBasicBlock* basic_block) { while (basic_block != nullptr) { - ArenaSafeMap<int, ValueRange*>* map = GetValueRangeMap(basic_block); + ScopedArenaSafeMap<int, ValueRange*>* map = GetValueRangeMap(basic_block); if (map != nullptr) { if (map->find(instruction->GetId()) != map->end()) { return map->Get(instruction->GetId()); @@ -668,8 +667,8 @@ class BCEVisitor : public HGraphVisitor { if (successor != nullptr) { bool overflow; bool underflow; - ValueRange* new_left_range = new (GetGraph()->GetAllocator()) ValueRange( - GetGraph()->GetAllocator(), + ValueRange* new_left_range = new (&allocator_) ValueRange( + &allocator_, left_range->GetBound(), right_range->GetBound().Add(left_compensation, &overflow, &underflow)); if (!overflow && !underflow) { @@ -677,8 +676,8 @@ class BCEVisitor : public HGraphVisitor { new_left_range); } - ValueRange* new_right_range = new (GetGraph()->GetAllocator()) ValueRange( - GetGraph()->GetAllocator(), + ValueRange* new_right_range = new (&allocator_) ValueRange( + &allocator_, left_range->GetBound().Add(right_compensation, &overflow, &underflow), right_range->GetBound()); if (!overflow && !underflow) { @@ -750,8 +749,8 @@ class BCEVisitor : public HGraphVisitor { if (overflow || underflow) { return; } - ValueRange* new_range = new (GetGraph()->GetAllocator()) - ValueRange(GetGraph()->GetAllocator(), ValueBound::Min(), new_upper); + ValueRange* new_range = new (&allocator_) ValueRange( + &allocator_, ValueBound::Min(), new_upper); ApplyRangeFromComparison(left, block, true_successor, new_range); } @@ -762,8 +761,8 @@ class BCEVisitor : public HGraphVisitor { if (overflow || underflow) { return; } - ValueRange* new_range = new (GetGraph()->GetAllocator()) - ValueRange(GetGraph()->GetAllocator(), new_lower, ValueBound::Max()); + ValueRange* new_range = new (&allocator_) ValueRange( + &allocator_, new_lower, ValueBound::Max()); ApplyRangeFromComparison(left, block, false_successor, new_range); } } else if (cond == kCondGT || cond == kCondGE) { @@ -774,8 +773,8 @@ class BCEVisitor : public HGraphVisitor { if (overflow || underflow) { return; } - ValueRange* new_range = new (GetGraph()->GetAllocator()) - ValueRange(GetGraph()->GetAllocator(), new_lower, ValueBound::Max()); + ValueRange* new_range = new (&allocator_) ValueRange( + &allocator_, new_lower, ValueBound::Max()); ApplyRangeFromComparison(left, block, true_successor, new_range); } @@ -785,8 +784,8 @@ class BCEVisitor : public HGraphVisitor { if (overflow || underflow) { return; } - ValueRange* new_range = new (GetGraph()->GetAllocator()) - ValueRange(GetGraph()->GetAllocator(), ValueBound::Min(), new_upper); + ValueRange* new_range = new (&allocator_) ValueRange( + &allocator_, ValueBound::Min(), new_upper); ApplyRangeFromComparison(left, block, false_successor, new_range); } } else if (cond == kCondNE || cond == kCondEQ) { @@ -795,8 +794,7 @@ class BCEVisitor : public HGraphVisitor { // length == [c,d] yields [c, d] along true // length != [c,d] yields [c, d] along false if (!lower.Equals(ValueBound::Min()) || !upper.Equals(ValueBound::Max())) { - ValueRange* new_range = new (GetGraph()->GetAllocator()) - ValueRange(GetGraph()->GetAllocator(), lower, upper); + ValueRange* new_range = new (&allocator_) ValueRange(&allocator_, lower, upper); ApplyRangeFromComparison( left, block, cond == kCondEQ ? true_successor : false_successor, new_range); } @@ -804,8 +802,8 @@ class BCEVisitor : public HGraphVisitor { // length == 0 yields [1, max] along false // length != 0 yields [1, max] along true if (lower.GetConstant() == 0 && upper.GetConstant() == 0) { - ValueRange* new_range = new (GetGraph()->GetAllocator()) - ValueRange(GetGraph()->GetAllocator(), ValueBound(nullptr, 1), ValueBound::Max()); + ValueRange* new_range = new (&allocator_) ValueRange( + &allocator_, ValueBound(nullptr, 1), ValueBound::Max()); ApplyRangeFromComparison( left, block, cond == kCondEQ ? false_successor : true_successor, new_range); } @@ -826,7 +824,7 @@ class BCEVisitor : public HGraphVisitor { // Non-constant index. ValueBound lower = ValueBound(nullptr, 0); // constant 0 ValueBound upper = ValueBound(array_length, -1); // array_length - 1 - ValueRange array_range(GetGraph()->GetAllocator(), lower, upper); + ValueRange array_range(&allocator_, lower, upper); // Try index range obtained by dominator-based analysis. ValueRange* index_range = LookupValueRange(index, block); if (index_range != nullptr && index_range->FitsIn(&array_range)) { @@ -875,8 +873,7 @@ class BCEVisitor : public HGraphVisitor { } else { ValueBound lower = ValueBound(nullptr, constant + 1); ValueBound upper = ValueBound::Max(); - ValueRange* range = new (GetGraph()->GetAllocator()) - ValueRange(GetGraph()->GetAllocator(), lower, upper); + ValueRange* range = new (&allocator_) ValueRange(&allocator_, lower, upper); AssignRange(block, array_length, range); } } @@ -938,8 +935,8 @@ class BCEVisitor : public HGraphVisitor { ValueRange* range = nullptr; if (increment == 0) { // Add constant 0. It's really a fixed value. - range = new (GetGraph()->GetAllocator()) ValueRange( - GetGraph()->GetAllocator(), + range = new (&allocator_) ValueRange( + &allocator_, ValueBound(initial_value, 0), ValueBound(initial_value, 0)); } else { @@ -959,8 +956,8 @@ class BCEVisitor : public HGraphVisitor { bound = increment > 0 ? ValueBound::Min() : ValueBound::Max(); } } - range = new (GetGraph()->GetAllocator()) MonotonicValueRange( - GetGraph()->GetAllocator(), + range = new (&allocator_) MonotonicValueRange( + &allocator_, phi, initial_value, increment, @@ -1039,8 +1036,8 @@ class BCEVisitor : public HGraphVisitor { !ValueBound::WouldAddOverflowOrUnderflow(c0, -c1)) { if ((c0 - c1) <= 0) { // array.length + (c0 - c1) won't overflow/underflow. - ValueRange* range = new (GetGraph()->GetAllocator()) ValueRange( - GetGraph()->GetAllocator(), + ValueRange* range = new (&allocator_) ValueRange( + &allocator_, ValueBound(nullptr, right_const - upper.GetConstant()), ValueBound(array_length, right_const - lower.GetConstant())); AssignRange(sub->GetBlock(), sub, range); @@ -1087,8 +1084,8 @@ class BCEVisitor : public HGraphVisitor { // than array_length. return; } - ValueRange* range = new (GetGraph()->GetAllocator()) ValueRange( - GetGraph()->GetAllocator(), + ValueRange* range = new (&allocator_) ValueRange( + &allocator_, ValueBound(nullptr, std::numeric_limits<int32_t>::min()), ValueBound(left, 0)); AssignRange(instruction->GetBlock(), instruction, range); @@ -1113,8 +1110,8 @@ class BCEVisitor : public HGraphVisitor { if (constant > 0) { // constant serves as a mask so any number masked with it // gets a [0, constant] value range. - ValueRange* range = new (GetGraph()->GetAllocator()) ValueRange( - GetGraph()->GetAllocator(), + ValueRange* range = new (&allocator_) ValueRange( + &allocator_, ValueBound(nullptr, 0), ValueBound(nullptr, constant)); AssignRange(instruction->GetBlock(), instruction, range); @@ -1139,8 +1136,8 @@ class BCEVisitor : public HGraphVisitor { // array[i % 10]; // index value range [0, 9] // array[i % -10]; // index value range [0, 9] // } - ValueRange* right_range = new (GetGraph()->GetAllocator()) ValueRange( - GetGraph()->GetAllocator(), + ValueRange* right_range = new (&allocator_) ValueRange( + &allocator_, ValueBound(nullptr, 1 - right_const), ValueBound(nullptr, right_const - 1)); @@ -1169,8 +1166,8 @@ class BCEVisitor : public HGraphVisitor { if (right->IsArrayLength()) { ValueBound lower = ValueBound::Min(); // ideally, lower should be '1-array_length'. ValueBound upper = ValueBound(right, -1); // array_length - 1 - ValueRange* right_range = new (GetGraph()->GetAllocator()) ValueRange( - GetGraph()->GetAllocator(), + ValueRange* right_range = new (&allocator_) ValueRange( + &allocator_, lower, upper); ValueRange* left_range = LookupValueRange(left, instruction->GetBlock()); @@ -1195,8 +1192,7 @@ class BCEVisitor : public HGraphVisitor { // which isn't available as an instruction yet. new_array will // be treated the same as new_array.length when it's used in a ValueBound. ValueBound upper = ValueBound(new_array, -right_const); - ValueRange* range = new (GetGraph()->GetAllocator()) - ValueRange(GetGraph()->GetAllocator(), lower, upper); + ValueRange* range = new (&allocator_) ValueRange(&allocator_, lower, upper); ValueRange* existing_range = LookupValueRange(left, new_array->GetBlock()); if (existing_range != nullptr) { range = existing_range->Narrow(range); @@ -1291,10 +1287,10 @@ class BCEVisitor : public HGraphVisitor { HInstruction* base = value.GetInstruction(); int32_t min_c = base == nullptr ? 0 : value.GetConstant(); int32_t max_c = value.GetConstant(); - ArenaVector<HBoundsCheck*> candidates( - GetGraph()->GetAllocator()->Adapter(kArenaAllocBoundsCheckElimination)); - ArenaVector<HBoundsCheck*> standby( - GetGraph()->GetAllocator()->Adapter(kArenaAllocBoundsCheckElimination)); + ScopedArenaVector<HBoundsCheck*> candidates( + allocator_.Adapter(kArenaAllocBoundsCheckElimination)); + ScopedArenaVector<HBoundsCheck*> standby( + allocator_.Adapter(kArenaAllocBoundsCheckElimination)); for (const HUseListNode<HInstruction*>& use : array_length->GetUses()) { // Another bounds check in same or dominated block? HInstruction* user = use.GetUser(); @@ -1378,7 +1374,7 @@ class BCEVisitor : public HGraphVisitor { v2.is_known && (v2.a_constant == 0 || v2.a_constant == 1)) { DCHECK(v1.a_constant == 1 || v1.instruction == nullptr); DCHECK(v2.a_constant == 1 || v2.instruction == nullptr); - ValueRange index_range(GetGraph()->GetAllocator(), + ValueRange index_range(&allocator_, ValueBound(v1.instruction, v1.b_constant), ValueBound(v2.instruction, v2.b_constant)); // If analysis reveals a certain OOB, disable dynamic BCE. Otherwise, @@ -1410,10 +1406,10 @@ class BCEVisitor : public HGraphVisitor { HInstruction* base = value.GetInstruction(); int32_t min_c = base == nullptr ? 0 : value.GetConstant(); int32_t max_c = value.GetConstant(); - ArenaVector<HBoundsCheck*> candidates( - GetGraph()->GetAllocator()->Adapter(kArenaAllocBoundsCheckElimination)); - ArenaVector<HBoundsCheck*> standby( - GetGraph()->GetAllocator()->Adapter(kArenaAllocBoundsCheckElimination)); + ScopedArenaVector<HBoundsCheck*> candidates( + allocator_.Adapter(kArenaAllocBoundsCheckElimination)); + ScopedArenaVector<HBoundsCheck*> standby( + allocator_.Adapter(kArenaAllocBoundsCheckElimination)); for (const HUseListNode<HInstruction*>& use : array_length->GetUses()) { HInstruction* user = use.GetUser(); if (user->IsBoundsCheck() && loop == user->GetBlock()->GetLoopInformation()) { @@ -1882,21 +1878,24 @@ class BCEVisitor : public HGraphVisitor { instruction->GetBlock()->RemoveInstruction(instruction); } + // Use local allocator for allocating memory. + ScopedArenaAllocator allocator_; + // A set of maps, one per basic block, from instruction to range. - ArenaVector<ArenaSafeMap<int, ValueRange*>> maps_; + ScopedArenaVector<ScopedArenaSafeMap<int, ValueRange*>> maps_; // Map an HArrayLength instruction's id to the first HBoundsCheck instruction // in a block that checks an index against that HArrayLength. - ArenaSafeMap<int, HBoundsCheck*> first_index_bounds_check_map_; + ScopedArenaSafeMap<int, HBoundsCheck*> first_index_bounds_check_map_; // Early-exit loop bookkeeping. - ArenaSafeMap<uint32_t, bool> early_exit_loop_; + ScopedArenaSafeMap<uint32_t, bool> early_exit_loop_; // Taken-test loop bookkeeping. - ArenaSafeMap<uint32_t, HBasicBlock*> taken_test_loop_; + ScopedArenaSafeMap<uint32_t, HBasicBlock*> taken_test_loop_; // Finite loop bookkeeping. - ArenaSet<uint32_t> finite_loop_; + ScopedArenaSet<uint32_t> finite_loop_; // Flag that denotes whether dominator-based dynamic elimination has occurred. bool has_dom_based_dynamic_bce_; diff --git a/compiler/optimizing/dead_code_elimination.cc b/compiler/optimizing/dead_code_elimination.cc index 5117e07a12..3cc7b0e78d 100644 --- a/compiler/optimizing/dead_code_elimination.cc +++ b/compiler/optimizing/dead_code_elimination.cc @@ -18,13 +18,18 @@ #include "base/array_ref.h" #include "base/bit_vector-inl.h" +#include "base/scoped_arena_allocator.h" +#include "base/scoped_arena_containers.h" #include "base/stl_util.h" #include "ssa_phi_elimination.h" namespace art { static void MarkReachableBlocks(HGraph* graph, ArenaBitVector* visited) { - ArenaVector<HBasicBlock*> worklist(graph->GetAllocator()->Adapter(kArenaAllocDCE)); + // Use local allocator for allocating memory. + ScopedArenaAllocator allocator(graph->GetArenaStack()); + + ScopedArenaVector<HBasicBlock*> worklist(allocator.Adapter(kArenaAllocDCE)); constexpr size_t kDefaultWorlistSize = 8; worklist.reserve(kDefaultWorlistSize); visited->SetBit(graph->GetEntryBlock()->GetBlockId()); @@ -305,9 +310,12 @@ void HDeadCodeElimination::ConnectSuccessiveBlocks() { } bool HDeadCodeElimination::RemoveDeadBlocks() { + // Use local allocator for allocating memory. + ScopedArenaAllocator allocator(graph_->GetArenaStack()); + // Classify blocks as reachable/unreachable. - ArenaAllocator* allocator = graph_->GetAllocator(); - ArenaBitVector live_blocks(allocator, graph_->GetBlocks().size(), false, kArenaAllocDCE); + ArenaBitVector live_blocks(&allocator, graph_->GetBlocks().size(), false, kArenaAllocDCE); + live_blocks.ClearAllBits(); MarkReachableBlocks(graph_, &live_blocks); bool removed_one_or_more_blocks = false; diff --git a/compiler/optimizing/graph_checker.cc b/compiler/optimizing/graph_checker.cc index 1c7d1a0b69..b1ac027a68 100644 --- a/compiler/optimizing/graph_checker.cc +++ b/compiler/optimizing/graph_checker.cc @@ -22,8 +22,9 @@ #include "android-base/stringprintf.h" -#include "base/arena_containers.h" #include "base/bit_vector-inl.h" +#include "base/scoped_arena_allocator.h" +#include "base/scoped_arena_containers.h" namespace art { @@ -47,10 +48,13 @@ static bool IsExitTryBoundaryIntoExitBlock(HBasicBlock* block) { void GraphChecker::VisitBasicBlock(HBasicBlock* block) { current_block_ = block; + // Use local allocator for allocating memory. + ScopedArenaAllocator allocator(GetGraph()->GetArenaStack()); + // Check consistency with respect to predecessors of `block`. // Note: Counting duplicates with a sorted vector uses up to 6x less memory // than ArenaSafeMap<HBasicBlock*, size_t> and also allows storage reuse. - ArenaVector<HBasicBlock*>& sorted_predecessors = blocks_storage_; + ScopedArenaVector<HBasicBlock*> sorted_predecessors(allocator.Adapter(kArenaAllocGraphChecker)); sorted_predecessors.assign(block->GetPredecessors().begin(), block->GetPredecessors().end()); std::sort(sorted_predecessors.begin(), sorted_predecessors.end()); for (auto it = sorted_predecessors.begin(), end = sorted_predecessors.end(); it != end; ) { @@ -73,7 +77,7 @@ void GraphChecker::VisitBasicBlock(HBasicBlock* block) { // Check consistency with respect to successors of `block`. // Note: Counting duplicates with a sorted vector uses up to 6x less memory // than ArenaSafeMap<HBasicBlock*, size_t> and also allows storage reuse. - ArenaVector<HBasicBlock*>& sorted_successors = blocks_storage_; + ScopedArenaVector<HBasicBlock*> sorted_successors(allocator.Adapter(kArenaAllocGraphChecker)); sorted_successors.assign(block->GetSuccessors().begin(), block->GetSuccessors().end()); std::sort(sorted_successors.begin(), sorted_successors.end()); for (auto it = sorted_successors.begin(), end = sorted_successors.end(); it != end; ) { @@ -829,10 +833,14 @@ void GraphChecker::VisitPhi(HPhi* phi) { phi->GetRegNumber(), type_str.str().c_str())); } else { + // Use local allocator for allocating memory. + ScopedArenaAllocator allocator(GetGraph()->GetArenaStack()); // If we get here, make sure we allocate all the necessary storage at once // because the BitVector reallocation strategy has very bad worst-case behavior. - ArenaBitVector& visited = visited_storage_; - visited.SetBit(GetGraph()->GetCurrentInstructionId()); + ArenaBitVector visited(&allocator, + GetGraph()->GetCurrentInstructionId(), + /* expandable */ false, + kArenaAllocGraphChecker); visited.ClearAllBits(); if (!IsConstantEquivalent(phi, other_phi, &visited)) { AddError(StringPrintf("Two phis (%d and %d) found for VReg %d but they " diff --git a/compiler/optimizing/graph_checker.h b/compiler/optimizing/graph_checker.h index 6af7b429f7..0f0b49d240 100644 --- a/compiler/optimizing/graph_checker.h +++ b/compiler/optimizing/graph_checker.h @@ -17,10 +17,13 @@ #ifndef ART_COMPILER_OPTIMIZING_GRAPH_CHECKER_H_ #define ART_COMPILER_OPTIMIZING_GRAPH_CHECKER_H_ -#include "nodes.h" - #include <ostream> +#include "base/arena_bit_vector.h" +#include "base/bit_vector-inl.h" +#include "base/scoped_arena_allocator.h" +#include "nodes.h" + namespace art { // A control-flow graph visitor performing various checks. @@ -30,12 +33,10 @@ class GraphChecker : public HGraphDelegateVisitor { : HGraphDelegateVisitor(graph), errors_(graph->GetAllocator()->Adapter(kArenaAllocGraphChecker)), dump_prefix_(dump_prefix), - seen_ids_(graph->GetAllocator(), - graph->GetCurrentInstructionId(), - false, - kArenaAllocGraphChecker), - blocks_storage_(graph->GetAllocator()->Adapter(kArenaAllocGraphChecker)), - visited_storage_(graph->GetAllocator(), 0u, true, kArenaAllocGraphChecker) {} + allocator_(graph->GetArenaStack()), + seen_ids_(&allocator_, graph->GetCurrentInstructionId(), false, kArenaAllocGraphChecker) { + seen_ids_.ClearAllBits(); + } // Check the whole graph (in reverse post-order). void Run() { @@ -104,12 +105,9 @@ class GraphChecker : public HGraphDelegateVisitor { private: // String displayed before dumped errors. const char* const dump_prefix_; + ScopedArenaAllocator allocator_; ArenaBitVector seen_ids_; - // To reduce the total arena memory allocation, we reuse the same storage. - ArenaVector<HBasicBlock*> blocks_storage_; - ArenaBitVector visited_storage_; - DISALLOW_COPY_AND_ASSIGN(GraphChecker); }; diff --git a/compiler/optimizing/load_store_analysis.h b/compiler/optimizing/load_store_analysis.h index 6a25da3cfd..5940ee755f 100644 --- a/compiler/optimizing/load_store_analysis.h +++ b/compiler/optimizing/load_store_analysis.h @@ -25,7 +25,7 @@ namespace art { // A ReferenceInfo contains additional info about a reference such as // whether it's a singleton, returned, etc. -class ReferenceInfo : public ArenaObject<kArenaAllocMisc> { +class ReferenceInfo : public ArenaObject<kArenaAllocLSA> { public: ReferenceInfo(HInstruction* reference, size_t pos) : reference_(reference), @@ -99,7 +99,7 @@ class ReferenceInfo : public ArenaObject<kArenaAllocMisc> { // A heap location is a reference-offset/index pair that a value can be loaded from // or stored to. -class HeapLocation : public ArenaObject<kArenaAllocMisc> { +class HeapLocation : public ArenaObject<kArenaAllocLSA> { public: static constexpr size_t kInvalidFieldOffset = -1; @@ -172,12 +172,12 @@ class HeapLocationCollector : public HGraphVisitor { explicit HeapLocationCollector(HGraph* graph) : HGraphVisitor(graph), - ref_info_array_(graph->GetAllocator()->Adapter(kArenaAllocLSE)), - heap_locations_(graph->GetAllocator()->Adapter(kArenaAllocLSE)), + ref_info_array_(graph->GetAllocator()->Adapter(kArenaAllocLSA)), + heap_locations_(graph->GetAllocator()->Adapter(kArenaAllocLSA)), aliasing_matrix_(graph->GetAllocator(), kInitialAliasingMatrixBitVectorSize, true, - kArenaAllocLSE), + kArenaAllocLSA), has_heap_stores_(false), has_volatile_(false), has_monitor_operations_(false) {} diff --git a/compiler/optimizing/load_store_elimination.cc b/compiler/optimizing/load_store_elimination.cc index 39bfc86432..af5585ec92 100644 --- a/compiler/optimizing/load_store_elimination.cc +++ b/compiler/optimizing/load_store_elimination.cc @@ -16,6 +16,9 @@ #include "load_store_elimination.h" +#include "base/array_ref.h" +#include "base/scoped_arena_allocator.h" +#include "base/scoped_arena_containers.h" #include "escape.h" #include "load_store_analysis.h" #include "side_effects_analysis.h" @@ -45,17 +48,18 @@ class LSEVisitor : public HGraphVisitor { : HGraphVisitor(graph, stats), heap_location_collector_(heap_locations_collector), side_effects_(side_effects), + allocator_(graph->GetArenaStack()), heap_values_for_(graph->GetBlocks().size(), - ArenaVector<HInstruction*>(heap_locations_collector. - GetNumberOfHeapLocations(), - kUnknownHeapValue, - graph->GetAllocator()->Adapter(kArenaAllocLSE)), - graph->GetAllocator()->Adapter(kArenaAllocLSE)), - removed_loads_(graph->GetAllocator()->Adapter(kArenaAllocLSE)), - substitute_instructions_for_loads_(graph->GetAllocator()->Adapter(kArenaAllocLSE)), - possibly_removed_stores_(graph->GetAllocator()->Adapter(kArenaAllocLSE)), - singleton_new_instances_(graph->GetAllocator()->Adapter(kArenaAllocLSE)), - singleton_new_arrays_(graph->GetAllocator()->Adapter(kArenaAllocLSE)) { + ScopedArenaVector<HInstruction*>(heap_locations_collector. + GetNumberOfHeapLocations(), + kUnknownHeapValue, + allocator_.Adapter(kArenaAllocLSE)), + allocator_.Adapter(kArenaAllocLSE)), + removed_loads_(allocator_.Adapter(kArenaAllocLSE)), + substitute_instructions_for_loads_(allocator_.Adapter(kArenaAllocLSE)), + possibly_removed_stores_(allocator_.Adapter(kArenaAllocLSE)), + singleton_new_instances_(allocator_.Adapter(kArenaAllocLSE)), + singleton_new_arrays_(allocator_.Adapter(kArenaAllocLSE)) { } void VisitBasicBlock(HBasicBlock* block) OVERRIDE { @@ -146,7 +150,7 @@ class LSEVisitor : public HGraphVisitor { void HandleLoopSideEffects(HBasicBlock* block) { DCHECK(block->IsLoopHeader()); int block_id = block->GetBlockId(); - ArenaVector<HInstruction*>& heap_values = heap_values_for_[block_id]; + ScopedArenaVector<HInstruction*>& heap_values = heap_values_for_[block_id]; // Don't eliminate loads in irreducible loops. This is safe for singletons, because // they are always used by the non-eliminated loop-phi. @@ -160,7 +164,7 @@ class LSEVisitor : public HGraphVisitor { } HBasicBlock* pre_header = block->GetLoopInformation()->GetPreHeader(); - ArenaVector<HInstruction*>& pre_header_heap_values = + ScopedArenaVector<HInstruction*>& pre_header_heap_values = heap_values_for_[pre_header->GetBlockId()]; // Inherit the values from pre-header. @@ -191,12 +195,12 @@ class LSEVisitor : public HGraphVisitor { } void MergePredecessorValues(HBasicBlock* block) { - const ArenaVector<HBasicBlock*>& predecessors = block->GetPredecessors(); + ArrayRef<HBasicBlock* const> predecessors(block->GetPredecessors()); if (predecessors.size() == 0) { return; } - ArenaVector<HInstruction*>& heap_values = heap_values_for_[block->GetBlockId()]; + ScopedArenaVector<HInstruction*>& heap_values = heap_values_for_[block->GetBlockId()]; for (size_t i = 0; i < heap_values.size(); i++) { HInstruction* merged_value = nullptr; // Whether merged_value is a result that's merged from all predecessors. @@ -234,7 +238,8 @@ class LSEVisitor : public HGraphVisitor { // or the heap value may be needed after method return or deoptimization. // Keep the last store in each predecessor since future loads cannot be eliminated. for (HBasicBlock* predecessor : predecessors) { - ArenaVector<HInstruction*>& pred_values = heap_values_for_[predecessor->GetBlockId()]; + ScopedArenaVector<HInstruction*>& pred_values = + heap_values_for_[predecessor->GetBlockId()]; KeepIfIsStore(pred_values[i]); } } @@ -303,7 +308,7 @@ class LSEVisitor : public HGraphVisitor { size_t idx = heap_location_collector_.FindHeapLocationIndex( ref_info, offset, index, declaring_class_def_index); DCHECK_NE(idx, HeapLocationCollector::kHeapLocationNotFound); - ArenaVector<HInstruction*>& heap_values = + ScopedArenaVector<HInstruction*>& heap_values = heap_values_for_[instruction->GetBlock()->GetBlockId()]; HInstruction* heap_value = heap_values[idx]; if (heap_value == kDefaultHeapValue) { @@ -369,7 +374,7 @@ class LSEVisitor : public HGraphVisitor { size_t idx = heap_location_collector_.FindHeapLocationIndex( ref_info, offset, index, declaring_class_def_index); DCHECK_NE(idx, HeapLocationCollector::kHeapLocationNotFound); - ArenaVector<HInstruction*>& heap_values = + ScopedArenaVector<HInstruction*>& heap_values = heap_values_for_[instruction->GetBlock()->GetBlockId()]; HInstruction* heap_value = heap_values[idx]; bool same_value = false; @@ -496,7 +501,7 @@ class LSEVisitor : public HGraphVisitor { } void VisitDeoptimize(HDeoptimize* instruction) { - const ArenaVector<HInstruction*>& heap_values = + const ScopedArenaVector<HInstruction*>& heap_values = heap_values_for_[instruction->GetBlock()->GetBlockId()]; for (HInstruction* heap_value : heap_values) { // Filter out fake instructions before checking instruction kind below. @@ -523,7 +528,7 @@ class LSEVisitor : public HGraphVisitor { } void HandleInvoke(HInstruction* invoke) { - ArenaVector<HInstruction*>& heap_values = + ScopedArenaVector<HInstruction*>& heap_values = heap_values_for_[invoke->GetBlock()->GetBlockId()]; for (size_t i = 0; i < heap_values.size(); i++) { ReferenceInfo* ref_info = heap_location_collector_.GetHeapLocation(i)->GetReferenceInfo(); @@ -590,7 +595,7 @@ class LSEVisitor : public HGraphVisitor { !new_instance->NeedsChecks()) { singleton_new_instances_.push_back(new_instance); } - ArenaVector<HInstruction*>& heap_values = + ScopedArenaVector<HInstruction*>& heap_values = heap_values_for_[new_instance->GetBlock()->GetBlockId()]; for (size_t i = 0; i < heap_values.size(); i++) { HInstruction* ref = @@ -612,7 +617,7 @@ class LSEVisitor : public HGraphVisitor { if (ref_info->IsSingletonAndRemovable()) { singleton_new_arrays_.push_back(new_array); } - ArenaVector<HInstruction*>& heap_values = + ScopedArenaVector<HInstruction*>& heap_values = heap_values_for_[new_array->GetBlock()->GetBlockId()]; for (size_t i = 0; i < heap_values.size(); i++) { HeapLocation* location = heap_location_collector_.GetHeapLocation(i); @@ -639,20 +644,23 @@ class LSEVisitor : public HGraphVisitor { const HeapLocationCollector& heap_location_collector_; const SideEffectsAnalysis& side_effects_; + // Use local allocator for allocating memory. + ScopedArenaAllocator allocator_; + // One array of heap values for each block. - ArenaVector<ArenaVector<HInstruction*>> heap_values_for_; + ScopedArenaVector<ScopedArenaVector<HInstruction*>> heap_values_for_; // We record the instructions that should be eliminated but may be // used by heap locations. They'll be removed in the end. - ArenaVector<HInstruction*> removed_loads_; - ArenaVector<HInstruction*> substitute_instructions_for_loads_; + ScopedArenaVector<HInstruction*> removed_loads_; + ScopedArenaVector<HInstruction*> substitute_instructions_for_loads_; // Stores in this list may be removed from the list later when it's // found that the store cannot be eliminated. - ArenaVector<HInstruction*> possibly_removed_stores_; + ScopedArenaVector<HInstruction*> possibly_removed_stores_; - ArenaVector<HInstruction*> singleton_new_instances_; - ArenaVector<HInstruction*> singleton_new_arrays_; + ScopedArenaVector<HInstruction*> singleton_new_instances_; + ScopedArenaVector<HInstruction*> singleton_new_arrays_; DISALLOW_COPY_AND_ASSIGN(LSEVisitor); }; diff --git a/compiler/optimizing/reference_type_propagation.cc b/compiler/optimizing/reference_type_propagation.cc index 6d9ebc8d91..cb9dc42572 100644 --- a/compiler/optimizing/reference_type_propagation.cc +++ b/compiler/optimizing/reference_type_propagation.cc @@ -18,8 +18,11 @@ #include "art_field-inl.h" #include "art_method-inl.h" +#include "base/scoped_arena_allocator.h" +#include "base/scoped_arena_containers.h" #include "base/enums.h" #include "class_linker-inl.h" +#include "handle_scope-inl.h" #include "mirror/class-inl.h" #include "mirror/dex_cache.h" #include "scoped_thread_state_change-inl.h" @@ -70,14 +73,16 @@ class ReferenceTypePropagation::RTPVisitor : public HGraphDelegateVisitor { Handle<mirror::ClassLoader> class_loader, Handle<mirror::DexCache> hint_dex_cache, HandleCache* handle_cache, - ArenaVector<HInstruction*>* worklist, bool is_first_run) : HGraphDelegateVisitor(graph), class_loader_(class_loader), hint_dex_cache_(hint_dex_cache), handle_cache_(handle_cache), - worklist_(worklist), - is_first_run_(is_first_run) {} + allocator_(graph->GetArenaStack()), + worklist_(allocator_.Adapter(kArenaAllocReferenceTypePropagation)), + is_first_run_(is_first_run) { + worklist_.reserve(kDefaultWorklistSize); + } void VisitDeoptimize(HDeoptimize* deopt) OVERRIDE; void VisitNewInstance(HNewInstance* new_instance) OVERRIDE; @@ -87,9 +92,6 @@ class ReferenceTypePropagation::RTPVisitor : public HGraphDelegateVisitor { void VisitLoadException(HLoadException* instr) OVERRIDE; void VisitNewArray(HNewArray* instr) OVERRIDE; void VisitParameterValue(HParameterValue* instr) OVERRIDE; - void UpdateFieldAccessTypeInfo(HInstruction* instr, const FieldInfo& info); - void SetClassAsTypeInfo(HInstruction* instr, ObjPtr<mirror::Class> klass, bool is_exact) - REQUIRES_SHARED(Locks::mutator_lock_); void VisitInstanceFieldGet(HInstanceFieldGet* instr) OVERRIDE; void VisitStaticFieldGet(HStaticFieldGet* instr) OVERRIDE; void VisitUnresolvedInstanceFieldGet(HUnresolvedInstanceFieldGet* instr) OVERRIDE; @@ -99,16 +101,39 @@ class ReferenceTypePropagation::RTPVisitor : public HGraphDelegateVisitor { void VisitCheckCast(HCheckCast* instr) OVERRIDE; void VisitBoundType(HBoundType* instr) OVERRIDE; void VisitNullCheck(HNullCheck* instr) OVERRIDE; + void VisitPhi(HPhi* phi); + + void VisitBasicBlock(HBasicBlock* block); + void ProcessWorklist(); + + private: + void UpdateFieldAccessTypeInfo(HInstruction* instr, const FieldInfo& info); + void SetClassAsTypeInfo(HInstruction* instr, ObjPtr<mirror::Class> klass, bool is_exact) + REQUIRES_SHARED(Locks::mutator_lock_); + void BoundTypeForIfNotNull(HBasicBlock* block); + static void BoundTypeForIfInstanceOf(HBasicBlock* block); + static bool UpdateNullability(HInstruction* instr); + static void UpdateBoundType(HBoundType* bound_type) REQUIRES_SHARED(Locks::mutator_lock_); + void UpdateArrayGet(HArrayGet* instr) REQUIRES_SHARED(Locks::mutator_lock_); + void UpdatePhi(HPhi* phi) REQUIRES_SHARED(Locks::mutator_lock_); + bool UpdateReferenceTypeInfo(HInstruction* instr); void UpdateReferenceTypeInfo(HInstruction* instr, dex::TypeIndex type_idx, const DexFile& dex_file, bool is_exact); - private: + void AddToWorklist(HInstruction* instruction); + void AddDependentInstructionsToWorklist(HInstruction* instruction); + + static constexpr size_t kDefaultWorklistSize = 8; + Handle<mirror::ClassLoader> class_loader_; Handle<mirror::DexCache> hint_dex_cache_; - HandleCache* handle_cache_; - ArenaVector<HInstruction*>* worklist_; + HandleCache* const handle_cache_; + + // Use local allocator for allocating memory. + ScopedArenaAllocator allocator_; + ScopedArenaVector<HInstruction*> worklist_; const bool is_first_run_; }; @@ -122,7 +147,6 @@ ReferenceTypePropagation::ReferenceTypePropagation(HGraph* graph, class_loader_(class_loader), hint_dex_cache_(hint_dex_cache), handle_cache_(handles), - worklist_(graph->GetAllocator()->Adapter(kArenaAllocReferenceTypePropagation)), is_first_run_(is_first_run) { } @@ -158,7 +182,6 @@ void ReferenceTypePropagation::Visit(HInstruction* instruction) { class_loader_, hint_dex_cache_, &handle_cache_, - &worklist_, is_first_run_); instruction->Accept(&visitor); } @@ -319,26 +342,20 @@ static void BoundTypeForClassCheck(HInstruction* check) { } void ReferenceTypePropagation::Run() { - worklist_.reserve(kDefaultWorklistSize); + RTPVisitor visitor(graph_, class_loader_, hint_dex_cache_, &handle_cache_, is_first_run_); // To properly propagate type info we need to visit in the dominator-based order. // Reverse post order guarantees a node's dominators are visited first. // We take advantage of this order in `VisitBasicBlock`. for (HBasicBlock* block : graph_->GetReversePostOrder()) { - VisitBasicBlock(block); + visitor.VisitBasicBlock(block); } - ProcessWorklist(); + visitor.ProcessWorklist(); ValidateTypes(); } -void ReferenceTypePropagation::VisitBasicBlock(HBasicBlock* block) { - RTPVisitor visitor(graph_, - class_loader_, - hint_dex_cache_, - &handle_cache_, - &worklist_, - is_first_run_); +void ReferenceTypePropagation::RTPVisitor::VisitBasicBlock(HBasicBlock* block) { // Handle Phis first as there might be instructions in the same block who depend on them. for (HInstructionIterator it(block->GetPhis()); !it.Done(); it.Advance()) { VisitPhi(it.Current()->AsPhi()); @@ -348,7 +365,7 @@ void ReferenceTypePropagation::VisitBasicBlock(HBasicBlock* block) { // last visited instruction, use `HInstructionIteratorHandleChanges` iterator. for (HInstructionIteratorHandleChanges it(block->GetInstructions()); !it.Done(); it.Advance()) { HInstruction* instr = it.Current(); - instr->Accept(&visitor); + instr->Accept(this); } // Add extra nodes to bound types. @@ -357,7 +374,7 @@ void ReferenceTypePropagation::VisitBasicBlock(HBasicBlock* block) { BoundTypeForClassCheck(block->GetLastInstruction()); } -void ReferenceTypePropagation::BoundTypeForIfNotNull(HBasicBlock* block) { +void ReferenceTypePropagation::RTPVisitor::BoundTypeForIfNotNull(HBasicBlock* block) { HIf* ifInstruction = block->GetLastInstruction()->AsIf(); if (ifInstruction == nullptr) { return; @@ -391,7 +408,7 @@ void ReferenceTypePropagation::BoundTypeForIfNotNull(HBasicBlock* block) { : ifInstruction->IfFalseSuccessor(); ReferenceTypeInfo object_rti = ReferenceTypeInfo::Create( - handle_cache_.GetObjectClassHandle(), /* is_exact */ false); + handle_cache_->GetObjectClassHandle(), /* is_exact */ false); BoundTypeIn(obj, notNullBlock, /* start_instruction */ nullptr, object_rti); } @@ -469,7 +486,7 @@ static bool MatchIfInstanceOf(HIf* ifInstruction, // `if (x instanceof ClassX) { }` // If that's the case insert an HBoundType instruction to bound the type of `x` // to `ClassX` in the scope of the dominated blocks. -void ReferenceTypePropagation::BoundTypeForIfInstanceOf(HBasicBlock* block) { +void ReferenceTypePropagation::RTPVisitor::BoundTypeForIfInstanceOf(HBasicBlock* block) { HIf* ifInstruction = block->GetLastInstruction()->AsIf(); if (ifInstruction == nullptr) { return; @@ -728,7 +745,7 @@ void ReferenceTypePropagation::RTPVisitor::VisitCheckCast(HCheckCast* check_cast } } -void ReferenceTypePropagation::VisitPhi(HPhi* phi) { +void ReferenceTypePropagation::RTPVisitor::VisitPhi(HPhi* phi) { if (phi->IsDead() || phi->GetType() != DataType::Type::kReference) { return; } @@ -812,7 +829,7 @@ ReferenceTypeInfo ReferenceTypePropagation::MergeTypes(const ReferenceTypeInfo& return ReferenceTypeInfo::Create(result_type_handle, is_exact); } -void ReferenceTypePropagation::UpdateArrayGet(HArrayGet* instr, HandleCache* handle_cache) { +void ReferenceTypePropagation::RTPVisitor::UpdateArrayGet(HArrayGet* instr) { DCHECK_EQ(DataType::Type::kReference, instr->GetType()); ReferenceTypeInfo parent_rti = instr->InputAt(0)->GetReferenceTypeInfo(); @@ -823,7 +840,7 @@ void ReferenceTypePropagation::UpdateArrayGet(HArrayGet* instr, HandleCache* han Handle<mirror::Class> handle = parent_rti.GetTypeHandle(); if (handle->IsObjectArrayClass() && IsAdmissible(handle->GetComponentType())) { ReferenceTypeInfo::TypeHandle component_handle = - handle_cache->NewHandle(handle->GetComponentType()); + handle_cache_->NewHandle(handle->GetComponentType()); bool is_exact = component_handle->CannotBeAssignedFromOtherTypes(); instr->SetReferenceTypeInfo(ReferenceTypeInfo::Create(component_handle, is_exact)); } else { @@ -832,7 +849,7 @@ void ReferenceTypePropagation::UpdateArrayGet(HArrayGet* instr, HandleCache* han } } -bool ReferenceTypePropagation::UpdateReferenceTypeInfo(HInstruction* instr) { +bool ReferenceTypePropagation::RTPVisitor::UpdateReferenceTypeInfo(HInstruction* instr) { ScopedObjectAccess soa(Thread::Current()); ReferenceTypeInfo previous_rti = instr->GetReferenceTypeInfo(); @@ -848,7 +865,7 @@ bool ReferenceTypePropagation::UpdateReferenceTypeInfo(HInstruction* instr) { } else if (instr->IsArrayGet()) { // TODO: consider if it's worth "looking back" and binding the input object // to an array type. - UpdateArrayGet(instr->AsArrayGet(), &handle_cache_); + UpdateArrayGet(instr->AsArrayGet()); } else { LOG(FATAL) << "Invalid instruction (should not get here)"; } @@ -873,13 +890,13 @@ void ReferenceTypePropagation::RTPVisitor::VisitArrayGet(HArrayGet* instr) { } ScopedObjectAccess soa(Thread::Current()); - UpdateArrayGet(instr, handle_cache_); + UpdateArrayGet(instr); if (!instr->GetReferenceTypeInfo().IsValid()) { - worklist_->push_back(instr); + worklist_.push_back(instr); } } -void ReferenceTypePropagation::UpdateBoundType(HBoundType* instr) { +void ReferenceTypePropagation::RTPVisitor::UpdateBoundType(HBoundType* instr) { ReferenceTypeInfo input_rti = instr->InputAt(0)->GetReferenceTypeInfo(); if (!input_rti.IsValid()) { return; // No new info yet. @@ -903,7 +920,7 @@ void ReferenceTypePropagation::UpdateBoundType(HBoundType* instr) { // NullConstant inputs are ignored during merging as they do not provide any useful information. // If all the inputs are NullConstants then the type of the phi will be set to Object. -void ReferenceTypePropagation::UpdatePhi(HPhi* instr) { +void ReferenceTypePropagation::RTPVisitor::UpdatePhi(HPhi* instr) { DCHECK(instr->IsLive()); HInputsRef inputs = instr->GetInputs(); @@ -931,7 +948,7 @@ void ReferenceTypePropagation::UpdatePhi(HPhi* instr) { if (inputs[i]->IsNullConstant()) { continue; } - new_rti = MergeTypes(new_rti, inputs[i]->GetReferenceTypeInfo(), &handle_cache_); + new_rti = MergeTypes(new_rti, inputs[i]->GetReferenceTypeInfo(), handle_cache_); if (new_rti.IsValid() && new_rti.IsObjectClass()) { if (!new_rti.IsExact()) { break; @@ -948,7 +965,7 @@ void ReferenceTypePropagation::UpdatePhi(HPhi* instr) { // Re-computes and updates the nullability of the instruction. Returns whether or // not the nullability was changed. -bool ReferenceTypePropagation::UpdateNullability(HInstruction* instr) { +bool ReferenceTypePropagation::RTPVisitor::UpdateNullability(HInstruction* instr) { DCHECK((instr->IsPhi() && instr->AsPhi()->IsLive()) || instr->IsBoundType() || instr->IsNullCheck() @@ -976,7 +993,7 @@ bool ReferenceTypePropagation::UpdateNullability(HInstruction* instr) { return existing_can_be_null != instr->CanBeNull(); } -void ReferenceTypePropagation::ProcessWorklist() { +void ReferenceTypePropagation::RTPVisitor::ProcessWorklist() { while (!worklist_.empty()) { HInstruction* instruction = worklist_.back(); worklist_.pop_back(); @@ -988,13 +1005,14 @@ void ReferenceTypePropagation::ProcessWorklist() { } } -void ReferenceTypePropagation::AddToWorklist(HInstruction* instruction) { +void ReferenceTypePropagation::RTPVisitor::AddToWorklist(HInstruction* instruction) { DCHECK_EQ(instruction->GetType(), DataType::Type::kReference) << instruction->DebugName() << ":" << instruction->GetType(); worklist_.push_back(instruction); } -void ReferenceTypePropagation::AddDependentInstructionsToWorklist(HInstruction* instruction) { +void ReferenceTypePropagation::RTPVisitor::AddDependentInstructionsToWorklist( + HInstruction* instruction) { for (const HUseListNode<HInstruction*>& use : instruction->GetUses()) { HInstruction* user = use.GetUser(); if ((user->IsPhi() && user->AsPhi()->IsLive()) diff --git a/compiler/optimizing/reference_type_propagation.h b/compiler/optimizing/reference_type_propagation.h index c221282b9b..fd4dad2b45 100644 --- a/compiler/optimizing/reference_type_propagation.h +++ b/compiler/optimizing/reference_type_propagation.h @@ -18,12 +18,10 @@ #define ART_COMPILER_OPTIMIZING_REFERENCE_TYPE_PROPAGATION_H_ #include "base/arena_containers.h" -#include "driver/dex_compilation_unit.h" -#include "handle_scope-inl.h" +#include "mirror/class-inl.h" #include "nodes.h" #include "obj_ptr.h" #include "optimization.h" -#include "optimizing_compiler_stats.h" namespace art { @@ -91,22 +89,6 @@ class ReferenceTypePropagation : public HOptimization { class RTPVisitor; - void VisitPhi(HPhi* phi); - void VisitBasicBlock(HBasicBlock* block); - void UpdateBoundType(HBoundType* bound_type) REQUIRES_SHARED(Locks::mutator_lock_); - void UpdatePhi(HPhi* phi) REQUIRES_SHARED(Locks::mutator_lock_); - void BoundTypeForIfNotNull(HBasicBlock* block); - void BoundTypeForIfInstanceOf(HBasicBlock* block); - void ProcessWorklist(); - void AddToWorklist(HInstruction* instr); - void AddDependentInstructionsToWorklist(HInstruction* instr); - - bool UpdateNullability(HInstruction* instr); - bool UpdateReferenceTypeInfo(HInstruction* instr); - - static void UpdateArrayGet(HArrayGet* instr, HandleCache* handle_cache) - REQUIRES_SHARED(Locks::mutator_lock_); - static ReferenceTypeInfo MergeTypes(const ReferenceTypeInfo& a, const ReferenceTypeInfo& b, HandleCache* handle_cache) @@ -122,13 +104,9 @@ class ReferenceTypePropagation : public HOptimization { Handle<mirror::DexCache> hint_dex_cache_; HandleCache handle_cache_; - ArenaVector<HInstruction*> worklist_; - // Whether this reference type propagation is the first run we are doing. const bool is_first_run_; - static constexpr size_t kDefaultWorklistSize = 8; - friend class ReferenceTypePropagationTest; DISALLOW_COPY_AND_ASSIGN(ReferenceTypePropagation); diff --git a/compiler/optimizing/select_generator.cc b/compiler/optimizing/select_generator.cc index 0e46aeca37..77ec9a6285 100644 --- a/compiler/optimizing/select_generator.cc +++ b/compiler/optimizing/select_generator.cc @@ -16,6 +16,8 @@ #include "select_generator.h" +#include "reference_type_propagation.h" + namespace art { static constexpr size_t kMaxInstructionsInBranch = 1u; diff --git a/compiler/optimizing/select_generator.h b/compiler/optimizing/select_generator.h index c060146478..f8cf00e35a 100644 --- a/compiler/optimizing/select_generator.h +++ b/compiler/optimizing/select_generator.h @@ -58,7 +58,6 @@ #define ART_COMPILER_OPTIMIZING_SELECT_GENERATOR_H_ #include "optimization.h" -#include "reference_type_propagation.h" namespace art { diff --git a/runtime/base/arena_allocator.cc b/runtime/base/arena_allocator.cc index 79cf087082..2e35f8ac4f 100644 --- a/runtime/base/arena_allocator.cc +++ b/runtime/base/arena_allocator.cc @@ -72,6 +72,7 @@ const char* const ArenaAllocatorStatsImpl<kCount>::kAllocNames[] = { "InductionVar ", "BCE ", "DCE ", + "LSA ", "LSE ", "CFRE ", "LICM ", diff --git a/runtime/base/arena_allocator.h b/runtime/base/arena_allocator.h index 212edfbdb1..a327cb0a8b 100644 --- a/runtime/base/arena_allocator.h +++ b/runtime/base/arena_allocator.h @@ -79,6 +79,7 @@ enum ArenaAllocKind { kArenaAllocInductionVarAnalysis, kArenaAllocBoundsCheckElimination, kArenaAllocDCE, + kArenaAllocLSA, kArenaAllocLSE, kArenaAllocCFRE, kArenaAllocLICM, |