Introduce a PathConstraintSupplier to allow reuse

Change-Id: I58c1fcaf3f02d96120aa5851fd16f797f918b6db
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/path/PathConstraintSupplier.java b/src/main/java/com/android/tools/r8/ir/analysis/path/PathConstraintSupplier.java
new file mode 100644
index 0000000..cb81605
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/ir/analysis/path/PathConstraintSupplier.java
@@ -0,0 +1,41 @@
+// Copyright (c) 2024, 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.ir.analysis.path;
+
+import com.android.tools.r8.graph.AppView;
+import com.android.tools.r8.ir.analysis.framework.intraprocedural.DataflowAnalysisResult.SuccessfulDataflowAnalysisResult;
+import com.android.tools.r8.ir.analysis.path.state.PathConstraintAnalysisState;
+import com.android.tools.r8.ir.code.BasicBlock;
+import com.android.tools.r8.ir.code.IRCode;
+import com.android.tools.r8.optimize.argumentpropagation.codescanner.MethodParameterFactory;
+import com.android.tools.r8.shaking.AppInfoWithLiveness;
+
+public class PathConstraintSupplier {
+
+  private final AppView<AppInfoWithLiveness> appView;
+  private final IRCode code;
+  private final MethodParameterFactory methodParameterFactory;
+
+  private SuccessfulDataflowAnalysisResult<BasicBlock, PathConstraintAnalysisState>
+      pathConstraintAnalysisResult;
+
+  public PathConstraintSupplier(
+      AppView<AppInfoWithLiveness> appView,
+      IRCode code,
+      MethodParameterFactory methodParameterFactory) {
+    this.appView = appView;
+    this.code = code;
+    this.methodParameterFactory = methodParameterFactory;
+  }
+
+  public PathConstraintAnalysisState getPathConstraint(BasicBlock block) {
+    if (pathConstraintAnalysisResult == null) {
+      PathConstraintAnalysis analysis =
+          new PathConstraintAnalysis(appView, code, methodParameterFactory);
+      pathConstraintAnalysisResult = analysis.run(code.entryBlock()).asSuccessfulAnalysisResult();
+      assert pathConstraintAnalysisResult != null;
+    }
+    return pathConstraintAnalysisResult.getBlockExitState(block);
+  }
+}
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 a17aa98..2273dbb 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
@@ -10,6 +10,7 @@
 import com.android.tools.r8.graph.ImmediateProgramSubtypingInfo;
 import com.android.tools.r8.graph.ProgramMethod;
 import com.android.tools.r8.graph.PrunedItems;
+import com.android.tools.r8.ir.analysis.path.PathConstraintSupplier;
 import com.android.tools.r8.ir.code.AbstractValueSupplier;
 import com.android.tools.r8.ir.code.IRCode;
 import com.android.tools.r8.ir.conversion.IRConverter;
@@ -128,7 +129,9 @@
       assert methodProcessor.isPrimaryMethodProcessor();
       AbstractValueSupplier abstractValueSupplier =
           value -> value.getAbstractValue(appView, method);
-      codeScanner.scan(method, code, abstractValueSupplier, timing);
+      PathConstraintSupplier pathConstraintSupplier =
+          new PathConstraintSupplier(appView, code, codeScanner.getMethodParameterFactory());
+      codeScanner.scan(method, code, abstractValueSupplier, pathConstraintSupplier, timing);
 
       assert effectivelyUnusedArgumentsAnalysis != null;
       effectivelyUnusedArgumentsAnalysis.scan(method, code);
diff --git a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/ArgumentPropagatorCodeScanner.java b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/ArgumentPropagatorCodeScanner.java
index a3961f0..ba31341 100644
--- a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/ArgumentPropagatorCodeScanner.java
+++ b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/ArgumentPropagatorCodeScanner.java
@@ -14,10 +14,8 @@
 import com.android.tools.r8.graph.MethodResolutionResult.SingleResolutionResult;
 import com.android.tools.r8.graph.ProgramField;
 import com.android.tools.r8.graph.ProgramMethod;
-import com.android.tools.r8.ir.analysis.framework.intraprocedural.DataflowAnalysisResult.SuccessfulDataflowAnalysisResult;
-import com.android.tools.r8.ir.analysis.path.PathConstraintAnalysis;
+import com.android.tools.r8.ir.analysis.path.PathConstraintSupplier;
 import com.android.tools.r8.ir.analysis.path.state.ConcretePathConstraintAnalysisState;
-import com.android.tools.r8.ir.analysis.path.state.PathConstraintAnalysisState;
 import com.android.tools.r8.ir.analysis.type.DynamicType;
 import com.android.tools.r8.ir.analysis.type.DynamicTypeWithUpperBound;
 import com.android.tools.r8.ir.analysis.type.Nullability;
@@ -111,7 +109,7 @@
 
   private final FieldValueFactory fieldValueFactory = new FieldValueFactory();
 
-  private final MethodParameterFactory methodParameterFactory = new MethodParameterFactory();
+  final MethodParameterFactory methodParameterFactory = new MethodParameterFactory();
 
   private final Set<DexMethod> monomorphicVirtualMethods = Sets.newIdentityHashSet();
 
@@ -163,6 +161,10 @@
     return fieldStates;
   }
 
+  public MethodParameterFactory getMethodParameterFactory() {
+    return methodParameterFactory;
+  }
+
   public MethodStateCollectionByReference getMethodStates() {
     return methodStates;
   }
@@ -228,8 +230,9 @@
       ProgramMethod method,
       IRCode code,
       AbstractValueSupplier abstractValueSupplier,
+      PathConstraintSupplier pathConstraintSupplier,
       Timing timing) {
-    new CodeScanner(abstractValueSupplier, code, method).scan(timing);
+    new CodeScanner(abstractValueSupplier, code, method, pathConstraintSupplier).scan(timing);
   }
 
   protected class CodeScanner {
@@ -237,16 +240,19 @@
     protected final AbstractValueSupplier abstractValueSupplier;
     protected final IRCode code;
     protected final ProgramMethod context;
+    private final PathConstraintSupplier pathConstraintSupplier;
 
-    private SuccessfulDataflowAnalysisResult<BasicBlock, PathConstraintAnalysisState>
-        pathConstraintAnalysisResult;
     private Object2IntMap<Phi> phiNumbering = null;
 
     protected CodeScanner(
-        AbstractValueSupplier abstractValueSupplier, IRCode code, ProgramMethod method) {
+        AbstractValueSupplier abstractValueSupplier,
+        IRCode code,
+        ProgramMethod method,
+        PathConstraintSupplier pathConstraintSupplier) {
       this.abstractValueSupplier = abstractValueSupplier;
       this.code = code;
       this.context = method;
+      this.pathConstraintSupplier = pathConstraintSupplier;
     }
 
     public void scan(Timing timing) {
@@ -419,9 +425,13 @@
         return null;
       }
       ConcretePathConstraintAnalysisState leftPredecessorPathConstraint =
-          getPathConstraint(phi.getBlock().getPredecessors().get(0)).asConcreteState();
+          pathConstraintSupplier
+              .getPathConstraint(phi.getBlock().getPredecessors().get(0))
+              .asConcreteState();
       ConcretePathConstraintAnalysisState rightPredecessorPathConstraint =
-          getPathConstraint(phi.getBlock().getPredecessors().get(1)).asConcreteState();
+          pathConstraintSupplier
+              .getPathConstraint(phi.getBlock().getPredecessors().get(1))
+              .asConcreteState();
       if (leftPredecessorPathConstraint == null || rightPredecessorPathConstraint == null) {
         return null;
       }
@@ -913,16 +923,6 @@
       }
     }
 
-    private PathConstraintAnalysisState getPathConstraint(BasicBlock block) {
-      if (pathConstraintAnalysisResult == null) {
-        PathConstraintAnalysis analysis =
-            new PathConstraintAnalysis(appView, code, methodParameterFactory);
-        pathConstraintAnalysisResult = analysis.run(code.entryBlock()).asSuccessfulAnalysisResult();
-        assert pathConstraintAnalysisResult != null;
-      }
-      return pathConstraintAnalysisResult.getBlockExitState(block);
-    }
-
     @SuppressWarnings("ReferenceEquality")
     private DexMethod getRepresentative(InvokeMethod invoke, ProgramMethod resolvedMethod) {
       if (resolvedMethod.getDefinition().belongsToDirectPool()) {
diff --git a/src/main/java/com/android/tools/r8/optimize/compose/ArgumentPropagatorCodeScannerForComposableFunctions.java b/src/main/java/com/android/tools/r8/optimize/compose/ArgumentPropagatorCodeScannerForComposableFunctions.java
index 2116f3a..371af3d 100644
--- a/src/main/java/com/android/tools/r8/optimize/compose/ArgumentPropagatorCodeScannerForComposableFunctions.java
+++ b/src/main/java/com/android/tools/r8/optimize/compose/ArgumentPropagatorCodeScannerForComposableFunctions.java
@@ -6,6 +6,7 @@
 import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.DexType;
 import com.android.tools.r8.graph.ProgramMethod;
+import com.android.tools.r8.ir.analysis.path.PathConstraintSupplier;
 import com.android.tools.r8.ir.code.AbstractValueSupplier;
 import com.android.tools.r8.ir.code.IRCode;
 import com.android.tools.r8.ir.code.InvokeMethod;
@@ -30,8 +31,9 @@
       ProgramMethod method,
       IRCode code,
       AbstractValueSupplier abstractValueSupplier,
+      PathConstraintSupplier pathConstraintSupplier,
       Timing timing) {
-    new CodeScanner(abstractValueSupplier, code, method).scan(timing);
+    new CodeScanner(abstractValueSupplier, code, method, pathConstraintSupplier).scan(timing);
   }
 
   @Override
@@ -44,8 +46,11 @@
   private class CodeScanner extends ArgumentPropagatorCodeScanner.CodeScanner {
 
     protected CodeScanner(
-        AbstractValueSupplier abstractValueSupplier, IRCode code, ProgramMethod method) {
-      super(abstractValueSupplier, code, method);
+        AbstractValueSupplier abstractValueSupplier,
+        IRCode code,
+        ProgramMethod method,
+        PathConstraintSupplier pathConstraintSupplier) {
+      super(abstractValueSupplier, code, method, pathConstraintSupplier);
     }
 
     @Override
diff --git a/src/main/java/com/android/tools/r8/optimize/compose/ComposeMethodProcessor.java b/src/main/java/com/android/tools/r8/optimize/compose/ComposeMethodProcessor.java
index 210a674..3b51e7c 100644
--- a/src/main/java/com/android/tools/r8/optimize/compose/ComposeMethodProcessor.java
+++ b/src/main/java/com/android/tools/r8/optimize/compose/ComposeMethodProcessor.java
@@ -13,6 +13,7 @@
 import com.android.tools.r8.graph.ProgramField;
 import com.android.tools.r8.graph.ProgramMethod;
 import com.android.tools.r8.ir.analysis.constant.SparseConditionalConstantPropagation;
+import com.android.tools.r8.ir.analysis.path.PathConstraintSupplier;
 import com.android.tools.r8.ir.analysis.value.AbstractValue;
 import com.android.tools.r8.ir.code.AbstractValueSupplier;
 import com.android.tools.r8.ir.code.IRCode;
@@ -233,7 +234,9 @@
           assert abstractValue != null;
           return abstractValue;
         };
-    codeScanner.scan(method, code, abstractValueSupplier, timing);
+    PathConstraintSupplier pathConstraintSupplier =
+        new PathConstraintSupplier(appView, code, codeScanner.getMethodParameterFactory());
+    codeScanner.scan(method, code, abstractValueSupplier, pathConstraintSupplier, timing);
   }
 
   public boolean isProcessed(ComposableCallGraphNode node) {