Apply Prototype changes only when needed

Bug: 149790050
Change-Id: Ic4c19c8ac2c34d91ad1eed4c9116fc5bc9054ee6
diff --git a/src/main/java/com/android/tools/r8/graph/CfCode.java b/src/main/java/com/android/tools/r8/graph/CfCode.java
index 5c8de46..4f8fa23 100644
--- a/src/main/java/com/android/tools/r8/graph/CfCode.java
+++ b/src/main/java/com/android/tools/r8/graph/CfCode.java
@@ -22,6 +22,7 @@
 import com.android.tools.r8.ir.code.ValueNumberGenerator;
 import com.android.tools.r8.ir.conversion.CfSourceCode;
 import com.android.tools.r8.ir.conversion.IRBuilder;
+import com.android.tools.r8.ir.conversion.MethodProcessor;
 import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
 import com.android.tools.r8.ir.optimize.InliningConstraints;
 import com.android.tools.r8.naming.ClassNameMapper;
@@ -210,7 +211,7 @@
     for (CfInstruction instruction : instructions) {
       if (instruction instanceof CfFrame
           && (classFileVersion <= 49
-              || (classFileVersion == 50 && !options.shouldKeepStackMapTable()))) {
+          || (classFileVersion == 50 && !options.shouldKeepStackMapTable()))) {
         continue;
       }
       instruction.write(visitor, namingLens);
@@ -287,7 +288,7 @@
   @Override
   public IRCode buildIR(DexEncodedMethod encodedMethod, AppView<?> appView, Origin origin) {
     return internalBuildPossiblyWithLocals(
-        encodedMethod, encodedMethod, appView, null, null, origin);
+        encodedMethod, encodedMethod, appView, null, null, origin, null);
   }
 
   @Override
@@ -297,11 +298,18 @@
       AppView<?> appView,
       ValueNumberGenerator valueNumberGenerator,
       Position callerPosition,
-      Origin origin) {
+      Origin origin,
+      MethodProcessor methodProcessor) {
     assert valueNumberGenerator != null;
     assert callerPosition != null;
     return internalBuildPossiblyWithLocals(
-        context, encodedMethod, appView, valueNumberGenerator, callerPosition, origin);
+        context,
+        encodedMethod,
+        appView,
+        valueNumberGenerator,
+        callerPosition,
+        origin,
+        methodProcessor);
   }
 
   // First build entry. Will either strip locals or build with locals.
@@ -311,7 +319,8 @@
       AppView<?> appView,
       ValueNumberGenerator generator,
       Position callerPosition,
-      Origin origin) {
+      Origin origin,
+      MethodProcessor methodProcessor) {
     if (!encodedMethod.keepLocals(appView.options())) {
       return internalBuild(
           Collections.emptyList(),
@@ -320,10 +329,11 @@
           appView,
           generator,
           callerPosition,
-          origin);
+          origin,
+          methodProcessor);
     } else {
       return internalBuildWithLocals(
-          context, encodedMethod, appView, generator, callerPosition, origin);
+          context, encodedMethod, appView, generator, callerPosition, origin, methodProcessor);
     }
   }
 
@@ -334,7 +344,8 @@
       AppView<?> appView,
       ValueNumberGenerator generator,
       Position callerPosition,
-      Origin origin) {
+      Origin origin,
+      MethodProcessor methodProcessor) {
     try {
       return internalBuild(
           Collections.unmodifiableList(localVariables),
@@ -343,7 +354,8 @@
           appView,
           generator,
           callerPosition,
-          origin);
+          origin,
+          methodProcessor);
     } catch (InvalidDebugInfoException e) {
       appView.options().warningInvalidDebugInfo(encodedMethod, origin, e);
       return internalBuild(
@@ -353,19 +365,21 @@
           appView,
           generator,
           callerPosition,
-          origin);
+          origin,
+          methodProcessor);
     }
   }
 
   // Inner-most subroutine for building. Must only be called by the two internalBuildXYZ above.
   private IRCode internalBuild(
-      List<CfCode.LocalVariableInfo> localVariables,
+      List<LocalVariableInfo> localVariables,
       DexEncodedMethod context,
       DexEncodedMethod encodedMethod,
       AppView<?> appView,
       ValueNumberGenerator generator,
       Position callerPosition,
-      Origin origin) {
+      Origin origin,
+      MethodProcessor methodProcessor) {
     CfSourceCode source =
         new CfSourceCode(
             this,
@@ -375,7 +389,11 @@
             callerPosition,
             origin,
             appView);
-    return new IRBuilder(encodedMethod, appView, source, origin, generator).build(context);
+    IRBuilder builder = methodProcessor == null ?
+        IRBuilder.create(encodedMethod, appView, source, origin) :
+        IRBuilder
+            .createForInlining(encodedMethod, appView, source, origin, methodProcessor, generator);
+    return builder.build(context);
   }
 
   @Override
diff --git a/src/main/java/com/android/tools/r8/graph/Code.java b/src/main/java/com/android/tools/r8/graph/Code.java
index 0fbae38..8e81c8e 100644
--- a/src/main/java/com/android/tools/r8/graph/Code.java
+++ b/src/main/java/com/android/tools/r8/graph/Code.java
@@ -9,6 +9,7 @@
 import com.android.tools.r8.ir.code.IRCode;
 import com.android.tools.r8.ir.code.Position;
 import com.android.tools.r8.ir.code.ValueNumberGenerator;
+import com.android.tools.r8.ir.conversion.MethodProcessor;
 import com.android.tools.r8.ir.optimize.Outliner.OutlineCode;
 import com.android.tools.r8.naming.ClassNameMapper;
 import com.android.tools.r8.origin.Origin;
@@ -24,7 +25,8 @@
       AppView<?> appView,
       ValueNumberGenerator valueNumberGenerator,
       Position callerPosition,
-      Origin origin) {
+      Origin origin,
+      MethodProcessor methodProcessor) {
     throw new Unreachable("Unexpected attempt to build IR graph for inlining from: "
         + getClass().getCanonicalName());
   }
diff --git a/src/main/java/com/android/tools/r8/graph/DexCode.java b/src/main/java/com/android/tools/r8/graph/DexCode.java
index d32abdf..9c02dec 100644
--- a/src/main/java/com/android/tools/r8/graph/DexCode.java
+++ b/src/main/java/com/android/tools/r8/graph/DexCode.java
@@ -16,6 +16,7 @@
 import com.android.tools.r8.ir.code.ValueNumberGenerator;
 import com.android.tools.r8.ir.conversion.DexSourceCode;
 import com.android.tools.r8.ir.conversion.IRBuilder;
+import com.android.tools.r8.ir.conversion.MethodProcessor;
 import com.android.tools.r8.naming.ClassNameMapper;
 import com.android.tools.r8.origin.Origin;
 import com.android.tools.r8.utils.StringUtils;
@@ -220,9 +221,7 @@
             encodedMethod,
             appView.graphLense().getOriginalMethodSignature(encodedMethod.method),
             null);
-    IRBuilder builder =
-        new IRBuilder(encodedMethod, appView, source, origin, new ValueNumberGenerator());
-    return builder.build(encodedMethod);
+    return IRBuilder.create(encodedMethod,appView,source,origin).build(encodedMethod);
   }
 
   @Override
@@ -232,15 +231,16 @@
       AppView<?> appView,
       ValueNumberGenerator valueNumberGenerator,
       Position callerPosition,
-      Origin origin) {
+      Origin origin,
+      MethodProcessor methodProcessor) {
     DexSourceCode source =
         new DexSourceCode(
             this,
             encodedMethod,
             appView.graphLense().getOriginalMethodSignature(encodedMethod.method),
             callerPosition);
-    IRBuilder builder = new IRBuilder(encodedMethod, appView, source, origin, valueNumberGenerator);
-    return builder.build(context);
+    return IRBuilder.createForInlining(
+        encodedMethod, appView, source, origin, methodProcessor, valueNumberGenerator).build(context);
   }
 
   @Override
diff --git a/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java b/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java
index b755c49..1fdd415 100644
--- a/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java
+++ b/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java
@@ -40,6 +40,7 @@
 import com.android.tools.r8.ir.code.ValueNumberGenerator;
 import com.android.tools.r8.ir.code.ValueType;
 import com.android.tools.r8.ir.conversion.DexBuilder;
+import com.android.tools.r8.ir.conversion.MethodProcessor;
 import com.android.tools.r8.ir.desugar.NestBasedAccessDesugaring.DexFieldWithAccess;
 import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
 import com.android.tools.r8.ir.optimize.Inliner.Reason;
@@ -550,10 +551,11 @@
       AppView<?> appView,
       ValueNumberGenerator valueNumberGenerator,
       Position callerPosition,
-      Origin origin) {
+      Origin origin,
+      MethodProcessor methodProcessor) {
     checkIfObsolete();
     return code.buildInliningIR(
-        context, this, appView, valueNumberGenerator, callerPosition, origin);
+        context, this, appView, valueNumberGenerator, callerPosition, origin, methodProcessor);
   }
 
   public void setCode(Code newCode, AppView<?> appView) {
diff --git a/src/main/java/com/android/tools/r8/graph/LazyCfCode.java b/src/main/java/com/android/tools/r8/graph/LazyCfCode.java
index ec6cba3..41499ea 100644
--- a/src/main/java/com/android/tools/r8/graph/LazyCfCode.java
+++ b/src/main/java/com/android/tools/r8/graph/LazyCfCode.java
@@ -56,6 +56,7 @@
 import com.android.tools.r8.ir.code.Position;
 import com.android.tools.r8.ir.code.ValueNumberGenerator;
 import com.android.tools.r8.ir.code.ValueType;
+import com.android.tools.r8.ir.conversion.MethodProcessor;
 import com.android.tools.r8.naming.ClassNameMapper;
 import com.android.tools.r8.origin.Origin;
 import com.android.tools.r8.position.MethodPosition;
@@ -200,10 +201,17 @@
       AppView<?> appView,
       ValueNumberGenerator valueNumberGenerator,
       Position callerPosition,
-      Origin origin) {
+      Origin origin,
+      MethodProcessor methodProcessor) {
     return asCfCode()
         .buildInliningIR(
-            context, encodedMethod, appView, valueNumberGenerator, callerPosition, origin);
+            context,
+            encodedMethod,
+            appView,
+            valueNumberGenerator,
+            callerPosition,
+            origin,
+            methodProcessor);
   }
 
   @Override
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/IRBuilder.java b/src/main/java/com/android/tools/r8/ir/conversion/IRBuilder.java
index 78b1405..0e24fe9 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/IRBuilder.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/IRBuilder.java
@@ -33,7 +33,6 @@
 import com.android.tools.r8.graph.DexReference;
 import com.android.tools.r8.graph.DexString;
 import com.android.tools.r8.graph.DexType;
-import com.android.tools.r8.graph.GraphLense;
 import com.android.tools.r8.graph.RewrittenPrototypeDescription;
 import com.android.tools.r8.graph.RewrittenPrototypeDescription.RemovedArgumentInfo;
 import com.android.tools.r8.graph.RewrittenPrototypeDescription.RemovedArgumentInfoCollection;
@@ -424,50 +423,66 @@
   // then the IR does not necessarily contain a const-string instruction).
   private final IRMetadata metadata = new IRMetadata();
 
-  public IRBuilder(DexEncodedMethod method, AppView<?> appView, SourceCode source, Origin origin) {
-    this(method, appView, source, origin, new ValueNumberGenerator());
+  public static IRBuilder create(DexEncodedMethod method,
+      AppView<?> appView,
+      SourceCode source,
+      Origin origin) {
+    return new IRBuilder(method,
+        appView,
+        source,
+        origin,
+        lookupPrototypeChanges(appView, method.method),
+        new ValueNumberGenerator());
   }
 
-  public IRBuilder(
+  public static IRBuilder createForInlining(DexEncodedMethod method,
+      AppView<?> appView,
+      SourceCode source,
+      Origin origin,
+      MethodProcessor processor,
+      ValueNumberGenerator valueNumberGenerator) {
+    RewrittenPrototypeDescription protoChanges = processor.shouldApplyCodeRewritings(method) ?
+        lookupPrototypeChanges(appView, method.method) :
+        RewrittenPrototypeDescription.none();
+    return new IRBuilder(method,
+        appView,
+        source,
+        origin,
+        protoChanges,
+        valueNumberGenerator);
+  }
+
+  private static RewrittenPrototypeDescription lookupPrototypeChanges(AppView<?> appView,
+      DexMethod method) {
+    RewrittenPrototypeDescription prototypeChanges = appView.graphLense()
+        .lookupPrototypeChanges(method);
+    if (Log.ENABLED
+        && prototypeChanges.getRemovedArgumentInfoCollection().hasRemovedArguments()) {
+      Log.info(
+          IRBuilder.class,
+          "Removed "
+              + prototypeChanges.getRemovedArgumentInfoCollection().numberOfRemovedArguments()
+              + " arguments from "
+              + method.toSourceString());
+    }
+    return prototypeChanges;
+  }
+
+  private IRBuilder(
       DexEncodedMethod method,
       AppView<?> appView,
       SourceCode source,
       Origin origin,
+      RewrittenPrototypeDescription prototypeChanges,
       ValueNumberGenerator valueNumberGenerator) {
     assert source != null;
+    assert valueNumberGenerator != null;
     this.method = method;
     this.appView = appView;
     this.source = source;
-    this.valueNumberGenerator =
-        valueNumberGenerator != null ? valueNumberGenerator : new ValueNumberGenerator();
     this.origin = origin;
-
-    if (method.isProcessed()) {
-      // NOTE: This is currently assuming that we never remove additional arguments from methods
-      // after they have already been processed once.
-      assert verifyMethodSignature(method, appView.graphLense());
-      this.prototypeChanges = RewrittenPrototypeDescription.none();
-    } else {
-      this.prototypeChanges = appView.graphLense().lookupPrototypeChanges(method.method);
-
-      if (Log.ENABLED
-          && prototypeChanges.getRemovedArgumentInfoCollection().hasRemovedArguments()) {
-        Log.info(
-            getClass(),
-            "Removed "
-                + prototypeChanges.getRemovedArgumentInfoCollection().numberOfRemovedArguments()
-                + " arguments from "
-                + method.toSourceString());
-      }
-    }
-  }
-
-  private static boolean verifyMethodSignature(DexEncodedMethod method, GraphLense graphLense) {
-    RewrittenPrototypeDescription prototypeChanges =
-        graphLense.lookupPrototypeChanges(method.method);
-    assert !prototypeChanges.hasBeenChangedToReturnVoid()
-        || method.method.proto.returnType.isVoidType();
-    return true;
+    this.prototypeChanges = prototypeChanges;
+    this.valueNumberGenerator = valueNumberGenerator;
   }
 
   public DexEncodedMethod getMethod() {
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 cb39d6f..94e5cf4 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
@@ -716,12 +716,11 @@
       // TODO(b/127694949): Adapt to PostOptimization.
       staticizeClasses(feedback, executorService);
       feedback.updateVisibleOptimizationInfo();
+      // The class staticizer lens shall not be applied through lens code rewriting or it breaks
+      // the lambda merger.
+      appView.clearCodeRewritings();
     }
 
-    // The class staticizer lens shall not be applied through lens code rewriting or it breaks
-    // the lambda merger.
-    appView.clearCodeRewritings();
-
     // Build a new application with jumbo string info.
     Builder<?> builder = application.builder();
     builder.setHighestSortingString(highestSortingString);
@@ -1148,7 +1147,7 @@
 
     if (lambdaMerger != null) {
       timing.begin("Merge lambdas");
-      lambdaMerger.rewriteCode(method, code, inliner);
+      lambdaMerger.rewriteCode(method, code, inliner, methodProcessor);
       timing.end();
       assert code.isConsistentSSA();
     }
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/MethodProcessor.java b/src/main/java/com/android/tools/r8/ir/conversion/MethodProcessor.java
index 34609c9..0c2eb60 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/MethodProcessor.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/MethodProcessor.java
@@ -15,6 +15,8 @@
 
   Phase getPhase();
 
+  boolean shouldApplyCodeRewritings(DexEncodedMethod method);
+
   default boolean isPrimary() {
     return getPhase() == Phase.PRIMARY;
   }
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/OneTimeMethodProcessor.java b/src/main/java/com/android/tools/r8/ir/conversion/OneTimeMethodProcessor.java
index b55f54f..939395f 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/OneTimeMethodProcessor.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/OneTimeMethodProcessor.java
@@ -31,6 +31,11 @@
   }
 
   @Override
+  public boolean shouldApplyCodeRewritings(DexEncodedMethod method) {
+    return true;
+  }
+
+  @Override
   public Phase getPhase() {
     return Phase.ONE_TIME;
   }
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/PostMethodProcessor.java b/src/main/java/com/android/tools/r8/ir/conversion/PostMethodProcessor.java
index 9616c47..529bdc7 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/PostMethodProcessor.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/PostMethodProcessor.java
@@ -16,6 +16,7 @@
 import com.android.tools.r8.utils.ThreadUtils;
 import com.android.tools.r8.utils.Timing;
 import com.google.common.collect.Maps;
+import com.google.common.collect.Sets;
 import java.util.ArrayDeque;
 import java.util.Collection;
 import java.util.Deque;
@@ -33,6 +34,7 @@
   private final Map<DexEncodedMethod, Collection<CodeOptimization>> methodsMap;
   private final Deque<Set<DexEncodedMethod>> waves;
   private Set<DexEncodedMethod> wave;
+  private final Set<DexEncodedMethod> processed = Sets.newIdentityHashSet();
 
   private PostMethodProcessor(
       AppView<AppInfoWithLiveness> appView,
@@ -48,6 +50,12 @@
     return Phase.POST;
   }
 
+  @Override
+  public boolean shouldApplyCodeRewritings(DexEncodedMethod method) {
+    assert !wave.contains(method);
+    return !processed.contains(method);
+  }
+
   static class Builder {
     private final Collection<CodeOptimization> defaultCodeOptimizations;
     private final Map<DexEncodedMethod, Collection<CodeOptimization>> methodsMap =
@@ -141,6 +149,7 @@
             forEachMethod(method, codeOptimizations, feedback);
           },
           executorService);
+      processed.addAll(wave);
     }
   }
 
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 8fb6afb..5b26255 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
@@ -65,6 +65,12 @@
   }
 
   @Override
+  public boolean shouldApplyCodeRewritings(DexEncodedMethod method) {
+    assert !wave.contains(method);
+    return !method.isProcessed();
+  }
+
+  @Override
   public CallSiteInformation getCallSiteInformation() {
     return callSiteInformation;
   }
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 7618cb6..ee62dc3 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
@@ -718,11 +718,12 @@
         }
       }
 
-      if (!target.isProcessed()) {
+      if (inliningIRProvider.shouldApplyCodeRewritings(code.method)) {
+        assert lensCodeRewriter != null;
         lensCodeRewriter.rewrite(code, target);
       }
       if (lambdaMerger != null) {
-        lambdaMerger.rewriteCodeForInlining(target, code, context);
+        lambdaMerger.rewriteCodeForInlining(target, code, context, inliningIRProvider);
       }
       assert code.isConsistentSSA();
       return new InlineeWithReason(code, reason);
@@ -817,14 +818,6 @@
   public void performForcedInlining(
       DexEncodedMethod method,
       IRCode code,
-      Map<? extends InvokeMethod, InliningInfo> invokesToInline) {
-    performForcedInlining(
-        method, code, invokesToInline, new InliningIRProvider(appView, method, code));
-  }
-
-  public void performForcedInlining(
-      DexEncodedMethod method,
-      IRCode code,
       Map<? extends InvokeMethod, InliningInfo> invokesToInline,
       InliningIRProvider inliningIRProvider) {
     ForcedInliningOracle oracle = new ForcedInliningOracle(appView, method, invokesToInline);
@@ -859,7 +852,8 @@
             options.inliningInstructionLimit,
             options.inliningInstructionAllowance - numberOfInstructions(code),
             inliningReasonStrategy);
-    InliningIRProvider inliningIRProvider = new InliningIRProvider(appView, method, code);
+    InliningIRProvider inliningIRProvider =
+        new InliningIRProvider(appView, method, code, methodProcessor);
     assert inliningIRProvider.verifyIRCacheIsEmpty();
     performInliningImpl(oracle, oracle, method, code, feedback, inliningIRProvider);
   }
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/Outliner.java b/src/main/java/com/android/tools/r8/ir/optimize/Outliner.java
index ea419cc..002abc9 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/Outliner.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/Outliner.java
@@ -1595,7 +1595,8 @@
     @Override
     public IRCode buildIR(DexEncodedMethod encodedMethod, AppView<?> appView, Origin origin) {
       OutlineSourceCode source = new OutlineSourceCode(outline, encodedMethod.method);
-      return new IRBuilder(encodedMethod, appView, source, origin).build(encodedMethod);
+      return IRBuilder.create(encodedMethod, appView, source, origin)
+          .build(encodedMethod);
     }
 
     @Override
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/classinliner/ClassInliner.java b/src/main/java/com/android/tools/r8/ir/optimize/classinliner/ClassInliner.java
index b20eba1..291f4d5 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/classinliner/ClassInliner.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/classinliner/ClassInliner.java
@@ -227,7 +227,8 @@
         assert processor.getReceivers().verifyReceiverSetsAreDisjoint();
 
         // Is inlining allowed.
-        InliningIRProvider inliningIRProvider = new InliningIRProvider(appView, method, code);
+        InliningIRProvider inliningIRProvider =
+            new InliningIRProvider(appView, method, code, methodProcessor);
         ClassInlinerCostAnalysis costAnalysis =
             new ClassInlinerCostAnalysis(
                 appView, inliningIRProvider, processor.getReceivers().getDefiniteReceiverAliases());
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/inliner/InliningIRProvider.java b/src/main/java/com/android/tools/r8/ir/optimize/inliner/InliningIRProvider.java
index b1408dd..3a98637 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/inliner/InliningIRProvider.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/inliner/InliningIRProvider.java
@@ -10,6 +10,7 @@
 import com.android.tools.r8.ir.code.InvokeMethod;
 import com.android.tools.r8.ir.code.Position;
 import com.android.tools.r8.ir.code.ValueNumberGenerator;
+import com.android.tools.r8.ir.conversion.MethodProcessor;
 import com.android.tools.r8.origin.Origin;
 import java.util.IdentityHashMap;
 import java.util.Map;
@@ -19,13 +20,16 @@
   private final AppView<?> appView;
   private final DexEncodedMethod context;
   private final ValueNumberGenerator valueNumberGenerator;
+  private final MethodProcessor methodProcessor;
 
   private final Map<InvokeMethod, IRCode> cache = new IdentityHashMap<>();
 
-  public InliningIRProvider(AppView<?> appView, DexEncodedMethod context, IRCode code) {
+  public InliningIRProvider(
+      AppView<?> appView, DexEncodedMethod context, IRCode code, MethodProcessor methodProcessor) {
     this.appView = appView;
     this.context = context;
     this.valueNumberGenerator = code.valueNumberGenerator;
+    this.methodProcessor = methodProcessor;
   }
 
   public IRCode getInliningIR(InvokeMethod invoke, DexEncodedMethod method) {
@@ -35,7 +39,8 @@
     }
     Position position = Position.getPositionForInlining(appView, invoke, context);
     Origin origin = appView.appInfo().originFor(method.method.holder);
-    return method.buildInliningIR(context, appView, valueNumberGenerator, position, origin);
+    return method.buildInliningIR(
+        context, appView, valueNumberGenerator, position, origin, methodProcessor);
   }
 
   public IRCode getAndCacheInliningIR(InvokeMethod invoke, DexEncodedMethod method) {
@@ -53,4 +58,8 @@
     assert cache.isEmpty();
     return true;
   }
+
+  public boolean shouldApplyCodeRewritings(DexEncodedMethod method) {
+    return methodProcessor.shouldApplyCodeRewritings(method);
+  }
 }
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/lambda/LambdaMerger.java b/src/main/java/com/android/tools/r8/ir/optimize/lambda/LambdaMerger.java
index 6512985..ab02906 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/lambda/LambdaMerger.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/lambda/LambdaMerger.java
@@ -29,6 +29,7 @@
 import com.android.tools.r8.ir.code.StaticPut;
 import com.android.tools.r8.ir.code.Value;
 import com.android.tools.r8.ir.conversion.IRConverter;
+import com.android.tools.r8.ir.conversion.MethodProcessor;
 import com.android.tools.r8.ir.optimize.Inliner;
 import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
 import com.android.tools.r8.ir.optimize.Inliner.InliningInfo;
@@ -36,6 +37,7 @@
 import com.android.tools.r8.ir.optimize.info.MethodOptimizationInfo;
 import com.android.tools.r8.ir.optimize.info.OptimizationFeedback;
 import com.android.tools.r8.ir.optimize.info.OptimizationFeedback.OptimizationInfoFixer;
+import com.android.tools.r8.ir.optimize.inliner.InliningIRProvider;
 import com.android.tools.r8.ir.optimize.lambda.CodeProcessor.Strategy;
 import com.android.tools.r8.ir.optimize.lambda.LambdaGroup.LambdaStructureError;
 import com.android.tools.r8.ir.optimize.lambda.kotlin.KotlinLambdaGroupIdFactory;
@@ -92,7 +94,11 @@
   private abstract static class Mode {
 
     void rewriteCode(
-        DexEncodedMethod method, IRCode code, Inliner inliner, DexEncodedMethod context) {}
+        DexEncodedMethod method,
+        IRCode code,
+        Inliner inliner,
+        DexEncodedMethod context,
+        InliningIRProvider provider) {}
 
     void analyzeCode(DexEncodedMethod method, IRCode code) {}
   }
@@ -119,7 +125,11 @@
 
     @Override
     void rewriteCode(
-        DexEncodedMethod method, IRCode code, Inliner inliner, DexEncodedMethod context) {
+        DexEncodedMethod method,
+        IRCode code,
+        Inliner inliner,
+        DexEncodedMethod context,
+        InliningIRProvider provider) {
       DexProgramClass clazz = appView.definitionFor(method.method.holder).asProgramClass();
       assert clazz != null;
 
@@ -150,7 +160,7 @@
 
       assert invokesToInline.size() > 1;
 
-      inliner.performForcedInlining(method, code, invokesToInline);
+      inliner.performForcedInlining(method, code, invokesToInline, provider);
     }
   }
 
@@ -291,20 +301,27 @@
    *       no more invalid lambda class references.
    * </ol>
    */
-  public final void rewriteCode(DexEncodedMethod method, IRCode code, Inliner inliner) {
+  public final void rewriteCode(
+      DexEncodedMethod method, IRCode code, Inliner inliner, MethodProcessor methodProcessor) {
     if (mode != null) {
-      mode.rewriteCode(method, code, inliner, null);
+      mode.rewriteCode(
+          method,
+          code,
+          inliner,
+          null,
+          new InliningIRProvider(appView, method, code, methodProcessor));
     }
   }
 
   /**
-   * Similar to {@link #rewriteCode(DexEncodedMethod, IRCode, Inliner)}, but for rewriting code for
-   * inlining. The {@param context} is the caller that {@param method} is being inlined into.
+   * Similar to {@link #rewriteCode(DexEncodedMethod, IRCode, Inliner, MethodProcessor)}, but for
+   * rewriting code for inlining. The {@param context} is the caller that {@param method} is being
+   * inlined into.
    */
   public final void rewriteCodeForInlining(
-      DexEncodedMethod method, IRCode code, DexEncodedMethod context) {
+      DexEncodedMethod method, IRCode code, DexEncodedMethod context, InliningIRProvider provider) {
     if (mode != null) {
-      mode.rewriteCode(method, code, null, context);
+      mode.rewriteCode(method, code, null, context, provider);
     }
   }
 
diff --git a/src/main/java/com/android/tools/r8/ir/synthetic/AbstractSynthesizedCode.java b/src/main/java/com/android/tools/r8/ir/synthetic/AbstractSynthesizedCode.java
index f9da7c6..331f14d 100644
--- a/src/main/java/com/android/tools/r8/ir/synthetic/AbstractSynthesizedCode.java
+++ b/src/main/java/com/android/tools/r8/ir/synthetic/AbstractSynthesizedCode.java
@@ -13,6 +13,7 @@
 import com.android.tools.r8.ir.code.Position;
 import com.android.tools.r8.ir.code.ValueNumberGenerator;
 import com.android.tools.r8.ir.conversion.IRBuilder;
+import com.android.tools.r8.ir.conversion.MethodProcessor;
 import com.android.tools.r8.ir.conversion.SourceCode;
 import com.android.tools.r8.naming.ClassNameMapper;
 import com.android.tools.r8.origin.Origin;
@@ -35,14 +36,11 @@
 
   @Override
   public final IRCode buildIR(DexEncodedMethod encodedMethod, AppView<?> appView, Origin origin) {
-    IRBuilder builder =
-        new IRBuilder(
-            encodedMethod,
-            appView,
-            getSourceCodeProvider().get(null),
-            origin,
-            new ValueNumberGenerator());
-    return builder.build(encodedMethod);
+    return IRBuilder.create(
+        encodedMethod,
+        appView,
+        getSourceCodeProvider().get(null),
+        origin).build(encodedMethod);
   }
 
   @Override
@@ -52,15 +50,15 @@
       AppView<?> appView,
       ValueNumberGenerator valueNumberGenerator,
       Position callerPosition,
-      Origin origin) {
-    IRBuilder builder =
-        new IRBuilder(
-            encodedMethod,
-            appView,
-            getSourceCodeProvider().get(callerPosition),
-            origin,
-            valueNumberGenerator);
-    return builder.build(context);
+      Origin origin,
+      MethodProcessor methodProcessor) {
+    return IRBuilder.createForInlining(
+        encodedMethod,
+        appView,
+        getSourceCodeProvider().get(callerPosition),
+        origin,
+        methodProcessor,
+        valueNumberGenerator).build(context);
   }
 
   @Override
diff --git a/src/test/java/com/android/tools/r8/ir/analysis/fieldaccess/FieldBitAccessInfoTest.java b/src/test/java/com/android/tools/r8/ir/analysis/fieldaccess/FieldBitAccessInfoTest.java
index 6a4bd17..43c8e17 100644
--- a/src/test/java/com/android/tools/r8/ir/analysis/fieldaccess/FieldBitAccessInfoTest.java
+++ b/src/test/java/com/android/tools/r8/ir/analysis/fieldaccess/FieldBitAccessInfoTest.java
@@ -216,6 +216,11 @@
     }
 
     @Override
+    public boolean shouldApplyCodeRewritings(DexEncodedMethod method) {
+      return false;
+    }
+
+    @Override
     public boolean isProcessedConcurrently(DexEncodedMethod method) {
       return false;
     }