Narrow unknown dynamic type in concrete value state

Change-Id: Ibe89e97f1120d23c7eed889521dd26d0256a90ae
diff --git a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/ConcreteClassTypeValueState.java b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/ConcreteClassTypeValueState.java
index 8542763..f689576 100644
--- a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/ConcreteClassTypeValueState.java
+++ b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/ConcreteClassTypeValueState.java
@@ -182,4 +182,8 @@
     dynamicType = widenedDynamicType;
     return !dynamicType.equals(oldDynamicType);
   }
+
+  public ConcreteClassTypeValueState withDynamicType(DynamicType dynamicType) {
+    return new ConcreteClassTypeValueState(abstractValue, dynamicType, copyInFlow());
+  }
 }
diff --git a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/ConcreteReceiverValueState.java b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/ConcreteReceiverValueState.java
index 894ad96..2d73c7b 100644
--- a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/ConcreteReceiverValueState.java
+++ b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/ConcreteReceiverValueState.java
@@ -62,7 +62,7 @@
 
   @Override
   public Nullability getNullability() {
-    return getDynamicType().getNullability();
+    return Nullability.definitelyNotNull();
   }
 
   @Override
@@ -140,4 +140,8 @@
     }
     return !dynamicType.equals(oldDynamicType);
   }
+
+  public ConcreteReceiverValueState withDynamicType(DynamicType dynamicType) {
+    return new ConcreteReceiverValueState(dynamicType, copyInFlow());
+  }
 }
diff --git a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/propagation/InFlowPropagator.java b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/propagation/InFlowPropagator.java
index 1a26af0..4404d74 100644
--- a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/propagation/InFlowPropagator.java
+++ b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/propagation/InFlowPropagator.java
@@ -193,6 +193,7 @@
   }
 
   private NonEmptyValueState narrowUnknownState(FlowGraphNode node, FlowGraphNode successorNode) {
+    assert node.isUnknown();
     boolean applyNarrowing =
         node.getStaticType().isReferenceType()
             && node.getStaticType().isNotIdenticalTo(successorNode.getStaticType());
@@ -226,11 +227,13 @@
       ConcreteValueState state,
       Set<AbstractFunction> transferFunctions,
       Deque<FlowGraphNode> worklist) {
+    ConcreteValueState stateToPropagate = narrowConcreteState(node, successorNode, state);
     assert !successorNode.isUnknown();
     for (AbstractFunction transferFunction : transferFunctions) {
       FlowGraphStateProvider flowGraphStateProvider =
           FlowGraphStateProvider.create(flowGraph, transferFunction);
-      ValueState transferState = transferFunction.apply(appView, flowGraphStateProvider, state);
+      ValueState transferState =
+          transferFunction.apply(appView, flowGraphStateProvider, stateToPropagate);
       if (transferState.isBottom()) {
         // Nothing to propagate.
       } else if (transferState.isUnknown()) {
@@ -254,6 +257,29 @@
     return false;
   }
 
+  private ConcreteValueState narrowConcreteState(
+      FlowGraphNode node, FlowGraphNode successorNode, ConcreteValueState state) {
+    boolean applyNarrowing =
+        node.getStaticType().isReferenceType()
+            && node.getStaticType().isNotIdenticalTo(successorNode.getStaticType());
+    if (!applyNarrowing) {
+      return state;
+    }
+    if (state.isArrayState()) {
+      // We don't track the dynamic type of array types, currently.
+      return state;
+    }
+    Nullability nullabilityToPropagate = state.asReferenceState().getNullability();
+    TypeElement typeToPropagate =
+        node.getStaticType().toTypeElement(appView, nullabilityToPropagate);
+    DynamicType dynamicTypeToPropagate = DynamicType.create(appView, typeToPropagate);
+    if (state.isClassState()) {
+      return state.asClassState().withDynamicType(dynamicTypeToPropagate);
+    } else {
+      return state.asReceiverState().withDynamicType(dynamicTypeToPropagate);
+    }
+  }
+
   private void postProcessMethodStates(ExecutorService executorService) throws ExecutionException {
     ThreadUtils.processItems(
         appView.appInfo().classes(),