Fix invalid switch generation in switch optimizer
Bug: b/236875523
Change-Id: I06dc2405a9fefb1f7669fcdd65c4715cd4429036
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/CodeRewriter.java b/src/main/java/com/android/tools/r8/ir/optimize/CodeRewriter.java
index 3c0854a..55c4950 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/CodeRewriter.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/CodeRewriter.java
@@ -922,20 +922,18 @@
if (options.testing.enableDeadSwitchCaseElimination) {
SwitchCaseEliminator eliminator =
removeUnnecessarySwitchCases(code, theSwitch, iterator, switchCaseAnalyzer);
- if (eliminator != null) {
- if (eliminator.mayHaveIntroducedUnreachableBlocks()) {
- needToRemoveUnreachableBlocks = true;
- }
-
- iterator.previous();
- instruction = iterator.next();
- if (instruction.isGoto()) {
- continue;
- }
-
- assert instruction.isSwitch();
- theSwitch = instruction.asSwitch();
+ if (eliminator.mayHaveIntroducedUnreachableBlocks()) {
+ needToRemoveUnreachableBlocks = true;
}
+
+ iterator.previous();
+ instruction = iterator.next();
+ if (instruction.isGoto()) {
+ continue;
+ }
+
+ assert instruction.isSwitch();
+ theSwitch = instruction.asSwitch();
}
if (theSwitch.isIntSwitch()) {
rewriteIntSwitch(code, blocksIterator, block, iterator, theSwitch.asIntSwitch());
@@ -1112,46 +1110,38 @@
InstructionListIterator iterator,
SwitchCaseAnalyzer switchCaseAnalyzer) {
BasicBlock defaultTarget = theSwitch.fallthroughBlock();
- SwitchCaseEliminator eliminator = null;
+ SwitchCaseEliminator eliminator = new SwitchCaseEliminator(theSwitch, iterator);
BasicBlockBehavioralSubsumption behavioralSubsumption =
new BasicBlockBehavioralSubsumption(appView, code);
// Compute the set of switch cases that can be removed.
+ boolean hasSwitchCaseToDefaultRewrite = false;
AbstractValue switchAbstractValue = theSwitch.value().getAbstractValue(appView, code.context());
for (int i = 0; i < theSwitch.numberOfKeys(); i++) {
BasicBlock targetBlock = theSwitch.targetBlock(i);
if (switchCaseAnalyzer.switchCaseIsAlwaysHit(theSwitch, i)) {
- if (eliminator == null) {
- eliminator = new SwitchCaseEliminator(theSwitch, iterator);
- }
eliminator.markSwitchCaseAsAlwaysHit(i);
break;
}
// This switch case can be removed if the behavior of the target block is equivalent to the
// behavior of the default block, or if the switch case is unreachable.
- if (switchCaseAnalyzer.switchCaseIsUnreachable(theSwitch, switchAbstractValue, i)
- || behavioralSubsumption.isSubsumedBy(targetBlock, defaultTarget)) {
- if (eliminator == null) {
- eliminator = new SwitchCaseEliminator(theSwitch, iterator);
- }
+ if (switchCaseAnalyzer.switchCaseIsUnreachable(theSwitch, switchAbstractValue, i)) {
eliminator.markSwitchCaseForRemoval(i);
+ } else if (behavioralSubsumption.isSubsumedBy(targetBlock, defaultTarget)) {
+ eliminator.markSwitchCaseForRemoval(i);
+ hasSwitchCaseToDefaultRewrite = true;
}
}
- if (eliminator == null || eliminator.isFallthroughLive()) {
- if (switchCaseAnalyzer.switchFallthroughIsNeverHit(theSwitch, switchAbstractValue)) {
- if (eliminator == null) {
- eliminator = new SwitchCaseEliminator(theSwitch, iterator);
- }
- eliminator.markSwitchFallthroughAsNeverHit();
- }
+ if (eliminator.isFallthroughLive()
+ && !hasSwitchCaseToDefaultRewrite
+ && switchCaseAnalyzer.switchFallthroughIsNeverHit(theSwitch, switchAbstractValue)) {
+ eliminator.markSwitchFallthroughAsNeverHit();
}
- if (eliminator != null) {
- eliminator.optimize();
- }
+ eliminator.optimize();
return eliminator;
}