Merge "Add support for ReachabilitySensitive annotations."
diff --git a/src/main/java/com/android/tools/r8/utils/BooleanUtils.java b/src/main/java/com/android/tools/r8/utils/BooleanUtils.java
new file mode 100644
index 0000000..bacea6f
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/utils/BooleanUtils.java
@@ -0,0 +1,13 @@
+// Copyright (c) 2018, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+package com.android.tools.r8.utils;
+
+public class BooleanUtils {
+
+  private static final Boolean[] VALUES = new Boolean[] { Boolean.TRUE, Boolean.FALSE };
+
+  public static Boolean[] values() {
+    return VALUES;
+  }
+}
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/B116282409.java b/src/test/java/com/android/tools/r8/ir/optimize/B116282409.java
index 6fe1f16..6008aab 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/B116282409.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/B116282409.java
@@ -19,6 +19,7 @@
 import com.android.tools.r8.jasmin.JasminTestBase;
 import com.android.tools.r8.utils.AbortException;
 import com.android.tools.r8.utils.AndroidApp;
+import com.android.tools.r8.utils.BooleanUtils;
 import com.google.common.collect.ImmutableList;
 import java.util.Arrays;
 import java.util.Collection;
@@ -44,11 +45,7 @@
 
   @Parameters(name = "Backend: {0}, vertical class merging: {1}")
   public static Collection<Object[]> data() {
-    return ImmutableList.of(
-        new Object[] {Backend.CF, false},
-        new Object[] {Backend.CF, true},
-        new Object[] {Backend.DEX, false},
-        new Object[] {Backend.DEX, true});
+    return buildParameters(Backend.values(), BooleanUtils.values());
   }
 
   public B116282409(Backend backend, boolean enableVerticalClassMerging) {
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/R8InliningTest.java b/src/test/java/com/android/tools/r8/ir/optimize/R8InliningTest.java
index e1167b9..c9e5f1e 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/R8InliningTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/R8InliningTest.java
@@ -15,6 +15,7 @@
 import com.android.tools.r8.graph.DexMethod;
 import com.android.tools.r8.origin.Origin;
 import com.android.tools.r8.utils.AndroidApiLevel;
+import com.android.tools.r8.utils.BooleanUtils;
 import com.android.tools.r8.utils.FileUtils;
 import com.android.tools.r8.utils.ZipUtils;
 import com.android.tools.r8.utils.codeinspector.ClassSubject;
@@ -27,7 +28,6 @@
 import java.nio.file.Files;
 import java.nio.file.Path;
 import java.nio.file.Paths;
-import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.Iterator;
@@ -49,15 +49,11 @@
 
   @Parameters(name = "{0}, backend={1}, minification={2}, allowaccessmodification={3}")
   public static Collection<Object[]> data() {
-    List<Object[]> configs = new ArrayList<>();
-    for (Backend backend : Backend.values()) {
-      for (boolean minification : new Boolean[] {false, true}) {
-        for (boolean allowaccessmodification : new Boolean[] {false, true}) {
-          configs.add(new Object[] {"Inlining", backend, minification, allowaccessmodification});
-        }
-      }
-    }
-    return configs;
+    return buildParameters(
+        ImmutableList.of("Inlining"),
+        Backend.values(),
+        BooleanUtils.values(),
+        BooleanUtils.values());
   }
 
   private final String name;
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/reflection/GetNameTestBase.java b/src/test/java/com/android/tools/r8/ir/optimize/reflection/GetNameTestBase.java
index e8ed51f..ef7a07b 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/reflection/GetNameTestBase.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/reflection/GetNameTestBase.java
@@ -5,8 +5,8 @@
 
 import com.android.tools.r8.TestBase;
 import com.android.tools.r8.graph.DexMethod;
+import com.android.tools.r8.utils.BooleanUtils;
 import com.android.tools.r8.utils.codeinspector.MethodSubject;
-import com.google.common.collect.ImmutableList;
 import com.google.common.collect.Streams;
 import java.util.Collection;
 import org.junit.runner.RunWith;
@@ -22,12 +22,7 @@
 
   @Parameterized.Parameters(name = "Backend: {0} minification: {1}")
   public static Collection<Object[]> data() {
-    ImmutableList.Builder<Object[]> builder = new ImmutableList.Builder<>();
-    for (Backend backend : Backend.values()) {
-      builder.add(new Object[]{backend, Boolean.TRUE});
-      builder.add(new Object[]{backend, Boolean.FALSE});
-    }
-    return builder.build();
+    return buildParameters(Backend.values(), BooleanUtils.values());
   }
 
   GetNameTestBase(Backend backend, boolean enableMinification) {
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 c184e6e..0794d92 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
@@ -9,9 +9,14 @@
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
+import static org.junit.Assume.assumeTrue;
 
+import com.android.tools.r8.ForceInline;
+import com.android.tools.r8.NeverInline;
 import com.android.tools.r8.OutputMode;
+import com.android.tools.r8.R8Command;
 import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestRunResult;
 import com.android.tools.r8.ToolHelper;
 import com.android.tools.r8.ToolHelper.ProcessResult;
 import com.android.tools.r8.VmTestRunner;
@@ -36,13 +41,16 @@
 import com.android.tools.r8.ir.optimize.staticizer.trivial.Simple;
 import com.android.tools.r8.ir.optimize.staticizer.trivial.SimpleWithGetter;
 import com.android.tools.r8.ir.optimize.staticizer.trivial.SimpleWithParams;
+import com.android.tools.r8.ir.optimize.staticizer.trivial.SimpleWithPhi;
 import com.android.tools.r8.ir.optimize.staticizer.trivial.SimpleWithSideEffects;
 import com.android.tools.r8.ir.optimize.staticizer.trivial.TrivialTestClass;
 import com.android.tools.r8.naming.MemberNaming.MethodSignature;
+import com.android.tools.r8.origin.Origin;
 import com.android.tools.r8.utils.AndroidApp;
 import com.android.tools.r8.utils.InternalOptions;
 import com.android.tools.r8.utils.codeinspector.ClassSubject;
 import com.android.tools.r8.utils.codeinspector.CodeInspector;
+import com.google.common.collect.ImmutableList;
 import com.google.common.collect.Lists;
 import com.google.common.collect.Streams;
 import java.nio.file.Path;
@@ -50,26 +58,49 @@
 import java.util.stream.Collectors;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
 
-@RunWith(VmTestRunner.class)
+@RunWith(Parameterized.class)
 public class ClassStaticizerTest extends TestBase {
+  private Backend backend;
+
+  @Parameterized.Parameters(name = "Backend: {0}")
+  public static Backend[] data() {
+    return Backend.values();
+  }
+
+  public ClassStaticizerTest(Backend backend) {
+    this.backend = backend;
+  }
+
   @Test
   public void testTrivial() throws Exception {
-    byte[][] classes = {
-        ToolHelper.getClassAsBytes(TrivialTestClass.class),
-        ToolHelper.getClassAsBytes(Simple.class),
-        ToolHelper.getClassAsBytes(SimpleWithSideEffects.class),
-        ToolHelper.getClassAsBytes(SimpleWithParams.class),
-        ToolHelper.getClassAsBytes(SimpleWithGetter.class),
+    assumeTrue("b/112831361", backend == Backend.DEX);
+    Class<?> main = TrivialTestClass.class;
+    Class<?>[] classes = {
+        NeverInline.class,
+        TrivialTestClass.class,
+        Simple.class,
+        SimpleWithSideEffects.class,
+        SimpleWithParams.class,
+        SimpleWithGetter.class,
+        SimpleWithPhi.class,
+        SimpleWithPhi.Companion.class
     };
-    AndroidApp app = runR8(buildAndroidApp(classes), TrivialTestClass.class);
+    String javaOutput = runOnJava(main);
+    TestRunResult result = testForR8(backend)
+        .addProgramClasses(classes)
+        .enableProguardTestOptions()
+        .enableInliningAnnotations()
+        .addKeepMainRule(main)
+        .addKeepRules("-dontobfuscate", "-allowaccessmodification")
+        .addKeepRules("-keepattributes InnerClasses,EnclosingMethod")
+        .addOptionsModification(this::configure)
+        .run(main)
+        .assertSuccessWithOutput(javaOutput);
 
-    String javaOutput = runOnJava(TrivialTestClass.class);
-    String artOutput = runOnArt(app, TrivialTestClass.class);
-    assertEquals(javaOutput, artOutput);
-
-    CodeInspector inspector = new CodeInspector(app);
-    ClassSubject clazz = inspector.clazz(TrivialTestClass.class);
+    CodeInspector inspector = result.inspector();
+    ClassSubject clazz = inspector.clazz(main);
 
     assertEquals(
         Lists.newArrayList(
@@ -82,6 +113,16 @@
 
     assertEquals(
         Lists.newArrayList(
+            "STATIC: String trivial.SimpleWithPhi.bar(String)",
+            "STATIC: String trivial.SimpleWithPhi.foo()",
+            "STATIC: String trivial.SimpleWithPhi.foo()",
+            "STATIC: String trivial.TrivialTestClass.next()"),
+        references(clazz, "testSimpleWithPhi", "void", "int"));
+
+    assertTrue(instanceMethods(inspector.clazz(SimpleWithPhi.class)).isEmpty());
+
+    assertEquals(
+        Lists.newArrayList(
             "STATIC: String trivial.SimpleWithParams.bar(String)",
             "STATIC: String trivial.SimpleWithParams.foo()",
             "STATIC: String trivial.TrivialTestClass.next()"),
@@ -115,25 +156,33 @@
 
   @Test
   public void testMoveToHost() throws Exception {
-    byte[][] classes = {
-        ToolHelper.getClassAsBytes(MoveToHostTestClass.class),
-        ToolHelper.getClassAsBytes(HostOk.class),
-        ToolHelper.getClassAsBytes(CandidateOk.class),
-        ToolHelper.getClassAsBytes(HostOkSideEffects.class),
-        ToolHelper.getClassAsBytes(CandidateOkSideEffects.class),
-        ToolHelper.getClassAsBytes(HostConflictMethod.class),
-        ToolHelper.getClassAsBytes(CandidateConflictMethod.class),
-        ToolHelper.getClassAsBytes(HostConflictField.class),
-        ToolHelper.getClassAsBytes(CandidateConflictField.class),
+    assumeTrue("b/112831361", backend == Backend.DEX);
+    Class<?> main = MoveToHostTestClass.class;
+    Class<?>[] classes = {
+        NeverInline.class,
+        MoveToHostTestClass.class,
+        HostOk.class,
+        CandidateOk.class,
+        HostOkSideEffects.class,
+        CandidateOkSideEffects.class,
+        HostConflictMethod.class,
+        CandidateConflictMethod.class,
+        HostConflictField.class,
+        CandidateConflictField.class
     };
-    AndroidApp app = runR8(buildAndroidApp(classes), MoveToHostTestClass.class);
+    String javaOutput = runOnJava(main);
+    TestRunResult result = testForR8(backend)
+        .addProgramClasses(classes)
+        .enableProguardTestOptions()
+        .enableInliningAnnotations()
+        .addKeepMainRule(main)
+        .addKeepRules("-dontobfuscate", "-allowaccessmodification")
+        .addOptionsModification(this::configure)
+        .run(main)
+        .assertSuccessWithOutput(javaOutput);
 
-    String javaOutput = runOnJava(MoveToHostTestClass.class);
-    String artOutput = runOnArt(app, MoveToHostTestClass.class);
-    assertEquals(javaOutput, artOutput);
-
-    CodeInspector inspector = new CodeInspector(app);
-    ClassSubject clazz = inspector.clazz(MoveToHostTestClass.class);
+    CodeInspector inspector = result.inspector();
+    ClassSubject clazz = inspector.clazz(main);
 
     assertEquals(
         Lists.newArrayList(
@@ -232,40 +281,6 @@
     return type.toSourceString().startsWith("com.android.tools.r8.ir.optimize.staticizer");
   }
 
-  private AndroidApp runR8(AndroidApp app, Class mainClass) throws Exception {
-    AndroidApp compiled =
-        compileWithR8(app, getProguardConfig(mainClass.getCanonicalName()), this::configure);
-
-    // Materialize file for execution.
-    Path generatedDexFile = temp.getRoot().toPath().resolve("classes.jar");
-    compiled.writeToZip(generatedDexFile, OutputMode.DexIndexed);
-
-    // Run with ART.
-    String artOutput = ToolHelper.runArtNoVerificationErrors(
-        generatedDexFile.toString(), mainClass.getCanonicalName());
-
-    // Compare with Java.
-    ProcessResult javaResult = ToolHelper.runJava(
-        ToolHelper.getClassPathForTests(), mainClass.getCanonicalName());
-
-    if (javaResult.exitCode != 0) {
-      System.out.println(javaResult.stdout);
-      System.err.println(javaResult.stderr);
-      fail("JVM failed for: " + mainClass);
-    }
-    assertEquals("JVM and ART output differ", javaResult.stdout, artOutput);
-
-    return compiled;
-  }
-
-  private String getProguardConfig(String main) {
-    return keepMainProguardConfiguration(main)
-        + System.lineSeparator()
-        + "-dontobfuscate"
-        + System.lineSeparator()
-        + "-allowaccessmodification";
-  }
-
   private void configure(InternalOptions options) {
     options.enableClassInlining = false;
   }
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/staticizer/movetohost/CandidateConflictField.java b/src/test/java/com/android/tools/r8/ir/optimize/staticizer/movetohost/CandidateConflictField.java
index f2108b0..82eef8e 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/staticizer/movetohost/CandidateConflictField.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/staticizer/movetohost/CandidateConflictField.java
@@ -4,18 +4,18 @@
 
 package com.android.tools.r8.ir.optimize.staticizer.movetohost;
 
+import com.android.tools.r8.NeverInline;
+
 public class CandidateConflictField {
   public static String field;
 
+  @NeverInline
   public String foo() {
-    synchronized ("") {
-      return bar("CandidateConflictMethod::foo()");
-    }
+    return bar("CandidateConflictMethod::foo()");
   }
 
+  @NeverInline
   public String bar(String other) {
-    synchronized ("") {
-      return "CandidateConflictMethod::bar(" + other + ")";
-    }
+    return "CandidateConflictMethod::bar(" + other + ")";
   }
 }
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/staticizer/movetohost/CandidateConflictMethod.java b/src/test/java/com/android/tools/r8/ir/optimize/staticizer/movetohost/CandidateConflictMethod.java
index 40d0576..4e5ce3a 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/staticizer/movetohost/CandidateConflictMethod.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/staticizer/movetohost/CandidateConflictMethod.java
@@ -4,16 +4,16 @@
 
 package com.android.tools.r8.ir.optimize.staticizer.movetohost;
 
+import com.android.tools.r8.NeverInline;
+
 public class CandidateConflictMethod {
+  @NeverInline
   public String foo() {
-    synchronized ("") {
-      return bar("CandidateConflictMethod::foo()");
-    }
+    return bar("CandidateConflictMethod::foo()");
   }
 
+  @NeverInline
   public String bar(String other) {
-    synchronized ("") {
-      return "CandidateConflictMethod::bar(" + other + ")";
-    }
+    return "CandidateConflictMethod::bar(" + other + ")";
   }
 }
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/staticizer/movetohost/CandidateOk.java b/src/test/java/com/android/tools/r8/ir/optimize/staticizer/movetohost/CandidateOk.java
index daf5647..0834c000 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/staticizer/movetohost/CandidateOk.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/staticizer/movetohost/CandidateOk.java
@@ -4,22 +4,21 @@
 
 package com.android.tools.r8.ir.optimize.staticizer.movetohost;
 
+import com.android.tools.r8.NeverInline;
+
 public class CandidateOk {
+  @NeverInline
   public String foo() {
-    synchronized ("") {
-      return bar("CandidateOk::foo()");
-    }
+    return bar("CandidateOk::foo()");
   }
 
+  @NeverInline
   public String bar(String other) {
-    synchronized ("") {
-      return "CandidateOk::bar(" + other + ")";
-    }
+    return "CandidateOk::bar(" + other + ")";
   }
 
+  @NeverInline
   public void blah(String other) {
-    synchronized ("") {
-      System.out.println("CandidateOk::blah(" + other + ")");
-    }
+    System.out.println("CandidateOk::blah(" + other + ")");
   }
 }
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/staticizer/movetohost/CandidateOkSideEffects.java b/src/test/java/com/android/tools/r8/ir/optimize/staticizer/movetohost/CandidateOkSideEffects.java
index 2077056..a02bed3 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/staticizer/movetohost/CandidateOkSideEffects.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/staticizer/movetohost/CandidateOkSideEffects.java
@@ -4,16 +4,16 @@
 
 package com.android.tools.r8.ir.optimize.staticizer.movetohost;
 
+import com.android.tools.r8.NeverInline;
+
 public class CandidateOkSideEffects {
+  @NeverInline
   public String foo() {
-    synchronized ("") {
-      return bar("CandidateOkSideEffects::foo()");
-    }
+    return bar("CandidateOkSideEffects::foo()");
   }
 
+  @NeverInline
   public String bar(String other) {
-    synchronized ("") {
-      return "CandidateOkSideEffects::bar(" + other + ")";
-    }
+    return "CandidateOkSideEffects::bar(" + other + ")";
   }
 }
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/staticizer/movetohost/HostConflictMethod.java b/src/test/java/com/android/tools/r8/ir/optimize/staticizer/movetohost/HostConflictMethod.java
index ad86b35..8804e14 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/staticizer/movetohost/HostConflictMethod.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/staticizer/movetohost/HostConflictMethod.java
@@ -4,12 +4,13 @@
 
 package com.android.tools.r8.ir.optimize.staticizer.movetohost;
 
+import com.android.tools.r8.NeverInline;
+
 public class HostConflictMethod {
   static CandidateConflictMethod INSTANCE = new CandidateConflictMethod();
 
+  @NeverInline
   public String bar(String other) {
-    synchronized ("") {
-      return "HostConflictMethod::bar(" + other + ")";
-    }
+    return "HostConflictMethod::bar(" + other + ")";
   }
 }
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/staticizer/movetohost/MoveToHostTestClass.java b/src/test/java/com/android/tools/r8/ir/optimize/staticizer/movetohost/MoveToHostTestClass.java
index 3f31839..3be6e5f 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/staticizer/movetohost/MoveToHostTestClass.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/staticizer/movetohost/MoveToHostTestClass.java
@@ -4,6 +4,8 @@
 
 package com.android.tools.r8.ir.optimize.staticizer.movetohost;
 
+import com.android.tools.r8.NeverInline;
+
 public class MoveToHostTestClass {
   private static int ID = 0;
 
@@ -19,24 +21,28 @@
     test.testConflictField();
   }
 
-  private synchronized void testOk() {
+  @NeverInline
+  private void testOk() {
     System.out.println(HostOk.INSTANCE.foo());
     System.out.println(HostOk.INSTANCE.bar(next()));
     HostOk.INSTANCE.blah(next());
   }
 
-  private synchronized void testOkSideEffects() {
+  @NeverInline
+  private void testOkSideEffects() {
     System.out.println(HostOkSideEffects.INSTANCE.foo());
     System.out.println(HostOkSideEffects.INSTANCE.bar(next()));
   }
 
-  private synchronized void testConflictMethod() {
+  @NeverInline
+  private void testConflictMethod() {
     System.out.println(new HostConflictMethod().bar(next()));
     System.out.println(HostConflictMethod.INSTANCE.foo());
     System.out.println(HostConflictMethod.INSTANCE.bar(next()));
   }
 
-  private synchronized void testConflictField() {
+  @NeverInline
+  private void testConflictField() {
     System.out.println(new HostConflictField().field);
     System.out.println(CandidateConflictField.field);
     System.out.println(HostConflictField.INSTANCE.foo());
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/staticizer/trivial/Simple.java b/src/test/java/com/android/tools/r8/ir/optimize/staticizer/trivial/Simple.java
index 8df079c..3cb1c49 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/staticizer/trivial/Simple.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/staticizer/trivial/Simple.java
@@ -4,18 +4,18 @@
 
 package com.android.tools.r8.ir.optimize.staticizer.trivial;
 
+import com.android.tools.r8.NeverInline;
+
 public class Simple {
   static Simple INSTANCE = new Simple();
 
+  @NeverInline
   String foo() {
-    synchronized ("") {
-      return bar("Simple::foo()");
-    }
+    return bar("Simple::foo()");
   }
 
+  @NeverInline
   String bar(String other) {
-    synchronized ("") {
-      return "Simple::bar(" + other + ")";
-    }
+    return "Simple::bar(" + other + ")";
   }
 }
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/staticizer/trivial/SimpleWithGetter.java b/src/test/java/com/android/tools/r8/ir/optimize/staticizer/trivial/SimpleWithGetter.java
index 9ff20c3..55487ac 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/staticizer/trivial/SimpleWithGetter.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/staticizer/trivial/SimpleWithGetter.java
@@ -4,6 +4,8 @@
 
 package com.android.tools.r8.ir.optimize.staticizer.trivial;
 
+import com.android.tools.r8.NeverInline;
+
 public class SimpleWithGetter {
   private static SimpleWithGetter INSTANCE = new SimpleWithGetter();
 
@@ -11,15 +13,13 @@
     return INSTANCE;
   }
 
+  @NeverInline
   String foo() {
-    synchronized ("") {
-      return bar("Simple::foo()");
-    }
+    return bar("Simple::foo()");
   }
 
+  @NeverInline
   String bar(String other) {
-    synchronized ("") {
-      return "Simple::bar(" + other + ")";
-    }
+    return "Simple::bar(" + other + ")";
   }
 }
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/staticizer/trivial/SimpleWithParams.java b/src/test/java/com/android/tools/r8/ir/optimize/staticizer/trivial/SimpleWithParams.java
index a71f1f5..24edea4 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/staticizer/trivial/SimpleWithParams.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/staticizer/trivial/SimpleWithParams.java
@@ -4,21 +4,21 @@
 
 package com.android.tools.r8.ir.optimize.staticizer.trivial;
 
+import com.android.tools.r8.NeverInline;
+
 public class SimpleWithParams {
   static SimpleWithParams INSTANCE = new SimpleWithParams(123);
 
   SimpleWithParams(int i) {
   }
 
+  @NeverInline
   String foo() {
-    synchronized ("") {
-      return bar("SimpleWithParams::foo()");
-    }
+    return bar("SimpleWithParams::foo()");
   }
 
+  @NeverInline
   String bar(String other) {
-    synchronized ("") {
-      return "SimpleWithParams::bar(" + other + ")";
-    }
+    return "SimpleWithParams::bar(" + other + ")";
   }
 }
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/staticizer/trivial/SimpleWithPhi.java b/src/test/java/com/android/tools/r8/ir/optimize/staticizer/trivial/SimpleWithPhi.java
new file mode 100644
index 0000000..f3c76cb
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/ir/optimize/staticizer/trivial/SimpleWithPhi.java
@@ -0,0 +1,36 @@
+// Copyright (c) 2018, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+package com.android.tools.r8.ir.optimize.staticizer.trivial;
+
+import com.android.tools.r8.NeverInline;
+
+public class SimpleWithPhi {
+  public static class Companion {
+    @NeverInline
+    String foo() {
+      return bar("SimpleWithPhi$Companion::foo()");
+    }
+
+    @NeverInline
+    String bar(String other) {
+      return "SimpleWithPhi$Companion::bar(" + other + ")";
+    }
+  }
+
+  static Companion INSTANCE = new Companion();
+
+  @NeverInline
+  static String foo() {
+    return INSTANCE.foo();
+  }
+
+  @NeverInline
+  static String bar(String other) {
+    if (other.length() > 2) {
+      return INSTANCE.foo();
+    } else {
+      return INSTANCE.bar(other);
+    }
+  }
+}
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/staticizer/trivial/SimpleWithSideEffects.java b/src/test/java/com/android/tools/r8/ir/optimize/staticizer/trivial/SimpleWithSideEffects.java
index 5ba97dc..2ee78f5 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/staticizer/trivial/SimpleWithSideEffects.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/staticizer/trivial/SimpleWithSideEffects.java
@@ -4,6 +4,8 @@
 
 package com.android.tools.r8.ir.optimize.staticizer.trivial;
 
+import com.android.tools.r8.NeverInline;
+
 public class SimpleWithSideEffects {
   static SimpleWithSideEffects INSTANCE = new SimpleWithSideEffects();
 
@@ -11,15 +13,13 @@
     System.out.println("SimpleWithSideEffects::<clinit>()");
   }
 
+  @NeverInline
   String foo() {
-    synchronized ("") {
-      return bar("SimpleWithSideEffects::foo()");
-    }
+    return bar("SimpleWithSideEffects::foo()");
   }
 
+  @NeverInline
   String bar(String other) {
-    synchronized ("") {
-      return "SimpleWithSideEffects::bar(" + other + ")";
-    }
+    return "SimpleWithSideEffects::bar(" + other + ")";
   }
 }
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/staticizer/trivial/TrivialTestClass.java b/src/test/java/com/android/tools/r8/ir/optimize/staticizer/trivial/TrivialTestClass.java
index 2dad273..964567c 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/staticizer/trivial/TrivialTestClass.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/staticizer/trivial/TrivialTestClass.java
@@ -4,6 +4,8 @@
 
 package com.android.tools.r8.ir.optimize.staticizer.trivial;
 
+import com.android.tools.r8.NeverInline;
+
 public class TrivialTestClass {
   private static int ID = 0;
 
@@ -14,27 +16,47 @@
   public static void main(String[] args) {
     TrivialTestClass test = new TrivialTestClass();
     test.testSimple();
+    test.testSimpleWithPhi(args.length);
     test.testSimpleWithSideEffects();
     test.testSimpleWithParams();
     test.testSimpleWithGetter();
   }
 
-  private synchronized void testSimple() {
+  @NeverInline
+  private void testSimple() {
     System.out.println(Simple.INSTANCE.foo());
     System.out.println(Simple.INSTANCE.bar(next()));
   }
 
-  private synchronized void testSimpleWithSideEffects() {
+  @NeverInline
+  private void testSimpleWithPhi(int arg) {
+    switch (arg) {
+      case 0:
+        System.out.println(SimpleWithPhi.foo() + " " + true);
+        break;
+      case 2:
+        System.out.println(SimpleWithPhi.foo() + " " + false);
+        break;
+      default:
+        System.out.println(SimpleWithPhi.bar(next()));
+        break;
+    }
+  }
+
+  @NeverInline
+  private void testSimpleWithSideEffects() {
     System.out.println(SimpleWithSideEffects.INSTANCE.foo());
     System.out.println(SimpleWithSideEffects.INSTANCE.bar(next()));
   }
 
-  private synchronized void testSimpleWithParams() {
+  @NeverInline
+  private void testSimpleWithParams() {
     System.out.println(SimpleWithParams.INSTANCE.foo());
     System.out.println(SimpleWithParams.INSTANCE.bar(next()));
   }
 
-  private synchronized void testSimpleWithGetter() {
+  @NeverInline
+  private void testSimpleWithGetter() {
     System.out.println(SimpleWithGetter.getInstance().foo());
     System.out.println(SimpleWithGetter.getInstance().bar(next()));
   }
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 b76e947..9380115 100644
--- a/src/test/java/com/android/tools/r8/kotlin/AbstractR8KotlinTestBase.java
+++ b/src/test/java/com/android/tools/r8/kotlin/AbstractR8KotlinTestBase.java
@@ -22,6 +22,7 @@
 import com.android.tools.r8.naming.MemberNaming.MethodSignature;
 import com.android.tools.r8.origin.Origin;
 import com.android.tools.r8.utils.AndroidApp;
+import com.android.tools.r8.utils.BooleanUtils;
 import com.android.tools.r8.utils.DescriptorUtils;
 import com.android.tools.r8.utils.FileUtils;
 import com.android.tools.r8.utils.InternalOptions;
@@ -59,12 +60,7 @@
 
   @Parameters(name = "allowAccessModification: {0} target: {1}")
   public static Collection<Object[]> data() {
-    ImmutableList.Builder<Object[]> builder = new ImmutableList.Builder<>();
-    for (KotlinTargetVersion targetVersion : KotlinTargetVersion.values()) {
-      builder.add(new Object[]{Boolean.TRUE, targetVersion});
-      builder.add(new Object[]{Boolean.FALSE, targetVersion});
-    }
-    return builder.build();
+    return buildParameters(BooleanUtils.values(), KotlinTargetVersion.values());
   }
 
   protected void addExtraClasspath(Path path) {
diff --git a/src/test/java/com/android/tools/r8/kotlin/KotlinClassInlinerTest.java b/src/test/java/com/android/tools/r8/kotlin/KotlinClassInlinerTest.java
index 7d73d8f..1d3f25e 100644
--- a/src/test/java/com/android/tools/r8/kotlin/KotlinClassInlinerTest.java
+++ b/src/test/java/com/android/tools/r8/kotlin/KotlinClassInlinerTest.java
@@ -8,8 +8,8 @@
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
+import static org.junit.Assume.assumeTrue;
 
-import com.android.tools.r8.ToolHelper.KotlinTargetVersion;
 import com.android.tools.r8.code.NewInstance;
 import com.android.tools.r8.code.SgetObject;
 import com.android.tools.r8.graph.DexClass;
@@ -20,28 +20,17 @@
 import com.android.tools.r8.utils.codeinspector.CodeInspector;
 import com.android.tools.r8.utils.codeinspector.InstructionSubject;
 import com.android.tools.r8.utils.codeinspector.MethodSubject;
-import com.google.common.collect.ImmutableList;
 import com.google.common.collect.Lists;
 import com.google.common.collect.Sets;
 import com.google.common.collect.Streams;
-import java.util.Collection;
 import java.util.List;
 import java.util.Set;
 import java.util.function.Predicate;
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
 import org.junit.Test;
-import org.junit.runners.Parameterized.Parameters;
 
 public class KotlinClassInlinerTest extends AbstractR8KotlinTestBase {
-  @Parameters(name = "allowAccessModification: {0} target: {1}")
-  public static Collection<Object[]> data() {
-    ImmutableList.Builder<Object[]> builder = new ImmutableList.Builder<>();
-    for (KotlinTargetVersion targetVersion : KotlinTargetVersion.values()) {
-      builder.add(new Object[]{Boolean.TRUE, targetVersion});
-    }
-    return builder.build();
-  }
 
   private static boolean isLambda(DexClass clazz) {
     return !clazz.type.getPackageDescriptor().startsWith("kotlin") &&
@@ -67,6 +56,7 @@
 
   @Test
   public void testJStyleLambdas() throws Exception {
+    assumeTrue("Only work with -allowaccessmodification", allowAccessModification);
     final String mainClassName = "class_inliner_lambda_j_style.MainKt";
     runTest("class_inliner_lambda_j_style", mainClassName, false, (app) -> {
       CodeInspector inspector = new CodeInspector(app);
@@ -112,6 +102,7 @@
 
   @Test
   public void testKStyleLambdas() throws Exception {
+    assumeTrue("Only work with -allowaccessmodification", allowAccessModification);
     final String mainClassName = "class_inliner_lambda_k_style.MainKt";
     runTest("class_inliner_lambda_k_style", mainClassName, false, (app) -> {
       CodeInspector inspector = new CodeInspector(app);
@@ -186,6 +177,7 @@
 
   @Test
   public void testDataClass() throws Exception {
+    assumeTrue("Only work with -allowaccessmodification", allowAccessModification);
     final String mainClassName = "class_inliner_data_class.MainKt";
     runTest("class_inliner_data_class", mainClassName, true, (app) -> {
       CodeInspector inspector = new CodeInspector(app);
diff --git a/src/test/java/com/android/tools/r8/kotlin/KotlinClassStaticizerTest.java b/src/test/java/com/android/tools/r8/kotlin/KotlinClassStaticizerTest.java
index c19b80e..ced08f5 100644
--- a/src/test/java/com/android/tools/r8/kotlin/KotlinClassStaticizerTest.java
+++ b/src/test/java/com/android/tools/r8/kotlin/KotlinClassStaticizerTest.java
@@ -7,28 +7,18 @@
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
+import static org.junit.Assume.assumeTrue;
 
-import com.android.tools.r8.ToolHelper.KotlinTargetVersion;
 import com.android.tools.r8.utils.codeinspector.ClassSubject;
 import com.android.tools.r8.utils.codeinspector.CodeInspector;
-import com.google.common.collect.ImmutableList;
-import java.util.Collection;
 import java.util.concurrent.atomic.AtomicInteger;
 import org.junit.Test;
-import org.junit.runners.Parameterized.Parameters;
 
 public class KotlinClassStaticizerTest extends AbstractR8KotlinTestBase {
-  @Parameters(name = "allowAccessModification: {0} target: {1}")
-  public static Collection<Object[]> data() {
-    ImmutableList.Builder<Object[]> builder = new ImmutableList.Builder<>();
-    for (KotlinTargetVersion targetVersion : KotlinTargetVersion.values()) {
-      builder.add(new Object[]{Boolean.TRUE, targetVersion});
-    }
-    return builder.build();
-  }
 
   @Test
   public void testCompanionAndRegularObjects() throws Exception {
+    assumeTrue("Only work with -allowaccessmodification", allowAccessModification);
     final String mainClassName = "class_staticizer.MainKt";
 
     // Without class staticizer.
diff --git a/src/test/java/com/android/tools/r8/kotlin/MetadataStripTest.java b/src/test/java/com/android/tools/r8/kotlin/MetadataStripTest.java
index 2abc1ed..1ab3147 100644
--- a/src/test/java/com/android/tools/r8/kotlin/MetadataStripTest.java
+++ b/src/test/java/com/android/tools/r8/kotlin/MetadataStripTest.java
@@ -47,13 +47,7 @@
 
   @Parameterized.Parameters(name = "Backend: {0} target: {1}")
   public static Collection<Object[]> data() {
-    ImmutableList.Builder<Object[]> builder = new ImmutableList.Builder<>();
-    for (Backend backend : Backend.values()) {
-      for (KotlinTargetVersion targetVersion : KotlinTargetVersion.values()) {
-        builder.add(new Object[]{backend, targetVersion});
-      }
-    }
-    return builder.build();
+    return buildParameters(Backend.values(), KotlinTargetVersion.values());
   }
 
   public MetadataStripTest(Backend backend, KotlinTargetVersion targetVersion) {
diff --git a/src/test/java/com/android/tools/r8/naming/b114554345/B114554345.java b/src/test/java/com/android/tools/r8/naming/b114554345/B114554345.java
index 5e9b9c8..0d2ab3a 100644
--- a/src/test/java/com/android/tools/r8/naming/b114554345/B114554345.java
+++ b/src/test/java/com/android/tools/r8/naming/b114554345/B114554345.java
@@ -9,9 +9,6 @@
 import com.android.tools.r8.TestBase;
 import com.android.tools.r8.ToolHelper;
 import com.android.tools.r8.utils.AndroidApp;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.Parameterized;
@@ -22,13 +19,9 @@
 
   private final Backend backend;
 
-  @Parameters(name = "mode:{0}")
-  public static Collection<Object[]> data() {
-    List<Object[]> parameters = new ArrayList<>();
-    for (Backend backend : Backend.values()) {
-      parameters.add(new Object[] {backend});
-    }
-    return parameters;
+  @Parameters(name = "backend: {0}")
+  public static Backend[] data() {
+    return Backend.values();
   }
 
   public B114554345(Backend backend) {
diff --git a/src/test/java/com/android/tools/r8/naming/retrace/RetraceTest.java b/src/test/java/com/android/tools/r8/naming/retrace/RetraceTest.java
index e1c61c1..b110ead 100644
--- a/src/test/java/com/android/tools/r8/naming/retrace/RetraceTest.java
+++ b/src/test/java/com/android/tools/r8/naming/retrace/RetraceTest.java
@@ -22,7 +22,6 @@
 import com.google.common.collect.ImmutableList;
 import java.io.IOException;
 import java.nio.file.Path;
-import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Iterator;
 import java.util.List;
@@ -39,13 +38,7 @@
 
   @Parameters(name = "Backend: {0}, mode: {1}")
   public static Collection<Object[]> data() {
-    List<Object[]> parameters = new ArrayList<>();
-    for (Backend backend : Backend.values()) {
-      for (CompilationMode mode : CompilationMode.values()) {
-        parameters.add(new Object[] {backend, mode});
-      }
-    }
-    return parameters;
+    return buildParameters(Backend.values(), CompilationMode.values());
   }
 
   public RetraceTest(Backend backend, CompilationMode mode) {
diff --git a/src/test/java/com/android/tools/r8/resource/KeepDirectoriesTest.java b/src/test/java/com/android/tools/r8/resource/KeepDirectoriesTest.java
index daf0bc2..ba79ec5 100644
--- a/src/test/java/com/android/tools/r8/resource/KeepDirectoriesTest.java
+++ b/src/test/java/com/android/tools/r8/resource/KeepDirectoriesTest.java
@@ -21,9 +21,9 @@
 import com.android.tools.r8.origin.Origin;
 import com.android.tools.r8.shaking.forceproguardcompatibility.ProguardCompatibilityTestBase;
 import com.android.tools.r8.utils.AndroidApp;
+import com.android.tools.r8.utils.BooleanUtils;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.Sets;
-import java.util.ArrayList;
 import java.util.Collection;
 import java.util.List;
 import java.util.Set;
@@ -50,13 +50,7 @@
 
   @Parameterized.Parameters(name = "Backend: {0}, Minify: {1}")
   public static Collection<Object[]> data() {
-    List<Object[]> result = new ArrayList<>();
-    for (Backend backend : Backend.values()) {
-      for (boolean minify : new boolean[] {false, true}) {
-        result.add(new Object[] {backend, minify});
-      }
-    }
-    return result;
+    return buildParameters(Backend.values(), BooleanUtils.values());
   }
 
   public KeepDirectoriesTest(Backend backend, boolean minify) {
diff --git a/src/test/java/com/android/tools/r8/shaking/AtomicFieldUpdaterTest.java b/src/test/java/com/android/tools/r8/shaking/AtomicFieldUpdaterTest.java
index 7e262ee..8dcdd38 100644
--- a/src/test/java/com/android/tools/r8/shaking/AtomicFieldUpdaterTest.java
+++ b/src/test/java/com/android/tools/r8/shaking/AtomicFieldUpdaterTest.java
@@ -15,9 +15,6 @@
 import com.android.tools.r8.utils.codeinspector.CodeInspector;
 import java.io.File;
 import java.nio.file.Path;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
 import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -29,13 +26,9 @@
 
   private final Backend backend;
 
-  @Parameters(name = "mode:{0}")
-  public static Collection<Object[]> data() {
-    List<Object[]> parameters = new ArrayList<>();
-    for (Backend backend : Backend.values()) {
-      parameters.add(new Object[] {backend});
-    }
-    return parameters;
+  @Parameters(name = "backend: {0}")
+  public static Backend[] data() {
+    return Backend.values();
   }
 
   public AtomicFieldUpdaterTest(Backend backend) {
diff --git a/src/test/java/com/android/tools/r8/shaking/ClassKindTest.java b/src/test/java/com/android/tools/r8/shaking/ClassKindTest.java
index 89cbbbe..5eba7b5 100644
--- a/src/test/java/com/android/tools/r8/shaking/ClassKindTest.java
+++ b/src/test/java/com/android/tools/r8/shaking/ClassKindTest.java
@@ -33,7 +33,7 @@
   }
 
   @Parameters(name = "{0}")
-  public static Collection<Object[]> paramters() {
+  public static Collection<Object[]> parameters() {
     return ImmutableList.copyOf(new Object[][]{
         {"-keep interface *", ImmutableList.of(Interface.class)},
         {"-keep class *", CLASSES_TO_INCLUDE},
diff --git a/src/test/java/com/android/tools/r8/shaking/EnclosingMethodTest.java b/src/test/java/com/android/tools/r8/shaking/EnclosingMethodTest.java
index bebe66f..afc319a 100644
--- a/src/test/java/com/android/tools/r8/shaking/EnclosingMethodTest.java
+++ b/src/test/java/com/android/tools/r8/shaking/EnclosingMethodTest.java
@@ -8,6 +8,7 @@
 import com.android.tools.r8.R8TestBuilder;
 import com.android.tools.r8.TestBase;
 import com.android.tools.r8.ToolHelper;
+import com.android.tools.r8.utils.BooleanUtils;
 import com.google.common.collect.ImmutableList;
 import java.nio.file.Path;
 import java.util.Collection;
@@ -48,12 +49,7 @@
 
   @Parameterized.Parameters(name = "Backend: {0} minification: {1}")
   public static Collection<Object[]> data() {
-    ImmutableList.Builder<Object[]> builder = new ImmutableList.Builder<>();
-    for (Backend backend : Backend.values()) {
-      builder.add(new Object[]{backend, Boolean.TRUE});
-      builder.add(new Object[]{backend, Boolean.FALSE});
-    }
-    return builder.build();
+    return buildParameters(Backend.values(), BooleanUtils.values());
   }
 
   public EnclosingMethodTest(Backend backend, boolean enableMinification) throws Exception {
diff --git a/src/test/java/com/android/tools/r8/shaking/NonVirtualOverrideTest.java b/src/test/java/com/android/tools/r8/shaking/NonVirtualOverrideTest.java
index 2490d41..4be2aaf 100644
--- a/src/test/java/com/android/tools/r8/shaking/NonVirtualOverrideTest.java
+++ b/src/test/java/com/android/tools/r8/shaking/NonVirtualOverrideTest.java
@@ -20,6 +20,7 @@
 import com.android.tools.r8.jasmin.JasminBuilder;
 import com.android.tools.r8.jasmin.JasminBuilder.ClassBuilder;
 import com.android.tools.r8.utils.AndroidApp;
+import com.android.tools.r8.utils.BooleanUtils;
 import com.android.tools.r8.utils.DescriptorUtils;
 import com.android.tools.r8.utils.codeinspector.ClassSubject;
 import com.android.tools.r8.utils.codeinspector.CodeInspector;
@@ -45,15 +46,7 @@
 
   @Parameterized.Parameters(name = "Backend: {0}, class inlining: {1}, vertical class merging: {2}")
   public static Collection<Object[]> data() {
-    ImmutableList.Builder<Object[]> builder = ImmutableList.builder();
-    for (Backend backend : Backend.values()) {
-      for (boolean enableClassInlining : ImmutableList.of(true, false)) {
-        for (boolean enableVerticalClassMerging : ImmutableList.of(true, false)) {
-          builder.add(new Object[] {backend, enableClassInlining, enableVerticalClassMerging});
-        }
-      }
-    }
-    return builder.build();
+    return buildParameters(Backend.values(), BooleanUtils.values(), BooleanUtils.values());
   }
 
   public NonVirtualOverrideTest(
diff --git a/src/test/java/com/android/tools/r8/shaking/PrintUsageTest.java b/src/test/java/com/android/tools/r8/shaking/PrintUsageTest.java
index 3b5a830..e5f3517 100644
--- a/src/test/java/com/android/tools/r8/shaking/PrintUsageTest.java
+++ b/src/test/java/com/android/tools/r8/shaking/PrintUsageTest.java
@@ -8,6 +8,7 @@
 
 import com.android.tools.r8.OutputMode;
 import com.android.tools.r8.R8Command;
+import com.android.tools.r8.TestBase;
 import com.android.tools.r8.ToolHelper;
 import com.android.tools.r8.shaking.PrintUsageTest.PrintUsageInspector.ClassSubject;
 import com.android.tools.r8.utils.ListUtils;
@@ -39,12 +40,7 @@
 import org.junit.runners.Parameterized.Parameters;
 
 @RunWith(Parameterized.class)
-public class PrintUsageTest {
-
-  private enum Backend {
-    CF,
-    DEX
-  }
+public class PrintUsageTest extends TestBase {
 
   private static final String PRINT_USAGE_FILE_SUFFIX = "-print-usage.txt";
 
diff --git a/src/test/java/com/android/tools/r8/shaking/TreeShakingTest.java b/src/test/java/com/android/tools/r8/shaking/TreeShakingTest.java
index c268023..b302615 100644
--- a/src/test/java/com/android/tools/r8/shaking/TreeShakingTest.java
+++ b/src/test/java/com/android/tools/r8/shaking/TreeShakingTest.java
@@ -7,7 +7,7 @@
 
 import com.android.tools.r8.OutputMode;
 import com.android.tools.r8.R8Command;
-import com.android.tools.r8.TestBase.MinifyMode;
+import com.android.tools.r8.TestBase;
 import com.android.tools.r8.ToolHelper;
 import com.android.tools.r8.ToolHelper.ArtCommandBuilder;
 import com.android.tools.r8.ToolHelper.ProcessResult;
@@ -44,7 +44,7 @@
  * that calls {@link TreeShakingTest::runTest}, passing in the path to your keep rule file and
  * lambdas to determine if the right bits of the application are kept or discarded.
  */
-public abstract class TreeShakingTest {
+public abstract class TreeShakingTest extends TestBase {
 
   private Path proguardMap;
   private Path out;
@@ -53,10 +53,6 @@
     DEX, JAR
   }
 
-  protected enum Backend {
-    DEX, CF
-  }
-
   private final String name;
   private final String mainClass;
   private final Frontend frontend;
diff --git a/src/test/java/com/android/tools/r8/shaking/ifrule/inlining/IfRuleWithInlining.java b/src/test/java/com/android/tools/r8/shaking/ifrule/inlining/IfRuleWithInlining.java
index de981ae..6aa68de 100644
--- a/src/test/java/com/android/tools/r8/shaking/ifrule/inlining/IfRuleWithInlining.java
+++ b/src/test/java/com/android/tools/r8/shaking/ifrule/inlining/IfRuleWithInlining.java
@@ -13,6 +13,7 @@
 import com.android.tools.r8.ToolHelper.ProcessResult;
 import com.android.tools.r8.shaking.forceproguardcompatibility.ProguardCompatibilityTestBase;
 import com.android.tools.r8.utils.AndroidApp;
+import com.android.tools.r8.utils.BooleanUtils;
 import com.android.tools.r8.utils.codeinspector.ClassSubject;
 import com.android.tools.r8.utils.codeinspector.CodeInspector;
 import com.google.common.collect.ImmutableList;
@@ -61,11 +62,8 @@
   @Parameters(name = "shrinker: {0} neverInlineMethod: {1}")
   public static Collection<Object[]> data() {
     // We don't run this on Proguard, as triggering inlining in Proguard is out of our control.
-    return ImmutableList.of(
-        new Object[] {Shrinker.R8, true},
-        new Object[] {Shrinker.R8, false},
-        new Object[] {Shrinker.R8_CF, true},
-        new Object[] {Shrinker.R8_CF, false});
+    return buildParameters(
+        ImmutableList.of(Shrinker.R8, Shrinker.R8_CF), BooleanUtils.values());
   }
 
   private void check(AndroidApp app) throws Exception {
diff --git a/src/test/java/com/android/tools/r8/shaking/ifrule/verticalclassmerging/IfRuleWithVerticalClassMerging.java b/src/test/java/com/android/tools/r8/shaking/ifrule/verticalclassmerging/IfRuleWithVerticalClassMerging.java
index f470aab..2d9027d 100644
--- a/src/test/java/com/android/tools/r8/shaking/ifrule/verticalclassmerging/IfRuleWithVerticalClassMerging.java
+++ b/src/test/java/com/android/tools/r8/shaking/ifrule/verticalclassmerging/IfRuleWithVerticalClassMerging.java
@@ -10,6 +10,7 @@
 
 import com.android.tools.r8.NeverClassInline;
 import com.android.tools.r8.TestBase;
+import com.android.tools.r8.utils.BooleanUtils;
 import com.android.tools.r8.utils.InternalOptions;
 import com.android.tools.r8.utils.StringUtils;
 import com.android.tools.r8.utils.codeinspector.ClassSubject;
@@ -77,11 +78,7 @@
   @Parameters(name = "Backend: {0}, vertical class merging: {1}")
   public static Collection<Object[]> data() {
     // We don't run this on Proguard, as Proguard does not merge A into B.
-    return ImmutableList.of(
-        new Object[] {Backend.DEX, true},
-        new Object[] {Backend.DEX, false},
-        new Object[] {Backend.CF, true},
-        new Object[] {Backend.CF, false});
+    return buildParameters(Backend.values(), BooleanUtils.values());
   }
 
   private void configure(InternalOptions options) {
diff --git a/src/test/java/com/android/tools/r8/shaking/ifrule/verticalclassmerging/MergedTypeBaseTest.java b/src/test/java/com/android/tools/r8/shaking/ifrule/verticalclassmerging/MergedTypeBaseTest.java
index 10a5ba0..4fa2440 100644
--- a/src/test/java/com/android/tools/r8/shaking/ifrule/verticalclassmerging/MergedTypeBaseTest.java
+++ b/src/test/java/com/android/tools/r8/shaking/ifrule/verticalclassmerging/MergedTypeBaseTest.java
@@ -10,6 +10,7 @@
 import static org.junit.Assert.assertEquals;
 
 import com.android.tools.r8.TestBase;
+import com.android.tools.r8.utils.BooleanUtils;
 import com.android.tools.r8.utils.InternalOptions;
 import com.android.tools.r8.utils.codeinspector.CodeInspector;
 import com.google.common.collect.ImmutableList;
@@ -59,11 +60,7 @@
   @Parameters(name = "Backend: {0}, vertical class merging: {1}")
   public static Collection<Object[]> data() {
     // We don't run this on Proguard, as Proguard does not merge A into B.
-    return ImmutableList.of(
-        new Object[] {Backend.DEX, true},
-        new Object[] {Backend.DEX, false},
-        new Object[] {Backend.CF, true},
-        new Object[] {Backend.CF, false});
+    return buildParameters(Backend.values(), BooleanUtils.values());
   }
 
   public abstract Class<?> getTestClass();