Prune keep info for instance fields removed by merging

Change-Id: I838e6039c199b4d1633692d3d126033cb2f99b0e
diff --git a/src/main/java/com/android/tools/r8/graph/PrunedItems.java b/src/main/java/com/android/tools/r8/graph/PrunedItems.java
index 4f901fd..68c1dde 100644
--- a/src/main/java/com/android/tools/r8/graph/PrunedItems.java
+++ b/src/main/java/com/android/tools/r8/graph/PrunedItems.java
@@ -36,6 +36,10 @@
     return new Builder();
   }
 
+  public Builder toBuilder() {
+    return new Builder(this);
+  }
+
   public static PrunedItems empty(DexApplication application) {
     return new Builder().setPrunedApp(application).build();
   }
@@ -113,6 +117,17 @@
     private final Set<DexField> removedFields = Sets.newIdentityHashSet();
     private Set<DexMethod> removedMethods = Sets.newIdentityHashSet();
 
+    Builder() {}
+
+    Builder(PrunedItems prunedItems) {
+      additionalPinnedItems.addAll(prunedItems.getAdditionalPinnedItems());
+      noLongerSyntheticItems.addAll(prunedItems.getNoLongerSyntheticItems());
+      prunedApp = prunedItems.getPrunedApp();
+      removedClasses.addAll(prunedItems.getRemovedClasses());
+      removedFields.addAll(prunedItems.getRemovedFields());
+      removedMethods.addAll(prunedItems.getRemovedMethods());
+    }
+
     public Builder setPrunedApp(DexApplication prunedApp) {
       this.prunedApp = prunedApp;
       return this;
@@ -129,6 +144,12 @@
       return this;
     }
 
+    public Builder addRemovedClass(DexType removedClass) {
+      this.noLongerSyntheticItems.add(removedClass);
+      this.removedClasses.add(removedClass);
+      return this;
+    }
+
     public Builder addRemovedClasses(Set<DexType> removedClasses) {
       this.noLongerSyntheticItems.addAll(removedClasses);
       this.removedClasses.addAll(removedClasses);
diff --git a/src/main/java/com/android/tools/r8/horizontalclassmerging/ClassMerger.java b/src/main/java/com/android/tools/r8/horizontalclassmerging/ClassMerger.java
index c76f43f..d7dc429 100644
--- a/src/main/java/com/android/tools/r8/horizontalclassmerging/ClassMerger.java
+++ b/src/main/java/com/android/tools/r8/horizontalclassmerging/ClassMerger.java
@@ -23,6 +23,7 @@
 import com.android.tools.r8.graph.MethodAccessFlags;
 import com.android.tools.r8.graph.ProgramMember;
 import com.android.tools.r8.graph.ProgramMethod;
+import com.android.tools.r8.graph.PrunedItems;
 import com.android.tools.r8.horizontalclassmerging.HorizontalClassMerger.Mode;
 import com.android.tools.r8.horizontalclassmerging.code.ClassInitializerMerger;
 import com.android.tools.r8.horizontalclassmerging.code.SyntheticInitializerConverter;
@@ -290,16 +291,21 @@
     group.getTarget().setInterfaces(DexTypeList.create(interfaces));
   }
 
-  void mergeFields() {
+  void mergeFields(PrunedItems.Builder prunedItemsBuilder) {
     if (group.hasClassIdField()) {
       appendClassIdField();
     }
-    mergeInstanceFields();
+    mergeInstanceFields(prunedItemsBuilder);
     mergeStaticFields();
   }
 
-  void mergeInstanceFields() {
-    group.forEachSource(DexClass::clearInstanceFields);
+  void mergeInstanceFields(PrunedItems.Builder prunedItemsBuilder) {
+    group.forEachSource(
+        clazz -> {
+          clazz.forEachInstanceField(
+              field -> prunedItemsBuilder.addRemovedField(field.getReference()));
+          clazz.clearInstanceFields();
+        });
     group.getTarget().setInstanceFields(classInstanceFieldsMerger.merge());
   }
 
@@ -310,16 +316,18 @@
   }
 
   public void mergeGroup(
+      PrunedItems.Builder prunedItemsBuilder,
       SyntheticArgumentClass syntheticArgumentClass,
       SyntheticInitializerConverter.Builder syntheticInitializerConverterBuilder) {
     fixAccessFlags();
     fixNestMemberAttributes();
     mergeAnnotations();
     mergeInterfaces();
-    mergeFields();
+    mergeFields(prunedItemsBuilder);
     mergeMethods(syntheticArgumentClass, syntheticInitializerConverterBuilder);
     group.getTarget().clearClassSignature();
     group.getTarget().forEachProgramMember(ProgramMember::clearGenericSignature);
+    group.forEachSource(clazz -> prunedItemsBuilder.addRemovedClass(clazz.getType()));
   }
 
   public static class Builder {
diff --git a/src/main/java/com/android/tools/r8/horizontalclassmerging/HorizontalClassMerger.java b/src/main/java/com/android/tools/r8/horizontalclassmerging/HorizontalClassMerger.java
index b14f07c..ad8d9df 100644
--- a/src/main/java/com/android/tools/r8/horizontalclassmerging/HorizontalClassMerger.java
+++ b/src/main/java/com/android/tools/r8/horizontalclassmerging/HorizontalClassMerger.java
@@ -103,7 +103,9 @@
             : null;
     SyntheticInitializerConverter.Builder syntheticInitializerConverterBuilder =
         SyntheticInitializerConverter.builder(appView, codeProvider);
-    applyClassMergers(classMergers, syntheticArgumentClass, syntheticInitializerConverterBuilder);
+    PrunedItems prunedItems =
+        applyClassMergers(
+            classMergers, syntheticArgumentClass, syntheticInitializerConverterBuilder);
 
     SyntheticInitializerConverter syntheticInitializerConverter =
         syntheticInitializerConverterBuilder.build();
@@ -124,10 +126,7 @@
 
     // Prune keep info.
     KeepInfoCollection keepInfo = appView.getKeepInfo();
-    keepInfo.mutate(
-        mutator ->
-            mutator.removeKeepInfoForMergedClasses(
-                PrunedItems.builder().setRemovedClasses(mergedClasses.getSources()).build()));
+    keepInfo.mutate(mutator -> mutator.removeKeepInfoForMergedClasses(prunedItems));
 
     // Must rewrite AppInfoWithLiveness before pruning the merged classes, to ensure that allocation
     // sites, fields accesses, etc. are correctly transferred to the target classes.
@@ -142,12 +141,7 @@
     }
 
     appView.pruneItems(
-        PrunedItems.builder()
-            .setPrunedApp(appView.appInfo().app())
-            .addRemovedClasses(mergedClasses.getSources())
-            .addNoLongerSyntheticItems(mergedClasses.getSources())
-            .build(),
-        executorService);
+        prunedItems.toBuilder().setPrunedApp(appView.app()).build(), executorService);
   }
 
   private FieldAccessInfoCollectionModifier createFieldAccessInfoCollectionModifier(
@@ -220,13 +214,16 @@
   }
 
   /** Merges all class groups using {@link ClassMerger}. */
-  private void applyClassMergers(
+  private PrunedItems applyClassMergers(
       Collection<ClassMerger> classMergers,
       SyntheticArgumentClass syntheticArgumentClass,
       SyntheticInitializerConverter.Builder syntheticInitializerConverterBuilder) {
+    PrunedItems.Builder prunedItemsBuilder = PrunedItems.builder().setPrunedApp(appView.app());
     for (ClassMerger merger : classMergers) {
-      merger.mergeGroup(syntheticArgumentClass, syntheticInitializerConverterBuilder);
+      merger.mergeGroup(
+          prunedItemsBuilder, syntheticArgumentClass, syntheticInitializerConverterBuilder);
     }
+    return prunedItemsBuilder.build();
   }
 
   /**
diff --git a/src/main/java/com/android/tools/r8/shaking/KeepInfoCollection.java b/src/main/java/com/android/tools/r8/shaking/KeepInfoCollection.java
index 570ed16..62529ed 100644
--- a/src/main/java/com/android/tools/r8/shaking/KeepInfoCollection.java
+++ b/src/main/java/com/android/tools/r8/shaking/KeepInfoCollection.java
@@ -249,6 +249,12 @@
       if (prunedItems.hasRemovedClasses()) {
         keepClassInfo.keySet().removeAll(prunedItems.getRemovedClasses());
       }
+      if (prunedItems.hasRemovedFields()) {
+        keepFieldInfo.keySet().removeAll(prunedItems.getRemovedFields());
+      }
+      if (prunedItems.hasRemovedMembers()) {
+        keepMethodInfo.keySet().removeAll(prunedItems.getRemovedMethods());
+      }
     }
 
     public void removeKeepInfoForPrunedItems(PrunedItems prunedItems) {