Introduce heuristic for spurious call graph edges
Bug: 133248798
Change-Id: I9c7b272f9c4fa65008892bb5ee92b27f4b708f48
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/CallGraph.java b/src/main/java/com/android/tools/r8/ir/conversion/CallGraph.java
index 5f3ffdb..d692425 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/CallGraph.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/CallGraph.java
@@ -51,7 +51,11 @@
}
public void addCallerConcurrently(Node caller) {
- if (caller != this) {
+ addCallerConcurrently(caller, false);
+ }
+
+ public void addCallerConcurrently(Node caller, boolean likelySpuriousCallEdge) {
+ if (caller != this && !likelySpuriousCallEdge) {
synchronized (callers) {
callers.add(caller);
numberOfCallSites++;
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/CallGraphBuilder.java b/src/main/java/com/android/tools/r8/ir/conversion/CallGraphBuilder.java
index c014d1b..4a659dd 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/CallGraphBuilder.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/CallGraphBuilder.java
@@ -116,8 +116,8 @@
private void addClassInitializerTarget(DexClass clazz) {
assert clazz != null;
- if (clazz.hasClassInitializer() && clazz.isProgramClass()) {
- addTarget(clazz.getClassInitializer());
+ if (clazz.isProgramClass() && clazz.hasClassInitializer()) {
+ addTarget(clazz.getClassInitializer(), false);
}
}
@@ -129,10 +129,10 @@
}
}
- private void addTarget(DexEncodedMethod callee) {
+ private void addTarget(DexEncodedMethod callee, boolean likelySpuriousCallEdge) {
if (!callee.accessFlags.isAbstract()) {
assert callee.isProgramMethod(appView);
- getOrCreateNode(callee).addCallerConcurrently(caller);
+ getOrCreateNode(callee).addCallerConcurrently(caller, likelySpuriousCallEdge);
}
}
@@ -159,7 +159,7 @@
if (type == Type.STATIC) {
addClassInitializerTarget(clazz);
}
- addTarget(singleTarget);
+ addTarget(singleTarget, false);
}
}
}
@@ -188,9 +188,11 @@
? appView.appInfo().lookupInterfaceTargets(method)
: appView.appInfo().lookupVirtualTargets(method));
if (possibleTargets != null) {
+ boolean likelySpuriousCallEdge =
+ possibleTargets.size() >= appView.options().callGraphLikelySpuriousCallEdgeThreshold;
for (DexEncodedMethod possibleTarget : possibleTargets) {
if (possibleTarget.isProgramMethod(appView)) {
- addTarget(possibleTarget);
+ addTarget(possibleTarget, likelySpuriousCallEdge);
}
}
}
diff --git a/src/main/java/com/android/tools/r8/utils/InternalOptions.java b/src/main/java/com/android/tools/r8/utils/InternalOptions.java
index cd82b98..bd17e99 100644
--- a/src/main/java/com/android/tools/r8/utils/InternalOptions.java
+++ b/src/main/java/com/android/tools/r8/utils/InternalOptions.java
@@ -170,6 +170,7 @@
// into stack overflows when the call graph contains large call chains. This should have a
// negligible impact on code size as long as the threshold is large enough.
public int callGraphCycleEliminatorMaxDepthThreshold = 256;
+ public int callGraphLikelySpuriousCallEdgeThreshold = 50;
public int classInliningInstructionLimit = 50;
// This defines the limit of instructions in the inlinee