Disable canonicalization for singleton fields
Bug: 171136616
Change-Id: I42a6046030ae104daf1f4b8a41aaf50b74904889
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/ConstantCanonicalizer.java b/src/main/java/com/android/tools/r8/ir/optimize/ConstantCanonicalizer.java
index 36fba35..5585153 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/ConstantCanonicalizer.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/ConstantCanonicalizer.java
@@ -11,6 +11,9 @@
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.graph.AppView;
+import com.android.tools.r8.graph.DexClass;
+import com.android.tools.r8.graph.DexEncodedField;
+import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.ir.analysis.value.AbstractValue;
import com.android.tools.r8.ir.analysis.value.SingleFieldValue;
@@ -147,13 +150,22 @@
continue;
}
SingleFieldValue singleFieldValue = abstractValue.asSingleFieldValue();
+ DexType fieldHolderType = singleFieldValue.getField().holder;
if (context.getDefinition().isClassInitializer()
- && context.getHolderType() == singleFieldValue.getField().holder) {
+ && context.getHolderType() == fieldHolderType) {
// Avoid that canonicalization inserts a read before the unique write in the class
// initializer, as that would change the program behavior.
continue;
}
- if (current.instructionMayHaveSideEffects(appView, context)) {
+ DexClass fieldHolder = appView.definitionFor(fieldHolderType);
+ if (fieldHolder == null) {
+ continue;
+ }
+ DexEncodedField field = fieldHolder.lookupField(singleFieldValue.getField());
+ if (field == null
+ || !field.isEnum()
+ || current.instructionMayHaveSideEffects(appView, context)) {
+ // Only allow canonicalization of enums.
continue;
}
}
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/canonicalization/EffectivelyFinalFieldCanonicalizationTest.java b/src/test/java/com/android/tools/r8/ir/optimize/canonicalization/EffectivelyFinalFieldCanonicalizationTest.java
index 4e73445..cde89ec 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/canonicalization/EffectivelyFinalFieldCanonicalizationTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/canonicalization/EffectivelyFinalFieldCanonicalizationTest.java
@@ -54,7 +54,7 @@
MethodSubject mainMethodSubject = testClassSubject.mainMethod();
assertThat(mainMethodSubject, isPresent());
assertEquals(
- 1, mainMethodSubject.streamInstructions().filter(InstructionSubject::isStaticGet).count());
+ 2, mainMethodSubject.streamInstructions().filter(InstructionSubject::isStaticGet).count());
}
static class TestClass {
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/canonicalization/SingletonCanonicalizationWithApiLevelCheckTest.java b/src/test/java/com/android/tools/r8/ir/optimize/canonicalization/SingletonCanonicalizationWithApiLevelCheckTest.java
index bbc7245..7b86868 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/canonicalization/SingletonCanonicalizationWithApiLevelCheckTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/canonicalization/SingletonCanonicalizationWithApiLevelCheckTest.java
@@ -63,15 +63,7 @@
.compile()
.addRunClasspathFiles(program)
.run(parameters.getRuntime(), TestClass.class)
- .apply(
- runResult -> {
- if (parameters.isCfRuntime()) {
- // Constant canonicalization is disabled for CF.
- runResult.assertSuccessWithOutput("");
- } else {
- runResult.assertFailureWithErrorThatThrows(NoClassDefFoundError.class);
- }
- });
+ .assertSuccessWithOutput("");
}
private List<String> getAssumeValuesRule(int version) {
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/staticizer/ClassStaticizerTest.java b/src/test/java/com/android/tools/r8/ir/optimize/staticizer/ClassStaticizerTest.java
index fc87e9b..885eb25 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/staticizer/ClassStaticizerTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/staticizer/ClassStaticizerTest.java
@@ -205,6 +205,7 @@
"STATIC: SimpleWithThrowingGetter SimpleWithThrowingGetter.getInstance()",
"STATIC: String TrivialTestClass.next()",
"SimpleWithThrowingGetter SimpleWithThrowingGetter.INSTANCE",
+ "SimpleWithThrowingGetter SimpleWithThrowingGetter.INSTANCE",
"VIRTUAL: String SimpleWithThrowingGetter.bar(String)",
"VIRTUAL: String SimpleWithThrowingGetter.foo()"),
references(clazz, "testSimpleWithThrowingGetter", "void"));