Do not compute optimization info twice for staticized methods

Change-Id: Iefeb2bfb4e05ee0a319f26ffd0088745e38273ed
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/staticizer/StaticizingProcessor.java b/src/main/java/com/android/tools/r8/ir/optimize/staticizer/StaticizingProcessor.java
index b9ef1c9..a467cb2 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/staticizer/StaticizingProcessor.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/staticizer/StaticizingProcessor.java
@@ -35,6 +35,7 @@
 import com.android.tools.r8.utils.ThreadUtils;
 import com.google.common.collect.BiMap;
 import com.google.common.collect.HashBiMap;
+import com.google.common.collect.ImmutableList;
 import com.google.common.collect.Sets;
 import com.google.common.collect.Streams;
 import java.util.ArrayList;
@@ -57,7 +58,8 @@
   private final ClassStaticizer classStaticizer;
   private final IRConverter converter;
 
-  private final Map<DexEncodedMethod, Collection<Consumer<IRCode>>> processingQueue =
+  // Optimization order matters, hence a collection that preserves orderings.
+  private final Map<DexEncodedMethod, ImmutableList.Builder<Consumer<IRCode>>> processingQueue =
       new IdentityHashMap<>();
 
   private final Set<DexEncodedMethod> referencingExtraMethods = Sets.newIdentityHashSet();
@@ -75,7 +77,7 @@
     this.converter = converter;
   }
 
-  final void run(OptimizationFeedback optimizationFeedback, ExecutorService executorService)
+  final void run(OptimizationFeedback feedback, ExecutorService executorService)
       throws ExecutionException {
     // Filter out candidates based on the information we collected while examining methods.
     finalEligibilityCheck();
@@ -84,15 +86,20 @@
     prepareCandidates();
 
     // Enqueue all host class initializers (only remove instantiations).
-    enqueueMethodsWithCodeOptimization(
-        hostClassInits.keySet(), this::removeCandidateInstantiation);
+    enqueueMethodsWithCodeOptimizations(
+        hostClassInits.keySet(),
+        optimizations ->
+            optimizations
+                .add(this::removeCandidateInstantiation)
+                .add(this::insertAssumeInstructions)
+                .add(collectOptimizationInfo(feedback)));
 
     // Enqueue instance methods to be staticized (only remove references to 'this').
-    enqueueMethodsWithCodeOptimization(
-        methodsToBeStaticized, this::removeReferencesToThis);
+    enqueueMethodsWithCodeOptimizations(
+        methodsToBeStaticized, optimizations -> optimizations.add(this::removeReferencesToThis));
 
     // Process queued methods with associated optimizations
-    processMethodsConcurrently(optimizationFeedback, executorService);
+    processMethodsConcurrently(feedback, executorService);
 
     // TODO(b/140767158): Merge the remaining part below.
     // Convert instance methods into static methods with an extra parameter.
@@ -103,10 +110,16 @@
     // a result of staticizing.)
     methods.addAll(referencingExtraMethods);
     methods.addAll(hostClassInits.keySet());
-    enqueueMethodsWithCodeOptimization(methods, this::rewriteReferences);
+    enqueueMethodsWithCodeOptimizations(
+        methods,
+        optimizations ->
+            optimizations
+                .add(this::rewriteReferences)
+                .add(this::insertAssumeInstructions)
+                .add(collectOptimizationInfo(feedback)));
 
     // Process queued methods with associated optimizations
-    processMethodsConcurrently(optimizationFeedback, executorService);
+    processMethodsConcurrently(feedback, executorService);
   }
 
   private void finalEligibilityCheck() {
@@ -249,15 +262,11 @@
     referencingExtraMethods.removeAll(removedInstanceMethods);
   }
 
-  private void enqueueMethodsWithCodeOptimization(
-      Iterable<DexEncodedMethod> methods, Consumer<IRCode> optimization) {
+  private void enqueueMethodsWithCodeOptimizations(
+      Iterable<DexEncodedMethod> methods,
+      Consumer<ImmutableList.Builder<Consumer<IRCode>>> extension) {
     for (DexEncodedMethod method : methods) {
-      processingQueue
-          .computeIfAbsent(
-              method,
-              // Optimization order might matter, hence a collection that preserves orderings.
-              k -> new ArrayList<>())
-          .add(optimization);
+      extension.accept(processingQueue.computeIfAbsent(method, ignore -> ImmutableList.builder()));
     }
   }
 
@@ -275,7 +284,7 @@
       OptimizationFeedback feedback, ExecutorService executorService) throws ExecutionException {
     ThreadUtils.processItems(
         processingQueue.keySet(),
-        method -> forEachMethod(method, processingQueue.get(method), feedback),
+        method -> forEachMethod(method, processingQueue.get(method).build(), feedback),
         executorService);
     // TODO(b/140767158): No need to clear if we can do every thing in one go.
     processingQueue.clear();
@@ -289,12 +298,18 @@
     Origin origin = appView.appInfo().originFor(method.method.holder);
     IRCode code = method.buildIR(appView, origin);
     codeOptimizations.forEach(codeOptimization -> codeOptimization.accept(code));
-    CodeRewriter.insertAssumeInstructions(code, converter.assumers);
-    converter.collectOptimizationInfo(code, feedback);
     CodeRewriter.removeAssumeInstructions(appView, code);
     converter.finalizeIR(method, code, feedback);
   }
 
+  private void insertAssumeInstructions(IRCode code) {
+    CodeRewriter.insertAssumeInstructions(code, converter.assumers);
+  }
+
+  private Consumer<IRCode> collectOptimizationInfo(OptimizationFeedback feedback) {
+    return code -> converter.collectOptimizationInfo(code, feedback);
+  }
+
   private void removeCandidateInstantiation(IRCode code) {
     CandidateInfo candidateInfo = hostClassInits.get(code.method);
     assert candidateInfo != null;