Simplify dual caller inlining
Bug: 142300882
Change-Id: I6009504022745159d629ce2dfe3286b3f8431e58
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java b/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java
index 449edec..26d42cf 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java
@@ -656,9 +656,6 @@
classStaticizer,
classStaticizer ->
classStaticizer.prepareForPrimaryOptimizationPass(graphLensForPrimaryOptimizationPass));
- ConsumerUtils.acceptIfNotNull(
- inliner,
- inliner -> inliner.initializeDoubleInlineCallers(graphLensForPrimaryOptimizationPass));
outliner.prepareForPrimaryOptimizationPass(graphLensForPrimaryOptimizationPass);
if (fieldAccessAnalysis != null) {
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/DefaultInliningOracle.java b/src/main/java/com/android/tools/r8/ir/optimize/DefaultInliningOracle.java
index 5555442..0b7b139 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/DefaultInliningOracle.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/DefaultInliningOracle.java
@@ -182,26 +182,7 @@
return false;
}
- if (reason == Reason.DUAL_CALLER) {
- assert methodProcessor.isPrimaryMethodProcessor() || methodProcessor.isPostMethodProcessor();
- if (satisfiesRequirementsForSimpleInlining(invoke, singleTarget)) {
- // When we have a method with two call sites, we simply inline the method as we normally do
- // when the method is small. We still need to ensure that the other call site is also
- // inlined, though. Therefore, we record here that we have seen one of the two call sites
- // as we normally do.
- inliner.recordDoubleInliningCandidate(method, singleTarget, methodProcessor);
- } else if (inliner.isDoubleInliningEnabled(methodProcessor)) {
- if (!inliner.satisfiesRequirementsForDoubleInlining(
- method, singleTarget, methodProcessor)) {
- whyAreYouNotInliningReporter.reportInvalidDoubleInliningCandidate();
- return false;
- }
- } else {
- // TODO(b/142300882): Should in principle disallow inlining in this case.
- inliner.recordDoubleInliningCandidate(method, singleTarget, methodProcessor);
- }
- } else if (reason == Reason.SIMPLE
- && !satisfiesRequirementsForSimpleInlining(invoke, singleTarget)) {
+ if (reason == Reason.SIMPLE && !satisfiesRequirementsForSimpleInlining(invoke, singleTarget)) {
whyAreYouNotInliningReporter.reportInlineeNotSimple();
return false;
}
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/Inliner.java b/src/main/java/com/android/tools/r8/ir/optimize/Inliner.java
index 2d56aaf..45709ff 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/Inliner.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/Inliner.java
@@ -76,7 +76,6 @@
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Deque;
-import java.util.IdentityHashMap;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
@@ -95,13 +94,9 @@
// due to not being processed at the time of inlining.
private final LongLivedProgramMethodSetBuilder<ProgramMethodSet> singleInlineCallers;
- // State for inlining methods which are known to be called twice.
- private LongLivedProgramMethodSetBuilder<ProgramMethodSet> doubleInlineCallers;
- private final ProgramMethodSet doubleInlineSelectedTargets = ProgramMethodSet.create();
- private final Map<DexEncodedMethod, ProgramMethod> doubleInlineeCandidates =
- new IdentityHashMap<>();
-
- private final Map<DexProgramClass, ProgramMethodSet> singleCallerInlinedMethods =
+ // The set of methods that have been single caller inlined in the current wave. These need to be
+ // pruned when the wave ends.
+ private final Map<DexProgramClass, ProgramMethodSet> singleCallerInlinedMethodsInWave =
new ConcurrentHashMap<>();
private final AvailableApiExceptions availableApiExceptions;
@@ -220,47 +215,6 @@
return false;
}
- public synchronized boolean isDoubleInlineSelectedTarget(ProgramMethod method) {
- return doubleInlineSelectedTargets.contains(method);
- }
-
- synchronized boolean satisfiesRequirementsForDoubleInlining(
- ProgramMethod method, ProgramMethod target, MethodProcessor methodProcessor) {
- if (isDoubleInliningEnabled(methodProcessor)) {
- // Don't perform the actual inlining if this was not selected.
- return doubleInlineSelectedTargets.contains(target);
- }
-
- // Just preparing for double inlining.
- recordDoubleInliningCandidate(method, target, methodProcessor);
- return false;
- }
-
- synchronized void recordDoubleInliningCandidate(
- ProgramMethod method, ProgramMethod target, MethodProcessor methodProcessor) {
- if (isDoubleInliningEnabled(methodProcessor)) {
- return;
- }
-
- if (doubleInlineeCandidates.containsKey(target.getDefinition())) {
- // Both calls can be inlined.
- GraphLens currentGraphLens = appView.graphLens();
- ProgramMethod doubleInlineeCandidate = doubleInlineeCandidates.get(target.getDefinition());
- doubleInlineCallers.add(doubleInlineeCandidate, currentGraphLens);
- doubleInlineCallers.add(method, currentGraphLens);
- doubleInlineSelectedTargets.add(target);
- } else {
- // First call can be inlined.
- doubleInlineeCandidates.put(target.getDefinition(), method);
- }
- }
-
- public void initializeDoubleInlineCallers(GraphLens graphLensForPrimaryOptimizationPass) {
- assert appView.graphLens() == graphLensForPrimaryOptimizationPass;
- doubleInlineCallers =
- LongLivedProgramMethodSetBuilder.createForIdentitySet(graphLensForPrimaryOptimizationPass);
- }
-
public void enqueueMethodsForReprocessing(
PostMethodProcessor.Builder postMethodProcessorBuilder) {
// The double inline callers are always rewritten up until the graph lens of the primary
@@ -270,18 +224,11 @@
.getMethodsToReprocessBuilder()
.rewrittenWithLens(appView)
.merge(
- doubleInlineCallers
- .rewrittenWithLens(appView)
- .removeIf(
- appView,
- method -> method.getOptimizationInfo().hasBeenInlinedIntoSingleCallSite()))
- .merge(
singleInlineCallers
.rewrittenWithLens(appView)
.removeIf(
appView,
method -> method.getOptimizationInfo().hasBeenInlinedIntoSingleCallSite()));
- doubleInlineCallers = null;
singleInlineCallers.clear();
}
@@ -970,7 +917,7 @@
public InliningReasonStrategy createDefaultInliningReasonStrategy(
MethodProcessor methodProcessor) {
DefaultInliningReasonStrategy defaultInliningReasonStrategy =
- new DefaultInliningReasonStrategy(appView, methodProcessor.getCallSiteInformation(), this);
+ new DefaultInliningReasonStrategy(appView, methodProcessor.getCallSiteInformation());
return appView.withGeneratedMessageLiteShrinker(
ignore -> new ProtoInliningReasonStrategy(appView, defaultInliningReasonStrategy),
defaultInliningReasonStrategy);
@@ -1137,10 +1084,10 @@
if (inlinee.reason == Reason.SINGLE_CALLER) {
assert converter.isInWave();
feedback.markInlinedIntoSingleCallSite(singleTargetMethod);
- if (singleCallerInlinedMethods.isEmpty()) {
+ if (singleCallerInlinedMethodsInWave.isEmpty()) {
converter.addWaveDoneAction(this::onWaveDone);
}
- singleCallerInlinedMethods
+ singleCallerInlinedMethodsInWave
.computeIfAbsent(
singleTarget.getHolder(), ignoreKey(ProgramMethodSet::createConcurrent))
.add(singleTarget);
@@ -1318,7 +1265,7 @@
}
private void onWaveDone() {
- singleCallerInlinedMethods.forEach(
+ singleCallerInlinedMethodsInWave.forEach(
(clazz, singleCallerInlinedMethodsForClass) -> {
// Convert and remove virtual single caller inlined methods to abstract or throw null.
singleCallerInlinedMethodsForClass.removeIf(
@@ -1340,7 +1287,7 @@
singleCallerInlinedMethodsForClass.forEach(converter::pruneMethod);
}
});
- singleCallerInlinedMethods.clear();
+ singleCallerInlinedMethodsInWave.clear();
}
public static boolean verifyAllSingleCallerMethodsHaveBeenPruned(
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/inliner/DefaultInliningReasonStrategy.java b/src/main/java/com/android/tools/r8/ir/optimize/inliner/DefaultInliningReasonStrategy.java
index 370b86b..ef00071 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/inliner/DefaultInliningReasonStrategy.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/inliner/DefaultInliningReasonStrategy.java
@@ -11,7 +11,6 @@
import com.android.tools.r8.ir.code.InvokeMethod;
import com.android.tools.r8.ir.conversion.CallSiteInformation;
import com.android.tools.r8.ir.conversion.MethodProcessor;
-import com.android.tools.r8.ir.optimize.Inliner;
import com.android.tools.r8.ir.optimize.Inliner.Reason;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
import com.android.tools.r8.utils.InternalOptions.InlinerOptions;
@@ -20,16 +19,12 @@
private final AppView<AppInfoWithLiveness> appView;
private final CallSiteInformation callSiteInformation;
- private final Inliner inliner;
private final InlinerOptions options;
public DefaultInliningReasonStrategy(
- AppView<AppInfoWithLiveness> appView,
- CallSiteInformation callSiteInformation,
- Inliner inliner) {
+ AppView<AppInfoWithLiveness> appView, CallSiteInformation callSiteInformation) {
this.appView = appView;
this.callSiteInformation = callSiteInformation;
- this.inliner = inliner;
this.options = appView.options().inlinerOptions();
}
@@ -59,7 +54,8 @@
if (isSingleCallerInliningTarget(target)) {
return Reason.SINGLE_CALLER;
}
- if (isDoubleInliningTarget(target, methodProcessor)) {
+ if (isDoubleInliningTarget(target)) {
+ assert methodProcessor.isPrimaryMethodProcessor();
return Reason.DUAL_CALLER;
}
return Reason.SIMPLE;
@@ -79,16 +75,11 @@
return true;
}
- private boolean isDoubleInliningTarget(ProgramMethod candidate, MethodProcessor methodProcessor) {
- if (methodProcessor.isPrimaryMethodProcessor() || methodProcessor.isPostMethodProcessor()) {
- if (callSiteInformation.hasDoubleCallSite(candidate)
- || inliner.isDoubleInlineSelectedTarget(candidate)) {
- return candidate
+ private boolean isDoubleInliningTarget(ProgramMethod candidate) {
+ return callSiteInformation.hasDoubleCallSite(candidate)
+ && candidate
.getDefinition()
.getCode()
.estimatedSizeForInliningAtMost(options.getDoubleInliningInstructionLimit());
- }
- }
- return false;
}
}