Use ScopedArenaAllocator in BCE, DCE, LSE, ...
... ReferenceTypePropagation and GraphChecker.
Define and use a new allocation kind for LoadStoreAnalysis.
Memory needed to compile the two most expensive methods for
aosp_angler-userdebug boot image:
BatteryStats.dumpCheckinLocked() : 19.7MiB -> 19.6MiB (-79KiB)
BatteryStats.dumpLocked(): 39.4MiB -> 39.3MiB (-120KiB)
Test: m test-art-host-gtest
Test: testrunner.py --host --optimizing
Bug: 64312607
Change-Id: Ib0cf074ac21ab67d8f8f2efabbdfb84cce9cae8e
diff --git a/compiler/optimizing/bounds_check_elimination.cc b/compiler/optimizing/bounds_check_elimination.cc
index 0255e73..9c2068e 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 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 @@
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 @@
}
private:
- ArenaAllocator* const allocator_;
+ ScopedArenaAllocator* const allocator_;
const ValueBound lower_; // inclusive
const ValueBound upper_; // inclusive
@@ -365,7 +366,7 @@
*/
class MonotonicValueRange : public ValueRange {
public:
- MonotonicValueRange(ArenaAllocator* allocator,
+ MonotonicValueRange(ScopedArenaAllocator* allocator,
HPhi* induction_variable,
HInstruction* initial,
int32_t increment,
@@ -510,21 +511,19 @@
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 @@
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 @@
// 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
// 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 @@
// 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 @@
// 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 @@
} 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 @@
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 @@
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 @@
!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 @@
// 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 @@
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 @@
// 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 @@
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 @@
// 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 @@
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 @@
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 @@
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 @@
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_;