Reapply "Avoid computing effectively live info in each if rule evaluation"
This reverts commit 6095462ec66eefe9e79f1b3c6e80711910b26fad.
Change-Id: Ic2b02854a9a1e1d7710d0ca32cab8e3a6aee7ac9
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 096b704..46d4c02 100644
--- a/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
+++ b/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
@@ -3531,29 +3531,6 @@
return liveTypes.contains(clazz);
}
- public boolean isEffectivelyLive(DexProgramClass clazz) {
- if (isTypeLive(clazz)) {
- return true;
- }
- if (mode.isInitialTreeShaking()) {
- return false;
- }
- // TODO(b/325014359): Replace this by value tracking in instructions (akin to resource values).
- for (DexEncodedField field : clazz.fields()) {
- if (field.getOptimizationInfo().valueHasBeenPropagated()) {
- return true;
- }
- }
- // TODO(b/325014359): Replace this by value or position tracking.
- // We need to be careful not to throw away such values/positions.
- for (DexEncodedMethod method : clazz.methods()) {
- if (method.getOptimizationInfo().returnValueHasBeenPropagated()) {
- return true;
- }
- }
- return false;
- }
-
public boolean isOriginalReferenceEffectivelyLive(DexReference reference) {
// The effectively-live original set contains types, fields and methods witnessed by
// instructions, such as method inlining positions.
diff --git a/src/main/java/com/android/tools/r8/shaking/IfRuleEvaluator.java b/src/main/java/com/android/tools/r8/shaking/IfRuleEvaluator.java
index 72563e2..4841933 100644
--- a/src/main/java/com/android/tools/r8/shaking/IfRuleEvaluator.java
+++ b/src/main/java/com/android/tools/r8/shaking/IfRuleEvaluator.java
@@ -52,7 +52,9 @@
this.tasks = tasks;
}
- public void run(Map<Wrapper<ProguardIfRule>, Set<ProguardIfRule>> ifRules)
+ public void run(
+ Map<Wrapper<ProguardIfRule>, Set<ProguardIfRule>> ifRules,
+ Set<DexProgramClass> effectivelyFakeLiveClasses)
throws ExecutionException {
MapUtils.removeIf(
ifRules,
@@ -66,7 +68,7 @@
for (DexProgramClass clazz :
ifRuleKey.relevantCandidatesForRule(
appView, subtypingInfo, appView.appInfo().classes())) {
- if (!isEffectivelyLive(clazz)) {
+ if (!isEffectivelyLive(clazz, effectivelyFakeLiveClasses)) {
continue;
}
evaluateRuleOnEffectivelyLiveClass(
@@ -88,6 +90,11 @@
tasks.await();
}
+ private boolean isEffectivelyLive(
+ DexProgramClass clazz, Set<DexProgramClass> effectivelyFakeLiveClasses) {
+ return enqueuer.isTypeLive(clazz) || effectivelyFakeLiveClasses.contains(clazz);
+ }
+
private void evaluateRuleOnEffectivelyLiveClass(
ProguardIfRule ifRuleKey,
Set<ProguardIfRule> ifRulesInEquivalence,
@@ -140,10 +147,6 @@
}
}
- private boolean isEffectivelyLive(DexProgramClass clazz) {
- return enqueuer.isEffectivelyLive(clazz);
- }
-
/** Determines if {@param clazz} satisfies the given if-rule class specification. */
private boolean evaluateClassForIfRule(ProguardIfRule rule, DexProgramClass clazz) {
incrementNumberOfProguardIfRuleClassEvaluations();
diff --git a/src/main/java/com/android/tools/r8/shaking/IfRuleEvaluatorFactory.java b/src/main/java/com/android/tools/r8/shaking/IfRuleEvaluatorFactory.java
index 28a61ff..5857e14 100644
--- a/src/main/java/com/android/tools/r8/shaking/IfRuleEvaluatorFactory.java
+++ b/src/main/java/com/android/tools/r8/shaking/IfRuleEvaluatorFactory.java
@@ -7,12 +7,16 @@
import com.android.tools.r8.graph.AppInfoWithClassHierarchy;
import com.android.tools.r8.graph.AppView;
+import com.android.tools.r8.graph.DexEncodedField;
+import com.android.tools.r8.graph.DexEncodedMethod;
+import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.SubtypingInfo;
import com.android.tools.r8.shaking.RootSetUtils.ConsequentRootSet;
import com.android.tools.r8.shaking.RootSetUtils.ConsequentRootSetBuilder;
import com.android.tools.r8.threading.TaskCollection;
import com.android.tools.r8.utils.Timing;
import com.google.common.base.Equivalence.Wrapper;
+import com.google.common.collect.Sets;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashSet;
@@ -29,6 +33,8 @@
/** Map of active if rules. This is important for speeding up aapt2 generated keep rules. */
private final Map<Wrapper<ProguardIfRule>, Set<ProguardIfRule>> activeIfRules;
+ private final Set<DexProgramClass> effectivelyFakeLiveClasses;
+
private final TaskCollection<?> tasks;
public IfRuleEvaluatorFactory(
@@ -38,6 +44,7 @@
this.appView = appView;
this.enqueuer = enqueuer;
this.activeIfRules = createActiveIfRules(appView.rootSet().ifRules);
+ this.effectivelyFakeLiveClasses = createEffectivelyFakeLiveClasses(appView, enqueuer);
this.tasks = new TaskCollection<>(appView.options(), executorService);
}
@@ -58,6 +65,38 @@
return activeIfRules;
}
+ @SuppressWarnings("MixedMutabilityReturnType")
+ private static Set<DexProgramClass> createEffectivelyFakeLiveClasses(
+ AppView<? extends AppInfoWithClassHierarchy> appView, Enqueuer enqueuer) {
+ if (enqueuer.getMode().isInitialTreeShaking()) {
+ return Collections.emptySet();
+ }
+ Set<DexProgramClass> effectivelyFakeLiveClasses = Sets.newIdentityHashSet();
+ for (DexProgramClass clazz : appView.appInfo().classes()) {
+ if (isFakeEffectiveLive(clazz)) {
+ effectivelyFakeLiveClasses.add(clazz);
+ }
+ }
+ return effectivelyFakeLiveClasses;
+ }
+
+ private static boolean isFakeEffectiveLive(DexProgramClass clazz) {
+ // TODO(b/325014359): Replace this by value tracking in instructions (akin to resource values).
+ for (DexEncodedField field : clazz.fields()) {
+ if (field.getOptimizationInfo().valueHasBeenPropagated()) {
+ return true;
+ }
+ }
+ // TODO(b/325014359): Replace this by value or position tracking.
+ // We need to be careful not to throw away such values/positions.
+ for (DexEncodedMethod method : clazz.methods()) {
+ if (method.getOptimizationInfo().returnValueHasBeenPropagated()) {
+ return true;
+ }
+ }
+ return false;
+ }
+
public void run(SubtypingInfo subtypingInfo, Timing timing) throws ExecutionException {
if (activeIfRules.isEmpty()) {
return;
@@ -66,7 +105,9 @@
ConsequentRootSet.builder(appView, enqueuer, subtypingInfo);
IfRuleEvaluator evaluator =
new IfRuleEvaluator(appView, subtypingInfo, enqueuer, consequentRootSetBuilder, tasks);
- timing.time("Find consequent items for -if rules...", () -> evaluator.run(activeIfRules));
+ timing.time(
+ "Find consequent items for -if rules...",
+ () -> evaluator.run(activeIfRules, effectivelyFakeLiveClasses));
enqueuer.addConsequentRootSet(consequentRootSetBuilder.buildConsequentRootSet());
}
}