Update null cyclic phis when rewriting always throwing instructions

Bug: b/250634405
Change-Id: I3a26861b028c553e8bb5c66ae30f335d19bc40c4
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/type/DestructivePhiTypeUpdater.java b/src/main/java/com/android/tools/r8/ir/analysis/type/DestructivePhiTypeUpdater.java
index 0ccf414..89e78e5 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/type/DestructivePhiTypeUpdater.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/type/DestructivePhiTypeUpdater.java
@@ -60,7 +60,7 @@
     worklist.addAll(affectedPhis);
     while (!worklist.isEmpty()) {
       Phi phi = worklist.poll();
-      TypeElement newType = phi.computePhiType(appView);
+      TypeElement newType = phi.getDynamicUpperBoundType(appView);
       if (!phi.getType().equals(newType)) {
         assert !newType.isBottom();
         phi.setType(newType);
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 a2cd8e8..dbd19bd 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
@@ -19,6 +19,7 @@
 import com.android.tools.r8.errors.CompilationError;
 import com.android.tools.r8.errors.Unreachable;
 import com.android.tools.r8.graph.AccessControl;
+import com.android.tools.r8.graph.AppInfoWithClassHierarchy;
 import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.DebugLocalInfo;
 import com.android.tools.r8.graph.DexClass;
@@ -3367,6 +3368,28 @@
     ListIterator<BasicBlock> blockIterator = code.listIterator();
     ProgramMethod context = code.context();
     boolean hasUnlinkedCatchHandlers = false;
+    // For cyclic phis we sometimes do not propagate the dynamic upper type after rewritings.
+    // The inValue.isAlwaysNull(appView) check below will not recompute the dynamic type of phi's
+    // so we recompute all phis here if they are always null.
+    AppView<AppInfoWithClassHierarchy> appViewWithClassHierarchy =
+        appView.hasClassHierarchy() ? appView.withClassHierarchy() : null;
+    if (appViewWithClassHierarchy != null) {
+      code.blocks.forEach(
+          block ->
+              block
+                  .getPhis()
+                  .forEach(
+                      phi -> {
+                        if (!phi.getType().isDefinitelyNull()) {
+                          TypeElement dynamicUpperBoundType =
+                              phi.getDynamicUpperBoundType(appViewWithClassHierarchy);
+                          if (dynamicUpperBoundType.isDefinitelyNull()) {
+                            affectedValues.add(phi);
+                            phi.setType(dynamicUpperBoundType);
+                          }
+                        }
+                      }));
+    }
     while (blockIterator.hasNext()) {
       BasicBlock block = blockIterator.next();
       if (block.getNumber() != 0 && block.getPredecessors().isEmpty()) {