Process double inlining in parallel.

Bug: 121235635
Change-Id: I23a442fea83b05ff2079a0357461f1c2b26f3f59
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java b/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java
index 8b98f07..9bfa951 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java
@@ -563,7 +563,7 @@
     if (inliner != null) {
       printPhase("Double caller inlining");
       assert graphLenseForIR == graphLense();
-      inliner.processDoubleInlineCallers(this, feedback);
+      inliner.processDoubleInlineCallers(this, executorService, feedback);
       feedback.updateVisibleOptimizationInfo();
       assert graphLenseForIR == graphLense();
     }
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 953562f..1feb48f 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
@@ -33,6 +33,8 @@
 import com.android.tools.r8.shaking.Enqueuer.AppInfoWithLiveness;
 import com.android.tools.r8.shaking.MainDexClasses;
 import com.android.tools.r8.utils.InternalOptions;
+import com.android.tools.r8.utils.ThreadUtils;
+import com.google.common.base.Predicates;
 import com.google.common.collect.Sets;
 import java.util.ArrayList;
 import java.util.HashMap;
@@ -40,8 +42,10 @@
 import java.util.ListIterator;
 import java.util.Map;
 import java.util.Set;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Future;
 import java.util.function.Predicate;
-import java.util.stream.Collectors;
 
 public class Inliner {
 
@@ -161,24 +165,29 @@
     return target;
   }
 
-  public synchronized void processDoubleInlineCallers(
-      IRConverter converter, OptimizationFeedback feedback) {
-    if (doubleInlineCallers.size() > 0) {
-      applyDoubleInlining = true;
-      List<DexEncodedMethod> methods = doubleInlineCallers
-          .stream()
-          .sorted(DexEncodedMethod::slowCompare)
-          .collect(Collectors.toList());
-      for (DexEncodedMethod method : methods) {
-        converter.processMethod(
-            method,
-            feedback,
-            x -> false,
-            CallSiteInformation.empty(),
-            Outliner::noProcessing);
-        assert method.isProcessed();
-      }
+  public void processDoubleInlineCallers(
+      IRConverter converter, ExecutorService executorService, OptimizationFeedback feedback)
+      throws ExecutionException {
+    if (doubleInlineCallers.isEmpty()) {
+      return;
     }
+    applyDoubleInlining = true;
+    List<Future<?>> futures = new ArrayList<>();
+    for (DexEncodedMethod method : doubleInlineCallers) {
+      futures.add(
+          executorService.submit(
+              () -> {
+                converter.processMethod(
+                    method,
+                    feedback,
+                    doubleInlineCallers::contains,
+                    CallSiteInformation.empty(),
+                    Outliner::noProcessing);
+                assert method.isProcessed();
+                return null;
+              }));
+    }
+    ThreadUtils.awaitFutures(futures);
   }
 
   /**
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/classinliner/ClassInlinerTest.java b/src/test/java/com/android/tools/r8/ir/optimize/classinliner/ClassInlinerTest.java
index 532a748..b69569f 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/classinliner/ClassInlinerTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/classinliner/ClassInlinerTest.java
@@ -94,6 +94,7 @@
     String javaOutput = runOnJava(main);
     TestRunResult result = testForR8(backend)
         .addProgramClasses(classes)
+        .enableInliningAnnotations()
         .addKeepMainRule(main)
         .addKeepRules(
             "-dontobfuscate", "-allowaccessmodification", "-keepattributes LineNumberTable")
@@ -172,7 +173,6 @@
     String javaOutput = runOnJava(main);
     TestRunResult result = testForR8(backend)
         .addProgramClasses(classes)
-        .enableProguardTestOptions()
         .enableInliningAnnotations()
         .addKeepMainRule(main)
         .addKeepRules(
@@ -277,6 +277,7 @@
     String javaOutput = runOnJava(main);
     TestRunResult result = testForR8(backend)
         .addProgramClasses(classes)
+        .enableInliningAnnotations()
         .addKeepMainRule(main)
         .addKeepRules(
             "-dontobfuscate", "-allowaccessmodification", "-keepattributes LineNumberTable")
@@ -316,6 +317,8 @@
     String javaOutput = runOnJava(main);
     TestRunResult result = testForR8(backend)
         .addProgramClasses(classes)
+        .enableProguardTestOptions()
+        .enableInliningAnnotations()
         .addKeepMainRule(main)
         .addKeepRules(
             "-dontobfuscate", "-allowaccessmodification", "-keepattributes LineNumberTable")
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/classinliner/code/C.java b/src/test/java/com/android/tools/r8/ir/optimize/classinliner/code/C.java
index 38e75c4..dcfb5eb 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/classinliner/code/C.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/classinliner/code/C.java
@@ -4,6 +4,8 @@
 
 package com.android.tools.r8.ir.optimize.classinliner.code;
 
+import com.android.tools.r8.NeverInline;
+
 public class C {
   public static class L {
     public final int x;
@@ -25,15 +27,18 @@
     }
   }
 
-  public synchronized static int method1() {
+  @NeverInline
+  public static int method1() {
     return new L(1).x;
   }
 
-  public synchronized static int method2() {
+  @NeverInline
+  public static int method2() {
     return new L(1).getX();
   }
 
-  public synchronized static int method3() {
+  @NeverInline
+  public static int method3() {
     return F.I.getX();
   }
 }
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/classinliner/invalidroot/InvalidRootsTestClass.java b/src/test/java/com/android/tools/r8/ir/optimize/classinliner/invalidroot/InvalidRootsTestClass.java
index 26dc8cc..8bba53e 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/classinliner/invalidroot/InvalidRootsTestClass.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/classinliner/invalidroot/InvalidRootsTestClass.java
@@ -4,6 +4,8 @@
 
 package com.android.tools.r8.ir.optimize.classinliner.invalidroot;
 
+import com.android.tools.r8.NeverInline;
+
 public class InvalidRootsTestClass {
   private static int ID = 0;
 
@@ -19,7 +21,8 @@
     test.testRootInvalidatesAfterInlining();
   }
 
-  private synchronized void testExtraNeverReturnsNormally() {
+  @NeverInline
+  private void testExtraNeverReturnsNormally() {
     testExtraNeverReturnsNormallyA();
     testExtraNeverReturnsNormallyB();
 
@@ -31,7 +34,8 @@
     }
   }
 
-  private synchronized void testExtraNeverReturnsNormallyA() {
+  @NeverInline
+  private void testExtraNeverReturnsNormallyA() {
     try {
       neverReturnsNormallyExtra(next(), null);
     } catch (RuntimeException re) {
@@ -39,7 +43,8 @@
     }
   }
 
-  private synchronized void testExtraNeverReturnsNormallyB() {
+  @NeverInline
+  private void testExtraNeverReturnsNormallyB() {
     try {
       neverReturnsNormallyExtra(next(), null);
     } catch (RuntimeException re) {
@@ -47,7 +52,8 @@
     }
   }
 
-  private synchronized void testDirectNeverReturnsNormally() {
+  @NeverInline
+  private void testDirectNeverReturnsNormally() {
     try {
       NeverReturnsNormally a = new NeverReturnsNormally();
       System.out.println(a.foo());
@@ -56,7 +62,8 @@
     }
   }
 
-  private synchronized void testInitNeverReturnsNormally() {
+  @NeverInline
+  private void testInitNeverReturnsNormally() {
     try {
       new InitNeverReturnsNormally();
     } catch (RuntimeException re) {
@@ -85,7 +92,8 @@
     }
   }
 
-  private synchronized void testRootInvalidatesAfterInlining() {
+  @NeverInline
+  private void testRootInvalidatesAfterInlining() {
     A a = new A();
     try {
       notInlinedExtraMethod(next(), a);
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/classinliner/trivial/TrivialTestClass.java b/src/test/java/com/android/tools/r8/ir/optimize/classinliner/trivial/TrivialTestClass.java
index 7e3cba2..a2576bf 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/classinliner/trivial/TrivialTestClass.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/classinliner/trivial/TrivialTestClass.java
@@ -4,6 +4,8 @@
 
 package com.android.tools.r8.ir.optimize.classinliner.trivial;
 
+import com.android.tools.r8.NeverInline;
+
 public class TrivialTestClass {
   private static int ID = 0;
 
@@ -25,35 +27,42 @@
     test.testCycles();
   }
 
-  private synchronized void testInner() {
+  @NeverInline
+  private void testInner() {
     Inner inner = new Inner("inner{", 123, next() + "}");
     System.out.println(inner.toString() + " " + inner.getPrefix() + " = " + inner.prefix);
   }
 
-  private synchronized void testConstructorMapping1() {
+  @NeverInline
+  private void testConstructorMapping1() {
     ReferencedFields o = new ReferencedFields(next());
     System.out.println(o.getA());
   }
 
-  private synchronized void testConstructorMapping2() {
+  @NeverInline
+  private void testConstructorMapping2() {
     ReferencedFields o = new ReferencedFields(next());
     System.out.println(o.getB());
   }
 
-  private synchronized void testConstructorMapping3() {
+  @NeverInline
+  private void testConstructorMapping3() {
     ReferencedFields o = new ReferencedFields(next(), next());
     System.out.println(o.getA() + o.getB() + o.getConcat());
   }
 
-  private synchronized void testEmptyClass() {
+  @NeverInline
+  private void testEmptyClass() {
     new EmptyClass();
   }
 
-  private synchronized void testEmptyClassWithInitializer() {
+  @NeverInline
+  private void testEmptyClassWithInitializer() {
     new EmptyClassWithInitializer();
   }
 
-  private synchronized void testClassWithFinalizer() {
+  @NeverInline
+  private void testClassWithFinalizer() {
     new ClassWithFinal();
   }
 
@@ -61,7 +70,8 @@
     iface.foo();
   }
 
-  private synchronized void testCallOnIface1() {
+  @NeverInline
+  private void testCallOnIface1() {
     callOnIface1(new Iface1Impl(next()));
   }
 
@@ -69,14 +79,18 @@
     iface.foo();
   }
 
-  private synchronized void testCallOnIface2() {
+  @NeverInline
+  private void testCallOnIface2() {
     callOnIface2(new Iface2Impl(next()));
     System.out.println(Iface2Impl.CONSTANT); // Keep constant referenced
   }
 
-  private synchronized void testCycles() {
+  @NeverInline
+  private void testCycles() {
     new CycleReferenceAB("first").foo(3);
     new CycleReferenceBA("second").foo(4);
+    new CycleReferenceAB("third").foo(5);
+    new CycleReferenceBA("fourth").foo(6);
   }
 
   public class Inner {