Add timing information to class inliner analysis

Change-Id: I9c68aae8d6814b76cc1c1577f8a666dd48d092b7
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/framework/intraprocedural/IntraproceduralDataflowAnalysis.java b/src/main/java/com/android/tools/r8/ir/analysis/framework/intraprocedural/IntraproceduralDataflowAnalysis.java
index 60136ce..dccf7e5 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/framework/intraprocedural/IntraproceduralDataflowAnalysis.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/framework/intraprocedural/IntraproceduralDataflowAnalysis.java
@@ -8,6 +8,7 @@
 import com.android.tools.r8.ir.analysis.framework.intraprocedural.DataflowAnalysisResult.SuccessfulDataflowAnalysisResult;
 import com.android.tools.r8.ir.code.BasicBlock;
 import com.android.tools.r8.ir.code.Instruction;
+import com.android.tools.r8.utils.Timing;
 import com.android.tools.r8.utils.WorkList;
 import java.util.IdentityHashMap;
 import java.util.Map;
@@ -40,20 +41,29 @@
   }
 
   public DataflowAnalysisResult run(BasicBlock root) {
-    return run(WorkList.newIdentityWorkList(root));
+    return run(root, Timing.empty());
   }
 
-  private DataflowAnalysisResult run(WorkList<BasicBlock> worklist) {
+  public DataflowAnalysisResult run(BasicBlock root, Timing timing) {
+    return run(WorkList.newIdentityWorkList(root), timing);
+  }
+
+  private DataflowAnalysisResult run(WorkList<BasicBlock> worklist, Timing timing) {
     while (worklist.hasNext()) {
-      BasicBlock block = worklist.next();
+      BasicBlock initialBlock = worklist.next();
+      BasicBlock block = initialBlock;
       BasicBlock end = null;
       // Compute the abstract state upon entry to the basic block, by joining all the predecessor
       // exit states.
-      StateType state = computeBlockEntryState(block);
+      StateType state =
+          timing.time("Compute block entry state", () -> computeBlockEntryState(initialBlock));
+
+      timing.begin("Compute transfers");
       do {
         for (Instruction instruction : block.getInstructions()) {
           TransferFunctionResult<StateType> transferResult = transfer.apply(instruction, state);
           if (transferResult.isFailedTransferResult()) {
+            timing.end();
             return new FailedDataflowAnalysisResult();
           }
           assert transferResult.isAbstractState();
@@ -66,6 +76,8 @@
           block = null;
         }
       } while (block != null);
+      timing.end();
+
       // Update the block exit state, and re-enqueue all successor blocks if the abstract state
       // changed.
       if (setBlockExitState(end, state)) {
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/classinliner/analysis/ClassInlinerMethodConstraintAnalysis.java b/src/main/java/com/android/tools/r8/ir/optimize/classinliner/analysis/ClassInlinerMethodConstraintAnalysis.java
index b8f406a..854188e 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/classinliner/analysis/ClassInlinerMethodConstraintAnalysis.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/classinliner/analysis/ClassInlinerMethodConstraintAnalysis.java
@@ -12,11 +12,12 @@
 import com.android.tools.r8.ir.optimize.classinliner.constraint.ClassInlinerMethodConstraint;
 import com.android.tools.r8.ir.optimize.classinliner.constraint.ConditionalClassInlinerMethodConstraint;
 import com.android.tools.r8.shaking.AppInfoWithLiveness;
+import com.android.tools.r8.utils.Timing;
 
 public class ClassInlinerMethodConstraintAnalysis {
 
   public static ClassInlinerMethodConstraint analyze(
-      AppView<AppInfoWithLiveness> appView, ProgramMethod method, IRCode code) {
+      AppView<AppInfoWithLiveness> appView, ProgramMethod method, IRCode code, Timing timing) {
     if (method.getDefinition().isClassInitializer()
         || method.getDefinition().getNumberOfArguments() == 0) {
       return ClassInlinerMethodConstraint.alwaysFalse();
@@ -27,11 +28,13 @@
         new IntraproceduralDataflowAnalysis<>(
             ParameterUsages.bottom(), new TransferFunction(appView, method, code));
     SuccessfulDataflowAnalysisResult<ParameterUsages> result =
-        analysis.run(code.entryBlock()).asSuccessfulAnalysisResult();
+        timing.time(
+            "Data flow analysis",
+            () -> analysis.run(code.entryBlock(), timing).asSuccessfulAnalysisResult());
     if (result == null) {
       return ClassInlinerMethodConstraint.alwaysFalse();
     }
-    ParameterUsages usages = result.join().externalize();
+    ParameterUsages usages = timing.time("Externalize", () -> result.join().externalize());
     if (usages.isBottom()) {
       return ClassInlinerMethodConstraint.alwaysTrue();
     }
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/info/MethodOptimizationInfoCollector.java b/src/main/java/com/android/tools/r8/ir/optimize/info/MethodOptimizationInfoCollector.java
index 9836791..e28b6ad 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/info/MethodOptimizationInfoCollector.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/info/MethodOptimizationInfoCollector.java
@@ -783,15 +783,10 @@
       OptimizationFeedback feedback,
       Timing timing) {
     timing.begin("Compute class inlining constraint");
-    computeClassInlinerMethodConstraint(method, code, feedback);
-    timing.end();
-  }
-
-  private void computeClassInlinerMethodConstraint(
-      ProgramMethod method, IRCode code, OptimizationFeedback feedback) {
     ClassInlinerMethodConstraint classInlinerMethodConstraint =
-        ClassInlinerMethodConstraintAnalysis.analyze(appView, method, code);
+        ClassInlinerMethodConstraintAnalysis.analyze(appView, method, code, timing);
     feedback.setClassInlinerMethodConstraint(method, classInlinerMethodConstraint);
+    timing.end();
   }
 
   private void computeEnumUnboxerMethodClassification(
diff --git a/src/main/java/com/android/tools/r8/utils/Timing.java b/src/main/java/com/android/tools/r8/utils/Timing.java
index 5652476..c1046e9 100644
--- a/src/main/java/com/android/tools/r8/utils/Timing.java
+++ b/src/main/java/com/android/tools/r8/utils/Timing.java
@@ -21,6 +21,7 @@
 import java.util.Map;
 import java.util.Map.Entry;
 import java.util.Stack;
+import java.util.function.Supplier;
 
 public class Timing {
 
@@ -370,6 +371,15 @@
     stack.push(child);
   }
 
+  public <T> T time(String title, Supplier<T> supplier) {
+    begin(title);
+    try {
+      return supplier.get();
+    } finally {
+      end();
+    }
+  }
+
   public void end() {
     stack.peek().end();  // record time.
     stack.pop();