Enable call site optimization.

Bug: 139246447
Change-Id: I7303c94cec985354529a8ff6d32284d738977155
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/CallSiteOptimizationInfoPropagator.java b/src/main/java/com/android/tools/r8/ir/optimize/CallSiteOptimizationInfoPropagator.java
index 0008162..45f8c45 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/CallSiteOptimizationInfoPropagator.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/CallSiteOptimizationInfoPropagator.java
@@ -5,7 +5,9 @@
 
 import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.DexEncodedMethod;
+import com.android.tools.r8.graph.DexMethod;
 import com.android.tools.r8.graph.DexProgramClass;
+import com.android.tools.r8.graph.ResolutionResult;
 import com.android.tools.r8.ir.analysis.type.TypeAnalysis;
 import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
 import com.android.tools.r8.ir.code.Assume;
@@ -89,6 +91,15 @@
         continue;
       }
       if (instruction.isInvokeMethod()) {
+        // For virtual and interface calls, proceed on valid results only (since it's enforced).
+        if (instruction.isInvokeVirtual() || instruction.isInvokeInterface()) {
+          DexMethod invokedMethod = instruction.asInvokeMethod().getInvokedMethod();
+          ResolutionResult resolutionResult =
+              appView.appInfo().resolveMethod(invokedMethod.holder, invokedMethod);
+          if (!resolutionResult.isValidVirtualTarget(appView.options())) {
+            continue;
+          }
+        }
         Collection<DexEncodedMethod> targets =
             instruction.asInvokeMethod().lookupTargets(appView, context.method.holder);
         if (targets == null) {
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 f7a2a5b..d78cb45 100644
--- a/src/main/java/com/android/tools/r8/utils/InternalOptions.java
+++ b/src/main/java/com/android/tools/r8/utils/InternalOptions.java
@@ -211,8 +211,7 @@
   public boolean enableNameReflectionOptimization = true;
   public boolean enableStringConcatenationOptimization = true;
   public boolean enableTreeShakingOfLibraryMethodOverrides = false;
-  // TODO(b/139246447): enable after branching.
-  public boolean enableCallSiteOptimizationInfoPropagation = false;
+  public boolean enableCallSiteOptimizationInfoPropagation = true;
   public boolean encodeChecksums = false;
   public BiPredicate<String, Long> dexClassChecksumFilter = (name, checksum) -> true;
 
@@ -1020,13 +1019,6 @@
     enableNameReflectionOptimization = false;
   }
 
-  // TODO(b/139246447): Remove this once enabled.
-  @VisibleForTesting
-  public void enableCallSiteOptimizationInfoPropagation() {
-    assert !enableCallSiteOptimizationInfoPropagation;
-    enableCallSiteOptimizationInfoPropagation = true;
-  }
-
   private boolean hasMinApi(AndroidApiLevel level) {
     assert isGeneratingDex();
     return minApiLevel >= level.getLevel();
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/callsites/dynamictype/InvokeDirectPositiveTest.java b/src/test/java/com/android/tools/r8/ir/optimize/callsites/dynamictype/InvokeDirectPositiveTest.java
index 0c77830..1890534 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/callsites/dynamictype/InvokeDirectPositiveTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/callsites/dynamictype/InvokeDirectPositiveTest.java
@@ -13,7 +13,6 @@
 import com.android.tools.r8.TestBase;
 import com.android.tools.r8.TestParameters;
 import com.android.tools.r8.TestParametersCollection;
-import com.android.tools.r8.utils.InternalOptions;
 import com.android.tools.r8.utils.codeinspector.ClassSubject;
 import com.android.tools.r8.utils.codeinspector.CodeInspector;
 import com.android.tools.r8.utils.codeinspector.InstructionSubject;
@@ -45,7 +44,6 @@
         .enableMergeAnnotations()
         .enableClassInliningAnnotations()
         .enableInliningAnnotations()
-        .addOptionsModification(InternalOptions::enableCallSiteOptimizationInfoPropagation)
         .setMinApi(parameters.getRuntime())
         .run(parameters.getRuntime(), MAIN)
         .assertSuccessWithOutputLines("Sub1")
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/callsites/dynamictype/InvokeInterfacePositiveTest.java b/src/test/java/com/android/tools/r8/ir/optimize/callsites/dynamictype/InvokeInterfacePositiveTest.java
index 0ee0af3..ce2fd2e 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/callsites/dynamictype/InvokeInterfacePositiveTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/callsites/dynamictype/InvokeInterfacePositiveTest.java
@@ -13,7 +13,6 @@
 import com.android.tools.r8.TestBase;
 import com.android.tools.r8.TestParameters;
 import com.android.tools.r8.TestParametersCollection;
-import com.android.tools.r8.utils.InternalOptions;
 import com.android.tools.r8.utils.codeinspector.ClassSubject;
 import com.android.tools.r8.utils.codeinspector.CodeInspector;
 import com.android.tools.r8.utils.codeinspector.InstructionSubject;
@@ -45,7 +44,6 @@
         .enableMergeAnnotations()
         .enableClassInliningAnnotations()
         .enableInliningAnnotations()
-        .addOptionsModification(InternalOptions::enableCallSiteOptimizationInfoPropagation)
         .addOptionsModification(o -> {
           // To prevent invoke-interface from being rewritten to invoke-virtual w/ a single target.
           o.enableDevirtualization = false;
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/callsites/dynamictype/InvokeStaticPositiveTest.java b/src/test/java/com/android/tools/r8/ir/optimize/callsites/dynamictype/InvokeStaticPositiveTest.java
index 09dd632..98012dc 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/callsites/dynamictype/InvokeStaticPositiveTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/callsites/dynamictype/InvokeStaticPositiveTest.java
@@ -12,7 +12,6 @@
 import com.android.tools.r8.TestBase;
 import com.android.tools.r8.TestParameters;
 import com.android.tools.r8.TestParametersCollection;
-import com.android.tools.r8.utils.InternalOptions;
 import com.android.tools.r8.utils.codeinspector.ClassSubject;
 import com.android.tools.r8.utils.codeinspector.CodeInspector;
 import com.android.tools.r8.utils.codeinspector.InstructionSubject;
@@ -43,7 +42,6 @@
         .addKeepMainRule(MAIN)
         .enableMergeAnnotations()
         .enableInliningAnnotations()
-        .addOptionsModification(InternalOptions::enableCallSiteOptimizationInfoPropagation)
         .setMinApi(parameters.getRuntime())
         .run(parameters.getRuntime(), MAIN)
         .assertSuccessWithOutputLines("Sub1")
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/callsites/dynamictype/InvokeVirtualPositiveTest.java b/src/test/java/com/android/tools/r8/ir/optimize/callsites/dynamictype/InvokeVirtualPositiveTest.java
index 27057c1..cd4852d 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/callsites/dynamictype/InvokeVirtualPositiveTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/callsites/dynamictype/InvokeVirtualPositiveTest.java
@@ -13,7 +13,6 @@
 import com.android.tools.r8.TestBase;
 import com.android.tools.r8.TestParameters;
 import com.android.tools.r8.TestParametersCollection;
-import com.android.tools.r8.utils.InternalOptions;
 import com.android.tools.r8.utils.codeinspector.ClassSubject;
 import com.android.tools.r8.utils.codeinspector.CodeInspector;
 import com.android.tools.r8.utils.codeinspector.InstructionSubject;
@@ -45,7 +44,6 @@
         .enableMergeAnnotations()
         .enableClassInliningAnnotations()
         .enableInliningAnnotations()
-        .addOptionsModification(InternalOptions::enableCallSiteOptimizationInfoPropagation)
         .setMinApi(parameters.getRuntime())
         .run(parameters.getRuntime(), MAIN)
         .assertSuccessWithOutputLines("A:Sub1", "B:Sub1")
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/callsites/nullability/InvokeDirectPositiveTest.java b/src/test/java/com/android/tools/r8/ir/optimize/callsites/nullability/InvokeDirectPositiveTest.java
index 9eef5ac..1db3da7 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/callsites/nullability/InvokeDirectPositiveTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/callsites/nullability/InvokeDirectPositiveTest.java
@@ -12,7 +12,6 @@
 import com.android.tools.r8.TestBase;
 import com.android.tools.r8.TestParameters;
 import com.android.tools.r8.TestParametersCollection;
-import com.android.tools.r8.utils.InternalOptions;
 import com.android.tools.r8.utils.codeinspector.ClassSubject;
 import com.android.tools.r8.utils.codeinspector.CodeInspector;
 import com.android.tools.r8.utils.codeinspector.InstructionSubject;
@@ -43,7 +42,6 @@
         .addKeepMainRule(MAIN)
         .enableClassInliningAnnotations()
         .enableInliningAnnotations()
-        .addOptionsModification(InternalOptions::enableCallSiteOptimizationInfoPropagation)
         .setMinApi(parameters.getRuntime())
         .run(parameters.getRuntime(), MAIN)
         .assertSuccessWithOutputLines("non-null")
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/callsites/nullability/InvokeInterfacePositiveTest.java b/src/test/java/com/android/tools/r8/ir/optimize/callsites/nullability/InvokeInterfacePositiveTest.java
index ae8ef12..b838d12 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/callsites/nullability/InvokeInterfacePositiveTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/callsites/nullability/InvokeInterfacePositiveTest.java
@@ -12,7 +12,6 @@
 import com.android.tools.r8.TestBase;
 import com.android.tools.r8.TestParameters;
 import com.android.tools.r8.TestParametersCollection;
-import com.android.tools.r8.utils.InternalOptions;
 import com.android.tools.r8.utils.codeinspector.ClassSubject;
 import com.android.tools.r8.utils.codeinspector.CodeInspector;
 import com.android.tools.r8.utils.codeinspector.InstructionSubject;
@@ -43,7 +42,6 @@
         .addKeepMainRule(MAIN)
         .enableClassInliningAnnotations()
         .enableInliningAnnotations()
-        .addOptionsModification(InternalOptions::enableCallSiteOptimizationInfoPropagation)
         .addOptionsModification(o -> {
           // To prevent invoke-interface from being rewritten to invoke-virtual w/ a single target.
           o.enableDevirtualization = false;
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/callsites/nullability/InvokeStaticPositiveTest.java b/src/test/java/com/android/tools/r8/ir/optimize/callsites/nullability/InvokeStaticPositiveTest.java
index 53c9f8f..f1081fc 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/callsites/nullability/InvokeStaticPositiveTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/callsites/nullability/InvokeStaticPositiveTest.java
@@ -11,7 +11,6 @@
 import com.android.tools.r8.TestBase;
 import com.android.tools.r8.TestParameters;
 import com.android.tools.r8.TestParametersCollection;
-import com.android.tools.r8.utils.InternalOptions;
 import com.android.tools.r8.utils.codeinspector.ClassSubject;
 import com.android.tools.r8.utils.codeinspector.CodeInspector;
 import com.android.tools.r8.utils.codeinspector.InstructionSubject;
@@ -42,7 +41,6 @@
         .addKeepMainRule(MAIN)
         .enableInliningAnnotations()
         .setMinApi(parameters.getRuntime())
-        .addOptionsModification(InternalOptions::enableCallSiteOptimizationInfoPropagation)
         .run(parameters.getRuntime(), MAIN)
         .assertSuccessWithOutputLines("non-null")
         .inspect(this::inspect);
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/callsites/nullability/InvokeVirtualPositiveTest.java b/src/test/java/com/android/tools/r8/ir/optimize/callsites/nullability/InvokeVirtualPositiveTest.java
index bc4d0a7..7d0838c 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/callsites/nullability/InvokeVirtualPositiveTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/callsites/nullability/InvokeVirtualPositiveTest.java
@@ -13,7 +13,6 @@
 import com.android.tools.r8.TestBase;
 import com.android.tools.r8.TestParameters;
 import com.android.tools.r8.TestParametersCollection;
-import com.android.tools.r8.utils.InternalOptions;
 import com.android.tools.r8.utils.codeinspector.ClassSubject;
 import com.android.tools.r8.utils.codeinspector.CodeInspector;
 import com.android.tools.r8.utils.codeinspector.InstructionSubject;
@@ -45,7 +44,6 @@
         .enableMergeAnnotations()
         .enableClassInliningAnnotations()
         .enableInliningAnnotations()
-        .addOptionsModification(InternalOptions::enableCallSiteOptimizationInfoPropagation)
         .setMinApi(parameters.getRuntime())
         .run(parameters.getRuntime(), MAIN)
         .assertSuccessWithOutputLines("A", "B")
diff --git a/src/test/java/com/android/tools/r8/kotlin/SimplifyIfNotNullKotlinTest.java b/src/test/java/com/android/tools/r8/kotlin/SimplifyIfNotNullKotlinTest.java
index a044d3f..59aae43 100644
--- a/src/test/java/com/android/tools/r8/kotlin/SimplifyIfNotNullKotlinTest.java
+++ b/src/test/java/com/android/tools/r8/kotlin/SimplifyIfNotNullKotlinTest.java
@@ -7,10 +7,8 @@
 
 import com.android.tools.r8.ToolHelper.KotlinTargetVersion;
 import com.android.tools.r8.naming.MemberNaming.MethodSignature;
-import com.android.tools.r8.utils.InternalOptions;
 import com.android.tools.r8.utils.codeinspector.ClassSubject;
 import com.android.tools.r8.utils.codeinspector.CodeInspector;
-import com.android.tools.r8.utils.codeinspector.InstructionSubject;
 import com.android.tools.r8.utils.codeinspector.MethodSubject;
 import com.google.common.collect.ImmutableList;
 import org.junit.Test;
@@ -35,7 +33,6 @@
     final String extraRules =
         keepMainMethod(mainClassName) + neverInlineMethod(mainClassName, testMethodSignature);
     runTest(FOLDER, mainClassName, extraRules,
-        InternalOptions::enableCallSiteOptimizationInfoPropagation,
         app -> {
           CodeInspector codeInspector = new CodeInspector(app);
           ClassSubject clazz = checkClassIsKept(codeInspector, ex1.getClassName());
@@ -61,13 +58,13 @@
     final String extraRules =
         keepMainMethod(mainClassName) + neverInlineMethod(mainClassName, testMethodSignature);
     runTest(FOLDER, mainClassName, extraRules,
-        InternalOptions::enableCallSiteOptimizationInfoPropagation,
         app -> {
           CodeInspector codeInspector = new CodeInspector(app);
           ClassSubject clazz = checkClassIsKept(codeInspector, ex2.getClassName());
 
           MethodSubject testMethod = checkMethodIsKept(clazz, testMethodSignature);
-          long ifzCount = testMethod.streamInstructions().filter(InstructionSubject::isIfEqz).count();
+          long ifzCount =
+              testMethod.streamInstructions().filter(i -> i.isIfEqz() || i.isIfNez()).count();
           long paramNullCheckCount =
               countCall(testMethod, "Intrinsics", "checkParameterIsNotNull");
           // ?: in aOrDefault
@@ -86,13 +83,13 @@
     final String extraRules =
         keepMainMethod(mainClassName) + neverInlineMethod(mainClassName, testMethodSignature);
     runTest(FOLDER, mainClassName, extraRules,
-        InternalOptions::enableCallSiteOptimizationInfoPropagation,
         app -> {
           CodeInspector codeInspector = new CodeInspector(app);
           ClassSubject clazz = checkClassIsKept(codeInspector, ex3.getClassName());
 
           MethodSubject testMethod = checkMethodIsKept(clazz, testMethodSignature);
-          long ifzCount = testMethod.streamInstructions().filter(InstructionSubject::isIfEqz).count();
+          long ifzCount =
+              testMethod.streamInstructions().filter(i -> i.isIfEqz() || i.isIfNez()).count();
           // !! operator inside explicit null check should be gone.
           // One explicit null-check as well as 4 bar? accesses.
           assertEquals(5, ifzCount);
diff --git a/src/test/java/com/android/tools/r8/shaking/ParameterTypeTest.java b/src/test/java/com/android/tools/r8/shaking/ParameterTypeTest.java
index 88a6e04..5cdbd87 100644
--- a/src/test/java/com/android/tools/r8/shaking/ParameterTypeTest.java
+++ b/src/test/java/com/android/tools/r8/shaking/ParameterTypeTest.java
@@ -137,15 +137,15 @@
 
     ClassSubject superInterface1 = inspector.clazz(B112452064SuperInterface1.class);
     assertThat(superInterface1, isRenamed());
-    MethodSubject foo = superInterface1.method("void", "foo", ImmutableList.of());
-    assertThat(foo, isRenamed());
+    MethodSubject foo = superInterface1.uniqueMethodWithName("foo");
+    assertThat(foo, not(isPresent()));
     ClassSubject superInterface2 = inspector.clazz(B112452064SuperInterface2.class);
     if (enableVerticalClassMerging) {
       assertThat(superInterface2, not(isPresent()));
     } else {
       assertThat(superInterface2, isRenamed());
     }
-    MethodSubject bar = superInterface1.method("void", "bar", ImmutableList.of());
+    MethodSubject bar = superInterface2.uniqueMethodWithName("bar");
     assertThat(bar, not(isPresent()));
     ClassSubject subInterface = inspector.clazz(B112452064SubInterface.class);
     if (enableUnusedInterfaceRemoval) {
diff --git a/src/test/java/com/android/tools/r8/shaking/assumevalues/AssumevaluesWithMultipleTargetsTest.java b/src/test/java/com/android/tools/r8/shaking/assumevalues/AssumevaluesWithMultipleTargetsTest.java
index 555fc7c..f91de77 100644
--- a/src/test/java/com/android/tools/r8/shaking/assumevalues/AssumevaluesWithMultipleTargetsTest.java
+++ b/src/test/java/com/android/tools/r8/shaking/assumevalues/AssumevaluesWithMultipleTargetsTest.java
@@ -5,7 +5,7 @@
 
 import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
 import static org.hamcrest.MatcherAssert.assertThat;
-import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
 
 import com.android.tools.r8.NeverClassInline;
 import com.android.tools.r8.NeverInline;
@@ -16,7 +16,6 @@
 import com.android.tools.r8.utils.codeinspector.ClassSubject;
 import com.android.tools.r8.utils.codeinspector.CodeInspector;
 import com.android.tools.r8.utils.codeinspector.MethodSubject;
-import com.google.common.collect.Streams;
 import java.util.Collection;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -125,17 +124,17 @@
 
       MethodSubject mainMethod = main.mainMethod();
       assertThat(mainMethod, isPresent());
-      assertEquals(
-          0,
-          Streams.stream(mainMethod.iterateInstructions(
-              i -> i.isInvoke() && i.getMethod().name.toString().equals("m"))).count());
+      assertTrue(
+          mainMethod.streamInstructions().noneMatch(
+              i -> i.isInvoke() && i.getMethod().name.toString().equals("m")));
 
       MethodSubject testInvokeInterface = main.uniqueMethodWithName("testInvokeInterface");
       assertThat(testInvokeInterface, isPresent());
-      assertEquals(
-          1,
-          Streams.stream(testInvokeInterface.iterateInstructions(
-              i -> i.isInvoke() && i.getMethod().name.toString().equals("m"))).count());
+      // With call site optimizations, the dynamic type of the argument is accurate (Impl1),
+      // hence the accurate resolution of the method call, resulting in rule application.
+      assertTrue(
+          testInvokeInterface.streamInstructions().noneMatch(
+              i -> i.isInvoke() && i.getMethod().name.toString().equals("m")));
     }
   }
 
diff --git a/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking17Test.java b/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking17Test.java
index 8430bb6..88d3b65 100644
--- a/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking17Test.java
+++ b/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking17Test.java
@@ -47,7 +47,11 @@
   private static void abstractMethodRemains(CodeInspector inspector) {
     ClassSubject programClass = inspector.clazz("shaking17.AbstractProgramClass");
     Assert.assertTrue(programClass.isPresent());
-    Assert.assertTrue(
+    // With call site optimization, the dynamic type of the argument of Shaking#callTheMethod is
+    // SubClass, not AbstractProgramClass. Then, the resolution of the invocation is accurately
+    // referring to SubClass#abstractMethod only, i.e., AbstractProgramClass#abstractMethod is no
+    // longer live, hence shrunken.
+    Assert.assertFalse(
         programClass.method("int", "abstractMethod", Collections.emptyList()).isPresent());
   }
 }
diff --git a/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking18Test.java b/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking18Test.java
index f2a924d..f28f242 100644
--- a/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking18Test.java
+++ b/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking18Test.java
@@ -6,7 +6,6 @@
 import static org.junit.Assert.assertFalse;
 
 import com.android.tools.r8.shaking.TreeShakingTest;
-import com.android.tools.r8.utils.InternalOptions;
 import com.android.tools.r8.utils.codeinspector.CodeInspector;
 import com.google.common.collect.ImmutableList;
 import java.util.ArrayList;
@@ -41,8 +40,7 @@
         TreeShaking18Test::unusedRemoved,
         null,
         null,
-        ImmutableList.of("src/test/examples/shaking18/keep-rules.txt"),
-        InternalOptions::enableCallSiteOptimizationInfoPropagation);
+        ImmutableList.of("src/test/examples/shaking18/keep-rules.txt"));
   }
 
   private static void unusedRemoved(CodeInspector inspector) {