OSDN Git Service

Reduce memory usage of SSA Phi elimination and make it faster.
authorVladimir Marko <vmarko@google.com>
Tue, 10 May 2016 12:31:23 +0000 (13:31 +0100)
committerVladimir Marko <vmarko@google.com>
Tue, 10 May 2016 13:50:41 +0000 (14:50 +0100)
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

(cherry picked from commit c9ef168bfabd118d112a054dffe2c27d4d4db4fc)

Change-Id: I6115006259a9f697ea70e31d4478966fc601e24b

compiler/optimizing/ssa_phi_elimination.cc

index 44bcadf..c67612e 100644 (file)
@@ -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 @@ void SsaRedundantPhiElimination::Run() {
     }
   }
 
-  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 @@ void SsaRedundantPhiElimination::Run() {
     }
 
     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 @@ void SsaRedundantPhiElimination::Run() {
           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 @@ void SsaRedundantPhiElimination::Run() {
       // 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());
         }
       }