Fix removal of non-trivial assume-dynamic-type instruction

Change-Id: I0805d08d40b0edeac84602cd9c97e4e82c30f927
diff --git a/src/main/java/com/android/tools/r8/ir/code/FieldGet.java b/src/main/java/com/android/tools/r8/ir/code/FieldGet.java
index 3f62f1f..aecb3eb 100644
--- a/src/main/java/com/android/tools/r8/ir/code/FieldGet.java
+++ b/src/main/java/com/android/tools/r8/ir/code/FieldGet.java
@@ -4,7 +4,11 @@
 
 package com.android.tools.r8.ir.code;
 
+import com.android.tools.r8.graph.DexField;
+
 public interface FieldGet {
 
+  DexField getField();
+
   Value outValue();
 }
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/RedundantFieldLoadAndStoreElimination.java b/src/main/java/com/android/tools/r8/ir/optimize/RedundantFieldLoadAndStoreElimination.java
index b3f74c5..0e3dfdb 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/RedundantFieldLoadAndStoreElimination.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/RedundantFieldLoadAndStoreElimination.java
@@ -20,6 +20,7 @@
 import com.android.tools.r8.ir.analysis.value.SingleValue;
 import com.android.tools.r8.ir.analysis.value.objectstate.ObjectState;
 import com.android.tools.r8.ir.code.BasicBlock;
+import com.android.tools.r8.ir.code.FieldGet;
 import com.android.tools.r8.ir.code.FieldInstruction;
 import com.android.tools.r8.ir.code.IRCode;
 import com.android.tools.r8.ir.code.InitClass;
@@ -91,6 +92,10 @@
 
   private interface FieldValue {
 
+    default ExistingValue asExistingValue() {
+      return null;
+    }
+
     void eliminateRedundantRead(InstructionListIterator it, FieldInstruction redundant);
   }
 
@@ -103,6 +108,11 @@
     }
 
     @Override
+    public ExistingValue asExistingValue() {
+      return this;
+    }
+
+    @Override
     public void eliminateRedundantRead(InstructionListIterator it, FieldInstruction redundant) {
       affectedValues.addAll(redundant.value().affectedValues());
       redundant.value().replaceUsers(value);
@@ -110,6 +120,10 @@
       value.uniquePhiUsers().forEach(Phi::removeTrivialPhi);
     }
 
+    public Value getValue() {
+      return value;
+    }
+
     @Override
     public String toString() {
       return "ExistingValue(v" + value.getNumber() + ")";
@@ -411,7 +425,7 @@
     FieldAndObject fieldAndObject = new FieldAndObject(field.getReference(), object);
     FieldValue replacement = activeState.getInstanceFieldValue(fieldAndObject);
     if (replacement != null) {
-      assumeRemover.markAssumeDynamicTypeUsersForRemoval(instanceGet.outValue());
+      markAssumeDynamicTypeUsersForRemoval(instanceGet, replacement, assumeRemover);
       replacement.eliminateRedundantRead(it, instanceGet);
       return;
     }
@@ -430,6 +444,21 @@
     }
   }
 
+  private void markAssumeDynamicTypeUsersForRemoval(
+      FieldGet fieldGet, FieldValue replacement, AssumeRemover assumeRemover) {
+    ExistingValue existingValue = replacement.asExistingValue();
+    if (existingValue == null
+        || !existingValue
+            .getValue()
+            .isDefinedByInstructionSatisfying(
+                definition ->
+                    definition.isFieldGet()
+                        && definition.asFieldGet().getField().getType()
+                            == fieldGet.getField().getType())) {
+      assumeRemover.markAssumeDynamicTypeUsersForRemoval(fieldGet.outValue());
+    }
+  }
+
   private void handleInstancePut(InstancePut instancePut, DexClassAndField field) {
     // An instance-put instruction can potentially write the given field on all objects because of
     // aliases.
@@ -480,7 +509,7 @@
 
     FieldValue replacement = activeState.getStaticFieldValue(field.getReference());
     if (replacement != null) {
-      assumeRemover.markAssumeDynamicTypeUsersForRemoval(staticGet.outValue());
+      markAssumeDynamicTypeUsersForRemoval(staticGet, replacement, assumeRemover);
       replacement.eliminateRedundantRead(instructionIterator, staticGet);
       return;
     }