Full single caller inlining in second optimization pass
Bug: b/355488535
Change-Id: I9038948f6678d62cd018ba3a0b1f757561bbca1b
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/PostMethodProcessor.java b/src/main/java/com/android/tools/r8/ir/conversion/PostMethodProcessor.java
index a8fe188..d31a884 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/PostMethodProcessor.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/PostMethodProcessor.java
@@ -52,13 +52,17 @@
CallGraph callGraph,
MethodProcessorEventConsumer eventConsumer,
ProgramMethodSet methodsToProcess) {
- this.callSiteInformation = callGraph.createCallSiteInformation(appView, this);
this.eventConsumer = eventConsumer;
this.methodsToProcess = methodsToProcess;
this.processorContext = appView.createProcessorContext();
+ this.callSiteInformation = callGraph.createCallSiteInformation(appView, this);
this.waves = createWaves(callGraph);
}
+ public void addMethodToProcess(ProgramMethod method) {
+ methodsToProcess.add(method);
+ }
+
public void markCallersForProcessing(ProgramMethod method) {
assert wave.contains(method);
synchronized (methodsToProcess) {
@@ -173,10 +177,6 @@
});
put(set);
}
- if (methodsToReprocessBuilder.isEmpty()) {
- // Nothing to revisit.
- return null;
- }
ProgramMethodSet methodsToReprocess = methodsToReprocessBuilder.build(appView);
// TODO(b/333677610): Check this assert when bridges synthesized by member rebinding is
// always removed
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/callgraph/CallSiteInformation.java b/src/main/java/com/android/tools/r8/ir/conversion/callgraph/CallSiteInformation.java
index 84685ae..f89b900 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/callgraph/CallSiteInformation.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/callgraph/CallSiteInformation.java
@@ -140,15 +140,19 @@
}
}
Set<Node> callersWithDeterministicOrder = node.getCallersWithDeterministicOrder();
- DexMethod caller = reference;
+ ProgramMethod caller = method;
// We can have recursive methods where the recursive call is the only call site. We do
// not track callers for these.
if (!callersWithDeterministicOrder.isEmpty()) {
assert callersWithDeterministicOrder.size() == 1;
- caller = callersWithDeterministicOrder.iterator().next().getMethod().getReference();
+ caller = callersWithDeterministicOrder.iterator().next().getProgramMethod();
}
assert !singleCallerMethods.containsKey(reference);
- singleCallerMethods.put(reference, caller);
+ singleCallerMethods.put(reference, caller.getReference());
+ if (methodProcessor.isPostMethodProcessor()
+ && appView.getKeepInfo(caller).isReprocessingAllowed(options, caller)) {
+ methodProcessor.asPostMethodProcessor().addMethodToProcess(caller);
+ }
} else if (numberOfCallSites > 1 && methodProcessor.isPrimaryMethodProcessor()) {
multiCallerInlineCandidates.add(reference);
}
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/Inliner.java b/src/main/java/com/android/tools/r8/ir/optimize/Inliner.java
index 4b9c547..99463ac 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/Inliner.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/Inliner.java
@@ -1299,15 +1299,28 @@
// Convert and remove virtual single caller inlined methods to abstract or throw null.
singleCallerInlinedMethodsForClass.removeIf(
(callee, caller) -> {
- // TODO(b/203188583): Enable pruning of methods with generic signatures. For this to
- // work we need to pass in a seed to GenericSignatureContextBuilder.create in R8.
- if (callee.getDefinition().belongsToVirtualPool()
- || callee.getDefinition().getGenericSignature().hasSignature()) {
+ boolean convertToAbstractOrThrowNullMethod =
+ callee.getDefinition().belongsToVirtualPool();
+ if (callee.getDefinition().getGenericSignature().hasSignature()) {
+ // TODO(b/203188583): Enable pruning of methods with generic signatures. For this
+ // to work we need to pass in a seed to GenericSignatureContextBuilder.create in
+ // R8.
+ convertToAbstractOrThrowNullMethod = true;
+ } else if (appView.options().configurationDebugging
+ && appView.getSyntheticItems().isSynthetic(callee.getHolder())) {
+ // If static synthetic methods are removed after being single caller inlined, we
+ // need to unregister them as synthetic methods in the synthetic items collection.
+ // This means that they will not be renamed to ExternalSynthetic leading to
+ // assertion errors. This should only be a problem when configuration debugging is
+ // enabled, since configuration debugging disables shrinking of the synthetic
+ // method's holder.
+ convertToAbstractOrThrowNullMethod = true;
+ }
+ if (convertToAbstractOrThrowNullMethod) {
callee.convertToAbstractOrThrowNullMethod(appView);
converter.onMethodCodePruned(callee);
- return true;
}
- return false;
+ return convertToAbstractOrThrowNullMethod;
});
// Remove direct single caller inlined methods from the application.
diff --git a/src/test/java/com/android/tools/r8/classmerging/vertical/VerticalClassMergerTest.java b/src/test/java/com/android/tools/r8/classmerging/vertical/VerticalClassMergerTest.java
index 723e674..627c16f 100644
--- a/src/test/java/com/android/tools/r8/classmerging/vertical/VerticalClassMergerTest.java
+++ b/src/test/java/com/android/tools/r8/classmerging/vertical/VerticalClassMergerTest.java
@@ -855,7 +855,6 @@
ImmutableSet.of(
"classmerging.SuperCallToMergedClassIsRewrittenTest",
"classmerging.A",
- "classmerging.D",
"classmerging.F");
JasminBuilder jasminBuilder = new JasminBuilder();
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/inliner/SingleTargetAfterInliningTest.java b/src/test/java/com/android/tools/r8/ir/optimize/inliner/SingleTargetAfterInliningTest.java
index 59e609d..3bd367b 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/inliner/SingleTargetAfterInliningTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/inliner/SingleTargetAfterInliningTest.java
@@ -25,13 +25,17 @@
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameter;
import org.junit.runners.Parameterized.Parameters;
@RunWith(Parameterized.class)
public class SingleTargetAfterInliningTest extends TestBase {
- private final int maxInliningDepth;
- private final TestParameters parameters;
+ @Parameter(0)
+ public int maxInliningDepth;
+
+ @Parameter(1)
+ public TestParameters parameters;
@Parameters(name = "{1}, max inlining depth: {0}")
public static List<Object[]> data() {
@@ -39,11 +43,6 @@
ImmutableList.of(0, 1), getTestParameters().withAllRuntimesAndApiLevels().build());
}
- public SingleTargetAfterInliningTest(int maxInliningDepth, TestParameters parameters) {
- this.maxInliningDepth = maxInliningDepth;
- this.parameters = parameters;
- }
-
@Test
public void test() throws Exception {
testForR8(parameters.getBackend())
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/membervaluepropagation/FieldWriteBeforeFieldReadTest.java b/src/test/java/com/android/tools/r8/ir/optimize/membervaluepropagation/FieldWriteBeforeFieldReadTest.java
index a603d83..4a681ad 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/membervaluepropagation/FieldWriteBeforeFieldReadTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/membervaluepropagation/FieldWriteBeforeFieldReadTest.java
@@ -24,22 +24,20 @@
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameter;
import org.junit.runners.Parameterized.Parameters;
@RunWith(Parameterized.class)
public class FieldWriteBeforeFieldReadTest extends TestBase {
- private final TestParameters parameters;
+ @Parameter(0)
+ public TestParameters parameters;
@Parameters(name = "{0}")
public static TestParametersCollection data() {
return getTestParameters().withAllRuntimesAndApiLevels().build();
}
- public FieldWriteBeforeFieldReadTest(TestParameters parameters) {
- this.parameters = parameters;
- }
-
@Test
public void test() throws Exception {
testForR8(parameters.getBackend())
diff --git a/src/test/java/com/android/tools/r8/regress/b165825758/Regress165825758Test.java b/src/test/java/com/android/tools/r8/regress/b165825758/Regress165825758Test.java
index 8f93035..4034d59 100644
--- a/src/test/java/com/android/tools/r8/regress/b165825758/Regress165825758Test.java
+++ b/src/test/java/com/android/tools/r8/regress/b165825758/Regress165825758Test.java
@@ -26,23 +26,22 @@
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameter;
+import org.junit.runners.Parameterized.Parameters;
@RunWith(Parameterized.class)
public class Regress165825758Test extends TestBase {
- static final String EXPECTED = StringUtils.lines("Hello, world");
+ private static final String EXPECTED = StringUtils.lines("Hello, world");
- private final TestParameters parameters;
+ @Parameter(0)
+ public TestParameters parameters;
- @Parameterized.Parameters(name = "{0}")
+ @Parameters(name = "{0}")
public static TestParametersCollection data() {
return getTestParameters().withAllRuntimesAndApiLevels().build();
}
- public Regress165825758Test(TestParameters parameters) {
- this.parameters = parameters;
- }
-
@Test
public void testReference() throws Exception {
testForRuntime(parameters)