Reduce memory usage of SSA Phi elimination and make it faster.
Use an ArenaBitVector instead of an ArenaSet<> that leaks
its allocated memory on clear(). We were also erroneously
using the O(n) helper ContainsElement() for the ArenaSet<>
instead of the O(log n) ArenaSet<>::find() which made the
methods with large number of processed Phis also very slow
to compile in addition to the enormous memory usage.
Bug: 28684584
Change-Id: Idc7604e51cfae643debd0378baf828a1430ec14c
diff --git a/compiler/optimizing/ssa_phi_elimination.cc b/compiler/optimizing/ssa_phi_elimination.cc
index 44bcadf..c67612e 100644
--- a/compiler/optimizing/ssa_phi_elimination.cc
+++ b/compiler/optimizing/ssa_phi_elimination.cc
@@ -17,6 +17,7 @@
#include "ssa_phi_elimination.h"
#include "base/arena_containers.h"
+#include "base/arena_bit_vector.h"
#include "base/bit_vector-inl.h"
namespace art {
@@ -127,8 +128,10 @@
}
}
- ArenaSet<uint32_t> visited_phis_in_cycle(
- graph_->GetArena()->Adapter(kArenaAllocSsaPhiElimination));
+ ArenaBitVector visited_phis_in_cycle(graph_->GetArena(),
+ graph_->GetCurrentInstructionId(),
+ /* expandable */ false,
+ kArenaAllocSsaPhiElimination);
ArenaVector<HPhi*> cycle_worklist(graph_->GetArena()->Adapter(kArenaAllocSsaPhiElimination));
while (!worklist_.empty()) {
@@ -147,11 +150,11 @@
}
HInstruction* candidate = nullptr;
- visited_phis_in_cycle.clear();
+ visited_phis_in_cycle.ClearAllBits();
cycle_worklist.clear();
cycle_worklist.push_back(phi);
- visited_phis_in_cycle.insert(phi->GetId());
+ visited_phis_in_cycle.SetBit(phi->GetId());
bool catch_phi_in_cycle = phi->IsCatchPhi();
bool irreducible_loop_phi_in_cycle = phi->IsIrreducibleLoopHeaderPhi();
@@ -183,9 +186,9 @@
if (input == current) {
continue;
} else if (input->IsPhi()) {
- if (!ContainsElement(visited_phis_in_cycle, input->GetId())) {
+ if (!visited_phis_in_cycle.IsBitSet(input->GetId())) {
cycle_worklist.push_back(input->AsPhi());
- visited_phis_in_cycle.insert(input->GetId());
+ visited_phis_in_cycle.SetBit(input->GetId());
catch_phi_in_cycle |= input->AsPhi()->IsCatchPhi();
irreducible_loop_phi_in_cycle |= input->IsIrreducibleLoopHeaderPhi();
} else {
@@ -234,7 +237,7 @@
// for elimination. Add phis that use this phi to the worklist.
for (const HUseListNode<HInstruction*>& use : current->GetUses()) {
HInstruction* user = use.GetUser();
- if (user->IsPhi() && !ContainsElement(visited_phis_in_cycle, user->GetId())) {
+ if (user->IsPhi() && !visited_phis_in_cycle.IsBitSet(user->GetId())) {
worklist_.push_back(user->AsPhi());
}
}