Enable new argument propagation

Change-Id: Iade5f22bffaf9d3283b8e5f3d78772a8c04a5c60
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 2a44d85..4a6a664 100644
--- a/src/main/java/com/android/tools/r8/utils/InternalOptions.java
+++ b/src/main/java/com/android/tools/r8/utils/InternalOptions.java
@@ -1219,7 +1219,7 @@
 
     // TODO(b/69963623): enable if everything is ready, including signature rewriting at call sites.
     private boolean enableLegacyConstantPropagation = false;
-    private boolean enableExperimentalArgumentPropagation = false;
+    private boolean enableExperimentalArgumentPropagation = true;
     private boolean enableDynamicTypePropagation = true;
 
     public void disableOptimization() {
@@ -1255,7 +1255,7 @@
     }
 
     public CallSiteOptimizationOptions setEnableLegacyConstantPropagation() {
-      assert !isConstantPropagationEnabled();
+      assert !enableLegacyConstantPropagation;
       enableLegacyConstantPropagation = true;
       return this;
     }
diff --git a/src/test/examples/shaking14/KeepConstantArguments.java b/src/test/examples/shaking14/KeepConstantArguments.java
new file mode 100644
index 0000000..0ff3910
--- /dev/null
+++ b/src/test/examples/shaking14/KeepConstantArguments.java
@@ -0,0 +1,13 @@
+// Copyright (c) 2021, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+package shaking14;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Retention(RetentionPolicy.CLASS)
+@Target({ElementType.METHOD})
+public @interface KeepConstantArguments {}
diff --git a/src/test/examples/shaking14/Subclass.java b/src/test/examples/shaking14/Subclass.java
index 31dd650..2cb520a 100644
--- a/src/test/examples/shaking14/Subclass.java
+++ b/src/test/examples/shaking14/Subclass.java
@@ -4,10 +4,13 @@
 package shaking14;
 
 public class Subclass extends Superclass {
+
+  @KeepConstantArguments
   static int aMethod(int value) {
     return value + 42;
   }
 
+  @KeepConstantArguments
   static double anotherMethod(double value) {
     return value + 42;
   }
diff --git a/src/test/examples/shaking14/keep-rules.txt b/src/test/examples/shaking14/keep-rules.txt
index 94682a3..594e244 100644
--- a/src/test/examples/shaking14/keep-rules.txt
+++ b/src/test/examples/shaking14/keep-rules.txt
@@ -10,3 +10,4 @@
 
 # allow access modification to enable minifcation
 -allowaccessmodification
+-keepconstantarguments class * { @shaking14.KeepConstantArguments *; }
diff --git a/src/test/java/com/android/tools/r8/KeepConstantArguments.java b/src/test/java/com/android/tools/r8/KeepConstantArguments.java
index 87edb4f..132b92d 100644
--- a/src/test/java/com/android/tools/r8/KeepConstantArguments.java
+++ b/src/test/java/com/android/tools/r8/KeepConstantArguments.java
@@ -4,7 +4,10 @@
 package com.android.tools.r8;
 
 import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 import java.lang.annotation.Target;
 
-@Target({ElementType.METHOD})
+@Retention(RetentionPolicy.CLASS)
+@Target({ElementType.CONSTRUCTOR, ElementType.METHOD})
 public @interface KeepConstantArguments {}
diff --git a/src/test/java/com/android/tools/r8/R8RunArtTestsTest.java b/src/test/java/com/android/tools/r8/R8RunArtTestsTest.java
index c81cdfc..188f23f 100644
--- a/src/test/java/com/android/tools/r8/R8RunArtTestsTest.java
+++ b/src/test/java/com/android/tools/r8/R8RunArtTestsTest.java
@@ -1287,8 +1287,16 @@
 
   private static Map<String, List<String>> keepRules =
       ImmutableMap.of(
-          "021-string2", ImmutableList.of("-dontwarn junit.framework.**"),
-          "082-inline-execute", ImmutableList.of("-dontwarn junit.framework.**"));
+          "021-string2",
+          ImmutableList.of("-dontwarn junit.framework.**"),
+          "082-inline-execute",
+          ImmutableList.of("-dontwarn junit.framework.**"),
+          // Constructor MakeBoundType.<init>(int) is called using reflection.
+          "476-checker-ctor-fence-redun-elim",
+          ImmutableList.of(
+              "-keep class TestDontOptimizeAcrossEscape$MakeBoundTypeTest$MakeBoundType {",
+              "  void <init>(int);",
+              "}"));
 
   private static Map<String, Consumer<InternalOptions>> configurations =
       ImmutableMap.of(
diff --git a/src/test/java/com/android/tools/r8/R8RunExamplesAndroidOTest.java b/src/test/java/com/android/tools/r8/R8RunExamplesAndroidOTest.java
index fb37493..08dd682 100644
--- a/src/test/java/com/android/tools/r8/R8RunExamplesAndroidOTest.java
+++ b/src/test/java/com/android/tools/r8/R8RunExamplesAndroidOTest.java
@@ -120,7 +120,7 @@
         .withOptionConsumer(opts -> opts.enableClassInlining = false)
         .withBuilderTransformation(
             b -> b.addProguardConfiguration(PROGUARD_OPTIONS, Origin.unknown()))
-        .withDexCheck(inspector -> checkLambdaCount(inspector, 10, "lambdadesugaring"))
+        .withDexCheck(inspector -> checkLambdaCount(inspector, 9, "lambdadesugaring"))
         .run();
 
     test("lambdadesugaring", "lambdadesugaring", "LambdaDesugaring")
@@ -159,7 +159,7 @@
         .withOptionConsumer(opts -> opts.enableClassInlining = false)
         .withBuilderTransformation(
             b -> b.addProguardConfiguration(PROGUARD_OPTIONS, Origin.unknown()))
-        .withDexCheck(inspector -> checkLambdaCount(inspector, 10, "lambdadesugaring"))
+        .withDexCheck(inspector -> checkLambdaCount(inspector, 9, "lambdadesugaring"))
         .run();
 
     test("lambdadesugaring", "lambdadesugaring", "LambdaDesugaring")
@@ -204,7 +204,7 @@
             b ->
                 b.addProguardConfiguration(
                     getProguardOptionsNPlus(enableProguardCompatibilityMode), Origin.unknown()))
-        .withDexCheck(inspector -> checkLambdaCount(inspector, 2, "lambdadesugaringnplus"))
+        .withDexCheck(inspector -> checkLambdaCount(inspector, 3, "lambdadesugaringnplus"))
         .run();
   }
 
diff --git a/src/test/java/com/android/tools/r8/accessrelaxation/NonConstructorRelaxationTest.java b/src/test/java/com/android/tools/r8/accessrelaxation/NonConstructorRelaxationTest.java
index 8cd7860..6bf8cf9 100644
--- a/src/test/java/com/android/tools/r8/accessrelaxation/NonConstructorRelaxationTest.java
+++ b/src/test/java/com/android/tools/r8/accessrelaxation/NonConstructorRelaxationTest.java
@@ -78,6 +78,7 @@
     R8TestRunResult result =
         testForR8(parameters.getBackend())
             .addProgramFiles(ToolHelper.getClassFilesForTestPackage(mainClass.getPackage()))
+            .enableConstantArgumentAnnotations()
             .enableInliningAnnotations()
             .enableNoHorizontalClassMergingAnnotations()
             .enableMemberValuePropagationAnnotations()
@@ -162,6 +163,7 @@
             .addProgramFiles(ToolHelper.getClassFilesForTestPackage(mainClass.getPackage()))
             .addKeepMainRule(mainClass)
             .addOptionsModification(o -> o.enableVerticalClassMerging = enableVerticalClassMerging)
+            .enableConstantArgumentAnnotations()
             .enableNeverClassInliningAnnotations()
             .enableInliningAnnotations()
             .enableMemberValuePropagationAnnotations()
diff --git a/src/test/java/com/android/tools/r8/accessrelaxation/privateinstance/Sub1.java b/src/test/java/com/android/tools/r8/accessrelaxation/privateinstance/Sub1.java
index c832fe7..7974306 100644
--- a/src/test/java/com/android/tools/r8/accessrelaxation/privateinstance/Sub1.java
+++ b/src/test/java/com/android/tools/r8/accessrelaxation/privateinstance/Sub1.java
@@ -3,6 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 package com.android.tools.r8.accessrelaxation.privateinstance;
 
+import com.android.tools.r8.KeepConstantArguments;
 import com.android.tools.r8.NeverClassInline;
 import com.android.tools.r8.NeverInline;
 import com.android.tools.r8.NoHorizontalClassMerging;
@@ -16,6 +17,7 @@
     return "Sub1::foo1()";
   }
 
+  @KeepConstantArguments
   @NeverInline
   private String bar1(int i) {
     return "Sub1::bar1(" + i + ")";
diff --git a/src/test/java/com/android/tools/r8/accessrelaxation/privateinstance/Sub2.java b/src/test/java/com/android/tools/r8/accessrelaxation/privateinstance/Sub2.java
index ffdeec6..6e8d5f7 100644
--- a/src/test/java/com/android/tools/r8/accessrelaxation/privateinstance/Sub2.java
+++ b/src/test/java/com/android/tools/r8/accessrelaxation/privateinstance/Sub2.java
@@ -3,6 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 package com.android.tools.r8.accessrelaxation.privateinstance;
 
+import com.android.tools.r8.KeepConstantArguments;
 import com.android.tools.r8.NeverClassInline;
 import com.android.tools.r8.NeverInline;
 import com.android.tools.r8.NoHorizontalClassMerging;
@@ -16,6 +17,7 @@
     return "Sub2::foo2()";
   }
 
+  @KeepConstantArguments
   @NeverInline
   private String bar1(int i) {
     return "Sub2::bar1(" + i + ")";
@@ -25,6 +27,7 @@
     return bar1(1);
   }
 
+  @KeepConstantArguments
   @NeverInline
   private String bar2(int i) {
     return "Sub2::bar2(" + i + ")";
diff --git a/src/test/java/com/android/tools/r8/accessrelaxation/privatestatic/A.java b/src/test/java/com/android/tools/r8/accessrelaxation/privatestatic/A.java
index a05f41f..a0c3330 100644
--- a/src/test/java/com/android/tools/r8/accessrelaxation/privatestatic/A.java
+++ b/src/test/java/com/android/tools/r8/accessrelaxation/privatestatic/A.java
@@ -4,6 +4,7 @@
 
 package com.android.tools.r8.accessrelaxation.privatestatic;
 
+import com.android.tools.r8.KeepConstantArguments;
 import com.android.tools.r8.NeverInline;
 import com.android.tools.r8.NeverPropagateValue;
 
@@ -42,6 +43,7 @@
     return bar(1);
   }
 
+  @KeepConstantArguments
   @NeverInline
   @NeverPropagateValue
   private static String blah(int i) {
diff --git a/src/test/java/com/android/tools/r8/accessrelaxation/privatestatic/BB.java b/src/test/java/com/android/tools/r8/accessrelaxation/privatestatic/BB.java
index a6c40ff..d458af8 100644
--- a/src/test/java/com/android/tools/r8/accessrelaxation/privatestatic/BB.java
+++ b/src/test/java/com/android/tools/r8/accessrelaxation/privatestatic/BB.java
@@ -4,12 +4,15 @@
 
 package com.android.tools.r8.accessrelaxation.privatestatic;
 
+import com.android.tools.r8.KeepConstantArguments;
 import com.android.tools.r8.NeverInline;
 import com.android.tools.r8.NeverPropagateValue;
 import com.android.tools.r8.NoHorizontalClassMerging;
 
 @NoHorizontalClassMerging
 public class BB extends A {
+
+  @KeepConstantArguments
   @NeverInline
   @NeverPropagateValue
   private static String blah(int i) {
diff --git a/src/test/java/com/android/tools/r8/apimodel/ApiModelNoInliningOfHigherApiLevelInterfaceTest.java b/src/test/java/com/android/tools/r8/apimodel/ApiModelNoInliningOfHigherApiLevelInterfaceTest.java
index 602f4a1..bdaf09d 100644
--- a/src/test/java/com/android/tools/r8/apimodel/ApiModelNoInliningOfHigherApiLevelInterfaceTest.java
+++ b/src/test/java/com/android/tools/r8/apimodel/ApiModelNoInliningOfHigherApiLevelInterfaceTest.java
@@ -7,6 +7,7 @@
 import static com.android.tools.r8.apimodel.ApiModelingTestHelper.setMockApiLevelForMethod;
 import static com.android.tools.r8.apimodel.ApiModelingTestHelper.verifyThat;
 
+import com.android.tools.r8.KeepConstantArguments;
 import com.android.tools.r8.NeverInline;
 import com.android.tools.r8.NoHorizontalClassMerging;
 import com.android.tools.r8.TestBase;
@@ -44,6 +45,7 @@
         .addDefaultRuntimeLibrary(parameters)
         .setMinApi(parameters.getApiLevel())
         .addKeepMainRule(Main.class)
+        .enableConstantArgumentAnnotations()
         .enableInliningAnnotations()
         .enableNoHorizontalClassMergingAnnotations()
         .apply(setMockApiLevelForMethod(apiMethod, AndroidApiLevel.L_MR1))
@@ -63,6 +65,7 @@
   @NoHorizontalClassMerging
   public static class ApiCaller {
 
+    @KeepConstantArguments
     public static void callInterfaceMethod(Api api) {
       System.out.println("ApiCaller::callInterfaceMethod");
       if (api != null) {
diff --git a/src/test/java/com/android/tools/r8/bridgeremoval/B77836766.java b/src/test/java/com/android/tools/r8/bridgeremoval/B77836766.java
index 07ad8f0..1790724 100644
--- a/src/test/java/com/android/tools/r8/bridgeremoval/B77836766.java
+++ b/src/test/java/com/android/tools/r8/bridgeremoval/B77836766.java
@@ -8,6 +8,7 @@
 import static org.hamcrest.MatcherAssert.assertThat;
 import static org.junit.Assert.assertEquals;
 
+import com.android.tools.r8.KeepConstantArguments;
 import com.android.tools.r8.TestBase;
 import com.android.tools.r8.TestParameters;
 import com.android.tools.r8.TestParametersCollection;
@@ -93,6 +94,7 @@
     ClassBuilder cls1 = jasminBuilder.addClass("Cls1", absCls.name, itf1.name);
     // Mimic Kotlin's "internal" class
     cls1.setAccess("");
+    cls1.addRuntimeInvisibleAnnotation(KeepConstantArguments.class.getTypeName());
     cls1.addBridgeMethod("foo", ImmutableList.of("Ljava/lang/String;"), "V",
         ".limit stack 2",
         ".limit locals 2",
@@ -143,6 +145,7 @@
         .addProgramClassFileData(jasminBuilder.buildClasses())
         .addKeepMainRule(mainClass.name)
         .addOptionsModification(this::configure)
+        .enableConstantArgumentAnnotations()
         .noHorizontalClassMerging(cls2Class.name)
         .noMinification()
         .setMinApi(parameters.getApiLevel())
@@ -239,6 +242,7 @@
         "return");
 
     ClassBuilder cls2 = jasminBuilder.addClass("DerivedString", baseCls.name);
+    cls2.addRuntimeInvisibleAnnotation(KeepConstantArguments.class.getTypeName());
     cls2.addVirtualMethod("bar", ImmutableList.of("Ljava/lang/String;"), "V",
         ".limit stack 2",
         ".limit locals 2",
@@ -272,6 +276,7 @@
         .addProgramClassFileData(jasminBuilder.buildClasses())
         .addKeepMainRule(mainClass.name)
         .addOptionsModification(this::configure)
+        .enableConstantArgumentAnnotations()
         .noHorizontalClassMerging(derivedIntegerClass.name)
         .noMinification()
         .setMinApi(parameters.getApiLevel())
@@ -347,6 +352,7 @@
         "return");
 
     ClassBuilder subCls = jasminBuilder.addClass("DerivedString", baseCls.name);
+    subCls.addRuntimeInvisibleAnnotation(KeepConstantArguments.class.getTypeName());
     subCls.addVirtualMethod("bar", ImmutableList.of("Ljava/lang/String;"), "V",
         ".limit stack 2",
         ".limit locals 2",
@@ -381,6 +387,7 @@
         .addProgramClassFileData(jasminBuilder.buildClasses())
         .addKeepMainRule(mainClass.name)
         .addOptionsModification(this::configure)
+        .enableConstantArgumentAnnotations()
         .noMinification()
         .setMinApi(parameters.getApiLevel())
         .compile()
@@ -433,6 +440,7 @@
         "aload_1",
         "invokevirtual java/io/PrintStream/print(Ljava/lang/Object;)V",
         "return");
+    cls.addRuntimeInvisibleAnnotation(KeepConstantArguments.class.getTypeName());
     cls.addVirtualMethod("bar", ImmutableList.of("Ljava/lang/String;"), "V",
         ".limit stack 2",
         ".limit locals 2",
@@ -467,6 +475,7 @@
         .addProgramClassFileData(jasminBuilder.buildClasses())
         .addKeepMainRule(mainClass.name)
         .addOptionsModification(this::configure)
+        .enableConstantArgumentAnnotations()
         .noMinification()
         .setMinApi(parameters.getApiLevel())
         .compile()
@@ -495,7 +504,6 @@
     // Callees are invoked with a simple constant, e.g., "Bar". Propagating it into the callees
     // bothers what the tests want to check, such as exact instructions in the body that include
     // invocation kinds, like virtual call to a bridge.
-    assert !options.callSiteOptimizationOptions().isConstantPropagationEnabled();
     // Disable inlining to avoid the (short) tested method from being inlined and then removed.
     options.enableInlining = false;
   }
diff --git a/src/test/java/com/android/tools/r8/bridgeremoval/hoisting/BridgeHoistingAccessibilityTest.java b/src/test/java/com/android/tools/r8/bridgeremoval/hoisting/BridgeHoistingAccessibilityTest.java
index 81c5c04..45855d8 100644
--- a/src/test/java/com/android/tools/r8/bridgeremoval/hoisting/BridgeHoistingAccessibilityTest.java
+++ b/src/test/java/com/android/tools/r8/bridgeremoval/hoisting/BridgeHoistingAccessibilityTest.java
@@ -6,6 +6,7 @@
 import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
 import static org.hamcrest.MatcherAssert.assertThat;
 
+import com.android.tools.r8.KeepConstantArguments;
 import com.android.tools.r8.NeverClassInline;
 import com.android.tools.r8.NeverInline;
 import com.android.tools.r8.NoVerticalClassMerging;
@@ -71,6 +72,7 @@
                         int.class))
                 .transform())
         .addKeepMainRule(TestClass.class)
+        .enableConstantArgumentAnnotations()
         .enableInliningAnnotations()
         .enableNoHorizontalClassMergingAnnotations()
         .enableNoVerticalClassMergingAnnotations()
@@ -119,6 +121,7 @@
 
     // This bridge cannot be hoisted to A, since it would then become inaccessible to the call site
     // in TestClass.main().
+    @KeepConstantArguments
     @NeverInline
     /*bridge*/ String bridgeB(Object o) {
       return (String) m((String) o);
@@ -131,6 +134,7 @@
     // This bridge is invoked from another package. However, this does not prevent us from hoisting
     // the bridge to B, although B is not public, since users from outside this package can still
     // access bridgeC() via class C. From B, the bridge can be hoisted again to A.
+    @KeepConstantArguments
     @NeverInline
     public /*bridge*/ String bridgeC(Object o) {
       return (String) m((String) o);
@@ -142,6 +146,7 @@
 
     // This bridge cannot be hoisted to A, since it would then become inaccessible to the call site
     // in TestClass.main().
+    @KeepConstantArguments
     @NeverInline
     /*bridge*/ String bridgeB(Object o, int a, int b, int c, int d, int e) {
       return (String) m((String) o, a, b, c, d, e);
@@ -154,6 +159,7 @@
     // This bridge is invoked from another package. However, this does not prevent us from hoisting
     // the bridge to B, although B is not public, since users from outside this package can still
     // access bridgeC() via class C. From B, the bridge can be hoisted again to A.
+    @KeepConstantArguments
     @NeverInline
     public /*bridge*/ String bridgeC(Object o, int a, int b, int c, int d, int e) {
       return (String) m((String) o, a, b, c, d, e);
diff --git a/src/test/java/com/android/tools/r8/bridgeremoval/hoisting/FinalBridgeHoistingTest.java b/src/test/java/com/android/tools/r8/bridgeremoval/hoisting/FinalBridgeHoistingTest.java
index de2e041..bf958f8 100644
--- a/src/test/java/com/android/tools/r8/bridgeremoval/hoisting/FinalBridgeHoistingTest.java
+++ b/src/test/java/com/android/tools/r8/bridgeremoval/hoisting/FinalBridgeHoistingTest.java
@@ -7,6 +7,7 @@
 import static org.hamcrest.CoreMatchers.not;
 import static org.hamcrest.MatcherAssert.assertThat;
 
+import com.android.tools.r8.KeepConstantArguments;
 import com.android.tools.r8.NeverClassInline;
 import com.android.tools.r8.NeverInline;
 import com.android.tools.r8.TestBase;
@@ -42,6 +43,7 @@
                 .transform())
         .addKeepMainRule(TestClass.class)
         .addKeepClassAndMembersRules(B1.class)
+        .enableConstantArgumentAnnotations()
         .enableInliningAnnotations()
         .enableNeverClassInliningAnnotations()
         .setMinApi(parameters.getApiLevel())
@@ -85,6 +87,7 @@
   @NeverClassInline
   static class B1 extends A {
 
+    @KeepConstantArguments
     public String virtualBridge(Object o) {
       return (String) m((String) o);
     }
@@ -93,6 +96,7 @@
   @NeverClassInline
   static class B2 extends A {
 
+    @KeepConstantArguments
     @NeverInline
     public final /*bridge*/ String virtualBridge(Object o) {
       return (String) m((String) o);
diff --git a/src/test/java/com/android/tools/r8/bridgeremoval/hoisting/NonSuperclassBridgeHoistingTest.java b/src/test/java/com/android/tools/r8/bridgeremoval/hoisting/NonSuperclassBridgeHoistingTest.java
index f2a91a8..e987a43 100644
--- a/src/test/java/com/android/tools/r8/bridgeremoval/hoisting/NonSuperclassBridgeHoistingTest.java
+++ b/src/test/java/com/android/tools/r8/bridgeremoval/hoisting/NonSuperclassBridgeHoistingTest.java
@@ -7,6 +7,7 @@
 import static org.hamcrest.MatcherAssert.assertThat;
 import static org.junit.Assert.assertFalse;
 
+import com.android.tools.r8.KeepConstantArguments;
 import com.android.tools.r8.NeverClassInline;
 import com.android.tools.r8.NeverInline;
 import com.android.tools.r8.NoVerticalClassMerging;
@@ -42,6 +43,7 @@
                 .setBridge(B.class.getDeclaredMethod("bridge", Object.class))
                 .transform())
         .addKeepMainRule(TestClass.class)
+        .enableConstantArgumentAnnotations()
         .enableInliningAnnotations()
         .enableNoVerticalClassMergingAnnotations()
         .enableNeverClassInliningAnnotations()
@@ -76,6 +78,7 @@
   @NeverClassInline
   static class B extends A {
 
+    @KeepConstantArguments
     @NeverInline
     public Object m(String arg) {
       return System.currentTimeMillis() >= 0 ? arg : null;
@@ -83,6 +86,7 @@
 
     // This bridge cannot be hoisted to A, since it targets a method on the enclosing class.
     // Hoisting the bridge to A would lead to a NoSuchMethodError.
+    @KeepConstantArguments
     @NeverInline
     public /*bridge*/ String bridge(Object o) {
       return (String) m((String) o);
diff --git a/src/test/java/com/android/tools/r8/bridgeremoval/hoisting/PositiveBridgeHoistingTest.java b/src/test/java/com/android/tools/r8/bridgeremoval/hoisting/PositiveBridgeHoistingTest.java
index dbdb906..ae77a45 100644
--- a/src/test/java/com/android/tools/r8/bridgeremoval/hoisting/PositiveBridgeHoistingTest.java
+++ b/src/test/java/com/android/tools/r8/bridgeremoval/hoisting/PositiveBridgeHoistingTest.java
@@ -7,6 +7,7 @@
 import static org.hamcrest.CoreMatchers.not;
 import static org.hamcrest.MatcherAssert.assertThat;
 
+import com.android.tools.r8.KeepConstantArguments;
 import com.android.tools.r8.NeverClassInline;
 import com.android.tools.r8.NeverInline;
 import com.android.tools.r8.NoHorizontalClassMerging;
@@ -51,6 +52,7 @@
                 .setBridge(B5.class.getDeclaredMethod("virtualBridge", Object.class))
                 .transform())
         .addKeepMainRule(TestClass.class)
+        .enableConstantArgumentAnnotations()
         .enableInliningAnnotations()
         .enableNeverClassInliningAnnotations()
         .enableNoHorizontalClassMergingAnnotations()
@@ -106,6 +108,7 @@
 
   static class A {
 
+    @KeepConstantArguments
     @NeverInline
     public Object m(String arg) {
       return System.currentTimeMillis() >= 0 ? arg : null;
@@ -122,12 +125,14 @@
 
     // This bridge can be hoisted to A if the invoke-super instruction is rewritten to an
     // invoke-virtual instruction.
+    @KeepConstantArguments
     @NeverInline
     public /*bridge*/ String superBridge(Object o) {
       return (String) super.m((String) o);
     }
 
     // This bridge can be hoisted to A.
+    @KeepConstantArguments
     @NeverInline
     public /*bridge*/ String virtualBridge(Object o) {
       return (String) m((String) o);
@@ -139,12 +144,14 @@
   static class B2 extends A {
 
     // By hoisting B1.superBridge() to A this method bridge redundant.
+    @KeepConstantArguments
     @NeverInline
     public /*bridge*/ String superBridge(Object o) {
       return (String) super.m((String) o);
     }
 
     // By hoisting B1.virtualBridge() to A this method bridge redundant.
+    @KeepConstantArguments
     @NeverInline
     public /*bridge*/ String virtualBridge(Object o) {
       return (String) m((String) o);
@@ -171,11 +178,13 @@
   @NoHorizontalClassMerging
   static class B4 extends A {
 
+    @KeepConstantArguments
     @NeverInline
     public String superBridge(Object o) {
       return System.currentTimeMillis() >= 0 ? ((String) o) : null;
     }
 
+    @KeepConstantArguments
     @NeverInline
     public String virtualBridge(Object o) {
       return System.currentTimeMillis() >= 0 ? ((String) o) : null;
@@ -188,11 +197,13 @@
   @NoHorizontalClassMerging
   static class B5 extends A {
 
+    @KeepConstantArguments
     @NeverInline
     public /*bridge*/ String superBridge(Object o) {
       return (String) super.m2((String) o);
     }
 
+    @KeepConstantArguments
     @NeverInline
     public /*bridge*/ String virtualBridge(Object o) {
       return (String) m2((String) o);
diff --git a/src/test/java/com/android/tools/r8/bridgeremoval/hoisting/testclasses/BridgeHoistingAccessibilityTestClasses.java b/src/test/java/com/android/tools/r8/bridgeremoval/hoisting/testclasses/BridgeHoistingAccessibilityTestClasses.java
index e7d430f..64c19e5 100644
--- a/src/test/java/com/android/tools/r8/bridgeremoval/hoisting/testclasses/BridgeHoistingAccessibilityTestClasses.java
+++ b/src/test/java/com/android/tools/r8/bridgeremoval/hoisting/testclasses/BridgeHoistingAccessibilityTestClasses.java
@@ -4,6 +4,7 @@
 
 package com.android.tools.r8.bridgeremoval.hoisting.testclasses;
 
+import com.android.tools.r8.KeepConstantArguments;
 import com.android.tools.r8.NeverInline;
 import com.android.tools.r8.NoHorizontalClassMerging;
 import com.android.tools.r8.NoVerticalClassMerging;
@@ -33,6 +34,7 @@
   @NoVerticalClassMerging
   public static class AWithRangedInvoke {
 
+    @KeepConstantArguments
     @NeverInline
     public Object m(String arg, int a, int b, int c, int d, int e) {
       return System.currentTimeMillis() > 0 ? arg + a + b + c + d + e : null;
diff --git a/src/test/java/com/android/tools/r8/classmerging/StatefulSingletonClassesMergingTest.java b/src/test/java/com/android/tools/r8/classmerging/StatefulSingletonClassesMergingTest.java
index fadf934..3f887af 100644
--- a/src/test/java/com/android/tools/r8/classmerging/StatefulSingletonClassesMergingTest.java
+++ b/src/test/java/com/android/tools/r8/classmerging/StatefulSingletonClassesMergingTest.java
@@ -4,6 +4,7 @@
 
 package com.android.tools.r8.classmerging;
 
+import com.android.tools.r8.KeepConstantArguments;
 import com.android.tools.r8.NeverClassInline;
 import com.android.tools.r8.NeverInline;
 import com.android.tools.r8.NeverPropagateValue;
@@ -35,6 +36,7 @@
         .addKeepMainRule(Main.class)
         .addHorizontallyMergedClassesInspector(
             inspector -> inspector.assertIsCompleteMergeGroup(A.class, B.class))
+        .enableConstantArgumentAnnotations()
         .enableInliningAnnotations()
         .enableMemberValuePropagationAnnotations()
         .enableNeverClassInliningAnnotations()
@@ -58,6 +60,9 @@
 
     @NeverPropagateValue private final String data;
 
+    // TODO(b/198758663): With argument propagation the constructors end up not being equivalent,
+    //  which prevents merging in the final round of horizontal class merging.
+    @KeepConstantArguments
     A(String data) {
       this.data = data;
     }
@@ -75,6 +80,9 @@
 
     @NeverPropagateValue private final String data;
 
+    // TODO(b/198758663): With argument propagation the constructors end up not being equivalent,
+    //  which prevents merging in the final round of horizontal class merging.
+    @KeepConstantArguments
     B(String data) {
       this.data = data;
     }
diff --git a/src/test/java/com/android/tools/r8/classmerging/horizontal/NoClassesOrMembersWithAnnotationsTest.java b/src/test/java/com/android/tools/r8/classmerging/horizontal/NoClassesOrMembersWithAnnotationsTest.java
index 3858a1e..667c261 100644
--- a/src/test/java/com/android/tools/r8/classmerging/horizontal/NoClassesOrMembersWithAnnotationsTest.java
+++ b/src/test/java/com/android/tools/r8/classmerging/horizontal/NoClassesOrMembersWithAnnotationsTest.java
@@ -9,6 +9,7 @@
 import static com.android.tools.r8.utils.codeinspector.Matchers.onlyIf;
 import static org.hamcrest.MatcherAssert.assertThat;
 
+import com.android.tools.r8.KeepConstantArguments;
 import com.android.tools.r8.NeverClassInline;
 import com.android.tools.r8.NeverInline;
 import com.android.tools.r8.TestParameters;
@@ -52,18 +53,13 @@
               } else {
                 inspector.assertIsCompleteMergeGroup(A.class, B.class, C.class);
               }
+              inspector.assertNoOtherClassesMerged();
             })
+        .enableConstantArgumentAnnotations()
         .enableNeverClassInliningAnnotations()
         .enableInliningAnnotations()
         .setMinApi(parameters.getApiLevel())
-        .run(parameters.getRuntime(), Main.class)
-        .applyIf(
-            enableProguardCompatibilityMode,
-            result ->
-                result.assertSuccessWithOutputLines(
-                    "a", "b", "c", "foo", "null", "annotation 2", "annotation 1", "annotation 2"),
-            result ->
-                result.assertSuccessWithOutputLines("a", "b", "c", "foo", "null", "annotation 2"))
+        .compile()
         .inspect(
             codeInspector -> {
               assertThat(codeInspector.clazz(TypeAnnotation.class), isPresent());
@@ -73,7 +69,15 @@
                   codeInspector.clazz(B.class),
                   onlyIf(enableProguardCompatibilityMode, isPresent()));
               assertThat(codeInspector.clazz(C.class), isAbsent());
-            });
+            })
+        .run(parameters.getRuntime(), Main.class)
+        .applyIf(
+            enableProguardCompatibilityMode,
+            result ->
+                result.assertSuccessWithOutputLines(
+                    "a", "b", "c", "foo", "null", "annotation 2", "annotation 1", "annotation 2"),
+            result ->
+                result.assertSuccessWithOutputLines("a", "b", "c", "foo", "null", "annotation 2"));
   }
 
   @Retention(RetentionPolicy.RUNTIME)
@@ -114,6 +118,7 @@
   }
 
   static class Main {
+    @KeepConstantArguments
     @NeverInline
     public static void foo(TypeAnnotation annotation) {
       System.out.println(annotation);
@@ -124,7 +129,7 @@
       System.out.println(annotation.toString().replaceFirst(".*@.*", "annotation 2"));
     }
 
-    public static void main(String[] args) throws NoSuchMethodException {
+    public static void main(String[] args) {
       A a = new A();
       B b = new B("b");
       C c = new C("c");
diff --git a/src/test/java/com/android/tools/r8/compatproguard/reflection/ReflectionTest.java b/src/test/java/com/android/tools/r8/compatproguard/reflection/ReflectionTest.java
index aab82f0..352186b 100644
--- a/src/test/java/com/android/tools/r8/compatproguard/reflection/ReflectionTest.java
+++ b/src/test/java/com/android/tools/r8/compatproguard/reflection/ReflectionTest.java
@@ -8,6 +8,7 @@
 import static org.hamcrest.MatcherAssert.assertThat;
 import static org.junit.Assert.assertEquals;
 
+import com.android.tools.r8.KeepConstantArguments;
 import com.android.tools.r8.NeverInline;
 import com.android.tools.r8.R8Command;
 import com.android.tools.r8.TestBase;
@@ -156,6 +157,7 @@
     nonConstArraySize(0);
   }
 
+  @KeepConstantArguments
   @NeverInline
   static void nonConstArraySize(int argumentTypesSize) {
     try {
@@ -485,28 +487,23 @@
 
   @Test
   public void testNonConstArraySize() throws Exception {
-    Class<?> mainClass = MainNonConstArraySize.class;
-    R8Command.Builder builder =
-        ToolHelper.prepareR8CommandBuilder(
-                readClasses(A.class, mainClass, NeverInline.class), emptyConsumer(backend))
-            .addLibraryFiles(runtimeJar(backend));
-    builder.addProguardConfiguration(
-        ImmutableList.of(keepMainProguardConfigurationWithInliningAnnotation(mainClass)),
-        Origin.unknown());
-    ToolHelper.allowTestProguardOptions(builder);
-    AndroidApp output = ToolHelper.runR8(builder.build());
-    CodeInspector inspector = new CodeInspector(output);
-
-    assertThat(
-        inspector.clazz(A.class).method("void", "method0", ImmutableList.of()),
-        isPresentAndRenamed());
-
-    // The reference run on the Java VM will succeed, whereas the run on the R8 output will fail
-    // as in this test we fail to recognize the reflective call. To compare the output of the
-    // successful reference run append "java.lang.NoSuchMethodException" to it.
-    assertEquals(
-        runOnJava(mainClass) + "java.lang.NoSuchMethodException",
-        runOnVM(output, mainClass, backend));
+    testForR8(backend)
+        .addProgramClasses(MainNonConstArraySize.class, A.class)
+        .addKeepMainRule(MainNonConstArraySize.class)
+        .enableConstantArgumentAnnotations()
+        .enableInliningAnnotations()
+        .run(MainNonConstArraySize.class)
+        .inspect(
+            inspector -> {
+              assertThat(
+                  inspector.clazz(A.class).method("void", "method0", ImmutableList.of()),
+                  isPresentAndRenamed());
+            })
+        // The reference run on the Java VM will succeed, whereas the run on the R8 output will fail
+        // as in this test we fail to recognize the reflective call. To compare the output of the
+        // successful reference run append "java.lang.NoSuchMethodException" to it.
+        .assertSuccessWithOutput(
+            runOnJava(MainNonConstArraySize.class) + "java.lang.NoSuchMethodException");
   }
 
   @Test
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/JavaUtilFunctionTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/JavaUtilFunctionTest.java
index 0ac3687..2e0481d 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/JavaUtilFunctionTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/JavaUtilFunctionTest.java
@@ -8,6 +8,7 @@
 import static org.hamcrest.MatcherAssert.assertThat;
 import static org.junit.Assert.assertEquals;
 
+import com.android.tools.r8.KeepConstantArguments;
 import com.android.tools.r8.NeverInline;
 import com.android.tools.r8.TestParameters;
 import com.android.tools.r8.ToolHelper;
@@ -89,6 +90,7 @@
         .addKeepMainRule(TestClass.class)
         .addInnerClasses(JavaUtilFunctionTest.class)
         .setMinApi(parameters.getApiLevel())
+        .enableConstantArgumentAnnotations()
         .enableCoreLibraryDesugaring(parameters.getApiLevel(), keepRuleConsumer)
         .compile()
         .inspect(this::checkRewrittenArguments)
@@ -103,6 +105,7 @@
 
   static class TestClass {
 
+    @KeepConstantArguments
     @NeverInline
     private static String applyFunction(Function<String, String> f) {
       return f.apply("Hello, world");
diff --git a/src/test/java/com/android/tools/r8/enumunboxing/VirtualMethodOverrideEnumUnboxingTest.java b/src/test/java/com/android/tools/r8/enumunboxing/VirtualMethodOverrideEnumUnboxingTest.java
index 4c69310..093f902 100644
--- a/src/test/java/com/android/tools/r8/enumunboxing/VirtualMethodOverrideEnumUnboxingTest.java
+++ b/src/test/java/com/android/tools/r8/enumunboxing/VirtualMethodOverrideEnumUnboxingTest.java
@@ -8,6 +8,7 @@
 import static org.hamcrest.MatcherAssert.assertThat;
 import static org.junit.Assert.assertFalse;
 
+import com.android.tools.r8.KeepConstantArguments;
 import com.android.tools.r8.NeverClassInline;
 import com.android.tools.r8.NeverInline;
 import com.android.tools.r8.NoVerticalClassMerging;
@@ -45,6 +46,7 @@
         .addInnerClasses(getClass())
         .addKeepMainRule(TestClass.class)
         .addKeepRules(enumKeepRules.getKeepRules())
+        .enableConstantArgumentAnnotations()
         .enableInliningAnnotations()
         .enableNeverClassInliningAnnotations()
         .enableNoVerticalClassMergingAnnotations()
@@ -89,11 +91,13 @@
   @NeverClassInline
   static class B extends A {
 
+    @KeepConstantArguments
     @NeverInline
     void m(int x, MyEnum y) {
       System.out.println("B.m(" + x + " : int, " + y.toString() + " : MyEnum)");
     }
 
+    @KeepConstantArguments
     @NeverInline
     @Override
     void m(MyEnum x, int y) {
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/callsites/WithStaticizerTest.java b/src/test/java/com/android/tools/r8/ir/optimize/callsites/WithStaticizerTest.java
index 3c7307c..f392b1d 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/callsites/WithStaticizerTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/callsites/WithStaticizerTest.java
@@ -4,9 +4,9 @@
 package com.android.tools.r8.ir.optimize.callsites;
 
 import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
+import static junit.framework.TestCase.assertTrue;
 import static org.hamcrest.CoreMatchers.not;
 import static org.hamcrest.MatcherAssert.assertThat;
-import static org.junit.Assert.assertTrue;
 
 import com.android.tools.r8.NeverClassInline;
 import com.android.tools.r8.NeverInline;
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/classinliner/ClassInlinerTest.java b/src/test/java/com/android/tools/r8/ir/optimize/classinliner/ClassInlinerTest.java
index 9cb52da..cb494cb 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/classinliner/ClassInlinerTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/classinliner/ClassInlinerTest.java
@@ -240,7 +240,7 @@
     SingleTestRunResult<?> result =
         testForR8(parameters.getBackend())
             .addProgramClasses(classes)
-            .enableProguardTestOptions()
+            .enableConstantArgumentAnnotations()
             .enableInliningAnnotations()
             .enableNoHorizontalClassMergingAnnotations()
             .addKeepMainRule(main)
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/classinliner/invalidroot/InvalidRootsTestClass.java b/src/test/java/com/android/tools/r8/ir/optimize/classinliner/invalidroot/InvalidRootsTestClass.java
index 2b29cea..d9785fe 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/classinliner/invalidroot/InvalidRootsTestClass.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/classinliner/invalidroot/InvalidRootsTestClass.java
@@ -4,6 +4,7 @@
 
 package com.android.tools.r8.ir.optimize.classinliner.invalidroot;
 
+import com.android.tools.r8.KeepConstantArguments;
 import com.android.tools.r8.NeverInline;
 import com.android.tools.r8.NoHorizontalClassMerging;
 
@@ -72,6 +73,7 @@
     }
   }
 
+  @KeepConstantArguments
   private void neverReturnsNormallyExtra(String prefix, NeverReturnsNormally a) {
     throw new RuntimeException("neverReturnsNormallyExtra(" +
         prefix + ", " + (a == null ? "null" : a.foo()) + "): " + next());
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/inliner/conditionalsimpleinlining/NopInliningConstraintTest.java b/src/test/java/com/android/tools/r8/ir/optimize/inliner/conditionalsimpleinlining/NopInliningConstraintTest.java
index 3295203..dcc572b 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/inliner/conditionalsimpleinlining/NopInliningConstraintTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/inliner/conditionalsimpleinlining/NopInliningConstraintTest.java
@@ -40,6 +40,8 @@
         .addKeepMainRule(Main.class)
         .enableAlwaysInliningAnnotations()
         .enableInliningAnnotations()
+        // TODO(b/173398086): uniqueMethodWithName() does not work with argument removal.
+        .noMinification()
         .setMinApi(parameters.getApiLevel())
         .compile()
         .inspect(
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/inliner/conditionalsimpleinlining/SimpleIfNullOrNotNullInliningTest.java b/src/test/java/com/android/tools/r8/ir/optimize/inliner/conditionalsimpleinlining/SimpleIfNullOrNotNullInliningTest.java
index c5073c5..f75c4c8 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/inliner/conditionalsimpleinlining/SimpleIfNullOrNotNullInliningTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/inliner/conditionalsimpleinlining/SimpleIfNullOrNotNullInliningTest.java
@@ -10,6 +10,7 @@
 import static org.hamcrest.CoreMatchers.not;
 import static org.hamcrest.MatcherAssert.assertThat;
 
+import com.android.tools.r8.KeepConstantArguments;
 import com.android.tools.r8.NeverSingleCallerInline;
 import com.android.tools.r8.TestBase;
 import com.android.tools.r8.TestParameters;
@@ -51,6 +52,7 @@
         .addProgramClasses(mainClass, TestMethods.class)
         .addKeepMainRule(mainClass)
         .apply(this::configure)
+        .enableConstantArgumentAnnotations()
         .enableNeverSingleCallerInlineAnnotations()
         .compile()
         .inspect(this::inspect)
@@ -116,6 +118,7 @@
 
   static class TestMethods {
 
+    @KeepConstantArguments
     @NeverSingleCallerInline
     static void simpleIfNullTest(Object o) {
       if (o == null) {
@@ -135,6 +138,7 @@
       System.out.println("!");
     }
 
+    @KeepConstantArguments
     @NeverSingleCallerInline
     static void simpleIfBothNullTest(Object o1, Object o2) {
       if (o1 == null && o2 == null) {
@@ -154,6 +158,7 @@
       System.out.println("!");
     }
 
+    @KeepConstantArguments
     @NeverSingleCallerInline
     static void simpleIfNotNullTest(Object o) {
       if (o != null) {
@@ -173,6 +178,7 @@
       System.out.println("!");
     }
 
+    @KeepConstantArguments
     @NeverSingleCallerInline
     static void simpleIfBothNotNullTest(Object o1, Object o2) {
       if (o1 != null && o2 != null) {
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/inliner/conditionalsimpleinlining/SimpleIfTrueOrFalseInliningTest.java b/src/test/java/com/android/tools/r8/ir/optimize/inliner/conditionalsimpleinlining/SimpleIfTrueOrFalseInliningTest.java
index b7a7186..180b971 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/inliner/conditionalsimpleinlining/SimpleIfTrueOrFalseInliningTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/inliner/conditionalsimpleinlining/SimpleIfTrueOrFalseInliningTest.java
@@ -10,6 +10,7 @@
 import static org.hamcrest.CoreMatchers.not;
 import static org.hamcrest.MatcherAssert.assertThat;
 
+import com.android.tools.r8.KeepConstantArguments;
 import com.android.tools.r8.NeverSingleCallerInline;
 import com.android.tools.r8.TestBase;
 import com.android.tools.r8.TestParameters;
@@ -51,6 +52,7 @@
         .addProgramClasses(mainClass, TestMethods.class)
         .addKeepMainRule(mainClass)
         .apply(this::configure)
+        .enableConstantArgumentAnnotations()
         .enableNeverSingleCallerInlineAnnotations()
         .compile()
         .inspect(this::inspect)
@@ -114,6 +116,7 @@
 
   static class TestMethods {
 
+    @KeepConstantArguments
     @NeverSingleCallerInline
     static void simpleIfTrueTest(boolean b) {
       if (b) {
@@ -133,6 +136,7 @@
       System.out.println("!");
     }
 
+    @KeepConstantArguments
     @NeverSingleCallerInline
     static void simpleIfBothTrueTest(boolean b1, boolean b2) {
       if (b1 && b2) {
@@ -152,6 +156,7 @@
       System.out.println("!");
     }
 
+    @KeepConstantArguments
     @NeverSingleCallerInline
     static void simpleIfFalseTest(boolean b) {
       if (!b) {
@@ -171,6 +176,7 @@
       System.out.println("!");
     }
 
+    @KeepConstantArguments
     @NeverSingleCallerInline
     static void simpleIfBothFalseTest(boolean b1, boolean b2) {
       if (!b1 && !b2) {
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/instanceofremoval/InstanceOfRemovalTest.java b/src/test/java/com/android/tools/r8/ir/optimize/instanceofremoval/InstanceOfRemovalTest.java
index 791bbae..09aef4c 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/instanceofremoval/InstanceOfRemovalTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/instanceofremoval/InstanceOfRemovalTest.java
@@ -177,6 +177,6 @@
     MethodSubject barMethodSubject = testClass.uniqueMethodWithName("bar");
     Iterator<InstructionSubject> barInstructionIterator =
         barMethodSubject.iterateInstructions(InstructionSubject::isInstanceOf);
-    assertEquals(4, Streams.stream(barInstructionIterator).count());
+    assertEquals(2, Streams.stream(barInstructionIterator).count());
   }
 }
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/outliner/classtypes/B134462736.java b/src/test/java/com/android/tools/r8/ir/optimize/outliner/classtypes/B134462736.java
index 29de662..3a0b304 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/outliner/classtypes/B134462736.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/outliner/classtypes/B134462736.java
@@ -7,6 +7,7 @@
 import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
 import static org.hamcrest.MatcherAssert.assertThat;
 
+import com.android.tools.r8.KeepConstantArguments;
 import com.android.tools.r8.NeverInline;
 import com.android.tools.r8.TestBase;
 import com.android.tools.r8.TestParameters;
@@ -64,6 +65,7 @@
         .enableInliningAnnotations()
         .addInnerClasses(B134462736.class)
         .addKeepMainRule(TestClass.class)
+        .enableConstantArgumentAnnotations()
         .setMinApi(parameters.getApiLevel())
         .noMinification()
         .addOptionsModification(
@@ -78,11 +80,14 @@
   }
 
   public static class TestClass {
+
+    @KeepConstantArguments
     @NeverInline
     public void consumer(String arg1, String arg2) {
       System.out.println(arg1 + " " + arg2);
     }
 
+    @KeepConstantArguments
     @NeverInline
     public void method1(StringBuilder builder, String arg1, String arg2) {
       builder.append(arg1);
@@ -90,6 +95,7 @@
       consumer(builder.toString(), null);
     }
 
+    @KeepConstantArguments
     @NeverInline
     public void method2(StringBuilder builder, String arg1, String arg2) {
       builder.append(arg1);
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/outliner/primitivetypes/PrimitiveTypesTest.java b/src/test/java/com/android/tools/r8/ir/optimize/outliner/primitivetypes/PrimitiveTypesTest.java
index e384d9b..8cc3b8c 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/outliner/primitivetypes/PrimitiveTypesTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/outliner/primitivetypes/PrimitiveTypesTest.java
@@ -5,20 +5,23 @@
 package com.android.tools.r8.ir.optimize.outliner.primitivetypes;
 
 import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
+import static junit.framework.TestCase.assertEquals;
 import static org.hamcrest.MatcherAssert.assertThat;
 
+import com.android.tools.r8.KeepConstantArguments;
 import com.android.tools.r8.NeverClassInline;
 import com.android.tools.r8.NeverInline;
 import com.android.tools.r8.TestBase;
 import com.android.tools.r8.TestParameters;
-import com.android.tools.r8.TestParametersCollection;
 import com.android.tools.r8.synthesis.SyntheticItemsTestUtils;
+import com.android.tools.r8.utils.BooleanUtils;
 import com.android.tools.r8.utils.StringUtils;
 import com.android.tools.r8.utils.codeinspector.ClassSubject;
 import com.android.tools.r8.utils.codeinspector.CodeInspector;
 import com.android.tools.r8.utils.codeinspector.CodeMatchers;
 import com.android.tools.r8.utils.codeinspector.MethodSubject;
 import com.google.common.collect.ImmutableList;
+import java.util.List;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.Parameterized;
@@ -26,18 +29,30 @@
 @RunWith(Parameterized.class)
 public class PrimitiveTypesTest extends TestBase {
 
+  private final boolean enableArgumentPropagation;
   private final TestParameters parameters;
 
-  @Parameterized.Parameters(name = "{0}")
-  public static TestParametersCollection data() {
-    return getTestParameters().withAllRuntimesAndApiLevels().build();
+  @Parameterized.Parameters(name = "{1}, argument propagation: {0}")
+  public static List<Object[]> data() {
+    return buildParameters(
+        BooleanUtils.values(), getTestParameters().withAllRuntimesAndApiLevels().build());
   }
 
-  public PrimitiveTypesTest(TestParameters parameters) {
+  public PrimitiveTypesTest(boolean keepConstantArguments, TestParameters parameters) {
+    this.enableArgumentPropagation = keepConstantArguments;
     this.parameters = parameters;
   }
 
   private void validateOutlining(CodeInspector inspector, Class<?> testClass, String argumentType) {
+    boolean isStringBuilderOptimized =
+        enableArgumentPropagation
+            && parameters.isDexRuntime()
+            && (argumentType.equals("char") || argumentType.equals("boolean"));
+    if (isStringBuilderOptimized) {
+      assertEquals(1, inspector.allClasses().size());
+      return;
+    }
+
     ClassSubject outlineClass =
         inspector.clazz(SyntheticItemsTestUtils.syntheticOutlineClass(testClass, 0));
     MethodSubject outline0Method =
@@ -56,6 +71,8 @@
   public void runTest(Class<?> testClass, String argumentType, String expectedOutput)
       throws Exception {
     testForR8(parameters.getBackend())
+        .addConstantArgumentAnnotations()
+        .enableConstantArgumentAnnotations(!enableArgumentPropagation)
         .enableInliningAnnotations()
         .enableNeverClassInliningAnnotations()
         .addProgramClasses(testClass)
@@ -120,6 +137,7 @@
 
   static class TestClassBoolean {
 
+    @KeepConstantArguments
     @NeverInline
     public static String method1(boolean b) {
       StringBuilder sb = new StringBuilder();
@@ -128,6 +146,7 @@
       return sb.toString();
     }
 
+    @KeepConstantArguments
     @NeverInline
     public static String method2(boolean b) {
       StringBuilder sb = new StringBuilder();
@@ -144,6 +163,7 @@
 
   static class TestClassByte {
 
+    @KeepConstantArguments
     @NeverInline
     public static String method1(byte b) {
       MyStringBuilder sb = new MyStringBuilder();
@@ -152,6 +172,7 @@
       return sb.toString();
     }
 
+    @KeepConstantArguments
     @NeverInline
     public static String method2(byte b) {
       MyStringBuilder sb = new MyStringBuilder();
@@ -168,6 +189,7 @@
 
   static class TestClassShort {
 
+    @KeepConstantArguments
     @NeverInline
     public static String method1(short s) {
       MyStringBuilder sb = new MyStringBuilder();
@@ -176,6 +198,7 @@
       return sb.toString();
     }
 
+    @KeepConstantArguments
     @NeverInline
     public static String method2(short s) {
       MyStringBuilder sb = new MyStringBuilder();
@@ -192,6 +215,7 @@
 
   static class TestClassChar {
 
+    @KeepConstantArguments
     @NeverInline
     public static String method1(char c) {
       StringBuilder sb = new StringBuilder();
@@ -200,6 +224,7 @@
       return sb.toString();
     }
 
+    @KeepConstantArguments
     @NeverInline
     public static String method2(char c) {
       StringBuilder sb = new StringBuilder();
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/staticizer/ClassStaticizerTest.java b/src/test/java/com/android/tools/r8/ir/optimize/staticizer/ClassStaticizerTest.java
index 5a60806..a1b6f08 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/staticizer/ClassStaticizerTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/staticizer/ClassStaticizerTest.java
@@ -410,6 +410,7 @@
     R8TestRunResult result =
         testForR8(parameters.getBackend())
             .addProgramClasses(classes)
+            .enableConstantArgumentAnnotations()
             .enableInliningAnnotations()
             .addKeepMainRule(main)
             .allowAccessModification()
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/staticizer/dualcallinline/Candidate.java b/src/test/java/com/android/tools/r8/ir/optimize/staticizer/dualcallinline/Candidate.java
index 9ccd630..4733ab3 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/staticizer/dualcallinline/Candidate.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/staticizer/dualcallinline/Candidate.java
@@ -4,6 +4,7 @@
 
 package com.android.tools.r8.ir.optimize.staticizer.dualcallinline;
 
+import com.android.tools.r8.KeepConstantArguments;
 import com.android.tools.r8.NeverInline;
 
 public class Candidate {
@@ -12,6 +13,7 @@
     return bar("Candidate::foo()");
   }
 
+  @KeepConstantArguments
   @NeverInline
   public String bar(String other) {
     return "Candidate::bar(" + other + ")";
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/string/StringIsEmptyTest.java b/src/test/java/com/android/tools/r8/ir/optimize/string/StringIsEmptyTest.java
index 5c9c9a3..6c47b03 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/string/StringIsEmptyTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/string/StringIsEmptyTest.java
@@ -58,7 +58,6 @@
     // This test wants to check if compile-time computation is not applied to non-null,
     // non-constant value. In a simple test setting, call-site optimization knows the argument is
     // always a non-null, specific constant, but that is beyond the scope of this test.
-    assert !options.callSiteOptimizationOptions().isConstantPropagationEnabled();
   }
 
   private void test(SingleTestRunResult result, int expectedStringIsEmptyCount) throws Exception {
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/uninstantiatedtypes/ParameterRewritingTest.java b/src/test/java/com/android/tools/r8/ir/optimize/uninstantiatedtypes/ParameterRewritingTest.java
index 0125189..ee595ce 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/uninstantiatedtypes/ParameterRewritingTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/uninstantiatedtypes/ParameterRewritingTest.java
@@ -11,7 +11,8 @@
 import com.android.tools.r8.NeverInline;
 import com.android.tools.r8.NoHorizontalClassMerging;
 import com.android.tools.r8.TestBase;
-import com.android.tools.r8.ToolHelper;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
 import com.android.tools.r8.graph.DexMethod;
 import com.android.tools.r8.utils.StringUtils;
 import com.android.tools.r8.utils.codeinspector.ClassSubject;
@@ -25,15 +26,15 @@
 @RunWith(Parameterized.class)
 public class ParameterRewritingTest extends TestBase {
 
-  private final Backend backend;
+  private final TestParameters parameters;
 
-  @Parameters(name = "Backend: {0}")
-  public static Backend[] data() {
-    return ToolHelper.getBackends();
+  @Parameters(name = "{0}")
+  public static TestParametersCollection data() {
+    return getTestParameters().withAllRuntimesAndApiLevels().build();
   }
 
-  public ParameterRewritingTest(Backend backend) {
-    this.backend = backend;
+  public ParameterRewritingTest(TestParameters parameters) {
+    this.parameters = parameters;
   }
 
   @Test
@@ -49,14 +50,15 @@
     testForJvm().addTestClasspath().run(TestClass.class).assertSuccessWithOutput(expected);
 
     CodeInspector inspector =
-        testForR8(backend)
+        testForR8(parameters.getBackend())
             .addInnerClasses(ParameterRewritingTest.class)
             .addKeepMainRule(TestClass.class)
             .enableInliningAnnotations()
             .enableNoHorizontalClassMergingAnnotations()
             .addOptionsModification(options -> options.enableClassInlining = false)
             .noMinification()
-            .run(TestClass.class)
+            .setMinApi(parameters.getApiLevel())
+            .run(parameters.getRuntime(), TestClass.class)
             .assertSuccessWithOutput(expected)
             .inspector();
 
@@ -64,7 +66,7 @@
     MethodSubject createStaticMethodSubject =
         factoryClassSubject.uniqueMethodWithName("createStatic");
     assertThat(createStaticMethodSubject, isPresent());
-    assertEquals(1, createStaticMethodSubject.getMethod().getReference().proto.parameters.size());
+    assertEquals(1, createStaticMethodSubject.getMethod().getParameters().size());
 
     for (int i = 1; i <= 3; ++i) {
       String createStaticWithUnusedMethodName = "createStaticWithUnused" + i;
@@ -73,8 +75,8 @@
       assertThat(createStaticWithUnusedMethodSubject, isPresent());
 
       DexMethod method = createStaticWithUnusedMethodSubject.getMethod().getReference();
-      assertEquals(1, method.proto.parameters.size());
-      assertEquals("java.lang.String", method.proto.parameters.toString());
+      assertEquals(1, method.getParameters().size());
+      assertEquals("java.lang.String", method.getParameters().toString());
     }
 
     MethodSubject createStaticWithUnusedMethodSubject =
@@ -82,9 +84,9 @@
     assertThat(createStaticWithUnusedMethodSubject, isPresent());
 
     DexMethod method = createStaticWithUnusedMethodSubject.getMethod().getReference();
-    assertEquals(3, method.proto.parameters.size());
+    assertEquals(3, method.getParameters().size());
     assertEquals(
-        "java.lang.String java.lang.String java.lang.String", method.proto.parameters.toString());
+        "java.lang.String java.lang.String java.lang.String", method.getParameters().toString());
 
     assertThat(inspector.clazz(Uninstantiated.class), not(isPresent()));
   }
@@ -92,26 +94,39 @@
   static class TestClass {
 
     public static void main(String[] args) {
-      Object obj1 = Factory.createStatic(null, "Factory.createStatic()");
+      Object obj1 = Factory.createStatic(null, asNonConstantString("Factory.createStatic()"));
       System.out.println(" -> " + obj1);
 
       Object obj2 =
-          Factory.createStaticWithUnused1(new Object(), null, "Factory.createStaticWithUnused1()");
+          Factory.createStaticWithUnused1(
+              new Object(), null, asNonConstantString("Factory.createStaticWithUnused1()"));
       System.out.println(" -> " + obj2);
 
       Object obj3 =
-          Factory.createStaticWithUnused2(null, new Object(), "Factory.createStaticWithUnused2()");
+          Factory.createStaticWithUnused2(
+              null, new Object(), asNonConstantString("Factory.createStaticWithUnused2()"));
       System.out.println(" -> " + obj3);
 
       Object obj4 =
-          Factory.createStaticWithUnused3(null, "Factory.createStaticWithUnused3()", new Object());
+          Factory.createStaticWithUnused3(
+              null, asNonConstantString("Factory.createStaticWithUnused3()"), new Object());
       System.out.println(" -> " + obj4);
 
       Object obj5 =
           Factory.createStaticWithUnused4(
-              "Factory", new Object(), null, ".", new Object(), null, "createStaticWithUnused4()");
+              asNonConstantString("Factory"),
+              new Object(),
+              null,
+              asNonConstantString("."),
+              new Object(),
+              null,
+              asNonConstantString("createStaticWithUnused4()"));
       System.out.println(" -> " + obj5);
     }
+
+    public static String asNonConstantString(String string) {
+      return System.currentTimeMillis() > 0 ? string : null;
+    }
   }
 
   @NoHorizontalClassMerging
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/uninstantiatedtypes/UninstantiatedAnnotatedArgumentsTest.java b/src/test/java/com/android/tools/r8/ir/optimize/uninstantiatedtypes/UninstantiatedAnnotatedArgumentsTest.java
index 339bbbc..663bcf6 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/uninstantiatedtypes/UninstantiatedAnnotatedArgumentsTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/uninstantiatedtypes/UninstantiatedAnnotatedArgumentsTest.java
@@ -158,12 +158,14 @@
   static class TestClass {
 
     public static void main(String[] args) {
-      testRemoveStaticFromStart(null, "Hello", " world!");
-      testRemoveStaticFromMiddle("Hello", null, " world!");
-      testRemoveStaticFromEnd("Hello", " world!", null);
-      new TestClass().testRemoveVirtualFromStart(null, "Hello", " world!");
-      new TestClass().testRemoveVirtualFromMiddle("Hello", null, " world!");
-      new TestClass().testRemoveVirtualFromEnd("Hello", " world!", null);
+      String hello = System.currentTimeMillis() > 0 ? "Hello" : null;
+      String world = System.currentTimeMillis() > 0 ? " world!" : null;
+      testRemoveStaticFromStart(null, hello, world);
+      testRemoveStaticFromMiddle(hello, null, world);
+      testRemoveStaticFromEnd(hello, world, null);
+      new TestClass().testRemoveVirtualFromStart(null, hello, world);
+      new TestClass().testRemoveVirtualFromMiddle(hello, null, world);
+      new TestClass().testRemoveVirtualFromEnd(hello, world, null);
     }
 
     @KeepConstantArguments
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/unusedarguments/PrivateInstanceMethodCollisionTest.java b/src/test/java/com/android/tools/r8/ir/optimize/unusedarguments/PrivateInstanceMethodCollisionTest.java
index b7ddd9e..ed2d01d 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/unusedarguments/PrivateInstanceMethodCollisionTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/unusedarguments/PrivateInstanceMethodCollisionTest.java
@@ -8,6 +8,7 @@
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotEquals;
 
+import com.android.tools.r8.KeepConstantArguments;
 import com.android.tools.r8.NeverClassInline;
 import com.android.tools.r8.NeverInline;
 import com.android.tools.r8.TestBase;
@@ -60,6 +61,7 @@
     testForR8(parameters.getBackend())
         .addInnerClasses(PrivateInstanceMethodCollisionTest.class)
         .addKeepMainRule(TestClass.class)
+        .enableConstantArgumentAnnotations()
         .enableInliningAnnotations()
         .enableNeverClassInliningAnnotations()
         .minification(minification)
@@ -109,11 +111,13 @@
 
   @NeverClassInline
   static class A {
+    @KeepConstantArguments
     @NeverInline
     private void foo(String used) {
       System.out.println("A#foo(" + used + ")");
     }
 
+    @KeepConstantArguments
     @NeverInline
     void foo(String used, Object unused) {
       System.out.println("A#foo(" + used + ", Object)");
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/unusedarguments/UnusedAnnotatedArgumentsTest.java b/src/test/java/com/android/tools/r8/ir/optimize/unusedarguments/UnusedAnnotatedArgumentsTest.java
index 7cf6193..2f3e14f 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/unusedarguments/UnusedAnnotatedArgumentsTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/unusedarguments/UnusedAnnotatedArgumentsTest.java
@@ -8,6 +8,7 @@
 import static org.hamcrest.MatcherAssert.assertThat;
 import static org.junit.Assert.assertEquals;
 
+import com.android.tools.r8.KeepConstantArguments;
 import com.android.tools.r8.KeepUnusedArguments;
 import com.android.tools.r8.NeverClassInline;
 import com.android.tools.r8.NeverInline;
@@ -66,6 +67,7 @@
         .addKeepAttributes("RuntimeVisibleParameterAnnotations")
         .enableNeverClassInliningAnnotations()
         .enableInliningAnnotations()
+        .enableConstantArgumentAnnotations()
         .enableUnusedArgumentAnnotations(keepUnusedArguments)
         // TODO(b/123060011): Mapping not working in presence of unused argument removal.
         .minification(keepUnusedArguments)
@@ -152,6 +154,7 @@
       new TestClass().testRemoveVirtualFromEnd("Hello", " world!", null);
     }
 
+    @KeepConstantArguments
     @KeepUnusedArguments
     @NeverInline
     static void testRemoveStaticFromStart(
@@ -159,6 +162,7 @@
       System.out.println(used + otherUsed);
     }
 
+    @KeepConstantArguments
     @KeepUnusedArguments
     @NeverInline
     static void testRemoveStaticFromMiddle(
@@ -166,6 +170,7 @@
       System.out.println(used + otherUsed);
     }
 
+    @KeepConstantArguments
     @KeepUnusedArguments
     @NeverInline
     static void testRemoveStaticFromEnd(
@@ -173,6 +178,7 @@
       System.out.println(used + otherUsed);
     }
 
+    @KeepConstantArguments
     @KeepUnusedArguments
     @NeverInline
     void testRemoveVirtualFromStart(
@@ -180,6 +186,7 @@
       System.out.println(used + otherUsed);
     }
 
+    @KeepConstantArguments
     @KeepUnusedArguments
     @NeverInline
     void testRemoveVirtualFromMiddle(
@@ -187,6 +194,7 @@
       System.out.println(used + otherUsed);
     }
 
+    @KeepConstantArguments
     @KeepUnusedArguments
     @NeverInline
     void testRemoveVirtualFromEnd(
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/unusedarguments/UnusedArgumentsCollisionMappingTest.java b/src/test/java/com/android/tools/r8/ir/optimize/unusedarguments/UnusedArgumentsCollisionMappingTest.java
index d8a7d6b..7d9a941 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/unusedarguments/UnusedArgumentsCollisionMappingTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/unusedarguments/UnusedArgumentsCollisionMappingTest.java
@@ -10,6 +10,7 @@
 import static org.junit.Assert.assertTrue;
 
 import com.android.tools.r8.CompilationMode;
+import com.android.tools.r8.KeepConstantArguments;
 import com.android.tools.r8.NeverInline;
 import com.android.tools.r8.R8TestRunResult;
 import com.android.tools.r8.TestBase;
@@ -50,6 +51,7 @@
             .addProgramClasses(Main.class)
             .setMinApi(parameters.getApiLevel())
             .addKeepMainRule(Main.class)
+            .enableConstantArgumentAnnotations()
             .enableInliningAnnotations()
             .addKeepAttributeLineNumberTable()
             .run(parameters.getRuntime(), Main.class)
@@ -92,6 +94,7 @@
       System.out.println("test with unused");
     }
 
+    @KeepConstantArguments
     @NeverInline
     public static void test(String used, String unused) {
       System.out.println("test with used: " + used);
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/unusedarguments/UnusedArgumentsDoubleTest.java b/src/test/java/com/android/tools/r8/ir/optimize/unusedarguments/UnusedArgumentsDoubleTest.java
index 95d571d..282371b 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/unusedarguments/UnusedArgumentsDoubleTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/unusedarguments/UnusedArgumentsDoubleTest.java
@@ -6,7 +6,9 @@
 
 import static org.junit.Assert.assertEquals;
 
+import com.android.tools.r8.KeepConstantArguments;
 import com.android.tools.r8.NeverInline;
+import com.android.tools.r8.R8FullTestBuilder;
 import com.android.tools.r8.utils.codeinspector.ClassSubject;
 import java.util.Collection;
 import org.junit.Assert;
@@ -27,16 +29,19 @@
   }
 
   static class TestClass {
+    @KeepConstantArguments
     @NeverInline
     public static double a(double a) {
       return a;
     }
 
+    @KeepConstantArguments
     @NeverInline
     public static double a(double a, double b) {
       return a;
     }
 
+    @KeepConstantArguments
     @NeverInline
     public static double a(double a, double b, double c) {
       return a;
@@ -50,6 +55,12 @@
   }
 
   @Override
+  public void configure(R8FullTestBuilder builder) {
+    super.configure(builder);
+    builder.enableConstantArgumentAnnotations();
+  }
+
+  @Override
   public Class<?> getTestClass() {
     return TestClass.class;
   }
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/unusedarguments/UnusedArgumentsIntTest.java b/src/test/java/com/android/tools/r8/ir/optimize/unusedarguments/UnusedArgumentsIntTest.java
index 06f665d..80309b2 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/unusedarguments/UnusedArgumentsIntTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/unusedarguments/UnusedArgumentsIntTest.java
@@ -6,7 +6,9 @@
 
 import static org.junit.Assert.assertEquals;
 
+import com.android.tools.r8.KeepConstantArguments;
 import com.android.tools.r8.NeverInline;
+import com.android.tools.r8.R8FullTestBuilder;
 import com.android.tools.r8.utils.codeinspector.ClassSubject;
 import com.google.common.collect.ImmutableSet;
 import java.util.Collection;
@@ -31,22 +33,26 @@
 
   static class TestClass {
 
+    @KeepConstantArguments
     @NeverInline
     public static int a(int a) {
       return a;
     }
 
+    @KeepConstantArguments
     @NeverInline
     public static int a(int a, int b) {
       return a;
     }
 
+    @KeepConstantArguments
     @NeverInline
     public static int iinc(int a, int b) {
       b++;
       return a;
     }
 
+    @KeepConstantArguments
     @NeverInline
     public static int a(int a, int b, int c) {
       return a;
@@ -61,6 +67,12 @@
   }
 
   @Override
+  public void configure(R8FullTestBuilder builder) {
+    super.configure(builder);
+    builder.enableConstantArgumentAnnotations();
+  }
+
+  @Override
   public Class<?> getTestClass() {
     return TestClass.class;
   }
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/unusedarguments/UnusedArgumentsLongTest.java b/src/test/java/com/android/tools/r8/ir/optimize/unusedarguments/UnusedArgumentsLongTest.java
index 6f44c8d..0dba75b 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/unusedarguments/UnusedArgumentsLongTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/unusedarguments/UnusedArgumentsLongTest.java
@@ -6,7 +6,9 @@
 
 import static org.junit.Assert.assertEquals;
 
+import com.android.tools.r8.KeepConstantArguments;
 import com.android.tools.r8.NeverInline;
+import com.android.tools.r8.R8FullTestBuilder;
 import com.android.tools.r8.utils.codeinspector.ClassSubject;
 import java.util.Collection;
 import org.junit.Assert;
@@ -27,16 +29,20 @@
   }
 
   static class TestClass {
+
+    @KeepConstantArguments
     @NeverInline
     public static long a(long a) {
       return a;
     }
 
+    @KeepConstantArguments
     @NeverInline
     public static long a(long a, long b) {
       return a;
     }
 
+    @KeepConstantArguments
     @NeverInline
     public static long a(long a, long b, long c) {
       return a;
@@ -50,6 +56,12 @@
   }
 
   @Override
+  public void configure(R8FullTestBuilder builder) {
+    super.configure(builder);
+    builder.enableConstantArgumentAnnotations();
+  }
+
+  @Override
   public Class<?> getTestClass() {
     return TestClass.class;
   }
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/unusedarguments/UnusedArgumentsMixedTest.java b/src/test/java/com/android/tools/r8/ir/optimize/unusedarguments/UnusedArgumentsMixedTest.java
index 717adac..dd63e78 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/unusedarguments/UnusedArgumentsMixedTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/unusedarguments/UnusedArgumentsMixedTest.java
@@ -6,7 +6,9 @@
 
 import static org.junit.Assert.assertEquals;
 
+import com.android.tools.r8.KeepConstantArguments;
 import com.android.tools.r8.NeverInline;
+import com.android.tools.r8.R8FullTestBuilder;
 import com.android.tools.r8.utils.codeinspector.ClassSubject;
 import java.util.Collection;
 import org.junit.Assert;
@@ -27,6 +29,8 @@
   }
 
   static class TestClass {
+
+    @KeepConstantArguments
     @NeverInline
     public static int a(int a, Object b) {
       return a;
@@ -37,6 +41,7 @@
       return a;
     }
 
+    @KeepConstantArguments
     @NeverInline
     public static int a(int a, Object b, int c) {
       return c;
@@ -56,6 +61,12 @@
   }
 
   @Override
+  public void configure(R8FullTestBuilder builder) {
+    super.configure(builder);
+    builder.enableConstantArgumentAnnotations();
+  }
+
+  @Override
   public Class<?> getTestClass() {
     return TestClass.class;
   }
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/unusedarguments/UnusedArgumentsMixedWidthTest.java b/src/test/java/com/android/tools/r8/ir/optimize/unusedarguments/UnusedArgumentsMixedWidthTest.java
index e10793d..7ed9021 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/unusedarguments/UnusedArgumentsMixedWidthTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/unusedarguments/UnusedArgumentsMixedWidthTest.java
@@ -6,7 +6,9 @@
 
 import static org.junit.Assert.assertEquals;
 
+import com.android.tools.r8.KeepConstantArguments;
 import com.android.tools.r8.NeverInline;
+import com.android.tools.r8.R8FullTestBuilder;
 import com.android.tools.r8.utils.codeinspector.ClassSubject;
 import java.util.Collection;
 import org.junit.Assert;
@@ -27,21 +29,26 @@
   }
 
   static class TestClass {
+
+    @KeepConstantArguments
     @NeverInline
     public static int a(int a, long b) {
       return a;
     }
 
+    @KeepConstantArguments
     @NeverInline
     public static long a(long a, int b) {
       return a;
     }
 
+    @KeepConstantArguments
     @NeverInline
     public static int a(int a, long b, int c) {
       return c;
     }
 
+    @KeepConstantArguments
     @NeverInline
     public static long a(long a, int b, long c) {
       return c;
@@ -56,6 +63,12 @@
   }
 
   @Override
+  public void configure(R8FullTestBuilder builder) {
+    super.configure(builder);
+    builder.enableConstantArgumentAnnotations();
+  }
+
+  @Override
   public Class<?> getTestClass() {
     return TestClass.class;
   }
diff --git a/src/test/java/com/android/tools/r8/jasmin/JasminBuilder.java b/src/test/java/com/android/tools/r8/jasmin/JasminBuilder.java
index 7f41f05..beb87b8 100644
--- a/src/test/java/com/android/tools/r8/jasmin/JasminBuilder.java
+++ b/src/test/java/com/android/tools/r8/jasmin/JasminBuilder.java
@@ -95,6 +95,8 @@
     private boolean isInterface = false;
     private String access = "public";
 
+    private final List<String> pendingAnnotations = new ArrayList<>();
+
     private ClassBuilder(String name) {
       this(name, "java/lang/Object");
     }
@@ -124,6 +126,13 @@
       return addMethod("public abstract", name, argumentTypes, returnType);
     }
 
+    public void addRuntimeInvisibleAnnotation(String typeName) {
+      pendingAnnotations.add(
+          StringUtils.lines(
+              ".annotation invisible " + DescriptorUtils.javaTypeToDescriptor(typeName),
+              ".end annotation"));
+    }
+
     public MethodSignature addFinalMethod(
         String name,
         List<String> argumentTypes,
@@ -221,6 +230,10 @@
           .append(StringUtils.join("", argumentTypes, BraceType.PARENS))
           .append(returnType)
           .append("\n");
+      if (!pendingAnnotations.isEmpty()) {
+        pendingAnnotations.forEach(builder::append);
+        pendingAnnotations.clear();
+      }
       for (String line : lines) {
         builder.append(line).append("\n");
       }
diff --git a/src/test/java/com/android/tools/r8/kotlin/AbstractR8KotlinTestBase.java b/src/test/java/com/android/tools/r8/kotlin/AbstractR8KotlinTestBase.java
index 495eae6..2516b74 100644
--- a/src/test/java/com/android/tools/r8/kotlin/AbstractR8KotlinTestBase.java
+++ b/src/test/java/com/android/tools/r8/kotlin/AbstractR8KotlinTestBase.java
@@ -262,7 +262,7 @@
     }
   }
 
-  private void checkMethodPresenceInInput(
+  protected void checkMethodPresenceInInput(
       String className, MethodSignature methodSignature, boolean isPresent) {
     boolean foundMethod = AsmUtils.doesMethodExist(classpath, className,
         methodSignature.name, methodSignature.toDescriptor());
diff --git a/src/test/java/com/android/tools/r8/kotlin/R8KotlinAccessorTest.java b/src/test/java/com/android/tools/r8/kotlin/R8KotlinAccessorTest.java
index 3d872c4..46adea0 100644
--- a/src/test/java/com/android/tools/r8/kotlin/R8KotlinAccessorTest.java
+++ b/src/test/java/com/android/tools/r8/kotlin/R8KotlinAccessorTest.java
@@ -14,6 +14,7 @@
 import com.android.tools.r8.R8TestBuilder;
 import com.android.tools.r8.TestParameters;
 import com.android.tools.r8.ToolHelper;
+import com.android.tools.r8.ToolHelper.KotlinTargetVersion;
 import com.android.tools.r8.ToolHelper.ProcessResult;
 import com.android.tools.r8.jasmin.JasminBuilder;
 import com.android.tools.r8.jasmin.JasminBuilder.ClassBuilder;
@@ -28,7 +29,6 @@
 import java.util.Collection;
 import java.util.Collections;
 import org.junit.Assert;
-import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.Parameterized;
@@ -111,7 +111,7 @@
               } else {
                 assertTrue(fieldSubject.getField().accessFlags.isPrivate());
                 checkMethodIsKept(outerClass, getterAccessor);
-                checkMethodIsKept(outerClass, setterAccessor);
+                checkMethodIsRemoved(outerClass, setterAccessor);
               }
             });
   }
@@ -146,7 +146,7 @@
                 assertTrue(fieldSubject.getField().accessFlags.isPrivate());
 
                 checkMethodIsKept(outerClass, getterAccessor);
-                checkMethodIsKept(outerClass, setterAccessor);
+                checkMethodIsRemoved(outerClass, setterAccessor);
               }
             });
   }
@@ -180,7 +180,7 @@
               } else {
                 assertTrue(fieldSubject.getField().accessFlags.isPrivate());
                 checkMethodIsKept(outerClass, getterAccessor);
-                checkMethodIsKept(outerClass, setterAccessor);
+                checkMethodIsRemoved(outerClass, setterAccessor);
               }
             });
   }
@@ -214,7 +214,7 @@
               } else {
                 assertTrue(fieldSubject.getField().accessFlags.isPrivate());
                 checkMethodIsKept(outerClass, getterAccessor);
-                checkMethodIsKept(outerClass, setterAccessor);
+                checkMethodIsRemoved(outerClass, setterAccessor);
               }
             });
   }
@@ -247,7 +247,7 @@
               } else {
                 assertTrue(fieldSubject.getField().accessFlags.isPrivate());
                 checkMethodIsKept(outerClass, getterAccessor);
-                checkMethodIsKept(outerClass, setterAccessor);
+                checkMethodIsRemoved(outerClass, setterAccessor);
               }
             });
   }
@@ -340,7 +340,6 @@
   }
 
   @Test
-  @Ignore("b/74103342")
   public void testAccessorFromPrivate() throws Exception {
     TestKotlinCompanionClass testedClass = ACCESSOR_COMPANION_PROPERTY_CLASS;
     String mainClass = addMainToClasspath("accessors.AccessorKt",
@@ -348,28 +347,8 @@
     runTest("accessors", mainClass)
         .inspect(
             inspector -> {
-              ClassSubject outerClass =
-                  checkClassIsKept(inspector, testedClass.getOuterClassName());
-              ClassSubject companionClass = checkClassIsKept(inspector, testedClass.getClassName());
-              String propertyName = "property";
-              FieldSubject fieldSubject =
-                  checkFieldIsKept(outerClass, JAVA_LANG_STRING, propertyName);
-              assertTrue(fieldSubject.getField().accessFlags.isStatic());
-
-              // We cannot inline the getter because we don't know if NPE is preserved.
-              MemberNaming.MethodSignature getter = testedClass.getGetterForProperty(propertyName);
-              checkMethodIsKept(companionClass, getter);
-
-              // We should always inline the static accessor method.
-              MemberNaming.MethodSignature getterAccessor =
-                  testedClass.getGetterAccessorForProperty(propertyName, AccessorKind.FROM_INNER);
-              checkMethodIsRemoved(companionClass, getterAccessor);
-
-              if (allowAccessModification) {
-                assertTrue(fieldSubject.getField().accessFlags.isPublic());
-              } else {
-                assertTrue(fieldSubject.getField().accessFlags.isPrivate());
-              }
+              checkClassIsRemoved(inspector, testedClass.getOuterClassName());
+              checkClassIsRemoved(inspector, testedClass.getClassName());
             });
   }
 
@@ -389,7 +368,6 @@
   }
 
   @Test
-  @Ignore("b/74103342")
   public void testPrivatePropertyAccessorForInnerClassCanBeInlined() throws Exception {
     TestKotlinClass testedClass = PROPERTY_ACCESS_FOR_INNER_CLASS;
     String mainClass = addMainToClasspath(testedClass.className + "Kt",
@@ -397,6 +375,13 @@
     runTest("accessors", mainClass)
         .inspect(
             inspector -> {
+              if (allowAccessModification
+                  && (testParameters.isCfRuntime()
+                      || !kotlinParameters.is(KOTLINC_1_5_0, KotlinTargetVersion.JAVA_8))) {
+                checkClassIsRemoved(inspector, testedClass.getClassName());
+                return;
+              }
+
               ClassSubject classSubject = checkClassIsKept(inspector, testedClass.getClassName());
 
               String propertyName = "privateProp";
@@ -415,13 +400,12 @@
               } else {
                 assertTrue(fieldSubject.getField().accessFlags.isPrivate());
                 checkMethodIsKept(classSubject, getterAccessor);
-                checkMethodIsKept(classSubject, setterAccessor);
+                checkMethodIsRemoved(classSubject, setterAccessor);
               }
             });
   }
 
   @Test
-  @Ignore("b/74103342")
   public void testPrivateLateInitPropertyAccessorForInnerClassCanBeInlined() throws Exception {
     TestKotlinClass testedClass = PROPERTY_ACCESS_FOR_INNER_CLASS;
     String mainClass = addMainToClasspath(testedClass.className + "Kt",
@@ -429,31 +413,15 @@
     runTest("accessors", mainClass)
         .inspect(
             inspector -> {
-              ClassSubject classSubject = checkClassIsKept(inspector, testedClass.getClassName());
-
-              String propertyName = "privateLateInitProp";
-              FieldSubject fieldSubject =
-                  checkFieldIsKept(classSubject, JAVA_LANG_STRING, propertyName);
-              assertFalse(fieldSubject.getField().accessFlags.isStatic());
-
-              MemberNaming.MethodSignature getterAccessor =
-                  testedClass.getGetterAccessorForProperty(propertyName, AccessorKind.FROM_INNER);
-              MemberNaming.MethodSignature setterAccessor =
-                  testedClass.getSetterAccessorForProperty(propertyName, AccessorKind.FROM_INNER);
-              if (allowAccessModification) {
-                assertTrue(fieldSubject.getField().accessFlags.isPublic());
-                checkMethodIsRemoved(classSubject, getterAccessor);
-                checkMethodIsRemoved(classSubject, setterAccessor);
+              if (kotlinc.getCompilerVersion() == KOTLINC_1_5_0 && testParameters.isDexRuntime()) {
+                checkClassIsKept(inspector, testedClass.getClassName());
               } else {
-                assertTrue(fieldSubject.getField().accessFlags.isPrivate());
-                checkMethodIsKept(classSubject, getterAccessor);
-                checkMethodIsKept(classSubject, setterAccessor);
+                checkClassIsRemoved(inspector, testedClass.getClassName());
               }
             });
   }
 
   @Test
-  @Ignore("b/74103342")
   public void testAccessorForLambdaIsRemovedWhenNotUsed() throws Exception {
     TestKotlinClass testedClass = PROPERTY_ACCESS_FOR_LAMBDA_CLASS;
     String mainClass = addMainToClasspath(testedClass.className + "Kt",
@@ -461,21 +429,11 @@
     runTest("accessors", mainClass)
         .inspect(
             inspector -> {
-              ClassSubject classSubject = checkClassIsKept(inspector, testedClass.getClassName());
-              String propertyName = "property";
-
-              MemberNaming.MethodSignature getterAccessor =
-                  testedClass.getGetterAccessorForProperty(propertyName, AccessorKind.FROM_LAMBDA);
-              MemberNaming.MethodSignature setterAccessor =
-                  testedClass.getSetterAccessorForProperty(propertyName, AccessorKind.FROM_LAMBDA);
-
-              checkMethodIsRemoved(classSubject, getterAccessor);
-              checkMethodIsRemoved(classSubject, setterAccessor);
+              checkClassIsRemoved(inspector, testedClass.getClassName());
             });
   }
 
   @Test
-  @Ignore("b/74103342")
   public void testAccessorForLambdaCanBeInlined() throws Exception {
     TestKotlinClass testedClass = PROPERTY_ACCESS_FOR_LAMBDA_CLASS;
     String mainClass = addMainToClasspath(testedClass.className + "Kt",
@@ -483,16 +441,25 @@
     runTest("accessors", mainClass)
         .inspect(
             inspector -> {
+              if (allowAccessModification) {
+                checkClassIsRemoved(inspector, testedClass.getClassName());
+                return;
+              }
+
               ClassSubject classSubject = checkClassIsKept(inspector, testedClass.getClassName());
               String propertyName = "property";
               FieldSubject fieldSubject =
                   checkFieldIsKept(classSubject, JAVA_LANG_STRING, propertyName);
               assertFalse(fieldSubject.getField().accessFlags.isStatic());
 
+              AccessorKind accessorKind =
+                  kotlinc.getCompilerVersion() == KOTLINC_1_5_0
+                      ? AccessorKind.FROM_INNER
+                      : AccessorKind.FROM_LAMBDA;
               MemberNaming.MethodSignature getterAccessor =
-                  testedClass.getGetterAccessorForProperty(propertyName, AccessorKind.FROM_LAMBDA);
+                  testedClass.getGetterAccessorForProperty(propertyName, accessorKind);
               MemberNaming.MethodSignature setterAccessor =
-                  testedClass.getSetterAccessorForProperty(propertyName, AccessorKind.FROM_LAMBDA);
+                  testedClass.getSetterAccessorForProperty(propertyName, accessorKind);
               if (allowAccessModification) {
                 assertTrue(fieldSubject.getField().accessFlags.isPublic());
                 checkMethodIsRemoved(classSubject, getterAccessor);
diff --git a/src/test/java/com/android/tools/r8/kotlin/R8KotlinIntrinsicsTest.java b/src/test/java/com/android/tools/r8/kotlin/R8KotlinIntrinsicsTest.java
index 5de5dbd..4457386 100644
--- a/src/test/java/com/android/tools/r8/kotlin/R8KotlinIntrinsicsTest.java
+++ b/src/test/java/com/android/tools/r8/kotlin/R8KotlinIntrinsicsTest.java
@@ -54,9 +54,7 @@
             "intrinsics",
             "intrinsics.IntrinsicsKt",
             testBuilder ->
-                testBuilder
-                    .addKeepRules(extraRules)
-                    .noHorizontalClassMerging(Intrinsics.class))
+                testBuilder.addKeepRules(extraRules).noHorizontalClassMerging(Intrinsics.class))
         .inspect(
             inspector -> {
               ClassSubject intrinsicsClass =
@@ -75,8 +73,7 @@
                               "checkParameterIsNotNull",
                               "void",
                               Lists.newArrayList("java.lang.Object", "java.lang.String")),
-                          // TODO(b/179866251): This is also different on CF
-                          !allowAccessModification || testParameters.isCfRuntime())
+                          !allowAccessModification)
                       .build());
             });
   }
diff --git a/src/test/java/com/android/tools/r8/kotlin/R8KotlinPropertiesTest.java b/src/test/java/com/android/tools/r8/kotlin/R8KotlinPropertiesTest.java
index 65822f7..c605951 100644
--- a/src/test/java/com/android/tools/r8/kotlin/R8KotlinPropertiesTest.java
+++ b/src/test/java/com/android/tools/r8/kotlin/R8KotlinPropertiesTest.java
@@ -253,9 +253,7 @@
     runTest(
             PACKAGE_NAME,
             mainClass,
-            testBuilder ->
-                testBuilder
-                    .addOptionsModification(disableAggressiveClassOptimizations))
+            testBuilder -> testBuilder.addOptionsModification(disableAggressiveClassOptimizations))
         .inspect(
             inspector -> {
               ClassSubject classSubject =
@@ -272,7 +270,7 @@
               } else {
                 assertTrue(fieldSubject.getField().accessFlags.isPrivate());
                 checkMethodIsKept(classSubject, getter);
-                checkMethodIsKept(classSubject, setter);
+                checkMethodIsRemoved(classSubject, setter);
               }
             });
   }
@@ -650,9 +648,7 @@
     runTest(
             PACKAGE_NAME,
             mainClass,
-            testBuilder ->
-                testBuilder
-                    .addOptionsModification(disableAggressiveClassOptimizations))
+            testBuilder -> testBuilder.addOptionsModification(disableAggressiveClassOptimizations))
         .inspect(
             inspector -> {
               ClassSubject objectClass = checkClassIsKept(inspector, testedClass.getClassName());
@@ -671,7 +667,7 @@
                 checkMethodIsRemoved(objectClass, setter);
               } else {
                 checkMethodIsKept(objectClass, getter);
-                checkMethodIsKept(objectClass, setter);
+                checkMethodIsRemoved(objectClass, setter);
               }
 
               if (allowAccessModification) {
@@ -724,9 +720,7 @@
     runTest(
             PACKAGE_NAME,
             mainClass,
-            testBuilder ->
-                testBuilder
-                    .addOptionsModification(disableAggressiveClassOptimizations))
+            testBuilder -> testBuilder.addOptionsModification(disableAggressiveClassOptimizations))
         .inspect(
             inspector -> {
               ClassSubject objectClass = checkClassIsKept(inspector, testedClass.getClassName());
@@ -746,7 +740,7 @@
                 checkMethodIsRemoved(objectClass, setter);
               } else {
                 checkMethodIsKept(objectClass, getter);
-                checkMethodIsKept(objectClass, setter);
+                checkMethodIsRemoved(objectClass, setter);
               }
 
               if (allowAccessModification) {
@@ -765,9 +759,7 @@
     runTest(
             PACKAGE_NAME,
             mainClass,
-            testBuilder ->
-                testBuilder
-                    .addOptionsModification(disableAggressiveClassOptimizations))
+            testBuilder -> testBuilder.addOptionsModification(disableAggressiveClassOptimizations))
         .inspect(
             inspector -> {
               ClassSubject objectClass = checkClassIsKept(inspector, testedClass.getClassName());
@@ -787,7 +779,7 @@
                 checkMethodIsRemoved(objectClass, setter);
               } else {
                 checkMethodIsKept(objectClass, getter);
-                checkMethodIsKept(objectClass, setter);
+                checkMethodIsRemoved(objectClass, setter);
               }
 
               if (allowAccessModification) {
@@ -896,9 +888,7 @@
     runTest(
             PACKAGE_NAME,
             mainClass,
-            testBuilder ->
-                testBuilder
-                    .addOptionsModification(disableAggressiveClassOptimizations))
+            testBuilder -> testBuilder.addOptionsModification(disableAggressiveClassOptimizations))
         .inspect(
             inspector -> {
               ClassSubject objectClass = checkClassIsKept(inspector, testedClass.getClassName());
@@ -916,7 +906,7 @@
               } else {
                 assertTrue(fieldSubject.getField().accessFlags.isPrivate());
                 checkMethodIsKept(objectClass, getter);
-                checkMethodIsKept(objectClass, setter);
+                checkMethodIsRemoved(objectClass, setter);
               }
             });
   }
diff --git a/src/test/java/com/android/tools/r8/kotlin/SimplifyIfNotNullKotlinTest.java b/src/test/java/com/android/tools/r8/kotlin/SimplifyIfNotNullKotlinTest.java
index e83626b..091a8b4 100644
--- a/src/test/java/com/android/tools/r8/kotlin/SimplifyIfNotNullKotlinTest.java
+++ b/src/test/java/com/android/tools/r8/kotlin/SimplifyIfNotNullKotlinTest.java
@@ -11,6 +11,7 @@
 import com.android.tools.r8.TestParameters;
 import com.android.tools.r8.naming.MemberNaming.MethodSignature;
 import com.android.tools.r8.utils.BooleanUtils;
+import com.android.tools.r8.utils.StringUtils;
 import com.android.tools.r8.utils.codeinspector.ClassSubject;
 import com.android.tools.r8.utils.codeinspector.MethodSubject;
 import com.google.common.collect.ImmutableList;
@@ -47,7 +48,13 @@
             ImmutableList.of("java.util.Collection", STRING, STRING, "java.lang.Integer"));
 
     final String mainClassName = ex1.getClassName();
-    final String extraRules = neverInlineMethod(mainClassName, testMethodSignature);
+    final String extraRules =
+        StringUtils.lines(
+            neverInlineMethod(mainClassName, testMethodSignature),
+            // TODO(b/173398086): uniqueMethodWithName() does not work with argument removal.
+            "-keepclassmembers,allowoptimization,allowshrinking class non_null.Example1Kt {",
+            "  *** forMakeAndModel(...);",
+            "}");
     runTest(
             FOLDER,
             mainClassName,
@@ -56,7 +63,11 @@
             inspector -> {
               ClassSubject clazz = checkClassIsKept(inspector, ex1.getClassName());
 
-              MethodSubject testMethod = checkMethodIsKept(clazz, testMethodSignature);
+              // Verify forMakeAndModel(...) is present in the input.
+              checkMethodPresenceInInput(clazz.getOriginalName(), testMethodSignature, true);
+
+              // Find forMakeAndModel(...) after parameter removal.
+              MethodSubject testMethod = clazz.uniqueMethodWithName(testMethodSignature.name);
               long ifzCount =
                   testMethod.streamInstructions().filter(i -> i.isIfEqz() || i.isIfNez()).count();
               long paramNullCheckCount =
diff --git a/src/test/java/com/android/tools/r8/naming/EnumMinification.java b/src/test/java/com/android/tools/r8/naming/EnumMinification.java
index aeb142f..3cf01e0 100644
--- a/src/test/java/com/android/tools/r8/naming/EnumMinification.java
+++ b/src/test/java/com/android/tools/r8/naming/EnumMinification.java
@@ -102,7 +102,7 @@
 class Main {
 
   public static void main(String[] args) {
-    Enum e = Enum.valueOf("VALUE1");
+    Enum e = Enum.valueOf(System.currentTimeMillis() > 0 ? "VALUE1" : null);
     System.out.print(e);
   }
 }
diff --git a/src/test/java/com/android/tools/r8/naming/KotlinIntrinsicsIdentifierTest.java b/src/test/java/com/android/tools/r8/naming/KotlinIntrinsicsIdentifierTest.java
index 3c52044..c129553 100644
--- a/src/test/java/com/android/tools/r8/naming/KotlinIntrinsicsIdentifierTest.java
+++ b/src/test/java/com/android/tools/r8/naming/KotlinIntrinsicsIdentifierTest.java
@@ -97,7 +97,12 @@
                 getKotlinAnnotationJar(kotlinc))
             .addProgramFiles(getJavaJarFile(FOLDER))
             .addKeepMainRule(mainClassName)
+            .addKeepRules(
+                "-keepconstantarguments class kotlin.jvm.internal.Intrinsics {",
+                "  *** checkParameterIsNotNull(...);",
+                "}")
             .allowDiagnosticWarningMessages()
+            .enableProguardTestOptions()
             .minification(minification)
             .compile()
             .assertAllWarningMessagesMatch(
@@ -158,7 +163,10 @@
                     "-neverclassinline class **." + targetClassName,
                     "-" + NoVerticalClassMergingRule.RULE_NAME + " class **." + targetClassName,
                     "-" + NoHorizontalClassMergingRule.RULE_NAME + " class **." + targetClassName,
-                    "-neverinline class **." + targetClassName + " { <methods>; }"))
+                    "-neverinline class **." + targetClassName + " { <methods>; }",
+                    "-keepconstantarguments class kotlin.jvm.internal.Intrinsics {",
+                    "  *** checkParameterIsNotNull(...);",
+                    "}"))
             .allowDiagnosticWarningMessages()
             .minification(minification)
             .compile()
diff --git a/src/test/java/com/android/tools/r8/naming/overloadaggressively/ValidNameConflictTest.java b/src/test/java/com/android/tools/r8/naming/overloadaggressively/ValidNameConflictTest.java
index 3d9645d..6c1175c 100644
--- a/src/test/java/com/android/tools/r8/naming/overloadaggressively/ValidNameConflictTest.java
+++ b/src/test/java/com/android/tools/r8/naming/overloadaggressively/ValidNameConflictTest.java
@@ -444,10 +444,12 @@
     ProcessResult javaOutput = runOnJavaNoVerifyRaw(builder, CLASS_NAME);
     assertEquals(0, javaOutput.exitCode);
 
-    List<String> pgConfigs = ImmutableList.of(
-        keepMainProguardConfiguration(CLASS_NAME),
-        "-overloadaggressively",
-        "-dontshrink");
+    List<String> pgConfigs =
+        ImmutableList.of(
+            keepMainProguardConfiguration(CLASS_NAME),
+            "-overloadaggressively",
+            "-dontoptimize",
+            "-dontshrink");
     AndroidApp app = compileWithR8(builder, pgConfigs, null, backend);
 
     CodeInspector codeInspector = new CodeInspector(app);
diff --git a/src/test/java/com/android/tools/r8/regress/b165825758/Regress165825758Test.java b/src/test/java/com/android/tools/r8/regress/b165825758/Regress165825758Test.java
index bf95231..41d6a49 100644
--- a/src/test/java/com/android/tools/r8/regress/b165825758/Regress165825758Test.java
+++ b/src/test/java/com/android/tools/r8/regress/b165825758/Regress165825758Test.java
@@ -9,6 +9,7 @@
 import static org.junit.Assert.assertTrue;
 
 import com.android.tools.r8.NeverInline;
+import com.android.tools.r8.NeverReprocessMethod;
 import com.android.tools.r8.TestBase;
 import com.android.tools.r8.TestParameters;
 import com.android.tools.r8.TestParametersCollection;
@@ -35,7 +36,7 @@
 
   @Parameterized.Parameters(name = "{0}")
   public static TestParametersCollection data() {
-    return getTestParameters().withAllRuntimes().withAllApiLevels().build();
+    return getTestParameters().withAllRuntimesAndApiLevels().build();
   }
 
   public Regress165825758Test(TestParameters parameters) {
@@ -57,6 +58,7 @@
         .addInnerClasses(Regress165825758Test.class)
         .addKeepMainRule(TestClass.class)
         .addKeepClassRules(A.class)
+        .enableNeverReprocessMethodAnnotations()
         .setMinApi(parameters.getApiLevel())
         .run(parameters.getRuntime(), TestClass.class)
         .assertSuccessWithOutput(EXPECTED)
@@ -99,6 +101,7 @@
   static class A {
 
     @NeverInline
+    @NeverReprocessMethod
     void synchronizedMethod() {
       synchronized (this) {
         TestClass.throwNpe();
diff --git a/src/test/java/com/android/tools/r8/repackage/RepackageWithPackagePrivateMethodParameterAnnotationTest.java b/src/test/java/com/android/tools/r8/repackage/RepackageWithPackagePrivateMethodParameterAnnotationTest.java
index d9833ae..8c754e5 100644
--- a/src/test/java/com/android/tools/r8/repackage/RepackageWithPackagePrivateMethodParameterAnnotationTest.java
+++ b/src/test/java/com/android/tools/r8/repackage/RepackageWithPackagePrivateMethodParameterAnnotationTest.java
@@ -8,6 +8,7 @@
 import static org.hamcrest.MatcherAssert.assertThat;
 import static org.junit.Assert.assertEquals;
 
+import com.android.tools.r8.KeepConstantArguments;
 import com.android.tools.r8.NeverInline;
 import com.android.tools.r8.TestParameters;
 import com.android.tools.r8.utils.codeinspector.ClassSubject;
@@ -36,6 +37,7 @@
         .addKeepClassRules(NonPublicKeptAnnotation.class)
         .addKeepRuntimeVisibleParameterAnnotations()
         .apply(this::configureRepackaging)
+        .enableConstantArgumentAnnotations()
         .enableInliningAnnotations()
         .setMinApi(parameters.getApiLevel())
         .compile()
@@ -67,6 +69,7 @@
 
   public static class IneligibleForRepackaging {
 
+    @KeepConstantArguments
     @NeverInline
     public static void greet(@NonPublicKeptAnnotation String greeting) {
       System.out.println(greeting);
diff --git a/src/test/java/com/android/tools/r8/rewrite/enums/EnumOptimizationTest.java b/src/test/java/com/android/tools/r8/rewrite/enums/EnumOptimizationTest.java
index 7733b23..a9574e8 100644
--- a/src/test/java/com/android/tools/r8/rewrite/enums/EnumOptimizationTest.java
+++ b/src/test/java/com/android/tools/r8/rewrite/enums/EnumOptimizationTest.java
@@ -57,6 +57,7 @@
     testForR8(parameters.getBackend())
         .addProgramClassesAndInnerClasses(Ordinals.class)
         .addKeepMainRule(Ordinals.class)
+        .enableConstantArgumentAnnotations()
         .enableForceInliningAnnotations()
         .enableInliningAnnotations()
         .enableSideEffectAnnotations()
@@ -106,6 +107,7 @@
     testForR8(parameters.getBackend())
         .addProgramClassesAndInnerClasses(Names.class)
         .addKeepMainRule(Names.class)
+        .enableConstantArgumentAnnotations()
         .enableForceInliningAnnotations()
         .enableInliningAnnotations()
         .enableSideEffectAnnotations()
@@ -152,6 +154,7 @@
     testForR8(parameters.getBackend())
         .addProgramClassesAndInnerClasses(ToStrings.class)
         .addKeepMainRule(ToStrings.class)
+        .enableConstantArgumentAnnotations()
         .enableForceInliningAnnotations()
         .enableInliningAnnotations()
         .enableSideEffectAnnotations()
diff --git a/src/test/java/com/android/tools/r8/rewrite/enums/Names.java b/src/test/java/com/android/tools/r8/rewrite/enums/Names.java
index 5dd5ec0..1c2964c 100644
--- a/src/test/java/com/android/tools/r8/rewrite/enums/Names.java
+++ b/src/test/java/com/android/tools/r8/rewrite/enums/Names.java
@@ -6,6 +6,7 @@
 
 import com.android.tools.r8.AssumeMayHaveSideEffects;
 import com.android.tools.r8.ForceInline;
+import com.android.tools.r8.KeepConstantArguments;
 import com.android.tools.r8.NeverInline;
 import java.util.concurrent.TimeUnit;
 
@@ -69,6 +70,7 @@
     return Number.DEFAULT.name();
   }
 
+  @KeepConstantArguments
   @NeverInline
   private static String phi(boolean value) {
     Number number = Number.ONE;
diff --git a/src/test/java/com/android/tools/r8/rewrite/enums/Ordinals.java b/src/test/java/com/android/tools/r8/rewrite/enums/Ordinals.java
index e1eee2c..c3fbffc 100644
--- a/src/test/java/com/android/tools/r8/rewrite/enums/Ordinals.java
+++ b/src/test/java/com/android/tools/r8/rewrite/enums/Ordinals.java
@@ -6,6 +6,7 @@
 
 import com.android.tools.r8.AssumeMayHaveSideEffects;
 import com.android.tools.r8.ForceInline;
+import com.android.tools.r8.KeepConstantArguments;
 import com.android.tools.r8.NeverInline;
 import java.util.concurrent.TimeUnit;
 
@@ -79,6 +80,7 @@
     return Number.DEFAULT.ordinal();
   }
 
+  @KeepConstantArguments
   @NeverInline
   private static long phi(boolean value) {
     Number number = Number.ONE;
diff --git a/src/test/java/com/android/tools/r8/rewrite/enums/ToStrings.java b/src/test/java/com/android/tools/r8/rewrite/enums/ToStrings.java
index 8055344..020f5fd 100644
--- a/src/test/java/com/android/tools/r8/rewrite/enums/ToStrings.java
+++ b/src/test/java/com/android/tools/r8/rewrite/enums/ToStrings.java
@@ -6,6 +6,7 @@
 
 import com.android.tools.r8.AssumeMayHaveSideEffects;
 import com.android.tools.r8.ForceInline;
+import com.android.tools.r8.KeepConstantArguments;
 import com.android.tools.r8.NeverInline;
 import java.util.Locale;
 import java.util.concurrent.TimeUnit;
@@ -106,6 +107,7 @@
     return NoToString.DEFAULT.toString();
   }
 
+  @KeepConstantArguments
   @NeverInline
   private static String phi(boolean value) {
     NoToString number = NoToString.ONE;
diff --git a/src/test/java/com/android/tools/r8/rewrite/switches/MaxIntSwitchTest.java b/src/test/java/com/android/tools/r8/rewrite/switches/MaxIntSwitchTest.java
index b32e476..26dcb7a 100644
--- a/src/test/java/com/android/tools/r8/rewrite/switches/MaxIntSwitchTest.java
+++ b/src/test/java/com/android/tools/r8/rewrite/switches/MaxIntSwitchTest.java
@@ -7,6 +7,7 @@
 import static org.junit.Assert.assertTrue;
 
 import com.android.tools.r8.CompilationMode;
+import com.android.tools.r8.KeepConstantArguments;
 import com.android.tools.r8.NeverInline;
 import com.android.tools.r8.NeverPropagateValue;
 import com.android.tools.r8.TestBase;
@@ -104,6 +105,7 @@
     testForR8(parameters.getBackend())
         .addInnerClasses(this.getClass())
         .addKeepMainRule(TestClass.class)
+        .enableConstantArgumentAnnotations()
         .enableInliningAnnotations()
         .enableMemberValuePropagationAnnotations()
         .setMinApi(parameters.getApiLevel())
@@ -125,6 +127,7 @@
           "?");
 
   static class TestClass {
+    @KeepConstantArguments
     @NeverInline
     @NeverPropagateValue
     public static void f(int i) {
@@ -143,6 +146,7 @@
       }
     }
 
+    @KeepConstantArguments
     @NeverInline
     @NeverPropagateValue
     public static void g(int i) {
@@ -162,6 +166,7 @@
       }
     }
 
+    @KeepConstantArguments
     @NeverInline
     @NeverPropagateValue
     public static void h(int i) {
@@ -174,6 +179,7 @@
       }
     }
 
+    @KeepConstantArguments
     @NeverInline
     @NeverPropagateValue
     public static void s(String s) {
diff --git a/src/test/java/com/android/tools/r8/shaking/KeepAnnotatedMemberTest.java b/src/test/java/com/android/tools/r8/shaking/KeepAnnotatedMemberTest.java
index d98725d..6a95824 100644
--- a/src/test/java/com/android/tools/r8/shaking/KeepAnnotatedMemberTest.java
+++ b/src/test/java/com/android/tools/r8/shaking/KeepAnnotatedMemberTest.java
@@ -3,7 +3,6 @@
 // BSD-style license that can be found in the LICENSE file.
 package com.android.tools.r8.shaking;
 
-import static com.android.tools.r8.DiagnosticsMatcher.diagnosticException;
 import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
 import static com.android.tools.r8.utils.codeinspector.Matchers.proguardConfigurationRuleDoesNotMatch;
 import static com.android.tools.r8.utils.codeinspector.Matchers.typeVariableNotInScope;
@@ -13,7 +12,6 @@
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 
-import com.android.tools.r8.CompilationFailedException;
 import com.android.tools.r8.R8;
 import com.android.tools.r8.R8FullTestBuilder;
 import com.android.tools.r8.TestBase;
@@ -76,8 +74,7 @@
     assertThat(method, isPresent());
   }
 
-  // TODO(b/159966986): A general keep rule should not cause compiler assertion errors.
-  @Test(expected = CompilationFailedException.class)
+  @Test
   public void testPresentAnnotation() throws Exception {
     testForR8(Backend.CF)
         .addProgramFiles(R8_JAR)
@@ -85,10 +82,7 @@
         .addDontWarnGoogle()
         .addDontWarnJavax()
         .addDontWarn("org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement")
-        .allowDiagnosticInfoMessages()
-        .compileWithExpectedDiagnostics(
-            diagnostics -> diagnostics.assertErrorsMatch(diagnosticException(AssertionError.class)))
-        .apply(TestBase::verifyAllInfoFromGenericSignatureTypeParameterValidation);
+        .compile();
   }
 
   @Test
diff --git a/src/test/java/com/android/tools/r8/shaking/array/DeadArrayLengthTest.java b/src/test/java/com/android/tools/r8/shaking/array/DeadArrayLengthTest.java
index 14259ca..03d5aa6 100644
--- a/src/test/java/com/android/tools/r8/shaking/array/DeadArrayLengthTest.java
+++ b/src/test/java/com/android/tools/r8/shaking/array/DeadArrayLengthTest.java
@@ -31,7 +31,7 @@
 
   @Parameterized.Parameters(name = "{0}")
   public static TestParametersCollection data() {
-    return getTestParameters().withAllRuntimes().build();
+    return getTestParameters().withAllRuntimesAndApiLevels().build();
   }
 
   public DeadArrayLengthTest(TestParameters parameters) {
@@ -65,7 +65,7 @@
     testForD8()
         .release()
         .addProgramClasses(MAIN)
-        .setMinApi(parameters.getRuntime())
+        .setMinApi(parameters.getApiLevel())
         .run(parameters.getRuntime(), MAIN)
         .assertSuccessWithOutput(EXPECTED_OUTPUT)
         .inspect(codeInspector -> inspect(codeInspector, false));
@@ -79,7 +79,7 @@
         .enableInliningAnnotations()
         .enableMemberValuePropagationAnnotations()
         .noMinification()
-        .setMinApi(parameters.getRuntime())
+        .setMinApi(parameters.getApiLevel())
         .run(parameters.getRuntime(), MAIN)
         .assertSuccessWithOutput(EXPECTED_OUTPUT)
         .inspect(codeInspector -> inspect(codeInspector, true));
diff --git a/src/test/java/com/android/tools/r8/shaking/attributes/KeepSignatureTest.java b/src/test/java/com/android/tools/r8/shaking/attributes/KeepSignatureTest.java
index 9dfff6e..fdea6ab 100644
--- a/src/test/java/com/android/tools/r8/shaking/attributes/KeepSignatureTest.java
+++ b/src/test/java/com/android/tools/r8/shaking/attributes/KeepSignatureTest.java
@@ -9,6 +9,7 @@
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNull;
 
+import com.android.tools.r8.KeepConstantArguments;
 import com.android.tools.r8.NeverClassInline;
 import com.android.tools.r8.NeverInline;
 import com.android.tools.r8.R8TestBuilder;
@@ -80,6 +81,7 @@
             ProguardKeepAttributes.INNER_CLASSES,
             ProguardKeepAttributes.ENCLOSING_METHOD)
         .setMinApi(parameters.getApiLevel())
+        .enableConstantArgumentAnnotations()
         .enableInliningAnnotations()
         .enableNeverClassInliningAnnotations()
         .run(parameters.getRuntime(), KeptClass.class)
@@ -137,6 +139,7 @@
 
     public List<P> notKeptField;
 
+    @KeepConstantArguments
     @NeverInline
     public List<P> notKeptMethod(P p1, P p2) {
       if (notKeptField != null) {
@@ -163,6 +166,7 @@
       return (R) keptField;
     }
 
+    @KeepConstantArguments
     @NeverInline
     @SuppressWarnings("unchecked")
     public <R> R notKeptMethod(T t) {
diff --git a/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking2Test.java b/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking2Test.java
index d951404..74232e1 100644
--- a/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking2Test.java
+++ b/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking2Test.java
@@ -3,6 +3,10 @@
 // BSD-style license that can be found in the LICENSE file.
 package com.android.tools.r8.shaking.examples;
 
+import static com.android.tools.r8.utils.codeinspector.Matchers.isAbsent;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.Assert.assertTrue;
+
 import com.android.tools.r8.TestParameters;
 import com.android.tools.r8.shaking.TreeShakingTest;
 import com.android.tools.r8.utils.codeinspector.ClassSubject;
@@ -10,7 +14,6 @@
 import com.google.common.collect.ImmutableList;
 import java.util.Collections;
 import java.util.List;
-import org.junit.Assert;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.Parameterized;
@@ -41,7 +44,7 @@
   @Test
   public void testKeeprules() throws Exception {
     runTest(
-        TreeShaking2Test::shaking2SuperClassIsAbstract,
+        TreeShaking2Test::shaking2SuperClassIsRemoved,
         null,
         null,
         ImmutableList.of("src/test/examples/shaking2/keep-rules.txt"));
@@ -62,16 +65,15 @@
         null, null, null, ImmutableList.of("src/test/examples/shaking2/keep-rules-printusage.txt"));
   }
 
-  private static void shaking2SuperClassIsAbstract(CodeInspector inspector) {
+  private static void shaking2SuperClassIsRemoved(CodeInspector inspector) {
     ClassSubject clazz = inspector.clazz("shaking2.SuperClass");
-    Assert.assertTrue(clazz.isAbstract());
-    Assert.assertTrue(clazz.method("void", "virtualMethod", Collections.emptyList()).isAbstract());
-    Assert.assertTrue(
-        clazz
-            .method(
-                "void",
-                "virtualMethod2",
-                ImmutableList.of("int", "int", "int", "int", "int", "int", "int", "int"))
-            .isAbstract());
+    assertTrue(clazz.isAbstract());
+    assertTrue(clazz.method("void", "virtualMethod", Collections.emptyList()).isAbstract());
+    assertThat(
+        clazz.method(
+            "void",
+            "virtualMethod2",
+            ImmutableList.of("int", "int", "int", "int", "int", "int", "int", "int")),
+        isAbsent());
   }
 }
diff --git a/src/test/java/com/android/tools/r8/shaking/keepparameternames/KeepParameterNamesTest.java b/src/test/java/com/android/tools/r8/shaking/keepparameternames/KeepParameterNamesTest.java
index 4740853..4f8131d 100644
--- a/src/test/java/com/android/tools/r8/shaking/keepparameternames/KeepParameterNamesTest.java
+++ b/src/test/java/com/android/tools/r8/shaking/keepparameternames/KeepParameterNamesTest.java
@@ -10,6 +10,7 @@
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 
+import com.android.tools.r8.KeepConstantArguments;
 import com.android.tools.r8.KeepUnusedArguments;
 import com.android.tools.r8.NeverClassInline;
 import com.android.tools.r8.NeverInline;
@@ -173,6 +174,7 @@
         .addInnerClasses(KeepParameterNamesTest.class)
         .addKeepMainRule(TestClass.class)
         .addKeepRules("-keep class " + Api.class.getTypeName() + "{ api*(...); }")
+        .enableConstantArgumentAnnotations()
         .enableInliningAnnotations()
         .enableNeverClassInliningAnnotations()
         .enableUnusedArgumentAnnotations()
@@ -209,6 +211,7 @@
             "In Api.api2",
             "In Api.api3");
     testForR8(parameters.getBackend())
+        .enableConstantArgumentAnnotations()
         .enableNeverClassInliningAnnotations()
         .enableInliningAnnotations()
         .enableUnusedArgumentAnnotations()
@@ -253,6 +256,7 @@
     }
 
     @NeverInline
+    @KeepConstantArguments
     @KeepUnusedArguments
     void api1(int parameter1, String parameter2) {
       try {
@@ -264,12 +268,14 @@
     }
 
     @NeverInline
+    @KeepConstantArguments
     @KeepUnusedArguments
     void api2(long parameter1, double parameter2) {
       System.out.println("In Api.api2");
     }
 
     @NeverInline
+    @KeepConstantArguments
     @KeepUnusedArguments
     void api3(List<String> parameter1, Map<String, Object> parameter2) {
       System.out.println("In Api.api3");
diff --git a/src/test/kotlinR8TestResources/unused_singleton/main.kt b/src/test/kotlinR8TestResources/unused_singleton/main.kt
index 213acb1..6c06b8c 100644
--- a/src/test/kotlinR8TestResources/unused_singleton/main.kt
+++ b/src/test/kotlinR8TestResources/unused_singleton/main.kt
@@ -10,6 +10,6 @@
   fun provideGreeting() = "Hello"
 }
 
-fun main(args: Array<String>) {
+fun main(args: Array<String>?) {
   println(provideGreeting())
 }