summaryrefslogtreecommitdiff
path: root/compiler/optimizing/nodes.cc
diff options
context:
space:
mode:
author Vladimir Marko <vmarko@google.com> 2016-03-29 12:21:58 +0100
committer Vladimir Marko <vmarko@google.com> 2016-04-19 18:33:06 +0100
commit46817b876ab00d6b78905b80ed12b4344c522b6c (patch)
tree6715bee60b0682a10437866c9617cb442146aa2f /compiler/optimizing/nodes.cc
parentf59149a151ee694484e21da7b3b207920dead5a6 (diff)
Use iterators "before" the use node in HUserRecord<>.
Create a new template class IntrusiveForwardList<> that mimicks std::forward_list<> except that all allocations are handled externally. This is essentially the same as boost::intrusive::slist<> but since we're not using Boost we have to reinvent the wheel. Use the new container to replace the HUseList and use the iterators to "before" use nodes in HUserRecord<> to avoid the extra pointer to the previous node which was used exclusively for removing nodes from the list. This reduces the size of the HUseListNode by 25%, 32B to 24B in 64-bit compiler, 16B to 12B in 32-bit compiler. This translates directly to overall memory savings for the 64-bit compiler but due to rounding up of the arena allocations to 8B, we do not get any improvement in the 32-bit compiler. Compiling the Nexus 5 boot image with the 64-bit dex2oat on host this CL reduces the memory used for compiling the most hungry method, BatteryStats.dumpLocked(), by ~3.3MiB: Before: MEM: used: 47829200, allocated: 48769120, lost: 939920 Number of arenas allocated: 345, Number of allocations: 815492, avg size: 58 ... UseListNode 13744640 ... After: MEM: used: 44393040, allocated: 45361248, lost: 968208 Number of arenas allocated: 319, Number of allocations: 815492, avg size: 54 ... UseListNode 10308480 ... Note that while we do not ship the 64-bit dex2oat to the device, the JIT compilation for 64-bit processes is using the 64-bit libart-compiler. Bug: 28173563 Change-Id: I985eabd4816f845372d8aaa825a1489cf9569208
Diffstat (limited to 'compiler/optimizing/nodes.cc')
-rw-r--r--compiler/optimizing/nodes.cc77
1 files changed, 39 insertions, 38 deletions
diff --git a/compiler/optimizing/nodes.cc b/compiler/optimizing/nodes.cc
index 1afa36a89c..53a10f3128 100644
--- a/compiler/optimizing/nodes.cc
+++ b/compiler/optimizing/nodes.cc
@@ -681,8 +681,8 @@ void HBasicBlock::ReplaceAndRemoveInstructionWith(HInstruction* initial,
DCHECK_EQ(replacement->GetType(), Primitive::kPrimVoid);
DCHECK_EQ(initial->GetBlock(), this);
DCHECK_EQ(initial->GetType(), Primitive::kPrimVoid);
- DCHECK(initial->GetUses().IsEmpty());
- DCHECK(initial->GetEnvUses().IsEmpty());
+ DCHECK(initial->GetUses().empty());
+ DCHECK(initial->GetEnvUses().empty());
replacement->SetBlock(this);
replacement->SetId(GetGraph()->GetNextInstructionId());
instructions_.InsertInstructionBefore(replacement, initial);
@@ -774,8 +774,8 @@ static void Remove(HInstructionList* instruction_list,
instruction->SetBlock(nullptr);
instruction_list->RemoveInstruction(instruction);
if (ensure_safety) {
- DCHECK(instruction->GetUses().IsEmpty());
- DCHECK(instruction->GetEnvUses().IsEmpty());
+ DCHECK(instruction->GetUses().empty());
+ DCHECK(instruction->GetEnvUses().empty());
RemoveAsUser(instruction);
}
}
@@ -839,8 +839,11 @@ void HEnvironment::CopyFromWithLoopPhiAdjustment(HEnvironment* env,
}
void HEnvironment::RemoveAsUserOfInput(size_t index) const {
- const HUserRecord<HEnvironment*>& user_record = vregs_[index];
- user_record.GetInstruction()->RemoveEnvironmentUser(user_record.GetUseNode());
+ const HUserRecord<HEnvironment*>& env_use = vregs_[index];
+ HInstruction* user = env_use.GetInstruction();
+ auto before_env_use_node = env_use.GetBeforeUseNode();
+ user->env_uses_.erase_after(before_env_use_node);
+ user->FixUpUserRecordsAfterEnvUseRemoval(before_env_use_node);
}
HInstruction::InstructionKind HInstruction::GetKind() const {
@@ -985,24 +988,22 @@ void HInstruction::RemoveEnvironment() {
void HInstruction::ReplaceWith(HInstruction* other) {
DCHECK(other != nullptr);
- for (HUseIterator<HInstruction*> it(GetUses()); !it.Done(); it.Advance()) {
- HUseListNode<HInstruction*>* current = it.Current();
- HInstruction* user = current->GetUser();
- size_t input_index = current->GetIndex();
+ for (const HUseListNode<HInstruction*>& use : GetUses()) {
+ HInstruction* user = use.GetUser();
+ size_t input_index = use.GetIndex();
user->SetRawInputAt(input_index, other);
other->AddUseAt(user, input_index);
}
- for (HUseIterator<HEnvironment*> it(GetEnvUses()); !it.Done(); it.Advance()) {
- HUseListNode<HEnvironment*>* current = it.Current();
- HEnvironment* user = current->GetUser();
- size_t input_index = current->GetIndex();
+ for (const HUseListNode<HEnvironment*>& use : GetEnvUses()) {
+ HEnvironment* user = use.GetUser();
+ size_t input_index = use.GetIndex();
user->SetRawEnvAt(input_index, other);
other->AddEnvUseAt(user, input_index);
}
- uses_.Clear();
- env_uses_.Clear();
+ uses_.clear();
+ env_uses_.clear();
}
void HInstruction::ReplaceInput(HInstruction* replacement, size_t index) {
@@ -1280,17 +1281,18 @@ void HInstruction::MoveBeforeFirstUserAndOutOfLoops() {
DCHECK_EQ(InputCount(), 0u);
// Find the target block.
- HUseIterator<HInstruction*> uses_it(GetUses());
- HBasicBlock* target_block = uses_it.Current()->GetUser()->GetBlock();
- uses_it.Advance();
- while (!uses_it.Done() && uses_it.Current()->GetUser()->GetBlock() == target_block) {
- uses_it.Advance();
- }
- if (!uses_it.Done()) {
+ auto uses_it = GetUses().begin();
+ auto uses_end = GetUses().end();
+ HBasicBlock* target_block = uses_it->GetUser()->GetBlock();
+ ++uses_it;
+ while (uses_it != uses_end && uses_it->GetUser()->GetBlock() == target_block) {
+ ++uses_it;
+ }
+ if (uses_it != uses_end) {
// This instruction has uses in two or more blocks. Find the common dominator.
CommonDominator finder(target_block);
- for (; !uses_it.Done(); uses_it.Advance()) {
- finder.Update(uses_it.Current()->GetUser()->GetBlock());
+ for (; uses_it != uses_end; ++uses_it) {
+ finder.Update(uses_it->GetUser()->GetBlock());
}
target_block = finder.Get();
DCHECK(target_block != nullptr);
@@ -1303,10 +1305,10 @@ void HInstruction::MoveBeforeFirstUserAndOutOfLoops() {
// Find insertion position.
HInstruction* insert_pos = nullptr;
- for (HUseIterator<HInstruction*> uses_it2(GetUses()); !uses_it2.Done(); uses_it2.Advance()) {
- if (uses_it2.Current()->GetUser()->GetBlock() == target_block &&
- (insert_pos == nullptr || uses_it2.Current()->GetUser()->StrictlyDominates(insert_pos))) {
- insert_pos = uses_it2.Current()->GetUser();
+ for (const HUseListNode<HInstruction*>& use : GetUses()) {
+ if (use.GetUser()->GetBlock() == target_block &&
+ (insert_pos == nullptr || use.GetUser()->StrictlyDominates(insert_pos))) {
+ insert_pos = use.GetUser();
}
}
if (insert_pos == nullptr) {
@@ -1586,10 +1588,10 @@ void HInstructionList::Add(const HInstructionList& instruction_list) {
static void RemoveUsesOfDeadInstruction(HInstruction* insn) {
DCHECK(!insn->HasEnvironmentUses());
while (insn->HasNonEnvironmentUses()) {
- HUseListNode<HInstruction*>* use = insn->GetUses().GetFirst();
- size_t use_index = use->GetIndex();
- HBasicBlock* user_block = use->GetUser()->GetBlock();
- DCHECK(use->GetUser()->IsPhi() && user_block->IsCatchBlock());
+ const HUseListNode<HInstruction*>& use = insn->GetUses().front();
+ size_t use_index = use.GetIndex();
+ HBasicBlock* user_block = use.GetUser()->GetBlock();
+ DCHECK(use.GetUser()->IsPhi() && user_block->IsCatchBlock());
for (HInstructionIterator phi_it(user_block->GetPhis()); !phi_it.Done(); phi_it.Advance()) {
phi_it.Current()->AsPhi()->RemoveInputAt(use_index);
}
@@ -2391,12 +2393,11 @@ std::ostream& operator<<(std::ostream& os, HLoadString::LoadKind rhs) {
}
void HInstruction::RemoveEnvironmentUsers() {
- for (HUseIterator<HEnvironment*> use_it(GetEnvUses()); !use_it.Done(); use_it.Advance()) {
- HUseListNode<HEnvironment*>* user_node = use_it.Current();
- HEnvironment* user = user_node->GetUser();
- user->SetRawEnvAt(user_node->GetIndex(), nullptr);
+ for (const HUseListNode<HEnvironment*>& use : GetEnvUses()) {
+ HEnvironment* user = use.GetUser();
+ user->SetRawEnvAt(use.GetIndex(), nullptr);
}
- env_uses_.Clear();
+ env_uses_.clear();
}
// Returns an instruction with the opposite Boolean value from 'cond'.