Rewrite optimization state after code or method pruning
Change-Id: Ideb62fa2a0158ccc82be900d26deada509ee5c48
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 26d42cf..293635b 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
@@ -1955,12 +1955,30 @@
* Called when a method is pruned as a result of optimizations during IR processing in R8, to
* allow optimizations that track sets of methods to fixup their state.
*/
- public void pruneMethod(ProgramMethod method) {
+ public void onMethodPruned(ProgramMethod method) {
assert appView.enableWholeProgramOptimizations();
assert method.getHolder().lookupMethod(method.getReference()) == null;
- appView.withArgumentPropagator(argumentPropagator -> argumentPropagator.pruneMethod(method));
+ appView.withArgumentPropagator(argumentPropagator -> argumentPropagator.onMethodPruned(method));
+ enumUnboxer.onMethodPruned(method);
+ outliner.onMethodPruned(method);
if (inliner != null) {
- inliner.pruneMethod(method);
+ inliner.onMethodPruned(method);
+ }
+ }
+
+ /**
+ * Called when a method is transformed into an abstract or "throw null" method as a result of
+ * optimizations during IR processing in R8.
+ */
+ public void onMethodCodePruned(ProgramMethod method) {
+ assert appView.enableWholeProgramOptimizations();
+ assert method.getHolder().lookupMethod(method.getReference()) != null;
+ appView.withArgumentPropagator(
+ argumentPropagator -> argumentPropagator.onMethodCodePruned(method));
+ enumUnboxer.onMethodCodePruned(method);
+ outliner.onMethodCodePruned(method);
+ if (inliner != null) {
+ inliner.onMethodCodePruned(method);
}
}
}
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 45709ff..32d2228 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
@@ -223,12 +223,7 @@
postMethodProcessorBuilder
.getMethodsToReprocessBuilder()
.rewrittenWithLens(appView)
- .merge(
- singleInlineCallers
- .rewrittenWithLens(appView)
- .removeIf(
- appView,
- method -> method.getOptimizationInfo().hasBeenInlinedIntoSingleCallSite()));
+ .merge(singleInlineCallers);
singleInlineCallers.clear();
}
@@ -1260,7 +1255,11 @@
singleInlineCallers.add(method, appView.graphLens());
}
- public void pruneMethod(ProgramMethod method) {
+ public void onMethodPruned(ProgramMethod method) {
+ onMethodCodePruned(method);
+ }
+
+ public void onMethodCodePruned(ProgramMethod method) {
singleInlineCallers.remove(method.getReference(), appView.graphLens());
}
@@ -1272,6 +1271,7 @@
singleCallerInlinedMethod -> {
if (singleCallerInlinedMethod.getDefinition().belongsToVirtualPool() || true) {
singleCallerInlinedMethod.convertToAbstractOrThrowNullMethod(appView);
+ converter.onMethodCodePruned(singleCallerInlinedMethod);
return true;
}
return false;
@@ -1284,7 +1284,7 @@
.removeMethods(
singleCallerInlinedMethodsForClass.toDefinitionSet(
SetUtils::newIdentityHashSet));
- singleCallerInlinedMethodsForClass.forEach(converter::pruneMethod);
+ singleCallerInlinedMethodsForClass.forEach(converter::onMethodPruned);
}
});
singleCallerInlinedMethodsInWave.clear();
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/OutlinerImpl.java b/src/main/java/com/android/tools/r8/ir/optimize/OutlinerImpl.java
index c0da8fd..31801c6 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/OutlinerImpl.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/OutlinerImpl.java
@@ -1318,6 +1318,16 @@
}
@Override
+ public void onMethodPruned(ProgramMethod method) {
+ onMethodCodePruned(method);
+ }
+
+ @Override
+ public void onMethodCodePruned(ProgramMethod method) {
+ outlineCollection.remove(appView, method);
+ }
+
+ @Override
public void prepareForPrimaryOptimizationPass(GraphLens graphLensForPrimaryOptimizationPass) {
assert appView.graphLens() == graphLensForPrimaryOptimizationPass;
assert outlineCollection == null;
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/enums/EmptyEnumUnboxer.java b/src/main/java/com/android/tools/r8/ir/optimize/enums/EmptyEnumUnboxer.java
index 9320e54..e7edb01 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/enums/EmptyEnumUnboxer.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/enums/EmptyEnumUnboxer.java
@@ -7,6 +7,7 @@
import com.android.tools.r8.graph.AppView;
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.analysis.fieldvalueanalysis.StaticFieldValues;
import com.android.tools.r8.ir.code.IRCode;
import com.android.tools.r8.ir.code.Phi;
@@ -41,6 +42,16 @@
}
@Override
+ public void onMethodPruned(ProgramMethod method) {
+ // Intentionally empty.
+ }
+
+ @Override
+ public void onMethodCodePruned(ProgramMethod method) {
+ // Intentionally empty.
+ }
+
+ @Override
public void recordEnumState(DexProgramClass clazz, StaticFieldValues staticFieldValues) {
// Intentionally empty.
}
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxer.java b/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxer.java
index 2cdf22f..659e685 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxer.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxer.java
@@ -7,6 +7,7 @@
import com.android.tools.r8.graph.AppView;
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.analysis.fieldvalueanalysis.StaticFieldValues;
import com.android.tools.r8.ir.code.IRCode;
import com.android.tools.r8.ir.code.Phi;
@@ -35,6 +36,10 @@
public abstract void analyzeEnums(IRCode code, MutableMethodConversionOptions conversionOptions);
+ public abstract void onMethodPruned(ProgramMethod method);
+
+ public abstract void onMethodCodePruned(ProgramMethod method);
+
public abstract void recordEnumState(DexProgramClass clazz, StaticFieldValues staticFieldValues);
public abstract Set<Phi> rewriteCode(IRCode code, MethodProcessor methodProcessor);
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxerImpl.java b/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxerImpl.java
index ea6b5e5..40e53fb 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxerImpl.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxerImpl.java
@@ -643,17 +643,11 @@
.merge(
dependencies
.rewrittenWithLens(appView)
- .removeAll(treeFixerResult.getPrunedItems().getRemovedMethods())
- .removeIf(
- appView,
- method -> method.getOptimizationInfo().hasBeenInlinedIntoSingleCallSite()))
+ .removeAll(treeFixerResult.getPrunedItems().getRemovedMethods()))
.merge(
methodsDependingOnLibraryModelisation
.rewrittenWithLens(appView)
- .removeAll(treeFixerResult.getPrunedItems().getRemovedMethods())
- .removeIf(
- appView,
- method -> method.getOptimizationInfo().hasBeenInlinedIntoSingleCallSite()));
+ .removeAll(treeFixerResult.getPrunedItems().getRemovedMethods()));
methodsDependingOnLibraryModelisation.clear();
updateOptimizationInfos(executorService, feedback, treeFixerResult);
@@ -1416,6 +1410,17 @@
}
@Override
+ public void onMethodPruned(ProgramMethod method) {
+ onMethodCodePruned(method);
+ }
+
+ @Override
+ public void onMethodCodePruned(ProgramMethod method) {
+ enumUnboxingCandidatesInfo.addPrunedMethod(method);
+ methodsDependingOnLibraryModelisation.remove(method.getReference(), appView.graphLens());
+ }
+
+ @Override
public Set<Phi> rewriteCode(IRCode code, MethodProcessor methodProcessor) {
// This has no effect during primary processing since the enumUnboxerRewriter is set
// in between primary and post processing.
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxingCandidateInfoCollection.java b/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxingCandidateInfoCollection.java
index 386bcb0..39dd787 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxingCandidateInfoCollection.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxingCandidateInfoCollection.java
@@ -6,6 +6,7 @@
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexField;
+import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.GraphLens;
@@ -25,6 +26,7 @@
public class EnumUnboxingCandidateInfoCollection {
private final Map<DexType, EnumUnboxingCandidateInfo> enumTypeToInfo = new ConcurrentHashMap<>();
+ private final Set<DexMethod> prunedMethods = Sets.newIdentityHashSet();
public void addCandidate(
AppView<AppInfoWithLiveness> appView,
@@ -36,6 +38,10 @@
new EnumUnboxingCandidateInfo(appView, enumClass, graphLensForPrimaryOptimizationPass));
}
+ public void addPrunedMethod(ProgramMethod method) {
+ prunedMethods.add(method.getReference());
+ }
+
public void removeCandidate(DexProgramClass enumClass) {
removeCandidate(enumClass.getType());
}
@@ -80,6 +86,7 @@
while (candidateInfoIterator.hasNext()) {
allMethodDependencies.merge(candidateInfoIterator.next().methodDependencies);
}
+ allMethodDependencies.removeAll(prunedMethods);
return allMethodDependencies;
}
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 78dc248..713322d 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
@@ -34,6 +34,11 @@
this.appliedGraphLens = graphLensForPrimaryOptimizationPass;
}
+ public void remove(AppView<AppInfoWithLiveness> appView, ProgramMethod method) {
+ assert appView.graphLens() == appliedGraphLens;
+ outlines.remove(method.getReference());
+ }
+
public void set(
AppView<AppInfoWithLiveness> appView, ProgramMethod method, List<Outline> outlinesForMethod) {
assert appView.graphLens() == appliedGraphLens;
@@ -101,9 +106,7 @@
assert false;
return;
}
- if (method.getOptimizationInfo().hasBeenInlinedIntoSingleCallSite()) {
- return;
- }
+ assert !method.getOptimizationInfo().hasBeenInlinedIntoSingleCallSite();
for (Outline outline : outlinesForMethod) {
methodsPerOutline.computeIfAbsent(outline, ignoreKey(ArrayList::new)).add(method);
}
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 a2bd90f..b3ed5f5 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
@@ -6,6 +6,7 @@
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.GraphLens;
+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;
@@ -29,6 +30,16 @@
}
@Override
+ public void onMethodPruned(ProgramMethod method) {
+ // Intentionally empty.
+ }
+
+ @Override
+ public void onMethodCodePruned(ProgramMethod method) {
+ // Intentionally empty.
+ }
+
+ @Override
public void prepareForPrimaryOptimizationPass(GraphLens graphLensForPrimaryOptimizationPass) {
// Intentionally empty.
}
@@ -52,6 +63,10 @@
public abstract void collectOutlineSites(IRCode code, Timing timing);
+ public abstract void onMethodPruned(ProgramMethod method);
+
+ public abstract void onMethodCodePruned(ProgramMethod method);
+
public abstract void prepareForPrimaryOptimizationPass(
GraphLens graphLensForPrimaryOptimizationPass);
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/typechecks/CheckCastAndInstanceOfMethodSpecialization.java b/src/main/java/com/android/tools/r8/ir/optimize/typechecks/CheckCastAndInstanceOfMethodSpecialization.java
index 18a964f..13f384e 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/typechecks/CheckCastAndInstanceOfMethodSpecialization.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/typechecks/CheckCastAndInstanceOfMethodSpecialization.java
@@ -162,7 +162,7 @@
// Remove the method and notify other optimizations that the override has been removed to allow
// the optimizations to fixup their state.
method.getHolder().removeMethod(method.getReference());
- converter.pruneMethod(method);
+ converter.onMethodPruned(method);
}
private ProgramMethod resolveOnSuperClass(ProgramMethod method) {
diff --git a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/ArgumentPropagator.java b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/ArgumentPropagator.java
index 922e198..158a8de 100644
--- a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/ArgumentPropagator.java
+++ b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/ArgumentPropagator.java
@@ -224,9 +224,13 @@
*
* <p>Therefore, we assert that we only find a method state for direct methods.
*/
- public void pruneMethod(ProgramMethod method) {
+ public void onMethodPruned(ProgramMethod method) {
assert codeScanner != null;
MethodState methodState = codeScanner.getMethodStates().removeOrElse(method, null);
assert methodState == null || method.getDefinition().belongsToDirectPool();
}
+
+ public void onMethodCodePruned(ProgramMethod method) {
+ // Intentionally empty.
+ }
}