Extend profile rewriting to outline optimization
Bug: b/265729283
Bug: b/267592755
Change-Id: If650e519df4db3048ce873a9e7e75523ed43d50c
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/outliner/OutlineCollection.java b/src/main/java/com/android/tools/r8/ir/optimize/outliner/OutlineCollection.java
index 713322d..a3782b6 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/outliner/OutlineCollection.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/outliner/OutlineCollection.java
@@ -11,7 +11,7 @@
import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.GraphLens;
import com.android.tools.r8.graph.ProgramMethod;
-import com.android.tools.r8.ir.optimize.OutlinerImpl.Outline;
+import com.android.tools.r8.ir.optimize.outliner.OutlinerImpl.Outline;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
import com.android.tools.r8.utils.ListUtils;
import com.android.tools.r8.utils.collections.ProgramMethodSet;
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/outliner/OutlineOptimizationEventConsumer.java b/src/main/java/com/android/tools/r8/ir/optimize/outliner/OutlineOptimizationEventConsumer.java
new file mode 100644
index 0000000..4d8a9ed
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/ir/optimize/outliner/OutlineOptimizationEventConsumer.java
@@ -0,0 +1,55 @@
+// 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.ir.optimize.outliner;
+
+import com.android.tools.r8.graph.ProgramMethod;
+import com.android.tools.r8.profile.art.rewriting.ArtProfileCollectionAdditions;
+import com.android.tools.r8.profile.art.rewriting.ConcreteArtProfileCollectionAdditions;
+import java.util.Collection;
+
+public interface OutlineOptimizationEventConsumer {
+
+ void acceptOutlineMethod(ProgramMethod method, Collection<ProgramMethod> contexts);
+
+ static OutlineOptimizationEventConsumer create(
+ ArtProfileCollectionAdditions collectionAdditions) {
+ if (collectionAdditions.isNop()) {
+ return empty();
+ }
+ return create(collectionAdditions.asConcrete());
+ }
+
+ static OutlineOptimizationEventConsumer create(
+ ConcreteArtProfileCollectionAdditions collectionAdditions) {
+ return (method, contexts) -> {
+ for (ProgramMethod context : contexts) {
+ collectionAdditions.applyIfContextIsInProfile(
+ context,
+ additionsBuilder -> additionsBuilder.addRule(method).addRule(method.getHolder()));
+ }
+ };
+ }
+
+ static EmptyOutlineOptimizationEventConsumer empty() {
+ return EmptyOutlineOptimizationEventConsumer.getInstance();
+ }
+
+ class EmptyOutlineOptimizationEventConsumer implements OutlineOptimizationEventConsumer {
+
+ private static final EmptyOutlineOptimizationEventConsumer INSTANCE =
+ new EmptyOutlineOptimizationEventConsumer();
+
+ private EmptyOutlineOptimizationEventConsumer() {}
+
+ static EmptyOutlineOptimizationEventConsumer getInstance() {
+ return INSTANCE;
+ }
+
+ @Override
+ public void acceptOutlineMethod(ProgramMethod method, Collection<ProgramMethod> contexts) {
+ // Intentionally empty.
+ }
+ }
+}
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/outliner/Outliner.java b/src/main/java/com/android/tools/r8/ir/optimize/outliner/Outliner.java
index b3ed5f5..f8d0177 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/outliner/Outliner.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/outliner/Outliner.java
@@ -9,7 +9,6 @@
import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.ir.code.IRCode;
import com.android.tools.r8.ir.conversion.IRConverter;
-import com.android.tools.r8.ir.optimize.OutlinerImpl;
import com.android.tools.r8.ir.optimize.info.OptimizationFeedbackDelayed;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
import com.android.tools.r8.utils.Timing;
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/OutlinerImpl.java b/src/main/java/com/android/tools/r8/ir/optimize/outliner/OutlinerImpl.java
similarity index 97%
rename from src/main/java/com/android/tools/r8/ir/optimize/OutlinerImpl.java
rename to src/main/java/com/android/tools/r8/ir/optimize/outliner/OutlinerImpl.java
index d697a36..7382a1e 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/OutlinerImpl.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/outliner/OutlinerImpl.java
@@ -1,8 +1,8 @@
-// Copyright (c) 2016, the R8 project authors. Please see the AUTHORS file
+// 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.ir.optimize;
+package com.android.tools.r8.ir.optimize.outliner;
import static com.android.tools.r8.ir.analysis.type.Nullability.definitelyNotNull;
import static com.android.tools.r8.ir.analysis.type.Nullability.maybeNull;
@@ -62,12 +62,13 @@
import com.android.tools.r8.ir.conversion.MethodConversionOptions.MutableMethodConversionOptions;
import com.android.tools.r8.ir.conversion.MethodProcessorEventConsumer;
import com.android.tools.r8.ir.conversion.SourceCode;
+import com.android.tools.r8.ir.optimize.CodeRewriter;
import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
+import com.android.tools.r8.ir.optimize.InliningConstraints;
import com.android.tools.r8.ir.optimize.info.OptimizationFeedbackDelayed;
import com.android.tools.r8.ir.optimize.info.OptimizationFeedbackIgnore;
-import com.android.tools.r8.ir.optimize.outliner.OutlineCollection;
-import com.android.tools.r8.ir.optimize.outliner.Outliner;
import com.android.tools.r8.origin.Origin;
+import com.android.tools.r8.profile.art.rewriting.ArtProfileCollectionAdditions;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
import com.android.tools.r8.utils.InternalOptions;
import com.android.tools.r8.utils.InternalOptions.OutlineOptions;
@@ -132,7 +133,7 @@
/** Result of third step (see {@link OutlinerImpl#buildOutlineMethods()}. */
private final Map<Outline, DexMethod> generatedOutlines = new HashMap<>();
- static final int MAX_IN_SIZE = 5; // Avoid using ranged calls for outlined code.
+ static final int MAX_IN_SIZE = 5; // Avoid using ranged calls for outlined code.
private final AppView<AppInfoWithLiveness> appView;
private final DexItemFactory dexItemFactory;
@@ -224,17 +225,14 @@
private final NumericType numericType;
- private BinOpOutlineInstruction(
- OutlineInstructionType type,
- NumericType numericType) {
+ private BinOpOutlineInstruction(OutlineInstructionType type, NumericType numericType) {
super(type);
this.numericType = numericType;
}
static BinOpOutlineInstruction fromInstruction(Binop instruction) {
return new BinOpOutlineInstruction(
- OutlineInstructionType.fromInstruction(instruction),
- instruction.getNumericType());
+ OutlineInstructionType.fromInstruction(instruction), instruction.getNumericType());
}
@Override
@@ -407,11 +405,7 @@
private final boolean hasReceiver;
private InvokeOutlineInstruction(
- DexMethod method,
- Type type,
- boolean hasOutValue,
- ValueType[] inputTypes,
- DexProto proto) {
+ DexMethod method, Type type, boolean hasOutValue, ValueType[] inputTypes, DexProto proto) {
super(OutlineInstructionType.INVOKE);
hasReceiver = inputTypes.length != method.proto.parameters.values.length;
assert !hasReceiver || inputTypes[0].isObject();
@@ -569,7 +563,7 @@
final List<DexType> argumentTypes;
final List<Integer> argumentMap;
final List<OutlineInstruction> templateInstructions = new ArrayList<>();
- final public DexType returnType;
+ public final DexType returnType;
private DexProto proto;
@@ -766,7 +760,7 @@
// This is the superclass for both collection candidates and actually replacing code.
// TODO(sgjesse): Collect more information in the candidate collection and reuse that for
// replacing.
- abstract private class OutlineSpotter {
+ private abstract class OutlineSpotter {
final ProgramMethod method;
final IRCode irCode;
@@ -956,7 +950,7 @@
}
private DexType argumentTypeFromInvoke(InvokeMethod invoke, int index) {
- boolean withReceiver = invoke.isInvokeMethodWithReceiver() || invoke.isInvokePolymorphic();
+ boolean withReceiver = invoke.isInvokeMethodWithReceiver() || invoke.isInvokePolymorphic();
if (withReceiver && index == 0) {
return invoke.getInvokedMethod().holder;
}
@@ -1356,7 +1350,12 @@
identifyOutlineSites(code);
},
executorService);
- List<ProgramMethod> outlineMethods = buildOutlineMethods();
+ ArtProfileCollectionAdditions artProfileCollectionAdditions =
+ ArtProfileCollectionAdditions.create(appView);
+ List<ProgramMethod> outlineMethods =
+ buildOutlineMethods(
+ OutlineOptimizationEventConsumer.create(artProfileCollectionAdditions));
+ artProfileCollectionAdditions.commit(appView);
MethodProcessorEventConsumer eventConsumer = MethodProcessorEventConsumer.empty();
converter.optimizeSynthesizedMethods(outlineMethods, eventConsumer, executorService);
feedback.updateVisibleOptimizationInfo();
@@ -1505,7 +1504,7 @@
return result;
}
- public List<ProgramMethod> buildOutlineMethods() {
+ public List<ProgramMethod> buildOutlineMethods(OutlineOptimizationEventConsumer eventConsumer) {
ProcessorContext outlineProcessorContext = appView.createProcessorContext();
Map<DexMethod, MethodProcessingContext> methodProcessingContexts = new IdentityHashMap<>();
List<ProgramMethod> outlineMethods = new ArrayList<>();
@@ -1546,6 +1545,7 @@
representative.getDefinition().getClassFileVersion());
}
});
+ eventConsumer.acceptOutlineMethod(outlineMethod, sites);
generatedOutlines.put(outline, outlineMethod.getReference());
outlineMethods.add(outlineMethod);
}
@@ -1662,12 +1662,10 @@
}
@Override
- public void setUp() {
- }
+ public void setUp() {}
@Override
- public void clear() {
- }
+ public void clear() {}
@Override
public void buildPrelude(IRBuilder builder) {
@@ -1717,14 +1715,14 @@
}
@Override
- public void resolveAndBuildSwitch(int value, int fallthroughOffset, int payloadOffset,
- IRBuilder builder) {
+ public void resolveAndBuildSwitch(
+ int value, int fallthroughOffset, int payloadOffset, IRBuilder builder) {
throw new Unreachable("Unexpected call to resolveAndBuildSwitch");
}
@Override
- public void resolveAndBuildNewArrayFilledData(int arrayRef, int payloadOffset,
- IRBuilder builder) {
+ public void resolveAndBuildNewArrayFilledData(
+ int arrayRef, int payloadOffset, IRBuilder builder) {
throw new Unreachable("Unexpected call to resolveAndBuildNewArrayFilledData");
}
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 ac5d3b5..388663b 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
@@ -49,7 +49,6 @@
testForR8(Backend.DEX)
.addProgramFiles(outDirectory.resolve("program.jar"))
.addOptionsModification(options -> options.enableEnumUnboxing = false)
- .addOptionsModification(options -> options.outline.enabled = false)
.addOptionsModification(
options -> options.apiModelingOptions().enableStubbingOfClasses = false)
.addOptionsModification(