Don't prune conditional rules in the same "wave".

Doing so leads to non-deterministic choices in which rule instance is
applied. That is observable by the kept-graph info (which the code was
previously conditional on) and on errors that may happen in the rule
evaluations.

Change-Id: Iec5927839848a1d9306646ab6c99edcb0f00cc65
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 d5c8c68..e5041d8 100644
--- a/src/main/java/com/android/tools/r8/shaking/IfRuleEvaluator.java
+++ b/src/main/java/com/android/tools/r8/shaking/IfRuleEvaluator.java
@@ -71,15 +71,17 @@
             ifRules.entrySet().iterator();
         while (it.hasNext()) {
           Map.Entry<Wrapper<ProguardIfRule>, Set<ProguardIfRule>> ifRuleEntry = it.next();
-          ProguardIfRule ifRule = ifRuleEntry.getKey().get();
+          ProguardIfRule ifRuleKey = ifRuleEntry.getKey().get();
+          Set<ProguardIfRule> ifRulesInEquivalence = ifRuleEntry.getValue();
           ProguardIfRuleEvaluationData ifRuleEvaluationData =
               appView.options().testing.proguardIfRuleEvaluationData;
+          List<ProguardIfRule> toRemove = new ArrayList<>();
 
           // Depending on which types that trigger the -if rule, the application of the subsequent
           // -keep rule may vary (due to back references). So, we need to try all pairs of -if
           // rule and live types.
           for (DexProgramClass clazz :
-              ifRule.relevantCandidatesForRule(
+              ifRuleKey.relevantCandidatesForRule(
                   appView, subtypingInfo, appView.appInfo().classes())) {
             if (!isEffectivelyLive(clazz)) {
               continue;
@@ -89,21 +91,21 @@
             if (appView.options().testing.measureProguardIfRuleEvaluations) {
               ifRuleEvaluationData.numberOfProguardIfRuleClassEvaluations++;
             }
-            if (evaluateClassForIfRule(ifRule, clazz)) {
+            if (evaluateClassForIfRule(ifRuleKey, clazz)) {
               // 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.
-              ifRuleEntry
-                  .getValue()
-                  .removeIf(
-                      memberRule -> {
-                        registerClassCapture(memberRule, clazz, clazz);
-                        if (appView.options().testing.measureProguardIfRuleEvaluations) {
-                          ifRuleEvaluationData.numberOfProguardIfRuleMemberEvaluations++;
-                        }
-                        return evaluateIfRuleMembersAndMaterialize(memberRule, clazz, clazz)
-                            && canRemoveSubsequentKeepRule(memberRule);
-                      });
+              ifRulesInEquivalence.forEach(
+                  ifRule -> {
+                    registerClassCapture(ifRule, clazz, clazz);
+                    if (appView.options().testing.measureProguardIfRuleEvaluations) {
+                      ifRuleEvaluationData.numberOfProguardIfRuleMemberEvaluations++;
+                    }
+                    boolean matched = evaluateIfRuleMembersAndMaterialize(ifRule, clazz, clazz);
+                    if (matched && canRemoveSubsequentKeepRule(ifRule)) {
+                      toRemove.add(ifRule);
+                    }
+                  });
             }
 
             // Check if one of the types that have been merged into `clazz` satisfies the if-rule.
@@ -123,25 +125,26 @@
                 if (appView.options().testing.measureProguardIfRuleEvaluations) {
                   ifRuleEvaluationData.numberOfProguardIfRuleClassEvaluations++;
                 }
-                if (evaluateClassForIfRule(ifRule, sourceClass)) {
-                  ifRuleEntry
-                      .getValue()
-                      .removeIf(
-                          memberRule -> {
-                            registerClassCapture(memberRule, sourceClass, clazz);
-                            if (appView.options().testing.measureProguardIfRuleEvaluations) {
-                              ifRuleEvaluationData.numberOfProguardIfRuleMemberEvaluations++;
-                            }
-                            return evaluateIfRuleMembersAndMaterialize(
-                                    memberRule, sourceClass, clazz)
-                                && canRemoveSubsequentKeepRule(memberRule);
-                          });
+                if (evaluateClassForIfRule(ifRuleKey, sourceClass)) {
+                  ifRulesInEquivalence.forEach(
+                      ifRule -> {
+                        registerClassCapture(ifRule, sourceClass, clazz);
+                        if (appView.options().testing.measureProguardIfRuleEvaluations) {
+                          ifRuleEvaluationData.numberOfProguardIfRuleMemberEvaluations++;
+                        }
+                        if (evaluateIfRuleMembersAndMaterialize(ifRule, sourceClass, clazz)
+                            && canRemoveSubsequentKeepRule(ifRule)) {
+                          toRemove.add(ifRule);
+                        }
+                      });
                 }
               }
             }
           }
-          if (ifRuleEntry.getValue().isEmpty()) {
+          if (ifRulesInEquivalence.size() == toRemove.size()) {
             it.remove();
+          } else if (!toRemove.isEmpty()) {
+            ifRulesInEquivalence.removeAll(toRemove);
           }
         }
         ThreadUtils.awaitFutures(futures);
@@ -153,10 +156,7 @@
   }
 
   private boolean canRemoveSubsequentKeepRule(ProguardIfRule rule) {
-    // We cannot remove an if-rule if there is a kept graph consumer, otherwise we would not record
-    // all edges.
-    return Iterables.isEmpty(rule.subsequentRule.getWildcards())
-        && appView.options().keptGraphConsumer == null;
+    return Iterables.isEmpty(rule.subsequentRule.getWildcards());
   }
 
   /**