Add timing to AppView#pruneItems

Change-Id: Ibf938573acb3f2a11d1c2623ba0cbd0e935599f7
diff --git a/src/main/java/com/android/tools/r8/R8.java b/src/main/java/com/android/tools/r8/R8.java
index f345f1b..7bd8767 100644
--- a/src/main/java/com/android/tools/r8/R8.java
+++ b/src/main/java/com/android/tools/r8/R8.java
@@ -413,7 +413,6 @@
               .notifyTreePrunerFinished(Enqueuer.Mode.INITIAL_TREE_SHAKING);
 
           // Recompute the subtyping information.
-          appView.pruneItems(prunedItems, executorService);
           new AbstractMethodRemover(
                   appViewWithLiveness, appViewWithLiveness.appInfo().computeSubtypingInfo())
               .run();
@@ -454,7 +453,7 @@
         // We can now remove redundant bridges. Note that we do not need to update the
         // invoke-targets here, as the existing invokes will simply dispatch to the now
         // visible super-method. MemberRebinding, if run, will then dispatch it correctly.
-        new RedundantBridgeRemover(appView.withLiveness()).run(null, executorService);
+        new RedundantBridgeRemover(appView.withLiveness()).run(null, executorService, timing);
       }
 
       // This pass attempts to reduce the number of nests and nest size to allow further passes, and
@@ -595,8 +594,6 @@
                   options.reporter, options.usageInformationConsumer);
             }
 
-            appView.pruneItems(prunedItems, executorService);
-
             new BridgeHoisting(appViewWithLiveness).run(executorService, timing);
 
             assert Inliner.verifyAllSingleCallerMethodsHaveBeenPruned(appViewWithLiveness);
@@ -684,7 +681,7 @@
       // This can only be done if we have AppInfoWithLiveness.
       if (appView.appInfo().hasLiveness()) {
         new RedundantBridgeRemover(appView.withLiveness())
-            .run(memberRebindingIdentityLens, executorService);
+            .run(memberRebindingIdentityLens, executorService, timing);
       } else {
         // If we don't have AppInfoWithLiveness here, it must be because we are not shrinking. When
         // we are not shrinking, we can't move visibility bridges. In principle, though, it would be
diff --git a/src/main/java/com/android/tools/r8/graph/AppInfo.java b/src/main/java/com/android/tools/r8/graph/AppInfo.java
index ec98db1..7052724 100644
--- a/src/main/java/com/android/tools/r8/graph/AppInfo.java
+++ b/src/main/java/com/android/tools/r8/graph/AppInfo.java
@@ -13,6 +13,7 @@
 import com.android.tools.r8.synthesis.SyntheticItems.GlobalSyntheticsStrategy;
 import com.android.tools.r8.utils.BooleanBox;
 import com.android.tools.r8.utils.InternalOptions;
+import com.android.tools.r8.utils.Timing;
 import java.util.Collection;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.ExecutorService;
@@ -70,7 +71,8 @@
     this.obsolete = obsolete;
   }
 
-  public AppInfo prunedCopyFrom(PrunedItems prunedItems, ExecutorService executorService)
+  public AppInfo prunedCopyFrom(
+      PrunedItems prunedItems, ExecutorService executorService, Timing timing)
       throws ExecutionException {
     assert getClass() == AppInfo.class;
     assert checkIfObsolete();
@@ -78,9 +80,13 @@
     if (prunedItems.isEmpty()) {
       return this;
     }
-    return new AppInfo(
-        getSyntheticItems().commitPrunedItems(prunedItems),
-        getMainDexInfo().withoutPrunedItems(prunedItems));
+    timing.begin("Pruning AppInfo");
+    AppInfo result =
+        new AppInfo(
+            getSyntheticItems().commitPrunedItems(prunedItems),
+            getMainDexInfo().withoutPrunedItems(prunedItems));
+    timing.end();
+    return result;
   }
 
   public AppInfo rebuildWithMainDexInfo(MainDexInfo mainDexInfo) {
diff --git a/src/main/java/com/android/tools/r8/graph/AppInfoWithClassHierarchy.java b/src/main/java/com/android/tools/r8/graph/AppInfoWithClassHierarchy.java
index 3040ebe..5e5d54d 100644
--- a/src/main/java/com/android/tools/r8/graph/AppInfoWithClassHierarchy.java
+++ b/src/main/java/com/android/tools/r8/graph/AppInfoWithClassHierarchy.java
@@ -18,6 +18,7 @@
 import com.android.tools.r8.synthesis.SyntheticItems;
 import com.android.tools.r8.synthesis.SyntheticItems.GlobalSyntheticsStrategy;
 import com.android.tools.r8.utils.Pair;
+import com.android.tools.r8.utils.Timing;
 import com.android.tools.r8.utils.TraversalContinuation;
 import com.android.tools.r8.utils.TriConsumer;
 import com.android.tools.r8.utils.TriFunction;
@@ -126,18 +127,23 @@
 
   @Override
   public AppInfoWithClassHierarchy prunedCopyFrom(
-      PrunedItems prunedItems, ExecutorService executorService) throws ExecutionException {
+      PrunedItems prunedItems, ExecutorService executorService, Timing timing)
+      throws ExecutionException {
     assert getClass() == AppInfoWithClassHierarchy.class;
     assert checkIfObsolete();
     assert prunedItems.getPrunedApp() == app();
     if (prunedItems.isEmpty()) {
       return this;
     }
-    return new AppInfoWithClassHierarchy(
-        getSyntheticItems().commitPrunedItems(prunedItems),
-        getClassToFeatureSplitMap().withoutPrunedItems(prunedItems),
-        getMainDexInfo().withoutPrunedItems(prunedItems),
-        getMissingClasses());
+    timing.begin("Pruning AppInfoWithClassHierarchy");
+    AppInfoWithClassHierarchy result =
+        new AppInfoWithClassHierarchy(
+            getSyntheticItems().commitPrunedItems(prunedItems),
+            getClassToFeatureSplitMap().withoutPrunedItems(prunedItems),
+            getMainDexInfo().withoutPrunedItems(prunedItems),
+            getMissingClasses());
+    timing.end();
+    return result;
   }
 
   public ClassToFeatureSplitMap getClassToFeatureSplitMap() {
diff --git a/src/main/java/com/android/tools/r8/graph/AppServices.java b/src/main/java/com/android/tools/r8/graph/AppServices.java
index 3ef7937..0c1eb41 100644
--- a/src/main/java/com/android/tools/r8/graph/AppServices.java
+++ b/src/main/java/com/android/tools/r8/graph/AppServices.java
@@ -156,7 +156,8 @@
     return new AppServices(appView, rewrittenFeatureMappings.build());
   }
 
-  public AppServices prunedCopy(PrunedItems prunedItems) {
+  public AppServices prunedCopy(PrunedItems prunedItems, Timing timing) {
+    timing.begin("Prune AppServices");
     ImmutableMap.Builder<DexType, Map<FeatureSplit, List<DexType>>> rewrittenServicesBuilder =
         ImmutableMap.builder();
     for (Entry<DexType, Map<FeatureSplit, List<DexType>>> entry : services.entrySet()) {
@@ -186,7 +187,9 @@
         rewrittenServicesBuilder.put(entry.getKey(), prunedServiceImplementations);
       }
     }
-    return new AppServices(appView, rewrittenServicesBuilder.build());
+    AppServices result = new AppServices(appView, rewrittenServicesBuilder.build());
+    timing.end();
+    return result;
   }
 
   public boolean verifyRewrittenWithLens() {
diff --git a/src/main/java/com/android/tools/r8/graph/AppView.java b/src/main/java/com/android/tools/r8/graph/AppView.java
index 0d4e982..3b85d38 100644
--- a/src/main/java/com/android/tools/r8/graph/AppView.java
+++ b/src/main/java/com/android/tools/r8/graph/AppView.java
@@ -865,47 +865,50 @@
     return !cfByteCodePassThrough.isEmpty();
   }
 
-  public void pruneItems(PrunedItems prunedItems, ExecutorService executorService)
+  public void pruneItems(PrunedItems prunedItems, ExecutorService executorService, Timing timing)
       throws ExecutionException {
     if (prunedItems.isEmpty()) {
       assert appInfo().app() == prunedItems.getPrunedApp();
       return;
     }
+    timing.begin("Prune AppView");
     if (appInfo.hasLiveness()) {
       AppView<AppInfoWithLiveness> self = withLiveness();
-      self.setAppInfo(self.appInfo().prunedCopyFrom(prunedItems, executorService));
+      self.setAppInfo(self.appInfo().prunedCopyFrom(prunedItems, executorService, timing));
     } else if (appInfo.hasClassHierarchy()) {
       AppView<AppInfoWithClassHierarchy> self = withClassHierarchy();
-      self.setAppInfo(self.appInfo().prunedCopyFrom(prunedItems, executorService));
+      self.setAppInfo(self.appInfo().prunedCopyFrom(prunedItems, executorService, timing));
     } else {
-      pruneAppInfo(prunedItems, this, executorService);
+      pruneAppInfo(prunedItems, this, executorService, timing);
     }
     if (appServices() != null) {
-      setAppServices(appServices().prunedCopy(prunedItems));
+      setAppServices(appServices().prunedCopy(prunedItems, timing));
     }
-    setArtProfileCollection(getArtProfileCollection().withoutPrunedItems(prunedItems));
-    setAssumeInfoCollection(getAssumeInfoCollection().withoutPrunedItems(prunedItems));
+    setArtProfileCollection(getArtProfileCollection().withoutPrunedItems(prunedItems, timing));
+    setAssumeInfoCollection(getAssumeInfoCollection().withoutPrunedItems(prunedItems, timing));
     if (hasProguardCompatibilityActions()) {
       setProguardCompatibilityActions(
-          getProguardCompatibilityActions().withoutPrunedItems(prunedItems));
+          getProguardCompatibilityActions().withoutPrunedItems(prunedItems, timing));
     }
     if (hasRootSet()) {
-      rootSet.pruneItems(prunedItems);
+      rootSet.pruneItems(prunedItems, timing);
     }
-    setStartupProfile(getStartupProfile().withoutPrunedItems(prunedItems, getSyntheticItems()));
+    setStartupProfile(
+        getStartupProfile().withoutPrunedItems(prunedItems, getSyntheticItems(), timing));
     if (hasMainDexRootSet()) {
-      setMainDexRootSet(mainDexRootSet.withoutPrunedItems(prunedItems));
+      setMainDexRootSet(mainDexRootSet.withoutPrunedItems(prunedItems, timing));
     }
     setOpenClosedInterfacesCollection(
-        openClosedInterfacesCollection.withoutPrunedItems(prunedItems));
+        openClosedInterfacesCollection.withoutPrunedItems(prunedItems, timing));
+    timing.end();
   }
 
   @SuppressWarnings("unchecked")
   private static void pruneAppInfo(
-      PrunedItems prunedItems, AppView<?> appView, ExecutorService executorService)
+      PrunedItems prunedItems, AppView<?> appView, ExecutorService executorService, Timing timing)
       throws ExecutionException {
     ((AppView<AppInfo>) appView)
-        .setAppInfo(appView.appInfo().prunedCopyFrom(prunedItems, executorService));
+        .setAppInfo(appView.appInfo().prunedCopyFrom(prunedItems, executorService, timing));
   }
 
   public void rewriteWithLens(
diff --git a/src/main/java/com/android/tools/r8/horizontalclassmerging/HorizontalClassMerger.java b/src/main/java/com/android/tools/r8/horizontalclassmerging/HorizontalClassMerger.java
index 3fa5ee2..9464ef4 100644
--- a/src/main/java/com/android/tools/r8/horizontalclassmerging/HorizontalClassMerger.java
+++ b/src/main/java/com/android/tools/r8/horizontalclassmerging/HorizontalClassMerger.java
@@ -216,7 +216,7 @@
     }
 
     appView.pruneItems(
-        prunedItems.toBuilder().setPrunedApp(appView.app()).build(), executorService);
+        prunedItems.toBuilder().setPrunedApp(appView.app()).build(), executorService, timing);
 
     amendKeepInfo(horizontalClassMergerGraphLens, virtuallyMergedMethodsKeepInfos);
   }
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/PrimaryR8IRConverter.java b/src/main/java/com/android/tools/r8/ir/conversion/PrimaryR8IRConverter.java
index f046229..f8946d4 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/PrimaryR8IRConverter.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/PrimaryR8IRConverter.java
@@ -252,7 +252,8 @@
               .setRemovedMethods(prunedMethodsInWave)
               .setPrunedApp(appView.appInfo().app())
               .build(),
-          executorService);
+          executorService,
+          timing);
       prunedMethodsInWave.clear();
     }
   }
diff --git a/src/main/java/com/android/tools/r8/optimize/interfaces/collection/DefaultOpenClosedInterfacesCollection.java b/src/main/java/com/android/tools/r8/optimize/interfaces/collection/DefaultOpenClosedInterfacesCollection.java
index 7db0c3a..564d133 100644
--- a/src/main/java/com/android/tools/r8/optimize/interfaces/collection/DefaultOpenClosedInterfacesCollection.java
+++ b/src/main/java/com/android/tools/r8/optimize/interfaces/collection/DefaultOpenClosedInterfacesCollection.java
@@ -37,7 +37,7 @@
   }
 
   @Override
-  public OpenClosedInterfacesCollection withoutPrunedItems(PrunedItems prunedItems) {
+  public OpenClosedInterfacesCollection withoutPrunedItems(PrunedItems prunedItems, Timing timing) {
     return this;
   }
 }
diff --git a/src/main/java/com/android/tools/r8/optimize/interfaces/collection/NonEmptyOpenClosedInterfacesCollection.java b/src/main/java/com/android/tools/r8/optimize/interfaces/collection/NonEmptyOpenClosedInterfacesCollection.java
index 2bcb577..6312216 100644
--- a/src/main/java/com/android/tools/r8/optimize/interfaces/collection/NonEmptyOpenClosedInterfacesCollection.java
+++ b/src/main/java/com/android/tools/r8/optimize/interfaces/collection/NonEmptyOpenClosedInterfacesCollection.java
@@ -47,16 +47,20 @@
   }
 
   @Override
-  public OpenClosedInterfacesCollection withoutPrunedItems(PrunedItems prunedItems) {
+  public OpenClosedInterfacesCollection withoutPrunedItems(PrunedItems prunedItems, Timing timing) {
     if (!prunedItems.hasRemovedClasses()) {
       return this;
     }
+    timing.begin("Prune NonEmptyOpenClosedInterfacesCollection");
     Set<DexType> prunedOpenInterfaceTypes = SetUtils.newIdentityHashSet(openInterfaceTypes.size());
     for (DexType openInterfaceType : openInterfaceTypes) {
       if (!prunedItems.isRemoved(openInterfaceType)) {
         prunedOpenInterfaceTypes.add(openInterfaceType);
       }
     }
-    return new NonEmptyOpenClosedInterfacesCollection(prunedOpenInterfaceTypes);
+    NonEmptyOpenClosedInterfacesCollection result =
+        new NonEmptyOpenClosedInterfacesCollection(prunedOpenInterfaceTypes);
+    timing.end();
+    return result;
   }
 }
diff --git a/src/main/java/com/android/tools/r8/optimize/interfaces/collection/OpenClosedInterfacesCollection.java b/src/main/java/com/android/tools/r8/optimize/interfaces/collection/OpenClosedInterfacesCollection.java
index 6c81c50..b8d14cc 100644
--- a/src/main/java/com/android/tools/r8/optimize/interfaces/collection/OpenClosedInterfacesCollection.java
+++ b/src/main/java/com/android/tools/r8/optimize/interfaces/collection/OpenClosedInterfacesCollection.java
@@ -99,5 +99,6 @@
   public abstract OpenClosedInterfacesCollection rewrittenWithLens(
       GraphLens graphLens, Timing timing);
 
-  public abstract OpenClosedInterfacesCollection withoutPrunedItems(PrunedItems prunedItems);
+  public abstract OpenClosedInterfacesCollection withoutPrunedItems(
+      PrunedItems prunedItems, Timing timing);
 }
diff --git a/src/main/java/com/android/tools/r8/optimize/redundantbridgeremoval/RedundantBridgeRemover.java b/src/main/java/com/android/tools/r8/optimize/redundantbridgeremoval/RedundantBridgeRemover.java
index 2ed2ab5..4a3c874 100644
--- a/src/main/java/com/android/tools/r8/optimize/redundantbridgeremoval/RedundantBridgeRemover.java
+++ b/src/main/java/com/android/tools/r8/optimize/redundantbridgeremoval/RedundantBridgeRemover.java
@@ -26,6 +26,7 @@
 import com.android.tools.r8.shaking.AppInfoWithLiveness;
 import com.android.tools.r8.shaking.KeepMethodInfo;
 import com.android.tools.r8.utils.ThreadUtils;
+import com.android.tools.r8.utils.Timing;
 import com.android.tools.r8.utils.collections.ProgramMethodSet;
 import java.util.Collection;
 import java.util.List;
@@ -112,18 +113,23 @@
   }
 
   public void run(
-      MemberRebindingIdentityLens memberRebindingIdentityLens, ExecutorService executorService)
+      MemberRebindingIdentityLens memberRebindingIdentityLens,
+      ExecutorService executorService,
+      Timing timing)
       throws ExecutionException {
     assert memberRebindingIdentityLens == null
         || memberRebindingIdentityLens == appView.graphLens();
 
+    timing.begin("Redundant bridge removal");
+
     // Collect all redundant bridges to remove.
     ProgramMethodSet bridgesToRemove = removeRedundantBridgesConcurrently(executorService);
     if (bridgesToRemove.isEmpty()) {
+      timing.end();
       return;
     }
 
-    pruneApp(bridgesToRemove, executorService);
+    pruneApp(bridgesToRemove, executorService, timing);
 
     if (!lensBuilder.isEmpty()) {
       appView.setGraphLens(lensBuilder.build(appView));
@@ -140,6 +146,8 @@
             bridgeToRemove.getReference(), resolvedMethod.getReference());
       }
     }
+
+    timing.end();
   }
 
   private ProgramMethodSet removeRedundantBridgesConcurrently(ExecutorService executorService)
@@ -225,11 +233,12 @@
     return true;
   }
 
-  private void pruneApp(ProgramMethodSet bridgesToRemove, ExecutorService executorService)
+  private void pruneApp(
+      ProgramMethodSet bridgesToRemove, ExecutorService executorService, Timing timing)
       throws ExecutionException {
     PrunedItems.Builder prunedItemsBuilder = PrunedItems.builder().setPrunedApp(appView.app());
     bridgesToRemove.forEach(method -> prunedItemsBuilder.addRemovedMethod(method.getReference()));
-    appView.pruneItems(prunedItemsBuilder.build(), executorService);
+    appView.pruneItems(prunedItemsBuilder.build(), executorService, timing);
   }
 
   class RedundantBridgeRemoverClassHierarchyTraversal
diff --git a/src/main/java/com/android/tools/r8/profile/art/ArtProfileCollection.java b/src/main/java/com/android/tools/r8/profile/art/ArtProfileCollection.java
index 2a3f889..2b2f387 100644
--- a/src/main/java/com/android/tools/r8/profile/art/ArtProfileCollection.java
+++ b/src/main/java/com/android/tools/r8/profile/art/ArtProfileCollection.java
@@ -79,5 +79,5 @@
 
   public abstract ArtProfileCollection withoutMissingItems(AppView<?> appView);
 
-  public abstract ArtProfileCollection withoutPrunedItems(PrunedItems prunedItems);
+  public abstract ArtProfileCollection withoutPrunedItems(PrunedItems prunedItems, Timing timing);
 }
diff --git a/src/main/java/com/android/tools/r8/profile/art/EmptyArtProfileCollection.java b/src/main/java/com/android/tools/r8/profile/art/EmptyArtProfileCollection.java
index fcd6d41..ab478b8 100644
--- a/src/main/java/com/android/tools/r8/profile/art/EmptyArtProfileCollection.java
+++ b/src/main/java/com/android/tools/r8/profile/art/EmptyArtProfileCollection.java
@@ -56,7 +56,7 @@
   }
 
   @Override
-  public ArtProfileCollection withoutPrunedItems(PrunedItems prunedItems) {
+  public ArtProfileCollection withoutPrunedItems(PrunedItems prunedItems, Timing timing) {
     return this;
   }
 }
diff --git a/src/main/java/com/android/tools/r8/profile/art/NonEmptyArtProfileCollection.java b/src/main/java/com/android/tools/r8/profile/art/NonEmptyArtProfileCollection.java
index 51ee7e6..51132d8 100644
--- a/src/main/java/com/android/tools/r8/profile/art/NonEmptyArtProfileCollection.java
+++ b/src/main/java/com/android/tools/r8/profile/art/NonEmptyArtProfileCollection.java
@@ -99,8 +99,12 @@
   }
 
   @Override
-  public NonEmptyArtProfileCollection withoutPrunedItems(PrunedItems prunedItems) {
-    return map(artProfile -> artProfile.withoutPrunedItems(prunedItems));
+  public NonEmptyArtProfileCollection withoutPrunedItems(PrunedItems prunedItems, Timing timing) {
+    timing.begin("Prune NonEmptyArtProfileCollection");
+    NonEmptyArtProfileCollection result =
+        map(artProfile -> artProfile.withoutPrunedItems(prunedItems));
+    timing.end();
+    return result;
   }
 
   private NonEmptyArtProfileCollection map(Function<ArtProfile, ArtProfile> fn) {
diff --git a/src/main/java/com/android/tools/r8/profile/startup/profile/EmptyStartupProfile.java b/src/main/java/com/android/tools/r8/profile/startup/profile/EmptyStartupProfile.java
index 0030057..a051dc9 100644
--- a/src/main/java/com/android/tools/r8/profile/startup/profile/EmptyStartupProfile.java
+++ b/src/main/java/com/android/tools/r8/profile/startup/profile/EmptyStartupProfile.java
@@ -77,7 +77,7 @@
 
   @Override
   public EmptyStartupProfile withoutPrunedItems(
-      PrunedItems prunedItems, SyntheticItems syntheticItems) {
+      PrunedItems prunedItems, SyntheticItems syntheticItems, Timing timing) {
     return this;
   }
 }
diff --git a/src/main/java/com/android/tools/r8/profile/startup/profile/NonEmptyStartupProfile.java b/src/main/java/com/android/tools/r8/profile/startup/profile/NonEmptyStartupProfile.java
index 34576c3..5ccba97 100644
--- a/src/main/java/com/android/tools/r8/profile/startup/profile/NonEmptyStartupProfile.java
+++ b/src/main/java/com/android/tools/r8/profile/startup/profile/NonEmptyStartupProfile.java
@@ -176,18 +176,23 @@
   }
 
   @Override
-  public StartupProfile withoutPrunedItems(PrunedItems prunedItems, SyntheticItems syntheticItems) {
-    return transform(
-        (classRule, builder) -> {
-          if (!prunedItems.isRemoved(classRule.getReference())) {
-            builder.addClassRule(classRule);
-          }
-        },
-        (methodRule, builder) -> {
-          if (!prunedItems.isRemoved(methodRule.getReference())) {
-            builder.addMethodRule(methodRule);
-          }
-        });
+  public StartupProfile withoutPrunedItems(
+      PrunedItems prunedItems, SyntheticItems syntheticItems, Timing timing) {
+    timing.begin("Prune NonEmptyStartupProfile");
+    StartupProfile result =
+        transform(
+            (classRule, builder) -> {
+              if (!prunedItems.isRemoved(classRule.getReference())) {
+                builder.addClassRule(classRule);
+              }
+            },
+            (methodRule, builder) -> {
+              if (!prunedItems.isRemoved(methodRule.getReference())) {
+                builder.addMethodRule(methodRule);
+              }
+            });
+    timing.end();
+    return result;
   }
 
   private StartupProfile transform(
diff --git a/src/main/java/com/android/tools/r8/profile/startup/profile/StartupProfile.java b/src/main/java/com/android/tools/r8/profile/startup/profile/StartupProfile.java
index cee5637..8ee1fd5 100644
--- a/src/main/java/com/android/tools/r8/profile/startup/profile/StartupProfile.java
+++ b/src/main/java/com/android/tools/r8/profile/startup/profile/StartupProfile.java
@@ -143,7 +143,7 @@
   public abstract StartupProfile withoutMissingItems(AppView<?> appView);
 
   public abstract StartupProfile withoutPrunedItems(
-      PrunedItems prunedItems, SyntheticItems syntheticItems);
+      PrunedItems prunedItems, SyntheticItems syntheticItems, Timing timing);
 
   public static class Builder
       implements AbstractProfile.Builder<
diff --git a/src/main/java/com/android/tools/r8/shaking/AppInfoWithLiveness.java b/src/main/java/com/android/tools/r8/shaking/AppInfoWithLiveness.java
index 7ba4bb8..2f12103 100644
--- a/src/main/java/com/android/tools/r8/shaking/AppInfoWithLiveness.java
+++ b/src/main/java/com/android/tools/r8/shaking/AppInfoWithLiveness.java
@@ -1132,13 +1132,15 @@
    */
   @Override
   public AppInfoWithLiveness prunedCopyFrom(
-      PrunedItems prunedItems, ExecutorService executorService) throws ExecutionException {
+      PrunedItems prunedItems, ExecutorService executorService, Timing timing)
+      throws ExecutionException {
     assert getClass() == AppInfoWithLiveness.class;
     assert checkIfObsolete();
     if (prunedItems.isEmpty()) {
       assert app() == prunedItems.getPrunedApp();
       return this;
     }
+    timing.begin("Pruning AppInfoWithLiveness");
     if (prunedItems.hasRemovedClasses()) {
       // Rebuild the hierarchy.
       objectAllocationInfoCollection.mutate(
@@ -1151,6 +1153,7 @@
     AppInfoWithLiveness appInfoWithLiveness =
         new AppInfoWithLiveness(this, prunedItems, executorService, futures);
     ThreadUtils.awaitFutures(futures);
+    timing.end();
     return appInfoWithLiveness;
   }
 
diff --git a/src/main/java/com/android/tools/r8/shaking/AssumeInfoCollection.java b/src/main/java/com/android/tools/r8/shaking/AssumeInfoCollection.java
index c45b7e3..dd3504b 100644
--- a/src/main/java/com/android/tools/r8/shaking/AssumeInfoCollection.java
+++ b/src/main/java/com/android/tools/r8/shaking/AssumeInfoCollection.java
@@ -85,7 +85,8 @@
     return new AssumeInfoCollection(rewrittenCollection);
   }
 
-  public AssumeInfoCollection withoutPrunedItems(PrunedItems prunedItems) {
+  public AssumeInfoCollection withoutPrunedItems(PrunedItems prunedItems, Timing timing) {
+    timing.begin("Prune AssumeInfoCollection");
     Map<DexMember<?, ?>, AssumeInfo> rewrittenCollection = new IdentityHashMap<>();
     backing.forEach(
         (reference, info) -> {
@@ -96,7 +97,9 @@
             }
           }
         });
-    return new AssumeInfoCollection(rewrittenCollection);
+    AssumeInfoCollection result = new AssumeInfoCollection(rewrittenCollection);
+    timing.end();
+    return result;
   }
 
   public static class Builder {
diff --git a/src/main/java/com/android/tools/r8/shaking/ProguardCompatibilityActions.java b/src/main/java/com/android/tools/r8/shaking/ProguardCompatibilityActions.java
index 373b1e1..88f5f12 100644
--- a/src/main/java/com/android/tools/r8/shaking/ProguardCompatibilityActions.java
+++ b/src/main/java/com/android/tools/r8/shaking/ProguardCompatibilityActions.java
@@ -32,14 +32,17 @@
     return compatInstantiatedTypes.isEmpty();
   }
 
-  public ProguardCompatibilityActions withoutPrunedItems(PrunedItems prunedItems) {
+  public ProguardCompatibilityActions withoutPrunedItems(PrunedItems prunedItems, Timing timing) {
+    timing.begin("Prune ProguardCompatibilityActions");
     Builder builder = builder();
     for (DexType compatInstantiatedType : compatInstantiatedTypes) {
       if (!prunedItems.isRemoved(compatInstantiatedType)) {
         builder.addCompatInstantiatedType(compatInstantiatedType);
       }
     }
-    return builder.build();
+    ProguardCompatibilityActions result = builder.build();
+    timing.end();
+    return result;
   }
 
   public ProguardCompatibilityActions rewrittenWithLens(GraphLens lens, Timing timing) {
diff --git a/src/main/java/com/android/tools/r8/shaking/RootSetUtils.java b/src/main/java/com/android/tools/r8/shaking/RootSetUtils.java
index ad7c388..192de92 100644
--- a/src/main/java/com/android/tools/r8/shaking/RootSetUtils.java
+++ b/src/main/java/com/android/tools/r8/shaking/RootSetUtils.java
@@ -1948,7 +1948,8 @@
           });
     }
 
-    public void pruneItems(PrunedItems prunedItems) {
+    public void pruneItems(PrunedItems prunedItems, Timing timing) {
+      timing.begin("Prune RootSet");
       MinimumKeepInfoCollection unconditionalMinimumKeepInfo =
           getDependentMinimumKeepInfo().getUnconditionalMinimumKeepInfoOrDefault(null);
       if (unconditionalMinimumKeepInfo != null) {
@@ -1957,6 +1958,7 @@
           getDependentMinimumKeepInfo().remove(UnconditionalKeepInfoEvent.get());
         }
       }
+      timing.end();
     }
 
     public RootSet rewrittenWithLens(GraphLens graphLens, Timing timing) {
@@ -2343,20 +2345,21 @@
       return rewrittenMainDexRootSet;
     }
 
-    public MainDexRootSet withoutPrunedItems(PrunedItems prunedItems) {
+    public MainDexRootSet withoutPrunedItems(PrunedItems prunedItems, Timing timing) {
       if (prunedItems.isEmpty()) {
         return this;
       }
+      timing.begin("Prune MainDexRootSet");
       // TODO(b/164019179): If rules can now reference dead items. These should be pruned or
       //  rewritten.
       ifRules.forEach(ProguardIfRule::canReferenceDeadTypes);
       // All delayed root set actions should have been processed at this point.
       assert delayedRootSetActionItems.isEmpty();
-      return new MainDexRootSet(
-          getDependentMinimumKeepInfo(),
-          reasonAsked,
-          ifRules,
-          delayedRootSetActionItems);
+      MainDexRootSet result =
+          new MainDexRootSet(
+              getDependentMinimumKeepInfo(), reasonAsked, ifRules, delayedRootSetActionItems);
+      timing.end();
+      return result;
     }
   }
 }
diff --git a/src/main/java/com/android/tools/r8/shaking/TreePruner.java b/src/main/java/com/android/tools/r8/shaking/TreePruner.java
index d8c17ba..fddfe68 100644
--- a/src/main/java/com/android/tools/r8/shaking/TreePruner.java
+++ b/src/main/java/com/android/tools/r8/shaking/TreePruner.java
@@ -76,13 +76,7 @@
   public PrunedItems run(
       ExecutorService executorService, Timing timing, PrunedItems.Builder prunedItemsBuilder)
       throws ExecutionException {
-    return timing.time(
-        "Pruning application...", () -> internalRun(executorService, prunedItemsBuilder));
-  }
-
-  private PrunedItems internalRun(
-      ExecutorService executorService, PrunedItems.Builder prunedItemsBuilder)
-      throws ExecutionException {
+    timing.begin("Pruning application");
     DirectMappedDexApplication application = appView.appInfo().app().asDirect();
       DirectMappedDexApplication.Builder builder = removeUnused(application);
       DirectMappedDexApplication newApplication =
@@ -90,13 +84,17 @@
               ? application
               : builder.build();
       fixupOptimizationInfo(newApplication, executorService);
-    return prunedItemsBuilder
-        .setPrunedApp(newApplication)
-        .addRemovedClasses(prunedTypes)
-        .addRemovedFields(prunedFields)
-        .addRemovedMethods(prunedMethods)
-        .addAdditionalPinnedItems(methodsToKeepForConfigurationDebugging)
-        .build();
+    PrunedItems prunedItems =
+        prunedItemsBuilder
+            .setPrunedApp(newApplication)
+            .addRemovedClasses(prunedTypes)
+            .addRemovedFields(prunedFields)
+            .addRemovedMethods(prunedMethods)
+            .addAdditionalPinnedItems(methodsToKeepForConfigurationDebugging)
+            .build();
+    appView.pruneItems(prunedItems, executorService, timing);
+    timing.end();
+    return prunedItems;
   }
 
   private DirectMappedDexApplication.Builder removeUnused(DirectMappedDexApplication application) {
diff --git a/src/main/java/com/android/tools/r8/synthesis/SyntheticFinalization.java b/src/main/java/com/android/tools/r8/synthesis/SyntheticFinalization.java
index cf3d627..e7c6a53 100644
--- a/src/main/java/com/android/tools/r8/synthesis/SyntheticFinalization.java
+++ b/src/main/java/com/android/tools/r8/synthesis/SyntheticFinalization.java
@@ -182,7 +182,7 @@
                       .rewrittenWithLens(appView.getSyntheticItems(), result.lens, timing)));
       appView.rewriteWithD8Lens(result.lens, timing);
     }
-    appView.pruneItems(result.prunedItems, executorService);
+    appView.pruneItems(result.prunedItems, executorService, timing);
   }
 
   public static void finalizeWithClassHierarchy(
@@ -196,7 +196,7 @@
     if (result.lens != null) {
       appView.rewriteWithLens(result.lens, executorService, timing);
     }
-    appView.pruneItems(result.prunedItems, executorService);
+    appView.pruneItems(result.prunedItems, executorService, timing);
   }
 
   public static void finalizeWithLiveness(
@@ -212,7 +212,7 @@
       assert result.commit.getApplication() == appView.appInfo().app();
     }
     appView.setAppInfo(appView.appInfo().rebuildWithLiveness(result.commit));
-    appView.pruneItems(result.prunedItems, executorService);
+    appView.pruneItems(result.prunedItems, executorService, timing);
   }
 
   Result computeFinalSynthetics(AppView<?> appView, Timing timing) {