Merge commit 'ff39e2b159b6b21508ec3b96d20a65d77202527f' into dev-release

Change-Id: I1f8aa59502a288677bdb68f637c8db63a8c98b4e
diff --git a/src/main/java/com/android/tools/r8/R8.java b/src/main/java/com/android/tools/r8/R8.java
index 8089d42..8f40057 100644
--- a/src/main/java/com/android/tools/r8/R8.java
+++ b/src/main/java/com/android/tools/r8/R8.java
@@ -734,6 +734,8 @@
 
       R8LibraryDesugaring.runIfNecessary(appView, executorService, timing);
 
+      appView.withThrowBlockOutliner(outliner -> outliner.runForR8(executorService, timing));
+
       if (appView.appInfo().hasLiveness()) {
         SyntheticFinalization.finalizeWithLiveness(appView.withLiveness(), executorService, timing);
       } else {
diff --git a/src/main/java/com/android/tools/r8/R8Command.java b/src/main/java/com/android/tools/r8/R8Command.java
index 9f1f42d..43953a0 100644
--- a/src/main/java/com/android/tools/r8/R8Command.java
+++ b/src/main/java/com/android/tools/r8/R8Command.java
@@ -1086,14 +1086,6 @@
       parserOptionsBuilder.setEnableExperimentalCheckEnumUnboxed(true);
     }
 
-    void setEnableExperimentalConvertCheckNotNull() {
-      parserOptionsBuilder.setEnableExperimentalConvertCheckNotNull(true);
-    }
-
-    void setEnableExperimentalWhyAreYouNotInlining() {
-      parserOptionsBuilder.setEnableExperimentalWhyAreYouNotInlining(true);
-    }
-
     // Internal for-testing method to allow proguard options only available for testing.
     void setEnableTestProguardOptions() {
       parserOptionsBuilder.setEnableTestingOptions(true);
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 5a4d355..124786f 100644
--- a/src/main/java/com/android/tools/r8/graph/AppView.java
+++ b/src/main/java/com/android/tools/r8/graph/AppView.java
@@ -617,6 +617,13 @@
     }
   }
 
+  public <E extends Throwable> void withD8ThrowBlockOutliner(
+      ThrowingConsumer<ThrowBlockOutliner, E> consumer) throws E {
+    if (!enableWholeProgramOptimizations()) {
+      withThrowBlockOutliner(consumer);
+    }
+  }
+
   public LibraryMemberOptimizer libraryMethodOptimizer() {
     return libraryMemberOptimizer;
   }
diff --git a/src/main/java/com/android/tools/r8/graph/DexMethod.java b/src/main/java/com/android/tools/r8/graph/DexMethod.java
index 4abdb68..ff4f333 100644
--- a/src/main/java/com/android/tools/r8/graph/DexMethod.java
+++ b/src/main/java/com/android/tools/r8/graph/DexMethod.java
@@ -346,7 +346,10 @@
 
   @Override
   public DexMethod withHolder(DexReference reference, DexItemFactory dexItemFactory) {
-    return dexItemFactory.createMethod(reference.getContextType(), proto, name);
+    DexType newHolder = reference.getContextType();
+    return newHolder.isIdenticalTo(holder)
+        ? this
+        : dexItemFactory.createMethod(newHolder, proto, name);
   }
 
   public DexMethod withName(String name, DexItemFactory dexItemFactory) {
diff --git a/src/main/java/com/android/tools/r8/graph/ProgramMethod.java b/src/main/java/com/android/tools/r8/graph/ProgramMethod.java
index 21b8de8..fe16b49 100644
--- a/src/main/java/com/android/tools/r8/graph/ProgramMethod.java
+++ b/src/main/java/com/android/tools/r8/graph/ProgramMethod.java
@@ -6,18 +6,22 @@
 import static com.android.tools.r8.ir.optimize.info.OptimizationFeedback.getSimpleFeedback;
 
 import com.android.tools.r8.dex.IndexedItemCollection;
+import com.android.tools.r8.graph.bytecodemetadata.BytecodeMetadataProvider;
 import com.android.tools.r8.graph.lens.GraphLens;
 import com.android.tools.r8.graph.proto.RewrittenPrototypeDescription;
 import com.android.tools.r8.ir.code.IRCode;
 import com.android.tools.r8.ir.code.NumberGenerator;
 import com.android.tools.r8.ir.code.Position;
+import com.android.tools.r8.ir.conversion.IRFinalizer;
 import com.android.tools.r8.ir.conversion.LensCodeRewriterUtils;
 import com.android.tools.r8.ir.conversion.MethodConversionOptions;
 import com.android.tools.r8.ir.conversion.MethodConversionOptions.MutableMethodConversionOptions;
 import com.android.tools.r8.ir.conversion.MethodProcessor;
+import com.android.tools.r8.ir.optimize.DeadCodeRemover;
 import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
 import com.android.tools.r8.kotlin.KotlinMethodLevelInfo;
 import com.android.tools.r8.shaking.AppInfoWithLiveness;
+import com.android.tools.r8.utils.timing.Timing;
 import it.unimi.dsi.fastutil.ints.Int2ReferenceMap;
 
 /** Type representing a method definition in the programs compilation unit and its holder. */
@@ -211,6 +215,13 @@
     getDefinition().setCode(newCode, parameterInfo);
   }
 
+  public void setCode(
+      IRCode newCode, AppView<?> appView, DeadCodeRemover deadCodeRemover, Timing timing) {
+    IRFinalizer<?> finalizer =
+        newCode.getConversionOptions().getFinalizer(deadCodeRemover, appView);
+    setCode(finalizer.finalizeCode(newCode, BytecodeMetadataProvider.empty(), timing), appView);
+  }
+
   public boolean keepLocals(AppView<?> appView) {
     if (appView.testing().noLocalsTableOnInput) {
       return false;
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/type/TypeUtils.java b/src/main/java/com/android/tools/r8/ir/analysis/type/TypeUtils.java
index 8d98060..65a5c1a 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/type/TypeUtils.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/type/TypeUtils.java
@@ -17,7 +17,6 @@
 import static com.android.tools.r8.ir.code.Opcodes.RETURN;
 import static com.android.tools.r8.ir.code.Opcodes.STATIC_PUT;
 
-import com.android.tools.r8.graph.AppInfo;
 import com.android.tools.r8.graph.AppInfoWithClassHierarchy;
 import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.DexField;
@@ -71,24 +70,15 @@
    * value must have in order for the program to type check.
    */
   public static TypeElement computeUseType(AppView<?> appView, DexType returnType, Value value) {
-    if (appView.hasClassHierarchy()) {
-      return computeUseType(appView, returnType, value, (s, t) -> s.join(t, appView));
-    } else {
-      AppView<AppInfo> appViewWithoutClassHierarchy = appView.withoutClassHierarchy();
-      AppInfoWithClassHierarchy appInfo = appView.appInfoForDesugaring();
-      return computeUseType(
-          appView,
-          returnType,
-          value,
-          (s, t) -> joinWithoutClassHierarchy(s, t, appViewWithoutClassHierarchy, appInfo));
-    }
+    AppInfoWithClassHierarchy appInfo = appView.appInfoForDesugaring();
+    return computeUseType(appView, returnType, value, (s, t) -> meet(s, t, appView, appInfo));
   }
 
   private static TypeElement computeUseType(
       AppView<?> appView,
       DexType returnType,
       Value value,
-      BiFunction<TypeElement, TypeElement, TypeElement> joiner) {
+      BiFunction<TypeElement, TypeElement, TypeElement> meet) {
     TypeElement staticType = value.getType();
     TypeElement useType = TypeElement.getBottom();
     WorkList<UserAndValuePair> users = WorkList.newEqualityWorkList();
@@ -101,9 +91,8 @@
       } else {
         Instruction instruction = user.asInstruction();
         TypeElement instructionUseType =
-            computeUseTypeForInstruction(
-                appView, returnType, instruction, item.value, joiner, users);
-        useType = joiner.apply(useType, instructionUseType);
+            computeUseTypeForInstruction(appView, returnType, instruction, item.value, meet, users);
+        useType = meet.apply(useType, instructionUseType);
         if (useType.isTop() || useType.equalUpToNullability(staticType)) {
           // Bail-out.
           return staticType;
@@ -127,7 +116,7 @@
       DexType returnType,
       Instruction instruction,
       Value value,
-      BiFunction<TypeElement, TypeElement, TypeElement> joiner,
+      BiFunction<TypeElement, TypeElement, TypeElement> meet,
       WorkList<UserAndValuePair> users) {
     switch (instruction.opcode()) {
       case ASSUME:
@@ -138,13 +127,13 @@
       case INSTANCE_GET:
         return computeUseTypeForInstanceGet(appView, instruction.asInstanceGet());
       case INSTANCE_PUT:
-        return computeUseTypeForInstancePut(appView, instruction.asInstancePut(), value, joiner);
+        return computeUseTypeForInstancePut(appView, instruction.asInstancePut(), value, meet);
       case INVOKE_DIRECT:
       case INVOKE_INTERFACE:
       case INVOKE_STATIC:
       case INVOKE_SUPER:
       case INVOKE_VIRTUAL:
-        return computeUseTypeForInvoke(appView, instruction.asInvokeMethod(), value, joiner);
+        return computeUseTypeForInvoke(appView, instruction.asInvokeMethod(), value, meet);
       case RETURN:
         return computeUseTypeForReturn(appView, returnType);
       case STATIC_PUT:
@@ -170,14 +159,14 @@
       AppView<?> appView,
       InstancePut instancePut,
       Value value,
-      BiFunction<TypeElement, TypeElement, TypeElement> joiner) {
+      BiFunction<TypeElement, TypeElement, TypeElement> meet) {
     DexField field = instancePut.getField();
     TypeElement useType = TypeElement.getBottom();
     if (instancePut.object() == value) {
-      useType = joiner.apply(useType, field.getHolderType().toTypeElement(appView));
+      useType = meet.apply(useType, field.getHolderType().toTypeElement(appView));
     }
     if (instancePut.value() == value) {
-      useType = joiner.apply(useType, field.getType().toTypeElement(appView));
+      useType = meet.apply(useType, field.getType().toTypeElement(appView));
     }
     return useType;
   }
@@ -186,7 +175,7 @@
       AppView<?> appView,
       InvokeMethod invoke,
       Value value,
-      BiFunction<TypeElement, TypeElement, TypeElement> joiner) {
+      BiFunction<TypeElement, TypeElement, TypeElement> meet) {
     TypeElement useType = TypeElement.getBottom();
     for (int argumentIndex = 0; argumentIndex < invoke.arguments().size(); argumentIndex++) {
       Value argument = invoke.getArgument(argumentIndex);
@@ -198,7 +187,7 @@
               .getInvokedMethod()
               .getArgumentType(argumentIndex, invoke.isInvokeStatic())
               .toTypeElement(appView);
-      useType = joiner.apply(useType, useTypeForArgument);
+      useType = meet.apply(useType, useTypeForArgument);
     }
     assert !useType.isBottom();
     return useType;
@@ -212,19 +201,24 @@
     return staticPut.getField().getType().toTypeElement(appView);
   }
 
-  private static TypeElement joinWithoutClassHierarchy(
-      TypeElement type,
-      TypeElement other,
-      AppView<AppInfo> appView,
-      AppInfoWithClassHierarchy appInfo) {
-    assert !other.isBottom();
+  private static TypeElement meet(
+      TypeElement type, TypeElement other, AppView<?> appView, AppInfoWithClassHierarchy appInfo) {
+    if (other.isBottom()) {
+      return type;
+    }
     if (type.isBottom()) {
       return other;
     }
     if (type.isTop() || other.isTop()) {
       return TypeElement.getTop();
     }
-    if (type.equals(other)) {
+    if (type.equalUpToNullability(other)) {
+      if (type.isReferenceType()) {
+        if (!type.nullability().equals(other.nullability())) {
+          return type.asReferenceType()
+              .getOrCreateVariant(type.nullability().meet(other.nullability()));
+        }
+      }
       return type;
     }
     if (type.isPrimitiveType()) {
@@ -242,11 +236,16 @@
     DexType classType = type.asClassType().getClassType();
     DexType otherClassType = other.asClassType().getClassType();
     if (appInfo.isSubtype(classType, otherClassType)) {
-      return ClassTypeElement.createForD8(classType, type.nullability().join(other.nullability()));
+      if (type.nullability().equals(other.nullability())) {
+        return type;
+      }
+      return type.asClassType().getOrCreateVariant(type.nullability().meet(other.nullability()));
     }
     if (appInfo.isSubtype(otherClassType, classType)) {
-      return ClassTypeElement.createForD8(
-          otherClassType, type.nullability().join(other.nullability()));
+      if (type.nullability().equals(other.nullability())) {
+        return other;
+      }
+      return other.asClassType().getOrCreateVariant(type.nullability().meet(other.nullability()));
     }
     return TypeElement.getTop();
   }
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 b54a50a..d43e0b2 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
@@ -816,7 +816,7 @@
     assert code.verifyNoNullabilityBottomTypes();
     assert code.verifyTypes(appView);
 
-    appView.withThrowBlockOutliner(outliner -> outliner.scan(code));
+    appView.withD8ThrowBlockOutliner(outliner -> outliner.scan(code));
 
     previous = printMethod(code, "Optimized IR (SSA)", previous);
     timing.begin("Finalize IR");
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxerImpl.java b/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxerImpl.java
index 3154d72..297ebe1 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxerImpl.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxerImpl.java
@@ -1407,6 +1407,9 @@
       // Check if this is a checkNotNull() user. In this case, we can create a copy of the method
       // that takes an int instead of java.lang.Object and call that method instead.
       if (singleTarget != null) {
+        if (singleTarget.getAccessFlags().isAbstract()) {
+          return Reason.INVALID_INVOKE;
+        }
         EnumUnboxerMethodClassification classification =
             singleTarget.getOptimizationInfo().getEnumUnboxerMethodClassification();
         if (classification.isCheckNotNullClassification()) {
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxingLens.java b/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxingLens.java
index 5068f5a..3b7abb1 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxingLens.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxingLens.java
@@ -50,7 +50,6 @@
   private final AbstractValueFactory abstractValueFactory;
   private final Map<DexMethod, RewrittenPrototypeDescription> prototypeChangesPerMethod;
   private final EnumDataMap unboxedEnums;
-  private final Set<DexMethod> dispatchMethods;
 
   EnumUnboxingLens(
       AppView<?> appView,
@@ -58,14 +57,12 @@
       BidirectionalOneToManyRepresentativeMap<DexMethod, DexMethod> renamedSignatures,
       BidirectionalManyToOneRepresentativeMap<DexType, DexType> typeMap,
       Map<DexMethod, DexMethod> methodMap,
-      Map<DexMethod, RewrittenPrototypeDescription> prototypeChangesPerMethod,
-      Set<DexMethod> dispatchMethods) {
+      Map<DexMethod, RewrittenPrototypeDescription> prototypeChangesPerMethod) {
     super(appView, fieldMap, methodMap, typeMap, renamedSignatures);
     assert !appView.unboxedEnums().isEmpty();
     this.abstractValueFactory = appView.abstractValueFactory();
     this.prototypeChangesPerMethod = prototypeChangesPerMethod;
     this.unboxedEnums = appView.unboxedEnums();
-    this.dispatchMethods = dispatchMethods;
   }
 
   @Override
@@ -108,15 +105,12 @@
 
   public DexMethod lookupRefinedDispatchMethod(
       DexMethod method,
-      DexMethod context,
-      InvokeType type,
-      GraphLens codeLens,
       AbstractValue unboxedEnumValue,
       DexType enumType) {
-    assert codeLens == getPrevious();
-    DexMethod reference = lookupMethod(method, context, type, codeLens).getReference();
-    if (!dispatchMethods.contains(reference) || !unboxedEnumValue.isSingleNumberValue()) {
-      return null;
+    DexMethod enumMethod = method.withHolder(enumType, dexItemFactory());
+    DexMethod rewrittenEnumMethod = newMethodSignatures.getRepresentativeValue(enumMethod);
+    if (!unboxedEnumValue.isSingleNumberValue()) {
+      return rewrittenEnumMethod;
     }
     // We know the exact type of enum, so there is no need to go for the dispatch method. Instead,
     // we compute the exact target from the enum instance.
@@ -126,11 +120,12 @@
             .get(enumType)
             .valuesTypes
             .getOrDefault(unboxedIntToOrdinal(unboxedEnum), enumType);
+    if (instanceType.isIdenticalTo(enumType)) {
+      return rewrittenEnumMethod;
+    }
     DexMethod specializedMethod = method.withHolder(instanceType, dexItemFactory());
-    DexMethod superEnumMethod = method.withHolder(enumType, dexItemFactory());
     DexMethod refined =
-        newMethodSignatures.getRepresentativeValueOrDefault(
-            specializedMethod, newMethodSignatures.getRepresentativeValue(superEnumMethod));
+        newMethodSignatures.getRepresentativeValueOrDefault(specializedMethod, rewrittenEnumMethod);
     assert refined != null;
     return refined;
   }
@@ -408,8 +403,7 @@
           originalCheckNotNullMethodSignature, checkNotNullMethod.getReference());
     }
 
-    public EnumUnboxingLens build(
-        AppView<AppInfoWithLiveness> appView, Set<DexMethod> dispatchMethods) {
+    public EnumUnboxingLens build(AppView<AppInfoWithLiveness> appView) {
       assert !typeMap.isEmpty();
       return new EnumUnboxingLens(
           appView,
@@ -417,8 +411,7 @@
           newMethodSignatures,
           typeMap,
           methodMap,
-          ImmutableMap.copyOf(prototypeChangesPerMethod),
-          dispatchMethods);
+          ImmutableMap.copyOf(prototypeChangesPerMethod));
     }
   }
 }
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxingRewriter.java b/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxingRewriter.java
index 7cca071..0c5c644 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxingRewriter.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxingRewriter.java
@@ -200,6 +200,7 @@
           rewriteInvokeMethodWithReceiver(
               code,
               eventConsumer,
+              affectedPhis,
               convertedEnums,
               blocks,
               block,
@@ -438,6 +439,7 @@
   private void rewriteInvokeMethodWithReceiver(
       IRCode code,
       EnumUnboxerMethodProcessorEventConsumer eventConsumer,
+      Set<Phi> affectedPhis,
       Map<Instruction, DexType> convertedEnums,
       BasicBlockIterator blocks,
       BasicBlock block,
@@ -499,18 +501,23 @@
       } else if (invoke.isInvokeVirtual() || invoke.isInvokeInterface()) {
         DexMethod refinedDispatchMethodReference =
             enumUnboxingLens.lookupRefinedDispatchMethod(
-                invokedMethod,
-                context.getReference(),
-                invoke.getType(),
-                enumUnboxingLens.getPrevious(),
-                invoke.getArgument(0).getAbstractValue(appView, context),
-                enumType);
+                invokedMethod, invoke.getReceiver().getAbstractValue(appView, context), enumType);
         if (refinedDispatchMethodReference != null) {
           DexClassAndMethod refinedDispatchMethod =
               appView.definitionFor(refinedDispatchMethodReference);
           assert refinedDispatchMethod != null;
           assert refinedDispatchMethod.isProgramMethod();
-          replaceEnumInvoke(iterator, invoke, refinedDispatchMethod.asProgramMethod());
+          InvokeStatic replacement =
+              replaceEnumInvoke(iterator, invoke, refinedDispatchMethod.asProgramMethod());
+          if (replacement.hasOutValue()
+              && refinedDispatchMethodReference.getReturnType().isIntType()
+              && !invokedMethod.getReturnType().isIntType()) {
+            Value rewrittenOutValue = code.createValue(TypeElement.getInt());
+            replacement.outValue().replaceUsers(rewrittenOutValue);
+            replacement.setOutValue(rewrittenOutValue);
+            affectedPhis.addAll(rewrittenOutValue.uniquePhiUsers());
+            convertedEnums.put(replacement, enumType);
+          }
         }
       }
     } else if (invokedMethod == factory.stringBuilderMethods.appendObject
@@ -859,12 +866,12 @@
         .ensureGetInstanceFieldMethod(appView, field, context, eventConsumer);
   }
 
-  private void replaceEnumInvoke(
+  private InvokeStatic replaceEnumInvoke(
       InstructionListIterator iterator, InvokeMethod invoke, ProgramMethod method) {
-    replaceEnumInvoke(iterator, invoke, method, invoke.arguments());
+    return replaceEnumInvoke(iterator, invoke, method, invoke.arguments());
   }
 
-  private void replaceEnumInvoke(
+  private InvokeStatic replaceEnumInvoke(
       InstructionListIterator iterator,
       InvokeMethod invoke,
       ProgramMethod method,
@@ -877,6 +884,7 @@
     assert !replacement.hasOutValue()
         || !replacement.getInvokedMethod().getReturnType().isVoidType();
     iterator.replaceCurrentInstruction(replacement);
+    return replacement;
   }
 
   private boolean validateArrayAccess(ArrayAccess arrayAccess) {
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxingTreeFixer.java b/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxingTreeFixer.java
index a6bda7d..53051d0 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxingTreeFixer.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxingTreeFixer.java
@@ -158,9 +158,7 @@
         .fixupClassesConcurrentlyByConnectedProgramComponents(Timing.empty(), executorService);
 
     // Install the new graph lens before processing any checkNotZero() methods.
-    Set<DexMethod> dispatchMethodReferences = Sets.newIdentityHashSet();
-    dispatchMethods.forEach((method, code) -> dispatchMethodReferences.add(method.getReference()));
-    EnumUnboxingLens lens = lensBuilder.build(appView, dispatchMethodReferences);
+    EnumUnboxingLens lens = lensBuilder.build(appView);
     appView.rewriteWithLens(lens, executorService, timing);
 
     // Rewrite outliner with lens.
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/outliner/exceptions/ThrowBlockOutline.java b/src/main/java/com/android/tools/r8/ir/optimize/outliner/exceptions/ThrowBlockOutline.java
index eca5fe3..0af7d88 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/outliner/exceptions/ThrowBlockOutline.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/outliner/exceptions/ThrowBlockOutline.java
@@ -253,6 +253,10 @@
             builder ->
                 builder
                     .setAccessFlags(MethodAccessFlags.createPublicStaticSynthetic())
+                    // TODO(b/434769547): The API level of the code may be higher than the min-api.
+                    //   This currently doesn't matter since outlining runs after API outlining.
+                    .setApiLevelForCode(
+                        appView.apiLevelCompute().computeInitialMinApiLevel(appView.options()))
                     .setCode(methodSig -> lirCode)
                     .setProto(getOptimizedProto(appView.dexItemFactory())));
   }
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/outliner/exceptions/ThrowBlockOutlineMarkerRewriter.java b/src/main/java/com/android/tools/r8/ir/optimize/outliner/exceptions/ThrowBlockOutlineMarkerRewriter.java
index 232c840..e9de503 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/outliner/exceptions/ThrowBlockOutlineMarkerRewriter.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/outliner/exceptions/ThrowBlockOutlineMarkerRewriter.java
@@ -75,12 +75,16 @@
         appView,
         callerPosition,
         outline.getProtoChanges(),
-        MethodConversionOptions.forD8(appView, method));
+        appView.enableWholeProgramOptimizations()
+            ? MethodConversionOptions.forLirPhase(appView)
+            : MethodConversionOptions.forD8(appView, method));
   }
 
   private void finalizeCode(ProgramMethod method, IRCode code) {
     // Convert to DEX.
-    assert code.getConversionOptions().isGeneratingDex();
+    assert appView.enableWholeProgramOptimizations()
+        ? code.getConversionOptions().isGeneratingLir()
+        : code.getConversionOptions().isGeneratingDex();
     IRFinalizer<?> finalizer = code.getConversionOptions().getFinalizer(deadCodeRemover, appView);
     Code dexCode = finalizer.finalizeCode(code, BytecodeMetadataProvider.empty(), Timing.empty());
     method.setCode(dexCode, appView);
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/outliner/exceptions/ThrowBlockOutliner.java b/src/main/java/com/android/tools/r8/ir/optimize/outliner/exceptions/ThrowBlockOutliner.java
index 755e836..004281a 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/outliner/exceptions/ThrowBlockOutliner.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/outliner/exceptions/ThrowBlockOutliner.java
@@ -4,6 +4,7 @@
 package com.android.tools.r8.ir.optimize.outliner.exceptions;
 
 import static com.android.tools.r8.utils.MapUtils.ignoreKey;
+import static com.google.common.base.Predicates.alwaysTrue;
 
 import com.android.tools.r8.contexts.CompilationContext.MethodProcessingContext;
 import com.android.tools.r8.contexts.CompilationContext.ProcessorContext;
@@ -12,20 +13,25 @@
 import com.android.tools.r8.dex.code.DexInvokeStatic;
 import com.android.tools.r8.dex.code.DexReturn;
 import com.android.tools.r8.graph.AppView;
+import com.android.tools.r8.graph.DexEncodedMethod;
 import com.android.tools.r8.graph.DexMethod;
+import com.android.tools.r8.graph.DexProgramClass;
 import com.android.tools.r8.graph.ProgramMethod;
 import com.android.tools.r8.ir.code.IRCode;
+import com.android.tools.r8.ir.optimize.DeadCodeRemover;
 import com.android.tools.r8.lightir.LirCode;
 import com.android.tools.r8.lightir.LirConstant;
 import com.android.tools.r8.utils.ListUtils;
 import com.android.tools.r8.utils.ThreadUtils;
 import com.android.tools.r8.utils.collections.ProgramMethodMap;
+import com.android.tools.r8.utils.timing.Timing;
 import com.google.common.collect.Multiset;
 import com.google.common.collect.Sets;
 import it.unimi.dsi.fastutil.objects.Reference2IntMap;
 import it.unimi.dsi.fastutil.objects.Reference2IntOpenHashMap;
 import java.util.ArrayList;
 import java.util.Collection;
+import java.util.Collections;
 import java.util.Comparator;
 import java.util.List;
 import java.util.Map;
@@ -55,6 +61,41 @@
         : null;
   }
 
+  // TODO(b/434769547): Ensure retracing works.
+  public void runForR8(ExecutorService executorService, Timing timing) throws ExecutionException {
+    timing.begin("Throw block outliner");
+    scan(executorService, timing);
+    tearDownScanner(Collections.emptyMap(), executorService);
+    // Commit pending synthetics.
+    appView.rebuildAppInfo();
+    appView.getTypeElementFactory().clearTypeElementsCache();
+    timing.end();
+  }
+
+  public void scan(ExecutorService executorService, Timing timing) throws ExecutionException {
+    ThreadUtils.processItemsThatMatches(
+        appView.appInfo().classes(),
+        alwaysTrue(),
+        this::scan,
+        appView.options(),
+        executorService,
+        timing,
+        timing.beginMerger("Scan for throw block outlines", executorService));
+  }
+
+  private void scan(DexProgramClass clazz, Timing timing) {
+    timing.begin("Scan " + clazz.getTypeName());
+    DeadCodeRemover deadCodeRemover = new DeadCodeRemover(appView);
+    clazz.forEachProgramMethodMatching(
+        DexEncodedMethod::hasLirCode,
+        method -> {
+          IRCode code = method.buildIR(appView);
+          scan(code);
+          method.setCode(code, appView, deadCodeRemover, timing);
+        });
+    timing.end();
+  }
+
   public void scan(IRCode code) {
     // Notify the scanner.
     if (scanner != null) {
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/outliner/exceptions/ThrowBlockOutlinerOptions.java b/src/main/java/com/android/tools/r8/ir/optimize/outliner/exceptions/ThrowBlockOutlinerOptions.java
index d1b50b6..55036d0 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/outliner/exceptions/ThrowBlockOutlinerOptions.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/outliner/exceptions/ThrowBlockOutlinerOptions.java
@@ -3,7 +3,6 @@
 // BSD-style license that can be found in the LICENSE file.
 package com.android.tools.r8.ir.optimize.outliner.exceptions;
 
-import com.android.tools.r8.errors.Unimplemented;
 import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.utils.SystemPropertyUtils;
 import java.util.Collection;
@@ -38,8 +37,8 @@
     if (appView.options().debug && !forceDebug) {
       return false;
     }
-    if (appView.enableWholeProgramOptimizations()) {
-      throw new Unimplemented();
+    if (appView.options().partialSubCompilationConfiguration != null) {
+      return false;
     }
     return true;
   }
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/outliner/exceptions/ThrowBlockOutlinerScanner.java b/src/main/java/com/android/tools/r8/ir/optimize/outliner/exceptions/ThrowBlockOutlinerScanner.java
index 07b7470..840483a 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/outliner/exceptions/ThrowBlockOutlinerScanner.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/outliner/exceptions/ThrowBlockOutlinerScanner.java
@@ -70,13 +70,17 @@
 
   private final AppView<?> appView;
   private final DexItemFactory factory;
-  private final AbstractValueFactory valueFactory = new AbstractValueFactory();
+  private final AbstractValueFactory valueFactory;
 
   private final Map<Wrapper<LirCode<?>>, ThrowBlockOutline> outlines = new ConcurrentHashMap<>();
 
   ThrowBlockOutlinerScanner(AppView<?> appView) {
     this.appView = appView;
     this.factory = appView.dexItemFactory();
+    this.valueFactory =
+        appView.enableWholeProgramOptimizations()
+            ? appView.abstractValueFactory()
+            : new AbstractValueFactory();
   }
 
   public void run(IRCode code) {
@@ -85,16 +89,18 @@
       new ThrowBlockOutlinerScannerForBlock(code, block).processThrowBlock();
     }
     if (code.metadata().mayHaveThrowBlockOutlineMarker()) {
-      assert code.getConversionOptions().isGeneratingDex();
-      code.mutateConversionOptions(MutableMethodConversionOptions::setIsGeneratingLir);
+      if (appView.enableWholeProgramOptimizations()) {
+        assert code.getConversionOptions().isGeneratingLir();
+      } else {
+        assert code.getConversionOptions().isGeneratingDex();
+        code.mutateConversionOptions(MutableMethodConversionOptions::setIsGeneratingLir);
+      }
     } else {
       assert code.streamInstructions().noneMatch(Instruction::isThrowBlockOutlineMarker);
     }
   }
 
   public AbstractValueFactory getAbstractValueFactory() {
-    // If/when extending this to R8, use the R8 AbstractValueFactory from AppView.
-    assert !appView.enableWholeProgramOptimizations();
     return valueFactory;
   }
 
diff --git a/src/main/java/com/android/tools/r8/shaking/ProguardConfigurationParser.java b/src/main/java/com/android/tools/r8/shaking/ProguardConfigurationParser.java
index 3c01885..dddd397 100644
--- a/src/main/java/com/android/tools/r8/shaking/ProguardConfigurationParser.java
+++ b/src/main/java/com/android/tools/r8/shaking/ProguardConfigurationParser.java
@@ -136,8 +136,6 @@
         ProguardConfigurationParserOptions.builder()
             .setEnableLegacyFullModeForKeepRules(false)
             .setEnableExperimentalCheckEnumUnboxed(false)
-            .setEnableExperimentalConvertCheckNotNull(false)
-            .setEnableExperimentalWhyAreYouNotInlining(false)
             .setEnableTestingOptions(false)
             .build(),
         null,
@@ -483,6 +481,13 @@
             parseRuleWithClassSpec(optionStart, ProguardIdentifierNameStringRule.builder()));
       } else if (acceptString("if")) {
         configurationConsumer.addRule(parseIfRule(optionStart));
+      } else if (acceptString(ConvertCheckNotNullRule.RULE_NAME)) {
+        configurationConsumer.addRule(parseConvertCheckNotNullRule(optionStart));
+        return true;
+      } else if (acceptString(WhyAreYouNotInliningRule.RULE_NAME)) {
+        configurationConsumer.addRule(
+            parseRuleWithClassSpec(optionStart, WhyAreYouNotInliningRule.builder()));
+        return true;
       } else if (parseMaximumRemovedAndroidLogLevelRule(optionStart)) {
         return true;
       } else {
@@ -507,20 +512,6 @@
         }
         return true;
       }
-      if (acceptString(ConvertCheckNotNullRule.RULE_NAME)) {
-        ConvertCheckNotNullRule convertCheckNotNullRule = parseConvertCheckNotNullRule(optionStart);
-        if (options.isExperimentalConvertCheckNotNullEnabled()) {
-          configurationConsumer.addRule(convertCheckNotNullRule);
-        }
-        return true;
-      }
-      if (options.isExperimentalWhyAreYouNotInliningEnabled()) {
-        if (acceptString(WhyAreYouNotInliningRule.RULE_NAME)) {
-          configurationConsumer.addRule(
-              parseRuleWithClassSpec(optionStart, WhyAreYouNotInliningRule.builder()));
-          return true;
-        }
-      }
       return false;
     }
 
diff --git a/src/main/java/com/android/tools/r8/shaking/ProguardConfigurationParserOptions.java b/src/main/java/com/android/tools/r8/shaking/ProguardConfigurationParserOptions.java
index df606a1..b7392e7 100644
--- a/src/main/java/com/android/tools/r8/shaking/ProguardConfigurationParserOptions.java
+++ b/src/main/java/com/android/tools/r8/shaking/ProguardConfigurationParserOptions.java
@@ -11,8 +11,6 @@
   private final boolean enableLegacyFullModeForKeepRules;
   private final boolean enableLegacyFullModeForKeepRulesWarnings;
   private final boolean enableExperimentalCheckEnumUnboxed;
-  private final boolean enableExperimentalConvertCheckNotNull;
-  private final boolean enableExperimentalWhyAreYouNotInlining;
   private final boolean enableKeepRuntimeInvisibleAnnotations;
   private final boolean enableTestingOptions;
   private final boolean forceProguardCompatibility;
@@ -21,14 +19,10 @@
       boolean enableLegacyFullModeForKeepRules,
       boolean enableLegacyFullModeForKeepRulesWarnings,
       boolean enableExperimentalCheckEnumUnboxed,
-      boolean enableExperimentalConvertCheckNotNull,
-      boolean enableExperimentalWhyAreYouNotInlining,
       boolean enableKeepRuntimeInvisibleAnnotations,
       boolean enableTestingOptions,
       boolean forceProguardCompatibility) {
     this.enableExperimentalCheckEnumUnboxed = enableExperimentalCheckEnumUnboxed;
-    this.enableExperimentalConvertCheckNotNull = enableExperimentalConvertCheckNotNull;
-    this.enableExperimentalWhyAreYouNotInlining = enableExperimentalWhyAreYouNotInlining;
     this.enableKeepRuntimeInvisibleAnnotations = enableKeepRuntimeInvisibleAnnotations;
     this.enableTestingOptions = enableTestingOptions;
     this.enableLegacyFullModeForKeepRules = enableLegacyFullModeForKeepRules;
@@ -54,14 +48,6 @@
     return enableExperimentalCheckEnumUnboxed;
   }
 
-  public boolean isExperimentalConvertCheckNotNullEnabled() {
-    return enableExperimentalConvertCheckNotNull;
-  }
-
-  public boolean isExperimentalWhyAreYouNotInliningEnabled() {
-    return enableExperimentalWhyAreYouNotInlining;
-  }
-
   public boolean isKeepRuntimeInvisibleAnnotationsEnabled() {
     return enableKeepRuntimeInvisibleAnnotations;
   }
@@ -75,8 +61,6 @@
     private boolean enableLegacyFullModeForKeepRules = true;
     private boolean enableLegacyFullModeForKeepRulesWarnings = false;
     private boolean enableExperimentalCheckEnumUnboxed;
-    private boolean enableExperimentalConvertCheckNotNull;
-    private boolean enableExperimentalWhyAreYouNotInlining;
     private boolean enableKeepRuntimeInvisibleAnnotations = true;
     private boolean enableTestingOptions;
     private boolean forceProguardCompatibility = false;
@@ -91,12 +75,6 @@
       enableExperimentalCheckEnumUnboxed =
           parseSystemPropertyOrDefault(
               "com.android.tools.r8.experimental.enablecheckenumunboxed", false);
-      enableExperimentalConvertCheckNotNull =
-          parseSystemPropertyOrDefault(
-              "com.android.tools.r8.experimental.enableconvertchecknotnull", false);
-      enableExperimentalWhyAreYouNotInlining =
-          parseSystemPropertyOrDefault(
-              "com.android.tools.r8.experimental.enablewhyareyounotinlining", false);
       enableKeepRuntimeInvisibleAnnotations =
           parseSystemPropertyOrDefault(
               "com.android.tools.r8.enableKeepRuntimeInvisibleAnnotations", true);
@@ -122,18 +100,6 @@
       return this;
     }
 
-    public Builder setEnableExperimentalConvertCheckNotNull(
-        boolean enableExperimentalConvertCheckNotNull) {
-      this.enableExperimentalConvertCheckNotNull = enableExperimentalConvertCheckNotNull;
-      return this;
-    }
-
-    public Builder setEnableExperimentalWhyAreYouNotInlining(
-        boolean enableExperimentalWhyAreYouNotInlining) {
-      this.enableExperimentalWhyAreYouNotInlining = enableExperimentalWhyAreYouNotInlining;
-      return this;
-    }
-
     public Builder setEnableTestingOptions(boolean enableTestingOptions) {
       this.enableTestingOptions = enableTestingOptions;
       return this;
@@ -149,8 +115,6 @@
           enableLegacyFullModeForKeepRules,
           enableLegacyFullModeForKeepRulesWarnings,
           enableExperimentalCheckEnumUnboxed,
-          enableExperimentalConvertCheckNotNull,
-          enableExperimentalWhyAreYouNotInlining,
           enableKeepRuntimeInvisibleAnnotations,
           enableTestingOptions,
           forceProguardCompatibility);
diff --git a/src/main/java/com/android/tools/r8/utils/InternalOptions.java b/src/main/java/com/android/tools/r8/utils/InternalOptions.java
index 8fadcd8..81cc3e0 100644
--- a/src/main/java/com/android/tools/r8/utils/InternalOptions.java
+++ b/src/main/java/com/android/tools/r8/utils/InternalOptions.java
@@ -1849,7 +1849,7 @@
     public boolean enableConstructorInlining = true;
     public boolean enableConstructorInliningWithFinalFields =
         parseSystemPropertyOrDefault(
-            "com.android.tools.r8.enableConstructorInliningWithFinalFields", false);
+            "com.android.tools.r8.enableConstructorInliningWithFinalFields", true);
     public boolean skipStoreStoreFenceInConstructorInlining =
         parseSystemPropertyOrDefault(
             "com.android.tools.r8.skipStoreStoreFenceInConstructorInlining", false);
diff --git a/src/test/java/com/android/tools/r8/enumunboxing/InvokeInterfaceNoDevirtualizationEnumUnboxingTest.java b/src/test/java/com/android/tools/r8/enumunboxing/InvokeInterfaceNoDevirtualizationEnumUnboxingTest.java
index 0d04b20..3eb7953 100644
--- a/src/test/java/com/android/tools/r8/enumunboxing/InvokeInterfaceNoDevirtualizationEnumUnboxingTest.java
+++ b/src/test/java/com/android/tools/r8/enumunboxing/InvokeInterfaceNoDevirtualizationEnumUnboxingTest.java
@@ -3,10 +3,15 @@
 // BSD-style license that can be found in the LICENSE file.
 package com.android.tools.r8.enumunboxing;
 
+import static org.junit.Assume.assumeFalse;
+import static org.junit.Assume.assumeTrue;
+
 import com.android.tools.r8.NeverInline;
+import com.android.tools.r8.NoAccessModification;
 import com.android.tools.r8.NoVerticalClassMerging;
 import com.android.tools.r8.TestParameters;
-import com.android.tools.r8.utils.codeinspector.AssertUtils;
+import com.google.common.collect.ImmutableList;
+import java.io.IOException;
 import java.util.List;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -22,7 +27,7 @@
 
   @Parameters(name = "{0} valueOpt: {1} keep: {2}")
   public static List<Object[]> data() {
-    return enumUnboxingTestParameters();
+    return enumUnboxingTestParameters(getTestParameters().withAllRuntimesAndApiLevels().build());
   }
 
   public InvokeInterfaceNoDevirtualizationEnumUnboxingTest(
@@ -33,43 +38,66 @@
   }
 
   @Test
-  public void test() throws Exception {
-    AssertUtils.assertFailsCompilation(
-        () ->
-            testForR8(parameters)
-                .addInnerClasses(getClass())
-                .addKeepMainRule(Main.class)
-                .addKeepRules(enumKeepRules.getKeepRules())
-                // Disable devirtualization so that the enum unboxing rewriter sees the call to
-                // I#greet instead of MyEnum#greet.
-                .addOptionsModification(options -> options.enableDevirtualization = false)
-                .addOptionsModification(
-                    options -> enableEnumOptions(options, enumValueOptimization))
-                .enableInliningAnnotations()
-                .enableNoVerticalClassMergingAnnotations()
-                .compile()
-                .run(parameters.getRuntime(), Main.class)
-                .assertSuccessWithOutputLines("Hello, world!"));
+  public void testJvm() throws Exception {
+    parameters.assumeJvmTestParameters();
+    assumeFalse(enumValueOptimization);
+    assumeTrue(enumKeepRules.isNone());
+    testForJvm(parameters)
+        .addProgramClasses(I.class)
+        .addProgramClassFileData(getProgramClassFileData())
+        .run(parameters.getRuntime(), Main.class)
+        .assertSuccessWithOutputLines("Hello, world!");
+  }
+
+  @Test
+  public void testR8() throws Exception {
+    testForR8(parameters)
+        .addProgramClasses(I.class)
+        .addProgramClassFileData(getProgramClassFileData())
+        .addKeepMainRule(Main.class)
+        .addKeepRules(enumKeepRules.getKeepRules())
+        .addOptionsModification(options -> enableEnumOptions(options, enumValueOptimization))
+        .enableInliningAnnotations()
+        .enableNoAccessModificationAnnotationsForClasses()
+        .enableNoVerticalClassMergingAnnotations()
+        .compile()
+        .run(parameters.getRuntime(), Main.class)
+        .assertSuccessWithOutputLines("Hello, world!");
+  }
+
+  private static List<byte[]> getProgramClassFileData() throws IOException {
+    return ImmutableList.of(
+        transformer(Main.class)
+            .replaceClassDescriptorInMethodInstructions(
+                descriptor(MyEnumAccessor.class), "LMyEnumAccessor;")
+            .transform(),
+        transformer(MyEnum.class).setClassDescriptor("LMyEnum;").transform(),
+        transformer(MyEnumAccessor.class)
+            .setClassDescriptor("LMyEnumAccessor;")
+            .replaceClassDescriptorInMethodInstructions(descriptor(MyEnum.class), "LMyEnum;")
+            .transform());
   }
 
   static class Main {
 
     public static void main(String[] args) {
-      MyEnum e = System.currentTimeMillis() > 0 ? MyEnum.A : MyEnum.B;
-      greet(e);
+      greet(MyEnumAccessor.get());
     }
 
     static void greet(I i) {
+      // Cannot be rewritten to call MyEnum#greet since MyEnum is not public and in another package.
       i.greet();
     }
   }
 
   @NoVerticalClassMerging
-  interface I {
+  public interface I {
 
     void greet();
   }
 
+  // Moved to separate package by transformer.
+  @NoAccessModification
   enum MyEnum implements I {
     A,
     B;
@@ -80,4 +108,12 @@
       System.out.println("Hello, world!");
     }
   }
+
+  // Moved to separate package by transformer.
+  public static class MyEnumAccessor {
+
+    public static I get() {
+      return System.currentTimeMillis() > 0 ? MyEnum.A : MyEnum.B;
+    }
+  }
 }
diff --git a/src/test/java/com/android/tools/r8/enumunboxing/enummerging/AbstractMethodErrorEnumMergingTest.java b/src/test/java/com/android/tools/r8/enumunboxing/enummerging/AbstractMethodErrorEnumMergingTest.java
index 7937ef7..b11d6de 100644
--- a/src/test/java/com/android/tools/r8/enumunboxing/enummerging/AbstractMethodErrorEnumMergingTest.java
+++ b/src/test/java/com/android/tools/r8/enumunboxing/enummerging/AbstractMethodErrorEnumMergingTest.java
@@ -10,6 +10,7 @@
 import com.android.tools.r8.TestParameters;
 import com.android.tools.r8.enumunboxing.EnumUnboxingTestBase;
 import com.android.tools.r8.utils.StringUtils;
+import com.android.tools.r8.utils.codeinspector.EnumUnboxingInspector;
 import java.nio.file.Files;
 import java.nio.file.Path;
 import java.util.ArrayList;
@@ -49,25 +50,22 @@
 
   @Test
   public void testReference() throws Exception {
-    testForD8(parameters.getBackend())
+    testForD8(parameters)
         .addProgramClassFileData(inputProgram())
         .addOptionsModification(opt -> enableEnumOptions(opt, enumValueOptimization))
-        .setMinApi(parameters)
         .run(parameters.getRuntime(), Main.class)
         .assertSuccessWithOutput(EXPECTED_RESULT);
   }
 
   @Test
   public void testEnumUnboxing() throws Exception {
-    testForR8(parameters.getBackend())
+    testForR8(parameters)
         .addProgramClassFileData(inputProgram())
         .addKeepMainRule(Main.class)
         .addKeepRules(enumKeepRules.getKeepRules())
-        .addEnumUnboxingInspector(
-            inspector -> inspector.assertUnboxed(MyEnum2Cases.class, MyEnum1Case.class))
+        .addEnumUnboxingInspector(EnumUnboxingInspector::assertNoEnumsUnboxed)
         .enableInliningAnnotations()
         .addOptionsModification(opt -> enableEnumOptions(opt, enumValueOptimization))
-        .setMinApi(parameters)
         .run(parameters.getRuntime(), Main.class)
         .assertSuccessWithOutput(EXPECTED_RESULT);
   }
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/inliner/whyareyounotinlining/WhyAreYouNotInliningInvokeWithUnknownTargetTest.java b/src/test/java/com/android/tools/r8/ir/optimize/inliner/whyareyounotinlining/WhyAreYouNotInliningInvokeWithUnknownTargetTest.java
index 06f5aa2..9e6e511 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/inliner/whyareyounotinlining/WhyAreYouNotInliningInvokeWithUnknownTargetTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/inliner/whyareyounotinlining/WhyAreYouNotInliningInvokeWithUnknownTargetTest.java
@@ -38,7 +38,6 @@
         .addInnerClasses(getClass())
         .addKeepMainRule(TestClass.class)
         .addKeepRules("-whyareyounotinlining class " + A.class.getTypeName() + " { void m(); }")
-        .enableExperimentalWhyAreYouNotInlining()
         .enableNoHorizontalClassMergingAnnotations()
         .enableNeverReprocessMethodAnnotations()
         .setMinApi(parameters)
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/inliner/whyareyounotinlining/WhyAreYouNotInliningLibraryTargetTest.java b/src/test/java/com/android/tools/r8/ir/optimize/inliner/whyareyounotinlining/WhyAreYouNotInliningLibraryTargetTest.java
index 1c85f7f..fc823ce 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/inliner/whyareyounotinlining/WhyAreYouNotInliningLibraryTargetTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/inliner/whyareyounotinlining/WhyAreYouNotInliningLibraryTargetTest.java
@@ -34,7 +34,6 @@
             "-whyareyounotinlining class "
                 + System.class.getTypeName()
                 + " { long currentTimeMillis(); }")
-        .enableExperimentalWhyAreYouNotInlining()
         .setMinApi(parameters)
         .compile()
         // The Inliner is currently not reporting -whyareyounotinlining for library calls.
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/outliner/exceptions/ThrowBlockOutlinerArrayUseTypeTest.java b/src/test/java/com/android/tools/r8/ir/optimize/outliner/exceptions/ThrowBlockOutlinerArrayUseTypeTest.java
index 0ee7d9b..d07c1e6 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/outliner/exceptions/ThrowBlockOutlinerArrayUseTypeTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/outliner/exceptions/ThrowBlockOutlinerArrayUseTypeTest.java
@@ -3,22 +3,46 @@
 // BSD-style license that can be found in the LICENSE file.
 package com.android.tools.r8.ir.optimize.outliner.exceptions;
 
+import static org.hamcrest.CoreMatchers.containsString;
 import static org.junit.Assert.assertEquals;
 
+import com.android.tools.r8.KeepUnusedArguments;
+import com.android.tools.r8.NeverInline;
+import com.android.tools.r8.SingleTestRunResult;
+import com.android.tools.r8.TestCompileResult;
+import com.android.tools.r8.TestCompilerBuilder;
 import com.android.tools.r8.graph.DexItemFactory;
+import com.android.tools.r8.utils.codeinspector.ClassSubject;
 import java.util.Collection;
 import org.junit.Test;
 
 public class ThrowBlockOutlinerArrayUseTypeTest extends ThrowBlockOutlinerTestBase {
 
   @Test
-  public void test() throws Exception {
-    testForD8(parameters)
-        .addInnerClasses(getClass())
-        .apply(this::configure)
-        .compile()
+  public void testD8() throws Exception {
+    runTest(testForD8(parameters));
+  }
+
+  @Test
+  public void testR8() throws Exception {
+    assumeRelease();
+    runTest(
+        testForR8(parameters)
+            .addKeepMainRule(Main.class)
+            .enableInliningAnnotations()
+            .enableUnusedArgumentAnnotations());
+  }
+
+  private void runTest(
+      TestCompilerBuilder<?, ?, ?, ? extends SingleTestRunResult<?>, ?> testBuilder)
+      throws Exception {
+    TestCompileResult<?, ?> compileResult =
+        testBuilder.addInnerClasses(getClass()).apply(this::configure).compile();
+
+    ClassSubject exceptionClassSubject = compileResult.inspector().clazz(MyException.class);
+    compileResult
         .run(parameters.getRuntime(), Main.class)
-        .assertFailureWithErrorThatThrows(MyException.class);
+        .assertFailureWithErrorThatMatches(containsString(exceptionClassSubject.getFinalName()));
   }
 
   @Override
@@ -46,6 +70,8 @@
 
   static class MyException extends RuntimeException {
 
+    @KeepUnusedArguments
+    @NeverInline
     MyException(String msg, Main[] main) {}
   }
 }
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/outliner/exceptions/ThrowBlockOutlinerConstArgumentTest.java b/src/test/java/com/android/tools/r8/ir/optimize/outliner/exceptions/ThrowBlockOutlinerConstArgumentTest.java
index cd6c533..2badee6 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/outliner/exceptions/ThrowBlockOutlinerConstArgumentTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/outliner/exceptions/ThrowBlockOutlinerConstArgumentTest.java
@@ -10,8 +10,11 @@
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
 
+import com.android.tools.r8.SingleTestRunResult;
 import com.android.tools.r8.TestCompileResult;
+import com.android.tools.r8.TestCompilerBuilder;
 import com.android.tools.r8.graph.DexItemFactory;
+import com.android.tools.r8.ir.optimize.outliner.exceptions.ThrowBlockOutlinerArrayUseTypeTest.Main;
 import com.android.tools.r8.synthesis.SyntheticItemsTestUtils;
 import com.android.tools.r8.utils.codeinspector.ClassSubject;
 import com.android.tools.r8.utils.codeinspector.CodeInspector;
@@ -24,9 +27,21 @@
 public class ThrowBlockOutlinerConstArgumentTest extends ThrowBlockOutlinerTestBase {
 
   @Test
-  public void test() throws Exception {
+  public void testD8() throws Exception {
+    runTest(testForD8(parameters));
+  }
+
+  @Test
+  public void testR8() throws Exception {
+    assumeRelease();
+    runTest(testForR8(parameters).addKeepMainRule(Main.class));
+  }
+
+  private void runTest(
+      TestCompilerBuilder<?, ?, ?, ? extends SingleTestRunResult<?>, ?> testBuilder)
+      throws Exception {
     TestCompileResult<?, ?> compileResult =
-        testForD8(parameters)
+        testBuilder
             .addInnerClasses(getClass())
             .apply(this::configure)
             .compile()
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/outliner/exceptions/ThrowBlockOutlinerInterfaceMethodDesugaringTest.java b/src/test/java/com/android/tools/r8/ir/optimize/outliner/exceptions/ThrowBlockOutlinerInterfaceMethodDesugaringTest.java
index 3b9a6e4..d0c21e3 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/outliner/exceptions/ThrowBlockOutlinerInterfaceMethodDesugaringTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/outliner/exceptions/ThrowBlockOutlinerInterfaceMethodDesugaringTest.java
@@ -6,8 +6,11 @@
 import static org.hamcrest.CoreMatchers.containsString;
 import static org.junit.Assert.assertEquals;
 
+import com.android.tools.r8.SingleTestRunResult;
 import com.android.tools.r8.TestCompileResult;
+import com.android.tools.r8.TestCompilerBuilder;
 import com.android.tools.r8.graph.DexItemFactory;
+import com.android.tools.r8.ir.optimize.outliner.exceptions.ThrowBlockOutlinerArrayUseTypeTest.Main;
 import com.android.tools.r8.utils.codeinspector.CodeInspector;
 import java.util.Collection;
 import org.junit.Test;
@@ -15,9 +18,21 @@
 public class ThrowBlockOutlinerInterfaceMethodDesugaringTest extends ThrowBlockOutlinerTestBase {
 
   @Test
-  public void test() throws Exception {
+  public void testD8() throws Exception {
+    runTest(testForD8(parameters));
+  }
+
+  @Test
+  public void testR8() throws Exception {
+    assumeRelease();
+    runTest(testForR8(parameters).addKeepMainRule(Main.class));
+  }
+
+  private void runTest(
+      TestCompilerBuilder<?, ?, ?, ? extends SingleTestRunResult<?>, ?> testBuilder)
+      throws Exception {
     TestCompileResult<?, ?> compileResult =
-        testForD8(parameters)
+        testBuilder
             .addProgramClasses(Main.class, A.class)
             .addProgramClassFileData(
                 transformer(I.class)
@@ -25,7 +40,7 @@
                     .transform())
             .apply(this::configure)
             .compile()
-            .inspect(this::inspectOutput);
+            .inspect(inspector -> inspectOutput(inspector, testBuilder));
     compileResult
         .run(parameters.getRuntime(), Main.class, "default")
         .assertFailureWithErrorThatThrows(RuntimeException.class)
@@ -49,7 +64,12 @@
     assertEquals(3, outline.getNumberOfUsers());
   }
 
-  private void inspectOutput(CodeInspector inspector) {
+  private void inspectOutput(
+      CodeInspector inspector,
+      TestCompilerBuilder<?, ?, ?, ? extends SingleTestRunResult<?>, ?> testBuilder) {
+    if (testBuilder.isR8TestBuilder()) {
+      return;
+    }
     // Main, I, I$-CC, A and the synthetic outline class.
     assertEquals(
         parameters.canUseDefaultAndStaticInterfaceMethods() ? 4 : 5, inspector.allClasses().size());
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/outliner/exceptions/ThrowBlockOutlinerNoArgumentsTest.java b/src/test/java/com/android/tools/r8/ir/optimize/outliner/exceptions/ThrowBlockOutlinerNoArgumentsTest.java
index 994e8be..cfb6c30 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/outliner/exceptions/ThrowBlockOutlinerNoArgumentsTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/outliner/exceptions/ThrowBlockOutlinerNoArgumentsTest.java
@@ -10,7 +10,9 @@
 import static org.junit.Assert.assertTrue;
 
 import com.android.tools.r8.CompilationMode;
+import com.android.tools.r8.SingleTestRunResult;
 import com.android.tools.r8.TestCompileResult;
+import com.android.tools.r8.TestCompilerBuilder;
 import com.android.tools.r8.graph.DexItemFactory;
 import com.android.tools.r8.synthesis.SyntheticItemsTestUtils;
 import com.android.tools.r8.utils.BooleanUtils;
@@ -39,9 +41,21 @@
   }
 
   @Test
-  public void test() throws Exception {
+  public void testD8() throws Exception {
+    runTest(testForD8(parameters));
+  }
+
+  @Test
+  public void testR8() throws Exception {
+    assumeRelease();
+    runTest(testForR8(parameters).addKeepMainRule(Main.class));
+  }
+
+  private void runTest(
+      TestCompilerBuilder<?, ?, ?, ? extends SingleTestRunResult<?>, ?> testBuilder)
+      throws Exception {
     TestCompileResult<?, ?> compileResult =
-        testForD8(parameters)
+        testBuilder
             .addInnerClasses(getClass())
             .apply(this::configure)
             .addOptionsModification(
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/outliner/exceptions/ThrowBlockOutlinerSharedStringBuilderTest.java b/src/test/java/com/android/tools/r8/ir/optimize/outliner/exceptions/ThrowBlockOutlinerSharedStringBuilderTest.java
index bebc31b..51d44e7 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/outliner/exceptions/ThrowBlockOutlinerSharedStringBuilderTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/outliner/exceptions/ThrowBlockOutlinerSharedStringBuilderTest.java
@@ -10,9 +10,12 @@
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
 
+import com.android.tools.r8.SingleTestRunResult;
 import com.android.tools.r8.TestCompileResult;
+import com.android.tools.r8.TestCompilerBuilder;
 import com.android.tools.r8.graph.DexItemFactory;
 import com.android.tools.r8.ir.analysis.value.AbstractValue;
+import com.android.tools.r8.ir.optimize.outliner.exceptions.ThrowBlockOutlinerArrayUseTypeTest.Main;
 import com.android.tools.r8.synthesis.SyntheticItemsTestUtils;
 import com.android.tools.r8.utils.ListUtils;
 import com.android.tools.r8.utils.codeinspector.ClassSubject;
@@ -25,9 +28,21 @@
 public class ThrowBlockOutlinerSharedStringBuilderTest extends ThrowBlockOutlinerTestBase {
 
   @Test
-  public void test() throws Exception {
+  public void testD8() throws Exception {
+    runTest(testForD8(parameters));
+  }
+
+  @Test
+  public void testR8() throws Exception {
+    assumeRelease();
+    runTest(testForR8(parameters).addKeepMainRule(Main.class));
+  }
+
+  private void runTest(
+      TestCompilerBuilder<?, ?, ?, ? extends SingleTestRunResult<?>, ?> testBuilder)
+      throws Exception {
     TestCompileResult<?, ?> compileResult =
-        testForD8(parameters)
+        testBuilder
             .addInnerClasses(getClass())
             .apply(this::configure)
             .compile()
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/outliner/exceptions/ThrowBlockOutlinerTestBase.java b/src/test/java/com/android/tools/r8/ir/optimize/outliner/exceptions/ThrowBlockOutlinerTestBase.java
index f507e28..5b62f54 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/outliner/exceptions/ThrowBlockOutlinerTestBase.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/outliner/exceptions/ThrowBlockOutlinerTestBase.java
@@ -3,8 +3,8 @@
 // BSD-style license that can be found in the LICENSE file.
 package com.android.tools.r8.ir.optimize.outliner.exceptions;
 
-import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
+import static org.junit.Assume.assumeTrue;
 
 import com.android.tools.r8.CompilationMode;
 import com.android.tools.r8.SingleTestRunResult;
@@ -49,14 +49,20 @@
     assertTrue(receivedCallback.isTrue());
   }
 
+  public void assumeRelease() {
+    if (mode.isDebug()) {
+      receivedCallback.set();
+    }
+    assumeTrue(mode.isRelease());
+  }
+
   public void configure(
       TestCompilerBuilder<?, ?, ?, ? extends SingleTestRunResult<?>, ?> testBuilder) {
     testBuilder
         .addOptionsModification(
             options -> {
               ThrowBlockOutlinerOptions outlinerOptions = options.getThrowBlockOutlinerOptions();
-              assertFalse(outlinerOptions.enable);
-              outlinerOptions.enable = true;
+              assertTrue(outlinerOptions.enable);
               outlinerOptions.forceDebug = true;
               outlinerOptions.outlineConsumerForTesting =
                   outlines -> {
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/outliner/exceptions/ThrowBlockOutlinerUseTypeTest.java b/src/test/java/com/android/tools/r8/ir/optimize/outliner/exceptions/ThrowBlockOutlinerUseTypeTest.java
index d48861d..5a3fcdb 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/outliner/exceptions/ThrowBlockOutlinerUseTypeTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/outliner/exceptions/ThrowBlockOutlinerUseTypeTest.java
@@ -3,22 +3,46 @@
 // BSD-style license that can be found in the LICENSE file.
 package com.android.tools.r8.ir.optimize.outliner.exceptions;
 
+import static org.hamcrest.CoreMatchers.containsString;
 import static org.junit.Assert.assertEquals;
 
+import com.android.tools.r8.KeepUnusedArguments;
+import com.android.tools.r8.NeverInline;
+import com.android.tools.r8.SingleTestRunResult;
+import com.android.tools.r8.TestCompileResult;
+import com.android.tools.r8.TestCompilerBuilder;
 import com.android.tools.r8.graph.DexItemFactory;
+import com.android.tools.r8.utils.codeinspector.ClassSubject;
 import java.util.Collection;
 import org.junit.Test;
 
 public class ThrowBlockOutlinerUseTypeTest extends ThrowBlockOutlinerTestBase {
 
   @Test
-  public void test() throws Exception {
-    testForD8(parameters)
-        .addInnerClasses(getClass())
-        .apply(this::configure)
-        .compile()
+  public void testD8() throws Exception {
+    runTest(testForD8(parameters));
+  }
+
+  @Test
+  public void testR8() throws Exception {
+    assumeRelease();
+    runTest(
+        testForR8(parameters)
+            .addKeepMainRule(Main.class)
+            .enableInliningAnnotations()
+            .enableUnusedArgumentAnnotations());
+  }
+
+  private void runTest(
+      TestCompilerBuilder<?, ?, ?, ? extends SingleTestRunResult<?>, ?> testBuilder)
+      throws Exception {
+    TestCompileResult<?, ?> compileResult =
+        testBuilder.addInnerClasses(getClass()).apply(this::configure).compile();
+
+    ClassSubject exceptionClassSubject = compileResult.inspector().clazz(MyException.class);
+    compileResult
         .run(parameters.getRuntime(), Main.class)
-        .assertFailureWithErrorThatThrows(MyException.class);
+        .assertFailureWithErrorThatMatches(containsString(exceptionClassSubject.getFinalName()));
   }
 
   @Override
@@ -46,6 +70,8 @@
 
   static class MyException extends RuntimeException {
 
+    @KeepUnusedArguments
+    @NeverInline
     MyException(String msg, Main main) {}
   }
 }
diff --git a/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteInlineSuspendFunctionTest.java b/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteInlineSuspendFunctionTest.java
index 59d559a..58456ef 100644
--- a/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteInlineSuspendFunctionTest.java
+++ b/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteInlineSuspendFunctionTest.java
@@ -102,6 +102,7 @@
             kotlinc.getKotlinStdlibJar(), kotlinc.getKotlinxCoroutinesCoreJar(), libJar)
         .addClasspath(output)
         .run(parameters.getRuntime(), PKG_APP + ".MainKt")
+        // TODO(b/449961100): R8 should keep $$forInline functions if original is kept.
         .assertFailureWithErrorThatThrowsIf(keepOnlyPublic, VerifyError.class)
         .assertSuccessWithOutputIf(!keepOnlyPublic, EXPECTED);
   }
diff --git a/src/test/java/com/android/tools/r8/optimize/serviceloader/ServiceLoaderTestBase.java b/src/test/java/com/android/tools/r8/optimize/serviceloader/ServiceLoaderTestBase.java
index 54ba9f3..56f3eba 100644
--- a/src/test/java/com/android/tools/r8/optimize/serviceloader/ServiceLoaderTestBase.java
+++ b/src/test/java/com/android/tools/r8/optimize/serviceloader/ServiceLoaderTestBase.java
@@ -138,7 +138,6 @@
                   o.enableServiceLoaderRewriting = enableRewriting;
                 })
             // Enables ServiceLoader optimization failure diagnostics.
-            .enableExperimentalWhyAreYouNotInlining()
             .addKeepRules("-whyareyounotinlining class java.util.ServiceLoader { *** load(...); }");
     if (implClasses.length > 0) {
       String implLines =
diff --git a/src/test/java/com/android/tools/r8/shaking/ProguardConfigurationParserTest.java b/src/test/java/com/android/tools/r8/shaking/ProguardConfigurationParserTest.java
index f9f7c65..cb788dc 100644
--- a/src/test/java/com/android/tools/r8/shaking/ProguardConfigurationParserTest.java
+++ b/src/test/java/com/android/tools/r8/shaking/ProguardConfigurationParserTest.java
@@ -185,8 +185,6 @@
             ProguardConfigurationParserOptions.builder()
                 .setEnableLegacyFullModeForKeepRules(false)
                 .setEnableExperimentalCheckEnumUnboxed(false)
-                .setEnableExperimentalConvertCheckNotNull(false)
-                .setEnableExperimentalWhyAreYouNotInlining(false)
                 .setEnableTestingOptions(false)
                 .build(),
             null,
@@ -205,8 +203,6 @@
             reporter,
             ProguardConfigurationParserOptions.builder()
                 .setEnableExperimentalCheckEnumUnboxed(false)
-                .setEnableExperimentalConvertCheckNotNull(false)
-                .setEnableExperimentalWhyAreYouNotInlining(false)
                 .setEnableTestingOptions(true)
                 .build(),
             null,
@@ -728,8 +724,6 @@
             reporter,
             ProguardConfigurationParserOptions.builder()
                 .setEnableExperimentalCheckEnumUnboxed(false)
-                .setEnableExperimentalConvertCheckNotNull(true)
-                .setEnableExperimentalWhyAreYouNotInlining(false)
                 .setEnableTestingOptions(false)
                 .build(),
             null,
@@ -750,8 +744,6 @@
             reporter,
             ProguardConfigurationParserOptions.builder()
                 .setEnableExperimentalCheckEnumUnboxed(false)
-                .setEnableExperimentalConvertCheckNotNull(true)
-                .setEnableExperimentalWhyAreYouNotInlining(false)
                 .setEnableTestingOptions(false)
                 .build(),
             null,
diff --git a/src/test/java/com/android/tools/r8/shaking/convertchecknotnull/ConvertCheckNotNullTest.java b/src/test/java/com/android/tools/r8/shaking/convertchecknotnull/ConvertCheckNotNullTest.java
index b1ad9de..eeb7d6c 100644
--- a/src/test/java/com/android/tools/r8/shaking/convertchecknotnull/ConvertCheckNotNullTest.java
+++ b/src/test/java/com/android/tools/r8/shaking/convertchecknotnull/ConvertCheckNotNullTest.java
@@ -54,7 +54,6 @@
             "-convertchecknotnull class java.util.Objects {",
             "  ** requireNonNull(**, ...);",
             "}")
-        .enableExperimentalConvertCheckNotNull()
         .setMinApi(parameters)
         .compile()
         .inspect(
diff --git a/src/test/java/com/android/tools/r8/shaking/convertchecknotnull/ConvertCheckNotNullWithAssumeNoSideEffectsTest.java b/src/test/java/com/android/tools/r8/shaking/convertchecknotnull/ConvertCheckNotNullWithAssumeNoSideEffectsTest.java
index fa3cc91..38f4d09 100644
--- a/src/test/java/com/android/tools/r8/shaking/convertchecknotnull/ConvertCheckNotNullWithAssumeNoSideEffectsTest.java
+++ b/src/test/java/com/android/tools/r8/shaking/convertchecknotnull/ConvertCheckNotNullWithAssumeNoSideEffectsTest.java
@@ -45,7 +45,6 @@
             "-convertchecknotnull class java.util.Objects {",
             "  ** requireNonNull(...);",
             "}")
-        .enableExperimentalConvertCheckNotNull()
         .setMinApi(parameters)
         .compile()
         .inspect(
diff --git a/src/test/testbase/java/com/android/tools/r8/R8TestBuilder.java b/src/test/testbase/java/com/android/tools/r8/R8TestBuilder.java
index 2ac3d7b..58f7a23 100644
--- a/src/test/testbase/java/com/android/tools/r8/R8TestBuilder.java
+++ b/src/test/testbase/java/com/android/tools/r8/R8TestBuilder.java
@@ -818,16 +818,6 @@
     return self();
   }
 
-  public T enableExperimentalConvertCheckNotNull() {
-    builder.setEnableExperimentalConvertCheckNotNull();
-    return self();
-  }
-
-  public T enableExperimentalWhyAreYouNotInlining() {
-    builder.setEnableExperimentalWhyAreYouNotInlining();
-    return self();
-  }
-
   public T enableExperimentalKeepAnnotations(KeepAnnotationLibrary keepAnnotationLibrary) {
     return addOptionsModification(o -> o.testing.enableEmbeddedKeepAnnotations = true)
         .addKeepAnnoLibToClasspath(keepAnnotationLibrary);
diff --git a/src/test/testbase/java/com/android/tools/r8/TestCompilerBuilder.java b/src/test/testbase/java/com/android/tools/r8/TestCompilerBuilder.java
index 35ab038..25efdbf 100644
--- a/src/test/testbase/java/com/android/tools/r8/TestCompilerBuilder.java
+++ b/src/test/testbase/java/com/android/tools/r8/TestCompilerBuilder.java
@@ -64,6 +64,7 @@
   public static final Consumer<InternalOptions> DEFAULT_OPTIONS =
       options -> {
         options.testing.enableTestAssertions = true;
+        options.getThrowBlockOutlinerOptions().enable = true;
       };
 
   public static final Consumer<InternalOptions> DEFAULT_D8_OPTIONS = DEFAULT_OPTIONS;
@@ -76,7 +77,6 @@
             options.testing.forcePruneMetaInfManifestMf = true;
             options.horizontalClassMergerOptions().enable();
             options.horizontalClassMergerOptions().setEnableInterfaceMerging();
-            options.inlinerOptions().enableConstructorInliningWithFinalFields = true;
             options
                 .getCfCodeAnalysisOptions()
                 .setAllowUnreachableCfBlocks(false)