Add new option to restrict class merging to synthetics

Bug: 187675788
Change-Id: Ie67f94f82d01ff723324efbf2667018dff7d9b31
diff --git a/src/main/java/com/android/tools/r8/D8Command.java b/src/main/java/com/android/tools/r8/D8Command.java
index 0ba1767..8863e35 100644
--- a/src/main/java/com/android/tools/r8/D8Command.java
+++ b/src/main/java/com/android/tools/r8/D8Command.java
@@ -25,6 +25,7 @@
 import com.android.tools.r8.utils.DumpInputFlags;
 import com.android.tools.r8.utils.InternalOptions;
 import com.android.tools.r8.utils.InternalOptions.DesugarState;
+import com.android.tools.r8.utils.InternalOptions.HorizontalClassMergerOptions;
 import com.android.tools.r8.utils.InternalOptions.LineNumberOptimization;
 import com.android.tools.r8.utils.Reporter;
 import com.android.tools.r8.utils.StringDiagnostic;
@@ -480,8 +481,13 @@
     assert !internal.outline.enabled;
     assert !internal.enableValuePropagation;
     assert !internal.enableTreeShakingOfLibraryMethodOverrides;
-    assert !internal.horizontalClassMergerOptions().isEnabled(HorizontalClassMerger.Mode.INITIAL);
-    assert !internal.horizontalClassMergerOptions().isEnabled(HorizontalClassMerger.Mode.FINAL);
+
+    // TODO(b/187675788): Enable class merging for synthetics in D8.
+    HorizontalClassMergerOptions horizontalClassMergerOptions =
+        internal.horizontalClassMergerOptions();
+    horizontalClassMergerOptions.disable();
+    assert !horizontalClassMergerOptions.isEnabled(HorizontalClassMerger.Mode.INITIAL);
+    assert !horizontalClassMergerOptions.isEnabled(HorizontalClassMerger.Mode.FINAL);
 
     internal.desugarState = getDesugarState();
     internal.encodeChecksums = getIncludeClassesChecksum();
diff --git a/src/main/java/com/android/tools/r8/L8Command.java b/src/main/java/com/android/tools/r8/L8Command.java
index 69fa568..fc9a567 100644
--- a/src/main/java/com/android/tools/r8/L8Command.java
+++ b/src/main/java/com/android/tools/r8/L8Command.java
@@ -19,6 +19,7 @@
 import com.android.tools.r8.utils.DumpInputFlags;
 import com.android.tools.r8.utils.InternalOptions;
 import com.android.tools.r8.utils.InternalOptions.DesugarState;
+import com.android.tools.r8.utils.InternalOptions.HorizontalClassMergerOptions;
 import com.android.tools.r8.utils.Pair;
 import com.android.tools.r8.utils.Reporter;
 import com.android.tools.r8.utils.StringDiagnostic;
@@ -179,8 +180,12 @@
     assert !internal.outline.enabled;
     assert !internal.enableValuePropagation;
     assert !internal.enableTreeShakingOfLibraryMethodOverrides;
-    assert !internal.horizontalClassMergerOptions().isEnabled(HorizontalClassMerger.Mode.INITIAL);
-    assert !internal.horizontalClassMergerOptions().isEnabled(HorizontalClassMerger.Mode.FINAL);
+
+    HorizontalClassMergerOptions horizontalClassMergerOptions =
+        internal.horizontalClassMergerOptions();
+    horizontalClassMergerOptions.disable();
+    assert !horizontalClassMergerOptions.isEnabled(HorizontalClassMerger.Mode.INITIAL);
+    assert !horizontalClassMergerOptions.isEnabled(HorizontalClassMerger.Mode.FINAL);
 
     assert internal.desugarState == DesugarState.ON;
     assert internal.enableInheritanceClassInDexDistributor;
diff --git a/src/main/java/com/android/tools/r8/R8Command.java b/src/main/java/com/android/tools/r8/R8Command.java
index 8deaa9c..4fdb44d 100644
--- a/src/main/java/com/android/tools/r8/R8Command.java
+++ b/src/main/java/com/android/tools/r8/R8Command.java
@@ -12,7 +12,6 @@
 import com.android.tools.r8.experimental.graphinfo.GraphConsumer;
 import com.android.tools.r8.features.FeatureSplitConfiguration;
 import com.android.tools.r8.graph.DexItemFactory;
-import com.android.tools.r8.horizontalclassmerging.HorizontalClassMerger;
 import com.android.tools.r8.inspector.Inspector;
 import com.android.tools.r8.inspector.internal.InspectorImpl;
 import com.android.tools.r8.ir.desugar.DesugaredLibraryConfiguration;
@@ -859,8 +858,7 @@
     HorizontalClassMergerOptions horizontalClassMergerOptions =
         internal.horizontalClassMergerOptions();
     assert proguardConfiguration.isOptimizing()
-        || (!horizontalClassMergerOptions.isEnabled(HorizontalClassMerger.Mode.INITIAL)
-            && !horizontalClassMergerOptions.isEnabled(HorizontalClassMerger.Mode.FINAL));
+        || horizontalClassMergerOptions.isRestrictedToSynthetics();
 
     assert !internal.enableTreeShakingOfLibraryMethodOverrides;
     assert internal.enableVerticalClassMerging || !proguardConfiguration.isOptimizing();
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 b984fd7..5f421dc 100644
--- a/src/main/java/com/android/tools/r8/horizontalclassmerging/HorizontalClassMerger.java
+++ b/src/main/java/com/android/tools/r8/horizontalclassmerging/HorizontalClassMerger.java
@@ -47,6 +47,7 @@
 import com.android.tools.r8.shaking.FieldAccessInfoCollectionModifier;
 import com.android.tools.r8.shaking.KeepInfoCollection;
 import com.android.tools.r8.shaking.RuntimeTypeCheckInfo;
+import com.android.tools.r8.synthesis.SyntheticItems;
 import com.android.tools.r8.utils.InternalOptions.HorizontalClassMergerOptions;
 import com.android.tools.r8.utils.Timing;
 import com.google.common.collect.ImmutableList;
@@ -190,7 +191,12 @@
   private List<MergeGroup> getInitialGroups() {
     MergeGroup initialClassGroup = new MergeGroup();
     MergeGroup initialInterfaceGroup = new MergeGroup();
+    HorizontalClassMergerOptions options = appView.options().horizontalClassMergerOptions();
+    SyntheticItems syntheticItems = appView.getSyntheticItems();
     for (DexProgramClass clazz : appView.appInfo().classesWithDeterministicOrder()) {
+      if (options.isRestrictedToSynthetics() && !syntheticItems.isSyntheticClass(clazz)) {
+        continue;
+      }
       if (clazz.isInterface()) {
         initialInterfaceGroup.add(clazz);
       } else {
diff --git a/src/main/java/com/android/tools/r8/utils/InternalOptions.java b/src/main/java/com/android/tools/r8/utils/InternalOptions.java
index 79fc436..f9580b6 100644
--- a/src/main/java/com/android/tools/r8/utils/InternalOptions.java
+++ b/src/main/java/com/android/tools/r8/utils/InternalOptions.java
@@ -210,7 +210,6 @@
     enableClassInlining = false;
     enableClassStaticizer = false;
     enableDevirtualization = false;
-    horizontalClassMergerOptions.disable();
     enableVerticalClassMerging = false;
     enableEnumUnboxing = false;
     enableUninstantiatedTypeOptimization = false;
@@ -220,6 +219,7 @@
     enableSideEffectAnalysis = false;
     enableTreeShakingOfLibraryMethodOverrides = false;
     callSiteOptimizationOptions.disableOptimization();
+    horizontalClassMergerOptions.setRestrictToSynthetics();
   }
 
   public boolean printTimes = System.getProperty("com.android.tools.r8.printtimes") != null;
@@ -559,6 +559,10 @@
   private final boolean enableTreeShaking;
   private final boolean enableMinification;
 
+  public boolean isOptimizing() {
+    return hasProguardConfiguration() && getProguardConfiguration().isOptimizing();
+  }
+
   public boolean isRelease() {
     return !debug;
   }
@@ -617,11 +621,13 @@
    */
   public boolean isClassMergingExtensionRequired(Enqueuer.Mode mode) {
     if (mode.isInitialTreeShaking()) {
-      return horizontalClassMergerOptions.isEnabled(HorizontalClassMerger.Mode.INITIAL)
+      return (horizontalClassMergerOptions.isEnabled(HorizontalClassMerger.Mode.INITIAL)
+              && !horizontalClassMergerOptions.isRestrictedToSynthetics())
           || enableVerticalClassMerging;
     }
     if (mode.isFinalTreeShaking()) {
-      return horizontalClassMergerOptions.isEnabled(HorizontalClassMerger.Mode.FINAL);
+      return horizontalClassMergerOptions.isEnabled(HorizontalClassMerger.Mode.FINAL)
+          && !horizontalClassMergerOptions.isRestrictedToSynthetics();
     }
     assert false;
     return false;
@@ -1205,9 +1211,9 @@
     private boolean enable =
         !Version.isDevelopmentVersion()
             || System.getProperty("com.android.tools.r8.disableHorizontalClassMerging") == null;
-    private boolean enableConstructorMerging = true;
     private boolean enableInterfaceMerging = false;
     private boolean ignoreRuntimeTypeChecksForTesting = false;
+    private boolean restrictToSynthetics = false;
 
     public int maxGroupSize = 30;
 
@@ -1232,7 +1238,7 @@
     }
 
     public boolean isConstructorMergingEnabled() {
-      return enableConstructorMerging;
+      return true;
     }
 
     public boolean isEnabled(HorizontalClassMerger.Mode mode) {
@@ -1261,9 +1267,17 @@
       return enableInterfaceMerging;
     }
 
+    public boolean isRestrictedToSynthetics() {
+      return restrictToSynthetics || !isOptimizing() || !isShrinking();
+    }
+
     public void setIgnoreRuntimeTypeChecksForTesting() {
       ignoreRuntimeTypeChecksForTesting = true;
     }
+
+    public void setRestrictToSynthetics() {
+      restrictToSynthetics = true;
+    }
   }
 
   public static class ProtoShrinkingOptions {