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)