Enable dynamic type optimization
Bug: 127461806
Change-Id: I8cc40901ea5cf4b977ba55b7b23caeaa43ab93b1
diff --git a/src/main/java/com/android/tools/r8/R8Command.java b/src/main/java/com/android/tools/r8/R8Command.java
index dfeaf74..4b53365 100644
--- a/src/main/java/com/android/tools/r8/R8Command.java
+++ b/src/main/java/com/android/tools/r8/R8Command.java
@@ -676,7 +676,7 @@
? LineNumberOptimization.ON
: LineNumberOptimization.OFF;
- assert !internal.enableDynamicTypeOptimization;
+ assert internal.enableDynamicTypeOptimization || !proguardConfiguration.isOptimizing();
assert internal.enableHorizontalClassMerging || !proguardConfiguration.isOptimizing();
assert !internal.enableTreeShakingOfLibraryMethodOverrides;
assert internal.enableVerticalClassMerging || !proguardConfiguration.isOptimizing();
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 f214373..334bfb2 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
@@ -2094,7 +2094,9 @@
if (aliasedValue != null) {
TypeLatticeElement dynamicType =
aliasedValue.definition.asAssumeDynamicType().getAssumption().getType();
- if (dynamicType.lessThanOrEqual(instanceOfType, appView)
+ if (dynamicType.isDefinitelyNull()) {
+ result = InstanceOfResult.FALSE;
+ } else if (dynamicType.lessThanOrEqual(instanceOfType, appView)
&& (!inType.isNullable() || !dynamicType.isNullable())) {
result = InstanceOfResult.TRUE;
}
diff --git a/src/main/java/com/android/tools/r8/utils/InternalOptions.java b/src/main/java/com/android/tools/r8/utils/InternalOptions.java
index c1b199c..022a58d 100644
--- a/src/main/java/com/android/tools/r8/utils/InternalOptions.java
+++ b/src/main/java/com/android/tools/r8/utils/InternalOptions.java
@@ -136,7 +136,7 @@
public boolean passthroughDexCode = false;
// Optimization-related flags. These should conform to -dontoptimize and disableAllOptimizations.
- public boolean enableDynamicTypeOptimization = false;
+ public boolean enableDynamicTypeOptimization = true;
public boolean enableHorizontalClassMerging = true;
public boolean enableVerticalClassMerging = true;
public boolean enableArgumentRemoval = true;
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/instanceofremoval/InstanceOfRemovalTest.java b/src/test/java/com/android/tools/r8/ir/optimize/instanceofremoval/InstanceOfRemovalTest.java
index efd4766..1cbeaae 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/instanceofremoval/InstanceOfRemovalTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/instanceofremoval/InstanceOfRemovalTest.java
@@ -8,7 +8,8 @@
import com.android.tools.r8.NeverInline;
import com.android.tools.r8.TestBase;
-import com.android.tools.r8.ToolHelper;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.utils.BooleanUtils;
import com.android.tools.r8.utils.StringUtils;
import com.android.tools.r8.utils.codeinspector.ClassSubject;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
@@ -16,6 +17,7 @@
import com.android.tools.r8.utils.codeinspector.MethodSubject;
import com.google.common.collect.Streams;
import java.util.Iterator;
+import java.util.List;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
@@ -109,15 +111,17 @@
}
}
- @Parameters(name = "Backend: {0}")
- public static Backend[] data() {
- return ToolHelper.getBackends();
+ @Parameters(name = "{1}, enable dynamic type optimization: {0}")
+ public static List<Object[]> data() {
+ return buildParameters(BooleanUtils.values(), getTestParameters().withAllRuntimes().build());
}
- private final Backend backend;
+ private final boolean enableDynamicTypeOptimization;
+ private final TestParameters parameters;
- public InstanceOfRemovalTest(Backend backend) {
- this.backend = backend;
+ public InstanceOfRemovalTest(boolean enableDynamicTypeOptimization, TestParameters parameters) {
+ this.enableDynamicTypeOptimization = enableDynamicTypeOptimization;
+ this.parameters = parameters;
}
@Test
@@ -146,14 +150,22 @@
"B[] instanceof B[]: true",
"");
- testForJvm().addTestClasspath().run(TestClass.class).assertSuccessWithOutput(expected);
+ if (parameters.isCfRuntime()) {
+ testForJvm()
+ .addTestClasspath()
+ .run(parameters.getRuntime(), TestClass.class)
+ .assertSuccessWithOutput(expected);
+ }
CodeInspector inspector =
- testForR8(backend)
+ testForR8(parameters.getBackend())
.addProgramClasses(A.class, B.class, TestClass.class)
.addKeepMainRule(TestClass.class)
+ .addOptionsModification(
+ options -> options.enableDynamicTypeOptimization = enableDynamicTypeOptimization)
.enableInliningAnnotations()
- .run(TestClass.class)
+ .setMinApi(parameters.getRuntime())
+ .run(parameters.getRuntime(), TestClass.class)
.assertSuccessWithOutput(expected)
.inspector();
@@ -165,10 +177,12 @@
fooMethodSubject.iterateInstructions(InstructionSubject::isInstanceOf);
assertEquals(0, Streams.stream(fooInstructionIterator).count());
- // Without inlining we cannot prove any of the instance-of checks to be trivial.
+ // Without inlining we cannot prove any of the instance-of checks to be trivial, but the dynamic
+ // type optimization allows us to prove that some are safe.
MethodSubject barMethodSubject = testClass.uniqueMethodWithName("bar");
Iterator<InstructionSubject> barInstructionIterator =
barMethodSubject.iterateInstructions(InstructionSubject::isInstanceOf);
- assertEquals(6, Streams.stream(barInstructionIterator).count());
+ assertEquals(
+ enableDynamicTypeOptimization ? 4 : 6, Streams.stream(barInstructionIterator).count());
}
}