Unify treatment of catch-all and catch Throwable handlers.

With this CL we treat both catch-all and catch-Throwable as the terminal case in
a catch handler set. Internally a catch-all is always represented with the guard
type java.lang.Throwable. When emitting code the catch-all encoding is used in
the respective output formats.

Bug: 124838685
Change-Id: Ib84d0b41026d5c5430d72bb1ed586e009f9f8fa2
diff --git a/src/main/java/com/android/tools/r8/cf/CfPrinter.java b/src/main/java/com/android/tools/r8/cf/CfPrinter.java
index 5be17c6..1f62c88 100644
--- a/src/main/java/com/android/tools/r8/cf/CfPrinter.java
+++ b/src/main/java/com/android/tools/r8/cf/CfPrinter.java
@@ -162,7 +162,7 @@
         assert guard != null;
         builder
             .append(".catch ")
-            .append(guard == DexItemFactory.catchAllType ? "all" : guard.getInternalName())
+            .append(guard.getInternalName()) // Do we wan't to write 'all' here?
             .append(" from ")
             .append(getLabel(tryCatch.start))
             .append(" to ")
diff --git a/src/main/java/com/android/tools/r8/graph/CfCode.java b/src/main/java/com/android/tools/r8/graph/CfCode.java
index 2042392..6abc3fd 100644
--- a/src/main/java/com/android/tools/r8/graph/CfCode.java
+++ b/src/main/java/com/android/tools/r8/graph/CfCode.java
@@ -174,7 +174,9 @@
             start,
             end,
             target,
-            guard == DexItemFactory.catchAllType ? null : namingLens.lookupInternalName(guard));
+            guard == options.itemFactory.throwableType
+                ? null
+                : namingLens.lookupInternalName(guard));
       }
     }
     for (LocalVariableInfo localVariable : localVariables) {
@@ -280,9 +282,7 @@
     }
     for (CfTryCatch tryCatch : tryCatchRanges) {
       for (DexType guard : tryCatch.guards) {
-        if (guard != DexItemFactory.catchAllType) {
-          registry.registerTypeReference(guard);
-        }
+        registry.registerTypeReference(guard);
       }
     }
   }
diff --git a/src/main/java/com/android/tools/r8/graph/DexItemFactory.java b/src/main/java/com/android/tools/r8/graph/DexItemFactory.java
index 0e58ec0..035b472 100644
--- a/src/main/java/com/android/tools/r8/graph/DexItemFactory.java
+++ b/src/main/java/com/android/tools/r8/graph/DexItemFactory.java
@@ -49,6 +49,8 @@
 
 public class DexItemFactory {
 
+  public static final String throwableDescriptorString = "Ljava/lang/Throwable;";
+
   private final ConcurrentHashMap<DexString, DexString> strings = new ConcurrentHashMap<>();
   private final ConcurrentHashMap<DexString, DexType> types = new ConcurrentHashMap<>();
   private final ConcurrentHashMap<DexField, DexField> fields = new ConcurrentHashMap<>();
@@ -76,8 +78,6 @@
 
   boolean sorted = false;
 
-  public static final DexType catchAllType = new DexType(new DexString("CATCH_ALL"));
-
   // Internal type containing only the null value.
   public static final DexType nullValueType = new DexType(new DexString("NULL"));
 
@@ -86,7 +86,6 @@
   private static final IdentityHashMap<DexItem, DexItem> internalSentinels =
       new IdentityHashMap<>(
           ImmutableMap.of(
-              catchAllType, catchAllType,
               nullValueType, nullValueType,
               unknownTypeName, unknownTypeName));
 
@@ -178,7 +177,7 @@
   public final DexString methodDescriptor = createString("Ljava/lang/reflect/Method;");
   public final DexString enumDescriptor = createString("Ljava/lang/Enum;");
   public final DexString annotationDescriptor = createString("Ljava/lang/annotation/Annotation;");
-  public final DexString throwableDescriptor = createString("Ljava/lang/Throwable;");
+  public final DexString throwableDescriptor = createString(throwableDescriptorString);
   public final DexString exceptionInInitializerErrorDescriptor =
       createString("Ljava/lang/ExceptionInInitializerError;");
   public final DexString objectsDescriptor = createString("Ljava/util/Objects;");
diff --git a/src/main/java/com/android/tools/r8/graph/LazyCfCode.java b/src/main/java/com/android/tools/r8/graph/LazyCfCode.java
index fa03827..a09ba4f 100644
--- a/src/main/java/com/android/tools/r8/graph/LazyCfCode.java
+++ b/src/main/java/com/android/tools/r8/graph/LazyCfCode.java
@@ -819,7 +819,7 @@
     public void visitTryCatchBlock(Label start, Label end, Label handler, String type) {
       List<DexType> guards =
           Collections.singletonList(
-              type == null ? DexItemFactory.catchAllType : createTypeFromInternalType(type));
+              type == null ? factory.throwableType : createTypeFromInternalType(type));
       List<CfLabel> targets = Collections.singletonList(getLabel(handler));
       tryCatchRanges.add(new CfTryCatch(getLabel(start), getLabel(end), guards, targets));
     }
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/ClassInitializationAnalysis.java b/src/main/java/com/android/tools/r8/ir/analysis/ClassInitializationAnalysis.java
index a19d070..9532404 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/ClassInitializationAnalysis.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/ClassInitializationAnalysis.java
@@ -191,10 +191,6 @@
       }
 
       DexType guard = catchHandler.guard;
-      if (guard == DexItemFactory.catchAllType) {
-        return AnalysisAssumption.NONE;
-      }
-
       if (exceptionalExit.isInstanceGet()
           || exceptionalExit.isInstancePut()
           || exceptionalExit.isInvokeMethodWithReceiver()) {
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 589b650..47013dd 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
@@ -854,7 +854,8 @@
       List<DexType> guards = catchHandlers.getGuards();
       int lastGuardIndex = guards.size() - 1;
       for (int i = 0; i < guards.size(); i++) {
-        assert guards.get(i) != DexItemFactory.catchAllType || i == lastGuardIndex;
+        assert !guards.get(i).toDescriptorString().equals(DexItemFactory.throwableDescriptorString)
+            || i == lastGuardIndex;
       }
       // Check that all successors except maybe the last are catch successors.
       List<Integer> sortedHandlerIndices = new ArrayList<>(catchHandlers.getAllTargets());
@@ -1533,7 +1534,7 @@
       ListIterator<BasicBlock> blockIterator,
       BasicBlock fromBlock,
       InternalOptions options) {
-    if (catchHandlers != null && catchHandlers.hasCatchAll()) {
+    if (catchHandlers != null && catchHandlers.hasCatchAll(options.itemFactory)) {
       return;
     }
     List<BasicBlock> catchSuccessors = appendCatchHandlers(fromBlock);
diff --git a/src/main/java/com/android/tools/r8/ir/code/CatchHandlers.java b/src/main/java/com/android/tools/r8/ir/code/CatchHandlers.java
index 34926fa..237c0cc 100644
--- a/src/main/java/com/android/tools/r8/ir/code/CatchHandlers.java
+++ b/src/main/java/com/android/tools/r8/ir/code/CatchHandlers.java
@@ -71,9 +71,9 @@
     return uniqueTargets;
   }
 
-  public boolean hasCatchAll() {
-    return getGuards().size() > 0 &&
-        getGuards().get(getGuards().size() - 1) == DexItemFactory.catchAllType;
+  public boolean hasCatchAll(DexItemFactory factory) {
+    return getGuards().size() > 0
+        && getGuards().get(getGuards().size() - 1) == factory.throwableType;
   }
 
   public CatchHandlers<T> removeGuard(DexType guardToBeRemoved) {
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/CfSourceCode.java b/src/main/java/com/android/tools/r8/ir/conversion/CfSourceCode.java
index 2c10fbd..661d3e9 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/CfSourceCode.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/CfSourceCode.java
@@ -79,7 +79,8 @@
     static TryHandlerList computeTryHandlers(
         int instructionOffset,
         List<CfTryCatch> tryCatchRanges,
-        Reference2IntMap<CfLabel> labelOffsets) {
+        Reference2IntMap<CfLabel> labelOffsets,
+        DexItemFactory factory) {
       int startOffset = Integer.MIN_VALUE;
       int endOffset = Integer.MAX_VALUE;
       List<DexType> guards = new ArrayList<>();
@@ -103,7 +104,7 @@
           if (seen.add(guard)) {
             guards.add(guard);
             offsets.add(labelOffsets.getInt(tryCatch.targets.get(i)));
-            seenCatchAll = guard == DexItemFactory.catchAllType;
+            seenCatchAll = guard == factory.throwableType;
           }
         }
         if (seenCatchAll) {
@@ -266,7 +267,7 @@
     CfInstruction instruction = code.getInstructions().get(instructionIndex);
     assert builder.isGeneratingClassFiles() == internalOutputMode.isGeneratingClassFiles();
     if (canThrowHelper(instruction)) {
-      TryHandlerList tryHandlers = getTryHandlers(instructionIndex);
+      TryHandlerList tryHandlers = getTryHandlers(instructionIndex, builder.getFactory());
       if (!tryHandlers.isEmpty()) {
         // Ensure the block starts at the start of the try-range (don't enqueue, not a target).
         builder.ensureBlockWithoutEnqueuing(tryHandlers.startOffset);
@@ -295,11 +296,11 @@
     return -1;
   }
 
-  private TryHandlerList getTryHandlers(int instructionOffset) {
+  private TryHandlerList getTryHandlers(int instructionOffset, DexItemFactory factory) {
     if (cachedTryHandlerList == null || !cachedTryHandlerList.validFor(instructionOffset)) {
       cachedTryHandlerList =
           TryHandlerList.computeTryHandlers(
-              instructionOffset, code.getTryCatchRanges(), labelOffsets);
+              instructionOffset, code.getTryCatchRanges(), labelOffsets, factory);
     }
     return cachedTryHandlerList;
   }
@@ -623,8 +624,9 @@
   }
 
   @Override
-  public CatchHandlers<Integer> getCurrentCatchHandlers() {
-    TryHandlerList tryHandlers = getTryHandlers(instructionOffset(currentInstructionIndex));
+  public CatchHandlers<Integer> getCurrentCatchHandlers(IRBuilder builder) {
+    TryHandlerList tryHandlers =
+        getTryHandlers(instructionOffset(currentInstructionIndex), builder.getFactory());
     if (tryHandlers.isEmpty()) {
       return null;
     }
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/DexBuilder.java b/src/main/java/com/android/tools/r8/ir/conversion/DexBuilder.java
index ec2fe4c..6fbe1e2 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/DexBuilder.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/DexBuilder.java
@@ -42,7 +42,6 @@
 import com.android.tools.r8.graph.DexCode.TryHandler;
 import com.android.tools.r8.graph.DexCode.TryHandler.TypeAddrPair;
 import com.android.tools.r8.graph.DexDebugEventBuilder;
-import com.android.tools.r8.graph.DexItemFactory;
 import com.android.tools.r8.graph.DexType;
 import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
 import com.android.tools.r8.ir.code.Argument;
@@ -803,7 +802,7 @@
         DexType type = handlerGroup.getGuards().get(i);
         BasicBlock target = handlerGroup.getAllTargets().get(i);
         int targetOffset = getInfo(target.entry()).getOffset();
-        if (type == DexItemFactory.catchAllType) {
+        if (type == options.itemFactory.throwableType) {
           assert i == handlerGroup.getGuards().size() - 1;
           catchAllOffset = targetOffset;
         } else {
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/DexSourceCode.java b/src/main/java/com/android/tools/r8/ir/conversion/DexSourceCode.java
index 4738403..0790018 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/DexSourceCode.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/DexSourceCode.java
@@ -53,6 +53,7 @@
 import java.util.ListIterator;
 import java.util.Map;
 import java.util.Set;
+import java.util.function.BiConsumer;
 
 public class DexSourceCode implements SourceCode {
 
@@ -202,14 +203,14 @@
   @Override
   public void buildInstruction(
       IRBuilder builder, int instructionIndex, boolean firstBlockInstruction) {
-    updateCurrentCatchHandlers(instructionIndex);
+    updateCurrentCatchHandlers(instructionIndex, builder.getFactory());
     updateDebugPosition(instructionIndex, builder);
     currentDexInstruction = code.instructions[instructionIndex];
     currentDexInstruction.buildIR(builder);
   }
 
   @Override
-  public CatchHandlers<Integer> getCurrentCatchHandlers() {
+  public CatchHandlers<Integer> getCurrentCatchHandlers(IRBuilder builder) {
     return currentCatchHandlers;
   }
 
@@ -246,7 +247,7 @@
     return true;
   }
 
-  private void updateCurrentCatchHandlers(int instructionIndex) {
+  private void updateCurrentCatchHandlers(int instructionIndex, DexItemFactory factory) {
     Try tryRange = getTryForOffset(instructionOffset(instructionIndex));
     if (tryRange == currentTryRange) {
       return;
@@ -255,9 +256,7 @@
     if (tryRange == null) {
       currentCatchHandlers = null;
     } else {
-      currentCatchHandlers = new CatchHandlers<>(
-          getTryHandlerGuards(tryRange),
-          getTryHandlerOffsets(tryRange));
+      currentCatchHandlers = getCurrentCatchHandlers(factory, tryRange);
     }
   }
 
@@ -391,7 +390,7 @@
         }
         builder.ensureBlockWithoutEnqueuing(tryRangeStartAddress);
         // Edge to exceptional successors.
-        for (Integer handlerOffset : getUniqueTryHandlerOffsets(tryRange)) {
+        for (Integer handlerOffset : getUniqueTryHandlerOffsets(tryRange, builder.getFactory())) {
           builder.ensureExceptionalSuccessorBlock(offset, handlerOffset);
         }
         // If the following instruction is a move-result include it in this (the invokes) block.
@@ -437,31 +436,46 @@
     return null;
   }
 
-  private Set<Integer> getUniqueTryHandlerOffsets(Try tryRange) {
-    return new HashSet<>(getTryHandlerOffsets(tryRange));
-  }
-
-  private List<Integer> getTryHandlerOffsets(Try tryRange) {
-    List<Integer> handlerOffsets = new ArrayList<>();
-    TryHandler handler = code.handlers[tryRange.handlerIndex];
-    for (TypeAddrPair pair : handler.pairs) {
-      handlerOffsets.add(pair.addr);
-    }
-    if (handler.catchAllAddr != TryHandler.NO_HANDLER) {
-      handlerOffsets.add(handler.catchAllAddr);
-    }
-    return handlerOffsets;
-  }
-
-  private List<DexType> getTryHandlerGuards(Try tryRange) {
+  private CatchHandlers<Integer> getCurrentCatchHandlers(DexItemFactory factory, Try tryRange) {
     List<DexType> handlerGuards = new ArrayList<>();
+    List<Integer> handlerOffsets = new ArrayList<>();
+    forEachTryRange(
+        tryRange,
+        factory,
+        (type, addr) -> {
+          handlerGuards.add(type);
+          handlerOffsets.add(addr);
+        });
+    return new CatchHandlers<>(handlerGuards, handlerOffsets);
+  }
+
+  private void forEachTryRange(
+      Try tryRange, DexItemFactory factory, BiConsumer<DexType, Integer> fn) {
     TryHandler handler = code.handlers[tryRange.handlerIndex];
     for (TypeAddrPair pair : handler.pairs) {
-      handlerGuards.add(pair.type);
+      fn.accept(pair.type, pair.addr);
+      if (pair.type == factory.throwableType) {
+        return;
+      }
     }
     if (handler.catchAllAddr != TryHandler.NO_HANDLER) {
-      handlerGuards.add(DexItemFactory.catchAllType);
+      fn.accept(factory.throwableType, handler.catchAllAddr);
     }
-    return handlerGuards;
+
+  }
+
+  private Set<Integer> getUniqueTryHandlerOffsets(Try tryRange, DexItemFactory factory) {
+    return new HashSet<>(getTryHandlerOffsets(tryRange, factory));
+  }
+
+  private List<Integer> getTryHandlerOffsets(Try tryRange, DexItemFactory factory) {
+    List<Integer> handlerOffsets = new ArrayList<>();
+    forEachTryRange(
+        tryRange,
+        factory,
+        (type, addr) -> {
+          handlerOffsets.add(addr);
+        });
+    return handlerOffsets;
   }
 }
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/IRBuilder.java b/src/main/java/com/android/tools/r8/ir/conversion/IRBuilder.java
index 0f09bbc..2e22480 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/IRBuilder.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/IRBuilder.java
@@ -2216,7 +2216,7 @@
     offsets.put(block, freshOffset);
 
     // Copy over the exceptional successors.
-    for (int offset : source.getCurrentCatchHandlers().getUniqueTargets()) {
+    for (int offset : source.getCurrentCatchHandlers(this).getUniqueTargets()) {
       info.addExceptionalSuccessor(offset);
       BlockInfo target = targets.get(offset);
       assert !target.block.isSealed();
@@ -2252,27 +2252,25 @@
     currentBlock.add(ir);
     if (ir.instructionTypeCanThrow()) {
       assert source.verifyCurrentInstructionCanThrow();
-      CatchHandlers<Integer> catchHandlers = source.getCurrentCatchHandlers();
+      CatchHandlers<Integer> catchHandlers = source.getCurrentCatchHandlers(this);
       if (catchHandlers != null) {
         assert !throwingInstructionInCurrentBlock;
         throwingInstructionInCurrentBlock = true;
         List<BasicBlock> targets = new ArrayList<>(catchHandlers.getAllTargets().size());
         Set<BasicBlock> moveExceptionTargets = Sets.newIdentityHashSet();
-        catchHandlers.forEach((type, targetOffset) -> {
-          DexType exceptionType = type == options.itemFactory.catchAllType
-              ? options.itemFactory.throwableType
-              : type;
-          BasicBlock header = new BasicBlock();
-          header.incrementUnfilledPredecessorCount();
-          ssaWorklist.add(
-              new MoveExceptionWorklistItem(
-                  header, exceptionType, currentInstructionOffset, targetOffset));
-          targets.add(header);
-          BasicBlock target = getTarget(targetOffset);
-          if (!moveExceptionTargets.add(target)) {
-            target.incrementUnfilledPredecessorCount();
-          }
-        });
+        catchHandlers.forEach(
+            (exceptionType, targetOffset) -> {
+              BasicBlock header = new BasicBlock();
+              header.incrementUnfilledPredecessorCount();
+              ssaWorklist.add(
+                  new MoveExceptionWorklistItem(
+                      header, exceptionType, currentInstructionOffset, targetOffset));
+              targets.add(header);
+              BasicBlock target = getTarget(targetOffset);
+              if (!moveExceptionTargets.add(target)) {
+                target.incrementUnfilledPredecessorCount();
+              }
+            });
         currentBlock.linkCatchSuccessors(catchHandlers.getGuards(), targets);
       }
     }
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/JarSourceCode.java b/src/main/java/com/android/tools/r8/ir/conversion/JarSourceCode.java
index 93e5355..6574551 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/JarSourceCode.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/JarSourceCode.java
@@ -9,7 +9,6 @@
 import com.android.tools.r8.graph.DebugLocalInfo;
 import com.android.tools.r8.graph.DexCallSite;
 import com.android.tools.r8.graph.DexField;
-import com.android.tools.r8.graph.DexItemFactory;
 import com.android.tools.r8.graph.DexMethod;
 import com.android.tools.r8.graph.DexMethodHandle;
 import com.android.tools.r8.graph.DexProto;
@@ -96,7 +95,11 @@
       this.handler = handler;
       this.start = start;
       this.end = end;
-      this.type = type;
+      this.type = type == null ? "java/lang/Throwable" : type;
+    }
+
+    boolean isCatchAll() {
+      return type.equals("java/lang/Throwable");
     }
 
     int getStart() {
@@ -617,7 +620,7 @@
   }
 
   @Override
-  public CatchHandlers<Integer> getCurrentCatchHandlers() {
+  public CatchHandlers<Integer> getCurrentCatchHandlers(IRBuilder builder) {
     if (generatingMethodSynchronization) {
       return null;
     }
@@ -811,7 +814,7 @@
     Set<String> seen = new HashSet<>();
     // The try-catch blocks are ordered by precedence.
     for (TryCatchBlock tryCatchBlock : getPotentialTryHandlers(insn)) {
-      if (tryCatchBlock.getType() == null) {
+      if (tryCatchBlock.isCatchAll()) {
         handlers.add(tryCatchBlock);
         return handlers;
       }
@@ -839,10 +842,10 @@
   private List<DexType> getTryHandlerGuards(List<TryCatchBlock> tryCatchBlocks) {
     List<DexType> guards = new ArrayList<>();
     for (TryCatchBlock tryCatchBlock : tryCatchBlocks) {
-      guards.add(tryCatchBlock.getType() == null
-          ? DexItemFactory.catchAllType
-          : application.getTypeFromName(tryCatchBlock.getType()));
-
+      guards.add(
+          tryCatchBlock.getType() == null
+              ? application.getFactory().throwableType
+              : application.getTypeFromName(tryCatchBlock.getType()));
     }
     return guards;
   }
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/SourceCode.java b/src/main/java/com/android/tools/r8/ir/conversion/SourceCode.java
index 9c0dccb..df2b663 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/SourceCode.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/SourceCode.java
@@ -63,7 +63,7 @@
   // Helper to resolve fill-array data and build new-array instructions (dex code only).
   void resolveAndBuildNewArrayFilledData(int arrayRef, int payloadOffset, IRBuilder builder);
 
-  CatchHandlers<Integer> getCurrentCatchHandlers();
+  CatchHandlers<Integer> getCurrentCatchHandlers(IRBuilder builder);
 
   int getMoveExceptionRegister(int instructionIndex);
 
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/DeadCodeRemover.java b/src/main/java/com/android/tools/r8/ir/optimize/DeadCodeRemover.java
index 504d01c..3d45805 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/DeadCodeRemover.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/DeadCodeRemover.java
@@ -6,7 +6,6 @@
 import com.android.tools.r8.graph.AppInfo;
 import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.DexClass;
-import com.android.tools.r8.graph.DexItemFactory;
 import com.android.tools.r8.graph.DexType;
 import com.android.tools.r8.graph.GraphLense;
 import com.android.tools.r8.ir.code.BasicBlock;
@@ -180,9 +179,6 @@
     for (int i = 0; i < catchHandlers.size(); ++i) {
       DexType guard = catchHandlers.getGuards().get(i);
       BasicBlock target = catchHandlers.getAllTargets().get(i);
-      if (guard == DexItemFactory.catchAllType) {
-        continue;
-      }
 
       // We can exploit subtyping information to eliminate a catch handler if the guard is
       // subsumed by a previous guard.
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/Outliner.java b/src/main/java/com/android/tools/r8/ir/optimize/Outliner.java
index 27ec7dc..5ba7eb1 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/Outliner.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/Outliner.java
@@ -1453,7 +1453,7 @@
     }
 
     @Override
-    public CatchHandlers<Integer> getCurrentCatchHandlers() {
+    public CatchHandlers<Integer> getCurrentCatchHandlers(IRBuilder builder) {
       return null;
     }
 
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/UninstantiatedTypeOptimization.java b/src/main/java/com/android/tools/r8/ir/optimize/UninstantiatedTypeOptimization.java
index 9dff882..ff330e1 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/UninstantiatedTypeOptimization.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/UninstantiatedTypeOptimization.java
@@ -581,8 +581,7 @@
               // target.
               return;
             }
-            if (guard != dexItemFactory.catchAllType
-                && !dexItemFactory.npeType.isSubtypeOf(guard, appView.appInfo())) {
+            if (!dexItemFactory.npeType.isSubtypeOf(guard, appView.appInfo())) {
               // TODO(christofferqa): Consider updating previous dominator tree instead of
               // rebuilding it from scratch.
               DominatorTree dominatorTree = new DominatorTree(code, MAY_HAVE_UNREACHABLE_BLOCKS);
diff --git a/src/main/java/com/android/tools/r8/ir/synthetic/SyntheticSourceCode.java b/src/main/java/com/android/tools/r8/ir/synthetic/SyntheticSourceCode.java
index 50d63e5..031ae7e 100644
--- a/src/main/java/com/android/tools/r8/ir/synthetic/SyntheticSourceCode.java
+++ b/src/main/java/com/android/tools/r8/ir/synthetic/SyntheticSourceCode.java
@@ -238,7 +238,7 @@
   }
 
   @Override
-  public final CatchHandlers<Integer> getCurrentCatchHandlers() {
+  public final CatchHandlers<Integer> getCurrentCatchHandlers(IRBuilder builder) {
     return null;
   }
 
diff --git a/src/test/java/com/android/tools/r8/CfFrontendExamplesTest.java b/src/test/java/com/android/tools/r8/CfFrontendExamplesTest.java
index 2253f1f..3f0d0be 100644
--- a/src/test/java/com/android/tools/r8/CfFrontendExamplesTest.java
+++ b/src/test/java/com/android/tools/r8/CfFrontendExamplesTest.java
@@ -8,6 +8,7 @@
 import static org.junit.Assert.assertEquals;
 
 import com.android.tools.r8.origin.Origin;
+import com.android.tools.r8.utils.StringUtils;
 import com.google.common.collect.ImmutableList;
 import java.io.PrintWriter;
 import java.io.StringWriter;
@@ -205,11 +206,11 @@
   public void testRegress37658666() throws Exception {
     runTest(
         "regress_37658666.Regress",
-        (expectedBytes, actualBytes) -> {
+        (expected, actual) -> {
           // javac emits LDC(-0.0f) instead of the shorter FCONST_0 FNEG emitted by CfConstNumber.
           String ldc = "methodVisitor.visitLdcInsn(new Float(\"-0.0\"));";
           String constNeg = "methodVisitor.visitInsn(FCONST_0);\nmethodVisitor.visitInsn(FNEG);";
-          assertEquals(asmToString(expectedBytes).replace(ldc, constNeg), asmToString(actualBytes));
+          assertEquals(expected.replace(ldc, constNeg), actual);
         });
   }
 
@@ -294,10 +295,12 @@
   }
 
   private void runTest(String clazz) throws Exception {
-    runTest(clazz, null);
+    runTest(
+        clazz, (expected, actual) -> assertEquals("Class " + clazz + " differs", expected, actual));
   }
 
-  private void runTest(String clazz, BiConsumer<byte[], byte[]> comparator) throws Exception {
+  private void runTest(String clazz, BiConsumer<String, String> comparator) throws Exception {
+    assert comparator != null;
     String pkg = clazz.substring(0, clazz.lastIndexOf('.'));
     String suffix = "_debuginfo_all";
     Path inputJar = Paths.get(ToolHelper.EXAMPLES_BUILD_DIR, pkg + suffix + JAR_EXTENSION);
@@ -324,17 +327,30 @@
     for (String descriptor : expected.getClassDescriptors()) {
       byte[] expectedBytes = getClassAsBytes(expected, descriptor);
       byte[] actualBytes = getClassAsBytes(actual, descriptor);
-      if (comparator != null) {
-        comparator.accept(expectedBytes, actualBytes);
-      } else if (!Arrays.equals(expectedBytes, actualBytes)) {
-        assertEquals(
-            "Class " + descriptor + " differs",
-            asmToString(expectedBytes),
-            asmToString(actualBytes));
+      if (!Arrays.equals(expectedBytes, actualBytes)) {
+        String expectedString = replaceCatchThrowableByCatchAll(asmToString(expectedBytes));
+        String actualString = asmToString(actualBytes);
+        comparator.accept(expectedString, actualString);
       }
     }
   }
 
+  private static String replaceCatchThrowableByCatchAll(String content) {
+    String catchThrowablePrefix = "methodVisitor.visitTryCatchBlock(";
+    String catchThrowableSuffix = ", \"java/lang/Throwable\");";
+    StringBuilder expected = new StringBuilder();
+    List<String> expectedLines = StringUtils.splitLines(content);
+    for (String line : expectedLines) {
+      if (line.startsWith(catchThrowablePrefix) && line.endsWith(catchThrowableSuffix)) {
+        expected.append(line.replace("\"java/lang/Throwable\"", "null"));
+      } else {
+        expected.append(line);
+      }
+      expected.append(StringUtils.LINE_SEPARATOR);
+    }
+    return expected.toString();
+  }
+
   private static List<String> getSortedDescriptorList(ArchiveClassFileProvider inputJar) {
     ArrayList<String> descriptorList = new ArrayList<>(inputJar.getClassDescriptors());
     Collections.sort(descriptorList);
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/TrivialGotoEliminationTest.java b/src/test/java/com/android/tools/r8/ir/optimize/TrivialGotoEliminationTest.java
index a9e2157..37b0cdc 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/TrivialGotoEliminationTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/TrivialGotoEliminationTest.java
@@ -132,9 +132,7 @@
         new Value(
             0,
             TypeLatticeElement.fromDexType(
-                DexItemFactory.catchAllType,
-                Nullability.definitelyNotNull(),
-                appInfo),
+                app.dexItemFactory.throwableType, Nullability.definitelyNotNull(), appInfo),
             null);
     instruction = new Argument(value);
     instruction.setPosition(position);
diff --git a/src/test/java/com/android/tools/r8/maindexlist/MainDexListTests.java b/src/test/java/com/android/tools/r8/maindexlist/MainDexListTests.java
index 30db56e..bdf815e 100644
--- a/src/test/java/com/android/tools/r8/maindexlist/MainDexListTests.java
+++ b/src/test/java/com/android/tools/r8/maindexlist/MainDexListTests.java
@@ -888,7 +888,7 @@
     }
 
     @Override
-    public CatchHandlers<Integer> getCurrentCatchHandlers() {
+    public CatchHandlers<Integer> getCurrentCatchHandlers(IRBuilder builder) {
       return null;
     }
 
diff --git a/src/test/java/com/android/tools/r8/utils/codeinspector/CfTryCatchSubject.java b/src/test/java/com/android/tools/r8/utils/codeinspector/CfTryCatchSubject.java
index 2d7aec8..663a070 100644
--- a/src/test/java/com/android/tools/r8/utils/codeinspector/CfTryCatchSubject.java
+++ b/src/test/java/com/android/tools/r8/utils/codeinspector/CfTryCatchSubject.java
@@ -58,7 +58,7 @@
 
   @Override
   public boolean hasCatchAll() {
-    return isCatching(DexItemFactory.catchAllType.toDescriptorString());
+    return isCatching(DexItemFactory.throwableDescriptorString);
   }
 
 }