Add Assume from progagated values that is never null

Before this would be a destructive update in the type lattice. After
this CL all explicit value narrowing will be done by the type
analysis.

Change-Id: Ifb81f0037fcd30415778940c60454a68499fa708
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 ce73362..6e195e7 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
@@ -1986,14 +1986,15 @@
     TypeLatticeElement inType = inValue.getTypeLattice();
     TypeLatticeElement instanceOfType =
         TypeLatticeElement.fromDexType(instanceOf.type(), inType.nullability(), appView);
+    Value aliasValue = inValue.getAliasedValue();
 
     InstanceOfResult result = InstanceOfResult.UNKNOWN;
     if (inType.isDefinitelyNull()) {
       result = InstanceOfResult.FALSE;
     } else if (inType.lessThanOrEqual(instanceOfType, appView) && !inType.isNullable()) {
       result = InstanceOfResult.TRUE;
-    } else if (!inValue.isPhi()
-        && inValue.definition.isCreatingInstanceOrArray()
+    } else if (!aliasValue.isPhi()
+        && aliasValue.definition.isCreatingInstanceOrArray()
         && instanceOfType.strictlyLessThan(inType, appView)) {
       result = InstanceOfResult.FALSE;
     } else if (appView.appInfo().hasLiveness()) {
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/MemberValuePropagation.java b/src/main/java/com/android/tools/r8/ir/optimize/MemberValuePropagation.java
index 8c27bd7..73facc3 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/MemberValuePropagation.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/MemberValuePropagation.java
@@ -20,6 +20,7 @@
 import com.android.tools.r8.ir.analysis.type.Nullability;
 import com.android.tools.r8.ir.analysis.type.TypeAnalysis;
 import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
+import com.android.tools.r8.ir.code.Assume;
 import com.android.tools.r8.ir.code.BasicBlock;
 import com.android.tools.r8.ir.code.BasicBlock.ThrowingInfo;
 import com.android.tools.r8.ir.code.ConstInstruction;
@@ -31,6 +32,7 @@
 import com.android.tools.r8.ir.code.InstructionIterator;
 import com.android.tools.r8.ir.code.InstructionListIterator;
 import com.android.tools.r8.ir.code.InvokeMethod;
+import com.android.tools.r8.ir.code.Position;
 import com.android.tools.r8.ir.code.StaticGet;
 import com.android.tools.r8.ir.code.Value;
 import com.android.tools.r8.shaking.AppInfoWithLiveness;
@@ -230,15 +232,6 @@
     if (target == null || !mayPropagateValueFor(target)) {
       return;
     }
-    if (target.getOptimizationInfo().neverReturnsNull()
-        && current.outValue().getTypeLattice().isReference()
-        && current.outValue().canBeNull()) {
-      Value knownToBeNonNullValue = current.outValue();
-      TypeLatticeElement typeLattice = knownToBeNonNullValue.getTypeLattice();
-      knownToBeNonNullValue.narrowing(
-          appView, typeLattice.asReferenceTypeLatticeElement().asNotNull());
-      affectedValues.addAll(knownToBeNonNullValue.affectedValues());
-    }
     if (target.getOptimizationInfo().returnsConstant()) {
       ConstInstruction replacement;
       if (target.getOptimizationInfo().returnsConstantNumber()) {
@@ -264,6 +257,12 @@
       } else {
         iterator.add(replacement);
       }
+      return;
+    }
+    if (target.getOptimizationInfo().neverReturnsNull()
+        && current.outValue().getTypeLattice().isReference()
+        && current.outValue().canBeNull()) {
+      insertAssumeNotNull(code, affectedValues, blocks, iterator, current);
     }
   }
 
@@ -325,9 +324,7 @@
               && !appView.appInfo().isPinned(field)
               && outValue.getTypeLattice().isReference()
               && outValue.canBeNull()) {
-            TypeLatticeElement typeLattice = outValue.getTypeLattice();
-            outValue.narrowing(appView, typeLattice.asReferenceTypeLatticeElement().asNotNull());
-            affectedValues.addAll(outValue.affectedValues());
+            insertAssumeNotNull(code, affectedValues, blocks, iterator, current);
           }
         }
       }
@@ -358,6 +355,31 @@
     }
   }
 
+  private void insertAssumeNotNull(
+      IRCode code,
+      Set<Value> affectedValues,
+      ListIterator<BasicBlock> blocks,
+      InstructionListIterator iterator,
+      Instruction current) {
+    Value knownToBeNonNullValue = current.outValue();
+    Set<Value> affectedUsers = knownToBeNonNullValue.affectedValues();
+    TypeLatticeElement typeLattice = knownToBeNonNullValue.getTypeLattice();
+    Value nonNullValue =
+        code.createValue(
+            typeLattice.asReferenceTypeLatticeElement().asNotNull(),
+            knownToBeNonNullValue.getLocalInfo());
+    knownToBeNonNullValue.replaceUsers(nonNullValue);
+    Assume nonNull = Assume.createAssumeNonNullInstruction(
+        nonNullValue, knownToBeNonNullValue, current);
+    nonNull.setPosition(appView.options().debug ? current.getPosition() : Position.none());
+    if (current.getBlock().hasCatchHandlers()) {
+      iterator.split(code, blocks).listIterator().add(nonNull);
+    } else {
+      iterator.add(nonNull);
+    }
+    affectedValues.addAll(affectedUsers);
+  }
+
   /**
    * Replace invoke targets and field accesses with constant values where possible.
    *