Extend profile rewriting to utility methods for code optimizations
Bug: b/265729283
Bug: b/267592755
Change-Id: I7084f16b898d461ee3c17c1d45c142f42729f379
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/ClassConverter.java b/src/main/java/com/android/tools/r8/ir/conversion/ClassConverter.java
index 879beb8..7b3641f 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/ClassConverter.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/ClassConverter.java
@@ -34,7 +34,6 @@
public abstract class ClassConverter {
protected final AppView<?> appView;
- private final ArtProfileCollectionAdditions artProfileCollectionAdditions;
private final PrimaryD8L8IRConverter converter;
private final D8MethodProcessor methodProcessor;
private final InterfaceProcessor interfaceProcessor;
@@ -45,7 +44,6 @@
D8MethodProcessor methodProcessor,
InterfaceProcessor interfaceProcessor) {
this.appView = appView;
- this.artProfileCollectionAdditions = ArtProfileCollectionAdditions.create(appView);
this.converter = converter;
this.methodProcessor = methodProcessor;
this.interfaceProcessor = interfaceProcessor;
@@ -66,7 +64,6 @@
throws ExecutionException {
ClassConverterResult.Builder resultBuilder = ClassConverterResult.builder();
internalConvertClasses(resultBuilder, executorService);
- artProfileCollectionAdditions.commit(appView);
notifyAllClassesConverted();
return resultBuilder.build();
}
@@ -117,6 +114,8 @@
ClassConverterResult.Builder resultBuilder, ExecutorService executorService)
throws ExecutionException {
Collection<DexProgramClass> classes = appView.appInfo().classes();
+ ArtProfileCollectionAdditions artProfileCollectionAdditions =
+ methodProcessor.getArtProfileCollectionAdditions();
CfClassSynthesizerDesugaringEventConsumer classSynthesizerEventConsumer =
CfClassSynthesizerDesugaringEventConsumer.create(artProfileCollectionAdditions);
converter.classSynthesisDesugaring(executorService, classSynthesizerEventConsumer);
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/D8MethodProcessor.java b/src/main/java/com/android/tools/r8/ir/conversion/D8MethodProcessor.java
index 9332c11..7a04167 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/D8MethodProcessor.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/D8MethodProcessor.java
@@ -13,6 +13,7 @@
import com.android.tools.r8.ir.desugar.CfInstructionDesugaringEventConsumer;
import com.android.tools.r8.ir.desugar.CfInstructionDesugaringEventConsumer.D8CfInstructionDesugaringEventConsumer;
import com.android.tools.r8.ir.optimize.info.OptimizationFeedbackIgnore;
+import com.android.tools.r8.profile.art.rewriting.ArtProfileCollectionAdditions;
import com.android.tools.r8.utils.ThreadUtils;
import com.google.common.collect.Sets;
import java.util.ArrayList;
@@ -25,6 +26,7 @@
public class D8MethodProcessor extends MethodProcessor {
+ private final ArtProfileCollectionAdditions artProfileCollectionAdditions;
private final PrimaryD8L8IRConverter converter;
private final MethodProcessorEventConsumer eventConsumer;
private final ExecutorService executorService;
@@ -43,11 +45,12 @@
private ProcessorContext processorContext;
public D8MethodProcessor(
+ ArtProfileCollectionAdditions artProfileCollectionAdditions,
PrimaryD8L8IRConverter converter,
- MethodProcessorEventConsumer eventConsumer,
ExecutorService executorService) {
+ this.artProfileCollectionAdditions = artProfileCollectionAdditions;
this.converter = converter;
- this.eventConsumer = eventConsumer;
+ this.eventConsumer = MethodProcessorEventConsumer.create(artProfileCollectionAdditions);
this.executorService = executorService;
this.processorContext = converter.appView.createProcessorContext();
}
@@ -66,6 +69,10 @@
return processorContext.createMethodProcessingContext(method);
}
+ public ArtProfileCollectionAdditions getArtProfileCollectionAdditions() {
+ return artProfileCollectionAdditions;
+ }
+
@Override
public MethodProcessorEventConsumer getEventConsumer() {
return eventConsumer;
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/MethodProcessorEventConsumer.java b/src/main/java/com/android/tools/r8/ir/conversion/MethodProcessorEventConsumer.java
index 1f45015..24b85b4 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/MethodProcessorEventConsumer.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/MethodProcessorEventConsumer.java
@@ -6,10 +6,18 @@
import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.ir.optimize.UtilityMethodsForCodeOptimizationsEventConsumer;
+import com.android.tools.r8.profile.art.rewriting.ArtProfileCollectionAdditions;
+import com.android.tools.r8.profile.art.rewriting.ArtProfileRewritingMethodProcessorEventConsumer;
public abstract class MethodProcessorEventConsumer
implements UtilityMethodsForCodeOptimizationsEventConsumer {
+ public static MethodProcessorEventConsumer create(
+ ArtProfileCollectionAdditions artProfileCollectionAdditions) {
+ return ArtProfileRewritingMethodProcessorEventConsumer.attach(
+ artProfileCollectionAdditions, empty());
+ }
+
public static MethodProcessorEventConsumer empty() {
return EmptyMethodProcessorEventConsumer.getInstance();
}
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/PrimaryD8L8IRConverter.java b/src/main/java/com/android/tools/r8/ir/conversion/PrimaryD8L8IRConverter.java
index fb8e0b9..1d06a25 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/PrimaryD8L8IRConverter.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/PrimaryD8L8IRConverter.java
@@ -55,8 +55,10 @@
LambdaDeserializationMethodRemover.run(appView);
workaroundAbstractMethodOnNonAbstractClassVerificationBug(executorService);
DexApplication application = appView.appInfo().app();
- MethodProcessorEventConsumer eventConsumer = MethodProcessorEventConsumer.empty();
- D8MethodProcessor methodProcessor = new D8MethodProcessor(this, eventConsumer, executorService);
+ ArtProfileCollectionAdditions artProfileCollectionAdditions =
+ ArtProfileCollectionAdditions.create(appView);
+ D8MethodProcessor methodProcessor =
+ new D8MethodProcessor(artProfileCollectionAdditions, this, executorService);
InterfaceProcessor interfaceProcessor = InterfaceProcessor.create(appView);
timing.begin("IR conversion");
@@ -99,6 +101,8 @@
appView.appInfo().getSyntheticItems().commit(application),
appView.appInfo().getMainDexInfo()));
+ artProfileCollectionAdditions.commit(appView);
+
printCfg();
}
@@ -302,11 +306,11 @@
InterfaceProcessor interfaceProcessor,
ExecutorService executorService)
throws ExecutionException {
- ArtProfileCollectionAdditions artProfileCollectionAdditions =
- ArtProfileCollectionAdditions.create(appView);
CfPostProcessingDesugaringEventConsumer eventConsumer =
CfPostProcessingDesugaringEventConsumer.createForD8(
- artProfileCollectionAdditions, methodProcessor, instructionDesugaring);
+ methodProcessor.getArtProfileCollectionAdditions(),
+ methodProcessor,
+ instructionDesugaring);
methodProcessor.newWave();
InterfaceMethodProcessorFacade interfaceDesugaring =
instructionDesugaring.getInterfaceMethodPostProcessingDesugaringD8(
@@ -315,7 +319,6 @@
.postProcessingDesugaring(appView.appInfo().classes(), eventConsumer, executorService);
methodProcessor.awaitMethodProcessing();
eventConsumer.finalizeDesugaring();
- artProfileCollectionAdditions.commit(appView);
}
void prepareDesugaring(
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/PrimaryR8IRConverter.java b/src/main/java/com/android/tools/r8/ir/conversion/PrimaryR8IRConverter.java
index 41b4243..aae02ab 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/PrimaryR8IRConverter.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/PrimaryR8IRConverter.java
@@ -16,6 +16,7 @@
import com.android.tools.r8.ir.optimize.info.OptimizationFeedbackDelayed;
import com.android.tools.r8.logging.Log;
import com.android.tools.r8.optimize.argumentpropagation.ArgumentPropagator;
+import com.android.tools.r8.profile.art.rewriting.ArtProfileCollectionAdditions;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
import com.android.tools.r8.utils.CfgPrinter;
import com.android.tools.r8.utils.Timing;
@@ -81,7 +82,10 @@
new PostMethodProcessor.Builder(graphLensForPrimaryOptimizationPass);
{
timing.begin("Build primary method processor");
- MethodProcessorEventConsumer eventConsumer = MethodProcessorEventConsumer.empty();
+ ArtProfileCollectionAdditions artProfileCollectionAdditions =
+ ArtProfileCollectionAdditions.create(appView);
+ MethodProcessorEventConsumer eventConsumer =
+ MethodProcessorEventConsumer.create(artProfileCollectionAdditions);
PrimaryMethodProcessor primaryMethodProcessor =
PrimaryMethodProcessor.create(
appView.withLiveness(), eventConsumer, executorService, timing);
@@ -97,6 +101,7 @@
timing,
executorService);
lastWaveDone(postMethodProcessorBuilder, executorService);
+ timing.time("Commit profile additions", () -> artProfileCollectionAdditions.commit(appView));
assert appView.graphLens() == graphLensForPrimaryOptimizationPass;
timing.end();
}
@@ -150,11 +155,14 @@
{
timing.begin("IR conversion phase 2");
+ ArtProfileCollectionAdditions artProfileCollectionAdditions =
+ ArtProfileCollectionAdditions.create(appView);
PostMethodProcessor postMethodProcessor =
timing.time(
"Build post method processor",
() -> {
- MethodProcessorEventConsumer eventConsumer = MethodProcessorEventConsumer.empty();
+ MethodProcessorEventConsumer eventConsumer =
+ MethodProcessorEventConsumer.create(artProfileCollectionAdditions);
return postMethodProcessorBuilder.build(
appView, eventConsumer, executorService, timing);
});
@@ -171,6 +179,8 @@
timing);
timing.end();
timing.time("Update visible optimization info", feedback::updateVisibleOptimizationInfo);
+ timing.time(
+ "Commit profile additions", () -> artProfileCollectionAdditions.commit(appView));
assert appView.graphLens() == graphLensForSecondaryOptimizationPass;
}
timing.end();
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/CodeRewriter.java b/src/main/java/com/android/tools/r8/ir/optimize/CodeRewriter.java
index b8d7c12..509d6c1 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/CodeRewriter.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/CodeRewriter.java
@@ -1484,8 +1484,7 @@
// type.
if (castType.isClassType()
&& castType.isAlwaysNull(appViewWithLiveness)
- && !outValue.hasDebugUsers()
- && options.testing.enableUtilityMethodsForCodeOptimizations) {
+ && !outValue.hasDebugUsers()) {
// Replace all usages of the out-value by null.
it.previous();
Value nullValue = it.insertConstNullInstruction(code, options);
diff --git a/src/main/java/com/android/tools/r8/profile/art/rewriting/ArtProfileRewritingMethodProcessorEventConsumer.java b/src/main/java/com/android/tools/r8/profile/art/rewriting/ArtProfileRewritingMethodProcessorEventConsumer.java
new file mode 100644
index 0000000..84143bf
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/profile/art/rewriting/ArtProfileRewritingMethodProcessorEventConsumer.java
@@ -0,0 +1,78 @@
+// Copyright (c) 2023, 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.profile.art.rewriting;
+
+import com.android.tools.r8.graph.ProgramMethod;
+import com.android.tools.r8.ir.conversion.MethodProcessorEventConsumer;
+
+public class ArtProfileRewritingMethodProcessorEventConsumer extends MethodProcessorEventConsumer {
+
+ private final ConcreteArtProfileCollectionAdditions additionsCollection;
+ private final MethodProcessorEventConsumer parent;
+
+ private ArtProfileRewritingMethodProcessorEventConsumer(
+ ConcreteArtProfileCollectionAdditions additionsCollection,
+ MethodProcessorEventConsumer parent) {
+ this.additionsCollection = additionsCollection;
+ this.parent = parent;
+ }
+
+ public static MethodProcessorEventConsumer attach(
+ ArtProfileCollectionAdditions artProfileCollectionAdditions,
+ MethodProcessorEventConsumer eventConsumer) {
+ if (artProfileCollectionAdditions.isNop()) {
+ return eventConsumer;
+ }
+ return new ArtProfileRewritingMethodProcessorEventConsumer(
+ artProfileCollectionAdditions.asConcrete(), eventConsumer);
+ }
+
+ @Override
+ public void acceptUtilityToStringIfNotNullMethod(ProgramMethod method, ProgramMethod context) {
+ additionsCollection.applyIfContextIsInProfile(
+ context, additionsBuilder -> additionsBuilder.addRule(method).addRule(method.getHolder()));
+ parent.acceptUtilityToStringIfNotNullMethod(method, context);
+ }
+
+ @Override
+ public void acceptUtilityThrowClassCastExceptionIfNotNullMethod(
+ ProgramMethod method, ProgramMethod context) {
+ additionsCollection.applyIfContextIsInProfile(
+ context, additionsBuilder -> additionsBuilder.addRule(method).addRule(method.getHolder()));
+ parent.acceptUtilityThrowClassCastExceptionIfNotNullMethod(method, context);
+ }
+
+ @Override
+ public void acceptUtilityThrowIllegalAccessErrorMethod(
+ ProgramMethod method, ProgramMethod context) {
+ additionsCollection.applyIfContextIsInProfile(
+ context, additionsBuilder -> additionsBuilder.addRule(method).addRule(method.getHolder()));
+ parent.acceptUtilityThrowIllegalAccessErrorMethod(method, context);
+ }
+
+ @Override
+ public void acceptUtilityThrowIncompatibleClassChangeErrorMethod(
+ ProgramMethod method, ProgramMethod context) {
+ additionsCollection.applyIfContextIsInProfile(
+ context, additionsBuilder -> additionsBuilder.addRule(method).addRule(method.getHolder()));
+ parent.acceptUtilityThrowIncompatibleClassChangeErrorMethod(method, context);
+ }
+
+ @Override
+ public void acceptUtilityThrowNoSuchMethodErrorMethod(
+ ProgramMethod method, ProgramMethod context) {
+ additionsCollection.applyIfContextIsInProfile(
+ context, additionsBuilder -> additionsBuilder.addRule(method).addRule(method.getHolder()));
+ parent.acceptUtilityThrowNoSuchMethodErrorMethod(method, context);
+ }
+
+ @Override
+ public void acceptUtilityThrowRuntimeExceptionWithMessageMethod(
+ ProgramMethod method, ProgramMethod context) {
+ additionsCollection.applyIfContextIsInProfile(
+ context, additionsBuilder -> additionsBuilder.addRule(method).addRule(method.getHolder()));
+ parent.acceptUtilityThrowRuntimeExceptionWithMessageMethod(method, context);
+ }
+}
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 f91b466..2c06cad 100644
--- a/src/main/java/com/android/tools/r8/utils/InternalOptions.java
+++ b/src/main/java/com/android/tools/r8/utils/InternalOptions.java
@@ -2095,7 +2095,6 @@
public boolean enableSwitchToIfRewriting = true;
public boolean enableEnumUnboxingDebugLogs =
System.getProperty("com.android.tools.r8.enableEnumUnboxingDebugLogs") != null;
- public boolean enableUtilityMethodsForCodeOptimizations = true;
public boolean forceRedundantConstNumberRemoval = false;
public boolean enableExperimentalDesugaredLibraryKeepRuleGenerator = false;
public boolean invertConditionals = false;
diff --git a/src/test/java/com/android/tools/r8/internal/opensourceapps/TiviTest.java b/src/test/java/com/android/tools/r8/internal/opensourceapps/TiviTest.java
index 26aa1b1..38074be 100644
--- a/src/test/java/com/android/tools/r8/internal/opensourceapps/TiviTest.java
+++ b/src/test/java/com/android/tools/r8/internal/opensourceapps/TiviTest.java
@@ -56,8 +56,6 @@
options -> options.apiModelingOptions().enableStubbingOfClasses = false)
.addOptionsModification(options -> options.callSiteOptimizationOptions().setEnabled(false))
.addOptionsModification(
- options -> options.testing.enableUtilityMethodsForCodeOptimizations = false)
- .addOptionsModification(
options -> options.getArtProfileOptions().setEnableCompletenessCheckForTesting(true))
.apply(this::configure)
.compile();