High-level structure for removing constant parameters

Change-Id: Icdb1ba49934a0cb75544adf5d213c5f31c26cd3e
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 115f31d..41f29a1 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
@@ -23,6 +23,7 @@
 import com.android.tools.r8.shaking.AppInfoWithLiveness;
 import com.android.tools.r8.utils.ThreadUtils;
 import com.android.tools.r8.utils.Timing;
+import java.util.Collection;
 import java.util.List;
 import java.util.Set;
 import java.util.concurrent.ExecutionException;
@@ -127,8 +128,13 @@
       throws ExecutionException {
     assert !appView.getSyntheticItems().hasPendingSyntheticClasses();
     timing.begin("Argument propagator");
-    populateParameterOptimizationInfo(executorService, timing);
-    optimizeMethodParameters();
+    ImmediateProgramSubtypingInfo immediateSubtypingInfo =
+        ImmediateProgramSubtypingInfo.create(appView);
+    List<Set<DexProgramClass>> stronglyConnectedProgramComponents =
+        computeStronglyConnectedProgramClasses(appView, immediateSubtypingInfo);
+    populateParameterOptimizationInfo(
+        immediateSubtypingInfo, stronglyConnectedProgramComponents, executorService, timing);
+    optimizeMethodParameters(immediateSubtypingInfo, stronglyConnectedProgramComponents);
     enqueueMethodsForProcessing(postMethodProcessorBuilder);
     timing.end();
   }
@@ -137,7 +143,11 @@
    * Called by {@link IRConverter} *after* the primary optimization pass to populate the parameter
    * optimization info.
    */
-  private void populateParameterOptimizationInfo(ExecutorService executorService, Timing timing)
+  private void populateParameterOptimizationInfo(
+      ImmediateProgramSubtypingInfo immediateSubtypingInfo,
+      List<Set<DexProgramClass>> stronglyConnectedProgramComponents,
+      ExecutorService executorService,
+      Timing timing)
       throws ExecutionException {
     // Unset the scanner since all code objects have been scanned at this point.
     assert appView.isAllCodeProcessed();
@@ -147,23 +157,39 @@
 
     timing.begin("Compute optimization info");
     new ArgumentPropagatorOptimizationInfoPopulator(
-            appView, codeScannerResult, reprocessingCriteriaCollection)
+            appView,
+            immediateSubtypingInfo,
+            codeScannerResult,
+            reprocessingCriteriaCollection,
+            stronglyConnectedProgramComponents)
         .populateOptimizationInfo(executorService, timing);
     reprocessingCriteriaCollection = null;
     timing.end();
   }
 
   /** Called by {@link IRConverter} to optimize method definitions. */
-  private void optimizeMethodParameters() {
-    // TODO(b/190154391): Remove parameters with constant values.
-    // TODO(b/190154391): Remove unused parameters by simulating they are constant.
-    // TODO(b/190154391): Strengthen the static type of parameters.
-    // TODO(b/190154391): If we learn that a method returns a constant, then consider changing its
-    //  return type to void.
-    // TODO(b/69963623): If we optimize a method to be unconditionally throwing (because it has a
-    //  bottom parameter), then for each caller that becomes unconditionally throwing, we could
-    //  also enqueue the caller's callers for reprocessing. This would propagate the throwing
-    //  information to all call sites.
+  private void optimizeMethodParameters(
+      ImmediateProgramSubtypingInfo immediateSubtypingInfo,
+      List<Set<DexProgramClass>> stronglyConnectedProgramComponents,
+      ExecutorService executorService)
+      throws ExecutionException {
+    Collection<ArgumentPropagatorGraphLens.Builder> partialGraphLensBuilders =
+        ThreadUtils.processItemsWithResults(
+            stronglyConnectedProgramComponents,
+            classes ->
+                new ArgumentPropagatorProgramOptimizer(appView, immediateSubtypingInfo)
+                    .optimize(classes),
+            executorService);
+
+    // Merge all the partial, disjoint graph lens builders into a single graph lens.
+    ArgumentPropagatorGraphLens.Builder graphLensBuilder =
+        ArgumentPropagatorGraphLens.builder(appView);
+    partialGraphLensBuilders.forEach(graphLensBuilder::mergeDisjoint);
+
+    ArgumentPropagatorGraphLens graphLens = graphLensBuilder.build();
+    if (graphLens != null) {
+      appView.setGraphLens(graphLens);
+    }
   }
 
   /**
diff --git a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/ArgumentPropagatorGraphLens.java b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/ArgumentPropagatorGraphLens.java
new file mode 100644
index 0000000..0110197
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/ArgumentPropagatorGraphLens.java
@@ -0,0 +1,108 @@
+// Copyright (c) 2021, 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.optimize.argumentpropagation;
+
+import com.android.tools.r8.graph.AppView;
+import com.android.tools.r8.graph.DexField;
+import com.android.tools.r8.graph.DexMethod;
+import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.GraphLens;
+import com.android.tools.r8.graph.GraphLens.NonIdentityGraphLens;
+import com.android.tools.r8.graph.RewrittenPrototypeDescription;
+import com.android.tools.r8.shaking.AppInfoWithLiveness;
+
+public class ArgumentPropagatorGraphLens extends NonIdentityGraphLens {
+
+  ArgumentPropagatorGraphLens(AppView<AppInfoWithLiveness> appView) {
+    super(appView);
+  }
+
+  public static Builder builder(AppView<AppInfoWithLiveness> appView) {
+    return new Builder(appView);
+  }
+
+  @Override
+  public DexType getOriginalType(DexType type) {
+    return getPrevious().getOriginalType(type);
+  }
+
+  @Override
+  public Iterable<DexType> getOriginalTypes(DexType type) {
+    return getPrevious().getOriginalTypes(type);
+  }
+
+  @Override
+  public DexField getOriginalFieldSignature(DexField field) {
+    return getPrevious().getOriginalFieldSignature(field);
+  }
+
+  @Override
+  public DexField getRenamedFieldSignature(DexField originalField) {
+    return getPrevious().getRenamedFieldSignature(originalField);
+  }
+
+  @Override
+  public DexMethod getOriginalMethodSignature(DexMethod method) {
+    return getPrevious().getOriginalMethodSignature(method);
+  }
+
+  @Override
+  public DexMethod getRenamedMethodSignature(DexMethod originalMethod, GraphLens applied) {
+    return applied != this
+        ? getPrevious().getRenamedMethodSignature(originalMethod, applied)
+        : originalMethod;
+  }
+
+  @Override
+  protected DexType internalDescribeLookupClassType(DexType previous) {
+    return previous;
+  }
+
+  @Override
+  protected FieldLookupResult internalDescribeLookupField(FieldLookupResult previous) {
+    return previous;
+  }
+
+  @Override
+  protected MethodLookupResult internalDescribeLookupMethod(
+      MethodLookupResult previous, DexMethod context) {
+    return previous;
+  }
+
+  @Override
+  protected DexMethod internalGetPreviousMethodSignature(DexMethod method) {
+    return method;
+  }
+
+  @Override
+  public boolean isContextFreeForMethods() {
+    return getPrevious().isContextFreeForMethods();
+  }
+
+  @Override
+  public RewrittenPrototypeDescription lookupPrototypeChangesForMethodDefinition(DexMethod method) {
+    return getPrevious().lookupPrototypeChangesForMethodDefinition(method);
+  }
+
+  public static class Builder {
+
+    private final AppView<AppInfoWithLiveness> appView;
+
+    Builder(AppView<AppInfoWithLiveness> appView) {
+      this.appView = appView;
+    }
+
+    public ArgumentPropagatorGraphLens.Builder mergeDisjoint(
+        ArgumentPropagatorGraphLens.Builder partialGraphLensBuilder) {
+      // TODO(b/190154391): Implement.
+      return this;
+    }
+
+    public ArgumentPropagatorGraphLens build() {
+      // TODO(b/190154391): Implement.
+      return null;
+    }
+  }
+}
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 39d1dc2..53876ab 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
@@ -4,7 +4,6 @@
 
 package com.android.tools.r8.optimize.argumentpropagation;
 
-import static com.android.tools.r8.optimize.argumentpropagation.utils.StronglyConnectedProgramClasses.computeStronglyConnectedProgramClasses;
 
 import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.DexEncodedMethod;
@@ -47,21 +46,19 @@
   private final ArgumentPropagatorReprocessingCriteriaCollection reprocessingCriteriaCollection;
 
   private final ImmediateProgramSubtypingInfo immediateSubtypingInfo;
-  private final List<Set<DexProgramClass>> stronglyConnectedComponents;
+  private final List<Set<DexProgramClass>> stronglyConnectedProgramComponents;
 
   ArgumentPropagatorOptimizationInfoPopulator(
       AppView<AppInfoWithLiveness> appView,
+      ImmediateProgramSubtypingInfo immediateSubtypingInfo,
       MethodStateCollectionByReference methodStates,
-      ArgumentPropagatorReprocessingCriteriaCollection reprocessingCriteriaCollection) {
+      ArgumentPropagatorReprocessingCriteriaCollection reprocessingCriteriaCollection,
+      List<Set<DexProgramClass>> stronglyConnectedProgramComponents) {
     this.appView = appView;
+    this.immediateSubtypingInfo = immediateSubtypingInfo;
     this.methodStates = methodStates;
     this.reprocessingCriteriaCollection = reprocessingCriteriaCollection;
-
-    ImmediateProgramSubtypingInfo immediateSubtypingInfo =
-        ImmediateProgramSubtypingInfo.create(appView);
-    this.immediateSubtypingInfo = immediateSubtypingInfo;
-    this.stronglyConnectedComponents =
-        computeStronglyConnectedProgramClasses(appView, immediateSubtypingInfo);
+    this.stronglyConnectedProgramComponents = stronglyConnectedProgramComponents;
   }
 
   /**
@@ -80,7 +77,9 @@
     //  that the method returns the constant.
     timing.begin("Propagate argument information for virtual methods");
     ThreadUtils.processItems(
-        stronglyConnectedComponents, this::processStronglyConnectedComponent, executorService);
+        stronglyConnectedProgramComponents,
+        this::processStronglyConnectedComponent,
+        executorService);
     timing.end();
 
     // Solve the parameter flow constraints.
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
new file mode 100644
index 0000000..859830b
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/ArgumentPropagatorProgramOptimizer.java
@@ -0,0 +1,37 @@
+// Copyright (c) 2021, 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.optimize.argumentpropagation;
+
+import com.android.tools.r8.graph.AppView;
+import com.android.tools.r8.graph.DexProgramClass;
+import com.android.tools.r8.graph.ImmediateProgramSubtypingInfo;
+import com.android.tools.r8.shaking.AppInfoWithLiveness;
+import java.util.Set;
+
+public class ArgumentPropagatorProgramOptimizer {
+
+  private final AppView<AppInfoWithLiveness> appView;
+  private final ImmediateProgramSubtypingInfo immediateSubtypingInfo;
+
+  public ArgumentPropagatorProgramOptimizer(
+      AppView<AppInfoWithLiveness> appView, ImmediateProgramSubtypingInfo immediateSubtypingInfo) {
+    this.appView = appView;
+    this.immediateSubtypingInfo = immediateSubtypingInfo;
+  }
+
+  // TODO(b/190154391): Remove parameters with constant values.
+  // TODO(b/190154391): Remove unused parameters by simulating they are constant.
+  // TODO(b/190154391): Strengthen the static type of parameters.
+  // TODO(b/190154391): If we learn that a method returns a constant, then consider changing its
+  //  return type to void.
+  // TODO(b/69963623): If we optimize a method to be unconditionally throwing (because it has a
+  //  bottom parameter), then for each caller that becomes unconditionally throwing, we could
+  //  also enqueue the caller's callers for reprocessing. This would propagate the throwing
+  //  information to all call sites.
+  public ArgumentPropagatorGraphLens.Builder optimize(
+      Set<DexProgramClass> stronglyConnectedProgramClasses) {
+    return ArgumentPropagatorGraphLens.builder(appView);
+  }
+}