Follow chains of gotos in basic block behavioral subsumption analysis
Change-Id: I2698d784f2294fd5a77ddc4bf47855e4795131b8
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/equivalence/BasicBlockBehavioralSubsumption.java b/src/main/java/com/android/tools/r8/ir/analysis/equivalence/BasicBlockBehavioralSubsumption.java
index 94da205..674bdb8 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/equivalence/BasicBlockBehavioralSubsumption.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/equivalence/BasicBlockBehavioralSubsumption.java
@@ -96,11 +96,24 @@
// If the current instruction is not a goto instruction, but the other instruction is, then
// we continue the search from the target of the other goto instruction.
- if (otherInstruction.isGoto()) {
+ Set<BasicBlock> otherVisited = null;
+ while (otherInstruction.isGoto()) {
+ BasicBlock block = otherInstruction.getBlock();
+ if (otherVisited != null && !otherVisited.add(block)) {
+ // Guard against cycles in the control flow graph.
+ return false;
+ }
+
otherIterator = otherInstruction.asGoto().getTarget().iterator();
otherInstruction =
otherIterator.nextUntil(
or(this::instructionMayHaveSideEffects, Instruction::isJumpInstruction));
+
+ // If following the first goto instruction leads to another goto instruction, then we need to
+ // keep track of the set of visited blocks to guard against cycles in the control flow graph.
+ if (otherInstruction.isGoto() && otherVisited == null) {
+ otherVisited = SetUtils.newIdentityHashSet(block);
+ }
}
if (instruction.isReturn()) {