Use argument info from optimization info in unused analysis

Change-Id: Ib5c3f6552ba3e776472ad26780ba845a06a53b62
diff --git a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/ArgumentPropagator.java b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/ArgumentPropagator.java
index 96b68f3..f5b55c6 100644
--- a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/ArgumentPropagator.java
+++ b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/ArgumentPropagator.java
@@ -225,7 +225,7 @@
     timing.end();
 
     timing.begin("Compute unused arguments");
-    effectivelyUnusedArgumentsAnalysis.computeEffectivelyUnusedArguments(codeScannerResult);
+    effectivelyUnusedArgumentsAnalysis.computeEffectivelyUnusedArguments();
     effectivelyUnusedArgumentsAnalysis = null;
     timing.end();
   }
diff --git a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/unusedarguments/EffectivelyUnusedArgumentsAnalysis.java b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/unusedarguments/EffectivelyUnusedArgumentsAnalysis.java
index c1a322b..b0be28f 100644
--- a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/unusedarguments/EffectivelyUnusedArgumentsAnalysis.java
+++ b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/unusedarguments/EffectivelyUnusedArgumentsAnalysis.java
@@ -16,7 +16,6 @@
 import com.android.tools.r8.ir.code.InvokeMethod;
 import com.android.tools.r8.ir.code.Value;
 import com.android.tools.r8.optimize.argumentpropagation.codescanner.MethodParameter;
-import com.android.tools.r8.optimize.argumentpropagation.codescanner.MethodStateCollectionByReference;
 import com.android.tools.r8.optimize.argumentpropagation.utils.ParameterRemovalUtils;
 import com.android.tools.r8.shaking.AppInfoWithLiveness;
 import com.android.tools.r8.utils.ListUtils;
@@ -172,11 +171,11 @@
     return effectivelyUnusedConstraints;
   }
 
-  public void computeEffectivelyUnusedArguments(MethodStateCollectionByReference methodStates) {
+  public void computeEffectivelyUnusedArguments() {
     // Build a graph where nodes are method parameters and there is an edge from method parameter p0
     // to method parameter p1 if the removal of p0 depends on the removal of p1.
     EffectivelyUnusedArgumentsGraph dependenceGraph =
-        EffectivelyUnusedArgumentsGraph.create(appView, constraints, methodStates);
+        EffectivelyUnusedArgumentsGraph.create(appView, constraints);
 
     // Remove all unoptimizable method parameters from the graph, as well as all nodes that depend
     // on a node that is unoptimable.
diff --git a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/unusedarguments/EffectivelyUnusedArgumentsGraph.java b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/unusedarguments/EffectivelyUnusedArgumentsGraph.java
index fdc01bc..9fbd408 100644
--- a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/unusedarguments/EffectivelyUnusedArgumentsGraph.java
+++ b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/unusedarguments/EffectivelyUnusedArgumentsGraph.java
@@ -10,7 +10,6 @@
 import com.android.tools.r8.graph.ProgramMethod;
 import com.android.tools.r8.ir.optimize.info.MethodOptimizationInfo;
 import com.android.tools.r8.optimize.argumentpropagation.codescanner.MethodParameter;
-import com.android.tools.r8.optimize.argumentpropagation.codescanner.MethodStateCollectionByReference;
 import com.android.tools.r8.shaking.AppInfoWithLiveness;
 import com.android.tools.r8.utils.WorkList;
 import com.android.tools.r8.utils.dfs.DFSStack;
@@ -38,14 +37,13 @@
 
   public static EffectivelyUnusedArgumentsGraph create(
       AppView<AppInfoWithLiveness> appView,
-      Map<MethodParameter, Set<MethodParameter>> constraints,
-      MethodStateCollectionByReference methodStates) {
+      Map<MethodParameter, Set<MethodParameter>> constraints) {
     EffectivelyUnusedArgumentsGraph graph = new EffectivelyUnusedArgumentsGraph(appView);
     constraints.forEach(
         (methodParameter, constraintsForMethodParameter) -> {
           EffectivelyUnusedArgumentsGraphNode node = graph.getOrCreateNode(methodParameter);
           for (MethodParameter constraint : constraintsForMethodParameter) {
-            graph.addConstraintEdge(node, constraint, constraints, methodStates);
+            graph.addConstraintEdge(node, constraint, constraints);
           }
         });
     return graph;
@@ -54,8 +52,7 @@
   void addConstraintEdge(
       EffectivelyUnusedArgumentsGraphNode node,
       MethodParameter constraint,
-      Map<MethodParameter, Set<MethodParameter>> constraints,
-      MethodStateCollectionByReference methodStates) {
+      Map<MethodParameter, Set<MethodParameter>> constraints) {
     ProgramMethod dependencyMethod =
         asProgramMethodOrNull(appView.definitionFor(constraint.getMethod()));
     if (dependencyMethod == null) {
@@ -68,7 +65,7 @@
     // invoke (or we cannot preserve NPE semantics).
     if (dependencyMethod.getDefinition().isInstance()
         && constraint.getIndex() == 0
-        && node.isNullable(methodStates)) {
+        && node.isNullable()) {
       node.setUnoptimizable();
       return;
     }
diff --git a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/unusedarguments/EffectivelyUnusedArgumentsGraphNode.java b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/unusedarguments/EffectivelyUnusedArgumentsGraphNode.java
index 2b52686..c093924 100644
--- a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/unusedarguments/EffectivelyUnusedArgumentsGraphNode.java
+++ b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/unusedarguments/EffectivelyUnusedArgumentsGraphNode.java
@@ -7,10 +7,7 @@
 import static com.android.tools.r8.ir.optimize.info.OptimizationFeedback.getSimpleFeedback;
 
 import com.android.tools.r8.graph.ProgramMethod;
-import com.android.tools.r8.optimize.argumentpropagation.codescanner.ConcreteMonomorphicMethodState;
-import com.android.tools.r8.optimize.argumentpropagation.codescanner.MethodState;
-import com.android.tools.r8.optimize.argumentpropagation.codescanner.MethodStateCollectionByReference;
-import com.android.tools.r8.optimize.argumentpropagation.codescanner.ParameterState;
+import com.android.tools.r8.ir.analysis.type.DynamicType;
 import com.google.common.collect.Sets;
 import java.util.BitSet;
 import java.util.Set;
@@ -75,28 +72,13 @@
     return successors;
   }
 
-  boolean isNullable(MethodStateCollectionByReference methodStates) {
+  boolean isNullable() {
     if (method.getDefinition().isInstance() && argumentIndex == 0) {
       return false;
     }
-    MethodState methodState = methodStates.get(method);
-    if (methodState.isBottom()) {
-      // TODO: this means the method is unreachable? what to do in this case?
-      return true;
-    }
-    assert !methodState.isBottom();
-    if (methodState.isUnknown()) {
-      return true;
-    }
-    assert methodState.isMonomorphic();
-    ConcreteMonomorphicMethodState monomorphicMethodState = methodState.asMonomorphic();
-    ParameterState parameterState = monomorphicMethodState.getParameterState(argumentIndex);
-    if (parameterState.isUnknown()) {
-      return true;
-    }
-    assert parameterState.isConcrete();
-    assert parameterState.asConcrete().isReferenceParameter();
-    return parameterState.asConcrete().asReferenceParameter().getNullability().isMaybeNull();
+    DynamicType dynamicType =
+        method.getOptimizationInfo().getArgumentInfos().getDynamicType(argumentIndex);
+    return dynamicType.getNullability().isNullable();
   }
 
   boolean isUnoptimizable() {
diff --git a/src/test/java/com/android/tools/r8/classmerging/horizontal/ConstructorMergingPreoptimizedTest.java b/src/test/java/com/android/tools/r8/classmerging/horizontal/ConstructorMergingPreoptimizedTest.java
index 06bfb5b..e5a169b 100644
--- a/src/test/java/com/android/tools/r8/classmerging/horizontal/ConstructorMergingPreoptimizedTest.java
+++ b/src/test/java/com/android/tools/r8/classmerging/horizontal/ConstructorMergingPreoptimizedTest.java
@@ -13,6 +13,7 @@
 import com.android.tools.r8.NeverClassInline;
 import com.android.tools.r8.NeverInline;
 import com.android.tools.r8.NoHorizontalClassMerging;
+import com.android.tools.r8.NoMethodStaticizing;
 import com.android.tools.r8.TestParameters;
 import com.android.tools.r8.horizontalclassmerging.ClassMerger;
 import com.android.tools.r8.utils.codeinspector.ClassSubject;
@@ -36,6 +37,7 @@
         .enableInliningAnnotations()
         .enableNeverClassInliningAnnotations()
         .enableNoHorizontalClassMergingAnnotations()
+        .enableNoMethodStaticizingAnnotations()
         .setMinApi(parameters.getApiLevel())
         .run(parameters.getRuntime(), Main.class)
         .assertSuccessWithOutputLines("changed", "0", "42", "foo", "7", "foo", "print a", "print b")
@@ -71,6 +73,7 @@
   @NoHorizontalClassMerging
   public static class Parent {
     @NeverInline
+    @NoMethodStaticizing
     public void foo() {
       System.out.println("foo");
     }
diff --git a/src/test/java/com/android/tools/r8/classmerging/horizontal/InheritInterfaceWithDefaultTest.java b/src/test/java/com/android/tools/r8/classmerging/horizontal/InheritInterfaceWithDefaultTest.java
index 1f413bc..02e26dc 100644
--- a/src/test/java/com/android/tools/r8/classmerging/horizontal/InheritInterfaceWithDefaultTest.java
+++ b/src/test/java/com/android/tools/r8/classmerging/horizontal/InheritInterfaceWithDefaultTest.java
@@ -10,6 +10,7 @@
 
 import com.android.tools.r8.NeverClassInline;
 import com.android.tools.r8.NeverInline;
+import com.android.tools.r8.NoMethodStaticizing;
 import com.android.tools.r8.TestParameters;
 import org.junit.Test;
 
@@ -27,6 +28,7 @@
         .allowStdoutMessages()
         .enableInliningAnnotations()
         .enableNeverClassInliningAnnotations()
+        .enableNoMethodStaticizingAnnotations()
         .setMinApi(parameters.getApiLevel())
         .addHorizontallyMergedClassesInspector(
             inspector -> inspector.assertMergedInto(B.class, A.class))
@@ -42,6 +44,7 @@
 
   public interface Interface {
     @NeverInline
+    @NoMethodStaticizing
     default void print() {
       System.out.println("print interface");
     }
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/uninstantiatedtypes/InvokeMethodWithNonNullParamCheckTest.java b/src/test/java/com/android/tools/r8/ir/optimize/uninstantiatedtypes/InvokeMethodWithNonNullParamCheckTest.java
index 35b475b..c12a128 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/uninstantiatedtypes/InvokeMethodWithNonNullParamCheckTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/uninstantiatedtypes/InvokeMethodWithNonNullParamCheckTest.java
@@ -9,6 +9,7 @@
 import static org.junit.Assert.assertEquals;
 
 import com.android.tools.r8.NeverInline;
+import com.android.tools.r8.NoMethodStaticizing;
 import com.android.tools.r8.TestBase;
 import com.android.tools.r8.TestParameters;
 import com.android.tools.r8.TestParametersCollection;
@@ -68,13 +69,19 @@
             "Caught NullPointerException from testRewriteInvokeVirtualToThrowNull"
                 + "WithDeadCatchHandler");
 
-    testForJvm().addTestClasspath().run(TestClass.class).assertSuccessWithOutput(expected);
+    if (parameters.isCfRuntime()) {
+      testForJvm()
+          .addTestClasspath()
+          .run(parameters.getRuntime(), TestClass.class)
+          .assertSuccessWithOutput(expected);
+    }
 
     CodeInspector inspector =
         testForR8(parameters.getBackend())
             .addInnerClasses(InvokeMethodWithNonNullParamCheckTest.class)
             .addKeepMainRule(TestClass.class)
             .enableInliningAnnotations()
+            .enableNoMethodStaticizingAnnotations()
             .addOptionsModification(
                 options -> {
                   // Avoid that the class inliner inlines testRewriteInvokeVirtualToThrowNullWith-
@@ -371,6 +378,7 @@
   static class Virtual {
 
     @NeverInline
+    @NoMethodStaticizing
     public String throwIfFirstIsNull(Object first) {
       if (first == null) {
         throw new NullPointerException();
@@ -379,6 +387,7 @@
     }
 
     @NeverInline
+    @NoMethodStaticizing
     public String throwIfSecondIsNull(Object first, Object second, Object third) {
       if (second == null) {
         throw new NullPointerException();
diff --git a/src/test/java/com/android/tools/r8/shaking/keptgraph/KeptByTwoMethods.java b/src/test/java/com/android/tools/r8/shaking/keptgraph/KeptByTwoMethods.java
index 035ddf7..c238e5d 100644
--- a/src/test/java/com/android/tools/r8/shaking/keptgraph/KeptByTwoMethods.java
+++ b/src/test/java/com/android/tools/r8/shaking/keptgraph/KeptByTwoMethods.java
@@ -7,6 +7,7 @@
 
 import com.android.tools.r8.NeverClassInline;
 import com.android.tools.r8.NeverInline;
+import com.android.tools.r8.NoMethodStaticizing;
 import com.android.tools.r8.NoVerticalClassMerging;
 import com.android.tools.r8.TestBase;
 import com.android.tools.r8.TestParameters;
@@ -27,6 +28,7 @@
   public static class A {
 
     @NeverInline
+    @NoMethodStaticizing
     void foo() {
       System.out.println("A.foo!");
     }
@@ -75,6 +77,7 @@
         testForR8(parameters.getBackend())
             .enableGraphInspector()
             .enableNeverClassInliningAnnotations()
+            .enableNoMethodStaticizingAnnotations()
             .enableNoVerticalClassMergingAnnotations()
             .enableInliningAnnotations()
             .addKeepMainRule(TestClass.class)