Fix invalid code generation in predecessor block sharing
Change-Id: Id45107a8b64d2da7d099156314632ba8561ac436
diff --git a/src/main/java/com/android/tools/r8/ir/code/BasicBlock.java b/src/main/java/com/android/tools/r8/ir/code/BasicBlock.java
index c926852..4059618 100644
--- a/src/main/java/com/android/tools/r8/ir/code/BasicBlock.java
+++ b/src/main/java/com/android/tools/r8/ir/code/BasicBlock.java
@@ -1378,6 +1378,15 @@
return blockIndex >= 0 && blockIndex < numberOfExceptionalSuccessors;
}
+ public boolean isCatchHandler() {
+ for (BasicBlock predecessor : predecessors) {
+ if (predecessor.hasCatchSuccessor(this)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
public int guardsForCatchSuccessor(BasicBlock block) {
assert hasCatchSuccessor(block);
int index = successors.indexOf(block);
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 b562fbb..e24d296 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
@@ -3,6 +3,7 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.ir.optimize;
+import static com.android.tools.r8.ir.conversion.passes.TrivialGotosCollapser.unlinkTrivialGotoBlock;
import static com.android.tools.r8.ir.regalloc.LiveIntervals.NO_REGISTER;
import com.android.tools.r8.graph.AppView;
@@ -467,6 +468,7 @@
* with a goto to the other.
*/
public static void removeIdenticalPredecessorBlocks(IRCode code, RegisterAllocator allocator) {
+ Set<BasicBlock> blocksToRemove = Sets.newIdentityHashSet();
BasicBlockInstructionsEquivalence equivalence =
new BasicBlockInstructionsEquivalence(code, allocator);
// Locate one block at a time that has identical predecessors. Rewrite those predecessors and
@@ -503,12 +505,20 @@
Goto exit = new Goto();
exit.setPosition(otherPred.getPosition());
pred.getInstructions().addLast(exit);
+
+ // If `otherPred` is a catch handler, then we cannot `goto otherPred`. In this case we
+ // therefore eliminate the goto and remove the `pred` block.
+ if (pred.isCatchHandler()) {
+ unlinkTrivialGotoBlock(pred, otherPred);
+ blocksToRemove.add(pred);
+ }
} else {
blockToIndex.put(wrapper, predIndex);
}
}
}
} while (changed);
+ code.removeBlocks(blocksToRemove);
}
/**