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.
+  }
 }