Use MethodParameter as open variable + add getSingleOpenVariable helper
Change-Id: Ib457ba13e7d49ba702cf893d89f91f42462b32e4
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/path/PathConstraintAnalysis.java b/src/main/java/com/android/tools/r8/ir/analysis/path/PathConstraintAnalysis.java
index dd5b2c9..3d61f0e 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/path/PathConstraintAnalysis.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/path/PathConstraintAnalysis.java
@@ -7,6 +7,7 @@
import com.android.tools.r8.ir.analysis.framework.intraprocedural.IntraproceduralDataflowAnalysis;
import com.android.tools.r8.ir.analysis.path.state.PathConstraintAnalysisState;
import com.android.tools.r8.ir.code.IRCode;
+import com.android.tools.r8.optimize.argumentpropagation.codescanner.MethodParameterFactory;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
/**
@@ -37,11 +38,15 @@
public class PathConstraintAnalysis
extends IntraproceduralDataflowAnalysis<PathConstraintAnalysisState> {
- public PathConstraintAnalysis(AppView<AppInfoWithLiveness> appView, IRCode code) {
+ public PathConstraintAnalysis(
+ AppView<AppInfoWithLiveness> appView,
+ IRCode code,
+ MethodParameterFactory methodParameterFactory) {
super(
appView,
PathConstraintAnalysisState.bottom(),
code,
- new PathConstraintAnalysisTransferFunction(appView.abstractValueFactory()));
+ new PathConstraintAnalysisTransferFunction(
+ appView.abstractValueFactory(), code.context(), methodParameterFactory));
}
}
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/path/PathConstraintAnalysisTransferFunction.java b/src/main/java/com/android/tools/r8/ir/analysis/path/PathConstraintAnalysisTransferFunction.java
index 6b86310..794a9a6 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/path/PathConstraintAnalysisTransferFunction.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/path/PathConstraintAnalysisTransferFunction.java
@@ -4,6 +4,7 @@
package com.android.tools.r8.ir.analysis.path;
import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.ir.analysis.framework.intraprocedural.AbstractTransferFunction;
import com.android.tools.r8.ir.analysis.framework.intraprocedural.TransferFunctionResult;
import com.android.tools.r8.ir.analysis.path.state.PathConstraintAnalysisState;
@@ -11,6 +12,7 @@
import com.android.tools.r8.ir.code.BasicBlock;
import com.android.tools.r8.ir.code.If;
import com.android.tools.r8.ir.code.Instruction;
+import com.android.tools.r8.optimize.argumentpropagation.codescanner.MethodParameterFactory;
import com.android.tools.r8.optimize.argumentpropagation.computation.ComputationTreeBuilder;
import com.android.tools.r8.optimize.argumentpropagation.computation.ComputationTreeNode;
@@ -19,8 +21,12 @@
private final ComputationTreeBuilder computationTreeBuilder;
- PathConstraintAnalysisTransferFunction(AbstractValueFactory abstractValueFactory) {
- computationTreeBuilder = new ComputationTreeBuilder(abstractValueFactory);
+ PathConstraintAnalysisTransferFunction(
+ AbstractValueFactory abstractValueFactory,
+ ProgramMethod method,
+ MethodParameterFactory methodParameterFactory) {
+ computationTreeBuilder =
+ new ComputationTreeBuilder(abstractValueFactory, method, methodParameterFactory);
}
@Override
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/value/AbstractValue.java b/src/main/java/com/android/tools/r8/ir/analysis/value/AbstractValue.java
index b83c92e..6350b1e 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/value/AbstractValue.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/value/AbstractValue.java
@@ -9,6 +9,7 @@
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.lens.GraphLens;
import com.android.tools.r8.ir.analysis.value.objectstate.ObjectState;
+import com.android.tools.r8.optimize.argumentpropagation.codescanner.MethodParameter;
import com.android.tools.r8.optimize.argumentpropagation.computation.ComputationTreeNode;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
import java.util.function.IntFunction;
@@ -29,6 +30,11 @@
return this;
}
+ @Override
+ public MethodParameter getSingleOpenVariable() {
+ return null;
+ }
+
public abstract boolean isNonTrivial();
public boolean isSingleBoolean() {
diff --git a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/MethodParameter.java b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/MethodParameter.java
index 1c83bfa..138725e 100644
--- a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/MethodParameter.java
+++ b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/MethodParameter.java
@@ -7,10 +7,14 @@
import com.android.tools.r8.graph.DexClassAndMethod;
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.ir.analysis.value.AbstractValue;
+import com.android.tools.r8.ir.analysis.value.AbstractValueFactory;
+import com.android.tools.r8.optimize.argumentpropagation.computation.ComputationTreeNode;
import com.android.tools.r8.utils.BooleanUtils;
import java.util.Objects;
+import java.util.function.IntFunction;
-public class MethodParameter implements BaseInFlow {
+public class MethodParameter implements BaseInFlow, ComputationTreeNode {
private final DexMethod method;
private final int index;
@@ -43,11 +47,22 @@
return index;
}
+ @Override
+ public MethodParameter getSingleOpenVariable() {
+ return this;
+ }
+
public DexType getType() {
return method.getArgumentType(index, isMethodStatic);
}
@Override
+ public AbstractValue evaluate(
+ IntFunction<AbstractValue> argumentAssignment, AbstractValueFactory abstractValueFactory) {
+ return argumentAssignment.apply(index);
+ }
+
+ @Override
public int internalCompareToSameKind(InFlow other) {
MethodParameter methodParameter = other.asMethodParameter();
int result = method.compareTo(methodParameter.method);
diff --git a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/computation/ComputationTreeArgumentNode.java b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/computation/ComputationTreeArgumentNode.java
deleted file mode 100644
index 2ea279f..0000000
--- a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/computation/ComputationTreeArgumentNode.java
+++ /dev/null
@@ -1,57 +0,0 @@
-// 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.optimize.argumentpropagation.computation;
-
-import com.android.tools.r8.ir.analysis.value.AbstractValue;
-import com.android.tools.r8.ir.analysis.value.AbstractValueFactory;
-import com.android.tools.r8.utils.ArrayUtils;
-import java.util.Objects;
-import java.util.function.IntFunction;
-
-/** Represents the read of an argument. */
-public class ComputationTreeArgumentNode extends ComputationTreeBaseNode {
-
- private static final int NUM_CANONICALIZED_INSTANCES = 32;
- private static final ComputationTreeArgumentNode[] CANONICALIZED_INSTANCES =
- ArrayUtils.initialize(
- new ComputationTreeArgumentNode[NUM_CANONICALIZED_INSTANCES],
- ComputationTreeArgumentNode::new);
-
- private final int argumentIndex;
-
- private ComputationTreeArgumentNode(int argumentIndex) {
- this.argumentIndex = argumentIndex;
- }
-
- public static ComputationTreeArgumentNode create(int argumentIndex) {
- return argumentIndex < NUM_CANONICALIZED_INSTANCES
- ? CANONICALIZED_INSTANCES[argumentIndex]
- : new ComputationTreeArgumentNode(argumentIndex);
- }
-
- @Override
- public AbstractValue evaluate(
- IntFunction<AbstractValue> argumentAssignment, AbstractValueFactory abstractValueFactory) {
- return argumentAssignment.apply(argumentIndex);
- }
-
- @Override
- public boolean equals(Object obj) {
- if (this == obj) {
- return true;
- }
- if (!(obj instanceof ComputationTreeArgumentNode)) {
- return false;
- }
- ComputationTreeArgumentNode node = (ComputationTreeArgumentNode) obj;
- assert argumentIndex >= NUM_CANONICALIZED_INSTANCES
- || node.argumentIndex >= NUM_CANONICALIZED_INSTANCES;
- return argumentIndex == node.argumentIndex;
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(getClass(), argumentIndex);
- }
-}
diff --git a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/computation/ComputationTreeBuilder.java b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/computation/ComputationTreeBuilder.java
index aca8a03..7e7b541 100644
--- a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/computation/ComputationTreeBuilder.java
+++ b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/computation/ComputationTreeBuilder.java
@@ -8,6 +8,7 @@
import static com.android.tools.r8.ir.code.Opcodes.CONST_NUMBER;
import static com.android.tools.r8.ir.code.Opcodes.IF;
+import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.ir.analysis.value.AbstractValue;
import com.android.tools.r8.ir.analysis.value.AbstractValueFactory;
import com.android.tools.r8.ir.analysis.value.UnknownValue;
@@ -17,13 +18,21 @@
import com.android.tools.r8.ir.code.If;
import com.android.tools.r8.ir.code.Instruction;
import com.android.tools.r8.ir.code.Value;
+import com.android.tools.r8.optimize.argumentpropagation.codescanner.MethodParameterFactory;
public class ComputationTreeBuilder {
private final AbstractValueFactory abstractValueFactory;
+ private final ProgramMethod method;
+ private final MethodParameterFactory methodParameterFactory;
- public ComputationTreeBuilder(AbstractValueFactory abstractValueFactory) {
+ public ComputationTreeBuilder(
+ AbstractValueFactory abstractValueFactory,
+ ProgramMethod method,
+ MethodParameterFactory methodParameterFactory) {
this.abstractValueFactory = abstractValueFactory;
+ this.method = method;
+ this.methodParameterFactory = methodParameterFactory;
}
// TODO(b/302281503): "Long lived" computation trees (i.e., the ones that survive past the IR
@@ -44,7 +53,7 @@
{
Argument argument = instruction.asArgument();
if (argument.getOutType().isInt()) {
- return ComputationTreeArgumentNode.create(argument.getIndex());
+ return methodParameterFactory.create(method, argument.getIndex());
}
break;
}
diff --git a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/computation/ComputationTreeLogicalBinopNode.java b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/computation/ComputationTreeLogicalBinopNode.java
index 8f0c95f..d7cf46b 100644
--- a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/computation/ComputationTreeLogicalBinopNode.java
+++ b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/computation/ComputationTreeLogicalBinopNode.java
@@ -4,6 +4,7 @@
package com.android.tools.r8.optimize.argumentpropagation.computation;
import com.android.tools.r8.ir.code.NumericType;
+import com.android.tools.r8.optimize.argumentpropagation.codescanner.MethodParameter;
public abstract class ComputationTreeLogicalBinopNode extends ComputationTreeBaseNode {
@@ -20,6 +21,15 @@
return NumericType.INT;
}
+ @Override
+ public final MethodParameter getSingleOpenVariable() {
+ MethodParameter openVariable = left.getSingleOpenVariable();
+ if (openVariable != null) {
+ return right.getSingleOpenVariable() == null ? openVariable : null;
+ }
+ return right.getSingleOpenVariable();
+ }
+
boolean internalIsEqualTo(ComputationTreeLogicalBinopNode node) {
return left.equals(node.left) && right.equals(node.right);
}
diff --git a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/computation/ComputationTreeNode.java b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/computation/ComputationTreeNode.java
index f055cff..1231d76 100644
--- a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/computation/ComputationTreeNode.java
+++ b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/computation/ComputationTreeNode.java
@@ -5,6 +5,7 @@
import com.android.tools.r8.ir.analysis.value.AbstractValue;
import com.android.tools.r8.ir.analysis.value.AbstractValueFactory;
+import com.android.tools.r8.optimize.argumentpropagation.codescanner.MethodParameter;
import java.util.function.IntFunction;
/**
@@ -16,6 +17,8 @@
AbstractValue evaluate(
IntFunction<AbstractValue> argumentAssignment, AbstractValueFactory abstractValueFactory);
+ MethodParameter getSingleOpenVariable();
+
default boolean isUnknown() {
return false;
}
diff --git a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/computation/ComputationTreeUnopNode.java b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/computation/ComputationTreeUnopNode.java
index 3c3fc1e..8ac1ca9 100644
--- a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/computation/ComputationTreeUnopNode.java
+++ b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/computation/ComputationTreeUnopNode.java
@@ -3,6 +3,8 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.optimize.argumentpropagation.computation;
+import com.android.tools.r8.optimize.argumentpropagation.codescanner.MethodParameter;
+
public abstract class ComputationTreeUnopNode extends ComputationTreeBaseNode {
final ComputationTreeNode operand;
@@ -12,6 +14,11 @@
this.operand = operand;
}
+ @Override
+ public MethodParameter getSingleOpenVariable() {
+ return operand.getSingleOpenVariable();
+ }
+
boolean internalIsEqualTo(ComputationTreeUnopNode node) {
return operand.equals(node.operand);
}
diff --git a/src/test/java/com/android/tools/r8/ir/analysis/path/PathConstraintAnalysisUnitTest.java b/src/test/java/com/android/tools/r8/ir/analysis/path/PathConstraintAnalysisUnitTest.java
index 56573a5..597cca6 100644
--- a/src/test/java/com/android/tools/r8/ir/analysis/path/PathConstraintAnalysisUnitTest.java
+++ b/src/test/java/com/android/tools/r8/ir/analysis/path/PathConstraintAnalysisUnitTest.java
@@ -17,6 +17,7 @@
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.optimize.argumentpropagation.computation.ComputationTreeNode;
import com.android.tools.r8.optimize.argumentpropagation.computation.ComputationTreeUnopCompareNode;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
@@ -50,7 +51,8 @@
CodeInspector inspector = new CodeInspector(app);
IRCode code =
inspector.clazz(Main.class).uniqueMethodWithOriginalName("greet").buildIR(appView);
- PathConstraintAnalysis analysis = new PathConstraintAnalysis(appView, code);
+ PathConstraintAnalysis analysis =
+ new PathConstraintAnalysis(appView, code, new MethodParameterFactory());
DataflowAnalysisResult result = analysis.run(code.entryBlock());
assertTrue(result.isSuccessfulAnalysisResult());
SuccessfulDataflowAnalysisResult<BasicBlock, PathConstraintAnalysisState> successfulResult =