Ensure redundant array get elimination leads to narrowing
Bug: b/278573402
Change-Id: I5f4fd4f491ddac40d4e720862ab711220c0be145
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 a3c270a..178c021 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
@@ -12,10 +12,13 @@
import com.android.tools.r8.graph.DexClassAndField;
import com.android.tools.r8.graph.DexClassAndMethod;
import com.android.tools.r8.graph.DexField;
+import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.FieldResolutionResult.SingleFieldResolutionResult;
import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.graph.classmerging.VerticallyMergedClasses;
+import com.android.tools.r8.ir.analysis.type.Nullability;
+import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.analysis.value.SingleFieldValue;
import com.android.tools.r8.ir.analysis.value.SingleValue;
import com.android.tools.r8.ir.analysis.value.objectstate.ObjectState;
@@ -105,6 +108,8 @@
}
void eliminateRedundantRead(InstructionListIterator it, Instruction redundant);
+
+ TypeElement getType(AppView<?> appView, TypeElement outType);
}
private class ExistingValue implements FieldValue {
@@ -128,6 +133,11 @@
value.uniquePhiUsers().forEach(Phi::removeTrivialPhi);
}
+ @Override
+ public TypeElement getType(AppView<?> appView, TypeElement outType) {
+ return value.getType();
+ }
+
public Value getValue() {
return value;
}
@@ -153,6 +163,27 @@
it.replaceCurrentInstruction(
value.createMaterializingInstruction(appView.withClassHierarchy(), code, redundant));
}
+
+ @Override
+ public TypeElement getType(AppView<?> appView, TypeElement outType) {
+ DexItemFactory dexItemFactory = appView.dexItemFactory();
+ if (value.isSingleStringValue() || value.isSingleDexItemBasedStringValue()) {
+ return dexItemFactory.stringType.toTypeElement(
+ RedundantFieldLoadAndStoreElimination.this.appView, Nullability.definitelyNotNull());
+ }
+ if (value.isSingleFieldValue()) {
+ return value.asSingleFieldValue().getField().getTypeElement(appView);
+ }
+ // For numbers (and null), we don't encode the type along with the value. Therefore, we
+ // fallback to the existing out type in this case.
+ assert value.isSingleNumberValue();
+ if (outType.isReferenceType()) {
+ assert value.isNull();
+ return TypeElement.getNull();
+ }
+ assert outType.isPrimitiveType();
+ return outType;
+ }
}
private abstract static class ArraySlot {
@@ -574,10 +605,12 @@
ArraySlot arraySlot = ArraySlot.create(array, index, arrayGet.getMemberType());
FieldValue replacement = activeState.getArraySlotValue(arraySlot);
if (replacement != null) {
- replacement.eliminateRedundantRead(it, arrayGet);
+ TypeElement outType = arrayGet.outValue().getType();
+ if (replacement.getType(appView, outType).lessThanOrEqual(outType, appView)) {
+ replacement.eliminateRedundantRead(it, arrayGet);
+ }
return;
}
-
activeState.putArraySlotValue(arraySlot, new ExistingValue(arrayGet.outValue()));
}
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/redundantarraygetelimination/ArrayGetTypePromotionTest.java b/src/test/java/com/android/tools/r8/ir/optimize/redundantarraygetelimination/ArrayGetTypePromotionTest.java
index 1f9edef..ad45f19 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/redundantarraygetelimination/ArrayGetTypePromotionTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/redundantarraygetelimination/ArrayGetTypePromotionTest.java
@@ -70,8 +70,7 @@
.setMinApi(parameters)
.compile()
.run(parameters.getRuntime(), Main.class)
- // TODO(b/278573402): Disallow redundant array load elimination.
- .assertFailureWithErrorThatThrows(VerifyError.class);
+ .assertSuccessWithOutputLines(EXPECTED_OUTPUT);
}
@Test
@@ -85,8 +84,7 @@
.setMinApi(parameters)
.compile()
.run(parameters.getRuntime(), Main.class)
- // TODO(b/278573402): Disallow redundant array load elimination.
- .assertFailureWithErrorThatThrows(VerifyError.class);
+ .assertSuccessWithOutputLines(EXPECTED_OUTPUT);
}
static class Main {