Revert "Reland "Prune single caller inlined direct methods when wave ends""

This reverts commit 5e7c3d56a9e7e5e50952198dc044a46211250f3f.

Reason for revert: YouTube 16.20 failure

Bug: 204743804
Change-Id: I7d5d0b5db442c4d8e1269446ea070482d4067926
diff --git a/src/main/java/com/android/tools/r8/graph/AppView.java b/src/main/java/com/android/tools/r8/graph/AppView.java
index cfb13ae..4d3d50a 100644
--- a/src/main/java/com/android/tools/r8/graph/AppView.java
+++ b/src/main/java/com/android/tools/r8/graph/AppView.java
@@ -514,10 +514,6 @@
     return options().testing;
   }
 
-  public boolean hasRootSet() {
-    return rootSet != null;
-  }
-
   public RootSet rootSet() {
     return rootSet;
   }
@@ -715,10 +711,7 @@
       setProguardCompatibilityActions(
           getProguardCompatibilityActions().withoutPrunedItems(prunedItems));
     }
-    if (hasRootSet()) {
-      rootSet.pruneItems(prunedItems);
-    }
-    if (hasMainDexRootSet()) {
+    if (mainDexRootSet != null) {
       setMainDexRootSet(mainDexRootSet.withoutPrunedItems(prunedItems));
     }
   }
diff --git a/src/main/java/com/android/tools/r8/graph/GraphLens.java b/src/main/java/com/android/tools/r8/graph/GraphLens.java
index 9236d1f..f0675ba 100644
--- a/src/main/java/com/android/tools/r8/graph/GraphLens.java
+++ b/src/main/java/com/android/tools/r8/graph/GraphLens.java
@@ -284,10 +284,6 @@
 
   public abstract DexField getOriginalFieldSignature(DexField field);
 
-  public final DexMember<?, ?> getOriginalMemberSignature(DexMember<?, ?> member) {
-    return member.apply(this::getOriginalFieldSignature, this::getOriginalMethodSignature);
-  }
-
   public final DexMethod getOriginalMethodSignature(DexMethod method) {
     return getOriginalMethodSignature(method, null);
   }
@@ -576,7 +572,7 @@
   }
 
   public <R extends DexReference, T> Map<R, T> rewriteReferenceKeys(
-      Map<R, T> map, BiFunction<R, List<T>, T> merge) {
+      Map<R, T> map, Function<List<T>, T> merge) {
     Map<R, T> result = new IdentityHashMap<>();
     Map<R, List<T>> needsMerge = new IdentityHashMap<>();
     map.forEach(
@@ -597,7 +593,7 @@
         });
     needsMerge.forEach(
         (rewrittenReference, unmergedValues) -> {
-          T mergedValue = merge.apply(rewrittenReference, unmergedValues);
+          T mergedValue = merge.apply(unmergedValues);
           if (mergedValue != null) {
             result.put(rewrittenReference, mergedValue);
           }
diff --git a/src/main/java/com/android/tools/r8/graph/ObjectAllocationInfoCollectionImpl.java b/src/main/java/com/android/tools/r8/graph/ObjectAllocationInfoCollectionImpl.java
index aa5e4c8..459c008 100644
--- a/src/main/java/com/android/tools/r8/graph/ObjectAllocationInfoCollectionImpl.java
+++ b/src/main/java/com/android/tools/r8/graph/ObjectAllocationInfoCollectionImpl.java
@@ -19,10 +19,8 @@
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.IdentityHashMap;
-import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
-import java.util.Map.Entry;
 import java.util.Set;
 import java.util.function.BiConsumer;
 import java.util.function.Consumer;
@@ -146,25 +144,6 @@
     return builder(true, null).rewrittenWithLens(this, definitions, lens).build(definitions);
   }
 
-  public ObjectAllocationInfoCollectionImpl withoutPrunedItems(PrunedItems prunedItems) {
-    if (prunedItems.hasRemovedMethods()) {
-      Iterator<Entry<DexProgramClass, Set<DexEncodedMethod>>> iterator =
-          classesWithAllocationSiteTracking.entrySet().iterator();
-      while (iterator.hasNext()) {
-        Entry<DexProgramClass, Set<DexEncodedMethod>> entry = iterator.next();
-        Set<DexEncodedMethod> allocationSites = entry.getValue();
-        allocationSites.removeIf(
-            allocationSite ->
-                prunedItems.getRemovedMethods().contains(allocationSite.getReference()));
-        if (allocationSites.isEmpty()) {
-          classesWithoutAllocationSiteTracking.add(entry.getKey());
-          iterator.remove();
-        }
-      }
-    }
-    return this;
-  }
-
   public void forEachInstantiatedSubType(
       DexType type,
       Consumer<DexProgramClass> onClass,
diff --git a/src/main/java/com/android/tools/r8/graph/PrunedItems.java b/src/main/java/com/android/tools/r8/graph/PrunedItems.java
index 4f901fd..4489421 100644
--- a/src/main/java/com/android/tools/r8/graph/PrunedItems.java
+++ b/src/main/java/com/android/tools/r8/graph/PrunedItems.java
@@ -55,10 +55,6 @@
     return removedMethods.contains(method) || removedClasses.contains(method.getHolderType());
   }
 
-  public boolean isRemoved(DexReference reference) {
-    return reference.apply(this::isRemoved, this::isRemoved, this::isRemoved);
-  }
-
   public boolean isRemoved(DexType type) {
     return removedClasses.contains(type);
   }
@@ -111,7 +107,7 @@
     private final Set<DexType> noLongerSyntheticItems = Sets.newIdentityHashSet();
     private Set<DexType> removedClasses = Sets.newIdentityHashSet();
     private final Set<DexField> removedFields = Sets.newIdentityHashSet();
-    private Set<DexMethod> removedMethods = Sets.newIdentityHashSet();
+    private final Set<DexMethod> removedMethods = Sets.newIdentityHashSet();
 
     public Builder setPrunedApp(DexApplication prunedApp) {
       this.prunedApp = prunedApp;
@@ -150,11 +146,6 @@
       return this;
     }
 
-    public Builder setRemovedMethods(Set<DexMethod> removedMethods) {
-      this.removedMethods = removedMethods;
-      return this;
-    }
-
     public PrunedItems build() {
       return new PrunedItems(
           prunedApp,
diff --git a/src/main/java/com/android/tools/r8/horizontalclassmerging/HorizontalClassMergerGraphLens.java b/src/main/java/com/android/tools/r8/horizontalclassmerging/HorizontalClassMergerGraphLens.java
index 03a044d..2b12d6d 100644
--- a/src/main/java/com/android/tools/r8/horizontalclassmerging/HorizontalClassMergerGraphLens.java
+++ b/src/main/java/com/android/tools/r8/horizontalclassmerging/HorizontalClassMergerGraphLens.java
@@ -250,7 +250,13 @@
             MutableBidirectionalManyToOneRepresentativeMap<R, R> newMemberSignatures,
             MutableBidirectionalManyToOneRepresentativeMap<R, R> pendingNewMemberSignatureUpdates) {
       newMemberSignatures.removeAll(pendingNewMemberSignatureUpdates.keySet());
-      newMemberSignatures.putAll(pendingNewMemberSignatureUpdates);
+      pendingNewMemberSignatureUpdates.forEachManyToOneMapping(
+          (keys, value, representative) -> {
+            newMemberSignatures.put(keys, value);
+            if (keys.size() > 1) {
+              newMemberSignatures.setRepresentative(value, representative);
+            }
+          });
       pendingNewMemberSignatureUpdates.clear();
     }
 
diff --git a/src/main/java/com/android/tools/r8/ir/code/IRCode.java b/src/main/java/com/android/tools/r8/ir/code/IRCode.java
index f4a2cdc..e5c792f 100644
--- a/src/main/java/com/android/tools/r8/ir/code/IRCode.java
+++ b/src/main/java/com/android/tools/r8/ir/code/IRCode.java
@@ -595,11 +595,7 @@
     for (Instruction instruction : instructions()) {
       if (instruction.outValue != null && instruction.outValue.getType().isClassType()) {
         ClassTypeElement classTypeLattice = instruction.outValue.getType().asClassType();
-        assert !mergedClasses.hasBeenMergedIntoDifferentType(classTypeLattice.getClassType())
-            : "Expected reference to "
-                + classTypeLattice.getClassType().getTypeName()
-                + " to be rewritten at instruction "
-                + instruction.toString();
+        assert !mergedClasses.hasBeenMergedIntoDifferentType(classTypeLattice.getClassType());
         assert !classTypeLattice
             .getInterfaces()
             .anyMatch(
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 6ffe166..07ba0ce 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
@@ -24,7 +24,6 @@
 import com.android.tools.r8.graph.DexTypeList;
 import com.android.tools.r8.graph.GraphLens;
 import com.android.tools.r8.graph.ProgramMethod;
-import com.android.tools.r8.graph.PrunedItems;
 import com.android.tools.r8.ir.analysis.TypeChecker;
 import com.android.tools.r8.ir.analysis.VerifyTypesHelper;
 import com.android.tools.r8.ir.analysis.constant.SparseConditionalConstantPropagation;
@@ -113,12 +112,10 @@
 import com.android.tools.r8.utils.collections.ProgramMethodSet;
 import com.android.tools.r8.utils.collections.SortedProgramMethodSet;
 import com.google.common.base.Suppliers;
-import com.google.common.collect.Sets;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
-import java.util.Set;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.atomic.AtomicBoolean;
@@ -174,7 +171,6 @@
   private DexString highestSortingString;
 
   private List<Action> onWaveDoneActions = null;
-  private final Set<DexMethod> prunedMethodsInWave = Sets.newIdentityHashSet();
 
   private final List<DexString> neverMergePrefixes;
   // Use AtomicBoolean to satisfy TSAN checking (see b/153714743).
@@ -330,10 +326,6 @@
     this(AppView.createForD8(appInfo), timing, printer);
   }
 
-  public Inliner getInliner() {
-    return inliner;
-  }
-
   private void synthesizeBridgesForNestBasedAccessesOnClasspath(
       D8MethodProcessor methodProcessor, ExecutorService executorService)
       throws ExecutionException {
@@ -718,7 +710,7 @@
     appView.withArgumentPropagator(
         argumentPropagator ->
             argumentPropagator.tearDownCodeScanner(
-                this, postMethodProcessorBuilder, executorService, timing));
+                postMethodProcessorBuilder, executorService, timing));
     appView.withCallSiteOptimizationInfoPropagator(
         callSiteOptimizationInfoPropagator ->
             callSiteOptimizationInfoPropagator.enqueueMethodsForReprocessing(
@@ -852,8 +844,7 @@
     onWaveDoneActions = Collections.synchronizedList(new ArrayList<>());
   }
 
-  private void waveDone(ProgramMethodSet wave, ExecutorService executorService)
-      throws ExecutionException {
+  private void waveDone(ProgramMethodSet wave) {
     delayedOptimizationFeedback.refineAppInfoWithLiveness(appView.appInfo().withLiveness());
     delayedOptimizationFeedback.updateVisibleOptimizationInfo();
     if (options.enableFieldAssignmentTracker) {
@@ -867,15 +858,6 @@
     assert delayedOptimizationFeedback.noUpdatesLeft();
     onWaveDoneActions.forEach(com.android.tools.r8.utils.Action::execute);
     onWaveDoneActions = null;
-    if (!prunedMethodsInWave.isEmpty()) {
-      appView.pruneItems(
-          PrunedItems.builder()
-              .setRemovedMethods(prunedMethodsInWave)
-              .setPrunedApp(appView.appInfo().app())
-              .build(),
-          executorService);
-      prunedMethodsInWave.clear();
-    }
   }
 
   public void addWaveDoneAction(com.android.tools.r8.utils.Action action) {
@@ -1979,13 +1961,9 @@
     appView.withArgumentPropagator(argumentPropagator -> argumentPropagator.onMethodPruned(method));
     enumUnboxer.onMethodPruned(method);
     outliner.onMethodPruned(method);
-    if (classStaticizer != null) {
-      classStaticizer.onMethodPruned(method);
-    }
     if (inliner != null) {
       inliner.onMethodPruned(method);
     }
-    prunedMethodsInWave.add(method.getReference());
   }
 
   /**
@@ -1999,9 +1977,6 @@
         argumentPropagator -> argumentPropagator.onMethodCodePruned(method));
     enumUnboxer.onMethodCodePruned(method);
     outliner.onMethodCodePruned(method);
-    if (classStaticizer != null) {
-      classStaticizer.onMethodCodePruned(method);
-    }
     if (inliner != null) {
       inliner.onMethodCodePruned(method);
     }
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/PrimaryMethodProcessor.java b/src/main/java/com/android/tools/r8/ir/conversion/PrimaryMethodProcessor.java
index 9998d53..bea221a 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/PrimaryMethodProcessor.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/PrimaryMethodProcessor.java
@@ -23,6 +23,7 @@
 import java.util.Set;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.ExecutorService;
+import java.util.function.Consumer;
 
 /**
  * A {@link MethodProcessor} that processes methods in the whole program in a bottom-up manner,
@@ -35,12 +36,6 @@
     void notifyWaveStart(ProgramMethodSet wave);
   }
 
-  interface WaveDoneAction {
-
-    void notifyWaveDone(ProgramMethodSet wave, ExecutorService executorService)
-        throws ExecutionException;
-  }
-
   private final AppView<?> appView;
   private final CallSiteInformation callSiteInformation;
   private final Deque<SortedProgramMethodSet> waves;
@@ -115,7 +110,7 @@
   <E extends Exception> void forEachMethod(
       MethodAction<E> consumer,
       WaveStartAction waveStartAction,
-      WaveDoneAction waveDoneAction,
+      Consumer<ProgramMethodSet> waveDone,
       Timing timing,
       ExecutorService executorService)
       throws ExecutionException {
@@ -138,7 +133,7 @@
                 },
                 executorService);
         merger.add(timings);
-        waveDoneAction.notifyWaveDone(wave, executorService);
+        waveDone.accept(wave);
         prepareForWaveExtensionProcessing();
       } while (!wave.isEmpty());
     }
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 f0de604..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
@@ -98,8 +98,6 @@
   // pruned when the wave ends.
   private final Map<DexProgramClass, ProgramMethodSet> singleCallerInlinedMethodsInWave =
       new ConcurrentHashMap<>();
-  private final Set<DexMethod> singleCallerInlinedPrunedMethodsForTesting =
-      Sets.newIdentityHashSet();
 
   private final AvailableApiExceptions availableApiExceptions;
 
@@ -1270,13 +1268,10 @@
         (clazz, singleCallerInlinedMethodsForClass) -> {
           // Convert and remove virtual single caller inlined methods to abstract or throw null.
           singleCallerInlinedMethodsForClass.removeIf(
-              method -> {
-                // TODO(b/203188583): Enable pruning of methods with generic signatures. For this to
-                //  work we need to pass in a seed to GenericSignatureContextBuilder.create in R8.
-                if (method.getDefinition().belongsToVirtualPool()
-                    || method.getDefinition().getGenericSignature().hasSignature()) {
-                  method.convertToAbstractOrThrowNullMethod(appView);
-                  converter.onMethodCodePruned(method);
+              singleCallerInlinedMethod -> {
+                if (singleCallerInlinedMethod.getDefinition().belongsToVirtualPool() || true) {
+                  singleCallerInlinedMethod.convertToAbstractOrThrowNullMethod(appView);
+                  converter.onMethodCodePruned(singleCallerInlinedMethod);
                   return true;
                 }
                 return false;
@@ -1289,10 +1284,7 @@
                 .removeMethods(
                     singleCallerInlinedMethodsForClass.toDefinitionSet(
                         SetUtils::newIdentityHashSet));
-            for (ProgramMethod method : singleCallerInlinedMethodsForClass) {
-              converter.onMethodPruned(method);
-              singleCallerInlinedPrunedMethodsForTesting.add(method.getReference());
-            }
+            singleCallerInlinedMethodsForClass.forEach(converter::onMethodPruned);
           }
         });
     singleCallerInlinedMethodsInWave.clear();
@@ -1310,9 +1302,4 @@
     }
     return true;
   }
-
-  public boolean verifyIsPrunedDueToSingleCallerInlining(DexMethod method) {
-    assert singleCallerInlinedPrunedMethodsForTesting.contains(method);
-    return true;
-  }
 }
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/staticizer/ClassStaticizer.java b/src/main/java/com/android/tools/r8/ir/optimize/staticizer/ClassStaticizer.java
index 30b0da1..748253f 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/staticizer/ClassStaticizer.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/staticizer/ClassStaticizer.java
@@ -105,8 +105,6 @@
   final Map<CandidateInfo, LongLivedProgramMethodSetBuilder<?>> referencedFrom =
       new ConcurrentHashMap<>();
 
-  private final Set<DexMethod> prunedMethods = Sets.newIdentityHashSet();
-
   // The map storing all the potential candidates for staticizing.
   final ConcurrentHashMap<DexType, CandidateInfo> candidates = new ConcurrentHashMap<>();
 
@@ -116,14 +114,6 @@
     this.converter = converter;
   }
 
-  public void onMethodPruned(ProgramMethod method) {
-    onMethodCodePruned(method);
-  }
-
-  public void onMethodCodePruned(ProgramMethod method) {
-    prunedMethods.add(method.getReference());
-  }
-
   public void prepareForPrimaryOptimizationPass(GraphLens graphLensForPrimaryOptimizationPass) {
     collectCandidates();
     this.graphLensForOptimizationPass = graphLensForPrimaryOptimizationPass;
@@ -139,11 +129,8 @@
         .values()
         .forEach(
             referencedFromBuilder ->
-                referencedFromBuilder
-                    .removeAll(prunedMethods)
-                    .rewrittenWithLens(graphLensForSecondaryOptimizationPass));
+                referencedFromBuilder.rewrittenWithLens(graphLensForSecondaryOptimizationPass));
     this.graphLensForOptimizationPass = graphLensForSecondaryOptimizationPass;
-    prunedMethods.clear();
   }
 
   // Before doing any usage-based analysis we collect a set of classes that can be
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/staticizer/StaticizingProcessor.java b/src/main/java/com/android/tools/r8/ir/optimize/staticizer/StaticizingProcessor.java
index 806b057..c73132f 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/staticizer/StaticizingProcessor.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/staticizer/StaticizingProcessor.java
@@ -237,6 +237,9 @@
         referencedFrom =
             referencedFromBuilder
                 .rewrittenWithLens(appView)
+                .removeIf(
+                    appView,
+                    method -> method.getOptimizationInfo().hasBeenInlinedIntoSingleCallSite())
                 .build(appView);
         materializedReferencedFromCollections.put(info, referencedFrom);
       } else {
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 45f4984..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
@@ -130,7 +130,6 @@
   }
 
   public void tearDownCodeScanner(
-      IRConverter converter,
       PostMethodProcessor.Builder postMethodProcessorBuilder,
       ExecutorService executorService,
       Timing timing)
@@ -153,7 +152,6 @@
     Map<Set<DexProgramClass>, DexMethodSignatureSet> interfaceDispatchOutsideProgram =
         new IdentityHashMap<>();
     populateParameterOptimizationInfo(
-        converter,
         immediateSubtypingInfo,
         stronglyConnectedProgramComponents,
         (stronglyConnectedProgramComponent, signature) -> {
@@ -191,7 +189,6 @@
    * optimization info.
    */
   private void populateParameterOptimizationInfo(
-      IRConverter converter,
       ImmediateProgramSubtypingInfo immediateSubtypingInfo,
       List<Set<DexProgramClass>> stronglyConnectedProgramComponents,
       BiConsumer<Set<DexProgramClass>, DexMethodSignature> interfaceDispatchOutsideProgram,
@@ -212,7 +209,7 @@
             reprocessingCriteriaCollection,
             stronglyConnectedProgramComponents,
             interfaceDispatchOutsideProgram)
-        .populateOptimizationInfo(converter, executorService, timing);
+        .populateOptimizationInfo(executorService, timing);
     reprocessingCriteriaCollection = null;
     timing.end();
   }
diff --git a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/ArgumentPropagatorOptimizationInfoPopulator.java b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/ArgumentPropagatorOptimizationInfoPopulator.java
index e050de8..5470ed5 100644
--- a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/ArgumentPropagatorOptimizationInfoPopulator.java
+++ b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/ArgumentPropagatorOptimizationInfoPopulator.java
@@ -14,7 +14,6 @@
 import com.android.tools.r8.graph.ProgramMethod;
 import com.android.tools.r8.ir.analysis.type.DynamicType;
 import com.android.tools.r8.ir.analysis.type.Nullability;
-import com.android.tools.r8.ir.conversion.IRConverter;
 import com.android.tools.r8.ir.optimize.info.ConcreteCallSiteOptimizationInfo;
 import com.android.tools.r8.ir.optimize.info.MethodOptimizationInfo;
 import com.android.tools.r8.ir.optimize.info.OptimizationFeedback;
@@ -83,8 +82,7 @@
    * Computes an over-approximation of each parameter's value and type and stores the result in
    * {@link com.android.tools.r8.ir.optimize.info.MethodOptimizationInfo}.
    */
-  void populateOptimizationInfo(
-      IRConverter converter, ExecutorService executorService, Timing timing)
+  void populateOptimizationInfo(ExecutorService executorService, Timing timing)
       throws ExecutionException {
     // TODO(b/190154391): Propagate argument information to handle virtual dispatch.
     // TODO(b/190154391): To deal with arguments that are themselves passed as arguments to invoke
@@ -100,7 +98,7 @@
 
     // Solve the parameter flow constraints.
     timing.begin("Solve flow constraints");
-    new InParameterFlowPropagator(appView, converter, methodStates).run(executorService);
+    new InParameterFlowPropagator(appView, methodStates).run(executorService);
     timing.end();
 
     // The information stored on each method is now sound, and can be used as optimization info.
diff --git a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/propagation/InParameterFlowPropagator.java b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/propagation/InParameterFlowPropagator.java
index 9b10015..9b583c7 100644
--- a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/propagation/InParameterFlowPropagator.java
+++ b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/propagation/InParameterFlowPropagator.java
@@ -12,7 +12,6 @@
 import com.android.tools.r8.graph.DexProgramClass;
 import com.android.tools.r8.graph.DexType;
 import com.android.tools.r8.graph.ProgramMethod;
-import com.android.tools.r8.ir.conversion.IRConverter;
 import com.android.tools.r8.optimize.argumentpropagation.codescanner.ConcreteMethodState;
 import com.android.tools.r8.optimize.argumentpropagation.codescanner.ConcreteMonomorphicMethodState;
 import com.android.tools.r8.optimize.argumentpropagation.codescanner.ConcreteParameterState;
@@ -43,15 +42,11 @@
 public class InParameterFlowPropagator {
 
   final AppView<AppInfoWithLiveness> appView;
-  final IRConverter converter;
   final MethodStateCollectionByReference methodStates;
 
   public InParameterFlowPropagator(
-      AppView<AppInfoWithLiveness> appView,
-      IRConverter converter,
-      MethodStateCollectionByReference methodStates) {
+      AppView<AppInfoWithLiveness> appView, MethodStateCollectionByReference methodStates) {
     this.appView = appView;
-    this.converter = converter;
     this.methodStates = methodStates;
   }
 
@@ -211,16 +206,6 @@
       ParameterNode node = getOrCreateParameterNode(method, parameterIndex, methodState);
       for (MethodParameter inParameter : concreteParameterState.getInParameters()) {
         ProgramMethod enclosingMethod = getEnclosingMethod(inParameter);
-        if (enclosingMethod == null) {
-          // This is a parameter of a single caller inlined method. Since this method has been
-          // pruned, the call from inside the method no longer exists, and we can therefore safely
-          // skip it.
-          assert converter
-              .getInliner()
-              .verifyIsPrunedDueToSingleCallerInlining(inParameter.getMethod());
-          continue;
-        }
-
         MethodState enclosingMethodState = getMethodState(enclosingMethod);
         if (enclosingMethodState.isBottom()) {
           // The current method is called from a dead method; no need to propagate any information
diff --git a/src/main/java/com/android/tools/r8/shaking/AppInfoWithLiveness.java b/src/main/java/com/android/tools/r8/shaking/AppInfoWithLiveness.java
index 04728fb..b0f3ea9 100644
--- a/src/main/java/com/android/tools/r8/shaking/AppInfoWithLiveness.java
+++ b/src/main/java/com/android/tools/r8/shaking/AppInfoWithLiveness.java
@@ -355,7 +355,7 @@
         pruneMethods(previous.liveMethods, prunedItems, executorService, futures),
         previous.fieldAccessInfoCollection,
         previous.methodAccessInfoCollection,
-        previous.objectAllocationInfoCollection.withoutPrunedItems(prunedItems),
+        previous.objectAllocationInfoCollection,
         previous.callSites,
         extendPinnedItems(previous, prunedItems.getAdditionalPinnedItems()),
         previous.mayHaveSideEffects,
@@ -439,7 +439,6 @@
   private static <T> Set<T> pruneItems(
       Set<T> items, Set<T> removedItems, ExecutorService executorService, List<Future<?>> futures) {
     if (!removedItems.isEmpty()) {
-
       futures.add(
           ThreadUtils.processAsynchronously(
               () -> {
@@ -1272,14 +1271,10 @@
         lens.rewriteCallSites(callSites, definitionSupplier),
         keepInfo.rewrite(definitionSupplier, lens, application.options),
         // Take any rule in case of collisions.
-        lens.rewriteReferenceKeys(mayHaveSideEffects, (reference, rules) -> ListUtils.first(rules)),
-        // Take the assume rule from the representative in case of collisions.
-        lens.rewriteReferenceKeys(
-            noSideEffects,
-            (reference, rules) -> noSideEffects.get(lens.getOriginalMemberSignature(reference))),
-        lens.rewriteReferenceKeys(
-            assumedValues,
-            (reference, rules) -> assumedValues.get(lens.getOriginalMemberSignature(reference))),
+        lens.rewriteReferenceKeys(mayHaveSideEffects, ListUtils::first),
+        // Drop assume rules in case of collisions.
+        lens.rewriteReferenceKeys(noSideEffects, rules -> null),
+        lens.rewriteReferenceKeys(assumedValues, rules -> null),
         lens.rewriteReferences(alwaysInline),
         lens.rewriteReferences(neverInline),
         lens.rewriteReferences(neverInlineDueToSingleCaller),
diff --git a/src/main/java/com/android/tools/r8/shaking/Enqueuer.java b/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
index 2526bb9..494cf92 100644
--- a/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
+++ b/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
@@ -129,6 +129,7 @@
 import com.android.tools.r8.shaking.ScopedDexMethodSet.AddMethodIfMoreVisibleResult;
 import com.android.tools.r8.synthesis.SyntheticItems.SynthesizingContextOracle;
 import com.android.tools.r8.utils.Action;
+import com.android.tools.r8.utils.BooleanBox;
 import com.android.tools.r8.utils.InternalOptions;
 import com.android.tools.r8.utils.IteratorUtils;
 import com.android.tools.r8.utils.OptionalBool;
@@ -3725,11 +3726,11 @@
                 : missingClassesBuilder.assertNoMissingClasses(appView),
             SetUtils.mapIdentityHashSet(liveTypes.getItems(), DexProgramClass::getType),
             Enqueuer.toDescriptorSet(targetedMethods.getItems()),
-            failedMethodResolutionTargets,
-            failedFieldResolutionTargets,
-            bootstrapMethods,
-            methodsTargetedByInvokeDynamic,
-            virtualMethodsTargetedByInvokeDirect,
+            Collections.unmodifiableSet(failedMethodResolutionTargets),
+            Collections.unmodifiableSet(failedFieldResolutionTargets),
+            Collections.unmodifiableSet(bootstrapMethods),
+            Collections.unmodifiableSet(methodsTargetedByInvokeDynamic),
+            Collections.unmodifiableSet(virtualMethodsTargetedByInvokeDirect),
             toDescriptorSet(liveMethods.getItems()),
             // Filter out library fields and pinned fields, because these are read by default.
             fieldAccessInfoCollection,
@@ -3771,15 +3772,16 @@
     if (methods.isEmpty() || interfaceProcessor == null) {
       return methods;
     }
-    Set<DexMethod> companionMethods = Sets.newIdentityHashSet();
+    BooleanBox changed = new BooleanBox(false);
+    ImmutableSet.Builder<DexMethod> builder = ImmutableSet.builder();
     interfaceProcessor.forEachMethodToMove(
         (method, companion) -> {
           if (methods.contains(method)) {
-            companionMethods.add(companion);
+            changed.set(true);
+            builder.add(companion);
           }
         });
-    methods.addAll(companionMethods);
-    return methods;
+    return changed.isTrue() ? builder.addAll(methods).build() : methods;
   }
 
   private boolean verifyReferences(DexApplication app) {
@@ -3848,11 +3850,11 @@
 
   private static <D extends DexEncodedMember<D, R>, R extends DexMember<D, R>>
       Set<R> toDescriptorSet(Set<D> set) {
-    Set<R> result = Sets.newIdentityHashSet();
+    ImmutableSet.Builder<R> builder = new ImmutableSet.Builder<>();
     for (D item : set) {
-      result.add(item.getReference());
+      builder.add(item.getReference());
     }
-    return result;
+    return builder.build();
   }
 
   private static Object2BooleanMap<DexMember<?, ?>> joinIdentifierNameStrings(
diff --git a/src/main/java/com/android/tools/r8/shaking/MinimumKeepInfoCollection.java b/src/main/java/com/android/tools/r8/shaking/MinimumKeepInfoCollection.java
index 8062beb..ec1594a 100644
--- a/src/main/java/com/android/tools/r8/shaking/MinimumKeepInfoCollection.java
+++ b/src/main/java/com/android/tools/r8/shaking/MinimumKeepInfoCollection.java
@@ -17,7 +17,6 @@
 import com.android.tools.r8.graph.ProgramDefinition;
 import com.android.tools.r8.graph.ProgramField;
 import com.android.tools.r8.graph.ProgramMethod;
-import com.android.tools.r8.graph.PrunedItems;
 import com.android.tools.r8.shaking.KeepInfo.Joiner;
 import com.android.tools.r8.utils.MapUtils;
 import java.util.Collections;
@@ -132,10 +131,6 @@
         });
   }
 
-  public void pruneItems(PrunedItems prunedItems) {
-    minimumKeepInfo.keySet().removeIf(prunedItems::isRemoved);
-  }
-
   public KeepClassInfo.Joiner remove(DexType clazz) {
     return (KeepClassInfo.Joiner) minimumKeepInfo.remove(clazz);
   }
diff --git a/src/main/java/com/android/tools/r8/shaking/RootSetUtils.java b/src/main/java/com/android/tools/r8/shaking/RootSetUtils.java
index 03cff10..b105a80 100644
--- a/src/main/java/com/android/tools/r8/shaking/RootSetUtils.java
+++ b/src/main/java/com/android/tools/r8/shaking/RootSetUtils.java
@@ -1740,17 +1740,6 @@
           });
     }
 
-    public void pruneItems(PrunedItems prunedItems) {
-      MinimumKeepInfoCollection unconditionalMinimumKeepInfo =
-          getDependentMinimumKeepInfo().getUnconditionalMinimumKeepInfoOrDefault(null);
-      if (unconditionalMinimumKeepInfo != null) {
-        unconditionalMinimumKeepInfo.pruneItems(prunedItems);
-        if (unconditionalMinimumKeepInfo.isEmpty()) {
-          getDependentMinimumKeepInfo().remove(UnconditionalKeepInfoEvent.get());
-        }
-      }
-    }
-
     void shouldNotBeMinified(ProgramDefinition definition) {
       getDependentMinimumKeepInfo()
           .getOrCreateUnconditionalMinimumKeepInfoFor(definition.getReference())
diff --git a/src/main/java/com/android/tools/r8/shaking/VerticalClassMerger.java b/src/main/java/com/android/tools/r8/shaking/VerticalClassMerger.java
index c44bdc9..e157ff8 100644
--- a/src/main/java/com/android/tools/r8/shaking/VerticalClassMerger.java
+++ b/src/main/java/com/android/tools/r8/shaking/VerticalClassMerger.java
@@ -1012,13 +1012,8 @@
         DexEncodedMethod shadowedBy = findMethodInTarget(virtualMethod);
         if (shadowedBy != null) {
           if (virtualMethod.isAbstract()) {
-            // Remove abstract/interface methods that are shadowed. The identity mapping below is
-            // needed to ensure we correctly fixup the mapping in case the signature refers to
-            // merged classes.
-            deferredRenamings
-                .map(virtualMethod.getReference(), shadowedBy.getReference())
-                .map(shadowedBy.getReference(), shadowedBy.getReference())
-                .recordMerge(virtualMethod.getReference(), shadowedBy.getReference());
+            // Remove abstract/interface methods that are shadowed.
+            deferredRenamings.map(virtualMethod.getReference(), shadowedBy.getReference());
 
             // The override now corresponds to the method in the parent, so unset its synthetic flag
             // if the method in the parent is not synthetic.
diff --git a/src/main/java/com/android/tools/r8/shaking/VerticalClassMergerGraphLens.java b/src/main/java/com/android/tools/r8/shaking/VerticalClassMergerGraphLens.java
index 0464966..ea9f971 100644
--- a/src/main/java/com/android/tools/r8/shaking/VerticalClassMergerGraphLens.java
+++ b/src/main/java/com/android/tools/r8/shaking/VerticalClassMergerGraphLens.java
@@ -16,10 +16,9 @@
 import com.android.tools.r8.graph.classmerging.VerticallyMergedClasses;
 import com.android.tools.r8.ir.code.Invoke.Type;
 import com.android.tools.r8.utils.IterableUtils;
-import com.android.tools.r8.utils.collections.BidirectionalManyToOneRepresentativeHashMap;
 import com.android.tools.r8.utils.collections.BidirectionalManyToOneRepresentativeMap;
 import com.android.tools.r8.utils.collections.BidirectionalOneToOneHashMap;
-import com.android.tools.r8.utils.collections.MutableBidirectionalManyToOneRepresentativeMap;
+import com.android.tools.r8.utils.collections.BidirectionalOneToOneMap;
 import com.android.tools.r8.utils.collections.MutableBidirectionalOneToOneMap;
 import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.Iterables;
@@ -75,7 +74,7 @@
       Set<DexMethod> mergedMethods,
       Map<DexType, Map<DexMethod, GraphLensLookupResultProvider>>
           contextualVirtualToDirectMethodMaps,
-      BidirectionalManyToOneRepresentativeMap<DexMethod, DexMethod> newMethodSignatures,
+      BidirectionalOneToOneMap<DexMethod, DexMethod> newMethodSignatures,
       Map<DexMethod, DexMethod> originalMethodSignaturesForBridges) {
     super(appView, fieldMap, methodMap, mergedClasses.getForwardMap(), newMethodSignatures);
     this.appView = appView;
@@ -165,8 +164,8 @@
     private final Map<DexType, Map<DexMethod, GraphLensLookupResultProvider>>
         contextualVirtualToDirectMethodMaps = new IdentityHashMap<>();
 
-    private final MutableBidirectionalManyToOneRepresentativeMap<DexMethod, DexMethod>
-        newMethodSignatures = BidirectionalManyToOneRepresentativeHashMap.newIdentityHashMap();
+    private final MutableBidirectionalOneToOneMap<DexMethod, DexMethod> newMethodSignatures =
+        new BidirectionalOneToOneHashMap<>();
     private final Map<DexMethod, DexMethod> originalMethodSignaturesForBridges =
         new IdentityHashMap<>();
 
@@ -209,17 +208,12 @@
               context);
         }
       }
-      builder.newMethodSignatures.forEachManyToOneMapping(
-          (originalMethodSignatures, renamedMethodSignature, representative) -> {
-            DexMethod methodSignatureAfterClassMerging =
-                builder.getMethodSignatureAfterClassMerging(renamedMethodSignature, mergedClasses);
-            newBuilder.newMethodSignatures.put(
-                originalMethodSignatures, methodSignatureAfterClassMerging);
-            if (originalMethodSignatures.size() > 1) {
-              newBuilder.newMethodSignatures.setRepresentative(
-                  methodSignatureAfterClassMerging, representative);
-            }
-          });
+      builder.newMethodSignatures.forEach(
+          (originalMethodSignature, renamedMethodSignature) ->
+              newBuilder.recordMove(
+                  originalMethodSignature,
+                  builder.getMethodSignatureAfterClassMerging(
+                      renamedMethodSignature, mergedClasses)));
       for (Map.Entry<DexMethod, DexMethod> entry :
           builder.originalMethodSignaturesForBridges.entrySet()) {
         newBuilder.recordCreationOfBridgeMethod(
@@ -323,12 +317,6 @@
       return this;
     }
 
-    public void recordMerge(DexMethod from, DexMethod to) {
-      newMethodSignatures.put(from, to);
-      newMethodSignatures.put(to, to);
-      newMethodSignatures.setRepresentative(to, to);
-    }
-
     public void recordMove(DexMethod from, DexMethod to) {
       newMethodSignatures.put(from, to);
     }
@@ -348,18 +336,7 @@
       fieldMap.putAll(builder.fieldMap);
       methodMap.putAll(builder.methodMap);
       mergedMethodsBuilder.addAll(builder.mergedMethodsBuilder.build());
-      builder.newMethodSignatures.forEachManyToOneMapping(
-          (keys, value, representative) -> {
-            if (newMethodSignatures.containsValue(value)
-                && !newMethodSignatures.hasExplicitRepresentativeKey(value)) {
-              newMethodSignatures.setRepresentative(
-                  value, newMethodSignatures.getRepresentativeKey(value));
-            }
-            newMethodSignatures.put(keys, value);
-            if (keys.size() > 1 && !newMethodSignatures.hasExplicitRepresentativeKey(value)) {
-              newMethodSignatures.setRepresentative(value, representative);
-            }
-          });
+      newMethodSignatures.putAll(builder.newMethodSignatures);
       originalMethodSignaturesForBridges.putAll(builder.originalMethodSignaturesForBridges);
       for (DexType context : builder.contextualVirtualToDirectMethodMaps.keySet()) {
         Map<DexMethod, GraphLensLookupResultProvider> current =
diff --git a/src/main/java/com/android/tools/r8/utils/SetUtils.java b/src/main/java/com/android/tools/r8/utils/SetUtils.java
index f363c3da..a7305a2 100644
--- a/src/main/java/com/android/tools/r8/utils/SetUtils.java
+++ b/src/main/java/com/android/tools/r8/utils/SetUtils.java
@@ -34,19 +34,18 @@
     return result;
   }
 
-  @SafeVarargs
-  public static <T> HashSet<T> newHashSet(T... elements) {
-    HashSet<T> result = new HashSet<>(elements.length);
-    Collections.addAll(result, elements);
-    return result;
-  }
-
   public static <T> Set<T> newIdentityHashSet(T element) {
     Set<T> result = Sets.newIdentityHashSet();
     result.add(element);
     return result;
   }
 
+  public static <T> Set<T> newIdentityHashSet(T[] elements) {
+    Set<T> result = Sets.newIdentityHashSet();
+    Collections.addAll(result, elements);
+    return result;
+  }
+
   public static <T> Set<T> newIdentityHashSet(ForEachable<T> forEachable) {
     Set<T> result = Sets.newIdentityHashSet();
     forEachable.forEach(result::add);
diff --git a/src/main/java/com/android/tools/r8/utils/collections/BidirectionalManyToOneRepresentativeHashMap.java b/src/main/java/com/android/tools/r8/utils/collections/BidirectionalManyToOneRepresentativeHashMap.java
index 0887329..bdd70c8 100644
--- a/src/main/java/com/android/tools/r8/utils/collections/BidirectionalManyToOneRepresentativeHashMap.java
+++ b/src/main/java/com/android/tools/r8/utils/collections/BidirectionalManyToOneRepresentativeHashMap.java
@@ -81,17 +81,6 @@
   }
 
   @Override
-  public void putAll(BidirectionalManyToOneRepresentativeMap<K, V> map) {
-    map.forEachManyToOneMapping(
-        (keys, value, representative) -> {
-          put(keys, value);
-          if (keys.size() > 1) {
-            setRepresentative(value, representative);
-          }
-        });
-  }
-
-  @Override
   public V remove(K key) {
     V value = super.remove(key);
     if (hasExplicitRepresentativeKey(value)) {
diff --git a/src/main/java/com/android/tools/r8/utils/collections/MutableBidirectionalManyToOneRepresentativeMap.java b/src/main/java/com/android/tools/r8/utils/collections/MutableBidirectionalManyToOneRepresentativeMap.java
index b80cc5b..24f91ac 100644
--- a/src/main/java/com/android/tools/r8/utils/collections/MutableBidirectionalManyToOneRepresentativeMap.java
+++ b/src/main/java/com/android/tools/r8/utils/collections/MutableBidirectionalManyToOneRepresentativeMap.java
@@ -8,8 +8,6 @@
 public interface MutableBidirectionalManyToOneRepresentativeMap<K, V>
     extends MutableBidirectionalManyToOneMap<K, V>, BidirectionalManyToOneRepresentativeMap<K, V> {
 
-  void putAll(BidirectionalManyToOneRepresentativeMap<K, V> map);
-
   K removeRepresentativeFor(V value);
 
   void setRepresentative(V value, K representative);
diff --git a/src/test/java/com/android/tools/r8/cf/bootstrap/BootstrapCurrentEqualityTest.java b/src/test/java/com/android/tools/r8/cf/bootstrap/BootstrapCurrentEqualityTest.java
index cdecb76..d1dc197 100644
--- a/src/test/java/com/android/tools/r8/cf/bootstrap/BootstrapCurrentEqualityTest.java
+++ b/src/test/java/com/android/tools/r8/cf/bootstrap/BootstrapCurrentEqualityTest.java
@@ -64,8 +64,8 @@
   @BeforeClass
   public static void beforeAll() throws Exception {
     if (data().stream().count() > 0) {
-      r8R8Release = compileR8(CompilationMode.RELEASE);
       r8R8Debug = compileR8(CompilationMode.DEBUG);
+      r8R8Release = compileR8(CompilationMode.RELEASE);
     }
   }
 
diff --git a/src/test/java/com/android/tools/r8/classmerging/vertical/VerticalClassMergerTest.java b/src/test/java/com/android/tools/r8/classmerging/vertical/VerticalClassMergerTest.java
index 7e98cdd..699bb50 100644
--- a/src/test/java/com/android/tools/r8/classmerging/vertical/VerticalClassMergerTest.java
+++ b/src/test/java/com/android/tools/r8/classmerging/vertical/VerticalClassMergerTest.java
@@ -35,7 +35,6 @@
 import com.android.tools.r8.utils.AndroidApp.Builder;
 import com.android.tools.r8.utils.FileUtils;
 import com.android.tools.r8.utils.InternalOptions;
-import com.android.tools.r8.utils.SetUtils;
 import com.android.tools.r8.utils.StringUtils;
 import com.android.tools.r8.utils.codeinspector.ClassSubject;
 import com.android.tools.r8.utils.codeinspector.CodeInspector;
@@ -1066,17 +1065,15 @@
         };
     // SimpleInterface cannot be merged into SimpleInterfaceImpl because SimpleInterfaceImpl
     // is in a different package and is not public.
-    Set<String> preservedClassNames =
-        SetUtils.newHashSet(
+    ImmutableSet<String> preservedClassNames =
+        ImmutableSet.of(
             "classmerging.SimpleInterfaceAccessTest",
+            "classmerging.SimpleInterfaceAccessTest$1",
             "classmerging.SimpleInterfaceAccessTest$SimpleInterface",
             "classmerging.SimpleInterfaceAccessTest$OtherSimpleInterface",
             "classmerging.SimpleInterfaceAccessTest$OtherSimpleInterfaceImpl",
             "classmerging.pkg.SimpleInterfaceImplRetriever",
             "classmerging.pkg.SimpleInterfaceImplRetriever$SimpleInterfaceImpl");
-    if (parameters.isCfRuntime()) {
-      preservedClassNames.add("classmerging.SimpleInterfaceAccessTest$1");
-    }
     runTest(
         testForR8(parameters.getBackend())
             .addKeepRules(getProguardConfig(EXAMPLE_KEEP))
diff --git a/src/test/java/com/android/tools/r8/regress/b69825683/Regress69825683Test.java b/src/test/java/com/android/tools/r8/regress/b69825683/Regress69825683Test.java
index 01d1c30..7138094 100644
--- a/src/test/java/com/android/tools/r8/regress/b69825683/Regress69825683Test.java
+++ b/src/test/java/com/android/tools/r8/regress/b69825683/Regress69825683Test.java
@@ -62,13 +62,14 @@
 
     List<FoundClassSubject> classes = inspector.allClasses();
 
-    // Check that the synthetic class is still present when generating class files.
-    assertEquals(parameters.isCfRuntime() ? 3 : 2, classes.size());
+    // Check that the synthetic class is still present.
+    assertEquals(3, classes.size());
     assertEquals(
-        parameters.isCfRuntime(),
+        1,
         classes.stream()
             .map(FoundClassSubject::getOriginalName)
-            .anyMatch(name -> name.endsWith("$1")));
+            .filter(name -> name.endsWith("$1"))
+            .count());
   }
 
   @Test
@@ -93,12 +94,13 @@
 
     List<FoundClassSubject> classes = inspector.allClasses();
 
-    // The synthetic class is still present when generating class files.
-    assertEquals(parameters.isCfRuntime() ? 3 : 2, classes.size());
+    // Check that the synthetic class is still present.
+    assertEquals(3, classes.size());
     assertEquals(
-        parameters.isCfRuntime(),
+        1,
         classes.stream()
             .map(FoundClassSubject::getOriginalName)
-            .anyMatch(name -> name.endsWith("$1")));
+            .filter(name -> name.endsWith("$1"))
+            .count());
   }
 }
diff --git a/src/test/java/com/android/tools/r8/shaking/assumenosideeffects/StringBuildersAfterAssumenosideeffectsTest.java b/src/test/java/com/android/tools/r8/shaking/assumenosideeffects/StringBuildersAfterAssumenosideeffectsTest.java
index b80febc..2787932 100644
--- a/src/test/java/com/android/tools/r8/shaking/assumenosideeffects/StringBuildersAfterAssumenosideeffectsTest.java
+++ b/src/test/java/com/android/tools/r8/shaking/assumenosideeffects/StringBuildersAfterAssumenosideeffectsTest.java
@@ -28,7 +28,7 @@
 
   @Parameterized.Parameters(name = "{0}")
   public static TestParametersCollection data() {
-    return getTestParameters().withAllRuntimesAndApiLevels().build();
+    return getTestParameters().withAllRuntimes().build();
   }
 
   private final TestParameters parameters;
@@ -51,7 +51,7 @@
             "  void info(...);",
             "}")
         .noMinification()
-        .setMinApi(parameters.getApiLevel())
+        .setMinApi(parameters.getRuntime())
         .run(parameters.getRuntime(), MAIN)
         .assertSuccessWithOutput(EXPECTED)
         .inspect(this::inspect);