Reapply "Remove unreachable blocks after lir lens rewriting"
This reverts commit 8ffb6489f2ea064b57fd3fb815127e35310f1e97.
Change-Id: I3ff80137b575be21276ba1dda1ce184b2dacc552
diff --git a/src/main/java/com/android/tools/r8/graph/lens/GraphLens.java b/src/main/java/com/android/tools/r8/graph/lens/GraphLens.java
index aad4cc2..05bf1b7 100644
--- a/src/main/java/com/android/tools/r8/graph/lens/GraphLens.java
+++ b/src/main/java/com/android/tools/r8/graph/lens/GraphLens.java
@@ -401,6 +401,10 @@
return false;
}
+ public final boolean isClassMergerLens() {
+ return isHorizontalClassMergerGraphLens() || isVerticalClassMergerLens();
+ }
+
public boolean isClearCodeRewritingLens() {
return false;
}
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/LirConverter.java b/src/main/java/com/android/tools/r8/ir/conversion/LirConverter.java
index f1c8a4336..2c7d62b 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/LirConverter.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/LirConverter.java
@@ -179,11 +179,6 @@
}
IRCode irCode = method.buildIR(appView, MethodConversionOptions.forPostLirPhase(appView));
assert irCode.verifyInvokeInterface(appView);
- if (lirCode.hasTryCatchTable()) {
- // Vertical class merging may lead to dead catch handlers.
- // TODO(b/322762660): Ensure IR is valid immediately after IR building.
- irCode.removeUnreachableBlocks();
- }
FilledNewArrayRewriter filledNewArrayRewriter = new FilledNewArrayRewriter(appView);
boolean changed = filledNewArrayRewriter.run(irCode, onThreadTiming).hasChanged().toBoolean();
if (appView.options().isGeneratingDex() && changed) {
diff --git a/src/main/java/com/android/tools/r8/lightir/LirCode.java b/src/main/java/com/android/tools/r8/lightir/LirCode.java
index cbe9cc2..a571e49 100644
--- a/src/main/java/com/android/tools/r8/lightir/LirCode.java
+++ b/src/main/java/com/android/tools/r8/lightir/LirCode.java
@@ -38,6 +38,7 @@
import com.android.tools.r8.utils.ComparatorUtils;
import com.android.tools.r8.utils.FastMapUtils;
import com.android.tools.r8.utils.IntBox;
+import com.android.tools.r8.utils.IntObjPredicate;
import com.android.tools.r8.utils.InternalOptions;
import com.android.tools.r8.utils.RetracerForCodePrinting;
import com.android.tools.r8.utils.structural.CompareToVisitor;
@@ -47,6 +48,7 @@
import com.android.tools.r8.utils.structural.StructuralMapping;
import com.android.tools.r8.utils.structural.StructuralSpecification;
import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Iterables;
import it.unimi.dsi.fastutil.ints.Int2ReferenceMap;
import it.unimi.dsi.fastutil.ints.Int2ReferenceOpenHashMap;
import java.util.ArrayList;
@@ -183,6 +185,12 @@
this.tryCatchHandlers = new Int2ReferenceOpenHashMap<>(tryCatchHandlers);
}
+ public boolean hasHandlerThatMatches(IntObjPredicate<CatchHandlers<Integer>> predicate) {
+ return Iterables.any(
+ tryCatchHandlers.int2ReferenceEntrySet(),
+ entry -> predicate.test(entry.getIntKey(), entry.getValue()));
+ }
+
public CatchHandlers<Integer> getHandlersForBlock(int blockIndex) {
return tryCatchHandlers.get(blockIndex);
}
diff --git a/src/main/java/com/android/tools/r8/lightir/LirLensCodeRewriter.java b/src/main/java/com/android/tools/r8/lightir/LirLensCodeRewriter.java
index 12bb785..b4a6cb7 100644
--- a/src/main/java/com/android/tools/r8/lightir/LirLensCodeRewriter.java
+++ b/src/main/java/com/android/tools/r8/lightir/LirLensCodeRewriter.java
@@ -31,6 +31,7 @@
import com.android.tools.r8.ir.conversion.LensCodeRewriterUtils;
import com.android.tools.r8.ir.conversion.MethodConversionOptions;
import com.android.tools.r8.ir.conversion.MethodProcessor;
+import com.android.tools.r8.ir.optimize.AffectedValues;
import com.android.tools.r8.ir.optimize.DeadCodeRemover;
import com.android.tools.r8.lightir.LirBuilder.RecordFieldValuesPayload;
import com.android.tools.r8.lightir.LirCode.TryCatchTable;
@@ -248,7 +249,13 @@
return rewriteWithLensCodeRewriter();
}
rewritten = rewriteInstructionsWithInvokeTypeChanges(rewritten);
- return rewriteTryCatchTable(rewritten);
+ rewritten = rewriteTryCatchTable(rewritten);
+ // In the unusual case where a catch handler has been eliminated as a result of class merging
+ // we remove the unreachable blocks.
+ if (hasPrunedCatchHandlers(rewritten)) {
+ rewritten = removeUnreachableBlocks(rewritten);
+ }
+ return rewritten;
}
private boolean hasNonTrivialMethodChanges() {
@@ -269,6 +276,42 @@
return false;
}
+ private boolean hasPrunedCatchHandlers(LirCode<EV> rewritten) {
+ if (!getCode().hasTryCatchTable()) {
+ return false;
+ }
+ if (!appView.graphLens().isClassMergerLens()) {
+ assert !internalHasPrunedCatchHandlers(rewritten);
+ return false;
+ }
+ return internalHasPrunedCatchHandlers(rewritten);
+ }
+
+ private boolean internalHasPrunedCatchHandlers(LirCode<EV> rewritten) {
+ TryCatchTable tryCatchTable = getCode().getTryCatchTable();
+ TryCatchTable rewrittenTryCatchTable = rewritten.getTryCatchTable();
+ return tryCatchTable.hasHandlerThatMatches(
+ (blockIndex, handlers) ->
+ handlers.size() > rewrittenTryCatchTable.getHandlersForBlock(blockIndex).size());
+ }
+
+ @SuppressWarnings("unchecked")
+ private LirCode<EV> removeUnreachableBlocks(LirCode<EV> rewritten) {
+ IRCode code =
+ rewritten.buildIR(
+ context,
+ appView,
+ MethodConversionOptions.forLirPhase(appView).disableStringSwitchConversion());
+ AffectedValues affectedValues = code.removeUnreachableBlocks();
+ affectedValues.narrowingWithAssumeRemoval(appView, code);
+ DeadCodeRemover deadCodeRemover = new DeadCodeRemover(appView);
+ deadCodeRemover.run(code, Timing.empty());
+ LirCode<Integer> result =
+ new IRToLirFinalizer(appView, deadCodeRemover)
+ .finalizeCode(code, BytecodeMetadataProvider.empty(), Timing.empty());
+ return (LirCode<EV>) result;
+ }
+
@SuppressWarnings("unchecked")
private LirCode<EV> rewriteWithLensCodeRewriter() {
IRCode code =