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 =