Remove uses of MethodAccessInfoCollection after final tree shaking

Change-Id: Ibdedf96c0056c6eb82484c25117c69a09ea85d86
diff --git a/src/main/java/com/android/tools/r8/R8.java b/src/main/java/com/android/tools/r8/R8.java
index 81b1687..5b08837 100644
--- a/src/main/java/com/android/tools/r8/R8.java
+++ b/src/main/java/com/android/tools/r8/R8.java
@@ -78,6 +78,7 @@
 import com.android.tools.r8.optimize.interfaces.analysis.CfOpenClosedInterfacesAnalysis;
 import com.android.tools.r8.optimize.proto.ProtoNormalizer;
 import com.android.tools.r8.optimize.redundantbridgeremoval.RedundantBridgeRemover;
+import com.android.tools.r8.optimize.redundantbridgeremoval.RedundantBridgeRemover.RedundantBridgeRemoverMode;
 import com.android.tools.r8.optimize.singlecaller.SingleCallerInliner;
 import com.android.tools.r8.origin.CommandLineOrigin;
 import com.android.tools.r8.origin.Origin;
@@ -487,7 +488,8 @@
       // should therefore be run after the publicizer.
       new NestReducer(appViewWithLiveness).run(executorService, timing);
 
-      appView.setGraphLens(MemberRebindingIdentityLensFactory.create(appView, executorService));
+      appView.setGraphLens(
+          MemberRebindingIdentityLensFactory.createFromAppInfo(appViewWithLiveness));
 
       new MemberRebindingAnalysis(appViewWithLiveness).run();
       appViewWithLiveness.appInfo().notifyMemberRebindingFinished(appViewWithLiveness);
@@ -496,7 +498,7 @@
 
       AccessModifier.run(appViewWithLiveness, executorService, timing);
 
-      new RedundantBridgeRemover(appViewWithLiveness)
+      new RedundantBridgeRemover(appViewWithLiveness, RedundantBridgeRemoverMode.INITIAL)
           .setMustRetargetInvokesToTargetMethod()
           .run(executorService, timing);
 
@@ -683,14 +685,14 @@
       // Insert a member rebinding oracle in the graph to ensure that all subsequent rewritings of
       // the application has an applied oracle for looking up non-rebound references.
       MemberRebindingIdentityLens memberRebindingIdentityLens =
-          MemberRebindingIdentityLensFactory.create(appView, executorService);
+          MemberRebindingIdentityLensFactory.createFromLir(appView, executorService);
       appView.setGraphLens(memberRebindingIdentityLens);
 
       // Remove redundant bridges that have been inserted for member rebinding.
       // This can only be done if we have AppInfoWithLiveness.
       if (appView.appInfo().hasLiveness()) {
         timing.begin("Bridge remover");
-        new RedundantBridgeRemover(appView.withLiveness())
+        new RedundantBridgeRemover(appView.withLiveness(), RedundantBridgeRemoverMode.FINAL)
             .run(executorService, timing, memberRebindingIdentityLens);
         timing.end();
       } else {
@@ -724,6 +726,7 @@
       GenericSignatureContextBuilder genericContextBuilderBeforeFinalMerging = null;
       if (appView.hasCfByteCodePassThroughMethods()) {
         LirConverter.rewriteLirWithLens(appView, timing, executorService);
+        appView.clearCodeRewritings(executorService, timing);
       } else {
         // Perform repackaging.
         if (appView.hasLiveness()) {
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 1b6b6f9..56670bf 100644
--- a/src/main/java/com/android/tools/r8/graph/AppView.java
+++ b/src/main/java/com/android/tools/r8/graph/AppView.java
@@ -448,7 +448,7 @@
     setGraphLens(new ClearCodeRewritingGraphLens(withClassHierarchy()));
 
     MemberRebindingIdentityLens memberRebindingIdentityLens =
-        MemberRebindingIdentityLensFactory.rebuild(withClassHierarchy(), executorService);
+        MemberRebindingIdentityLensFactory.createFromLir(withClassHierarchy(), executorService);
     setGraphLens(memberRebindingIdentityLens);
     timing.end();
   }
diff --git a/src/main/java/com/android/tools/r8/graph/DexCallSite.java b/src/main/java/com/android/tools/r8/graph/DexCallSite.java
index 518a40d..c09e32a 100644
--- a/src/main/java/com/android/tools/r8/graph/DexCallSite.java
+++ b/src/main/java/com/android/tools/r8/graph/DexCallSite.java
@@ -110,6 +110,10 @@
     return bootstrapArgs;
   }
 
+  public DexMethodHandle getBootstrapMethod() {
+    return bootstrapMethod;
+  }
+
   public DexProto getMethodProto() {
     return methodProto;
   }
diff --git a/src/main/java/com/android/tools/r8/graph/MethodAccessInfoCollection.java b/src/main/java/com/android/tools/r8/graph/MethodAccessInfoCollection.java
index 908f08f..0701401 100644
--- a/src/main/java/com/android/tools/r8/graph/MethodAccessInfoCollection.java
+++ b/src/main/java/com/android/tools/r8/graph/MethodAccessInfoCollection.java
@@ -37,6 +37,15 @@
 
   private boolean fullyDestroyed = false;
 
+  private MethodAccessInfoCollection() {
+    this.directInvokes = ThrowingMap.get();
+    this.interfaceInvokes = ThrowingMap.get();
+    this.staticInvokes = ThrowingMap.get();
+    this.superInvokes = ThrowingMap.get();
+    this.virtualInvokes = ThrowingMap.get();
+    this.fullyDestroyed = true;
+  }
+
   private MethodAccessInfoCollection(
       Map<DexMethod, ProgramMethodSet> directInvokes,
       Map<DexMethod, ProgramMethodSet> interfaceInvokes,
@@ -452,6 +461,13 @@
       return new MethodAccessInfoCollection(
           directInvokes, interfaceInvokes, staticInvokes, superInvokes, virtualInvokes);
     }
+
+    public MethodAccessInfoCollection build(Enqueuer.Mode mode) {
+      if (mode.isInitialTreeShaking()) {
+        return build();
+      }
+      return new MethodAccessInfoCollection();
+    }
   }
 
   public static class ConcurrentBuilder
diff --git a/src/main/java/com/android/tools/r8/graph/ReferencedMembersCollector.java b/src/main/java/com/android/tools/r8/graph/ReferencedMembersCollector.java
new file mode 100644
index 0000000..c82116a
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/graph/ReferencedMembersCollector.java
@@ -0,0 +1,112 @@
+// Copyright (c) 2024, 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.graph;
+
+import com.android.tools.r8.cf.code.CfInstruction;
+import com.android.tools.r8.lightir.LirCode;
+import com.android.tools.r8.lightir.LirConstant;
+import com.android.tools.r8.utils.ThreadUtils;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+
+public class ReferencedMembersCollector {
+
+  public interface ReferencedMembersConsumer {
+
+    void onFieldReference(DexField field, ProgramMethod context);
+
+    void onMethodReference(DexMethod method, ProgramMethod context);
+  }
+
+  private final AppView<? extends AppInfoWithClassHierarchy> appView;
+  private final ReferencedMembersConsumer consumer;
+
+  public ReferencedMembersCollector(
+      AppView<? extends AppInfoWithClassHierarchy> appView, ReferencedMembersConsumer consumer) {
+    this.appView = appView;
+    this.consumer = consumer;
+  }
+
+  public void run(ExecutorService executorService) throws ExecutionException {
+    ThreadUtils.processItems(
+        appView.appInfo().classes(),
+        this::processClass,
+        appView.options().getThreadingModule(),
+        executorService);
+  }
+
+  private void processClass(DexProgramClass clazz) {
+    clazz.forEachProgramMethodMatching(DexEncodedMethod::hasCode, this::processMethod);
+  }
+
+  private void processMethod(ProgramMethod method) {
+    Code code = method.getDefinition().getCode();
+    if (code.isCfCode()) {
+      assert appView.isCfByteCodePassThrough(method.getDefinition());
+      processCfCode(method, code.asCfCode());
+    } else if (code.isDefaultInstanceInitializerCode()) {
+      processDefaultInstanceInitializerCode(method);
+    } else if (code.isLirCode()) {
+      processLirCode(method, code.asLirCode());
+    } else if (code.isThrowNullCode()) {
+      // Intentionally empty.
+    } else {
+      assert false : code.getClass().getTypeName();
+    }
+  }
+
+  private void processDefaultInstanceInitializerCode(ProgramMethod method) {
+    DexMethod invokedMethod =
+        DefaultInstanceInitializerCode.getParentConstructor(method, appView.dexItemFactory());
+    consumer.onMethodReference(invokedMethod, method);
+  }
+
+  private void processCfCode(ProgramMethod method, CfCode code) {
+    for (CfInstruction instruction : code.getInstructions()) {
+      if (instruction.isFieldInstruction()) {
+        consumer.onFieldReference(instruction.asFieldInstruction().getField(), method);
+      } else if (instruction.isInvoke()) {
+        consumer.onMethodReference(instruction.asInvoke().getMethod(), method);
+      } else if (instruction.isInvokeDynamic()) {
+        processCallSite(method, instruction.asInvokeDynamic().getCallSite());
+      }
+    }
+  }
+
+  private void processLirCode(ProgramMethod method, LirCode<Integer> code) {
+    for (LirConstant constant : code.getConstantPool()) {
+      if (constant instanceof DexField) {
+        consumer.onFieldReference((DexField) constant, method);
+      } else if (constant instanceof DexCallSite) {
+        processCallSite(method, (DexCallSite) constant);
+      } else if (constant instanceof DexMethod) {
+        consumer.onMethodReference((DexMethod) constant, method);
+      } else if (constant instanceof DexMethodHandle) {
+        processMethodHandle(method, (DexMethodHandle) constant);
+      }
+    }
+  }
+
+  private void processCallSite(ProgramMethod method, DexCallSite callSite) {
+    processMethodHandle(method, callSite.getBootstrapMethod());
+    for (DexValue bootstrapArg : callSite.getBootstrapArgs()) {
+      if (bootstrapArg.isDexValueField()) {
+        consumer.onFieldReference(bootstrapArg.asDexValueField().getValue(), method);
+      } else if (bootstrapArg.isDexValueMethod()) {
+        consumer.onMethodReference(bootstrapArg.asDexValueMethod().getValue(), method);
+      } else if (bootstrapArg.isDexValueMethodHandle()) {
+        processMethodHandle(method, bootstrapArg.asDexValueMethodHandle().getValue());
+      }
+    }
+  }
+
+  private void processMethodHandle(ProgramMethod method, DexMethodHandle methodHandle) {
+    if (methodHandle.isFieldHandle()) {
+      consumer.onFieldReference(methodHandle.asField(), method);
+    } else {
+      assert methodHandle.isMethodHandle();
+      consumer.onMethodReference(methodHandle.asMethod(), method);
+    }
+  }
+}
diff --git a/src/main/java/com/android/tools/r8/horizontalclassmerging/HorizontalClassMerger.java b/src/main/java/com/android/tools/r8/horizontalclassmerging/HorizontalClassMerger.java
index 9c774c4..80b6dc7 100644
--- a/src/main/java/com/android/tools/r8/horizontalclassmerging/HorizontalClassMerger.java
+++ b/src/main/java/com/android/tools/r8/horizontalclassmerging/HorizontalClassMerger.java
@@ -16,10 +16,8 @@
 import com.android.tools.r8.graph.DexMethod;
 import com.android.tools.r8.graph.DexProgramClass;
 import com.android.tools.r8.graph.ImmediateProgramSubtypingInfo;
-import com.android.tools.r8.graph.MethodAccessInfoCollection;
 import com.android.tools.r8.graph.ProgramMethod;
 import com.android.tools.r8.graph.PrunedItems;
-import com.android.tools.r8.horizontalclassmerging.VirtualMethodMerger.SuperMethodReference;
 import com.android.tools.r8.horizontalclassmerging.code.SyntheticInitializerConverter;
 import com.android.tools.r8.ir.conversion.LirConverter;
 import com.android.tools.r8.ir.conversion.MethodConversionOptions;
@@ -36,7 +34,6 @@
 import com.android.tools.r8.utils.ThreadUtils;
 import com.android.tools.r8.utils.Timing;
 import com.android.tools.r8.utils.TraversalContinuation;
-import com.android.tools.r8.utils.collections.ProgramMethodMap;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.LinkedList;
@@ -192,8 +189,6 @@
     // sites, fields accesses, etc. are correctly transferred to the target classes.
     DexApplication newApplication = getNewApplication(mergedClasses);
     if (appView.enableWholeProgramOptimizations()) {
-      ProgramMethodMap<DexMethod> newNonReboundMethodReferences =
-          extractNonReboundMethodReferences(groups, horizontalClassMergerGraphLens);
       // Finalize synthetic code.
       transformIncompleteCode(groups, horizontalClassMergerGraphLens, executorService);
       // Prune keep info.
@@ -212,8 +207,6 @@
         appViewWithClassHierarchy.setAppInfo(
             appViewWithClassHierarchy.appInfo().rebuildWithClassHierarchy(newApplication));
       }
-      amendMethodAccessInfoCollection(
-          horizontalClassMergerGraphLens, newNonReboundMethodReferences);
       appView.clearCodeRewritings(executorService, timing);
     } else {
       SyntheticItems syntheticItems = appView.appInfo().getSyntheticItems();
@@ -277,40 +270,6 @@
             });
   }
 
-  private ProgramMethodMap<DexMethod> extractNonReboundMethodReferences(
-      Collection<HorizontalMergeGroup> groups, HorizontalClassMergerGraphLens lens) {
-    ProgramMethodMap<DexMethod> newNonReboundMethodReferences = ProgramMethodMap.create();
-    for (HorizontalMergeGroup group : groups) {
-      group
-          .getTarget()
-          .forEachProgramVirtualMethodMatching(
-              method ->
-                  method.hasCode()
-                      && method.getCode() instanceof IncompleteVirtuallyMergedMethodCode
-                      && ((IncompleteVirtuallyMergedMethodCode) method.getCode()).hasSuperMethod(),
-              method -> {
-                SuperMethodReference superMethodReference =
-                    ((IncompleteVirtuallyMergedMethodCode) method.getDefinition().getCode())
-                        .getSuperMethod();
-                newNonReboundMethodReferences.put(
-                    method, superMethodReference.getRewrittenReference(lens, method));
-              });
-    }
-    return newNonReboundMethodReferences;
-  }
-
-  private void amendMethodAccessInfoCollection(
-      HorizontalClassMergerGraphLens lens,
-      ProgramMethodMap<DexMethod> newNonReboundMethodReferences) {
-    MethodAccessInfoCollection.Modifier methodAccessInfoCollectionModifier =
-        appView.appInfoWithLiveness().getMethodAccessInfoCollection().modifier();
-    newNonReboundMethodReferences.forEach(
-        (context, reference) ->
-            // Reference is already lens rewritten.
-            methodAccessInfoCollectionModifier.registerInvokeSuperInContext(
-                reference, context.rewrittenWithLens(lens, lens.getPrevious(), appView)));
-  }
-
   private FieldAccessInfoCollectionModifier createFieldAccessInfoCollectionModifier(
       Collection<HorizontalMergeGroup> groups) {
     FieldAccessInfoCollectionModifier.Builder builder =
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 31577fc..71f0772 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
@@ -115,7 +115,6 @@
   private final ClassInliner classInliner;
   protected final InternalOptions options;
   public final CodeRewriter codeRewriter;
-  public AssertionErrorTwoArgsConstructorRewriter assertionErrorTwoArgsConstructorRewriter;
   public final MemberValuePropagation<?> memberValuePropagation;
   private final LensCodeRewriter lensCodeRewriter;
   protected final Inliner inliner;
@@ -124,7 +123,6 @@
   protected final CovariantReturnTypeAnnotationTransformer covariantReturnTypeAnnotationTransformer;
   private final StringSwitchRemover stringSwitchRemover;
   private final TypeChecker typeChecker;
-  protected ServiceLoaderRewriter serviceLoaderRewriter;
   protected EnumUnboxer enumUnboxer;
   protected final NumberUnboxer numberUnboxer;
   protected final RemoveVerificationErrorForUnknownReturnedValues
@@ -164,10 +162,6 @@
     this.options = appView.options();
     this.codeRewriter = new CodeRewriter(appView);
     this.rewriterPassCollection = CodeRewriterPassCollection.create(appView);
-    this.assertionErrorTwoArgsConstructorRewriter =
-        appView.options().desugarState.isOn()
-            ? new AssertionErrorTwoArgsConstructorRewriter(appView)
-            : null;
     this.classInitializerDefaultsOptimization =
         new ClassInitializerDefaultsOptimization(appView, this);
     this.deadCodeRemover = new DeadCodeRemover(appView);
@@ -210,7 +204,6 @@
       this.devirtualizer = null;
       this.typeChecker = null;
       this.stringSwitchRemover = null;
-      this.serviceLoaderRewriter = null;
       this.methodOptimizationInfoCollector = null;
       this.enumUnboxer = EnumUnboxer.empty();
       this.numberUnboxer = NumberUnboxer.empty();
@@ -262,10 +255,6 @@
       this.devirtualizer =
           options.enableDevirtualization ? new Devirtualizer(appViewWithLiveness) : null;
       this.typeChecker = new TypeChecker(appViewWithLiveness, VerifyTypesHelper.create(appView));
-      this.serviceLoaderRewriter =
-          options.enableServiceLoaderRewriting
-              ? new ServiceLoaderRewriter(appViewWithLiveness, appView.apiLevelCompute())
-              : null;
     } else {
       AppView<AppInfo> appViewWithoutClassHierarchy = appView.withoutClassHierarchy();
       this.assumeInserter = null;
@@ -283,7 +272,6 @@
       this.identifierNameStringMarker = null;
       this.devirtualizer = null;
       this.typeChecker = null;
-      this.serviceLoaderRewriter = null;
       this.methodOptimizationInfoCollector = null;
       this.enumUnboxer = EnumUnboxer.empty();
       this.numberUnboxer = NumberUnboxer.empty();
@@ -298,14 +286,6 @@
     this(AppView.createForD8(appInfo));
   }
 
-  public void clearEnumUnboxer() {
-    enumUnboxer = EnumUnboxer.empty();
-  }
-
-  public void clearServiceLoaderRewriter() {
-    serviceLoaderRewriter = null;
-  }
-
   public Inliner getInliner() {
     return inliner;
   }
@@ -631,10 +611,12 @@
     CheckNotNullConverter.runIfNecessary(appView, code);
     previous = printMethod(code, "IR after disable assertions (SSA)", previous);
 
-    if (serviceLoaderRewriter != null) {
-      assert appView.appInfo().hasLiveness();
+    if (appView.hasLiveness()
+        && methodProcessor.isPrimaryMethodProcessor()
+        && options.enableServiceLoaderRewriting) {
       timing.begin("Rewrite service loaders");
-      serviceLoaderRewriter.rewrite(code, methodProcessor, methodProcessingContext);
+      new ServiceLoaderRewriter(appView.withLiveness())
+          .rewrite(code, methodProcessor, methodProcessingContext);
       timing.end();
       previous = printMethod(code, "IR after service rewriting (SSA)", previous);
     }
@@ -732,10 +714,11 @@
 
     assert code.verifyTypes(appView);
 
-    if (assertionErrorTwoArgsConstructorRewriter != null) {
+    if (appView.options().desugarState.isOn()
+        && (methodProcessor.isPrimaryMethodProcessor() || methodProcessor.isD8MethodProcessor())) {
       timing.begin("Rewrite AssertionError");
-      assertionErrorTwoArgsConstructorRewriter.rewrite(
-          code, methodProcessor, methodProcessingContext);
+      new AssertionErrorTwoArgsConstructorRewriter(appView)
+          .rewrite(code, methodProcessor, methodProcessingContext);
       timing.end();
     }
 
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/LirConverter.java b/src/main/java/com/android/tools/r8/ir/conversion/LirConverter.java
index 941930c..6da063b 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/LirConverter.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/LirConverter.java
@@ -37,7 +37,7 @@
 public class LirConverter {
 
   public static void enterLirSupportedPhase(
-      AppView<AppInfoWithClassHierarchy> appView, ExecutorService executorService)
+      AppView<? extends AppInfoWithClassHierarchy> appView, ExecutorService executorService)
       throws ExecutionException {
     assert appView.testing().canUseLir(appView);
     assert appView.testing().isPreLirPhase();
@@ -161,7 +161,8 @@
     // Clear the reference type cache after conversion to reduce memory pressure.
     appView.dexItemFactory().clearTypeElementsCache();
     // At this point all code has been mapped according to the graph lens.
-    appView.clearCodeRewritings(executorService, timing);
+    assert appView.graphLens().isMemberRebindingIdentityLens()
+        && appView.graphLens().asMemberRebindingIdentityLens().getPrevious() == appView.codeLens();
   }
 
   private static void finalizeLirMethodToOutputFormat(
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/PrimaryD8L8IRConverter.java b/src/main/java/com/android/tools/r8/ir/conversion/PrimaryD8L8IRConverter.java
index 625a337..eb16aef 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/PrimaryD8L8IRConverter.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/PrimaryD8L8IRConverter.java
@@ -71,11 +71,6 @@
     reportNestDesugarDependencies();
     clearNestAttributes();
 
-    if (assertionErrorTwoArgsConstructorRewriter != null) {
-      processSimpleSynthesizeMethods(
-          assertionErrorTwoArgsConstructorRewriter.getSynthesizedMethods(), executorService);
-    }
-
     application = commitPendingSyntheticItems(appView, application);
 
     postProcessingDesugaringForD8(methodProcessor, interfaceProcessor, executorService);
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/PrimaryR8IRConverter.java b/src/main/java/com/android/tools/r8/ir/conversion/PrimaryR8IRConverter.java
index 663f27f..71f3df9 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/PrimaryR8IRConverter.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/PrimaryR8IRConverter.java
@@ -273,17 +273,9 @@
       PostMethodProcessor.Builder postMethodProcessorBuilder, ExecutorService executorService)
       throws ExecutionException {
     pruneItems(executorService);
-    if (assertionErrorTwoArgsConstructorRewriter != null) {
-      assertionErrorTwoArgsConstructorRewriter.onLastWaveDone(postMethodProcessorBuilder);
-      assertionErrorTwoArgsConstructorRewriter = null;
-    }
     if (inliner != null) {
       inliner.onLastWaveDone(postMethodProcessorBuilder, executorService, timing);
     }
-    if (serviceLoaderRewriter != null) {
-      serviceLoaderRewriter.onLastWaveDone(postMethodProcessorBuilder);
-      serviceLoaderRewriter = null;
-    }
 
     // Ensure determinism of method-to-reprocess set.
     appView.testing().checkDeterminism(postMethodProcessorBuilder::dump);
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/AssertionErrorTwoArgsConstructorRewriter.java b/src/main/java/com/android/tools/r8/ir/optimize/AssertionErrorTwoArgsConstructorRewriter.java
index d1201b5..be2e313 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/AssertionErrorTwoArgsConstructorRewriter.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/AssertionErrorTwoArgsConstructorRewriter.java
@@ -22,7 +22,6 @@
 import com.android.tools.r8.ir.code.NewInstance;
 import com.android.tools.r8.ir.code.Value;
 import com.android.tools.r8.ir.conversion.MethodProcessor;
-import com.android.tools.r8.ir.conversion.PostMethodProcessor;
 import com.android.tools.r8.ir.desugar.backports.BackportedMethods;
 import com.android.tools.r8.ir.optimize.info.OptimizationFeedback;
 import com.android.tools.r8.utils.InternalOptions;
@@ -42,7 +41,6 @@
     this.dexItemFactory = appView.dexItemFactory();
   }
 
-  @SuppressWarnings("ReferenceEquality")
   public void rewrite(
       IRCode code,
       MethodProcessor methodProcessor,
@@ -61,7 +59,8 @@
         InvokeDirect invoke = insnIterator.next().asInvokeDirect();
         if (invoke != null) {
           DexMethod invokedMethod = invoke.getInvokedMethod();
-          if (invokedMethod == dexItemFactory.assertionErrorMethods.initMessageAndCause) {
+          if (invokedMethod.isIdenticalTo(
+              dexItemFactory.assertionErrorMethods.initMessageAndCause)) {
             assert invoke.arguments().size() == 3; // receiver, message, cause
             Value newInstanceValue = invoke.getReceiver();
             Instruction definition = newInstanceValue.getDefinition();
@@ -90,12 +89,6 @@
     assert code.isConsistentSSA(appView);
   }
 
-  private final List<ProgramMethod> synthesizedMethods = new ArrayList<>();
-
-  public List<ProgramMethod> getSynthesizedMethods() {
-    return synthesizedMethods;
-  }
-
   private ProgramMethod createSynthetic(
       MethodProcessor methodProcessor, MethodProcessingContext methodProcessingContext) {
     DexItemFactory factory = appView.dexItemFactory();
@@ -117,25 +110,19 @@
                             methodSig ->
                                 BackportedMethods.AssertionErrorMethods_createAssertionError(
                                     factory, methodSig)));
-    synchronized (synthesizedMethods) {
-      synthesizedMethods.add(method);
-      OptimizationFeedback.getSimpleFeedback()
-          .setDynamicReturnType(
-              method,
-              appView,
-              DynamicType.createExact(
-                  dexItemFactory
-                      .assertionErrorType
-                      .toTypeElement(appView, Nullability.definitelyNotNull())
-                      .asClassType()));
-    }
+    OptimizationFeedback.getSimpleFeedback()
+        .setDynamicReturnType(
+            method,
+            appView,
+            DynamicType.createExact(
+                dexItemFactory
+                    .assertionErrorType
+                    .toTypeElement(appView, Nullability.definitelyNotNull())
+                    .asClassType()));
+    methodProcessor.scheduleDesugaredMethodForProcessing(method);
     methodProcessor
         .getEventConsumer()
         .acceptAssertionErrorCreateMethod(method, methodProcessingContext.getMethodContext());
     return method;
   }
-
-  public void onLastWaveDone(PostMethodProcessor.Builder postMethodProcessorBuilder) {
-    postMethodProcessorBuilder.addAll(synthesizedMethods, appView.graphLens());
-  }
 }
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/ServiceLoaderRewriter.java b/src/main/java/com/android/tools/r8/ir/optimize/ServiceLoaderRewriter.java
index 9e7e988..455ef32 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/ServiceLoaderRewriter.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/ServiceLoaderRewriter.java
@@ -24,7 +24,6 @@
 import com.android.tools.r8.ir.code.InvokeVirtual;
 import com.android.tools.r8.ir.code.Value;
 import com.android.tools.r8.ir.conversion.MethodProcessor;
-import com.android.tools.r8.ir.conversion.PostMethodProcessor;
 import com.android.tools.r8.ir.desugar.ServiceLoaderSourceCode;
 import com.android.tools.r8.shaking.AppInfoWithLiveness;
 import com.android.tools.r8.utils.BooleanBox;
@@ -70,12 +69,9 @@
   private final Reporter reporter;
   private final ServiceLoaderMethods serviceLoaderMethods;
 
-  private final List<ProgramMethod> synthesizedServiceLoadMethods = new ArrayList<>();
-
-  public ServiceLoaderRewriter(
-      AppView<AppInfoWithLiveness> appView, AndroidApiLevelCompute apiLevelCompute) {
+  public ServiceLoaderRewriter(AppView<AppInfoWithLiveness> appView) {
     this.appView = appView;
-    this.apiLevelCompute = apiLevelCompute;
+    this.apiLevelCompute = appView.apiLevelCompute();
     serviceLoaderMethods = appView.dexItemFactory().serviceLoaderMethods;
     reporter = shouldReportWhyAreYouNotInliningServiceLoaderLoad() ? appView.reporter() : null;
   }
@@ -91,7 +87,6 @@
       IRCode code,
       MethodProcessor methodProcessor,
       MethodProcessingContext methodProcessingContext) {
-    assert !methodProcessor.isPostMethodProcessor();
     InstructionListIterator instructionIterator = code.instructionListIterator();
     // Create a map from service type to loader methods local to this context since two
     // service loader calls to the same type in different methods and in the same wave can race.
@@ -243,10 +238,6 @@
     assert code.isConsistentSSA(appView);
   }
 
-  public void onLastWaveDone(PostMethodProcessor.Builder postMethodProcessorBuilder) {
-    postMethodProcessorBuilder.addAll(synthesizedServiceLoadMethods, appView.graphLens());
-  }
-
   private void report(ProgramMethod method, DexType serviceLoaderType, String message) {
     if (reporter != null) {
       reporter.info(
@@ -286,9 +277,7 @@
                             m ->
                                 ServiceLoaderSourceCode.generate(
                                     serviceType, classes, appView.dexItemFactory())));
-    synchronized (synthesizedServiceLoadMethods) {
-      synthesizedServiceLoadMethods.add(method);
-    }
+    methodProcessor.scheduleDesugaredMethodForProcessing(method);
     methodProcessor
         .getEventConsumer()
         .acceptServiceLoaderLoadUtilityMethod(method, methodProcessingContext.getMethodContext());
diff --git a/src/main/java/com/android/tools/r8/naming/FieldNameMinifier.java b/src/main/java/com/android/tools/r8/naming/FieldNameMinifier.java
index f15bba1..8bfa3ec 100644
--- a/src/main/java/com/android/tools/r8/naming/FieldNameMinifier.java
+++ b/src/main/java/com/android/tools/r8/naming/FieldNameMinifier.java
@@ -3,18 +3,13 @@
 // BSD-style license that can be found in the LICENSE file.
 package com.android.tools.r8.naming;
 
-import static com.android.tools.r8.graph.DexProgramClass.asProgramClassOrNull;
-
 import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.DexClass;
 import com.android.tools.r8.graph.DexClassAndField;
-import com.android.tools.r8.graph.DexEncodedField;
 import com.android.tools.r8.graph.DexField;
 import com.android.tools.r8.graph.DexProgramClass;
 import com.android.tools.r8.graph.DexString;
 import com.android.tools.r8.graph.DexType;
-import com.android.tools.r8.graph.FieldAccessInfo;
-import com.android.tools.r8.graph.FieldAccessInfoCollection;
 import com.android.tools.r8.graph.ProgramField;
 import com.android.tools.r8.graph.SubtypingInfo;
 import com.android.tools.r8.graph.TopDownClassHierarchyTraversal;
@@ -70,10 +65,6 @@
     renameFieldsInClasses();
     renameFieldsInUnrelatedClasspathClasses();
     timing.end();
-    // Rename the references that are not rebound to definitions for some reasons.
-    timing.begin("rename-references");
-    renameNonReboundReferences();
-    timing.end();
     return new FieldRenaming(renaming);
   }
 
@@ -281,35 +272,6 @@
     return newName;
   }
 
-  private void renameNonReboundReferences() {
-    FieldAccessInfoCollection<?> fieldAccessInfoCollection =
-        appView.appInfo().getFieldAccessInfoCollection();
-    fieldAccessInfoCollection.forEach(this::renameNonReboundAccessesToField);
-  }
-
-  private void renameNonReboundAccessesToField(FieldAccessInfo fieldAccessInfo) {
-    fieldAccessInfo.forEachIndirectAccess(this::renameNonReboundAccessToField);
-  }
-
-  @SuppressWarnings("ReferenceEquality")
-  private void renameNonReboundAccessToField(DexField field) {
-    // If the given field reference is a non-rebound reference to a program field, then assign the
-    // same name as the resolved field.
-    if (renaming.containsKey(field)) {
-      return;
-    }
-    DexProgramClass holder = asProgramClassOrNull(appView.definitionForHolder(field));
-    if (holder == null) {
-      return;
-    }
-    DexEncodedField definition = appView.appInfo().resolveFieldOn(holder, field).getResolvedField();
-    if (definition != null
-        && definition.getReference() != field
-        && renaming.containsKey(definition.getReference())) {
-      renaming.put(field, renaming.get(definition.getReference()));
-    }
-  }
-
   static class InterfacePartitioning {
 
     private final FieldNameMinifier minifier;
diff --git a/src/main/java/com/android/tools/r8/naming/MethodNameMinifier.java b/src/main/java/com/android/tools/r8/naming/MethodNameMinifier.java
index fa5089d..ceb8d73b 100644
--- a/src/main/java/com/android/tools/r8/naming/MethodNameMinifier.java
+++ b/src/main/java/com/android/tools/r8/naming/MethodNameMinifier.java
@@ -10,26 +10,20 @@
 import com.android.tools.r8.graph.DexClass;
 import com.android.tools.r8.graph.DexClassAndMember;
 import com.android.tools.r8.graph.DexClassAndMethod;
-import com.android.tools.r8.graph.DexEncodedMethod;
 import com.android.tools.r8.graph.DexMethod;
 import com.android.tools.r8.graph.DexString;
 import com.android.tools.r8.graph.DexType;
-import com.android.tools.r8.graph.MethodAccessInfoCollection;
-import com.android.tools.r8.graph.MethodResolutionResult;
 import com.android.tools.r8.graph.SubtypingInfo;
 import com.android.tools.r8.graph.TopDownClassHierarchyTraversal;
 import com.android.tools.r8.shaking.AppInfoWithLiveness;
-import com.android.tools.r8.utils.ConsumerUtils;
 import com.android.tools.r8.utils.InternalOptions;
 import com.android.tools.r8.utils.ListUtils;
-import com.android.tools.r8.utils.ThreadUtils;
 import com.android.tools.r8.utils.Timing;
 import com.android.tools.r8.utils.WorkList;
 import com.android.tools.r8.utils.collections.DexClassAndMethodSet;
 import com.google.common.collect.BiMap;
 import com.google.common.collect.HashBiMap;
 import com.google.common.collect.ImmutableMap;
-import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Comparator;
 import java.util.HashMap;
@@ -38,9 +32,6 @@
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.ExecutorService;
 import java.util.function.Function;
 
 /**
@@ -191,11 +182,7 @@
   }
 
   MethodRenaming computeRenaming(
-      Iterable<DexClass> interfaces,
-      SubtypingInfo subtypingInfo,
-      ExecutorService executorService,
-      Timing timing)
-      throws ExecutionException {
+      Iterable<DexClass> interfaces, SubtypingInfo subtypingInfo, Timing timing) {
     // Phase 1: Reserve all the names that need to be kept and allocate linked state in the
     //          library part.
     timing.begin("Phase 1");
@@ -216,9 +203,6 @@
     assignNamesToClassesMethods();
     renameMethodsInUnrelatedClasspathClasses();
     timing.end();
-    timing.begin("Phase 5: non-rebound references");
-    renameNonReboundReferences(executorService);
-    timing.end();
 
     return new MethodRenaming(renaming);
   }
@@ -436,65 +420,6 @@
     return reservationState;
   }
 
-  private void renameNonReboundReferences(ExecutorService executorService)
-      throws ExecutionException {
-    Map<DexMethod, DexString> nonReboundRenamings = new ConcurrentHashMap<>();
-    MethodAccessInfoCollection methodAccessInfoCollection =
-        appView.appInfo().getMethodAccessInfoCollection();
-    ThreadUtils.processItems(
-        methodAccessInfoCollection::forEachMethodReference,
-        method -> renameNonReboundMethodReference(method, nonReboundRenamings),
-        appView.options().getThreadingModule(),
-        executorService);
-    renaming.putAll(nonReboundRenamings);
-  }
-
-  @SuppressWarnings("ReferenceEquality")
-  private void renameNonReboundMethodReference(
-      DexMethod method, Map<DexMethod, DexString> nonReboundRenamings) {
-    if (method.getHolderType().isArrayType()) {
-      return;
-    }
-
-    DexClass holder = appView.contextIndependentDefinitionFor(method.getHolderType());
-    if (holder == null) {
-      return;
-    }
-
-    MethodResolutionResult resolutionResult =
-        appView.appInfo().resolveMethodOnLegacy(holder, method);
-    if (resolutionResult.isSingleResolution()) {
-      DexEncodedMethod resolvedMethod = resolutionResult.getSingleTarget();
-      if (resolvedMethod.getReference() == method) {
-        return;
-      }
-
-      DexString newName = renaming.get(resolvedMethod.getReference());
-      if (newName != null) {
-        assert newName != resolvedMethod.getName();
-        nonReboundRenamings.put(method, newName);
-      }
-      return;
-    }
-
-    // If resolution fails, the method must be renamed consistently with the targets that give rise
-    // to the failure.
-    assert resolutionResult.isFailedResolution();
-
-    List<DexEncodedMethod> targets = new ArrayList<>();
-    resolutionResult
-        .asFailedResolution()
-        .forEachFailureDependency(ConsumerUtils.emptyConsumer(), targets::add);
-    if (!targets.isEmpty()) {
-      DexString newName = renaming.get(targets.get(0).getReference());
-      assert targets.stream().allMatch(target -> renaming.get(target.getReference()) == newName);
-      if (newName != null) {
-        assert newName != targets.get(0).getName();
-        nonReboundRenamings.put(method, newName);
-      }
-    }
-  }
-
   // Shuffles the given methods if assertions are enabled and deterministic debugging is disabled.
   // Used to ensure that the generated output is deterministic.
   private static Iterable<DexClassAndMethod> shuffleMethods(
diff --git a/src/main/java/com/android/tools/r8/naming/Minifier.java b/src/main/java/com/android/tools/r8/naming/Minifier.java
index 376c969..335caa5 100644
--- a/src/main/java/com/android/tools/r8/naming/Minifier.java
+++ b/src/main/java/com/android/tools/r8/naming/Minifier.java
@@ -8,29 +8,40 @@
 import static com.android.tools.r8.utils.SymbolGenerationUtils.RESERVED_NAMES;
 
 import com.android.tools.r8.errors.CompilationError;
+import com.android.tools.r8.graph.AppInfoWithClassHierarchy;
 import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.DexClass;
 import com.android.tools.r8.graph.DexClassAndField;
 import com.android.tools.r8.graph.DexClassAndMethod;
+import com.android.tools.r8.graph.DexEncodedField;
+import com.android.tools.r8.graph.DexEncodedMethod;
+import com.android.tools.r8.graph.DexField;
 import com.android.tools.r8.graph.DexItemFactory;
 import com.android.tools.r8.graph.DexMethod;
 import com.android.tools.r8.graph.DexProgramClass;
 import com.android.tools.r8.graph.DexString;
 import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.MethodResolutionResult;
 import com.android.tools.r8.graph.ProgramField;
 import com.android.tools.r8.graph.ProgramMethod;
+import com.android.tools.r8.graph.ReferencedMembersCollector;
+import com.android.tools.r8.graph.ReferencedMembersCollector.ReferencedMembersConsumer;
 import com.android.tools.r8.graph.SubtypingInfo;
 import com.android.tools.r8.naming.ClassNameMinifier.ClassNamingStrategy;
 import com.android.tools.r8.naming.ClassNameMinifier.ClassRenaming;
 import com.android.tools.r8.naming.FieldNameMinifier.FieldRenaming;
 import com.android.tools.r8.naming.MethodNameMinifier.MethodRenaming;
 import com.android.tools.r8.shaking.AppInfoWithLiveness;
+import com.android.tools.r8.utils.ConsumerUtils;
 import com.android.tools.r8.utils.SymbolGenerationUtils;
 import com.android.tools.r8.utils.SymbolGenerationUtils.MixedCasing;
 import com.android.tools.r8.utils.Timing;
+import java.util.ArrayList;
 import java.util.HashSet;
 import java.util.List;
+import java.util.Map;
 import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.ExecutorService;
 import java.util.function.BiPredicate;
@@ -70,7 +81,7 @@
     timing.begin("MinifyMethods");
     MethodRenaming methodRenaming =
         new MethodNameMinifier(appView, minifyMembers)
-            .computeRenaming(interfaces, subtypingInfo, executorService, timing);
+            .computeRenaming(interfaces, subtypingInfo, timing);
     timing.end();
 
     assert new MinifiedRenaming(appView, classRenaming, methodRenaming, FieldRenaming.empty())
@@ -82,6 +93,11 @@
             .computeRenaming(interfaces, timing);
     timing.end();
 
+    // Rename the references that are not rebound to definitions.
+    timing.begin("non-rebound-references");
+    renameNonReboundReferences(appView, fieldRenaming, methodRenaming, executorService);
+    timing.end();
+
     NamingLens lens = new MinifiedRenaming(appView, classRenaming, methodRenaming, fieldRenaming);
     assert lens.verifyNoCollisions(appView.appInfo().classes(), appView.dexItemFactory());
 
@@ -90,6 +106,75 @@
     appView.setNamingLens(lens);
   }
 
+  public static void renameNonReboundReferences(
+      AppView<? extends AppInfoWithClassHierarchy> appView,
+      FieldRenaming fieldRenaming,
+      MethodRenaming methodRenaming,
+      ExecutorService executorService)
+      throws ExecutionException {
+    Map<DexField, DexString> fieldNames = new ConcurrentHashMap<>(fieldRenaming.renaming);
+    fieldRenaming.renaming.clear();
+    Map<DexMethod, DexString> methodNames = new ConcurrentHashMap<>(methodRenaming.renaming);
+    methodRenaming.renaming.clear();
+    ReferencedMembersConsumer consumer =
+        new ReferencedMembersConsumer() {
+
+          @Override
+          public void onFieldReference(DexField field, ProgramMethod context) {
+            // If the given field reference is a non-rebound reference to a program field, then
+            // assign the same name as the resolved field.
+            if (fieldNames.containsKey(field)) {
+              return;
+            }
+            DexEncodedField resolvedField =
+                appView.appInfo().resolveField(field).getResolvedField();
+            if (resolvedField != null
+                && resolvedField.getReference().isNotIdenticalTo(field)
+                && fieldNames.containsKey(resolvedField.getReference())) {
+              fieldNames.put(field, fieldNames.get(resolvedField.getReference()));
+            }
+          }
+
+          @Override
+          public void onMethodReference(DexMethod method, ProgramMethod context) {
+            // If the given method reference is a non-rebound reference to a program method, then
+            // assign the same name as the resolved method.
+            if (method.getHolderType().isArrayType() || methodNames.containsKey(method)) {
+              return;
+            }
+            MethodResolutionResult resolutionResult =
+                appView.appInfo().unsafeResolveMethodDueToDexFormat(method);
+            DexEncodedMethod resolvedMethod = resolutionResult.getResolvedMethod();
+            if (resolvedMethod != null
+                && resolvedMethod.getReference().isNotIdenticalTo(method)
+                && methodNames.containsKey(resolvedMethod.getReference())) {
+              methodNames.put(method, methodNames.get(resolvedMethod.getReference()));
+            }
+            // If resolution fails, the method must be renamed consistently with the targets that
+            // give rise to the failure.
+            if (resolutionResult.isFailedResolution()) {
+              List<DexEncodedMethod> targets = new ArrayList<>();
+              resolutionResult
+                  .asFailedResolution()
+                  .forEachFailureDependency(ConsumerUtils.emptyConsumer(), targets::add);
+              if (!targets.isEmpty()) {
+                DexString newName = methodNames.get(targets.get(0).getReference());
+                assert targets.stream()
+                    .allMatch(
+                        target -> newName.isIdenticalTo(methodNames.get(target.getReference())));
+                if (newName != null) {
+                  assert newName.isNotIdenticalTo(targets.get(0).getName());
+                  methodNames.put(method, newName);
+                }
+              }
+            }
+          }
+        };
+    new ReferencedMembersCollector(appView, consumer).run(executorService);
+    fieldRenaming.renaming.putAll(fieldNames);
+    methodRenaming.renaming.putAll(methodNames);
+  }
+
   abstract static class BaseMinificationNamingStrategy {
 
     // We have to ensure that the names proposed by the minifier is not used in the obfuscation
diff --git a/src/main/java/com/android/tools/r8/naming/ProguardMapMinifier.java b/src/main/java/com/android/tools/r8/naming/ProguardMapMinifier.java
index d5f4683..d2f2e8a 100644
--- a/src/main/java/com/android/tools/r8/naming/ProguardMapMinifier.java
+++ b/src/main/java/com/android/tools/r8/naming/ProguardMapMinifier.java
@@ -10,6 +10,7 @@
 import static com.android.tools.r8.ir.desugar.itf.InterfaceDesugaringSyntheticHelper.getInterfaceClassType;
 import static com.android.tools.r8.ir.desugar.itf.InterfaceDesugaringSyntheticHelper.isCompanionClassType;
 import static com.android.tools.r8.ir.desugar.itf.InterfaceDesugaringSyntheticHelper.staticAsMethodOfCompanionClass;
+import static com.android.tools.r8.naming.Minifier.renameNonReboundReferences;
 
 import com.android.tools.r8.graph.AppInfoWithClassHierarchy;
 import com.android.tools.r8.graph.AppView;
@@ -138,7 +139,7 @@
     timing.begin("MinifyMethods");
     MethodRenaming methodRenaming =
         new MethodNameMinifier(appView, nameStrategy)
-            .computeRenaming(interfaces, subtypingInfo, executorService, timing);
+            .computeRenaming(interfaces, subtypingInfo, timing);
     // Amend the method renamings with the default interface methods.
     methodRenaming.renaming.putAll(companionClassInterfaceMethodImplementationNames);
     methodRenaming.renaming.putAll(additionalMethodNamings);
@@ -151,6 +152,11 @@
     fieldRenaming.renaming.putAll(additionalFieldNamings);
     timing.end();
 
+    // Rename the references that are not rebound to definitions.
+    timing.begin("non-rebound-references");
+    renameNonReboundReferences(appView, fieldRenaming, methodRenaming, executorService);
+    timing.end();
+
     appView.options().reporter.failIfPendingErrors();
 
     NamingLens lens =
diff --git a/src/main/java/com/android/tools/r8/optimize/MemberRebindingIdentityLens.java b/src/main/java/com/android/tools/r8/optimize/MemberRebindingIdentityLens.java
index 0ea0a9a..76e600d 100644
--- a/src/main/java/com/android/tools/r8/optimize/MemberRebindingIdentityLens.java
+++ b/src/main/java/com/android/tools/r8/optimize/MemberRebindingIdentityLens.java
@@ -7,6 +7,7 @@
 import com.android.tools.r8.graph.AppInfoWithClassHierarchy;
 import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.DexClass;
+import com.android.tools.r8.graph.DexEncodedField;
 import com.android.tools.r8.graph.DexField;
 import com.android.tools.r8.graph.DexItemFactory;
 import com.android.tools.r8.graph.DexMethod;
@@ -21,6 +22,7 @@
 import java.util.Deque;
 import java.util.IdentityHashMap;
 import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
 
 /**
  * This lens is used to populate the rebound field and method reference during lookup, such that
@@ -48,7 +50,16 @@
 
   public static Builder builder(
       AppView<? extends AppInfoWithClassHierarchy> appView, GraphLens previousLens) {
-    return new Builder(appView, previousLens);
+    return new Builder(appView, previousLens, new IdentityHashMap<>(), new IdentityHashMap<>());
+  }
+
+  public static Builder concurrentBuilder(AppView<? extends AppInfoWithClassHierarchy> appView) {
+    return concurrentBuilder(appView, appView.graphLens());
+  }
+
+  public static Builder concurrentBuilder(
+      AppView<? extends AppInfoWithClassHierarchy> appView, GraphLens previousLens) {
+    return new Builder(appView, previousLens, new ConcurrentHashMap<>(), new ConcurrentHashMap<>());
   }
 
   public void addNonReboundMethodReference(
@@ -174,14 +185,18 @@
     private final AppView<? extends AppInfoWithClassHierarchy> appView;
     private final GraphLens previousLens;
 
-    private final Map<DexField, DexField> nonReboundFieldReferenceToDefinitionMap =
-        new IdentityHashMap<>();
-    private final Map<DexMethod, DexMethod> nonReboundMethodReferenceToDefinitionMap =
-        new IdentityHashMap<>();
+    private final Map<DexField, DexField> nonReboundFieldReferenceToDefinitionMap;
+    private final Map<DexMethod, DexMethod> nonReboundMethodReferenceToDefinitionMap;
 
-    private Builder(AppView<? extends AppInfoWithClassHierarchy> appView, GraphLens previousLens) {
+    private Builder(
+        AppView<? extends AppInfoWithClassHierarchy> appView,
+        GraphLens previousLens,
+        Map<DexField, DexField> nonReboundFieldReferenceToDefinitionMap,
+        Map<DexMethod, DexMethod> nonReboundMethodReferenceToDefinitionMap) {
       this.appView = appView;
       this.previousLens = previousLens;
+      this.nonReboundFieldReferenceToDefinitionMap = nonReboundFieldReferenceToDefinitionMap;
+      this.nonReboundMethodReferenceToDefinitionMap = nonReboundMethodReferenceToDefinitionMap;
     }
 
     void recordNonReboundFieldAccesses(FieldAccessInfo fieldAccessInfo) {
@@ -203,11 +218,21 @@
           nonReboundMethodReference, reboundMethodReference);
     }
 
+    void recordFieldAccess(DexField reference) {
+      DexEncodedField resolvedField = appView.appInfo().resolveField(reference).getResolvedField();
+      if (resolvedField != null && resolvedField.getReference().isNotIdenticalTo(reference)) {
+        recordNonReboundFieldAccess(reference, resolvedField.getReference());
+      }
+    }
+
     void recordMethodAccess(DexMethod reference) {
       if (reference.getHolderType().isArrayType()) {
         return;
       }
-      DexClass holder = appView.contextIndependentDefinitionFor(reference.getHolderType());
+      // TODO(b/324526473): Use normal definitionFor() when LIR constant pool does not have any
+      //  outdated, unused constants.
+      DexClass holder =
+          appView.appInfo().definitionForWithoutExistenceAssert(reference.getHolderType());
       if (holder != null) {
         SingleResolutionResult<?> resolutionResult =
             appView.appInfo().resolveMethodOnLegacy(holder, reference).asSingleResolution();
diff --git a/src/main/java/com/android/tools/r8/optimize/MemberRebindingIdentityLensFactory.java b/src/main/java/com/android/tools/r8/optimize/MemberRebindingIdentityLensFactory.java
index 19e25d2..f2a6f2b 100644
--- a/src/main/java/com/android/tools/r8/optimize/MemberRebindingIdentityLensFactory.java
+++ b/src/main/java/com/android/tools/r8/optimize/MemberRebindingIdentityLensFactory.java
@@ -4,24 +4,17 @@
 
 package com.android.tools.r8.optimize;
 
-import com.android.tools.r8.graph.AbstractAccessContexts.ConcreteAccessContexts;
 import com.android.tools.r8.graph.AppInfoWithClassHierarchy;
 import com.android.tools.r8.graph.AppView;
-import com.android.tools.r8.graph.DefaultUseRegistry;
-import com.android.tools.r8.graph.DexClass;
 import com.android.tools.r8.graph.DexField;
+import com.android.tools.r8.graph.DexMember;
 import com.android.tools.r8.graph.DexMethod;
 import com.android.tools.r8.graph.FieldAccessInfoCollection;
-import com.android.tools.r8.graph.FieldAccessInfoCollectionImpl;
-import com.android.tools.r8.graph.FieldAccessInfoImpl;
 import com.android.tools.r8.graph.MethodAccessInfoCollection;
-import com.android.tools.r8.graph.MethodResolutionResult.SingleResolutionResult;
 import com.android.tools.r8.graph.ProgramMethod;
+import com.android.tools.r8.graph.ReferencedMembersCollector;
+import com.android.tools.r8.graph.ReferencedMembersCollector.ReferencedMembersConsumer;
 import com.android.tools.r8.shaking.AppInfoWithLiveness;
-import com.android.tools.r8.utils.SetUtils;
-import com.android.tools.r8.utils.ThreadUtils;
-import com.android.tools.r8.utils.collections.ProgramMethodSet;
-import java.util.Map;
 import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ExecutionException;
@@ -29,62 +22,39 @@
 
 public class MemberRebindingIdentityLensFactory {
 
-  /**
-   * In order to construct an instance of {@link MemberRebindingIdentityLens} we need a mapping from
-   * non-rebound field and method references to their definitions.
-   *
-   * <p>If shrinking or minification is enabled, we retrieve these from {@link AppInfoWithLiveness}.
-   * Otherwise we apply the {@link NonReboundMemberReferencesRegistry} below to all code objects to
-   * compute the mapping.
-   */
-  public static MemberRebindingIdentityLens rebuild(
-      AppView<? extends AppInfoWithClassHierarchy> appView, ExecutorService executorService)
-      throws ExecutionException {
-    FieldAccessInfoCollectionImpl mutableFieldAccessInfoCollection =
-        new FieldAccessInfoCollectionImpl(new ConcurrentHashMap<>());
-    MethodAccessInfoCollection.ConcurrentBuilder methodAccessInfoCollectionBuilder =
-        MethodAccessInfoCollection.concurrentBuilder();
-    initializeMemberAccessInfoCollectionsForMemberRebinding(
-        appView,
-        mutableFieldAccessInfoCollection,
-        methodAccessInfoCollectionBuilder,
-        executorService);
-    return create(
-        appView, mutableFieldAccessInfoCollection, methodAccessInfoCollectionBuilder.build());
+  public static MemberRebindingIdentityLens createFromAppInfo(
+      AppView<AppInfoWithLiveness> appView) {
+    FieldAccessInfoCollection<?> fieldAccessInfoCollection =
+        appView.appInfo().getFieldAccessInfoCollection();
+    MethodAccessInfoCollection methodAccessInfoCollection =
+        appView.appInfo().getMethodAccessInfoCollection();
+    return create(appView, fieldAccessInfoCollection, methodAccessInfoCollection);
   }
 
-  /**
-   * In order to construct an instance of {@link MemberRebindingIdentityLens} we need a mapping from
-   * non-rebound field and method references to their definitions.
-   *
-   * <p>If shrinking or minification is enabled, we retrieve these from {@link AppInfoWithLiveness}.
-   * Otherwise we apply the {@link NonReboundMemberReferencesRegistry} below to all code objects to
-   * compute the mapping.
-   */
-  public static MemberRebindingIdentityLens create(
+  public static MemberRebindingIdentityLens createFromLir(
       AppView<? extends AppInfoWithClassHierarchy> appView, ExecutorService executorService)
       throws ExecutionException {
-    FieldAccessInfoCollection<?> fieldAccessInfoCollection;
-    MethodAccessInfoCollection methodAccessInfoCollection;
-    if (appView.appInfo().hasLiveness()
-        && appView.options().testing.alwaysUseExistingAccessInfoCollectionsInMemberRebinding) {
-      AppInfoWithLiveness appInfo = appView.appInfo().withLiveness();
-      fieldAccessInfoCollection = appInfo.getFieldAccessInfoCollection();
-      methodAccessInfoCollection = appInfo.getMethodAccessInfoCollection();
-    } else {
-      FieldAccessInfoCollectionImpl mutableFieldAccessInfoCollection =
-          new FieldAccessInfoCollectionImpl(new ConcurrentHashMap<>());
-      MethodAccessInfoCollection.ConcurrentBuilder methodAccessInfoCollectionBuilder =
-          MethodAccessInfoCollection.concurrentBuilder();
-      initializeMemberAccessInfoCollectionsForMemberRebinding(
-          appView,
-          mutableFieldAccessInfoCollection,
-          methodAccessInfoCollectionBuilder,
-          executorService);
-      fieldAccessInfoCollection = mutableFieldAccessInfoCollection;
-      methodAccessInfoCollection = methodAccessInfoCollectionBuilder.build();
-    }
-    return create(appView, fieldAccessInfoCollection, methodAccessInfoCollection);
+    MemberRebindingIdentityLens.Builder builder =
+        MemberRebindingIdentityLens.concurrentBuilder(appView);
+    Set<DexMember<?, ?>> seen = ConcurrentHashMap.newKeySet();
+    ReferencedMembersConsumer consumer =
+        new ReferencedMembersConsumer() {
+          @Override
+          public void onFieldReference(DexField field, ProgramMethod context) {
+            if (seen.add(field)) {
+              builder.recordFieldAccess(field);
+            }
+          }
+
+          @Override
+          public void onMethodReference(DexMethod method, ProgramMethod context) {
+            if (seen.add(method)) {
+              builder.recordMethodAccess(method);
+            }
+          }
+        };
+    new ReferencedMembersCollector(appView, consumer).run(executorService);
+    return builder.build();
   }
 
   public static MemberRebindingIdentityLens create(
@@ -96,165 +66,4 @@
     methodAccessInfoCollection.forEachMethodReference(builder::recordMethodAccess);
     return builder.build();
   }
-
-  /**
-   * Applies {@link NonReboundMemberReferencesRegistry} to all code objects to construct a mapping
-   * from non-rebound field references to their definition.
-   */
-  private static void initializeMemberAccessInfoCollectionsForMemberRebinding(
-      AppView<? extends AppInfoWithClassHierarchy> appView,
-      FieldAccessInfoCollectionImpl fieldAccessInfoCollection,
-      MethodAccessInfoCollection.ConcurrentBuilder methodAccessInfoCollectionBuilder,
-      ExecutorService executorService)
-      throws ExecutionException {
-    Set<DexField> seenFieldReferences = SetUtils.newConcurrentHashSet();
-    Set<DexMethod> seenMethodReferences = SetUtils.newConcurrentHashSet();
-    ThreadUtils.processItems(
-        appView.appInfo()::forEachMethod,
-        method ->
-            new NonReboundMemberReferencesRegistry(
-                    appView,
-                    method,
-                    fieldAccessInfoCollection,
-                    methodAccessInfoCollectionBuilder,
-                    seenFieldReferences,
-                    seenMethodReferences)
-                .accept(method),
-        appView.options().getThreadingModule(),
-        executorService);
-  }
-
-  private static class NonReboundMemberReferencesRegistry
-      extends DefaultUseRegistry<ProgramMethod> {
-
-    private final AppInfoWithClassHierarchy appInfo;
-    private final FieldAccessInfoCollectionImpl fieldAccessInfoCollection;
-    private final MethodAccessInfoCollection.ConcurrentBuilder methodAccessInfoCollectionBuilder;
-    private final Set<DexField> seenFieldReferences;
-    private final Set<DexMethod> seenMethodReferences;
-
-    public NonReboundMemberReferencesRegistry(
-        AppView<? extends AppInfoWithClassHierarchy> appView,
-        ProgramMethod context,
-        FieldAccessInfoCollectionImpl fieldAccessInfoCollection,
-        MethodAccessInfoCollection.ConcurrentBuilder methodAccessInfoCollectionBuilder,
-        Set<DexField> seenFieldReferences,
-        Set<DexMethod> seenMethodReferences) {
-      super(appView, context);
-      this.appInfo = appView.appInfo();
-      this.fieldAccessInfoCollection = fieldAccessInfoCollection;
-      this.methodAccessInfoCollectionBuilder = methodAccessInfoCollectionBuilder;
-      this.seenFieldReferences = seenFieldReferences;
-      this.seenMethodReferences = seenMethodReferences;
-    }
-
-    @Override
-    public void registerInstanceFieldRead(DexField field) {
-      registerFieldAccess(field);
-    }
-
-    @Override
-    public void registerInstanceFieldWrite(DexField field) {
-      registerFieldAccess(field);
-    }
-
-    @Override
-    public void registerStaticFieldRead(DexField field) {
-      registerFieldAccess(field);
-    }
-
-    @Override
-    public void registerStaticFieldWrite(DexField field) {
-      registerFieldAccess(field);
-    }
-
-    @SuppressWarnings("ReferenceEquality")
-    private void registerFieldAccess(DexField field) {
-      if (!seenFieldReferences.add(field)) {
-        return;
-      }
-      appInfo
-          .resolveField(field)
-          .forEachSuccessfulFieldResolutionResult(
-              resolutionResult -> {
-                DexField reboundReference = resolutionResult.getResolvedField().getReference();
-                if (field == reboundReference) {
-                  // For the purpose of member rebinding, we don't care about already rebound
-                  // references.
-                  return;
-                }
-                FieldAccessInfoImpl fieldAccessInfo =
-                    fieldAccessInfoCollection.computeIfAbsent(
-                        reboundReference, FieldAccessInfoImpl::new);
-                synchronized (fieldAccessInfo) {
-                  // Record the fact that there is a non-rebound access to the given field. We don't
-                  // distinguish between non-rebound reads and writes, so we just record it as a
-                  // read.
-                  if (fieldAccessInfo.getReadsWithContexts().isBottom()) {
-                    fieldAccessInfo.setReadsWithContexts(new ConcreteAccessContexts());
-                  } else {
-                    assert fieldAccessInfo.getReadsWithContexts().isConcrete();
-                  }
-                  // For the purpose of member rebinding, we don't care about the access contexts,
-                  // so we
-                  // simply use the empty set.
-                  ConcreteAccessContexts accessContexts =
-                      fieldAccessInfo.getReadsWithContexts().asConcrete();
-                  accessContexts.getAccessesWithContexts().put(field, ProgramMethodSet.empty());
-                }
-              });
-    }
-
-    @Override
-    public void registerInvokeDirect(DexMethod method) {
-      registerInvokeMethod(method, methodAccessInfoCollectionBuilder.getDirectInvokes());
-    }
-
-    @Override
-    public void registerInvokeInterface(DexMethod method) {
-      registerInvokeMethod(method, methodAccessInfoCollectionBuilder.getInterfaceInvokes());
-    }
-
-    @Override
-    public void registerInvokeStatic(DexMethod method) {
-      registerInvokeMethod(method, methodAccessInfoCollectionBuilder.getStaticInvokes());
-    }
-
-    @Override
-    public void registerInvokeSuper(DexMethod method) {
-      registerInvokeMethod(method, methodAccessInfoCollectionBuilder.getSuperInvokes());
-    }
-
-    @Override
-    public void registerInvokeVirtual(DexMethod method) {
-      registerInvokeMethod(method, methodAccessInfoCollectionBuilder.getVirtualInvokes());
-    }
-
-    @SuppressWarnings("ReferenceEquality")
-    private void registerInvokeMethod(DexMethod method, Map<DexMethod, ProgramMethodSet> invokes) {
-      if (!seenMethodReferences.add(method)) {
-        return;
-      }
-      if (method.getHolderType().isArrayType()) {
-        return;
-      }
-      DexClass holder = appInfo.definitionFor(method.getHolderType(), getContext());
-      if (holder == null) {
-        return;
-      }
-      SingleResolutionResult<?> resolutionResult =
-          appInfo.resolveMethodOnLegacy(holder, method).asSingleResolution();
-      if (resolutionResult == null) {
-        return;
-      }
-      DexMethod reboundReference = resolutionResult.getResolvedMethod().getReference();
-      if (method == reboundReference) {
-        // For the purpose of member rebinding, we don't care about already rebound references.
-        return;
-      }
-      // For the purpose of member rebinding, we don't care about the access contexts, so we
-      // simply use the empty set.
-      invokes.put(method, ProgramMethodSet.empty());
-    }
-  }
 }
diff --git a/src/main/java/com/android/tools/r8/optimize/redundantbridgeremoval/RedundantBridgeRemover.java b/src/main/java/com/android/tools/r8/optimize/redundantbridgeremoval/RedundantBridgeRemover.java
index b1e1922..9c045cf 100644
--- a/src/main/java/com/android/tools/r8/optimize/redundantbridgeremoval/RedundantBridgeRemover.java
+++ b/src/main/java/com/android/tools/r8/optimize/redundantbridgeremoval/RedundantBridgeRemover.java
@@ -3,7 +3,10 @@
 // BSD-style license that can be found in the LICENSE file.
 package com.android.tools.r8.optimize.redundantbridgeremoval;
 
+import static com.android.tools.r8.graph.DexClassAndMethod.asProgramMethodOrNull;
+
 import com.android.tools.r8.graph.AppView;
+import com.android.tools.r8.graph.DefaultUseRegistry;
 import com.android.tools.r8.graph.DexClass;
 import com.android.tools.r8.graph.DexClassAndMethod;
 import com.android.tools.r8.graph.DexEncodedMethod;
@@ -27,6 +30,7 @@
 import com.android.tools.r8.shaking.KeepMethodInfo;
 import com.android.tools.r8.utils.ThreadUtils;
 import com.android.tools.r8.utils.Timing;
+import com.android.tools.r8.utils.WorkList;
 import com.android.tools.r8.utils.collections.ProgramMethodSet;
 import java.util.Collection;
 import java.util.List;
@@ -36,8 +40,14 @@
 
 public class RedundantBridgeRemover {
 
+  public enum RedundantBridgeRemoverMode {
+    INITIAL,
+    FINAL
+  }
+
   private final AppView<AppInfoWithLiveness> appView;
   private final ImmediateProgramSubtypingInfo immediateSubtypingInfo;
+  private final RedundantBridgeRemoverMode mode;
   private final RedundantBridgeRemovalOptions redundantBridgeRemovalOptions;
 
   private final RedundantBridgeRemovalLens.Builder lensBuilder =
@@ -45,9 +55,11 @@
 
   private boolean mustRetargetInvokesToTargetMethod = false;
 
-  public RedundantBridgeRemover(AppView<AppInfoWithLiveness> appView) {
+  public RedundantBridgeRemover(
+      AppView<AppInfoWithLiveness> appView, RedundantBridgeRemoverMode mode) {
     this.appView = appView;
     this.immediateSubtypingInfo = ImmediateProgramSubtypingInfo.create(appView);
+    this.mode = mode;
     this.redundantBridgeRemovalOptions = appView.options().getRedundantBridgeRemovalOptions();
   }
 
@@ -264,6 +276,7 @@
       extends DepthFirstTopDownClassHierarchyTraversal {
 
     private final ProgramMethodSet removedBridges = ProgramMethodSet.create();
+    private ProgramMethodSet superTargets = null;
 
     RedundantBridgeRemoverClassHierarchyTraversal() {
       super(
@@ -316,11 +329,7 @@
         return false;
       }
       // Check if the current method is an interface method targeted by invoke-super.
-      if (method.getHolder().isInterface()
-          && appView
-              .appInfo()
-              .getMethodAccessInfoCollection()
-              .hasSuperInvoke(method.getReference())) {
+      if (method.getHolder().isInterface() && hasSuperInvoke(method)) {
         return false;
       }
       // Check if all possible contexts that have access to the holder of the redundant bridge
@@ -353,5 +362,48 @@
     public void prune(DexProgramClass clazz) {
       // Empty.
     }
+
+    private boolean hasSuperInvoke(ProgramMethod method) {
+      if (mode == RedundantBridgeRemoverMode.INITIAL) {
+        return appView
+            .appInfo()
+            .getMethodAccessInfoCollection()
+            .hasSuperInvoke(method.getReference());
+      }
+      return getOrCreateSuperTargets(method.getHolder()).contains(method);
+    }
+
+    private ProgramMethodSet getOrCreateSuperTargets(DexProgramClass root) {
+      if (superTargets != null) {
+        return superTargets;
+      }
+      AppView<AppInfoWithLiveness> appViewWithLiveness = appView;
+      superTargets = ProgramMethodSet.create();
+      WorkList<DexProgramClass> worklist =
+          WorkList.newIdentityWorkList(immediateSubtypingInfo.getSubclasses(root));
+      while (worklist.hasNext()) {
+        DexProgramClass clazz = worklist.next();
+        clazz.forEachProgramMethodMatching(
+            DexEncodedMethod::hasCode,
+            method ->
+                method.registerCodeReferences(
+                    new DefaultUseRegistry<>(appView, method) {
+
+                      @Override
+                      public void registerInvokeSuper(DexMethod method) {
+                        ProgramMethod superTarget =
+                            asProgramMethodOrNull(
+                                appViewWithLiveness
+                                    .appInfo()
+                                    .lookupSuperTarget(method, getContext(), appViewWithLiveness));
+                        if (superTarget != null) {
+                          superTargets.add(superTarget);
+                        }
+                      }
+                    }));
+        worklist.addIfNotSeen(immediateSubtypingInfo.getSubclasses(clazz));
+      }
+      return superTargets;
+    }
   }
 }
diff --git a/src/main/java/com/android/tools/r8/optimize/singlecaller/SingleCallerInliner.java b/src/main/java/com/android/tools/r8/optimize/singlecaller/SingleCallerInliner.java
index 3a0e9a1..126960b 100644
--- a/src/main/java/com/android/tools/r8/optimize/singlecaller/SingleCallerInliner.java
+++ b/src/main/java/com/android/tools/r8/optimize/singlecaller/SingleCallerInliner.java
@@ -176,7 +176,6 @@
         });
     PrunedItems prunedItems = prunedItemsBuilder.build();
     appView.pruneItems(prunedItems, executorService, Timing.empty());
-    appView.appInfo().getMethodAccessInfoCollection().withoutPrunedItems(prunedItems);
   }
 
   private static class SingleCallerInlinerImpl extends Inliner {
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 a41b281..6680806 100644
--- a/src/main/java/com/android/tools/r8/shaking/AppInfoWithLiveness.java
+++ b/src/main/java/com/android/tools/r8/shaking/AppInfoWithLiveness.java
@@ -467,7 +467,6 @@
   @Override
   public void notifyMinifierFinished() {
     liveMethods = ThrowingSet.get();
-    getMethodAccessInfoCollection().destroy();
   }
 
   public void notifyTreePrunerFinished(Enqueuer.Mode mode) {
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 eee85a1..3640796 100644
--- a/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
+++ b/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
@@ -4481,7 +4481,7 @@
             toDescriptorSet(liveMethods.getItems()),
             // Filter out library fields and pinned fields, because these are read by default.
             fieldAccessInfoCollection,
-            methodAccessInfoCollection.build(),
+            methodAccessInfoCollection.build(mode),
             objectAllocationInfoCollection.build(appInfo),
             callSites,
             keepInfo,
diff --git a/src/test/examples/naming001/keep-rules-001.txt b/src/test/examples/naming001/keep-rules-001.txt
index 72be5a2..885f5cf 100644
--- a/src/test/examples/naming001/keep-rules-001.txt
+++ b/src/test/examples/naming001/keep-rules-001.txt
@@ -3,5 +3,6 @@
 # BSD-style license that can be found in the LICENSE file.
 
 -allowaccessmodification
+-dontshrink
 
 -keep class naming001.A
diff --git a/src/test/examples/naming001/keep-rules-002.txt b/src/test/examples/naming001/keep-rules-002.txt
index 1554e31..62e3976 100644
--- a/src/test/examples/naming001/keep-rules-002.txt
+++ b/src/test/examples/naming001/keep-rules-002.txt
@@ -3,6 +3,7 @@
 # BSD-style license that can be found in the LICENSE file.
 
 -allowaccessmodification
+-dontshrink
 
 -keep !final class naming001.A {
   private <methods>;
diff --git a/src/test/examples/naming001/keep-rules-003.txt b/src/test/examples/naming001/keep-rules-003.txt
index cdcab79..4846f64 100644
--- a/src/test/examples/naming001/keep-rules-003.txt
+++ b/src/test/examples/naming001/keep-rules-003.txt
@@ -3,6 +3,7 @@
 # BSD-style license that can be found in the LICENSE file.
 
 -allowaccessmodification
+-dontshrink
 
 -keep !final class naming001.A {
   !private <methods>;
diff --git a/src/test/examples/naming001/keep-rules-005.txt b/src/test/examples/naming001/keep-rules-005.txt
index ef4b5c8..b15cc5c 100644
--- a/src/test/examples/naming001/keep-rules-005.txt
+++ b/src/test/examples/naming001/keep-rules-005.txt
@@ -3,6 +3,7 @@
 # BSD-style license that can be found in the LICENSE file.
 
 -allowaccessmodification
+-dontshrink
 
 -keep class naming001.D {
   public static void main(...);
diff --git a/src/test/examples/naming001/keep-rules-006.txt b/src/test/examples/naming001/keep-rules-006.txt
index 7a8e99e..2b69f6c 100644
--- a/src/test/examples/naming001/keep-rules-006.txt
+++ b/src/test/examples/naming001/keep-rules-006.txt
@@ -3,6 +3,7 @@
 # BSD-style license that can be found in the LICENSE file.
 
 -allowaccessmodification
+-dontshrink
 
 -keep class naming001.G {
   public static void main(...);
diff --git a/src/test/examples/naming001/keep-rules-014.txt b/src/test/examples/naming001/keep-rules-014.txt
index 6423782..6c10eb8 100644
--- a/src/test/examples/naming001/keep-rules-014.txt
+++ b/src/test/examples/naming001/keep-rules-014.txt
@@ -3,6 +3,7 @@
 # BSD-style license that can be found in the LICENSE file.
 
 -allowaccessmodification
+-dontshrink
 
 -keep class naming001.Reflect {
   *** keep6();
diff --git a/src/test/examples/naming001/keep-rules-017.txt b/src/test/examples/naming001/keep-rules-017.txt
index b146df8..20f585f 100644
--- a/src/test/examples/naming001/keep-rules-017.txt
+++ b/src/test/examples/naming001/keep-rules-017.txt
@@ -3,6 +3,7 @@
 # BSD-style license that can be found in the LICENSE file.
 
 -allowaccessmodification
+-dontshrink
 
 -keep class naming001.K {
   void keep();
diff --git a/src/test/examples/naming001/keep-rules-105.txt b/src/test/examples/naming001/keep-rules-105.txt
index 011596b..02a54e6 100644
--- a/src/test/examples/naming001/keep-rules-105.txt
+++ b/src/test/examples/naming001/keep-rules-105.txt
@@ -3,6 +3,7 @@
 # BSD-style license that can be found in the LICENSE file.
 
 -allowaccessmodification
+-dontshrink
 
 -keep class naming001.D {
   public static void main(...);
diff --git a/src/test/examples/naming001/keep-rules-106.txt b/src/test/examples/naming001/keep-rules-106.txt
index ca320eb..744c783 100644
--- a/src/test/examples/naming001/keep-rules-106.txt
+++ b/src/test/examples/naming001/keep-rules-106.txt
@@ -2,4 +2,5 @@
 # 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.
 
--applymapping mapping-106.txt
\ No newline at end of file
+-applymapping mapping-106.txt
+-dontshrink
\ No newline at end of file
diff --git a/src/test/java/com/android/tools/r8/naming/NamingTestBase.java b/src/test/java/com/android/tools/r8/naming/NamingTestBase.java
index c71f930..daff675 100644
--- a/src/test/java/com/android/tools/r8/naming/NamingTestBase.java
+++ b/src/test/java/com/android/tools/r8/naming/NamingTestBase.java
@@ -9,6 +9,7 @@
 import com.android.tools.r8.ToolHelper;
 import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.DexItemFactory;
+import com.android.tools.r8.ir.conversion.LirConverter;
 import com.android.tools.r8.shaking.AppInfoWithLiveness;
 import com.android.tools.r8.utils.AndroidApp;
 import com.android.tools.r8.utils.Timing;
@@ -53,6 +54,7 @@
     dexItemFactory = appView.dexItemFactory();
     ExecutorService executor = Executors.newSingleThreadExecutor();
     try {
+      LirConverter.enterLirSupportedPhase(appView, executor);
       new Minifier(appView).run(executor, Timing.empty());
     } finally {
       executor.shutdown();