Skip visited blocks already seen when munching
Bug: 172781146
Change-Id: I21bb56971ddf61c4fee1891eb863a3db647418f4
diff --git a/src/main/java/com/android/tools/r8/ir/code/LinearFlowInstructionListIterator.java b/src/main/java/com/android/tools/r8/ir/code/LinearFlowInstructionListIterator.java
index 0dd2895..889089f 100644
--- a/src/main/java/com/android/tools/r8/ir/code/LinearFlowInstructionListIterator.java
+++ b/src/main/java/com/android/tools/r8/ir/code/LinearFlowInstructionListIterator.java
@@ -12,6 +12,7 @@
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.utils.InternalOptions;
+import com.google.common.collect.Sets;
import java.util.ListIterator;
import java.util.Set;
@@ -21,6 +22,7 @@
private BasicBlock currentBlock;
private InstructionListIterator currentBlockIterator;
+ private Set<BasicBlock> seenBlocks = Sets.newIdentityHashSet();
public LinearFlowInstructionListIterator(IRCode code, BasicBlock block) {
this(code, block, 0);
@@ -32,12 +34,17 @@
this.currentBlockIterator = block.listIterator(code, index);
// If index is pointing after the last instruction, and it is a goto with a linear edge,
// we have to move the pointer. This is achieved by calling previous and next.
+ seenBlocks.add(block);
if (index > 0) {
this.previous();
this.next();
}
}
+ public boolean hasVisitedBlock(BasicBlock basicBlock) {
+ return seenBlocks.contains(basicBlock);
+ }
+
@Override
public void replaceCurrentInstruction(Instruction newInstruction, Set<Value> affectedValues) {
currentBlockIterator.replaceCurrentInstruction(newInstruction, affectedValues);
@@ -146,6 +153,7 @@
target = candidate;
}
currentBlock = target;
+ seenBlocks.add(target);
currentBlockIterator = currentBlock.listIterator(code);
return currentBlockIterator.next();
}
@@ -183,6 +191,7 @@
return currentBlockIterator.previous();
}
currentBlock = target;
+ seenBlocks.add(target);
currentBlockIterator = currentBlock.listIterator(code, currentBlock.getInstructions().size());
// Iterate over the jump.
currentBlockIterator.previous();
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/peepholes/BasicBlockMuncher.java b/src/main/java/com/android/tools/r8/ir/optimize/peepholes/BasicBlockMuncher.java
index fc48072..b196de9 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/peepholes/BasicBlockMuncher.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/peepholes/BasicBlockMuncher.java
@@ -5,13 +5,14 @@
package com.android.tools.r8.ir.optimize.peepholes;
import static com.android.tools.r8.utils.InternalOptions.TestingOptions.NO_LIMIT;
+import static com.android.tools.r8.utils.PredicateUtils.not;
import com.android.tools.r8.errors.CompilationError;
import com.android.tools.r8.ir.code.BasicBlock;
import com.android.tools.r8.ir.code.IRCode;
-import com.android.tools.r8.ir.code.InstructionListIterator;
import com.android.tools.r8.ir.code.LinearFlowInstructionListIterator;
import com.android.tools.r8.utils.InternalOptions;
+import com.android.tools.r8.utils.IteratorUtils;
import com.google.common.collect.ImmutableList;
import java.util.List;
import java.util.ListIterator;
@@ -45,7 +46,7 @@
int iterations = 0;
while (blocksIterator.hasPrevious()) {
BasicBlock currentBlock = blocksIterator.previous();
- InstructionListIterator it =
+ LinearFlowInstructionListIterator it =
new LinearFlowInstructionListIterator(
code, currentBlock, currentBlock.getInstructions().size());
boolean matched = false;
@@ -74,6 +75,11 @@
new LinearFlowInstructionListIterator(
code, currentBlock, currentBlock.getInstructions().size());
} else {
+ // Move the iterator to the first block we have not seen.
+ if (IteratorUtils.previousUntilUnsafe(blocksIterator, not(it::hasVisitedBlock)) != null) {
+ // Ensure that we visit the first not visited block.
+ blocksIterator.next();
+ }
break;
}
}
diff --git a/src/main/java/com/android/tools/r8/utils/IteratorUtils.java b/src/main/java/com/android/tools/r8/utils/IteratorUtils.java
index 2ebce28..35f950a 100644
--- a/src/main/java/com/android/tools/r8/utils/IteratorUtils.java
+++ b/src/main/java/com/android/tools/r8/utils/IteratorUtils.java
@@ -87,6 +87,16 @@
throw new Unreachable();
}
+ public static <T> T previousUntilUnsafe(ListIterator<T> iterator, Predicate<T> predicate) {
+ while (iterator.hasPrevious()) {
+ T previous = iterator.previous();
+ if (predicate.test(previous)) {
+ return previous;
+ }
+ }
+ return null;
+ }
+
public static <T> T removeFirst(Iterator<T> iterator, Predicate<T> predicate) {
while (iterator.hasNext()) {
T item = iterator.next();