Merge "Cache computed hash of basic block for equivalence"
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/BasicBlockInstructionsEquivalence.java b/src/main/java/com/android/tools/r8/ir/optimize/BasicBlockInstructionsEquivalence.java
index 27cf89a..9f833f0 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/BasicBlockInstructionsEquivalence.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/BasicBlockInstructionsEquivalence.java
@@ -5,19 +5,25 @@
 
 import com.android.tools.r8.ir.code.BasicBlock;
 import com.android.tools.r8.ir.code.CatchHandlers;
+import com.android.tools.r8.ir.code.IRCode;
 import com.android.tools.r8.ir.code.Instruction;
 import com.android.tools.r8.ir.code.Value;
 import com.android.tools.r8.ir.regalloc.RegisterAllocator;
 import com.google.common.base.Equivalence;
+import java.util.Arrays;
+import java.util.Comparator;
 import java.util.List;
 
 class BasicBlockInstructionsEquivalence extends Equivalence<BasicBlock> {
-
+  private static final int UNKNOW_HASH = -1;
   private static final int MAX_HASH_INSTRUCTIONS = 5;
   private final RegisterAllocator allocator;
+  private final int[] hashes;
 
-  BasicBlockInstructionsEquivalence(RegisterAllocator allocator) {
+  BasicBlockInstructionsEquivalence(IRCode code, RegisterAllocator allocator) {
     this.allocator = allocator;
+    hashes = new int[code.getHighestBlockNumber() + 1];
+    Arrays.fill(hashes, UNKNOW_HASH);
   }
 
   private boolean hasIdenticalInstructions(BasicBlock first, BasicBlock second) {
@@ -60,8 +66,23 @@
     return hasIdenticalInstructions(a, b);
   }
 
+  void clearComputedHash(BasicBlock basicBlock) {
+    hashes[basicBlock.getNumber()] = UNKNOW_HASH;
+  }
+
   @Override
   protected int doHash(BasicBlock basicBlock) {
+    int hash = hashes[basicBlock.getNumber()];
+    if (hash != UNKNOW_HASH) {
+      assert hash == computeHash(basicBlock);
+      return hash;
+    }
+    hash = computeHash(basicBlock);
+    hashes[basicBlock.getNumber()] = hash;
+    return hash;
+  }
+
+  private int computeHash(BasicBlock basicBlock) {
     List<Instruction> instructions = basicBlock.getInstructions();
     int hash = instructions.size();
     for (int i = 0; i < instructions.size() && i < MAX_HASH_INSTRUCTIONS; i++) {
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/PeepholeOptimizer.java b/src/main/java/com/android/tools/r8/ir/optimize/PeepholeOptimizer.java
index 4ad05cc..a7d6e8d 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/PeepholeOptimizer.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/PeepholeOptimizer.java
@@ -173,7 +173,7 @@
    */
   private static void removeIdenticalPredecessorBlocks(IRCode code, RegisterAllocator allocator) {
     BasicBlockInstructionsEquivalence equivalence =
-        new BasicBlockInstructionsEquivalence(allocator);
+        new BasicBlockInstructionsEquivalence(code, allocator);
     // Locate one block at a time that has identical predecessors. Rewrite those predecessors and
     // then start over. Restarting when one blocks predecessors have been rewritten simplifies
     // the rewriting and reduces the size of the data structures.
@@ -194,6 +194,7 @@
             BasicBlock otherPred = block.getPredecessors().get(otherPredIndex);
             pred.clearCatchHandlers();
             pred.getInstructions().clear();
+            equivalence.clearComputedHash(pred);
             for (BasicBlock succ : pred.getSuccessors()) {
               succ.removePredecessor(pred);
             }