Share synthetic methods calling other synthetic methods

- Only share with a call graph tree of depth 1.

Fixes: b/382242341
Change-Id: I092844530185b3cb1e463c010fdd12a9c07d9209
diff --git a/src/main/java/com/android/tools/r8/synthesis/CallOtherMergeableSyntheticMethodUseRegistry.java b/src/main/java/com/android/tools/r8/synthesis/CallOtherMergeableSyntheticMethodUseRegistry.java
new file mode 100644
index 0000000..080fd8e
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/synthesis/CallOtherMergeableSyntheticMethodUseRegistry.java
@@ -0,0 +1,33 @@
+// Copyright (c) 2025, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+package com.android.tools.r8.synthesis;
+
+import com.android.tools.r8.graph.AppView;
+import com.android.tools.r8.graph.DefaultUseRegistryWithResult;
+import com.android.tools.r8.graph.DexMethod;
+import com.android.tools.r8.graph.ProgramMethod;
+import com.google.common.collect.Iterables;
+
+public class CallOtherMergeableSyntheticMethodUseRegistry
+    extends DefaultUseRegistryWithResult<Boolean, ProgramMethod> {
+
+  public CallOtherMergeableSyntheticMethodUseRegistry(AppView<?> appView, ProgramMethod context) {
+    super(appView, context, false);
+  }
+
+  @Override
+  public void registerInvokeStatic(DexMethod method) {
+    if (appView.getSyntheticItems().isSynthetic(method.getHolderType())
+        && isSyntheticMethodAllowingGlobalMerging(method)) {
+      setResult(true);
+    }
+  }
+
+  private boolean isSyntheticMethodAllowingGlobalMerging(DexMethod method) {
+    return Iterables.all(
+        appView.getSyntheticItems().getSyntheticKinds(method.getHolderType()),
+        kind ->
+            kind.isSyntheticMethodKind() && kind.asSyntheticMethodKind().isAllowGlobalMerging());
+  }
+}
diff --git a/src/main/java/com/android/tools/r8/synthesis/SyntheticFinalization.java b/src/main/java/com/android/tools/r8/synthesis/SyntheticFinalization.java
index 5a83444..0b9f17c 100644
--- a/src/main/java/com/android/tools/r8/synthesis/SyntheticFinalization.java
+++ b/src/main/java/com/android/tools/r8/synthesis/SyntheticFinalization.java
@@ -19,6 +19,7 @@
 import com.android.tools.r8.graph.DexProgramClass;
 import com.android.tools.r8.graph.DexString;
 import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.ProgramMethod;
 import com.android.tools.r8.graph.PrunedItems;
 import com.android.tools.r8.graph.fixup.TreeFixerBase;
 import com.android.tools.r8.graph.lens.GraphLens;
@@ -586,7 +587,14 @@
     potentialEquivalences.forEach(
         members -> {
           T t = members.get(0);
-          if (t.getKind().mayCallOtherSyntheticMethods(appView.getSyntheticItems().getNaming())) {
+          boolean mayCallOtherSyntheticMethods = false;
+          if (t.isMethodDefinition()) {
+            ProgramMethod method = t.asMethodDefinition().getMethod();
+            mayCallOtherSyntheticMethods =
+                method.registerCodeReferencesWithResult(
+                    new CallOtherMergeableSyntheticMethodUseRegistry(appView, method));
+          }
+          if (mayCallOtherSyntheticMethods) {
             indirectPotentialEquivalences.add(members);
           } else {
             directPotentialEquivalences.add(members);
diff --git a/src/main/java/com/android/tools/r8/synthesis/SyntheticNaming.java b/src/main/java/com/android/tools/r8/synthesis/SyntheticNaming.java
index ebc0b1d..1ef8edc 100644
--- a/src/main/java/com/android/tools/r8/synthesis/SyntheticNaming.java
+++ b/src/main/java/com/android/tools/r8/synthesis/SyntheticNaming.java
@@ -259,11 +259,6 @@
 
     public abstract boolean isSingleSyntheticMethod();
 
-    @SuppressWarnings("ReferenceEquality")
-    public boolean mayCallOtherSyntheticMethods(SyntheticNaming naming) {
-      return this == naming.AUTOCLOSEABLE_DISPATCHER;
-    }
-
     public abstract boolean isFixedSuffixSynthetic();
 
     public abstract boolean isGlobal();
diff --git a/src/test/java/com/android/tools/r8/desugar/backports/GetMajorAndMinorSdkVersionBackportOutlineInBackportTest.java b/src/test/java/com/android/tools/r8/desugar/backports/GetMajorAndMinorSdkVersionBackportOutlineInBackportTest.java
index 4e39653..337c252 100644
--- a/src/test/java/com/android/tools/r8/desugar/backports/GetMajorAndMinorSdkVersionBackportOutlineInBackportTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/backports/GetMajorAndMinorSdkVersionBackportOutlineInBackportTest.java
@@ -137,10 +137,7 @@
       assertEquals(
           1,
           countInvokeStaticToMethod(apiOutline1.uniqueMethod(), getGetMajorSdkVersion(inspector)));
-      // TODO(b/382242341):There are 4 backports, as even though they are identical two by two, they
-      //  are not currently shared, as synthetic sharing does not see equivalence of the backports
-      //  calling the API outline synthetics, which are shared.
-      for (int i = 2; i < 6; i++) {
+      for (int i = 2; i < 3; i++) {
         ClassSubject backport =
             inspector.clazz(
                 SyntheticItemsTestUtils.syntheticBackportWithForwardingClass(TestClass.class, i));
@@ -174,8 +171,6 @@
     } else {
       ClassSubject apiOutline0 =
           inspector.clazz(SyntheticItemsTestUtils.syntheticApiOutlineClass(TestClass.class, 0));
-      // TODO(b/382242341): There are 4 methods merged into the outline synthetic. Two calling
-      //  getMajorSdkVersion and two calling getMinorSdkVersion.
       assertEquals(4, apiOutline0.allMethods().size());
       MethodSubject main = inspector.clazz(TestClass.class).mainMethod();
       assertEquals(