Extend materialized rule merging to rules with members in precondition
Change-Id: Ia9dcd07127a0a48ae0befa31e5b5fd56a0faba34
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 5897798..583380c 100644
--- a/src/main/java/com/android/tools/r8/shaking/IfRuleEvaluator.java
+++ b/src/main/java/com/android/tools/r8/shaking/IfRuleEvaluator.java
@@ -30,7 +30,7 @@
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ExecutionException;
-import java.util.function.Consumer;
+import java.util.function.BiPredicate;
import java.util.function.Predicate;
import java.util.stream.Collectors;
@@ -76,15 +76,8 @@
ifRuleKey.relevantCandidatesForRule(
appView, subtypingInfo, classesWithNewlyLiveMembers, isEffectivelyLive)) {
assert isEffectivelyLive.test(clazz);
- evaluateRuleOnEffectivelyLiveClass(
- ifRuleKey,
- ifRulesInEquivalence,
- clazz,
- matchedIfRule -> {
- if (canRemoveSubsequentKeepRule(matchedIfRule)) {
- toRemove.add(matchedIfRule);
- }
- });
+ processActiveIfRulesWithMembersAndSameClassPrecondition(
+ ifRuleKey, ifRulesInEquivalence, clazz, toRemove);
}
if (ifRulesInEquivalence.size() == toRemove.size()) {
return true;
@@ -95,6 +88,38 @@
tasks.await();
}
+ private void processActiveIfRulesWithMembersAndSameClassPrecondition(
+ ProguardIfRule ifRuleKey,
+ Set<ProguardIfRule> ifRulesInEquivalence,
+ DexProgramClass clazz,
+ List<ProguardIfRule> toRemove) {
+ // Check if the class matches the if-rule.
+ if (!evaluateClassForIfRule(ifRuleKey, clazz)) {
+ return;
+ }
+ // When matching an if rule against a type, the if-rule are filled with the current
+ // capture of wildcards. Propagate this down to member rules with same class part
+ // equivalence.
+ for (ProguardIfRule ifRule : ifRulesInEquivalence) {
+ registerClassCapture(ifRule, clazz, clazz);
+ List<Pair<ProguardIfRulePreconditionMatch, ProguardKeepRule>> materializedSubsequentRules =
+ new ArrayList<>();
+ evaluateIfRuleMembersAndMaterialize(
+ ifRule,
+ clazz,
+ (ifRulePreconditionMatch, materializedSubsequentRule) -> {
+ materializedSubsequentRules.add(
+ new Pair<>(ifRulePreconditionMatch, materializedSubsequentRule));
+ if (canRemoveSubsequentKeepRule(ifRule)) {
+ toRemove.add(ifRule);
+ return true;
+ }
+ return false;
+ });
+ applyMaterializedSubsequentRules(ifRule, materializedSubsequentRules);
+ }
+ }
+
public void processActiveIfRulesWithoutMembers(
Map<Wrapper<ProguardIfRule>, Set<ProguardIfRule>> ifRules,
Iterable<DexProgramClass> newlyLiveClasses)
@@ -144,36 +169,10 @@
break;
}
}
- materializedSubsequentRules =
- MaterializedSubsequentRulesOptimizer.optimize(ifRule, materializedSubsequentRules);
- for (Pair<ProguardIfRulePreconditionMatch, ProguardKeepRule> pair :
- materializedSubsequentRules) {
- ProguardIfRulePreconditionMatch ifRulePreconditionMatch = pair.getFirst();
- ProguardKeepRule materializedSubsequentRule = pair.getSecond();
- applyMaterializedSubsequentRule(materializedSubsequentRule, ifRulePreconditionMatch);
- }
+ applyMaterializedSubsequentRules(ifRule, materializedSubsequentRules);
return isSubsequentRuleFullyEvaluated;
}
- private void evaluateRuleOnEffectivelyLiveClass(
- ProguardIfRule ifRuleKey,
- Set<ProguardIfRule> ifRulesInEquivalence,
- DexProgramClass clazz,
- Consumer<ProguardIfRule> matchedConsumer)
- throws ExecutionException {
- // Check if the class matches the if-rule.
- if (!evaluateClassForIfRule(ifRuleKey, clazz)) {
- return;
- }
- // When matching an if rule against a type, the if-rule are filled with the current
- // capture of wildcards. Propagate this down to member rules with same class part
- // equivalence.
- for (ProguardIfRule ifRule : ifRulesInEquivalence) {
- registerClassCapture(ifRule, clazz, clazz);
- evaluateIfRuleMembersAndMaterialize(ifRule, clazz, matchedConsumer);
- }
- }
-
private void incrementNumberOfProguardIfRuleClassEvaluations() {
if (appView.testing().measureProguardIfRuleEvaluations) {
appView.testing().proguardIfRuleEvaluationData.numberOfProguardIfRuleClassEvaluations++;
@@ -232,8 +231,9 @@
}
private void evaluateIfRuleMembersAndMaterialize(
- ProguardIfRule rule, DexProgramClass clazz, Consumer<ProguardIfRule> matchedConsumer)
- throws ExecutionException {
+ ProguardIfRule rule,
+ DexProgramClass clazz,
+ BiPredicate<ProguardIfRulePreconditionMatch, ProguardKeepRule> materializedIfRuleConsumer) {
incrementNumberOfProguardIfRuleMemberEvaluations();
Collection<ProguardMemberRule> memberKeepRules = rule.getMemberRules();
assert !memberKeepRules.isEmpty();
@@ -332,9 +332,7 @@
new ProguardIfRulePreconditionMatch(rule, clazz, methodsSatisfyingRule);
ifRulePreconditionMatch.disallowOptimizationsForReevaluation(enqueuer, rootSetBuilder);
ProguardKeepRule materializedSubsequentRule = rule.materialize(factory);
- applyMaterializedSubsequentRule(materializedSubsequentRule, ifRulePreconditionMatch);
- if (canRemoveSubsequentKeepRule(rule)) {
- matchedConsumer.accept(rule);
+ if (materializedIfRuleConsumer.test(ifRulePreconditionMatch, materializedSubsequentRule)) {
return;
}
}
@@ -350,6 +348,19 @@
return field.getOrComputeIsInlinableByJavaC(factory);
}
+ private void applyMaterializedSubsequentRules(
+ ProguardIfRule ifRule,
+ List<Pair<ProguardIfRulePreconditionMatch, ProguardKeepRule>> materializedSubsequentRules) {
+ materializedSubsequentRules =
+ MaterializedSubsequentRulesOptimizer.optimize(ifRule, materializedSubsequentRules);
+ for (Pair<ProguardIfRulePreconditionMatch, ProguardKeepRule> pair :
+ materializedSubsequentRules) {
+ ProguardIfRulePreconditionMatch ifRulePreconditionMatch = pair.getFirst();
+ ProguardKeepRule materializedSubsequentRule = pair.getSecond();
+ applyMaterializedSubsequentRule(materializedSubsequentRule, ifRulePreconditionMatch);
+ }
+ }
+
private void applyMaterializedSubsequentRule(
ProguardKeepRule materializedSubsequentRule,
ProguardIfRulePreconditionMatch ifRulePreconditionMatch) {
diff --git a/src/main/java/com/android/tools/r8/shaking/ProguardClassSpecification.java b/src/main/java/com/android/tools/r8/shaking/ProguardClassSpecification.java
index 63e6b5a..98f41cd 100644
--- a/src/main/java/com/android/tools/r8/shaking/ProguardClassSpecification.java
+++ b/src/main/java/com/android/tools/r8/shaking/ProguardClassSpecification.java
@@ -253,7 +253,7 @@
}
public boolean hasMemberRules() {
- return memberRules != null && !memberRules.isEmpty();
+ return !memberRules.isEmpty();
}
public ProguardMemberRule getMemberRule(int index) {
diff --git a/src/main/java/com/android/tools/r8/shaking/ifrules/MaterializedSubsequentRulesOptimizer.java b/src/main/java/com/android/tools/r8/shaking/ifrules/MaterializedSubsequentRulesOptimizer.java
index 3cbb5a0..adb78d5 100644
--- a/src/main/java/com/android/tools/r8/shaking/ifrules/MaterializedSubsequentRulesOptimizer.java
+++ b/src/main/java/com/android/tools/r8/shaking/ifrules/MaterializedSubsequentRulesOptimizer.java
@@ -17,6 +17,7 @@
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.List;
import java.util.Objects;
@@ -100,7 +101,7 @@
memberRules = new ArrayList<>(representativeKeepRule.getMemberRules());
memberRules.set(memberRuleWithBackReferenceIndex, replacementMemberRule);
} else {
- memberRules = null;
+ memberRules = Collections.emptyList();
}
ProguardKeepRule replacementKeepRule =
new ProguardKeepRule(