Account for other merge groups in deadlock after class merging detection

Bug: 205611444
Change-Id: Ib7fbaebb9319baa3197c05a7167b074a4068e72d
diff --git a/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/NoClassInitializerCycles.java b/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/NoClassInitializerCycles.java
index a57a034..d3c2661 100644
--- a/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/NoClassInitializerCycles.java
+++ b/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/NoClassInitializerCycles.java
@@ -131,7 +131,23 @@
       }
       newGroups.addAll(newGroupsFromPartition);
     }
-    return removeTrivialGroups(newGroups);
+    removeTrivialGroups(newGroups);
+    commit(group, newGroups);
+    return newGroups;
+  }
+
+  private void commit(MergeGroup oldGroup, List<MergeGroup> newGroups) {
+    for (MergeGroup newGroup : newGroups) {
+      for (DexProgramClass member : newGroup) {
+        allGroups.put(member, newGroup);
+      }
+    }
+    for (DexProgramClass member : oldGroup) {
+      MergeGroup newGroup = allGroups.get(member);
+      if (newGroup == oldGroup) {
+        allGroups.remove(member);
+      }
+    }
   }
 
   private MergeGroup getOrCreateGroupFor(
@@ -273,7 +289,10 @@
 
   private class Tracer {
 
-    final Set<DexProgramClass> group;
+    final MergeGroup group;
+
+    // The members of the existing merge group, for efficient membership querying.
+    final Set<DexProgramClass> groupMembers;
 
     private final Set<DexProgramClass> seenClassInitializers = Sets.newIdentityHashSet();
     private final ProgramMethodSet seenMethods = ProgramMethodSet.create();
@@ -289,7 +308,8 @@
     private Collection<DexProgramClass> tracingRoots;
 
     Tracer(MergeGroup group) {
-      this.group = SetUtils.newIdentityHashSet(group);
+      this.group = group;
+      this.groupMembers = SetUtils.newIdentityHashSet(group);
     }
 
     void clearSeen() {
@@ -320,7 +340,7 @@
     }
 
     void recordClassInitializerReachableFromTracingRoots(DexProgramClass clazz) {
-      assert group.contains(clazz);
+      assert groupMembers.contains(clazz);
       classInitializerReachableFromClasses
           .computeIfAbsent(clazz, ignoreKey(Sets::newIdentityHashSet))
           .addAll(tracingRoots);
@@ -428,15 +448,12 @@
         }
       }
 
-      // TODO(b/205611444): This needs to account for pending merging. If the given class is in a
-      //  merge group, then this should trigger the class initializers of all of the classes in the
-      //  merge group.
       private void triggerClassInitializer(DexProgramClass clazz) {
         if (!markClassInitializerAsSeen(clazz)) {
           return;
         }
 
-        if (group.contains(clazz)) {
+        if (groupMembers.contains(clazz)) {
           if (hasSingleTracingRoot(clazz)) {
             // We found an execution path from the class initializer of the given class back to its
             // own class initializer. Therefore this class is not eligible for merging.
@@ -457,6 +474,13 @@
         }
 
         triggerClassInitializer(clazz.getSuperType());
+
+        MergeGroup other = allGroups.get(clazz);
+        if (other != null && other != group) {
+          for (DexProgramClass member : other) {
+            triggerClassInitializer(member);
+          }
+        }
       }
 
       @Override
diff --git a/src/test/java/com/android/tools/r8/classmerging/horizontal/ClinitDeadlockAfterMergingMultipleGroupsTest.java b/src/test/java/com/android/tools/r8/classmerging/horizontal/ClinitDeadlockAfterMergingMultipleGroupsTest.java
index a2b099a..3d07644 100644
--- a/src/test/java/com/android/tools/r8/classmerging/horizontal/ClinitDeadlockAfterMergingMultipleGroupsTest.java
+++ b/src/test/java/com/android/tools/r8/classmerging/horizontal/ClinitDeadlockAfterMergingMultipleGroupsTest.java
@@ -33,11 +33,10 @@
     testForR8(parameters.getBackend())
         .addInnerClasses(getClass())
         .addKeepClassAndMembersRules(Main.class)
-        // TODO(b/205611444): Should only allow merging three out of the four merge groups.
         .addHorizontallyMergedClassesInspector(
             inspector ->
                 inspector
-                    .assertIsCompleteMergeGroup(A1.class, A2.class)
+                    .assertClassesNotMerged(A1.class, A2.class)
                     .assertIsCompleteMergeGroup(B1.class, B2.class)
                     .assertIsCompleteMergeGroup(C1.class, C2.class)
                     .assertIsCompleteMergeGroup(D1.class, D2.class)