Widen dynamic argument types after rebuilding allocation site collection

Change-Id: I7904f13bc1cc6f23501b406712388a867cd79e9e
diff --git a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/ArgumentPropagatorOptimizationInfoPopulator.java b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/ArgumentPropagatorOptimizationInfoPopulator.java
index bd70946..db9543f 100644
--- a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/ArgumentPropagatorOptimizationInfoPopulator.java
+++ b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/ArgumentPropagatorOptimizationInfoPopulator.java
@@ -14,6 +14,7 @@
 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.value.AbstractValue;
 import com.android.tools.r8.ir.conversion.IRConverter;
 import com.android.tools.r8.ir.optimize.info.ConcreteCallSiteOptimizationInfo;
 import com.android.tools.r8.ir.optimize.info.MethodOptimizationInfo;
@@ -27,6 +28,7 @@
 import com.android.tools.r8.optimize.argumentpropagation.codescanner.MethodState;
 import com.android.tools.r8.optimize.argumentpropagation.codescanner.MethodStateCollectionByReference;
 import com.android.tools.r8.optimize.argumentpropagation.codescanner.ParameterState;
+import com.android.tools.r8.optimize.argumentpropagation.codescanner.StateCloner;
 import com.android.tools.r8.optimize.argumentpropagation.propagation.InParameterFlowPropagator;
 import com.android.tools.r8.optimize.argumentpropagation.propagation.InterfaceMethodArgumentPropagator;
 import com.android.tools.r8.optimize.argumentpropagation.propagation.VirtualDispatchMethodArgumentPropagator;
@@ -43,7 +45,6 @@
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.ExecutorService;
 import java.util.function.BiConsumer;
-import java.util.stream.IntStream;
 
 /**
  * Propagates the argument flow information collected by the {@link ArgumentPropagatorCodeScanner}.
@@ -185,6 +186,14 @@
 
     ConcreteMonomorphicMethodState monomorphicMethodState = concreteMethodState.asMonomorphic();
 
+    // Widen the dynamic type information so that we don't store any trivial dynamic types.
+    // Note that all dynamic types are already being widened when the method states are created, but
+    // this does not guarantee that they are non-trivial at this point, since we may refine the
+    // object allocation info collection during the primary optimization pass.
+    if (!widenDynamicTypes(method, monomorphicMethodState)) {
+      return;
+    }
+
     // Verify that there is no parameter with bottom info.
     assert monomorphicMethodState.getParameterStates().stream().noneMatch(ParameterState::isBottom);
 
@@ -194,28 +203,6 @@
         .map(ParameterState::asConcrete)
         .noneMatch(ConcreteParameterState::hasInParameters);
 
-    // Verify that the dynamic type information is correct.
-    assert IntStream.range(0, monomorphicMethodState.getParameterStates().size())
-        .filter(
-            index -> {
-              ParameterState parameterState = monomorphicMethodState.getParameterState(index);
-              return parameterState.isConcrete() && parameterState.asConcrete().isClassParameter();
-            })
-        .allMatch(
-            index -> {
-              DynamicType dynamicType =
-                  monomorphicMethodState
-                      .getParameterState(index)
-                      .asConcrete()
-                      .asClassParameter()
-                      .getDynamicType();
-              DexType staticType = method.getArgumentType(index);
-              assert dynamicType.isUnknown()
-                  || !WideningUtils.widenDynamicNonReceiverType(appView, dynamicType, staticType)
-                      .isUnknown();
-              return true;
-            });
-
     getSimpleFeedback()
         .setArgumentInfos(
             method,
@@ -316,4 +303,34 @@
           appView.abstractValueFactory().createZeroValue());
     }
   }
+
+  private boolean widenDynamicTypes(
+      ProgramMethod method, ConcreteMonomorphicMethodState methodState) {
+    for (int argumentIndex = 0;
+        argumentIndex < methodState.getParameterStates().size();
+        argumentIndex++) {
+      ConcreteParameterState parameterState =
+          methodState.getParameterState(argumentIndex).asConcrete();
+      if (parameterState == null || !parameterState.isClassParameter()) {
+        continue;
+      }
+      DynamicType dynamicType = parameterState.asClassParameter().getDynamicType();
+      if (dynamicType.isUnknown()) {
+        continue;
+      }
+      DexType staticType = method.getArgumentType(argumentIndex);
+      if (!WideningUtils.widenDynamicNonReceiverType(appView, dynamicType, staticType)
+          .isUnknown()) {
+        continue;
+      }
+      methodState.setParameterState(
+          argumentIndex,
+          parameterState.mutableJoin(
+              appView,
+              new ConcreteClassTypeParameterState(AbstractValue.bottom(), DynamicType.unknown()),
+              staticType,
+              StateCloner.getIdentity()));
+    }
+    return !methodState.isEffectivelyUnknown();
+  }
 }
diff --git a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/ConcreteMonomorphicMethodState.java b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/ConcreteMonomorphicMethodState.java
index c98c383..d32df00 100644
--- a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/ConcreteMonomorphicMethodState.java
+++ b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/ConcreteMonomorphicMethodState.java
@@ -21,9 +21,8 @@
   public ConcreteMonomorphicMethodState(List<ParameterState> parameterStates) {
     assert Streams.stream(Iterables.skip(parameterStates, 1))
         .noneMatch(x -> x.isConcrete() && x.asConcrete().isReceiverParameter());
-    assert Iterables.any(parameterStates, parameterState -> !parameterState.isUnknown())
-        : "Must use UnknownMethodState instead";
     this.parameterStates = parameterStates;
+    assert !isEffectivelyUnknown() : "Must use UnknownMethodState instead";
   }
 
   public ParameterState getParameterState(int index) {
@@ -34,6 +33,10 @@
     return parameterStates;
   }
 
+  public boolean isEffectivelyUnknown() {
+    return Iterables.all(parameterStates, ParameterState::isUnknown);
+  }
+
   @Override
   public ConcreteMonomorphicMethodState mutableCopy() {
     List<ParameterState> copiedParametersStates = new ArrayList<>(size());
@@ -75,10 +78,7 @@
           || !parameterStates.get(argumentIndex).asConcrete().isReceiverParameter();
     }
 
-    if (Iterables.all(parameterStates, ParameterState::isUnknown)) {
-      return unknown();
-    }
-    return this;
+    return isEffectivelyUnknown() ? unknown() : this;
   }
 
   @Override