Defer clearing of in-flow to after flow graph construction
Change-Id: Ie34188a02588f9a425249fc2a36f1ff1c42fcd1f
diff --git a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/CastAbstractFunction.java b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/CastAbstractFunction.java
index 2758d38..ee147a5 100644
--- a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/CastAbstractFunction.java
+++ b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/CastAbstractFunction.java
@@ -63,4 +63,9 @@
public int hashCode() {
return Objects.hash(inFlow, type);
}
+
+ @Override
+ public String toString() {
+ return "Cast(" + inFlow + ", " + type.getTypeName() + ")";
+ }
}
diff --git a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/FieldValue.java b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/FieldValue.java
index f7bd0ec..af8ec1a 100644
--- a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/FieldValue.java
+++ b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/FieldValue.java
@@ -51,4 +51,9 @@
public int hashCode() {
return field.hashCode();
}
+
+ @Override
+ public String toString() {
+ return field.toSourceString();
+ }
}
diff --git a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/InstanceFieldReadAbstractFunction.java b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/InstanceFieldReadAbstractFunction.java
index bd97c0b..1993257 100644
--- a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/InstanceFieldReadAbstractFunction.java
+++ b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/InstanceFieldReadAbstractFunction.java
@@ -71,4 +71,9 @@
public InstanceFieldReadAbstractFunction asInstanceFieldReadAbstractFunction() {
return this;
}
+
+ @Override
+ public String toString() {
+ return "Read(" + receiver + ", " + field.toSourceString() + ")";
+ }
}
diff --git a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/propagation/FlowGraphBuilder.java b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/propagation/FlowGraphBuilder.java
index 061c898..45ecb34 100644
--- a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/propagation/FlowGraphBuilder.java
+++ b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/propagation/FlowGraphBuilder.java
@@ -29,8 +29,8 @@
import com.android.tools.r8.shaking.AppInfoWithLiveness;
import com.android.tools.r8.utils.TraversalContinuation;
import it.unimi.dsi.fastutil.ints.Int2ReferenceMap;
+import it.unimi.dsi.fastutil.ints.Int2ReferenceMaps;
import it.unimi.dsi.fastutil.ints.Int2ReferenceOpenHashMap;
-import java.util.Collection;
import java.util.IdentityHashMap;
import java.util.List;
import java.util.Map;
@@ -57,10 +57,13 @@
this.methodStates = methodStates;
}
- public FlowGraphBuilder addClasses(Collection<DexProgramClass> classes) {
- for (DexProgramClass clazz : classes) {
- add(clazz);
- }
+ public FlowGraphBuilder addClasses() {
+ appView.appInfo().classes().forEach(this::add);
+ return this;
+ }
+
+ public FlowGraphBuilder clearInFlow() {
+ appView.appInfo().classes().forEach(this::clearInFlow);
return this;
}
@@ -97,15 +100,6 @@
break;
}
}
-
- ValueState concreteFieldStateOrBottom = concreteFieldState.clearInFlow();
- if (concreteFieldStateOrBottom.isBottom()) {
- fieldStates.remove(field);
- if (!node.getState().isUnknown()) {
- assert node.getState() == concreteFieldState;
- node.setState(concreteFieldStateOrBottom);
- }
- }
}
private void addMethodParameters(ProgramMethod method) {
@@ -152,11 +146,6 @@
break;
}
}
-
- if (!node.getState().isUnknown()) {
- assert node.getState() == concreteParameterState;
- node.setState(concreteParameterState.clearInFlow());
- }
}
// Returns BREAK if the current node has been set to unknown.
@@ -252,11 +241,60 @@
return TraversalContinuation.doContinue();
}
+ private void clearInFlow(DexProgramClass clazz) {
+ clazz.forEachProgramField(this::clearInFlow);
+ clazz.forEachProgramMethod(this::clearInFlow);
+ }
+
+ private void clearInFlow(ProgramField field) {
+ ConcreteValueState concreteFieldState = fieldStates.get(field).asConcrete();
+ if (concreteFieldState == null) {
+ return;
+ }
+ ValueState concreteFieldStateOrBottom = concreteFieldState.clearInFlow();
+ if (concreteFieldStateOrBottom.isBottom()) {
+ fieldStates.remove(field);
+ FlowGraphFieldNode node = getFieldNode(field);
+ if (node != null && !node.getState().isUnknown()) {
+ assert node.getState() == concreteFieldState;
+ node.setState(concreteFieldStateOrBottom);
+ }
+ }
+ }
+
+ private void clearInFlow(ProgramMethod method) {
+ ConcreteMonomorphicMethodState methodState = methodStates.get(method).asMonomorphic();
+ if (methodState != null) {
+ for (int i = 0; i < methodState.getParameterStates().size(); i++) {
+ ValueState parameterState = methodState.getParameterState(i);
+ ConcreteValueState concreteParameterState = parameterState.asConcrete();
+ if (concreteParameterState != null) {
+ ValueState concreteParameterStateOrBottom = concreteParameterState.clearInFlow();
+ FlowGraphParameterNode node = getParameterNode(method, i);
+ if (node != null && !node.getState().isUnknown()) {
+ assert node.getState() == concreteParameterState;
+ node.setState(concreteParameterStateOrBottom);
+ }
+ }
+ }
+ }
+ }
+
+ private FlowGraphFieldNode getFieldNode(ProgramField field) {
+ return fieldNodes.get(field.getReference());
+ }
+
private FlowGraphFieldNode getOrCreateFieldNode(ProgramField field, ValueState fieldState) {
return fieldNodes.computeIfAbsent(
field.getReference(), ignoreKey(() -> new FlowGraphFieldNode(field, fieldState)));
}
+ private FlowGraphParameterNode getParameterNode(ProgramMethod method, int parameterIndex) {
+ return parameterNodes
+ .getOrDefault(method.getReference(), Int2ReferenceMaps.emptyMap())
+ .get(parameterIndex);
+ }
+
private FlowGraphParameterNode getOrCreateParameterNode(
ProgramMethod method, int parameterIndex, MethodState methodState) {
Int2ReferenceMap<FlowGraphParameterNode> parameterNodesForMethod =
diff --git a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/propagation/FlowGraphFieldNode.java b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/propagation/FlowGraphFieldNode.java
index 4fed1f1..d65a397 100644
--- a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/propagation/FlowGraphFieldNode.java
+++ b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/propagation/FlowGraphFieldNode.java
@@ -45,4 +45,9 @@
FlowGraphFieldNode asFieldNode() {
return this;
}
+
+ @Override
+ public String toString() {
+ return field.toSourceString();
+ }
}
diff --git a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/propagation/FlowGraphParameterNode.java b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/propagation/FlowGraphParameterNode.java
index 12d516b..242faa1 100644
--- a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/propagation/FlowGraphParameterNode.java
+++ b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/propagation/FlowGraphParameterNode.java
@@ -5,6 +5,7 @@
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.ProgramMethod;
+import com.android.tools.r8.optimize.argumentpropagation.codescanner.MethodParameter;
import com.android.tools.r8.optimize.argumentpropagation.codescanner.MethodState;
import com.android.tools.r8.optimize.argumentpropagation.codescanner.ValueState;
@@ -67,4 +68,9 @@
boolean isReceiverNode() {
return !method.getAccessFlags().isStatic() && parameterIndex == 0;
}
+
+ @Override
+ public String toString() {
+ return new MethodParameter(method, parameterIndex).toString();
+ }
}
diff --git a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/propagation/InFlowPropagator.java b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/propagation/InFlowPropagator.java
index 0794838..1a26af0 100644
--- a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/propagation/InFlowPropagator.java
+++ b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/propagation/InFlowPropagator.java
@@ -92,7 +92,8 @@
// must be included in the argument information for p'.
FlowGraph flowGraph =
FlowGraph.builder(appView, converter, fieldStates, methodStates)
- .addClasses(appView.appInfo().classes())
+ .addClasses()
+ .clearInFlow()
.build();
List<Set<FlowGraphNode>> stronglyConnectedComponents =
flowGraph.computeStronglyConnectedComponents();