Widen dynamic argument types after rebuilding allocation site collection
Change-Id: I7904f13bc1cc6f23501b406712388a867cd79e9e
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 bd70946..db9543f 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
@@ -14,6 +14,7 @@
import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.ir.analysis.type.DynamicType;
import com.android.tools.r8.ir.analysis.type.Nullability;
+import com.android.tools.r8.ir.analysis.value.AbstractValue;
import com.android.tools.r8.ir.conversion.IRConverter;
import com.android.tools.r8.ir.optimize.info.ConcreteCallSiteOptimizationInfo;
import com.android.tools.r8.ir.optimize.info.MethodOptimizationInfo;
@@ -27,6 +28,7 @@
import com.android.tools.r8.optimize.argumentpropagation.codescanner.MethodState;
import com.android.tools.r8.optimize.argumentpropagation.codescanner.MethodStateCollectionByReference;
import com.android.tools.r8.optimize.argumentpropagation.codescanner.ParameterState;
+import com.android.tools.r8.optimize.argumentpropagation.codescanner.StateCloner;
import com.android.tools.r8.optimize.argumentpropagation.propagation.InParameterFlowPropagator;
import com.android.tools.r8.optimize.argumentpropagation.propagation.InterfaceMethodArgumentPropagator;
import com.android.tools.r8.optimize.argumentpropagation.propagation.VirtualDispatchMethodArgumentPropagator;
@@ -43,7 +45,6 @@
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.function.BiConsumer;
-import java.util.stream.IntStream;
/**
* Propagates the argument flow information collected by the {@link ArgumentPropagatorCodeScanner}.
@@ -185,6 +186,14 @@
ConcreteMonomorphicMethodState monomorphicMethodState = concreteMethodState.asMonomorphic();
+ // Widen the dynamic type information so that we don't store any trivial dynamic types.
+ // Note that all dynamic types are already being widened when the method states are created, but
+ // this does not guarantee that they are non-trivial at this point, since we may refine the
+ // object allocation info collection during the primary optimization pass.
+ if (!widenDynamicTypes(method, monomorphicMethodState)) {
+ return;
+ }
+
// Verify that there is no parameter with bottom info.
assert monomorphicMethodState.getParameterStates().stream().noneMatch(ParameterState::isBottom);
@@ -194,28 +203,6 @@
.map(ParameterState::asConcrete)
.noneMatch(ConcreteParameterState::hasInParameters);
- // Verify that the dynamic type information is correct.
- assert IntStream.range(0, monomorphicMethodState.getParameterStates().size())
- .filter(
- index -> {
- ParameterState parameterState = monomorphicMethodState.getParameterState(index);
- return parameterState.isConcrete() && parameterState.asConcrete().isClassParameter();
- })
- .allMatch(
- index -> {
- DynamicType dynamicType =
- monomorphicMethodState
- .getParameterState(index)
- .asConcrete()
- .asClassParameter()
- .getDynamicType();
- DexType staticType = method.getArgumentType(index);
- assert dynamicType.isUnknown()
- || !WideningUtils.widenDynamicNonReceiverType(appView, dynamicType, staticType)
- .isUnknown();
- return true;
- });
-
getSimpleFeedback()
.setArgumentInfos(
method,
@@ -316,4 +303,34 @@
appView.abstractValueFactory().createZeroValue());
}
}
+
+ private boolean widenDynamicTypes(
+ ProgramMethod method, ConcreteMonomorphicMethodState methodState) {
+ for (int argumentIndex = 0;
+ argumentIndex < methodState.getParameterStates().size();
+ argumentIndex++) {
+ ConcreteParameterState parameterState =
+ methodState.getParameterState(argumentIndex).asConcrete();
+ if (parameterState == null || !parameterState.isClassParameter()) {
+ continue;
+ }
+ DynamicType dynamicType = parameterState.asClassParameter().getDynamicType();
+ if (dynamicType.isUnknown()) {
+ continue;
+ }
+ DexType staticType = method.getArgumentType(argumentIndex);
+ if (!WideningUtils.widenDynamicNonReceiverType(appView, dynamicType, staticType)
+ .isUnknown()) {
+ continue;
+ }
+ methodState.setParameterState(
+ argumentIndex,
+ parameterState.mutableJoin(
+ appView,
+ new ConcreteClassTypeParameterState(AbstractValue.bottom(), DynamicType.unknown()),
+ staticType,
+ StateCloner.getIdentity()));
+ }
+ return !methodState.isEffectivelyUnknown();
+ }
}
diff --git a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/ConcreteMonomorphicMethodState.java b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/ConcreteMonomorphicMethodState.java
index c98c383..d32df00 100644
--- a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/ConcreteMonomorphicMethodState.java
+++ b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/ConcreteMonomorphicMethodState.java
@@ -21,9 +21,8 @@
public ConcreteMonomorphicMethodState(List<ParameterState> parameterStates) {
assert Streams.stream(Iterables.skip(parameterStates, 1))
.noneMatch(x -> x.isConcrete() && x.asConcrete().isReceiverParameter());
- assert Iterables.any(parameterStates, parameterState -> !parameterState.isUnknown())
- : "Must use UnknownMethodState instead";
this.parameterStates = parameterStates;
+ assert !isEffectivelyUnknown() : "Must use UnknownMethodState instead";
}
public ParameterState getParameterState(int index) {
@@ -34,6 +33,10 @@
return parameterStates;
}
+ public boolean isEffectivelyUnknown() {
+ return Iterables.all(parameterStates, ParameterState::isUnknown);
+ }
+
@Override
public ConcreteMonomorphicMethodState mutableCopy() {
List<ParameterState> copiedParametersStates = new ArrayList<>(size());
@@ -75,10 +78,7 @@
|| !parameterStates.get(argumentIndex).asConcrete().isReceiverParameter();
}
- if (Iterables.all(parameterStates, ParameterState::isUnknown)) {
- return unknown();
- }
- return this;
+ return isEffectivelyUnknown() ? unknown() : this;
}
@Override