Don't treat unused arguments as being constant null/zero

This does not work for effectively unused arguments. Unused arguments are now removed and substituted by a special UnusedArgument instruction, which must be removed by lens code rewriting.

Change-Id: Ia632fe53c5c8d997468e1c6272c3c76b41a2dbbe
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 5f43dd3..4b8bff6 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
@@ -206,7 +206,6 @@
             appView,
             immediateSubtypingInfo,
             codeScannerResult,
-            reprocessingCriteriaCollection,
             stronglyConnectedProgramComponents,
             interfaceDispatchOutsideProgram)
         .populateOptimizationInfo(converter, executorService, timing);
diff --git a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/ArgumentPropagatorOptimizationInfoPopulator.java b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/ArgumentPropagatorOptimizationInfoPopulator.java
index f9bfde1..ac24eac 100644
--- a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/ArgumentPropagatorOptimizationInfoPopulator.java
+++ b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/ArgumentPropagatorOptimizationInfoPopulator.java
@@ -33,14 +33,11 @@
 import com.android.tools.r8.optimize.argumentpropagation.propagation.InParameterFlowPropagator;
 import com.android.tools.r8.optimize.argumentpropagation.propagation.InterfaceMethodArgumentPropagator;
 import com.android.tools.r8.optimize.argumentpropagation.propagation.VirtualDispatchMethodArgumentPropagator;
-import com.android.tools.r8.optimize.argumentpropagation.reprocessingcriteria.ArgumentPropagatorReprocessingCriteriaCollection;
 import com.android.tools.r8.optimize.argumentpropagation.utils.WideningUtils;
 import com.android.tools.r8.shaking.AppInfoWithLiveness;
 import com.android.tools.r8.utils.ListUtils;
 import com.android.tools.r8.utils.ThreadUtils;
 import com.android.tools.r8.utils.Timing;
-import com.google.common.collect.Iterables;
-import java.util.BitSet;
 import java.util.List;
 import java.util.Set;
 import java.util.concurrent.ExecutionException;
@@ -56,7 +53,6 @@
 
   private final AppView<AppInfoWithLiveness> appView;
   private final MethodStateCollectionByReference methodStates;
-  private final ArgumentPropagatorReprocessingCriteriaCollection reprocessingCriteriaCollection;
 
   private final ImmediateProgramSubtypingInfo immediateSubtypingInfo;
   private final List<Set<DexProgramClass>> stronglyConnectedProgramComponents;
@@ -68,13 +64,11 @@
       AppView<AppInfoWithLiveness> appView,
       ImmediateProgramSubtypingInfo immediateSubtypingInfo,
       MethodStateCollectionByReference methodStates,
-      ArgumentPropagatorReprocessingCriteriaCollection reprocessingCriteriaCollection,
       List<Set<DexProgramClass>> stronglyConnectedProgramComponents,
       BiConsumer<Set<DexProgramClass>, DexMethodSignature> interfaceDispatchOutsideProgram) {
     this.appView = appView;
     this.immediateSubtypingInfo = immediateSubtypingInfo;
     this.methodStates = methodStates;
-    this.reprocessingCriteriaCollection = reprocessingCriteriaCollection;
     this.stronglyConnectedProgramComponents = stronglyConnectedProgramComponents;
     this.interfaceDispatchOutsideProgram = interfaceDispatchOutsideProgram;
   }
@@ -172,7 +166,6 @@
     }
 
     methodState = getMethodStateAfterUninstantiatedParameterRemoval(method, methodState);
-    methodState = getMethodStateAfterUnusedParameterRemoval(method, methodState);
 
     if (methodState.isUnknown()) {
       // Nothing is known about the arguments to this method.
@@ -254,57 +247,6 @@
         : methodState;
   }
 
-  private MethodState getMethodStateAfterUnusedParameterRemoval(
-      ProgramMethod method, MethodState methodState) {
-    assert methodState.isMonomorphic() || methodState.isUnknown();
-    if (!method.getOptimizationInfo().hasUnusedArguments()
-        || appView.appInfo().isKeepUnusedArgumentsMethod(method)) {
-      return methodState;
-    }
-
-    int numberOfArguments = method.getDefinition().getNumberOfArguments();
-    List<ParameterState> parameterStates =
-        methodState.isMonomorphic()
-            ? methodState.asMonomorphic().getParameterStates()
-            : ListUtils.newInitializedArrayList(numberOfArguments, ParameterState.unknown());
-
-    BitSet unusedArguments = method.getOptimizationInfo().getUnusedArguments();
-    for (int argumentIndex = method.getDefinition().getFirstNonReceiverArgumentIndex();
-        argumentIndex < numberOfArguments;
-        argumentIndex++) {
-      boolean isUnused = unusedArguments.get(argumentIndex);
-      if (isUnused) {
-        DexType argumentType = method.getArgumentType(argumentIndex);
-        parameterStates.set(argumentIndex, getUnusedParameterState(argumentType));
-      }
-    }
-
-    if (methodState.isUnknown()) {
-      if (!unusedArguments.get(0) || Iterables.any(parameterStates, ParameterState::isConcrete)) {
-        assert parameterStates.stream().anyMatch(ParameterState::isConcrete);
-        return new ConcreteMonomorphicMethodState(parameterStates);
-      }
-    }
-    return methodState;
-  }
-
-  private ParameterState getUnusedParameterState(DexType argumentType) {
-    if (argumentType.isArrayType()) {
-      // Ensure argument removal by simulating that this unused parameter is the constant null.
-      return new ConcreteArrayTypeParameterState(Nullability.definitelyNull());
-    } else if (argumentType.isClassType()) {
-      // Ensure argument removal by simulating that this unused parameter is the constant null.
-      return new ConcreteClassTypeParameterState(
-          appView.abstractValueFactory().createNullValue(), DynamicType.definitelyNull());
-    } else {
-      assert argumentType.isPrimitiveType();
-      // Ensure argument removal by simulating that this unused parameter is the constant zero.
-      // Note that the same zero value is used for all primitive types.
-      return new ConcretePrimitiveTypeParameterState(
-          appView.abstractValueFactory().createZeroValue());
-    }
-  }
-
   private boolean widenDynamicTypes(
       ProgramMethod method, ConcreteMonomorphicMethodState methodState) {
     for (int argumentIndex = 0;
diff --git a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/ArgumentPropagatorProgramOptimizer.java b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/ArgumentPropagatorProgramOptimizer.java
index 7d3eb3d..c2912c0 100644
--- a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/ArgumentPropagatorProgramOptimizer.java
+++ b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/ArgumentPropagatorProgramOptimizer.java
@@ -484,6 +484,13 @@
           // OK, this parameter can be removed.
           continue;
         }
+        if (method.getOptimizationInfo().hasUnusedArguments()
+            && method.getOptimizationInfo().getUnusedArguments().get(parameterIndex)
+            && ParameterRemovalUtils.canRemoveUnusedParametersFrom(appView, method)
+            && ParameterRemovalUtils.canRemoveUnusedParameter(appView, method, parameterIndex)) {
+          // OK, this parameter is unused.
+          continue;
+        }
         CallSiteOptimizationInfo optimizationInfo = method.getOptimizationInfo().getArgumentInfos();
         if (optimizationInfo.isConcreteCallSiteOptimizationInfo()) {
           ConcreteCallSiteOptimizationInfo concreteOptimizationInfo =
@@ -1000,38 +1007,47 @@
                 .build());
       }
 
-      ConcreteCallSiteOptimizationInfo optimizationInfo =
-          method.getOptimizationInfo().getArgumentInfos().asConcreteCallSiteOptimizationInfo();
-      if (optimizationInfo != null) {
-        for (int argumentIndex = method.getDefinition().getFirstNonReceiverArgumentIndex();
-            argumentIndex < method.getDefinition().getNumberOfArguments();
-            argumentIndex++) {
-          if (removableParameterIndices.test(argumentIndex)) {
-            AbstractValue abstractValue = optimizationInfo.getAbstractArgumentValue(argumentIndex);
-            if (abstractValue.isSingleValue()
-                && abstractValue.asSingleValue().isMaterializableInContext(appView, method)) {
-              parameterChangesBuilder.addArgumentInfo(
-                  argumentIndex,
-                  RemovedArgumentInfo.builder()
-                      .setSingleValue(abstractValue.asSingleValue())
-                      .setType(method.getArgumentType(argumentIndex))
-                      .build());
-              continue;
-            }
-          }
-
-          DexType dynamicType = newParameterTypes.apply(argumentIndex);
-          if (dynamicType != null) {
-            DexType staticType = method.getArgumentType(argumentIndex);
-            assert dynamicType != staticType;
+      CallSiteOptimizationInfo optimizationInfo = method.getOptimizationInfo().getArgumentInfos();
+      for (int argumentIndex = method.getDefinition().getFirstNonReceiverArgumentIndex();
+          argumentIndex < method.getDefinition().getNumberOfArguments();
+          argumentIndex++) {
+        if (removableParameterIndices.test(argumentIndex)) {
+          if (method.getOptimizationInfo().hasUnusedArguments()
+              && method.getOptimizationInfo().getUnusedArguments().get(argumentIndex)
+              && ParameterRemovalUtils.canRemoveUnusedParametersFrom(appView, method)
+              && ParameterRemovalUtils.canRemoveUnusedParameter(appView, method, argumentIndex)) {
             parameterChangesBuilder.addArgumentInfo(
                 argumentIndex,
-                RewrittenTypeInfo.builder()
-                    .setCastType(dynamicType)
-                    .setOldType(staticType)
-                    .setNewType(dynamicType)
+                RemovedArgumentInfo.builder()
+                    .setType(method.getArgumentType(argumentIndex))
                     .build());
+            continue;
           }
+
+          AbstractValue abstractValue = optimizationInfo.getAbstractArgumentValue(argumentIndex);
+          if (abstractValue.isSingleValue()
+              && abstractValue.asSingleValue().isMaterializableInContext(appView, method)) {
+            parameterChangesBuilder.addArgumentInfo(
+                argumentIndex,
+                RemovedArgumentInfo.builder()
+                    .setSingleValue(abstractValue.asSingleValue())
+                    .setType(method.getArgumentType(argumentIndex))
+                    .build());
+            continue;
+          }
+        }
+
+        DexType dynamicType = newParameterTypes.apply(argumentIndex);
+        if (dynamicType != null) {
+          DexType staticType = method.getArgumentType(argumentIndex);
+          assert dynamicType != staticType;
+          parameterChangesBuilder.addArgumentInfo(
+              argumentIndex,
+              RewrittenTypeInfo.builder()
+                  .setCastType(dynamicType)
+                  .setOldType(staticType)
+                  .setNewType(dynamicType)
+                  .build());
         }
       }
       return parameterChangesBuilder.build();