Remove unused argument removal phase
Change-Id: I766a217828642057dd0e5357a130e9f5a56e78fb
diff --git a/src/main/java/com/android/tools/r8/R8.java b/src/main/java/com/android/tools/r8/R8.java
index 02ef891..65a9a2f 100644
--- a/src/main/java/com/android/tools/r8/R8.java
+++ b/src/main/java/com/android/tools/r8/R8.java
@@ -57,8 +57,6 @@
import com.android.tools.r8.ir.optimize.SwitchMapCollector;
import com.android.tools.r8.ir.optimize.UninstantiatedTypeOptimization;
import com.android.tools.r8.ir.optimize.UninstantiatedTypeOptimization.UninstantiatedTypeOptimizationGraphLens;
-import com.android.tools.r8.ir.optimize.UnusedArgumentsCollector;
-import com.android.tools.r8.ir.optimize.UnusedArgumentsCollector.UnusedArgumentsGraphLens;
import com.android.tools.r8.ir.optimize.enums.EnumUnboxingCfMethods;
import com.android.tools.r8.ir.optimize.info.OptimizationFeedbackSimple;
import com.android.tools.r8.ir.optimize.templates.CfUtilityMethodsForCodeOptimizations;
@@ -512,32 +510,15 @@
}
assert appView.verticallyMergedClasses() != null;
- if (options.enableArgumentRemoval) {
- SubtypingInfo subtypingInfo = appViewWithLiveness.appInfo().computeSubtypingInfo();
- {
- timing.begin("UnusedArgumentRemoval");
- UnusedArgumentsGraphLens lens =
- new UnusedArgumentsCollector(
- appViewWithLiveness,
- new MethodPoolCollection(appViewWithLiveness, subtypingInfo))
- .run(executorService, timing);
- assert lens == null || getDirectApp(appView).verifyNothingToRewrite(appView, lens);
- appView.rewriteWithLens(lens);
- timing.end();
- }
- if (options.enableUninstantiatedTypeOptimization) {
- timing.begin("UninstantiatedTypeOptimization");
- UninstantiatedTypeOptimizationGraphLens lens =
- new UninstantiatedTypeOptimization(appViewWithLiveness)
- .strenghtenOptimizationInfo()
- .run(
- new MethodPoolCollection(appViewWithLiveness, subtypingInfo),
- executorService,
- timing);
- assert lens == null || getDirectApp(appView).verifyNothingToRewrite(appView, lens);
- appView.rewriteWithLens(lens);
- timing.end();
- }
+ if (options.enableUninstantiatedTypeOptimization) {
+ timing.begin("UninstantiatedTypeOptimization");
+ UninstantiatedTypeOptimizationGraphLens lens =
+ new UninstantiatedTypeOptimization(appViewWithLiveness)
+ .strenghtenOptimizationInfo()
+ .run(new MethodPoolCollection(appViewWithLiveness), executorService, timing);
+ assert lens == null || getDirectApp(appView).verifyNothingToRewrite(appView, lens);
+ appView.rewriteWithLens(lens);
+ timing.end();
}
HorizontalClassMerger.createForInitialClassMerging(appViewWithLiveness)
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/MethodPoolCollection.java b/src/main/java/com/android/tools/r8/ir/optimize/MethodPoolCollection.java
index 652c185..2b439a6 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/MethodPoolCollection.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/MethodPoolCollection.java
@@ -34,6 +34,10 @@
private final Predicate<DexEncodedMethod> methodTester;
+ public MethodPoolCollection(AppView<AppInfoWithLiveness> appView) {
+ this(appView, appView.appInfo().computeSubtypingInfo());
+ }
+
public MethodPoolCollection(AppView<AppInfoWithLiveness> appView, SubtypingInfo subtypingInfo) {
this(appView, subtypingInfo, Predicates.alwaysTrue());
}
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/UnusedArgumentsCollector.java b/src/main/java/com/android/tools/r8/ir/optimize/UnusedArgumentsCollector.java
deleted file mode 100644
index 052e196..0000000
--- a/src/main/java/com/android/tools/r8/ir/optimize/UnusedArgumentsCollector.java
+++ /dev/null
@@ -1,333 +0,0 @@
-// Copyright (c) 2018, 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.optimize;
-
-import com.android.tools.r8.graph.AppView;
-import com.android.tools.r8.graph.ArgumentUse;
-import com.android.tools.r8.graph.DexEncodedMethod;
-import com.android.tools.r8.graph.DexMethod;
-import com.android.tools.r8.graph.DexProgramClass;
-import com.android.tools.r8.graph.DexProto;
-import com.android.tools.r8.graph.DexString;
-import com.android.tools.r8.graph.DexType;
-import com.android.tools.r8.graph.NestedGraphLens;
-import com.android.tools.r8.graph.RewrittenPrototypeDescription;
-import com.android.tools.r8.graph.RewrittenPrototypeDescription.ArgumentInfoCollection;
-import com.android.tools.r8.graph.RewrittenPrototypeDescription.RemovedArgumentInfo;
-import com.android.tools.r8.ir.optimize.MemberPoolCollection.MemberPool;
-import com.android.tools.r8.shaking.AppInfoWithLiveness;
-import com.android.tools.r8.utils.MethodSignatureEquivalence;
-import com.android.tools.r8.utils.SymbolGenerationUtils;
-import com.android.tools.r8.utils.SymbolGenerationUtils.MixedCasing;
-import com.android.tools.r8.utils.ThreadUtils;
-import com.android.tools.r8.utils.Timing;
-import com.android.tools.r8.utils.collections.BidirectionalOneToOneHashMap;
-import com.android.tools.r8.utils.collections.BidirectionalOneToOneMap;
-import com.android.tools.r8.utils.collections.MutableBidirectionalOneToOneMap;
-import com.google.common.base.Equivalence.Wrapper;
-import com.google.common.collect.Streams;
-import java.util.BitSet;
-import java.util.HashSet;
-import java.util.IdentityHashMap;
-import java.util.Map;
-import java.util.Set;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.ExecutorService;
-import java.util.stream.Collectors;
-
-public class UnusedArgumentsCollector {
-
- private static final MethodSignatureEquivalence equivalence = MethodSignatureEquivalence.get();
-
- private final AppView<AppInfoWithLiveness> appView;
- private final MethodPoolCollection methodPoolCollection;
-
- private final MutableBidirectionalOneToOneMap<DexMethod, DexMethod> methodMapping =
- new BidirectionalOneToOneHashMap<>();
- private final Map<DexMethod, ArgumentInfoCollection> removedArguments = new IdentityHashMap<>();
-
- public static class UnusedArgumentsGraphLens extends NestedGraphLens {
-
- private final Map<DexMethod, ArgumentInfoCollection> removedArguments;
-
- UnusedArgumentsGraphLens(
- AppView<?> appView,
- BidirectionalOneToOneMap<DexMethod, DexMethod> methodMap,
- Map<DexMethod, ArgumentInfoCollection> removedArguments) {
- super(appView, EMPTY_FIELD_MAP, methodMap, EMPTY_TYPE_MAP);
- this.removedArguments = removedArguments;
- }
-
- @Override
- protected RewrittenPrototypeDescription internalDescribePrototypeChanges(
- RewrittenPrototypeDescription prototypeChanges, DexMethod method) {
- return prototypeChanges.withRemovedArguments(
- removedArguments.getOrDefault(method, ArgumentInfoCollection.empty()));
- }
- }
-
- public UnusedArgumentsCollector(
- AppView<AppInfoWithLiveness> appView, MethodPoolCollection methodPoolCollection) {
- this.appView = appView;
- this.methodPoolCollection = methodPoolCollection;
- }
-
- public UnusedArgumentsGraphLens run(ExecutorService executorService, Timing timing)
- throws ExecutionException {
- ThreadUtils.awaitFutures(
- Streams.stream(appView.appInfo().classes())
- .map(this::runnableForClass)
- .map(executorService::submit)
- // Materialize list such that all runnables are submitted to the executor service
- // before calling awaitFutures().
- .collect(Collectors.toList()));
-
- // Build method pool collection to enable unused argument removal for virtual methods.
- methodPoolCollection.buildAll(executorService, timing);
-
- // Visit classes in deterministic order to ensure deterministic output.
- appView.appInfo().classesWithDeterministicOrder().forEach(this::processVirtualMethods);
-
- if (!methodMapping.isEmpty()) {
- return new UnusedArgumentsGraphLens(appView, methodMapping, removedArguments);
- }
-
- return null;
- }
-
- private class UsedSignatures {
-
- private final MethodSignatureEquivalence equivalence = MethodSignatureEquivalence.get();
- private final Set<Wrapper<DexMethod>> usedSignatures = new HashSet<>();
-
- private boolean isMethodSignatureAvailable(DexMethod method) {
- return !usedSignatures.contains(equivalence.wrap(method));
- }
-
- private void markSignatureAsUsed(DexMethod method) {
- usedSignatures.add(equivalence.wrap(method));
- }
-
- DexMethod getNewSignature(DexEncodedMethod method, DexProto newProto) {
- DexMethod newSignature;
- int count = 0;
- DexString newName = null;
- do {
- if (newName == null) {
- newName = method.getReference().name;
- } else if (!appView.dexItemFactory().isConstructor(method.getReference())) {
- newName =
- appView
- .dexItemFactory()
- .createString(
- SymbolGenerationUtils.numberToIdentifier(
- count,
- MixedCasing.USE_MIXED_CASE,
- method.getReference().name.toSourceString().toCharArray()));
- } else {
- // Constructors must be named `<init>`.
- return null;
- }
- newSignature =
- appView.dexItemFactory().createMethod(method.getHolderType(), newProto, newName);
- count++;
- } while (!isMethodSignatureAvailable(newSignature));
- return newSignature;
- }
-
- DexEncodedMethod removeArguments(
- DexEncodedMethod method, DexMethod newSignature, ArgumentInfoCollection unused) {
- boolean removed = usedSignatures.remove(equivalence.wrap(method.getReference()));
- assert removed;
-
- markSignatureAsUsed(newSignature);
-
- return method.toTypeSubstitutedMethod(
- newSignature, unused.createParameterAnnotationsRemover(method));
- }
- }
-
- private class GloballyUsedSignatures {
-
- private final MemberPool<DexMethod> methodPool;
-
- GloballyUsedSignatures(MemberPool<DexMethod> methodPool) {
- this.methodPool = methodPool;
- }
-
- DexMethod getNewSignature(DexEncodedMethod method, DexProto newProto) {
- DexMethod newSignature;
- int count = 0;
- DexString newName = null;
- do {
- if (newName == null) {
- newName = method.getReference().name;
- } else if (!appView.dexItemFactory().isConstructor(method.getReference())) {
- newName =
- appView
- .dexItemFactory()
- .createString(method.getReference().name.toSourceString() + count);
- } else {
- // Constructors must be named `<init>`.
- return null;
- }
- newSignature =
- appView.dexItemFactory().createMethod(method.getHolderType(), newProto, newName);
- count++;
- } while (methodPool.hasSeen(equivalence.wrap(newSignature)));
- return newSignature;
- }
-
- DexEncodedMethod removeArguments(
- DexEncodedMethod method, DexMethod newSignature, ArgumentInfoCollection unused) {
- methodPool.seen(equivalence.wrap(newSignature));
- return method.toTypeSubstitutedMethod(
- newSignature, unused.createParameterAnnotationsRemover(method));
- }
- }
-
- private Runnable runnableForClass(DexProgramClass clazz) {
- return () -> this.processDirectMethods(clazz);
- }
-
- private void processDirectMethods(DexProgramClass clazz) {
- UsedSignatures signatures = new UsedSignatures();
- for (DexEncodedMethod method : clazz.methods()) {
- signatures.markSignatureAsUsed(method.getReference());
- }
-
- clazz
- .getMethodCollection()
- .replaceDirectMethods(
- method -> {
-
- // If this is a method with known resolution issues, then don't remove any unused
- // arguments.
- if (appView.appInfo().isFailedResolutionTarget(method.getReference())) {
- return method;
- }
-
- ArgumentInfoCollection unused = collectUnusedArguments(method);
- if (unused != null && unused.hasRemovedArguments()) {
- DexProto newProto = createProtoWithRemovedArguments(method, unused);
- DexMethod newSignature = signatures.getNewSignature(method, newProto);
- if (newSignature == null) {
- assert appView.dexItemFactory().isConstructor(method.getReference());
- return method;
- }
- DexEncodedMethod newMethod =
- signatures.removeArguments(method, newSignature, unused);
- synchronized (this) {
- methodMapping.put(method.getReference(), newMethod.getReference());
- removedArguments.put(newMethod.getReference(), unused);
- }
- return newMethod;
- }
- return method;
- });
- }
-
- private void processVirtualMethods(DexProgramClass clazz) {
- MemberPool<DexMethod> methodPool = methodPoolCollection.get(clazz);
- GloballyUsedSignatures signatures = new GloballyUsedSignatures(methodPool);
-
- clazz
- .getMethodCollection()
- .replaceVirtualMethods(
- method -> {
- ArgumentInfoCollection unused = collectUnusedArguments(method, methodPool);
- if (unused != null && unused.hasRemovedArguments()) {
- DexProto newProto = createProtoWithRemovedArguments(method, unused);
- DexMethod newSignature = signatures.getNewSignature(method, newProto);
-
- // Double-check that the new method signature is in fact available.
- assert !methodPool.hasSeenStrictlyAbove(equivalence.wrap(newSignature));
- assert !methodPool.hasSeenStrictlyBelow(equivalence.wrap(newSignature));
-
- DexEncodedMethod newMethod =
- signatures.removeArguments(
- method, signatures.getNewSignature(method, newProto), unused);
-
- methodMapping.put(method.getReference(), newMethod.getReference());
- removedArguments.put(newMethod.getReference(), unused);
- return newMethod;
- }
- return method;
- });
- }
-
- private ArgumentInfoCollection collectUnusedArguments(DexEncodedMethod method) {
- return collectUnusedArguments(method, null);
- }
-
- private ArgumentInfoCollection collectUnusedArguments(
- DexEncodedMethod method, MemberPool<DexMethod> methodPool) {
- if (ArgumentRemovalUtils.isPinned(method, appView)
- || appView.appInfo().isKeepUnusedArgumentsMethod(method.getReference())) {
- return null;
- }
- // Only process classfile code objects.
- if (method.getCode() == null || !method.getCode().isCfCode()) {
- return null;
- }
- if (method.isNonPrivateVirtualMethod()) {
- // Abort if the method overrides another method, or if the method is overridden. In both cases
- // an unused argument cannot be removed unless it is unused in all of the related methods in
- // the hierarchy.
- assert methodPool != null;
- Wrapper<DexMethod> wrapper = equivalence.wrap(method.getReference());
- if (methodPool.hasSeenStrictlyAbove(wrapper) || methodPool.hasSeenStrictlyBelow(wrapper)) {
- return null;
- }
- }
- int offset = method.getFirstNonReceiverArgumentIndex();
- int argumentCount = method.getReference().proto.parameters.size() + offset;
- CollectUsedArguments collector = new CollectUsedArguments();
- if (!method.accessFlags.isStatic()) {
- // TODO(65810338): The receiver cannot be removed without transforming the method to being
- // static.
- collector.register(0);
- }
- method.getCode().registerArgumentReferences(method, collector);
- BitSet used = collector.getUsedArguments();
- if (used.cardinality() < argumentCount) {
- ArgumentInfoCollection.Builder argInfosBuilder = ArgumentInfoCollection.builder();
- for (int argumentIndex = 0; argumentIndex < argumentCount; argumentIndex++) {
- if (!used.get(argumentIndex)) {
- RemovedArgumentInfo removedArg =
- RemovedArgumentInfo.builder()
- .setType(method.getReference().proto.parameters.values[argumentIndex - offset])
- .build();
- argInfosBuilder.addArgumentInfo(argumentIndex, removedArg);
- }
- }
- return argInfosBuilder.build();
- }
- return null;
- }
-
- private DexProto createProtoWithRemovedArguments(
- DexEncodedMethod encodedMethod, ArgumentInfoCollection unused) {
- DexType[] parameters = unused.rewriteParameters(encodedMethod);
- return appView
- .dexItemFactory()
- .createProto(encodedMethod.getReference().proto.returnType, parameters);
- }
-
- private static class CollectUsedArguments extends ArgumentUse {
-
- private final BitSet used = new BitSet();
-
- BitSet getUsedArguments() {
- return used;
- }
-
- @Override
- public boolean register(int argument) {
- used.set(argument);
- return true;
- }
- }
-}
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 6f97143..ae2a8aa 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
@@ -18,6 +18,7 @@
import com.android.tools.r8.optimize.argumentpropagation.codescanner.ConcreteClassTypeParameterState;
import com.android.tools.r8.optimize.argumentpropagation.codescanner.ConcreteMethodState;
import com.android.tools.r8.optimize.argumentpropagation.codescanner.ConcreteMonomorphicMethodState;
+import com.android.tools.r8.optimize.argumentpropagation.codescanner.ConcreteMonomorphicMethodStateOrUnknown;
import com.android.tools.r8.optimize.argumentpropagation.codescanner.ConcreteParameterState;
import com.android.tools.r8.optimize.argumentpropagation.codescanner.ConcretePrimitiveTypeParameterState;
import com.android.tools.r8.optimize.argumentpropagation.codescanner.MethodState;
@@ -159,6 +160,11 @@
return;
}
+ // Do not optimize @KeepConstantArgument methods.
+ if (appView.appInfo().isKeepConstantArgumentsMethod(method)) {
+ methodState = MethodState.unknown();
+ }
+
methodState = getMethodStateAfterUnusedParameterRemoval(method, methodState);
if (methodState.isUnknown()) {
@@ -208,12 +214,9 @@
// before reenqueing.
MethodReprocessingCriteria reprocessingCriteria =
reprocessingCriteriaCollection.getReprocessingCriteria(method);
- if (!reprocessingCriteria.shouldReprocess(appView, method, monomorphicMethodState)) {
- return;
- }
-
- // Do not optimize @KeepConstantArgument methods.
- if (appView.appInfo().isKeepConstantArgumentsMethod(method)) {
+ ConcreteMonomorphicMethodStateOrUnknown widenedMethodState =
+ reprocessingCriteria.widenMethodState(appView, method, monomorphicMethodState);
+ if (widenedMethodState.isUnknown()) {
return;
}
@@ -221,7 +224,7 @@
.getDefinition()
.setCallSiteOptimizationInfo(
ConcreteCallSiteOptimizationInfo.fromMethodState(
- appView, method, monomorphicMethodState));
+ appView, method, widenedMethodState.asMonomorphic()));
}
private MethodState getMethodStateAfterUnusedParameterRemoval(
diff --git a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/ArgumentPropagatorProgramOptimizer.java b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/ArgumentPropagatorProgramOptimizer.java
index 90397d7..8d83dd6 100644
--- a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/ArgumentPropagatorProgramOptimizer.java
+++ b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/ArgumentPropagatorProgramOptimizer.java
@@ -268,6 +268,7 @@
private boolean isParameterRemovalAllowed(ProgramMethod method) {
return appView.getKeepInfo(method).isParameterRemovalAllowed(options)
&& !method.getDefinition().isLibraryMethodOverride().isPossiblyTrue()
+ && !appView.appInfo().isBootstrapMethod(method)
&& !appView.appInfo().isMethodTargetedByInvokeDynamic(method);
}
diff --git a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/reprocessingcriteria/MethodReprocessingCriteria.java b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/reprocessingcriteria/MethodReprocessingCriteria.java
index 0afc8ca..658383f 100644
--- a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/reprocessingcriteria/MethodReprocessingCriteria.java
+++ b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/reprocessingcriteria/MethodReprocessingCriteria.java
@@ -8,8 +8,12 @@
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.optimize.argumentpropagation.codescanner.ConcreteMonomorphicMethodState;
+import com.android.tools.r8.optimize.argumentpropagation.codescanner.ConcreteMonomorphicMethodStateOrUnknown;
+import com.android.tools.r8.optimize.argumentpropagation.codescanner.MethodState;
import com.android.tools.r8.optimize.argumentpropagation.codescanner.ParameterState;
+import com.android.tools.r8.optimize.argumentpropagation.codescanner.UnknownParameterState;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
+import com.google.common.collect.Iterables;
import it.unimi.dsi.fastutil.ints.Int2ReferenceMap;
import it.unimi.dsi.fastutil.ints.Int2ReferenceOpenHashMap;
@@ -39,7 +43,7 @@
parameterIndex, ParameterReprocessingCriteria.alwaysReprocess());
}
- public boolean shouldReprocess(
+ public ConcreteMonomorphicMethodStateOrUnknown widenMethodState(
AppView<AppInfoWithLiveness> appView,
ProgramMethod method,
ConcreteMonomorphicMethodState methodState) {
@@ -50,14 +54,24 @@
continue;
}
+ if (parameterState.getAbstractValue(appView).isSingleValue()) {
+ // Don't widen when we have information that can be used for parameter removal.
+ continue;
+ }
+
ParameterReprocessingCriteria parameterReprocessingCriteria =
getParameterReprocessingCriteria(parameterIndex);
DexType parameterType = method.getArgumentType(parameterIndex);
if (parameterReprocessingCriteria.shouldReprocess(
appView, parameterState.asConcrete(), parameterType)) {
- return true;
+ continue;
}
+
+ methodState.setParameterState(parameterIndex, UnknownParameterState.get());
}
- return false;
+
+ return Iterables.all(methodState.getParameterStates(), ParameterState::isUnknown)
+ ? MethodState.unknown()
+ : methodState;
}
}
diff --git a/src/main/java/com/android/tools/r8/shaking/AppInfoWithLiveness.java b/src/main/java/com/android/tools/r8/shaking/AppInfoWithLiveness.java
index 4887a27..7b5eee3 100644
--- a/src/main/java/com/android/tools/r8/shaking/AppInfoWithLiveness.java
+++ b/src/main/java/com/android/tools/r8/shaking/AppInfoWithLiveness.java
@@ -591,6 +591,10 @@
return bootstrapMethods.contains(method);
}
+ public boolean isBootstrapMethod(ProgramMethod method) {
+ return isBootstrapMethod(method.getReference());
+ }
+
public boolean isMethodTargetedByInvokeDynamic(DexMethod method) {
return methodsTargetedByInvokeDynamic.contains(method);
}
diff --git a/src/main/java/com/android/tools/r8/utils/InternalOptions.java b/src/main/java/com/android/tools/r8/utils/InternalOptions.java
index 3718fcf..308862a 100644
--- a/src/main/java/com/android/tools/r8/utils/InternalOptions.java
+++ b/src/main/java/com/android/tools/r8/utils/InternalOptions.java
@@ -214,7 +214,6 @@
}
public void disableGlobalOptimizations() {
- enableArgumentRemoval = false;
enableInlining = false;
enableClassInlining = false;
enableClassStaticizer = false;
@@ -255,7 +254,6 @@
public boolean enableFieldBitAccessAnalysis =
System.getProperty("com.android.tools.r8.fieldBitAccessAnalysis") != null;
public boolean enableVerticalClassMerging = true;
- public boolean enableArgumentRemoval = true;
public boolean enableUnusedInterfaceRemoval = true;
public boolean enableDevirtualization = true;
public boolean enableInlining =
@@ -1258,6 +1256,15 @@
return enableDynamicTypePropagation;
}
+ public CallSiteOptimizationOptions setEnabled(boolean enabled) {
+ if (enabled) {
+ assert isEnabled();
+ } else {
+ disableOptimization();
+ }
+ return this;
+ }
+
public CallSiteOptimizationOptions setEnableLegacyConstantPropagation() {
assert !enableLegacyConstantPropagation;
enableLegacyConstantPropagation = true;
diff --git a/src/test/java/com/android/tools/r8/accessrelaxation/NonConstructorRelaxationTest.java b/src/test/java/com/android/tools/r8/accessrelaxation/NonConstructorRelaxationTest.java
index 19c8015..29e44c0 100644
--- a/src/test/java/com/android/tools/r8/accessrelaxation/NonConstructorRelaxationTest.java
+++ b/src/test/java/com/android/tools/r8/accessrelaxation/NonConstructorRelaxationTest.java
@@ -113,7 +113,7 @@
MethodSignature barMethodSignatureAfterArgumentRemoval =
enableUnusedArgumentRemoval
- ? new MethodSignature("bara", STRING, ImmutableList.of())
+ ? new MethodSignature("bar$1", STRING, ImmutableList.of())
: new MethodSignature("bar", STRING, ImmutableList.of("int"));
assertPublic(inspector, A.class, new MethodSignature("baz", STRING, ImmutableList.of()));
assertPublic(inspector, A.class, new MethodSignature("bar", STRING, ImmutableList.of()));
diff --git a/src/test/java/com/android/tools/r8/graph/genericsignature/GenericSignatureKeepAttributesTest.java b/src/test/java/com/android/tools/r8/graph/genericsignature/GenericSignatureKeepAttributesTest.java
index fe4a189..48877b9 100644
--- a/src/test/java/com/android/tools/r8/graph/genericsignature/GenericSignatureKeepAttributesTest.java
+++ b/src/test/java/com/android/tools/r8/graph/genericsignature/GenericSignatureKeepAttributesTest.java
@@ -8,6 +8,7 @@
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.Assert.assertEquals;
+import com.android.tools.r8.NeverInline;
import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.graph.genericsignature.GenericSignatureKeepAttributesTest.Outer.Middle;
@@ -72,6 +73,7 @@
.addKeepAttributeInnerClassesAndEnclosingMethod()
.addKeepMainRule(Main.class)
.addKeepClassAndMembersRules(Outer.Middle.Inner.class, Supplier.class, Predicate.class)
+ .enableInliningAnnotations()
.run(parameters.getRuntime(), Main.class)
.assertSuccessWithOutputLines(parameters.isCfRuntime() ? EXPECTED_JVM : EXPECTED_DEX)
.inspect(this::inspectSignatures);
@@ -146,6 +148,7 @@
return new Outer<O>.Middle<>();
}
+ @NeverInline
public static Outer<?>.Middle<?>.Inner<Object> create() {
return new Outer<>().createMiddle().createInner();
}
diff --git a/src/test/java/com/android/tools/r8/graph/genericsignature/GenericSignatureReflectiveInnerTest.java b/src/test/java/com/android/tools/r8/graph/genericsignature/GenericSignatureReflectiveInnerTest.java
index e34a36c..3c32c7b 100644
--- a/src/test/java/com/android/tools/r8/graph/genericsignature/GenericSignatureReflectiveInnerTest.java
+++ b/src/test/java/com/android/tools/r8/graph/genericsignature/GenericSignatureReflectiveInnerTest.java
@@ -7,6 +7,7 @@
import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
import static org.hamcrest.MatcherAssert.assertThat;
+import com.android.tools.r8.NeverInline;
import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
@@ -48,6 +49,7 @@
.addKeepAttributeInnerClassesAndEnclosingMethod()
.addKeepAttributeSignature()
.addKeepClassRules(Foo.Bar.class)
+ .enableInliningAnnotations()
.setMinApi(parameters.getApiLevel())
.run(parameters.getRuntime(), Main.class)
.assertSuccessWithOutputLines(EXPECTED)
@@ -71,6 +73,7 @@
}
}
+ @NeverInline
public Bar<String> foo() {
return new Bar<>();
}
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/inliner/InliningAfterClassInitializationTest.java b/src/test/java/com/android/tools/r8/ir/optimize/inliner/InliningAfterClassInitializationTest.java
index f9081c2..59e5118 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/inliner/InliningAfterClassInitializationTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/inliner/InliningAfterClassInitializationTest.java
@@ -10,6 +10,7 @@
import static org.hamcrest.core.IsNot.not;
import com.android.tools.r8.KeepConstantArguments;
+import com.android.tools.r8.KeepUnusedArguments;
import com.android.tools.r8.NeverInline;
import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestParameters;
@@ -224,6 +225,7 @@
.addOptionsModification(
options -> options.enableInliningOfInvokesWithClassInitializationSideEffects = false)
.enableConstantArgumentAnnotations()
+ .enableUnusedArgumentAnnotations()
.enableInliningAnnotations()
.setMinApi(parameters.getApiLevel())
.run(parameters.getRuntime(), mainClass)
@@ -322,6 +324,7 @@
}
@KeepConstantArguments
+ @KeepUnusedArguments
@NeverInline
private static void test(A obj) {
try {
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/staticizer/ClassStaticizerTest.java b/src/test/java/com/android/tools/r8/ir/optimize/staticizer/ClassStaticizerTest.java
index a1b6f08..c3f71e3 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/staticizer/ClassStaticizerTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/staticizer/ClassStaticizerTest.java
@@ -164,16 +164,19 @@
assertTrue(instanceMethods(simpleWithPhi).isEmpty());
assertThat(simpleWithPhi.clinit(), not(isPresent()));
+ // TODO(b/200498092): SimpleWithParams should be staticized, but due to reprocessing the
+ // instantiation of SimpleWithParams, it is marked as ineligible for staticizing.
assertEquals(
Lists.newArrayList(
- "STATIC: String SimpleWithParams.bar(String)",
- "STATIC: String SimpleWithParams.foo()",
- "STATIC: String TrivialTestClass.next()"),
+ "STATIC: String TrivialTestClass.next()",
+ "SimpleWithParams SimpleWithParams.INSTANCE",
+ "VIRTUAL: String SimpleWithParams.bar(String)",
+ "VIRTUAL: String SimpleWithParams.foo()"),
references(clazz, "testSimpleWithParams", "void"));
ClassSubject simpleWithParams = inspector.clazz(SimpleWithParams.class);
- assertTrue(instanceMethods(simpleWithParams).isEmpty());
- assertThat(simpleWithParams.clinit(), not(isPresent()));
+ assertFalse(instanceMethods(simpleWithParams).isEmpty());
+ assertThat(simpleWithParams.clinit(), isPresent());
assertEquals(
Lists.newArrayList(
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/uninstantiatedtypes/InvokeMethodWithReceiverOptimizationTest.java b/src/test/java/com/android/tools/r8/ir/optimize/uninstantiatedtypes/InvokeMethodWithReceiverOptimizationTest.java
index e7e09dd..06aae25 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/uninstantiatedtypes/InvokeMethodWithReceiverOptimizationTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/uninstantiatedtypes/InvokeMethodWithReceiverOptimizationTest.java
@@ -12,7 +12,7 @@
import com.android.tools.r8.NeverInline;
import com.android.tools.r8.TestBase;
-import com.android.tools.r8.ToolHelper;
+import com.android.tools.r8.TestParameters;
import com.android.tools.r8.utils.BooleanUtils;
import com.android.tools.r8.utils.StringUtils;
import com.android.tools.r8.utils.codeinspector.ClassSubject;
@@ -33,17 +33,19 @@
@RunWith(Parameterized.class)
public class InvokeMethodWithReceiverOptimizationTest extends TestBase {
- private final Backend backend;
- private final boolean enableArgumentRemoval;
+ private final TestParameters parameters;
+ private final boolean enableArgumentPropagation;
- @Parameters(name = "Backend: {0}, enable argument removal: {1}")
+ @Parameters(name = "{0}, argument propagation: {1}")
public static List<Object[]> data() {
- return buildParameters(ToolHelper.getBackends(), BooleanUtils.values());
+ return buildParameters(
+ getTestParameters().withAllRuntimesAndApiLevels().build(), BooleanUtils.values());
}
- public InvokeMethodWithReceiverOptimizationTest(Backend backend, boolean enableArgumentRemoval) {
- this.backend = backend;
- this.enableArgumentRemoval = enableArgumentRemoval;
+ public InvokeMethodWithReceiverOptimizationTest(
+ TestParameters parameters, boolean enableArgumentPropagation) {
+ this.parameters = parameters;
+ this.enableArgumentPropagation = enableArgumentPropagation;
}
@Test
@@ -57,15 +59,20 @@
testForJvm().addTestClasspath().run(TestClass.class).assertSuccessWithOutput(expected);
CodeInspector inspector =
- testForR8(backend)
+ testForR8(parameters.getBackend())
.addInnerClasses(InvokeMethodWithReceiverOptimizationTest.class)
.addKeepMainRule(TestClass.class)
.enableInliningAnnotations()
- .addOptionsModification(o -> o.enableArgumentRemoval = enableArgumentRemoval)
+ .addOptionsModification(
+ options -> {
+ options.enableUninstantiatedTypeOptimization = enableArgumentPropagation;
+ options.callSiteOptimizationOptions().setEnabled(enableArgumentPropagation);
+ })
// TODO(b/120764902): The calls to getOriginalName() below does not work in presence of
- // argument removal.
- .addKeepRules("-dontobfuscate")
- .run(TestClass.class)
+ // argument removal.
+ .noMinification()
+ .setMinApi(parameters.getApiLevel())
+ .run(parameters.getRuntime(), TestClass.class)
.assertSuccessWithOutput(expected)
.inspector();
@@ -73,7 +80,7 @@
assertThat(testClassSubject, isPresent());
ClassSubject otherClassSubject = inspector.clazz(A.class);
- assertNotEquals(enableArgumentRemoval, otherClassSubject.isPresent());
+ assertNotEquals(enableArgumentPropagation, otherClassSubject.isPresent());
// Check that A.method() has been removed.
assertThat(otherClassSubject.uniqueMethodWithName("method"), not(isPresent()));
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/uninstantiatedtypes/PrivateInstanceMethodCollisionTest.java b/src/test/java/com/android/tools/r8/ir/optimize/uninstantiatedtypes/PrivateInstanceMethodCollisionTest.java
index 8dc29fb..58dc4e5 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/uninstantiatedtypes/PrivateInstanceMethodCollisionTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/uninstantiatedtypes/PrivateInstanceMethodCollisionTest.java
@@ -35,7 +35,7 @@
@Parameters(name = "{0}, minification: {1}, allowaccessmodification: {2}")
public static List<Object[]> data() {
return buildParameters(
- getTestParameters().withAllRuntimes().build(),
+ getTestParameters().withAllRuntimesAndApiLevels().build(),
BooleanUtils.values(),
BooleanUtils.values());
}
@@ -66,7 +66,7 @@
.enableNoHorizontalClassMergingAnnotations()
.minification(minification)
.allowAccessModification(allowAccessModification)
- .setMinApi(parameters.getRuntime())
+ .setMinApi(parameters.getApiLevel())
.compile()
.inspect(this::verifyUninstantiatedArgumentsRemovedAndNoCollisions)
.run(parameters.getRuntime(), TestClass.class)
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/uninstantiatedtypes/UninstantiatedAnnotatedArgumentsTest.java b/src/test/java/com/android/tools/r8/ir/optimize/uninstantiatedtypes/UninstantiatedAnnotatedArgumentsTest.java
index 663bcf6..0e4a3a2 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/uninstantiatedtypes/UninstantiatedAnnotatedArgumentsTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/uninstantiatedtypes/UninstantiatedAnnotatedArgumentsTest.java
@@ -100,10 +100,7 @@
for (MethodSubject methodSubject : methodSubjects) {
assertThat(methodSubject, isPresent());
- // TODO(b/131735725): Should also remove arguments from the virtual methods.
- boolean shouldHaveArgumentRemoval =
- keepUninstantiatedArguments || methodSubject.getOriginalName().contains("Virtual");
- if (shouldHaveArgumentRemoval) {
+ if (keepUninstantiatedArguments) {
assertEquals(3, methodSubject.getMethod().getParameters().size());
// In non-compat mode, R8 removes annotations from non-pinned items.
@@ -122,7 +119,7 @@
assertEquals(1, annotationSet.size());
DexAnnotation annotation = annotationSet.getFirst();
- if (shouldHaveArgumentRemoval && i == getPositionOfUnusedArgument(methodSubject)) {
+ if (keepUninstantiatedArguments && i == getPositionOfUnusedArgument(methodSubject)) {
assertEquals(
uninstantiatedClassSubject.getFinalName(),
annotation.getAnnotationType().getTypeName());
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/unusedarguments/CollisionWithLibraryMethodsTest.java b/src/test/java/com/android/tools/r8/ir/optimize/unusedarguments/CollisionWithLibraryMethodsTest.java
index 14efc77..612a0b5 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/unusedarguments/CollisionWithLibraryMethodsTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/unusedarguments/CollisionWithLibraryMethodsTest.java
@@ -67,7 +67,7 @@
assertEquals("a", methodSubject.getFinalName());
assertEquals(0, methodSubject.getMethod().getReference().proto.parameters.size());
} else {
- assertEquals("toString1", methodSubject.getFinalName());
+ assertEquals("toString$1", methodSubject.getFinalName());
assertEquals(0, methodSubject.getMethod().getReference().proto.parameters.size());
}
}
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/unusedarguments/UnusedAndUninstantiatedTypesTest.java b/src/test/java/com/android/tools/r8/ir/optimize/unusedarguments/UnusedAndUninstantiatedTypesTest.java
index 138f0a9..7ca05fb 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/unusedarguments/UnusedAndUninstantiatedTypesTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/unusedarguments/UnusedAndUninstantiatedTypesTest.java
@@ -6,6 +6,7 @@
import static org.junit.Assert.assertEquals;
+import com.android.tools.r8.NeverClassInline;
import com.android.tools.r8.NeverInline;
import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestParameters;
@@ -39,6 +40,7 @@
.addKeepMainRule(Main.class)
.noMinification()
.enableInliningAnnotations()
+ .enableNeverClassInliningAnnotations()
.setMinApi(parameters.getApiLevel())
.compile()
.inspect(this::assertMethodsAreThere)
@@ -168,5 +170,6 @@
private static class UnInstantiated {}
+ @NeverClassInline
private static class Unused {}
}
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/unusedarguments/UnusedArgumentRemovalWithOverridingTest.java b/src/test/java/com/android/tools/r8/ir/optimize/unusedarguments/UnusedArgumentRemovalWithOverridingTest.java
index 281db3e..58b052c 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/unusedarguments/UnusedArgumentRemovalWithOverridingTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/unusedarguments/UnusedArgumentRemovalWithOverridingTest.java
@@ -32,7 +32,8 @@
@Parameters(name = "{1}, minification: {0}")
public static List<Object[]> params() {
- return buildParameters(BooleanUtils.values(), getTestParameters().withAllRuntimes().build());
+ return buildParameters(
+ BooleanUtils.values(), getTestParameters().withAllRuntimesAndApiLevels().build());
}
public UnusedArgumentRemovalWithOverridingTest(boolean minification, TestParameters parameters) {
@@ -50,7 +51,7 @@
.enableInliningAnnotations()
.enableNoVerticalClassMergingAnnotations()
.minification(minification)
- .setMinApi(parameters.getRuntime())
+ .setMinApi(parameters.getApiLevel())
.compile()
.inspect(this::verify)
.run(parameters.getRuntime(), TestClass.class)
@@ -70,8 +71,9 @@
static class TestClass {
public static void main(String[] args) {
- System.out.println(new A().greeting("Hello world!"));
- System.out.println(new B().greeting("Hello world!"));
+ String greeting = System.currentTimeMillis() > 0 ? "Hello world!" : null;
+ System.out.println(new A().greeting(greeting));
+ System.out.println(new B().greeting(greeting));
}
}
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/unusedarguments/UnusedArgumentsCollisionMappingTest.java b/src/test/java/com/android/tools/r8/ir/optimize/unusedarguments/UnusedArgumentsCollisionMappingTest.java
index 7d9a941..8ccee13 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/unusedarguments/UnusedArgumentsCollisionMappingTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/unusedarguments/UnusedArgumentsCollisionMappingTest.java
@@ -9,12 +9,12 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
-import com.android.tools.r8.CompilationMode;
import com.android.tools.r8.KeepConstantArguments;
import com.android.tools.r8.NeverInline;
import com.android.tools.r8.R8TestRunResult;
import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
import com.android.tools.r8.utils.StringUtils;
import com.android.tools.r8.utils.codeinspector.ClassSubject;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
@@ -29,25 +29,20 @@
public class UnusedArgumentsCollisionMappingTest extends TestBase {
private final TestParameters parameters;
- private final CompilationMode compilationMode;
- @Parameters(name = "{0}, compilation mode: {1}")
- public static List<Object[]> data() {
- return buildParameters(
- getTestParameters().withAllRuntimesAndApiLevels().build(), CompilationMode.values());
+ @Parameters(name = "{0}")
+ public static TestParametersCollection data() {
+ return getTestParameters().withAllRuntimesAndApiLevels().build();
}
- public UnusedArgumentsCollisionMappingTest(
- TestParameters parameters, CompilationMode compilationMode) {
+ public UnusedArgumentsCollisionMappingTest(TestParameters parameters) {
this.parameters = parameters;
- this.compilationMode = compilationMode;
}
@Test
public void testR8() throws Exception {
R8TestRunResult runResult =
testForR8(parameters.getBackend())
- .setMode(compilationMode)
.addProgramClasses(Main.class)
.setMinApi(parameters.getApiLevel())
.addKeepMainRule(Main.class)
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/unusedarguments/UnusedArgumentsCollisionTest.java b/src/test/java/com/android/tools/r8/ir/optimize/unusedarguments/UnusedArgumentsCollisionTest.java
index 1137a01..c59eb85 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/unusedarguments/UnusedArgumentsCollisionTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/unusedarguments/UnusedArgumentsCollisionTest.java
@@ -34,7 +34,8 @@
@Parameters(name = "{1}, minification: {0}")
public static List<Object[]> data() {
- return buildParameters(BooleanUtils.values(), getTestParameters().withAllRuntimes().build());
+ return buildParameters(
+ BooleanUtils.values(), getTestParameters().withAllRuntimesAndApiLevels().build());
}
public UnusedArgumentsCollisionTest(boolean minification, TestParameters parameters) {
@@ -60,7 +61,7 @@
.enableNeverClassInliningAnnotations()
.enableNoVerticalClassMergingAnnotations()
.minification(minification)
- .setMinApi(parameters.getRuntime())
+ .setMinApi(parameters.getApiLevel())
.compile()
.inspect(this::verifyUnusedArgumentsRemovedAndNoCollisions)
.run(parameters.getRuntime(), TestClass.class)
@@ -85,11 +86,10 @@
MethodSubject methodB1Subject =
bClassSubject.allMethods().stream().filter(FoundMethodSubject::isStatic).findFirst().get();
assertThat(methodB1Subject, isPresent());
- assertEquals(0, methodB1Subject.getMethod().getReference().proto.parameters.size());
+ assertEquals(0, methodB1Subject.getMethod().getParameters().size());
- // TODO(b/129933280): Determine if we should use member pool collection for unused argument
- // removal for private and static methods.
- assertEquals(methodB1Subject.getFinalName(), methodA1Subject.getFinalName());
+ // Verify that the static method B.method1() does not collide with a method in A.
+ assertNotEquals(methodB1Subject.getFinalName(), methodA1Subject.getFinalName());
assertNotEquals(methodB1Subject.getFinalName(), methodA2Subject.getFinalName());
// Verify that the unused argument has been removed from B.method2().
@@ -97,7 +97,7 @@
MethodSubject methodB2Subject =
bClassSubject.allMethods().stream().filter(FoundMethodSubject::isVirtual).findFirst().get();
assertThat(methodB2Subject, isPresent());
- assertEquals(0, methodB2Subject.getMethod().getReference().proto.parameters.size());
+ assertEquals(0, methodB2Subject.getMethod().getParameters().size());
// Verify that the virtual method B.method2() does not collide with a method in A.
assertNotEquals(methodB2Subject.getFinalName(), methodA1Subject.getFinalName());
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/unusedarguments/UnusedArgumentsInstanceConstructorTest.java b/src/test/java/com/android/tools/r8/ir/optimize/unusedarguments/UnusedArgumentsInstanceConstructorTest.java
index c890e97..a4622bc 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/unusedarguments/UnusedArgumentsInstanceConstructorTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/unusedarguments/UnusedArgumentsInstanceConstructorTest.java
@@ -11,11 +11,14 @@
import com.android.tools.r8.NeverClassInline;
import com.android.tools.r8.NeverInline;
+import com.android.tools.r8.NoHorizontalClassMerging;
import com.android.tools.r8.TestBase;
-import com.android.tools.r8.ToolHelper;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
import com.android.tools.r8.utils.StringUtils;
import com.android.tools.r8.utils.codeinspector.ClassSubject;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
+import com.android.tools.r8.utils.codeinspector.HorizontallyMergedClassesInspector;
import com.android.tools.r8.utils.codeinspector.MethodSubject;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -25,32 +28,39 @@
@RunWith(Parameterized.class)
public class UnusedArgumentsInstanceConstructorTest extends TestBase {
- private final Backend backend;
+ private final TestParameters parameters;
- @Parameters(name = "Backend: {0}")
- public static Backend[] data() {
- return ToolHelper.getBackends();
+ @Parameters(name = "{0}")
+ public static TestParametersCollection data() {
+ return getTestParameters().withAllRuntimesAndApiLevels().build();
}
- public UnusedArgumentsInstanceConstructorTest(Backend backend) {
- this.backend = backend;
+ public UnusedArgumentsInstanceConstructorTest(TestParameters parameters) {
+ this.parameters = parameters;
}
@Test
public void test() throws Exception {
String expectedOutput = StringUtils.lines("Hello world");
- if (backend == Backend.CF) {
- testForJvm().addTestClasspath().run(TestClass.class).assertSuccessWithOutput(expectedOutput);
+ if (parameters.isCfRuntime()) {
+ testForJvm()
+ .addTestClasspath()
+ .run(parameters.getRuntime(), TestClass.class)
+ .assertSuccessWithOutput(expectedOutput);
}
CodeInspector inspector =
- testForR8(backend)
+ testForR8(parameters.getBackend())
.addInnerClasses(UnusedArgumentsInstanceConstructorTest.class)
.addKeepMainRule(TestClass.class)
+ .addHorizontallyMergedClassesInspector(
+ HorizontallyMergedClassesInspector::assertNoClassesMerged)
.enableInliningAnnotations()
.enableNeverClassInliningAnnotations()
- .run(TestClass.class)
+ .enableNoHorizontalClassMergingAnnotations()
+ .setMinApi(parameters.getApiLevel())
+ .run(parameters.getRuntime(), TestClass.class)
.assertSuccessWithOutput(expectedOutput)
.inspector();
@@ -73,6 +83,7 @@
}
@NeverClassInline
+ @NoHorizontalClassMerging
static class A {
public A(B uninstantiated, C unused) {
@@ -90,7 +101,9 @@
}
}
+ @NoHorizontalClassMerging
static class B {}
+ @NoHorizontalClassMerging
static class C {}
}
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/unusedarguments/UnusedArgumentsObjectTest.java b/src/test/java/com/android/tools/r8/ir/optimize/unusedarguments/UnusedArgumentsObjectTest.java
index 794d588..3a4eeda 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/unusedarguments/UnusedArgumentsObjectTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/unusedarguments/UnusedArgumentsObjectTest.java
@@ -29,6 +29,7 @@
return UnusedArgumentsTestBase.data();
}
+ @NeverClassInline
static class TestObject {
public final String s;
diff --git a/src/test/java/com/android/tools/r8/regress/b69825683/Regress69825683Test.java b/src/test/java/com/android/tools/r8/regress/b69825683/Regress69825683Test.java
index d0cb2bf..d251e28 100644
--- a/src/test/java/com/android/tools/r8/regress/b69825683/Regress69825683Test.java
+++ b/src/test/java/com/android/tools/r8/regress/b69825683/Regress69825683Test.java
@@ -24,7 +24,7 @@
@Parameterized.Parameters(name = "{0}")
public static TestParametersCollection data() {
- return getTestParameters().withAllRuntimes().build();
+ return getTestParameters().withAllRuntimesAndApiLevels().build();
}
public Regress69825683Test(TestParameters parameters) {
@@ -48,10 +48,13 @@
.addKeepRules(
"-assumemayhavesideeffects class " + inner.getName() + " {",
" synthetic void <init>(...);",
+ "}",
+ "-keepunusedarguments class " + inner.getName() + " {",
+ " synthetic void <init>(...);",
"}")
.addOptionsModification(options -> options.enableClassInlining = false)
.noMinification()
- .setMinApi(parameters.getRuntime())
+ .setMinApi(parameters.getApiLevel())
.run(parameters.getRuntime(), outer)
// Run code to check that the constructor with synthetic class as argument is present.
.assertSuccessWithOutputThatMatches(startsWith(innerName))
@@ -82,7 +85,7 @@
"}")
.noMinification()
.addOptionsModification(o -> o.enableClassInlining = false)
- .setMinApi(parameters.getRuntime())
+ .setMinApi(parameters.getApiLevel())
// Run code to check that the constructor with synthetic class as argument is present.
.run(parameters.getRuntime(), clazz)
.assertSuccessWithOutputThatMatches(startsWith(clazz.getName()))
diff --git a/src/test/java/com/android/tools/r8/shaking/ParameterTypeTest.java b/src/test/java/com/android/tools/r8/shaking/ParameterTypeTest.java
index 7f6323a..b99494e 100644
--- a/src/test/java/com/android/tools/r8/shaking/ParameterTypeTest.java
+++ b/src/test/java/com/android/tools/r8/shaking/ParameterTypeTest.java
@@ -80,17 +80,17 @@
@RunWith(Parameterized.class)
public class ParameterTypeTest extends TestBase {
- private final boolean enableArgumentRemoval;
+ private final boolean enableArgumentPropagation;
private final TestParameters parameters;
- @Parameters(name = "{1}, argument removal: {0}")
+ @Parameters(name = "{1}, argument propagation: {0}")
public static List<Object[]> data() {
return buildParameters(
BooleanUtils.values(), getTestParameters().withAllRuntimesAndApiLevels().build());
}
- public ParameterTypeTest(boolean enableArgumentRemoval, TestParameters parameters) {
- this.enableArgumentRemoval = enableArgumentRemoval;
+ public ParameterTypeTest(boolean enableArgumentPropagation, TestParameters parameters) {
+ this.enableArgumentPropagation = enableArgumentPropagation;
this.parameters = parameters;
}
@@ -228,7 +228,7 @@
options -> {
// Disable inlining to avoid the (short) tested method from being inlined and removed.
options.enableInlining = false;
- options.enableArgumentRemoval = enableArgumentRemoval;
+ options.callSiteOptimizationOptions().setEnabled(enableArgumentPropagation);
});
// Run processed (output) program on ART
@@ -239,7 +239,7 @@
CodeInspector inspector = new CodeInspector(processedApp);
ClassSubject subSubject = inspector.clazz(sub.name);
- assertNotEquals(enableArgumentRemoval, subSubject.isPresent());
+ assertNotEquals(enableArgumentPropagation, subSubject.isPresent());
}
@Test
@@ -307,7 +307,7 @@
options -> {
// Disable inlining to avoid the (short) tested method from being inlined and removed.
options.enableInlining = false;
- options.enableArgumentRemoval = enableArgumentRemoval;
+ options.callSiteOptimizationOptions().setEnabled(enableArgumentPropagation);
})
.noMinification()
.setMinApi(parameters.getApiLevel())
@@ -315,11 +315,11 @@
.inspect(
inspector -> {
ClassSubject subSubject = inspector.clazz(sub.name);
- assertNotEquals(enableArgumentRemoval, subSubject.isPresent());
+ assertNotEquals(enableArgumentPropagation, subSubject.isPresent());
})
.run(parameters.getRuntime(), mainClassName)
.applyIf(
- enableArgumentRemoval || parameters.isCfRuntime(),
+ enableArgumentPropagation || parameters.isCfRuntime(),
SingleTestRunResult::assertSuccess,
result ->
result.assertFailureWithErrorThatMatches(
@@ -410,7 +410,7 @@
options -> {
// Disable inlining to avoid the (short) tested method from being inlined and removed.
options.enableInlining = false;
- options.enableArgumentRemoval = enableArgumentRemoval;
+ options.callSiteOptimizationOptions().setEnabled(enableArgumentPropagation);
});
// Run processed (output) program on ART
@@ -422,6 +422,6 @@
CodeInspector inspector = new CodeInspector(processedApp);
ClassSubject subSubject = inspector.clazz(sub.name);
- assertNotEquals(enableArgumentRemoval, subSubject.isPresent());
+ assertNotEquals(enableArgumentPropagation, subSubject.isPresent());
}
}