Optimizing: Reduce GraphChecker memory usage.

Bug: 27690481
Change-Id: I15ce5524d94fc1780da02e6471bede66b3a1b82a
diff --git a/compiler/optimizing/graph_checker.cc b/compiler/optimizing/graph_checker.cc
index 9491ef6..2d220fc 100644
--- a/compiler/optimizing/graph_checker.cc
+++ b/compiler/optimizing/graph_checker.cc
@@ -17,7 +17,6 @@
 #include "graph_checker.h"
 
 #include <algorithm>
-#include <map>
 #include <string>
 #include <sstream>
 
@@ -32,19 +31,19 @@
   current_block_ = block;
 
   // Check consistency with respect to predecessors of `block`.
-  ArenaSafeMap<HBasicBlock*, size_t> predecessors_count(
-      std::less<HBasicBlock*>(), GetGraph()->GetArena()->Adapter(kArenaAllocGraphChecker));
-  for (HBasicBlock* p : block->GetPredecessors()) {
-    auto it = predecessors_count.find(p);
-    if (it != predecessors_count.end()) {
-      ++it->second;
-    } else {
-      predecessors_count.Put(p, 1u);
+  // Note: Counting duplicates with a sorted vector uses up to 6x less memory
+  // than ArenaSafeMap<HBasicBlock*, size_t>.
+  ArenaVector<HBasicBlock*> sorted_predecessors(
+      block->GetPredecessors().begin(),
+      block->GetPredecessors().end(),
+      GetGraph()->GetArena()->Adapter(kArenaAllocGraphChecker));
+  std::sort(sorted_predecessors.begin(), sorted_predecessors.end());
+  for (auto it = sorted_predecessors.begin(), end = sorted_predecessors.end(); it != end; ) {
+    HBasicBlock* p = *it++;
+    size_t p_count_in_block_predecessors = 1u;
+    for (; it != end && *it == p; ++it) {
+      ++p_count_in_block_predecessors;
     }
-  }
-  for (auto& pc : predecessors_count) {
-    HBasicBlock* p = pc.first;
-    size_t p_count_in_block_predecessors = pc.second;
     size_t block_count_in_p_successors =
         std::count(p->GetSuccessors().begin(), p->GetSuccessors().end(), block);
     if (p_count_in_block_predecessors != block_count_in_p_successors) {
@@ -57,19 +56,19 @@
   }
 
   // Check consistency with respect to successors of `block`.
-  ArenaSafeMap<HBasicBlock*, size_t> successors_count(
-      std::less<HBasicBlock*>(), GetGraph()->GetArena()->Adapter(kArenaAllocGraphChecker));
-  for (HBasicBlock* s : block->GetSuccessors()) {
-    auto it = successors_count.find(s);
-    if (it != successors_count.end()) {
-      ++it->second;
-    } else {
-      successors_count.Put(s, 1u);
+  // Note: Counting duplicates with a sorted vector uses up to 6x less memory
+  // than ArenaSafeMap<HBasicBlock*, size_t>.
+  ArenaVector<HBasicBlock*> sorted_successors(
+      block->GetSuccessors().begin(),
+      block->GetSuccessors().end(),
+      GetGraph()->GetArena()->Adapter(kArenaAllocGraphChecker));
+  std::sort(sorted_successors.begin(), sorted_successors.end());
+  for (auto it = sorted_successors.begin(), end = sorted_successors.end(); it != end; ) {
+    HBasicBlock* s = *it++;
+    size_t s_count_in_block_successors = 1u;
+    for (; it != end && *it == s; ++it) {
+      ++s_count_in_block_successors;
     }
-  }
-  for (auto& sc : successors_count) {
-    HBasicBlock* s = sc.first;
-    size_t s_count_in_block_successors = sc.second;
     size_t block_count_in_s_predecessors =
         std::count(s->GetPredecessors().begin(), s->GetPredecessors().end(), block);
     if (s_count_in_block_successors != block_count_in_s_predecessors) {