Introduce base class for computation tree building
Change-Id: Ic41526c33af976c5298bfe627c0b9ce333c308c5
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 3d61f0e..12c6309 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
@@ -47,6 +47,6 @@
PathConstraintAnalysisState.bottom(),
code,
new PathConstraintAnalysisTransferFunction(
- appView.abstractValueFactory(), code.context(), methodParameterFactory));
+ appView, code, 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 c61df2a..97bb2d6 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
@@ -3,31 +3,34 @@
// 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.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.ConcretePathConstraintAnalysisState;
import com.android.tools.r8.ir.analysis.path.state.PathConstraintAnalysisState;
-import com.android.tools.r8.ir.analysis.value.AbstractValueFactory;
import com.android.tools.r8.ir.code.BasicBlock;
+import com.android.tools.r8.ir.code.IRCode;
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;
+import com.android.tools.r8.optimize.argumentpropagation.computation.DefaultComputationTreeBuilder;
+import com.android.tools.r8.shaking.AppInfoWithLiveness;
public class PathConstraintAnalysisTransferFunction
implements AbstractTransferFunction<BasicBlock, Instruction, PathConstraintAnalysisState> {
- private final ComputationTreeBuilder computationTreeBuilder;
+ private final DefaultComputationTreeBuilder computationTreeBuilder;
PathConstraintAnalysisTransferFunction(
- AbstractValueFactory abstractValueFactory,
+ AppView<AppInfoWithLiveness> appView,
+ IRCode code,
ProgramMethod method,
MethodParameterFactory methodParameterFactory) {
computationTreeBuilder =
- new ComputationTreeBuilder(abstractValueFactory, method, methodParameterFactory);
+ new DefaultComputationTreeBuilder(appView, code, method, methodParameterFactory);
}
@Override
diff --git a/src/main/java/com/android/tools/r8/ir/code/InstructionOrPhi.java b/src/main/java/com/android/tools/r8/ir/code/InstructionOrPhi.java
index 0ae5aaf..34d9483 100644
--- a/src/main/java/com/android/tools/r8/ir/code/InstructionOrPhi.java
+++ b/src/main/java/com/android/tools/r8/ir/code/InstructionOrPhi.java
@@ -4,27 +4,4 @@
package com.android.tools.r8.ir.code;
-public interface InstructionOrPhi {
-
- default boolean isInstruction() {
- return false;
- }
-
- default Instruction asInstruction() {
- return null;
- }
-
- default boolean isPhi() {
- return false;
- }
-
- default boolean isStackMapPhi() {
- return false;
- }
-
- default Phi asPhi() {
- return null;
- }
-
- BasicBlock getBlock();
-}
+public interface InstructionOrPhi extends InstructionOrValue {}
diff --git a/src/main/java/com/android/tools/r8/ir/code/InstructionOrValue.java b/src/main/java/com/android/tools/r8/ir/code/InstructionOrValue.java
new file mode 100644
index 0000000..b45fd92
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/ir/code/InstructionOrValue.java
@@ -0,0 +1,33 @@
+// 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.code;
+
+public interface InstructionOrValue {
+
+ default boolean isInstruction() {
+ return false;
+ }
+
+ default Instruction asInstruction() {
+ return null;
+ }
+
+ default boolean isPhi() {
+ return false;
+ }
+
+ default boolean isStackMapPhi() {
+ return false;
+ }
+
+ default Phi asPhi() {
+ return null;
+ }
+
+ default Value asValue() {
+ return null;
+ }
+
+ BasicBlock getBlock();
+}
diff --git a/src/main/java/com/android/tools/r8/ir/code/Value.java b/src/main/java/com/android/tools/r8/ir/code/Value.java
index 5fc512f..d08946f 100644
--- a/src/main/java/com/android/tools/r8/ir/code/Value.java
+++ b/src/main/java/com/android/tools/r8/ir/code/Value.java
@@ -51,7 +51,7 @@
import java.util.function.Consumer;
import java.util.function.Predicate;
-public class Value implements Comparable<Value> {
+public class Value implements Comparable<Value>, InstructionOrValue {
public void constrainType(
ValueTypeConstraint constraint, ProgramMethod method, Reporter reporter) {
@@ -789,6 +789,11 @@
}
@Override
+ public Value asValue() {
+ return this;
+ }
+
+ @Override
public int compareTo(Value value) {
return Integer.compare(this.number, value.number);
}
@@ -943,14 +948,6 @@
return predicate.test(definition);
}
- public boolean isPhi() {
- return false;
- }
-
- public Phi asPhi() {
- return null;
- }
-
/**
* Returns whether this value is known to never be <code>null</code>.
*/
@@ -1120,6 +1117,7 @@
return definition.hasBlock();
}
+ @Override
public BasicBlock getBlock() {
return definition.getBlock();
}
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 74804a2..a2a899b 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
@@ -3,102 +3,76 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.optimize.argumentpropagation.computation;
-import static com.android.tools.r8.ir.code.Opcodes.AND;
-import static com.android.tools.r8.ir.code.Opcodes.ARGUMENT;
-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.AppView;
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;
-import com.android.tools.r8.ir.code.And;
-import com.android.tools.r8.ir.code.Argument;
-import com.android.tools.r8.ir.code.ConstNumber;
-import com.android.tools.r8.ir.code.If;
+import com.android.tools.r8.ir.code.IRCode;
import com.android.tools.r8.ir.code.Instruction;
+import com.android.tools.r8.ir.code.InstructionOrValue;
+import com.android.tools.r8.ir.code.Phi;
import com.android.tools.r8.ir.code.Value;
import com.android.tools.r8.optimize.argumentpropagation.codescanner.MethodParameterFactory;
+import com.android.tools.r8.shaking.AppInfoWithLiveness;
import java.util.IdentityHashMap;
import java.util.Map;
-public class ComputationTreeBuilder {
+public abstract class ComputationTreeBuilder {
- private final AbstractValueFactory abstractValueFactory;
- private final ProgramMethod method;
- private final MethodParameterFactory methodParameterFactory;
+ final AppView<AppInfoWithLiveness> appView;
+ final IRCode code;
+ final ProgramMethod method;
+ final MethodParameterFactory methodParameterFactory;
- private final Map<Instruction, ComputationTreeNode> cache = new IdentityHashMap<>();
+ private final Map<InstructionOrValue, ComputationTreeNode> cache = new IdentityHashMap<>();
public ComputationTreeBuilder(
- AbstractValueFactory abstractValueFactory,
+ AppView<AppInfoWithLiveness> appView,
+ IRCode code,
ProgramMethod method,
MethodParameterFactory methodParameterFactory) {
- this.abstractValueFactory = abstractValueFactory;
+ this.appView = appView;
+ this.code = code;
this.method = method;
this.methodParameterFactory = methodParameterFactory;
}
+ AbstractValueFactory factory() {
+ return appView.abstractValueFactory();
+ }
+
// TODO(b/302281503): "Long lived" computation trees (i.e., the ones that survive past the IR
// conversion of the current method) should be canonicalized.
- public ComputationTreeNode getOrBuildComputationTree(Instruction instruction) {
- ComputationTreeNode existing = cache.get(instruction);
+ public final ComputationTreeNode getOrBuildComputationTree(
+ InstructionOrValue instructionOrValue) {
+ ComputationTreeNode existing = cache.get(instructionOrValue);
if (existing != null) {
return existing;
}
- ComputationTreeNode result = buildComputationTree(instruction);
- cache.put(instruction, result);
+ ComputationTreeNode result = buildComputationTree(instructionOrValue);
+ cache.put(instructionOrValue, result);
return result;
}
- private ComputationTreeNode buildComputationTree(Instruction instruction) {
- switch (instruction.opcode()) {
- case AND:
- {
- And and = instruction.asAnd();
- ComputationTreeNode left = buildComputationTreeFromValue(and.leftValue());
- ComputationTreeNode right = buildComputationTreeFromValue(and.rightValue());
- return ComputationTreeLogicalBinopAndNode.create(left, right);
- }
- case ARGUMENT:
- {
- Argument argument = instruction.asArgument();
- if (argument.getOutType().isInt()) {
- return methodParameterFactory.create(method, argument.getIndex());
- }
- break;
- }
- case CONST_NUMBER:
- {
- ConstNumber constNumber = instruction.asConstNumber();
- if (constNumber.getOutType().isInt()) {
- return constNumber.getAbstractValue(abstractValueFactory);
- }
- break;
- }
- case IF:
- {
- If theIf = instruction.asIf();
- if (theIf.isZeroTest()) {
- ComputationTreeNode operand = buildComputationTreeFromValue(theIf.lhs());
- return ComputationTreeUnopCompareNode.create(operand, theIf.getType());
- }
- break;
- }
- default:
- break;
+ private ComputationTreeNode buildComputationTree(InstructionOrValue instructionOrValue) {
+ if (instructionOrValue.isInstruction()) {
+ return buildComputationTree(instructionOrValue.asInstruction());
+ } else {
+ Value value = instructionOrValue.asValue();
+ if (value.isPhi()) {
+ return buildComputationTree(value.asPhi());
+ } else {
+ return buildComputationTree(value.getDefinition());
+ }
}
- return AbstractValue.unknown();
}
- private ComputationTreeNode buildComputationTreeFromValue(Value value) {
- if (value.isPhi()) {
- return unknown();
- }
- return getOrBuildComputationTree(value.getDefinition());
- }
+ abstract ComputationTreeNode buildComputationTree(Instruction instruction);
- private static UnknownValue unknown() {
+ abstract ComputationTreeNode buildComputationTree(Phi phi);
+
+ static UnknownValue unknown() {
return AbstractValue.unknown();
}
}
diff --git a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/computation/DefaultComputationTreeBuilder.java b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/computation/DefaultComputationTreeBuilder.java
new file mode 100644
index 0000000..36d7ca9
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/computation/DefaultComputationTreeBuilder.java
@@ -0,0 +1,78 @@
+// 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 static com.android.tools.r8.ir.code.Opcodes.AND;
+import static com.android.tools.r8.ir.code.Opcodes.ARGUMENT;
+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.AppView;
+import com.android.tools.r8.graph.ProgramMethod;
+import com.android.tools.r8.ir.code.And;
+import com.android.tools.r8.ir.code.Argument;
+import com.android.tools.r8.ir.code.ConstNumber;
+import com.android.tools.r8.ir.code.IRCode;
+import com.android.tools.r8.ir.code.If;
+import com.android.tools.r8.ir.code.Instruction;
+import com.android.tools.r8.ir.code.Phi;
+import com.android.tools.r8.optimize.argumentpropagation.codescanner.MethodParameterFactory;
+import com.android.tools.r8.shaking.AppInfoWithLiveness;
+
+public class DefaultComputationTreeBuilder extends ComputationTreeBuilder {
+
+ public DefaultComputationTreeBuilder(
+ AppView<AppInfoWithLiveness> appView,
+ IRCode code,
+ ProgramMethod method,
+ MethodParameterFactory methodParameterFactory) {
+ super(appView, code, method, methodParameterFactory);
+ }
+
+ @Override
+ ComputationTreeNode buildComputationTree(Instruction instruction) {
+ switch (instruction.opcode()) {
+ case AND:
+ {
+ And and = instruction.asAnd();
+ ComputationTreeNode left = getOrBuildComputationTree(and.leftValue());
+ ComputationTreeNode right = getOrBuildComputationTree(and.rightValue());
+ return ComputationTreeLogicalBinopAndNode.create(left, right);
+ }
+ case ARGUMENT:
+ {
+ Argument argument = instruction.asArgument();
+ if (argument.getOutType().isInt()) {
+ return methodParameterFactory.create(method, argument.getIndex());
+ }
+ break;
+ }
+ case CONST_NUMBER:
+ {
+ ConstNumber constNumber = instruction.asConstNumber();
+ if (constNumber.getOutType().isInt()) {
+ return constNumber.getAbstractValue(factory());
+ }
+ break;
+ }
+ case IF:
+ {
+ If theIf = instruction.asIf();
+ if (theIf.isZeroTest()) {
+ ComputationTreeNode operand = getOrBuildComputationTree(theIf.lhs());
+ return ComputationTreeUnopCompareNode.create(operand, theIf.getType());
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ return unknown();
+ }
+
+ @Override
+ ComputationTreeNode buildComputationTree(Phi phi) {
+ return unknown();
+ }
+}