Update AssertionErrorRewriter to not remove NewInstance on the fly

Bug: b/245692849
Change-Id: I805d4dbe80ceaa3821eec01138469e0ea9727297
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/AssertionErrorTwoArgsConstructorRewriter.java b/src/main/java/com/android/tools/r8/ir/optimize/AssertionErrorTwoArgsConstructorRewriter.java
index 06d9d8f..6d5083c 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/AssertionErrorTwoArgsConstructorRewriter.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/AssertionErrorTwoArgsConstructorRewriter.java
@@ -11,19 +11,24 @@
 import com.android.tools.r8.graph.DexProto;
 import com.android.tools.r8.graph.MethodAccessFlags;
 import com.android.tools.r8.graph.ProgramMethod;
+import com.android.tools.r8.ir.analysis.type.DynamicType;
 import com.android.tools.r8.ir.analysis.type.Nullability;
-import com.android.tools.r8.ir.analysis.type.TypeElement;
+import com.android.tools.r8.ir.analysis.type.TypeAnalysis;
 import com.android.tools.r8.ir.code.BasicBlock;
 import com.android.tools.r8.ir.code.IRCode;
 import com.android.tools.r8.ir.code.Instruction;
 import com.android.tools.r8.ir.code.InstructionListIterator;
 import com.android.tools.r8.ir.code.InvokeStatic;
+import com.android.tools.r8.ir.code.NewInstance;
 import com.android.tools.r8.ir.code.Value;
 import com.android.tools.r8.ir.desugar.backports.BackportedMethods;
+import com.android.tools.r8.ir.optimize.info.OptimizationFeedback;
 import com.android.tools.r8.utils.InternalOptions;
+import com.google.common.collect.Sets;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.ListIterator;
+import java.util.Set;
 
 public class AssertionErrorTwoArgsConstructorRewriter {
 
@@ -41,11 +46,12 @@
     if (options.canUseAssertionErrorTwoArgumentConstructor()) {
       return;
     }
-
+    Set<Value> newOutValues = Sets.newIdentityHashSet();
     ListIterator<BasicBlock> blockIterator = code.listIterator();
     while (blockIterator.hasNext()) {
       BasicBlock block = blockIterator.next();
       InstructionListIterator insnIterator = block.listIterator(code);
+      List<NewInstance> newInstancesToRemove = new ArrayList<>();
       while (insnIterator.hasNext()) {
         Instruction current = insnIterator.next();
         if (current.isInvokeMethod()) {
@@ -53,24 +59,31 @@
           if (invokedMethod == dexItemFactory.assertionErrorMethods.initMessageAndCause) {
             List<Value> inValues = current.inValues();
             assert inValues.size() == 3; // receiver, message, cause
-
-            Value assertionError =
-                code.createValue(
-                    TypeElement.fromDexType(
-                        dexItemFactory.assertionErrorType,
-                        Nullability.definitelyNotNull(),
-                        appView));
-            Instruction invoke =
-                new InvokeStatic(
-                    createSynthetic(methodProcessingContext).getReference(),
-                    assertionError,
-                    inValues.subList(1, 3));
+            Value newInstanceValue = current.getFirstOperand();
+            Instruction definition = newInstanceValue.getDefinition();
+            if (!definition.isNewInstance()) {
+              continue;
+            }
+            InvokeStatic invoke =
+                InvokeStatic.builder()
+                    .setMethod(createSynthetic(methodProcessingContext).getReference())
+                    .setFreshOutValue(
+                        code, dexItemFactory.assertionErrorType.toTypeElement(appView))
+                    .setPosition(current)
+                    .setArguments(inValues.subList(1, 3))
+                    .build();
             insnIterator.replaceCurrentInstruction(invoke);
-            inValues.get(0).replaceUsers(assertionError);
-            inValues.get(0).definition.removeOrReplaceByDebugLocalRead(code);
+            newInstanceValue.replaceUsers(invoke.outValue());
+            newOutValues.add(invoke.outValue());
+            newInstancesToRemove.add(definition.asNewInstance());
           }
         }
       }
+      newInstancesToRemove.forEach(
+          newInstance -> newInstance.removeOrReplaceByDebugLocalRead(code));
+    }
+    if (!newOutValues.isEmpty()) {
+      new TypeAnalysis(appView).widening(newOutValues);
     }
     assert code.isConsistentSSA(appView);
   }
@@ -103,6 +116,15 @@
                                     factory, methodSig)));
     synchronized (synthesizedMethods) {
       synthesizedMethods.add(method);
+      OptimizationFeedback.getSimpleFeedback()
+          .setDynamicReturnType(
+              method,
+              appView,
+              DynamicType.createExact(
+                  dexItemFactory
+                      .assertionErrorType
+                      .toTypeElement(appView, Nullability.definitelyNotNull())
+                      .asClassType()));
     }
     return method;
   }