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);
}