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;
}