Add more detailed timing information
Change-Id: I923e63ed536717eb4bca890af53f5fdcc9f5169c
diff --git a/src/main/java/com/android/tools/r8/R8.java b/src/main/java/com/android/tools/r8/R8.java
index 5223520..100b5aa 100644
--- a/src/main/java/com/android/tools/r8/R8.java
+++ b/src/main/java/com/android/tools/r8/R8.java
@@ -717,7 +717,7 @@
// TODO(b/112437944): Avoid iterating the entire application to post-process every
// dynamicMethod() method.
appView.withGeneratedMessageLiteShrinker(
- shrinker -> shrinker.postOptimizeDynamicMethods(converter));
+ shrinker -> shrinker.postOptimizeDynamicMethods(converter, timing));
// If proto shrinking is enabled, we need to post-process every
// findLiteExtensionByNumber() method. This ensures that there are no references to dead
@@ -725,7 +725,7 @@
// TODO(b/112437944): Avoid iterating the entire application to post-process every
// findLiteExtensionByNumber() method.
appView.withGeneratedExtensionRegistryShrinker(
- shrinker -> shrinker.postOptimizeGeneratedExtensionRegistry(converter));
+ shrinker -> shrinker.postOptimizeGeneratedExtensionRegistry(converter, timing));
}
}
diff --git a/src/main/java/com/android/tools/r8/graph/analysis/EnqueuerAnalysis.java b/src/main/java/com/android/tools/r8/graph/analysis/EnqueuerAnalysis.java
index 8374410..29d7dcc 100644
--- a/src/main/java/com/android/tools/r8/graph/analysis/EnqueuerAnalysis.java
+++ b/src/main/java/com/android/tools/r8/graph/analysis/EnqueuerAnalysis.java
@@ -9,6 +9,7 @@
import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.shaking.Enqueuer;
import com.android.tools.r8.shaking.EnqueuerWorklist;
+import com.android.tools.r8.utils.Timing;
public abstract class EnqueuerAnalysis {
@@ -28,7 +29,7 @@
* Called when the Enqueuer reaches a fixpoint. This may happen multiple times, since each
* analysis may enqueue items into the worklist upon the fixpoint using {@param worklist}.
*/
- public void notifyFixpoint(Enqueuer enqueuer, EnqueuerWorklist worklist) {}
+ public void notifyFixpoint(Enqueuer enqueuer, EnqueuerWorklist worklist, Timing timing) {}
/**
* Called when the Enqueuer has reached the final fixpoint. Each analysis may use this callback to
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/fieldvalueanalysis/InstanceFieldValueAnalysis.java b/src/main/java/com/android/tools/r8/ir/analysis/fieldvalueanalysis/InstanceFieldValueAnalysis.java
index e540a06..3e96616 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/fieldvalueanalysis/InstanceFieldValueAnalysis.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/fieldvalueanalysis/InstanceFieldValueAnalysis.java
@@ -30,6 +30,7 @@
import com.android.tools.r8.ir.optimize.info.field.InstanceFieldInitializationInfoCollection;
import com.android.tools.r8.ir.optimize.info.field.InstanceFieldInitializationInfoFactory;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
+import com.android.tools.r8.utils.Timing;
public class InstanceFieldValueAnalysis extends FieldValueAnalysis {
@@ -66,6 +67,20 @@
IRCode code,
ClassInitializerDefaultsResult classInitializerDefaultsResult,
OptimizationFeedback feedback,
+ DexEncodedMethod method,
+ Timing timing) {
+ timing.begin("Analyze instance initializer");
+ InstanceFieldInitializationInfoCollection result =
+ run(appView, code, classInitializerDefaultsResult, feedback, method);
+ timing.end();
+ return result;
+ }
+
+ private static InstanceFieldInitializationInfoCollection run(
+ AppView<?> appView,
+ IRCode code,
+ ClassInitializerDefaultsResult classInitializerDefaultsResult,
+ OptimizationFeedback feedback,
DexEncodedMethod method) {
assert appView.appInfo().hasLiveness();
assert appView.enableWholeProgramOptimizations();
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/fieldvalueanalysis/StaticFieldValueAnalysis.java b/src/main/java/com/android/tools/r8/ir/analysis/fieldvalueanalysis/StaticFieldValueAnalysis.java
index 10dd287..f467406 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/fieldvalueanalysis/StaticFieldValueAnalysis.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/fieldvalueanalysis/StaticFieldValueAnalysis.java
@@ -29,6 +29,7 @@
import com.android.tools.r8.ir.optimize.ClassInitializerDefaultsOptimization.ClassInitializerDefaultsResult;
import com.android.tools.r8.ir.optimize.info.OptimizationFeedback;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
+import com.android.tools.r8.utils.Timing;
public class StaticFieldValueAnalysis extends FieldValueAnalysis {
@@ -46,13 +47,16 @@
IRCode code,
ClassInitializerDefaultsResult classInitializerDefaultsResult,
OptimizationFeedback feedback,
- DexEncodedMethod method) {
+ DexEncodedMethod method,
+ Timing timing) {
assert appView.appInfo().hasLiveness();
assert appView.enableWholeProgramOptimizations();
assert method.isClassInitializer();
+ timing.begin("Analyze class initializer");
DexProgramClass clazz = appView.definitionFor(method.method.holder).asProgramClass();
new StaticFieldValueAnalysis(appView.withLiveness(), code, feedback, clazz, method)
.computeFieldOptimizationInfo(classInitializerDefaultsResult);
+ timing.end();
}
@Override
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/proto/GeneratedExtensionRegistryShrinker.java b/src/main/java/com/android/tools/r8/ir/analysis/proto/GeneratedExtensionRegistryShrinker.java
index 4de5c39..2a70440 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/proto/GeneratedExtensionRegistryShrinker.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/proto/GeneratedExtensionRegistryShrinker.java
@@ -32,6 +32,7 @@
import com.android.tools.r8.shaking.TreePrunerConfiguration;
import com.android.tools.r8.utils.DescriptorUtils;
import com.android.tools.r8.utils.FileUtils;
+import com.android.tools.r8.utils.Timing;
import com.google.common.base.Predicates;
import com.google.common.collect.Sets;
import java.io.IOException;
@@ -155,13 +156,15 @@
return removedExtensionFields.contains(field);
}
- public void postOptimizeGeneratedExtensionRegistry(IRConverter converter) {
+ public void postOptimizeGeneratedExtensionRegistry(IRConverter converter, Timing timing) {
+ timing.begin("[Proto] Post optimize generated extension registry");
forEachFindLiteExtensionByNumberMethod(
method ->
converter.processMethod(
method,
OptimizationFeedbackIgnore.getInstance(),
OneTimeMethodProcessor.getInstance()));
+ timing.end(); // [Proto] Post optimize generated extension registry
}
private void forEachFindLiteExtensionByNumberMethod(Consumer<DexEncodedMethod> consumer) {
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/proto/GeneratedMessageLiteShrinker.java b/src/main/java/com/android/tools/r8/ir/analysis/proto/GeneratedMessageLiteShrinker.java
index cc7307f..b7ceccf 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/proto/GeneratedMessageLiteShrinker.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/proto/GeneratedMessageLiteShrinker.java
@@ -32,6 +32,7 @@
import com.android.tools.r8.ir.conversion.OneTimeMethodProcessor;
import com.android.tools.r8.ir.optimize.info.OptimizationFeedbackIgnore;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
+import com.android.tools.r8.utils.Timing;
import java.util.List;
import java.util.function.Consumer;
@@ -69,13 +70,15 @@
}
}
- public void postOptimizeDynamicMethods(IRConverter converter) {
+ public void postOptimizeDynamicMethods(IRConverter converter, Timing timing) {
+ timing.begin("[Proto] Post optimize dynamic methods");
forEachDynamicMethod(
method ->
converter.processMethod(
method,
OptimizationFeedbackIgnore.getInstance(),
OneTimeMethodProcessor.getInstance()));
+ timing.end();
}
private void forEachDynamicMethod(Consumer<DexEncodedMethod> consumer) {
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/proto/schema/ProtoEnqueuerExtension.java b/src/main/java/com/android/tools/r8/ir/analysis/proto/schema/ProtoEnqueuerExtension.java
index bf6c8b1..e2837c4 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/proto/schema/ProtoEnqueuerExtension.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/proto/schema/ProtoEnqueuerExtension.java
@@ -37,6 +37,7 @@
import com.android.tools.r8.shaking.KeepReason;
import com.android.tools.r8.utils.BitUtils;
import com.android.tools.r8.utils.OptionalBool;
+import com.android.tools.r8.utils.Timing;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Sets;
import java.util.IdentityHashMap;
@@ -171,7 +172,8 @@
}
@Override
- public void notifyFixpoint(Enqueuer enqueuer, EnqueuerWorklist worklist) {
+ public void notifyFixpoint(Enqueuer enqueuer, EnqueuerWorklist worklist, Timing timing) {
+ timing.begin("[Proto] Extend fixpoint");
populateExtensionGraph(enqueuer);
markMapOrRequiredFieldsAsReachable(enqueuer, worklist);
@@ -187,6 +189,7 @@
tracePendingInstructionsInDynamicMethods(enqueuer, worklist);
}
}
+ timing.end();
}
/**
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 d968d31..a0934cd 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
@@ -1599,15 +1599,20 @@
if (method.isInitializer()) {
if (method.isClassInitializer()) {
StaticFieldValueAnalysis.run(
- appView, code, classInitializerDefaultsResult, feedback, code.method);
+ appView, code, classInitializerDefaultsResult, feedback, code.method, timing);
} else {
instanceFieldInitializationInfos =
InstanceFieldValueAnalysis.run(
- appView, code, classInitializerDefaultsResult, feedback, code.method);
+ appView, code, classInitializerDefaultsResult, feedback, code.method, timing);
}
}
methodOptimizationInfoCollector.collectMethodOptimizationInfo(
- code.method, code, feedback, dynamicTypeOptimization, instanceFieldInitializationInfos);
+ code.method,
+ code,
+ feedback,
+ dynamicTypeOptimization,
+ instanceFieldInitializationInfos,
+ timing);
}
public void removeDeadCodeAndFinalizeIR(
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 bbf2f22..05e6fa5 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
@@ -95,6 +95,7 @@
import com.android.tools.r8.utils.ListUtils;
import com.android.tools.r8.utils.MethodSignatureEquivalence;
import com.android.tools.r8.utils.Pair;
+import com.android.tools.r8.utils.Timing;
import com.android.tools.r8.utils.WorkList;
import com.google.common.base.Equivalence.Wrapper;
import com.google.common.collect.Sets;
@@ -123,20 +124,29 @@
IRCode code,
OptimizationFeedback feedback,
DynamicTypeOptimization dynamicTypeOptimization,
- InstanceFieldInitializationInfoCollection instanceFieldInitializationInfos) {
- identifyClassInlinerEligibility(method, code, feedback);
- identifyParameterUsages(method, code, feedback);
- identifyReturnsArgument(method, code, feedback);
+ InstanceFieldInitializationInfoCollection instanceFieldInitializationInfos,
+ Timing timing) {
+ identifyClassInlinerEligibility(method, code, feedback, timing);
+ identifyParameterUsages(method, code, feedback, timing);
+ identifyReturnsArgument(method, code, feedback, timing);
if (options.enableInlining) {
- identifyInvokeSemanticsForInlining(method, code, appView, feedback);
+ identifyInvokeSemanticsForInlining(method, code, feedback, timing);
}
- computeDynamicReturnType(dynamicTypeOptimization, feedback, method, code);
- computeInitializedClassesOnNormalExit(feedback, method, code);
- computeInstanceInitializerInfo(method, code, feedback, instanceFieldInitializationInfos);
- computeMayHaveSideEffects(feedback, method, code);
- computeReturnValueOnlyDependsOnArguments(feedback, method, code);
- computeNonNullParamOrThrow(feedback, method, code);
- computeNonNullParamOnNormalExits(feedback, code);
+ computeDynamicReturnType(dynamicTypeOptimization, feedback, method, code, timing);
+ computeInitializedClassesOnNormalExit(feedback, method, code, timing);
+ computeInstanceInitializerInfo(
+ method, code, feedback, instanceFieldInitializationInfos, timing);
+ computeMayHaveSideEffects(feedback, method, code, timing);
+ computeReturnValueOnlyDependsOnArguments(feedback, method, code, timing);
+ computeNonNullParamOrThrow(feedback, method, code, timing);
+ computeNonNullParamOnNormalExits(feedback, code, timing);
+ }
+
+ private void identifyClassInlinerEligibility(
+ DexEncodedMethod method, IRCode code, OptimizationFeedback feedback, Timing timing) {
+ timing.begin("Identify class inliner eligibility");
+ identifyClassInlinerEligibility(method, code, feedback);
+ timing.end();
}
private void identifyClassInlinerEligibility(
@@ -283,6 +293,13 @@
}
private void identifyParameterUsages(
+ DexEncodedMethod method, IRCode code, OptimizationFeedback feedback, Timing timing) {
+ timing.begin("Identify parameter usages");
+ identifyParameterUsages(method, code, feedback);
+ timing.end();
+ }
+
+ private void identifyParameterUsages(
DexEncodedMethod method, IRCode code, OptimizationFeedback feedback) {
List<ParameterUsage> usages = new ArrayList<>();
List<Value> values = code.collectArguments();
@@ -322,6 +339,13 @@
}
private void identifyReturnsArgument(
+ DexEncodedMethod method, IRCode code, OptimizationFeedback feedback, Timing timing) {
+ timing.begin("Identify returns argument");
+ identifyReturnsArgument(method, code, feedback);
+ timing.end();
+ }
+
+ private void identifyReturnsArgument(
DexEncodedMethod method, IRCode code, OptimizationFeedback feedback) {
List<BasicBlock> normalExits = code.computeNormalExitBlocks();
if (normalExits.isEmpty()) {
@@ -365,6 +389,17 @@
DexEncodedMethod method,
IRCode code,
OptimizationFeedback feedback,
+ InstanceFieldInitializationInfoCollection instanceFieldInitializationInfos,
+ Timing timing) {
+ timing.begin("Compute instance initializer info");
+ computeInstanceInitializerInfo(method, code, feedback, instanceFieldInitializationInfos);
+ timing.end();
+ }
+
+ private void computeInstanceInitializerInfo(
+ DexEncodedMethod method,
+ IRCode code,
+ OptimizationFeedback feedback,
InstanceFieldInitializationInfoCollection instanceFieldInitializationInfos) {
assert !appView.appInfo().isPinned(method.method);
@@ -641,7 +676,14 @@
}
private void identifyInvokeSemanticsForInlining(
- DexEncodedMethod method, IRCode code, AppView<?> appView, OptimizationFeedback feedback) {
+ DexEncodedMethod method, IRCode code, OptimizationFeedback feedback, Timing timing) {
+ timing.begin("Identify invoke semantics for inlining");
+ identifyInvokeSemanticsForInlining(method, code, feedback);
+ timing.end();
+ }
+
+ private void identifyInvokeSemanticsForInlining(
+ DexEncodedMethod method, IRCode code, OptimizationFeedback feedback) {
if (method.isStatic()) {
// Identifies if the method preserves class initialization after inlining.
feedback.markTriggerClassInitBeforeAnySideEffect(
@@ -899,6 +941,17 @@
DynamicTypeOptimization dynamicTypeOptimization,
OptimizationFeedback feedback,
DexEncodedMethod method,
+ IRCode code,
+ Timing timing) {
+ timing.begin("Compute dynamic return type");
+ computeDynamicReturnType(dynamicTypeOptimization, feedback, method, code);
+ timing.end();
+ }
+
+ private void computeDynamicReturnType(
+ DynamicTypeOptimization dynamicTypeOptimization,
+ OptimizationFeedback feedback,
+ DexEncodedMethod method,
IRCode code) {
if (dynamicTypeOptimization != null) {
DexType staticReturnTypeRaw = method.method.proto.returnType;
@@ -925,6 +978,13 @@
}
private void computeInitializedClassesOnNormalExit(
+ OptimizationFeedback feedback, DexEncodedMethod method, IRCode code, Timing timing) {
+ timing.begin("Compute initialized classes on normal exits");
+ computeInitializedClassesOnNormalExit(feedback, method, code);
+ timing.end();
+ }
+
+ private void computeInitializedClassesOnNormalExit(
OptimizationFeedback feedback, DexEncodedMethod method, IRCode code) {
if (options.enableInitializedClassesAnalysis && appView.appInfo().hasLiveness()) {
AppView<AppInfoWithLiveness> appViewWithLiveness = appView.withLiveness();
@@ -938,6 +998,13 @@
}
private void computeMayHaveSideEffects(
+ OptimizationFeedback feedback, DexEncodedMethod method, IRCode code, Timing timing) {
+ timing.begin("Compute may have side effects");
+ computeMayHaveSideEffects(feedback, method, code);
+ timing.end();
+ }
+
+ private void computeMayHaveSideEffects(
OptimizationFeedback feedback, DexEncodedMethod method, IRCode code) {
// If the method is native, we don't know what could happen.
assert !method.accessFlags.isNative();
@@ -1018,6 +1085,13 @@
}
private void computeReturnValueOnlyDependsOnArguments(
+ OptimizationFeedback feedback, DexEncodedMethod method, IRCode code, Timing timing) {
+ timing.begin("Return value only depends on argument");
+ computeReturnValueOnlyDependsOnArguments(feedback, method, code);
+ timing.end();
+ }
+
+ private void computeReturnValueOnlyDependsOnArguments(
OptimizationFeedback feedback, DexEncodedMethod method, IRCode code) {
if (!options.enableDeterminismAnalysis) {
return;
@@ -1029,6 +1103,13 @@
}
}
+ private void computeNonNullParamOrThrow(
+ OptimizationFeedback feedback, DexEncodedMethod method, IRCode code, Timing timing) {
+ timing.begin("Compute non-null-param-or-throw");
+ computeReturnValueOnlyDependsOnArguments(feedback, method, code);
+ timing.end();
+ }
+
// Track usage of parameters and compute their nullability and possibility of NPE.
private void computeNonNullParamOrThrow(
OptimizationFeedback feedback, DexEncodedMethod method, IRCode code) {
@@ -1058,6 +1139,13 @@
}
}
+ private void computeNonNullParamOnNormalExits(
+ OptimizationFeedback feedback, IRCode code, Timing timing) {
+ timing.begin("Compute non-null-param-on-normal-exits");
+ computeNonNullParamOnNormalExits(feedback, code, timing);
+ timing.end();
+ }
+
private void computeNonNullParamOnNormalExits(OptimizationFeedback feedback, IRCode code) {
Set<BasicBlock> normalExits = Sets.newIdentityHashSet();
normalExits.addAll(code.computeNormalExitBlocks());
diff --git a/src/main/java/com/android/tools/r8/shaking/Enqueuer.java b/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
index 2bc230c..1dd374d 100644
--- a/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
+++ b/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
@@ -2893,7 +2893,7 @@
// Notify each analysis that a fixpoint has been reached, and give each analysis an
// opportunity to add items to the worklist.
- analyses.forEach(analysis -> analysis.notifyFixpoint(this, workList));
+ analyses.forEach(analysis -> analysis.notifyFixpoint(this, workList, timing));
if (!workList.isEmpty()) {
continue;
}