Merge "Properly dedup synthetic $r8$twr$utility classes."
diff --git a/build.gradle b/build.gradle
index e49bbb5..f42501a 100644
--- a/build.gradle
+++ b/build.gradle
@@ -20,7 +20,6 @@
     junitVersion = '4.12'
     kotlinVersion = '1.2.30'
     kotlinExtMetadataJVMVersion = '0.0.3'
-    protobufVersion = '3.0.0'
     smaliVersion = '2.2b4'
 }
 
@@ -65,7 +64,6 @@
         }
     }
     dependencies {
-        classpath 'com.google.protobuf:protobuf-gradle-plugin:0.8.1'
         classpath 'com.cookpad.android.licensetools:license-tools-plugin:0.23.0'
         classpath 'com.github.jengelman.gradle.plugins:shadow:2.0.4'
         classpath "net.ltgt.gradle:gradle-errorprone-plugin:0.0.13"
@@ -83,7 +81,6 @@
 
 apply plugin: 'java'
 apply plugin: 'idea'
-apply plugin: 'com.google.protobuf'
 apply plugin: 'com.cookpad.android.licensetools'
 apply plugin: 'net.ltgt.errorprone-base'
 apply plugin: "net.ltgt.apt"
@@ -151,12 +148,7 @@
     }
     examples {
         java {
-            srcDirs = ['src/test/examples', 'build/generated/source/proto/examples/javalite/' ]
-        }
-        proto {
-            srcDirs = [
-                    'src/test/examples',
-            ]
+            srcDirs = ['src/test/examples']
         }
         output.resourcesDir = 'build/classes/examples'
     }
@@ -252,9 +244,7 @@
     examplesAndroidPCompile group: 'org.ow2.asm', name: 'asm', version: asmVersion
     // Import Guava for @Nullable annotation
     examplesCompile "com.google.guava:guava:$guavaVersion"
-    examplesCompile "com.google.protobuf:protobuf-lite:$protobufVersion"
     examplesCompileOnly "com.google.auto.value:auto-value:$autoValueVersion"
-    examplesRuntime "com.google.protobuf:protobuf-lite:$protobufVersion"
     supportLibs "com.android.support:support-v4:$androidSupportVersion"
     supportLibs "junit:junit:$junitVersion"
     supportLibs "com.android.support.test.espresso:espresso-core:$espressoVersion"
@@ -271,29 +261,6 @@
     licensesYaml = file('LIBRARY-LICENSE')
 }
 
-protobuf {
-    protoc {
-        // Download from repositories
-        artifact = "com.google.protobuf:protoc:$protobufVersion"
-    }
-    plugins {
-        javalite {
-            artifact = "com.google.protobuf:protoc-gen-javalite:$protobufVersion"
-        }
-    }
-    generateProtoTasks {
-        all().each { task ->
-            task.builtins {
-                // Disable the java code generator, as we want javalite only.
-                remove java
-            }
-            task.plugins {
-                javalite {}
-            }
-        }
-    }
-}
-
 def osString = OperatingSystem.current().isLinux() ? "linux" :
         OperatingSystem.current().isMacOsX() ? "mac" : "windows"
 
@@ -759,7 +726,6 @@
 task buildExampleJars {
     dependsOn downloadProguard
     def examplesDir = file("src/test/examples")
-    def protoSourceDir = file("build/generated/source/proto/examples/javalite")
     def proguardScript
     if (OperatingSystem.current().isWindows()) {
         proguardScript = "third_party/proguard/proguard5.2.1/bin/proguard.bat"
@@ -782,9 +748,8 @@
     }
 
     task "compile_examples"(type: JavaCompile) {
-        dependsOn "generateExamplesProto"
         dependsOn "copy_examples_resources"
-        source examplesDir, protoSourceDir
+        source examplesDir
         include "**/*.java"
         destinationDir = file("build/test/examples/classes")
         classpath = sourceSets.examples.compileClasspath
@@ -792,8 +757,8 @@
         targetCompatibility = JavaVersion.VERSION_1_7
         options.compilerArgs = ["-g:source,lines", "-Xlint:none"]
     }
-    task "compile_examples_debuginfo_all"(type: JavaCompile, dependsOn: "generateExamplesProto") {
-        source examplesDir, protoSourceDir
+    task "compile_examples_debuginfo_all"(type: JavaCompile) {
+        source examplesDir
         include "**/*.java"
         destinationDir = file("build/test/examples/classes_debuginfo_all")
         classpath = sourceSets.examples.compileClasspath
@@ -801,8 +766,8 @@
         targetCompatibility = JavaVersion.VERSION_1_7
         options.compilerArgs = ["-g", "-Xlint:none"]
     }
-    task "compile_examples_debuginfo_none"(type: JavaCompile, dependsOn: "generateExamplesProto") {
-        source examplesDir, protoSourceDir
+    task "compile_examples_debuginfo_none"(type: JavaCompile) {
+        source examplesDir
         include "**/*.java"
         destinationDir = file("build/test/examples/classes_debuginfo_none")
         classpath = sourceSets.examples.compileClasspath
@@ -819,13 +784,6 @@
         dependsOn "jar_example_${name}_debuginfo_none"
         dependsOn "extractExamplesRuntime"
         def runtimeDependencies = copySpec { }
-        if (!fileTree(dir: dir, include: '**/*.proto').empty) {
-            // If we have any proto use, we have to include those classes and the runtime.
-            runtimeDependencies = copySpec {
-                from "$buildDir/runtime/examples/"
-                include "com/google/protobuf/**/*.class"
-            }
-        }
         // The "throwing" test verifies debugging/stack info on the post-proguarded output.
         def proguardConfigPath = "${dir}/proguard.cfg"
         if (new File(proguardConfigPath).exists()) {
diff --git a/src/main/java/com/android/tools/r8/R8.java b/src/main/java/com/android/tools/r8/R8.java
index b1622ba..6de196e 100644
--- a/src/main/java/com/android/tools/r8/R8.java
+++ b/src/main/java/com/android/tools/r8/R8.java
@@ -46,7 +46,6 @@
 import com.android.tools.r8.shaking.RootSetBuilder.RootSet;
 import com.android.tools.r8.shaking.TreePruner;
 import com.android.tools.r8.shaking.VerticalClassMerger;
-import com.android.tools.r8.shaking.protolite.ProtoLiteExtension;
 import com.android.tools.r8.utils.AndroidApiLevel;
 import com.android.tools.r8.utils.AndroidApp;
 import com.android.tools.r8.utils.CfgPrinter;
@@ -289,18 +288,14 @@
                     options.proguardConfiguration.getRules(),
                     options)
                 .run(executorService);
-        ProtoLiteExtension protoLiteExtension =
-            options.forceProguardCompatibility
-                ? null
-                : new ProtoLiteExtension(appView.getAppInfo());
+
         Enqueuer enqueuer =
             new Enqueuer(
                 appView.getAppInfo(),
                 appView.getGraphLense(),
                 options,
                 options.forceProguardCompatibility,
-                compatibility,
-                protoLiteExtension);
+                compatibility);
         appView.setAppInfo(enqueuer.traceApplication(rootSet, executorService, timing));
         if (options.proguardConfiguration.isPrintSeeds()) {
           ByteArrayOutputStream bytes = new ByteArrayOutputStream();
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java b/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java
index ca4652c..fb67255 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java
@@ -58,7 +58,6 @@
 import com.android.tools.r8.kotlin.KotlinInfo;
 import com.android.tools.r8.logging.Log;
 import com.android.tools.r8.naming.IdentifierNameStringMarker;
-import com.android.tools.r8.shaking.protolite.ProtoLitePruner;
 import com.android.tools.r8.utils.CfgPrinter;
 import com.android.tools.r8.utils.DescriptorUtils;
 import com.android.tools.r8.utils.InternalOptions;
@@ -109,7 +108,6 @@
   private final LensCodeRewriter lensCodeRewriter;
   private final NonNullTracker nonNullTracker;
   private final Inliner inliner;
-  private final ProtoLitePruner protoLiteRewriter;
   private final IdentifierNameStringMarker identifierNameStringMarker;
   private final Devirtualizer devirtualizer;
   private final CovariantReturnTypeAnnotationTransformer covariantReturnTypeAnnotationTransformer;
@@ -165,9 +163,6 @@
               new MemberValuePropagation(appInfo.withLiveness()) : null;
       this.lensCodeRewriter = new LensCodeRewriter(graphLense, appInfo.withSubtyping());
       if (appInfo.hasLiveness()) {
-        // When disabling the pruner here, also disable the ProtoLiteExtension in R8.java.
-        this.protoLiteRewriter =
-            options.forceProguardCompatibility ? null : new ProtoLitePruner(appInfo.withLiveness());
         if (!appInfo.withLiveness().identifierNameStrings.isEmpty() && options.enableMinification) {
           this.identifierNameStringMarker =
               new IdentifierNameStringMarker(appInfo.withLiveness(), options);
@@ -177,7 +172,6 @@
         this.devirtualizer =
             options.enableDevirtualization ? new Devirtualizer(appInfo.withLiveness()) : null;
       } else {
-        this.protoLiteRewriter = null;
         this.identifierNameStringMarker = null;
         this.devirtualizer = null;
       }
@@ -187,7 +181,6 @@
       this.outliner = null;
       this.memberValuePropagation = null;
       this.lensCodeRewriter = null;
-      this.protoLiteRewriter = null;
       this.identifierNameStringMarker = null;
       this.devirtualizer = null;
     }
@@ -743,9 +736,6 @@
     }
 
     if (!method.isProcessed()) {
-      if (protoLiteRewriter != null && protoLiteRewriter.appliesTo(method)) {
-        protoLiteRewriter.rewriteProtoLiteSpecialMethod(code, method);
-      }
       if (lensCodeRewriter != null) {
         lensCodeRewriter.rewrite(code, method);
       } else {
diff --git a/src/main/java/com/android/tools/r8/naming/MemberNameMinifier.java b/src/main/java/com/android/tools/r8/naming/MemberNameMinifier.java
index 4c2479d..e03890c 100644
--- a/src/main/java/com/android/tools/r8/naming/MemberNameMinifier.java
+++ b/src/main/java/com/android/tools/r8/naming/MemberNameMinifier.java
@@ -31,7 +31,8 @@
     this.rootSet = rootSet;
     this.dictionary = options.proguardConfiguration.getObfuscationDictionary();
     this.useUniqueMemberNames = options.proguardConfiguration.isUseUniqueClassMemberNames();
-    this.overloadAggressively = options.proguardConfiguration.isOverloadAggressively();
+    this.overloadAggressively =
+        options.proguardConfiguration.isOverloadAggressivelyWithoutUseUniqueClassMemberNames();
     this.globalState = NamingState.createRoot(
         appInfo.dexItemFactory, dictionary, getKeyTransform(), useUniqueMemberNames);
   }
diff --git a/src/main/java/com/android/tools/r8/shaking/Enqueuer.java b/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
index 97456ec..13308e5 100644
--- a/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
+++ b/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
@@ -44,7 +44,6 @@
 import com.android.tools.r8.origin.Origin;
 import com.android.tools.r8.shaking.RootSetBuilder.ConsequentRootSet;
 import com.android.tools.r8.shaking.RootSetBuilder.RootSet;
-import com.android.tools.r8.shaking.protolite.ProtoLiteExtension;
 import com.android.tools.r8.utils.InternalOptions;
 import com.android.tools.r8.utils.StringDiagnostic;
 import com.android.tools.r8.utils.Timing;
@@ -116,8 +115,6 @@
       Maps.newIdentityHashMap();
   private final Set<DexCallSite> callSites = Sets.newIdentityHashSet();
 
-  private final ProtoLiteExtension protoLiteExtension;
-  private final Set<DexField> protoLiteFields = Sets.newIdentityHashSet();
   private final Set<DexReference> identifierNameStrings = Sets.newIdentityHashSet();
 
   /**
@@ -228,7 +225,7 @@
       GraphLense graphLense,
       InternalOptions options,
       boolean forceProguardCompatibility) {
-    this(appInfo, graphLense, options, forceProguardCompatibility, null, null);
+    this(appInfo, graphLense, options, forceProguardCompatibility, null);
   }
 
   public Enqueuer(
@@ -236,13 +233,11 @@
       GraphLense graphLense,
       InternalOptions options,
       boolean forceProguardCompatibility,
-      ProguardConfiguration.Builder compatibility,
-      ProtoLiteExtension protoLiteExtension) {
+      ProguardConfiguration.Builder compatibility) {
     this.appInfo = appInfo;
     this.graphLense = graphLense;
     this.compatibility = compatibility;
     this.options = options;
-    this.protoLiteExtension = protoLiteExtension;
     this.forceProguardCompatibility = forceProguardCompatibility;
   }
 
@@ -1378,11 +1373,7 @@
       markParameterAndReturnTypesAsLive(method);
       processAnnotations(method.annotations.annotations);
       method.parameterAnnotationsList.forEachAnnotation(this::processAnnotation);
-      if (protoLiteExtension != null && protoLiteExtension.appliesTo(method)) {
-        protoLiteExtension.processMethod(method, new UseRegistry(method), protoLiteFields);
-      } else {
-        method.registerCodeReferences(new UseRegistry(method));
-      }
+      method.registerCodeReferences(new UseRegistry(method));
       // Add all dependent members to the workqueue.
       enqueueRootItems(rootSet.getDependentItems(method));
     }
@@ -1711,11 +1702,6 @@
      */
     public final Object2BooleanMap<DexReference> identifierNameStrings;
     /**
-     * Set of fields that have been identified as proto-lite fields by the
-     * {@link ProtoLiteExtension}.
-     */
-    final Set<DexField> protoLiteFields;
-    /**
      * A set of types that have been removed by the {@link TreePruner}.
      */
     final Set<DexType> prunedTypes;
@@ -1770,7 +1756,6 @@
       this.neverInline = enqueuer.rootSet.neverInline;
       this.identifierNameStrings = joinIdentifierNameStrings(
           enqueuer.rootSet.identifierNameStrings, enqueuer.identifierNameStrings);
-      this.protoLiteFields = enqueuer.protoLiteFields;
       this.prunedTypes = Collections.emptySet();
       this.switchMaps = Collections.emptyMap();
       this.ordinalsMaps = Collections.emptyMap();
@@ -1808,7 +1793,6 @@
       this.staticInvokes = previous.staticInvokes;
       this.callSites = previous.callSites;
       this.brokenSuperInvokes = previous.brokenSuperInvokes;
-      this.protoLiteFields = previous.protoLiteFields;
       this.alwaysInline = previous.alwaysInline;
       this.forceInline = previous.forceInline;
       this.neverInline = previous.neverInline;
@@ -1872,7 +1856,6 @@
               .collect(Collectors.toList()));
       this.switchMaps = previous.switchMaps;
       this.ordinalsMaps = rewriteKeys(previous.ordinalsMaps, lense::lookupType);
-      this.protoLiteFields = previous.protoLiteFields;
       // Sanity check sets after rewriting.
       assert Sets.intersection(instanceFieldReads.keySet(), staticFieldReads.keySet()).isEmpty();
       assert Sets.intersection(instanceFieldWrites.keySet(), staticFieldWrites.keySet()).isEmpty();
@@ -1905,7 +1888,6 @@
       this.staticInvokes = previous.staticInvokes;
       this.callSites = previous.callSites;
       this.brokenSuperInvokes = previous.brokenSuperInvokes;
-      this.protoLiteFields = previous.protoLiteFields;
       this.alwaysInline = previous.alwaysInline;
       this.forceInline = previous.forceInline;
       this.neverInline = previous.neverInline;
@@ -2027,10 +2009,6 @@
       return pinnedItems.contains(reference);
     }
 
-    public boolean isProtoLiteField(DexField field) {
-      return protoLiteFields.contains(field);
-    }
-
     public Iterable<DexReference> getPinnedItems() {
       return pinnedItems;
     }
diff --git a/src/main/java/com/android/tools/r8/shaking/ProguardConfiguration.java b/src/main/java/com/android/tools/r8/shaking/ProguardConfiguration.java
index 599d444..bbb255c 100644
--- a/src/main/java/com/android/tools/r8/shaking/ProguardConfiguration.java
+++ b/src/main/java/com/android/tools/r8/shaking/ProguardConfiguration.java
@@ -208,6 +208,10 @@
       return useUniqueClassMemberNames;
     }
 
+    boolean isOverloadAggressively() {
+      return overloadAggressively;
+    }
+
     public void setKeepParameterNames(boolean keepParameterNames, Origin optionOrigin,
         Position optionPosition) {
       assert optionOrigin != null || !keepParameterNames;
@@ -552,8 +556,8 @@
     return rules;
   }
 
-  public boolean isOverloadAggressively() {
-    return overloadAggressively;
+  public boolean isOverloadAggressivelyWithoutUseUniqueClassMemberNames() {
+    return overloadAggressively && !useUniqueClassMemberNames;
   }
 
   public ImmutableList<String> getObfuscationDictionary() {
diff --git a/src/main/java/com/android/tools/r8/shaking/ProguardConfigurationParser.java b/src/main/java/com/android/tools/r8/shaking/ProguardConfigurationParser.java
index 75e91b1..a410a65 100644
--- a/src/main/java/com/android/tools/r8/shaking/ProguardConfigurationParser.java
+++ b/src/main/java/com/android/tools/r8/shaking/ProguardConfigurationParser.java
@@ -127,6 +127,13 @@
           configurationBuilder.getKeepParameterNamesOptionOrigin(),
           configurationBuilder.getKeepParameterNamesOptionPosition()));
     }
+    if (configurationBuilder.isOverloadAggressively()
+        && configurationBuilder.isUseUniqueClassMemberNames()) {
+      reporter.warning(
+          new StringDiagnostic(
+              "The -overloadaggressively flag has no effect if -useuniqueclassmembernames"
+                  + " is also specified."));
+    }
   }
 
   /**
diff --git a/src/main/java/com/android/tools/r8/shaking/protolite/ProtoLiteBase.java b/src/main/java/com/android/tools/r8/shaking/protolite/ProtoLiteBase.java
deleted file mode 100644
index c2264f2..0000000
--- a/src/main/java/com/android/tools/r8/shaking/protolite/ProtoLiteBase.java
+++ /dev/null
@@ -1,98 +0,0 @@
-// Copyright (c) 2017, 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.shaking.protolite;
-
-import com.android.tools.r8.graph.AppInfoWithSubtyping;
-import com.android.tools.r8.graph.DexClass;
-import com.android.tools.r8.graph.DexEncodedMethod;
-import com.android.tools.r8.graph.DexField;
-import com.android.tools.r8.graph.DexItemFactory;
-import com.android.tools.r8.graph.DexMethod;
-import com.android.tools.r8.graph.DexString;
-import com.android.tools.r8.graph.DexType;
-
-/**
- * Contains common definitions used by the {@link ProtoLiteExtension} for tree shaking and the
- * corresponding {@link ProtoLitePruner} code rewriting.
- */
-abstract class ProtoLiteBase {
-
-  static final int GETTER_NAME_PREFIX_LENGTH = 3;
-  static final int COUNT_POSTFIX_LENGTH = 5;
-
-  final AppInfoWithSubtyping appInfo;
-
-  final DexType messageType;
-  final DexString dynamicMethodName;
-  final DexString writeToMethodName;
-  final DexString getSerializedSizeMethodName;
-  final DexString constructorMethodName;
-  final DexString setterNamePrefix;
-  final DexString getterNamePrefix;
-  final DexString bitFieldPrefix;
-  final DexString underscore;
-
-  ProtoLiteBase(AppInfoWithSubtyping appInfo) {
-    this.appInfo = appInfo;
-    DexItemFactory factory = appInfo.dexItemFactory;
-    this.messageType = factory.createType("Lcom/google/protobuf/GeneratedMessageLite;");
-    this.dynamicMethodName = factory.createString("dynamicMethod");
-    this.writeToMethodName = factory.createString("writeTo");
-    this.getSerializedSizeMethodName = factory.createString("getSerializedSize");
-    this.constructorMethodName = factory.constructorMethodName;
-    this.setterNamePrefix = factory.createString("set");
-    this.getterNamePrefix = factory.createString("get");
-    this.bitFieldPrefix = factory.createString("bitField");
-    this.underscore = factory.createString("_");
-    assert getterNamePrefix.size == GETTER_NAME_PREFIX_LENGTH;
-  }
-
-  /**
-   * Returns true of the given method is a setter on a message class that does need processing
-   * by this phase of proto lite shaking.
-   * <p>
-   * False positives are ok.
-   */
-  abstract boolean isSetterThatNeedsProcessing(DexEncodedMethod method);
-
-  DexField getterToField(DexMethod getter) {
-    return getterToField(getter, 0);
-  }
-
-  DexField getterToField(DexMethod getter, int postfixLength) {
-    String getterName = getter.name.toString();
-    assert getterName.length() > GETTER_NAME_PREFIX_LENGTH + postfixLength;
-    String fieldName = Character.toLowerCase(getterName.charAt(GETTER_NAME_PREFIX_LENGTH))
-        + getterName.substring(GETTER_NAME_PREFIX_LENGTH + 1, getterName.length() - postfixLength)
-        + "_";
-    DexItemFactory factory = appInfo.dexItemFactory;
-    return factory
-        .createField(getter.holder, getter.proto.returnType, factory.createString(fieldName));
-  }
-
-  boolean hasSingleIntArgument(DexMethod method) {
-    return method.getArity() == 1
-        && method.proto.parameters.values[0] == appInfo.dexItemFactory.intType;
-  }
-
-  public boolean appliesTo(DexEncodedMethod method) {
-    if (!method.method.holder.isSubtypeOf(messageType, appInfo)) {
-      return false;
-    }
-    DexClass clazz = appInfo.definitionFor(method.method.holder);
-    // We only care for the actual leaf classes that implement a specific proto.
-    if (!clazz.accessFlags.isFinal()) {
-      return false;
-    }
-    DexString methodName = method.method.name;
-    // We could be even more precise here and check for the signature. However, there is only
-    // one of each method generated.
-    return methodName == dynamicMethodName
-        || methodName == writeToMethodName
-        || methodName == getSerializedSizeMethodName
-        || methodName == constructorMethodName
-        || isSetterThatNeedsProcessing(method);
-  }
-
-}
diff --git a/src/main/java/com/android/tools/r8/shaking/protolite/ProtoLiteExtension.java b/src/main/java/com/android/tools/r8/shaking/protolite/ProtoLiteExtension.java
deleted file mode 100644
index c4dee58..0000000
--- a/src/main/java/com/android/tools/r8/shaking/protolite/ProtoLiteExtension.java
+++ /dev/null
@@ -1,198 +0,0 @@
-// Copyright (c) 2017, 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.shaking.protolite;
-
-import com.android.tools.r8.graph.AppInfoWithSubtyping;
-import com.android.tools.r8.graph.DelegatingUseRegistry;
-import com.android.tools.r8.graph.DexClass;
-import com.android.tools.r8.graph.DexEncodedMethod;
-import com.android.tools.r8.graph.DexField;
-import com.android.tools.r8.graph.DexItemFactory;
-import com.android.tools.r8.graph.DexMethod;
-import com.android.tools.r8.graph.DexString;
-import com.android.tools.r8.graph.DexType;
-import com.android.tools.r8.graph.UseRegistry;
-import com.android.tools.r8.utils.MethodJavaSignatureEquivalence;
-import com.google.common.base.Equivalence;
-import com.google.common.base.Equivalence.Wrapper;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.Set;
-
-/**
- * Extends the tree shaker with special treatment for ProtoLite generated classes.
- * <p>
- * The goal is to remove unused fields from proto classes. To achieve this, we filter the
- * dependency processing of certain methods of ProtoLite classes. Read/write references to
- * fields or corresponding getters are ignored. If the fields or getters are not used otherwise
- * in the program, they will be pruned even though they are referenced from the processed
- * ProtoLite class.
- * <p>
- * The companion code rewriter in {@link ProtoLitePruner} then fixes up the code and removes
- * references to these dead fields and getters in a semantics preserving way. For proto2, the
- * fields are turned into unknown fields and hence are preserved over the wire. For proto3, the
- * fields are removed and, as with unknown fields in proto3, their data is lost on retransmission.
- * <p>
- * We have to process the following three methods specially:
- * <dl>
- *   <dt>dynamicMethod</dt>
- *   <dd>implements most proto operations, like merging, comparing, etc</dd>
- *   <dt>writeTo</dt>
- *   <dd>performs the actual write operations</dd>
- *   <dt>getSerializedSize</dt>
- *   <dd>implements computing the serialized size of a proto, very similar to writeTo</dd>
- * </dl>
- * As they access all fields of a proto, regardless of whether they are used, we have to mask
- * their accesses to ensure actually dead fields are not made live.
- * <p>
- * We also have to treat setters specially. While their code does not need to be rewritten, we
- * need to ensure that the fields they write are actually kept and marked as live. We achieve
- * this by also marking them read.
- */
-public class ProtoLiteExtension extends ProtoLiteBase {
-
-  private final Equivalence<DexMethod> equivalence = MethodJavaSignatureEquivalence.get();
-  /**
-   * Set of all methods directly defined on the GeneratedMessageLite class. Used to filter
-   * getters from other methods that begin with get.
-   */
-  private final Set<Wrapper<DexMethod>> methodsOnMessageType;
-
-  private final DexString caseGetterSuffix;
-  private final DexString caseFieldSuffix;
-
-  public ProtoLiteExtension(AppInfoWithSubtyping appInfo) {
-    super(appInfo);
-    DexItemFactory factory = appInfo.dexItemFactory;
-    this.methodsOnMessageType = computeMethodsOnMessageType();
-    this.caseGetterSuffix = factory.createString("Case");
-    this.caseFieldSuffix = factory.createString("Case_");
-  }
-
-  private Set<Wrapper<DexMethod>> computeMethodsOnMessageType() {
-    DexClass messageClass = appInfo.definitionFor(messageType);
-    if (messageClass == null) {
-      return Collections.emptySet();
-    }
-    Set<Wrapper<DexMethod>> superMethods = new HashSet<>();
-    messageClass.forEachMethod(method -> superMethods.add(equivalence.wrap(method.method)));
-    return superMethods;
-  }
-
-  @Override
-  boolean isSetterThatNeedsProcessing(DexEncodedMethod method) {
-    return method.accessFlags.isPrivate()
-        && method.method.name.beginsWith(setterNamePrefix)
-        && !methodsOnMessageType.contains(equivalence.wrap(method.method));
-  }
-
-  private boolean isGetter(DexMethod method, DexType instanceType) {
-    return method.holder == instanceType
-        && (method.proto.parameters.isEmpty() || hasSingleIntArgument(method))
-        && method.name.beginsWith(getterNamePrefix)
-        && !method.name.endsWith(caseGetterSuffix)
-        && !methodsOnMessageType.contains(equivalence.wrap(method));
-  }
-
-  private boolean isProtoField(DexField field, DexType instanceType) {
-    if (field.getHolder() != instanceType) {
-      return false;
-    }
-    // All instance fields that end with _ are proto fields. For proto2, there are also the
-    // bitField<n>_ fields that are used to store presence information. We process those normally.
-    // Likewise, the XXXCase_ fields for oneOfs.
-    DexString name = field.name;
-    return name.endsWith(underscore)
-        && !name.beginsWith(bitFieldPrefix)
-        && !name.endsWith(caseFieldSuffix);
-  }
-
-  public void processMethod(DexEncodedMethod method, UseRegistry registry,
-      Set<DexField> protoLiteFields) {
-    assert protoLiteFields != null;
-    if (isSetterThatNeedsProcessing(method)) {
-      // If a field is accessed by a live setter, the field is live as it has to be written to the
-      // serialized stream for this proto. As we mask all reads in the writing code and normally
-      // remove fields that are only written but never read, we have to mark fields used in setters
-      // as read and written.
-      method.registerCodeReferences(
-          new FieldWriteImpliesReadUseRegistry(registry, method.method.holder));
-    } else {
-      // Filter all getters and field accesses in these methods. We do not want fields to become
-      // live just due to being referenced in a special method. The pruning phase will remove
-      // all references to dead fields in the code later.
-      method.registerCodeReferences(new FilteringUseRegistry(registry, method.method.holder,
-          protoLiteFields));
-    }
-  }
-
-  private class FieldWriteImpliesReadUseRegistry extends DelegatingUseRegistry {
-
-    private final DexType instanceType;
-
-    FieldWriteImpliesReadUseRegistry(UseRegistry delegate,
-        DexType instanceType) {
-      super(delegate);
-      this.instanceType = instanceType;
-    }
-
-    @Override
-    public boolean registerInstanceFieldWrite(DexField field) {
-      if (isProtoField(field, instanceType)) {
-        super.registerInstanceFieldRead(field);
-      }
-      return super.registerInstanceFieldWrite(field);
-    }
-  }
-
-  private class FilteringUseRegistry extends DelegatingUseRegistry {
-
-    private final DexType instanceType;
-    private final Set<DexField> registerField;
-
-    private FilteringUseRegistry(UseRegistry delegate,
-        DexType instanceType, Set<DexField> registerField) {
-      super(delegate);
-      this.instanceType = instanceType;
-      this.registerField = registerField;
-    }
-
-    @Override
-    public boolean registerInstanceFieldWrite(DexField field) {
-      if (isProtoField(field, instanceType)) {
-        registerField.add(field);
-        return false;
-      }
-      return super.registerInstanceFieldWrite(field);
-    }
-
-    @Override
-    public boolean registerInstanceFieldRead(DexField field) {
-      if (isProtoField(field, instanceType)) {
-        registerField.add(field);
-        return false;
-      }
-      return super.registerInstanceFieldRead(field);
-    }
-
-    @Override
-    public boolean registerInvokeVirtual(DexMethod method) {
-      if (isGetter(method, instanceType)) {
-        // Try whether this is a getXXX method.
-        DexField field = getterToField(method);
-        if (isProtoField(field, instanceType)) {
-          registerField.add(field);
-          return false;
-        }
-        // Try whether this is a getXXXCount method.
-        field = getterToField(method, COUNT_POSTFIX_LENGTH);
-        if (isProtoField(field, instanceType)) {
-          registerField.add(field);
-          return false;
-        }
-      }
-      return super.registerInvokeVirtual(method);
-    }
-  }
-}
diff --git a/src/main/java/com/android/tools/r8/shaking/protolite/ProtoLitePruner.java b/src/main/java/com/android/tools/r8/shaking/protolite/ProtoLitePruner.java
deleted file mode 100644
index c37102c..0000000
--- a/src/main/java/com/android/tools/r8/shaking/protolite/ProtoLitePruner.java
+++ /dev/null
@@ -1,735 +0,0 @@
-// Copyright (c) 2017, 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.shaking.protolite;
-
-import com.android.tools.r8.errors.CompilationError;
-import com.android.tools.r8.errors.Unreachable;
-import com.android.tools.r8.graph.DexEncodedMethod;
-import com.android.tools.r8.graph.DexField;
-import com.android.tools.r8.graph.DexItemFactory;
-import com.android.tools.r8.graph.DexMethod;
-import com.android.tools.r8.graph.DexString;
-import com.android.tools.r8.graph.DexType;
-import com.android.tools.r8.ir.code.BasicBlock;
-import com.android.tools.r8.ir.code.DominatorTree;
-import com.android.tools.r8.ir.code.IRCode;
-import com.android.tools.r8.ir.code.InstanceGet;
-import com.android.tools.r8.ir.code.InstancePut;
-import com.android.tools.r8.ir.code.Instruction;
-import com.android.tools.r8.ir.code.InstructionIterator;
-import com.android.tools.r8.ir.code.InstructionListIterator;
-import com.android.tools.r8.ir.code.InvokeInterface;
-import com.android.tools.r8.ir.code.InvokeMethod;
-import com.android.tools.r8.ir.code.InvokeMethodWithReceiver;
-import com.android.tools.r8.ir.code.InvokeStatic;
-import com.android.tools.r8.ir.code.MemberType;
-import com.android.tools.r8.ir.code.Switch;
-import com.android.tools.r8.ir.code.Value;
-import com.android.tools.r8.ir.code.ValueType;
-import com.android.tools.r8.ir.optimize.SwitchUtils;
-import com.android.tools.r8.ir.optimize.SwitchUtils.EnumSwitchInfo;
-import com.android.tools.r8.shaking.Enqueuer.AppInfoWithLiveness;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.Iterables;
-import it.unimi.dsi.fastutil.ints.IntArrayList;
-import it.unimi.dsi.fastutil.ints.IntList;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.function.BiPredicate;
-
-/**
- * Implements the second phase of proto lite tree shaking.
- * <p>
- * In the pruner pass, we remove all references to the now dead fields from the methods that
- * were treated specially during tree shaking using the {@link ProtoLiteExtension}.
- * <p>
- * For proto2 code, we aim to keep presence information for fields alive and move the values of
- * dead fields to the unknown fields storage. For proto3, as it has no concept of passing on
- * unknown fields, dead fields are completely removed. In particular, reading a proto and writing
- * it again might loose data.
- */
-public class ProtoLitePruner extends ProtoLiteBase {
-
-  private final DexType visitorType;
-
-  private final DexType methodEnumType;
-  private final DexType codedOutputStreamType;
-  private final DexType protobufListType;
-  private final DexType listType;
-
-  private final DexString visitTag;
-  private final DexString mergeTag;
-  private final DexString isInitializedTag;
-  private final DexString makeImmutabkeTag;
-  private final DexString computeMethodPrefix;
-  private final DexString writeMethodPrefix;
-  private final DexString isInitializedMethodName;
-
-  private final DexString makeImmutableMethodName;
-  private final DexString sizeMethodName;
-  private final DexMethod sizeMethod;
-
-  public ProtoLitePruner(AppInfoWithLiveness appInfo) {
-    super(appInfo);
-    DexItemFactory factory = appInfo.dexItemFactory;
-    this.visitorType = factory.createType("Lcom/google/protobuf/GeneratedMessageLite$Visitor;");
-    this.methodEnumType = factory
-        .createType("Lcom/google/protobuf/GeneratedMessageLite$MethodToInvoke;");
-    this.codedOutputStreamType = factory.createType("Lcom/google/protobuf/CodedOutputStream;");
-    this.protobufListType = factory.createType("Lcom/google/protobuf/Internal$ProtobufList;");
-    this.listType = factory.createType("Ljava/util/List;");
-    this.visitTag = factory.createString("VISIT");
-    this.mergeTag = factory.createString("MERGE_FROM_STREAM");
-    this.isInitializedTag = factory.createString("IS_INITIALIZED");
-    this.makeImmutabkeTag = factory.createString("MAKE_IMMUTABLE");
-    this.computeMethodPrefix = factory.createString("compute");
-    this.writeMethodPrefix = factory.createString("write");
-    this.sizeMethodName = factory.createString("size");
-    this.isInitializedMethodName = factory.createString("isInitialized");
-    this.makeImmutableMethodName = factory.createString("makeImmutable");
-    this.sizeMethod = factory.createMethod(listType,
-        factory.createProto(factory.intType), sizeMethodName);
-  }
-
-  private boolean isPresenceField(DexField field, DexType instanceType) {
-    if (field.getHolder() != instanceType) {
-      return false;
-    }
-    // Proto2 uses fields named bitField<n>_ fields to store presence information.
-    String fieldName = field.name.toString();
-    return fieldName.endsWith("_")
-        && fieldName.startsWith("bitField");
-  }
-
-  @Override
-  boolean isSetterThatNeedsProcessing(DexEncodedMethod method) {
-    // The pruner does not need to process setters, so this method always returns false.
-    return false;
-  }
-
-  private boolean isGetter(DexMethod method) {
-    return isGetterHelper(method, 0);
-  }
-
-  private boolean isCountGetter(DexMethod method) {
-    return isGetterHelper(method, COUNT_POSTFIX_LENGTH);
-  }
-
-  private boolean isGetterHelper(DexMethod method, int postFixLength) {
-    if (!method.name.beginsWith(getterNamePrefix)
-        || !(method.proto.parameters.isEmpty() || hasSingleIntArgument(method))
-        || (method.holder == messageType)
-        || !method.holder.isSubtypeOf(messageType, appInfo)
-        || method.name.size <= GETTER_NAME_PREFIX_LENGTH + postFixLength) {
-      return false;
-    }
-    DexField correspondingField = getterToField(method, postFixLength);
-    return isProtoField(correspondingField);
-  }
-
-  private boolean isDefinedAsNull(Value value) {
-    return value.definition != null && value.isZero();
-  }
-
-  private boolean isComputeSizeMethod(DexMethod invokedMethod) {
-    return invokedMethod.holder == codedOutputStreamType
-        && invokedMethod.name.beginsWith(computeMethodPrefix);
-  }
-
-  private boolean isWriteMethod(DexMethod invokedMethod) {
-    return invokedMethod.holder == codedOutputStreamType
-        && invokedMethod.name.beginsWith(writeMethodPrefix);
-  }
-
-  private boolean isProtoField(DexField field) {
-    return appInfo.withLiveness().isProtoLiteField(field);
-  }
-
-  public void rewriteProtoLiteSpecialMethod(IRCode code, DexEncodedMethod method) {
-    DexString methodName = method.method.name;
-    if (methodName == dynamicMethodName) {
-      rewriteDynamicMethod(code, method);
-    } else if ((methodName == writeToMethodName) || (methodName == getSerializedSizeMethodName)) {
-      rewriteSizeOrWriteMethod(code);
-    } else if (methodName == constructorMethodName) {
-      rewriteConstructor(code);
-    } else {
-      throw new Unreachable();
-    }
-  }
-
-  /**
-   * For protos with repeated fields, the constructor may contain field initialization code like
-   *
-   * <pre>
-   * private Repeated() {
-   *  repeated_ = com.google.protobuf.GeneratedMessageLite.emptyProtobufList();
-   *  other_ = emptyBooleanList();
-   *  sub_ = emptyProtobufList();
-   * }
-   * </pre>
-   *
-   * which this rewriting removes.
-   */
-  private void rewriteConstructor(IRCode code) {
-    boolean wasRewritten;
-    do {
-      wasRewritten = false;
-      InstructionIterator it = code.instructionIterator();
-      while (it.hasNext()) {
-        Instruction insn = it.next();
-        if (insn.isInstancePut() && isDeadProtoField(insn.asInstancePut().getField())) {
-          // Remove initializations of dead fields.
-          it.remove();
-          wasRewritten = true;
-        } else if (insn.isInvokeStatic()) {
-          // Remove now unneeded constructor calls.
-          InvokeStatic invokeStatic = insn.asInvokeStatic();
-          DexMethod invokedMethod = invokeStatic.getInvokedMethod();
-          if ((!invokeStatic.outValue().isUsed())
-              && invokedMethod.proto.returnType.isSubtypeOf(protobufListType, appInfo)) {
-            it.remove();
-          }
-        }
-      }
-    } while (wasRewritten);
-  }
-
-
-  /**
-   * The writeTo and getSerializedSize methods of a generated proto access all fields. We have to
-   * remove the accesses to dead fields. The actual code of these methods varies to quite some
-   * degree depending on the types of the fields. For example
-   *
-   * <pre>
-   * public void writeTo(com.google.protobuf.CodedOutputStream output) throws java.io.IOException {
-   *   if (((bitField0_ & 0x00000001) == 0x00000001)) {
-   *     output.writeInt32(1, id_);
-   *   }
-   *   if (((bitField0_ & 0x00000002) == 0x00000002)) {
-   *     output.writeMessage(2, getInner());
-   *   }
-   *   for (int i = 0; i < repeated_.size(); i++) {
-   *     output.writeString(3, repeated_.get(i));
-   *   }
-   *   for (int i = 0; i < other_.size(); i++) {
-   *     output.writeBool(4, other_.getBoolean(i));
-   *   }
-   *   for (int i = 0; i < sub_.size(); i++) {
-   *     output.writeMessage(5, sub_.get(i));
-   *   }
-   *   unknownFields.writeTo(output);
-   * }
-   * </pre>
-   *
-   * We look for direct field accesses (id_, repeated_, etc. above) and getters (getInner) and
-   * rewrite those to null/0. We also rewrite all uses of the results, like the size() and
-   * write methods above.
-   */
-  private void rewriteSizeOrWriteMethod(IRCode code) {
-    boolean wasRewritten;
-    do {
-      wasRewritten = false;
-      InstructionIterator it = code.instructionIterator();
-      while (it.hasNext()) {
-        Instruction insn = it.next();
-        if (insn.isInstanceGet()) {
-          DexField field = insn.asInstanceGet().getField();
-          if (isDeadProtoField(field)) {
-            // Rewrite deads field access to corresponding 0.
-            it.replaceCurrentInstruction(code.createConstNull(insn.asInstanceGet()));
-            wasRewritten = true;
-          }
-        } else if (insn.isInvokeMethodWithReceiver()) {
-          InvokeMethodWithReceiver invokeMethod = insn.asInvokeMethodWithReceiver();
-          DexMethod invokedMethod = invokeMethod.getInvokedMethod();
-          if (isDeadProtoGetter(invokedMethod)) {
-            // Rewrite dead getters.
-            it.replaceCurrentInstruction(code.createConstNull(invokeMethod));
-            wasRewritten = true;
-          } else if (invokedMethod.name == sizeMethodName
-              && invokedMethod.holder.isSubtypeOf(listType, appInfo)) {
-            Value receiver = invokeMethod.getReceiver();
-            if (isDefinedAsNull(receiver)) {
-              // Rewrite size() methods with null receiver.
-              it.replaceCurrentInstruction(code.createConstNull(invokeMethod));
-            }
-          } else if (invokedMethod.name == getterNamePrefix
-              && invokedMethod.holder.isSubtypeOf(listType, appInfo)) {
-            Value receiver = invokeMethod.getReceiver();
-            if (isDefinedAsNull(receiver)) {
-              // Rewrite get(x) methods with null receiver.
-              it.replaceCurrentInstruction(code.createConstNull(invokeMethod));
-              wasRewritten = true;
-            }
-          } else if (isWriteMethod(invokedMethod)) {
-            Value lastArg = Iterables.getLast(invokeMethod.inValues());
-            if (isDefinedAsNull(lastArg)) {
-              it.remove();
-            }
-          }
-        } else if (insn.isInvokeMethod()) {
-          InvokeMethod invokeMethod = insn.asInvokeMethod();
-          DexMethod invokedMethod = invokeMethod.getInvokedMethod();
-          if (isComputeSizeMethod(invokedMethod)) {
-            Value lastArg = Iterables.getLast(invokeMethod.inValues());
-            if (isDefinedAsNull(lastArg)) {
-              // This is a computeSize method on a constant null. The field was dead.
-              assert (invokeMethod.outValue() != null);
-              it.replaceCurrentInstruction(code.createConstNull(invokeMethod));
-              wasRewritten = true;
-            }
-          }
-        }
-      }
-    } while (wasRewritten);
-  }
-
-  /**
-   * The dyanmicMethod code is actually a collection of various methods contained in one.
-   * It uses a switch statement over an enum to identify which actual operation is performed.
-   * We need to rewrite all cases that might access dead fields. These are
-   * <dl>
-   * <dt>IS_INITIALIZED</dt>
-   * <dd>See {@link #rewriteIsInitializedCase}.</dd>
-   * <dt>MAKE_IMMUTABLE</dt>
-   * <dd>See {@link #rewriteMakeImmutableCase}.</dd>
-   * <dt>VISIT</dt>
-   * <dd>See {@link #rewriteVisitCase}.</dd>
-   * <dt>MERGE_FROM_STREAM</dt>
-   * <dd>See {@link #rewriteMergeCase}.</dd>
-   * </dl>
-   */
-  private void rewriteDynamicMethod(IRCode code, DexEncodedMethod method) {
-    // This method contains a switch and we are interested in some of the cases only.
-    InstructionIterator iterator = code.instructionIterator();
-    Instruction matchingInstr = iterator.nextUntil(Instruction::isSwitch);
-    if (matchingInstr == null) {
-      throw new CompilationError("dynamicMethod in protoLite without switch.");
-    }
-    Switch switchInstr = matchingInstr.asSwitch();
-    EnumSwitchInfo info = SwitchUtils.analyzeSwitchOverEnum(switchInstr, appInfo.withLiveness());
-    if (info == null || info.enumClass != methodEnumType) {
-      throw new CompilationError("Malformed switch in dynamicMethod of proto lite.");
-    }
-    BasicBlock initializedCase = null;
-    BasicBlock visitCase = null;
-    BasicBlock mergeCase = null;
-    BasicBlock makeImmutableCase = null;
-    for (int keyIdx = 0; keyIdx < switchInstr.numberOfKeys(); keyIdx++) {
-      int key = switchInstr.getKey(keyIdx);
-      DexField label = info.indexMap.get(key);
-      assert label != null;
-      if (label.name == visitTag) {
-        assert visitCase == null;
-        visitCase = switchInstr.targetBlock(keyIdx);
-      } else if (label.name == mergeTag) {
-        assert mergeCase == null;
-        mergeCase = switchInstr.targetBlock(keyIdx);
-      } else if (label.name == isInitializedTag) {
-        assert initializedCase == null;
-        initializedCase = switchInstr.targetBlock(keyIdx);
-      } else if (label.name == makeImmutabkeTag) {
-        assert makeImmutableCase == null;
-        makeImmutableCase = switchInstr.targetBlock(keyIdx);
-      }
-    }
-    DexType instanceType = method.method.getHolder();
-    rewriteIsInitializedCase(initializedCase, instanceType, code);
-    assert code.isConsistentSSA();
-    rewriteMakeImmutableCase(makeImmutableCase, code);
-    assert code.isConsistentSSA();
-    rewriteVisitCase(visitCase, code);
-    assert code.isConsistentSSA();
-    rewriteMergeCase(mergeCase, instanceType, code);
-    // Rewriting of the merge case changes branching structure and adds more blocks that target
-    // the fallthrough label. This can introduce critical edges. Therefore, we split critical
-    // edges to maintain our edge-split form.
-    code.splitCriticalEdges();
-    assert code.isConsistentSSA();
-  }
-
-  /**
-   * In the presence of repeated fields, the MAKE_IMMUTABLE case will contain code of the form
-   *
-   * <pre>
-   * case MAKE_IMMUTABLE: {
-   *   repeated_.makeImmutable();
-   *   other_.makeImmutable();
-   *   sub_.makeImmutable();
-   *   return null;
-   * }
-   * </pre>
-   *
-   * For dead fields, we remove the field access and the call to makeImmutable.
-   */
-  private void rewriteMakeImmutableCase(BasicBlock switchCase, IRCode code) {
-    DominatorTree dom = new DominatorTree(code);
-    boolean wasRewritten;
-    do {
-      wasRewritten = false;
-      for (BasicBlock current : dom.dominatedBlocks(switchCase)) {
-        InstructionIterator it = current.iterator();
-        while (it.hasNext()) {
-          Instruction insn = it.next();
-          if (insn.isInstanceGet() && isDeadProtoField(insn.asInstanceGet().getField())) {
-            it.replaceCurrentInstruction(code.createConstNull(insn));
-            wasRewritten = true;
-          } else if (insn.isInvokeMethodWithReceiver()) {
-            InvokeMethodWithReceiver invokeMethod = insn.asInvokeMethodWithReceiver();
-            DexMethod invokedMethod = invokeMethod.getInvokedMethod();
-            if (isDeadProtoGetter(invokedMethod)) {
-              it.replaceCurrentInstruction(code.createConstNull(invokeMethod));
-              wasRewritten = true;
-            } else if (invokedMethod.name == makeImmutableMethodName
-                && invokedMethod.getHolder().isSubtypeOf(protobufListType, appInfo)) {
-              Value receiver = invokeMethod.getReceiver();
-              if (isDefinedAsNull(receiver)) {
-                it.remove();
-              }
-            }
-          }
-        }
-      }
-    } while (wasRewritten);
-  }
-
-  /**
-   * The IS_INITIALIZED case also has a high degree of variability depending on the type of fields.
-   * Common code looks as follows
-   *
-   * <pre>
-   * case IS_INITIALIZED: {
-   *   byte isInitialized = memoizedIsInitialized;
-   *   if (isInitialized == 1) return DEFAULT_INSTANCE;
-   *   if (isInitialized == 0) return null;
-   *
-   *   boolean shouldMemoize = ((Boolean) arg0).booleanValue();
-   *   if (!hasId()) {
-   *     if (shouldMemoize) {
-   *       memoizedIsInitialized = 0;
-   *     }
-   *     return null;
-   *   }
-   *   for (int i = 0; i < getSubCount(); i++) {
-   *     if (!getSub(i).isInitialized()) {
-   *       if (shouldMemoize) {
-   *         memoizedIsInitialized = 0;
-   *       }
-   *       return null;
-   *     }
-   *   }
-   *   if (shouldMemoize) memoizedIsInitialized = 1;
-   *   return DEFAULT_INSTANCE;
-   * }
-   * </pre>
-   *
-   * We remove all the accesses of dead fields and getters. We also replace secondary invokes
-   * (like getSubCount or isInitialized) with conservative default values (e.g. 0, true).
-   * <p>
-   * We also rewrite getXXXCount methods on live fields, as accesses to those methods was filtered
-   * during tree shaking. In place of those methods, we inline their definition.
-   */
-  private void rewriteIsInitializedCase(BasicBlock switchCase, DexType instanceType,
-      IRCode code) {
-    DominatorTree dom = new DominatorTree(code);
-    boolean wasRewritten;
-    do {
-      wasRewritten = false;
-      for (BasicBlock current : dom.dominatedBlocks(switchCase)) {
-        InstructionIterator it = current.iterator();
-        while (it.hasNext()) {
-          Instruction insn = it.next();
-          if (insn.isInvokeMethodWithReceiver()) {
-            InvokeMethodWithReceiver invokeMethod = insn.asInvokeMethodWithReceiver();
-            DexMethod invokedMethod = invokeMethod.getInvokedMethod();
-            if (isDeadProtoGetter(invokedMethod)) {
-              it.replaceCurrentInstruction(code.createConstNull(invokeMethod));
-              wasRewritten = true;
-            } else if (invokedMethod.name == isInitializedMethodName
-                && invokedMethod.getHolder().isSubtypeOf(messageType, appInfo)) {
-              Value receiver = invokeMethod.getReceiver();
-              if (isDefinedAsNull(receiver)) {
-                // We cannot compute initialization state for nested messages and repeated
-                // messages that have been removed or moved to unknown fields. Just return
-                // true.
-                it.replaceCurrentInstruction(code.createTrue());
-                wasRewritten = true;
-              }
-            } else if (isCountGetter(invokedMethod)) {
-              // We have to rewrite these as a precaution, as they might be dead due to
-              // tree shaking ignoring them.
-              DexField field = getterToField(invokedMethod, 5);
-              if (appInfo.withLiveness().liveFields.contains(field)) {
-                // Effectively inline the code that is normally inside these methods.
-                Value thisReference = invokeMethod.getReceiver();
-                Value newResult = code.createValue(ValueType.INT);
-                invokeMethod.outValue().replaceUsers(newResult);
-                Value theList = code.createValue(ValueType.OBJECT);
-                it.replaceCurrentInstruction(
-                    new InstanceGet(MemberType.OBJECT, theList, thisReference, field));
-                it.add(new InvokeInterface(sizeMethod, newResult, Collections.emptyList()));
-              } else {
-                // The field is dead, so its count is always 0.
-                it.replaceCurrentInstruction(code.createConstNull(invokeMethod));
-              }
-            }
-          }
-        }
-      }
-    } while (wasRewritten);
-  }
-
-  private InstancePut findProtoFieldWrite(BasicBlock block, DexType instanceType,
-      BiPredicate<DexField, DexType> filter, DominatorTree dom) {
-    for (BasicBlock current : dom.dominatedBlocks(block)) {
-      InstructionIterator insns = current.iterator();
-      InstancePut instancePut = (InstancePut) insns.nextUntil(Instruction::isInstancePut);
-      if (instancePut != null && filter.test(instancePut.getField(), instanceType)) {
-        return instancePut;
-      }
-    }
-    return null;
-  }
-
-  /**
-   * For the merge case, we typically see code that contains a switch over the field tags. The inner
-   * switch has the form
-   *
-   * <pre>
-   * switch (tag) {
-   *   case 0:
-   *     done = true;
-   *     break;
-   *   default: {
-   *     if (!parseUnknownField(tag, input)) {
-   *       done = true;
-   *     }
-   *     break;
-   *   }
-   *   case 8: {
-   *     bitField0_ |= 0x00000001;
-   *     id_ = input.readInt32();
-   *     break;
-   *   }
-   *   case 18: {
-   *     nestedproto2.GeneratedNestedProto.NestedOne.Builder subBuilder = null;
-   *     if (((bitField0_ & 0x00000002) == 0x00000002)) {
-   *       subBuilder = inner_.toBuilder();
-   *     }
-   *     inner_ = input.readMessage(nestedproto2.GeneratedNestedProto.NestedOne.parser(),
-   *         extensionRegistry);
-   *     if (subBuilder != null) {
-   *       subBuilder.mergeFrom(inner_);
-   *       inner_ = subBuilder.buildPartial();
-   *     }
-   *     bitField0_ |= 0x00000002;
-   *     break;
-   *   }
-   *   case 24: {
-   *     if (!other_.isModifiable()) {
-   *       other_ =
-   *           com.google.protobuf.GeneratedMessageLite.mutableCopy(other_);
-   *     }
-   *     other_.addBoolean(input.readBool());
-   *     break;
-   *   }
-   *   case 26: {
-   *     int length = input.readRawVarint32();
-   *     int limit = input.pushLimit(length);
-   *     if (!other_.isModifiable() && input.getBytesUntilLimit() > 0) {
-   *       final int currentSize = other_.size();
-   *       other_ = other_.mutableCopyWithCapacity(
-   *       currentSize + (length/1));
-   *     }
-   *     while (input.getBytesUntilLimit() > 0) {
-   *       other_.addBoolean(input.readBool());
-   *     }
-   *     input.popLimit(limit);
-   *     break;
-   *   }
-   * }
-   * </pre>
-   *
-   * The general approach here is to identify the field that is processed by a case and, if
-   * the field is dead, remove the entire case.
-   * <p>
-   * We slightly complicate the rewriting by also checking whether the block computes a
-   * presence bitfield (bitField0_ above). If so, we move that computation to a new block that
-   * continues to the default case. This ensures that presence is recorded correctly, yet the
-   * field is moved to the unknownFields collection, if such exists.
-   */
-  private void rewriteMergeCase(BasicBlock caseBlock, DexType instanceType,
-      IRCode code) {
-    // We are looking for a switch statement over the input tag. Just traverse all blocks until
-    // we find it.
-    List<BasicBlock> deadBlocks = new ArrayList<>();
-    DominatorTree dom = new DominatorTree(code);
-    for (BasicBlock current : dom.dominatedBlocks(caseBlock)) {
-      InstructionIterator it = current.iterator();
-      Switch switchInstr = (Switch) it.nextUntil(Instruction::isSwitch);
-      if (switchInstr != null) {
-        int nextBlock = code.getHighestBlockNumber() + 1;
-        IntList liveKeys = new IntArrayList(switchInstr.numberOfKeys());
-        List<BasicBlock> liveBlocks = new ArrayList<>(switchInstr.numberOfKeys());
-        boolean needsCleanup = false;
-        // Filter out all the cases that contain writes to dead fields.
-        for (int keyIdx = 0; keyIdx < switchInstr.numberOfKeys(); keyIdx++) {
-          BasicBlock targetBlock = switchInstr.targetBlock(keyIdx);
-          InstancePut instancePut =
-              findProtoFieldWrite(targetBlock, instanceType, (field, holder) -> isProtoField(field),
-                  dom);
-          if (instancePut == null
-              || appInfo.withLiveness().liveFields.contains(instancePut.getField())) {
-            // This is a live case. Keep it.
-            liveKeys.add(switchInstr.getKey(keyIdx));
-            liveBlocks.add(targetBlock);
-          } else {
-            // We cannot just remove this entire switch case if there is some computation here
-            // for whether the field is present. We check this by searching for a write to
-            // the bitField<xxx>_ fields. If such write exists, we move the corresponding
-            // instructions to the first block in the switch.
-            //TODO(herhut): Only do this if the written field has a live hasMethod.
-            InstancePut bitFieldUpdate = findProtoFieldWrite(targetBlock, instanceType,
-                this::isPresenceField, dom);
-            if (bitFieldUpdate != null) {
-              BasicBlock newBlock = BasicBlock.createGotoBlock(nextBlock++);
-              newBlock.link(switchInstr.fallthroughBlock());
-              // Copy over the computation of the field;
-              moveInstructionTo(newBlock.listIterator(), bitFieldUpdate, dom, targetBlock);
-              switchInstr.getBlock().link(newBlock);
-              liveKeys.add(switchInstr.getKey(keyIdx));
-              liveBlocks.add(newBlock);
-              code.blocks.add(newBlock);
-            }
-            needsCleanup = true;
-          }
-        }
-        if (needsCleanup) {
-          DominatorTree updatedTree = new DominatorTree(code);
-          BasicBlock fallThrough = switchInstr.fallthroughBlock();
-          List<BasicBlock> successors = ImmutableList.copyOf(current.getNormalSuccessors());
-          for (BasicBlock successor : successors) {
-            if (successor != fallThrough && !liveBlocks.contains(successor)) {
-              deadBlocks.addAll(current.unlink(successor, updatedTree));
-            }
-          }
-          int[] blockIndices = new int[liveBlocks.size()];
-          for (int i = 0; i < liveBlocks.size(); i++) {
-            blockIndices[i] = current.getSuccessors().indexOf(liveBlocks.get(i));
-          }
-          Switch newSwitch = new Switch(switchInstr.inValues().get(0), liveKeys.toIntArray(),
-              blockIndices, current.getSuccessors().indexOf(fallThrough));
-          it.replaceCurrentInstruction(newSwitch);
-        }
-        break;
-      }
-    }
-    code.removeBlocks(deadBlocks);
-  }
-
-  //TODO(herhut): This should really be a copy with a value substitution map.
-  private void moveInstructionTo(InstructionListIterator iterator, Instruction insn,
-      DominatorTree dom,
-      BasicBlock dominator) {
-    for (Value value : insn.inValues()) {
-      Instruction input = value.definition;
-      // We do not support phis.
-      assert input != null;
-      if (dom.dominatedBy(input.getBlock(), dominator)) {
-        // And no shared instructions.
-        assert input.outValue().numberOfUsers() == 1;
-        moveInstructionTo(iterator, input, dom, dominator);
-      }
-    }
-    insn.getBlock().removeInstruction(insn);
-    iterator.add(insn);
-  }
-
-  private boolean isDeadProtoField(DexField field) {
-    return isProtoField(field) && !appInfo.withLiveness().liveFields.contains(field);
-  }
-
-  private boolean isDeadProtoGetter(DexMethod method) {
-    return isGetter(method) && isDeadProtoField(getterToField(method));
-  }
-
-  private boolean isVisitOfDeadField(Instruction instruction) {
-    if (!instruction.isInvokeMethod()) {
-      return false;
-    }
-    InvokeMethod invokeMethod = instruction.asInvokeMethod();
-    if (invokeMethod.getInvokedMethod().getHolder() == visitorType
-        && invokeMethod.getInvokedMethod().getArity() >= 2) {
-      Instruction secondArg = invokeMethod.inValues().get(2).definition;
-      return secondArg.isConstNumber();
-    }
-    return false;
-  }
-
-  /**
-   * The visit case has typically the form
-   *
-   * <pre>
-   * case VISIT: {
-   *   Visitor visitor = (Visitor) arg0;
-   *   repeatedproto.GeneratedRepeatedProto.Repeated other =
-   *       (repeatedproto.GeneratedRepeatedProto.Repeated) arg1;
-   *   id_ = visitor.visitInt(
-   *       hasId(), id_,
-   *       other.hasId(), other.id_);
-   *   repeated_= visitor.visitList(repeated_, other.repeated_);
-   *   inner_ = visitor.visitMessage(inner_, other.inner_);
-   *   if (visitor == com.google.protobuf.GeneratedMessageLite.MergeFromVisitor.INSTANCE) {
-   *     bitField0_ |= other.bitField0_;
-   *   }
-   *   return this;
-   * }
-   * </pre>
-   *
-   * We remove all writes and reads to dead fields and correspondign secondary instructions, like
-   * the visitXXX methods.
-   * <p>
-   * Note that the invoked hasMethods are benign, as the only access the bitFieldXXX_ fields, which
-   * we currently do not remove. Inlining will likely remove the methods.
-   */
-  private void rewriteVisitCase(BasicBlock switchCase, IRCode code) {
-    DominatorTree dom = new DominatorTree(code);
-    boolean wasRewritten;
-    do {
-      wasRewritten = false;
-      for (BasicBlock target : dom.dominatedBlocks(switchCase)) {
-        InstructionIterator it = target.iterator();
-        while (it.hasNext()) {
-          Instruction insn = it.next();
-          if (insn.isInstanceGet()) {
-            InstanceGet instanceGet = insn.asInstanceGet();
-            if (isDeadProtoField(instanceGet.getField())) {
-              it.replaceCurrentInstruction(code.createConstNull(instanceGet));
-              wasRewritten = true;
-            }
-          } else if (insn.isInstancePut()) {
-            if (isDeadProtoField(insn.asInstancePut().getField())) {
-              it.remove();
-            }
-          } else if (isVisitOfDeadField(insn)) {
-            it.replaceCurrentInstruction(code.createConstNull(insn));
-          } else if (insn.isCheckCast()) {
-            // The call to visitXXX is a generic method invoke, so it will be followed by a check
-            // cast to fix up the type. As the result is no longer needed once we are done, we can
-            // remove the cast. This removes a potential last reference to an inner message class.
-            // TODO(herhut): We should have a generic dead cast removal.
-            Value inValue = insn.inValues().get(0);
-            if (isDefinedAsNull(inValue)) {
-              insn.outValue().replaceUsers(inValue);
-              it.remove();
-            }
-          }
-
-        }
-      }
-    } while (wasRewritten);
-  }
-}
diff --git a/src/test/examples/enumproto/Enumproto.java b/src/test/examples/enumproto/Enumproto.java
deleted file mode 100644
index 9176378..0000000
--- a/src/test/examples/enumproto/Enumproto.java
+++ /dev/null
@@ -1,66 +0,0 @@
-// Copyright (c) 2017, 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 enumproto;
-
-
-import enumproto.GeneratedEnumProto.Enum;
-import enumproto.three.GeneratedEnumProto.EnumThree;
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-
-public class Enumproto {
-
-  private static final byte[] WITH_ALL_FIELDS = new byte[]{6, 8, 42, 16, 2, 24, 3};
-  private static final byte[] WITH_DEFAULT_FOR_ENUM = new byte[]{2, 8, 42};
-
-
-  public static void main(String... args) throws IOException {
-    readProtoAndPrintDaEnum(WITH_ALL_FIELDS);
-    readProtoAndPrintDaEnum(WITH_DEFAULT_FOR_ENUM);
-    readProtoThreeAndPrintDaEnum(WITH_ALL_FIELDS);
-    readProtoThreeAndPrintDaEnum(WITH_DEFAULT_FOR_ENUM);
-    roundTrip(WITH_ALL_FIELDS);
-    roundTrip(WITH_DEFAULT_FOR_ENUM);
-    roundTripThree(WITH_ALL_FIELDS);
-    roundTripThree(WITH_DEFAULT_FOR_ENUM);
-  }
-
-  private static void readProtoAndPrintDaEnum(byte[] bytes) throws IOException {
-    ByteArrayInputStream input = new ByteArrayInputStream(bytes);
-    Enum.Builder builder = Enum.newBuilder();
-    builder.mergeDelimitedFrom(input);
-    Enum buffer = builder.build();
-    System.out.println(buffer.getEnum());
-  }
-
-  private static void readProtoThreeAndPrintDaEnum(byte[] bytes) throws IOException {
-    ByteArrayInputStream input = new ByteArrayInputStream(bytes);
-    EnumThree.Builder builder = EnumThree.newBuilder();
-    builder.mergeDelimitedFrom(input);
-    EnumThree buffer = builder.build();
-    System.out.println(buffer.getEnum());
-  }
-
-  private static void roundTrip(byte[] bytes) throws IOException {
-    ByteArrayInputStream input = new ByteArrayInputStream(bytes);
-    Enum.Builder builder = Enum.newBuilder();
-    builder.mergeDelimitedFrom(input);
-    Enum buffer = builder.build();
-    ByteArrayOutputStream output = new ByteArrayOutputStream();
-    buffer.writeDelimitedTo(output);
-    readProtoAndPrintDaEnum(output.toByteArray());
-  }
-
-  private static void roundTripThree(byte[] bytes) throws IOException {
-    ByteArrayInputStream input = new ByteArrayInputStream(bytes);
-    EnumThree.Builder builder = EnumThree.newBuilder();
-    builder.mergeDelimitedFrom(input);
-    EnumThree buffer = builder.build();
-    ByteArrayOutputStream output = new ByteArrayOutputStream();
-    buffer.writeDelimitedTo(output);
-    readProtoThreeAndPrintDaEnum(output.toByteArray());
-  }
-
-}
diff --git a/src/test/examples/enumproto/enum.proto b/src/test/examples/enumproto/enum.proto
deleted file mode 100644
index 0fa5695..0000000
--- a/src/test/examples/enumproto/enum.proto
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright (c) 2017, 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.
-syntax = "proto2";
-package enumproto;
-
-option java_outer_classname = "GeneratedEnumProto";
-
-message Enum {
-  required int32 id = 1;
-  enum DaEnum {
-    UNKOWN = 0;
-    KNOWN = 1;
-    BELIEF = 2;
-  }
-  optional DaEnum enum = 2;
-  enum OtherEnum {
-    BLACK = 0;
-    RED = 1;
-    GREEN = 2;
-    OKALALALA = 3;
-  }
-  optional OtherEnum other = 3;
-}
-
diff --git a/src/test/examples/enumproto/enum_three.proto b/src/test/examples/enumproto/enum_three.proto
deleted file mode 100644
index a2731fb..0000000
--- a/src/test/examples/enumproto/enum_three.proto
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright (c) 2016, 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.
-syntax = "proto3";
-package enumproto.three;
-
-option java_outer_classname = "GeneratedEnumProto";
-
-message EnumThree {
-  int32 id = 1;
-  enum DaEnum {
-    UNKOWN = 0;
-    KNOWN = 1;
-    BELIEF = 2;
-  }
-  DaEnum enum = 2;
-  enum OtherEnum {
-    BLACK = 0;
-    RED = 1;
-    GREEN = 2;
-    OKALALALA = 3;
-  }
-  OtherEnum other = 3;
-}
-
diff --git a/src/test/examples/enumproto/keep-rules.txt b/src/test/examples/enumproto/keep-rules.txt
deleted file mode 100644
index 088f88f..0000000
--- a/src/test/examples/enumproto/keep-rules.txt
+++ /dev/null
@@ -1,12 +0,0 @@
-# Copyright (c) 2017, 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.
-
-# Keep the application entry point. Get rid of everything that is not
-# reachable from there.
--keep public class enumproto.Enumproto {
-  public static void main(...);
-}
-
-# allow access modification to enable minification
--allowaccessmodification
diff --git a/src/test/examples/nestedproto1/Nestedproto.java b/src/test/examples/nestedproto1/Nestedproto.java
deleted file mode 100644
index fe1a535..0000000
--- a/src/test/examples/nestedproto1/Nestedproto.java
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright (c) 2017, 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 nestedproto1;
-
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import nestedproto1.GeneratedNestedProto.Outer;
-
-public class Nestedproto {
-
-  private static final byte[] NESTED_MESSAGE_WITH_BOTH = new byte[] {25, 8, 42, 18, 12, 8, 1, 18, 8,
-      105, 110, 110, 101, 114, 79, 110, 101, 26, 7, 8, 2, 21, 0, 0, -10, 66};
-
-  private static final byte[] NESTED_MESSAGE_WITH_ONE = new byte[]{16, 8, 42, 18, 12, 8, 1, 18, 8,
-      105,
-      110, 110, 101, 114, 79, 110, 101};
-
-  public static void main(String... args) throws IOException {
-    testWith(NESTED_MESSAGE_WITH_BOTH);
-    testWith(NESTED_MESSAGE_WITH_ONE);
-  }
-
-  public static void testWith(byte[] data) throws IOException {
-    ByteArrayInputStream input = new ByteArrayInputStream(data);
-    Outer.Builder builder = Outer.newBuilder();
-    builder.mergeDelimitedFrom(input);
-    Outer outer = builder.build();
-    System.out.println(outer.getInner().getOther());
-  }
-}
diff --git a/src/test/examples/nestedproto1/keep-rules.txt b/src/test/examples/nestedproto1/keep-rules.txt
deleted file mode 100644
index 1c47672..0000000
--- a/src/test/examples/nestedproto1/keep-rules.txt
+++ /dev/null
@@ -1,12 +0,0 @@
-# Copyright (c) 2017, 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.
-
-# Keep the application entry point. Get rid of everything that is not
-# reachable from there.
--keep public class nestedproto1.Nestedproto {
-  public static void main(...);
-}
-
-# allow access modification to enable minification
--allowaccessmodification
diff --git a/src/test/examples/nestedproto1/nested.proto b/src/test/examples/nestedproto1/nested.proto
deleted file mode 100644
index 0d05749..0000000
--- a/src/test/examples/nestedproto1/nested.proto
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright (c) 2016, 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.
-syntax = "proto2";
-package nestedproto1;
-
-option java_outer_classname = "GeneratedNestedProto";
-
-message NestedOne {
-  required int32 id = 1;
-  optional string other = 2;
-}
-
-message NestedTwo {
-  required int32 id = 1;
-  optional float other = 2;
-}
-
-message Outer {
-  required int32 id = 1;
-  required NestedOne inner = 2;
-  optional NestedTwo inner2 = 3;
-}
-
diff --git a/src/test/examples/nestedproto2/Nestedproto.java b/src/test/examples/nestedproto2/Nestedproto.java
deleted file mode 100644
index 59217de..0000000
--- a/src/test/examples/nestedproto2/Nestedproto.java
+++ /dev/null
@@ -1,33 +0,0 @@
-// Copyright (c) 2017, 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 nestedproto2;
-
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import nestedproto2.GeneratedNestedProto.Outer;
-
-public class Nestedproto {
-
-  private static final byte[] NESTED_MESSAGE_WITH_BOTH = new byte[]{25, 8, 42, 18, 12, 8, 1, 18, 8,
-      105, 110, 110, 101, 114, 79, 110, 101, 26, 7, 8, 2, 21, 0, 0, -10, 66};
-
-  private static final byte[] NESTED_MESSAGE_WITH_ONE = new byte[]{16, 8, 42, 18, 12, 8, 1, 18, 8,
-      105,
-      110, 110, 101, 114, 79, 110, 101};
-
-  // Test that all fields remain when roundtripping with removed fields.
-  public static void main(String... args) throws IOException {
-    testWith(NESTED_MESSAGE_WITH_BOTH);
-    testWith(NESTED_MESSAGE_WITH_ONE);
-  }
-
-  private static void testWith(byte[] data) throws IOException {
-    ByteArrayInputStream input = new ByteArrayInputStream(data);
-    Outer.Builder builder = Outer.newBuilder();
-    builder.mergeDelimitedFrom(input);
-    builder.setId(1982);
-    Outer outer = builder.build();
-    outer.writeTo(System.out);
-  }
-}
diff --git a/src/test/examples/nestedproto2/keep-rules.txt b/src/test/examples/nestedproto2/keep-rules.txt
deleted file mode 100644
index 87c9218..0000000
--- a/src/test/examples/nestedproto2/keep-rules.txt
+++ /dev/null
@@ -1,12 +0,0 @@
-# Copyright (c) 2017, 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.
-
-# Keep the application entry point. Get rid of everything that is not
-# reachable from there.
--keep public class nestedproto2.Nestedproto {
-  public static void main(...);
-}
-
-# allow access modification to enable minification
--allowaccessmodification
diff --git a/src/test/examples/nestedproto2/nested.proto b/src/test/examples/nestedproto2/nested.proto
deleted file mode 100644
index ac56f40..0000000
--- a/src/test/examples/nestedproto2/nested.proto
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright (c) 2016, 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.
-syntax = "proto2";
-package nestedproto2;
-
-option java_outer_classname = "GeneratedNestedProto";
-
-message NestedOne {
-  required int32 id = 1;
-  optional string other = 2;
-}
-
-message NestedTwo {
-  required int32 id = 1;
-  optional float other = 2;
-}
-
-message Outer {
-  required int32 id = 1;
-  required NestedOne inner = 2;
-  optional NestedTwo inner2 = 3;
-}
-
diff --git a/src/test/examples/oneofproto/Oneofproto.java b/src/test/examples/oneofproto/Oneofproto.java
deleted file mode 100644
index 261705f..0000000
--- a/src/test/examples/oneofproto/Oneofproto.java
+++ /dev/null
@@ -1,38 +0,0 @@
-// Copyright (c) 2017, 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 oneofproto;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.util.Arrays;
-import oneofproto.GeneratedOneOfProto.Oneof;
-
-public class Oneofproto {
-
-  private static final byte[] WITH_BOOL_FIELD = new byte[]{4, 8, 42, 24, 1};
-  private static final byte[] WITH_FLOAT_FIELD = new byte[]{7, 8, 42, 21, 0, 0, -10, 66};
-  private static final byte[] WITH_STRING_FIELD = new byte[]{9, 8, 42, 34, 5, 104, 101, 108, 108,
-      111};
-  private static final byte[] WITH_NO_FIELD = new byte[]{2, 8, 42};
-
-
-  public static void main(String... args) throws IOException {
-    roundTrip(WITH_BOOL_FIELD);
-    roundTrip(WITH_FLOAT_FIELD);
-    roundTrip(WITH_STRING_FIELD);
-    roundTrip(WITH_NO_FIELD);
-  }
-
-  private static void roundTrip(byte[] data) throws IOException {
-    ByteArrayInputStream input = new ByteArrayInputStream(data);
-    Oneof.Builder builder = Oneof.newBuilder();
-    builder.mergeDelimitedFrom(input);
-    Oneof oneof = builder.build();
-    ByteArrayOutputStream output = new ByteArrayOutputStream();
-    oneof.writeDelimitedTo(output);
-    System.out.println(Arrays.toString(output.toByteArray()));
-  }
-
-}
diff --git a/src/test/examples/oneofproto/keep-rules.txt b/src/test/examples/oneofproto/keep-rules.txt
deleted file mode 100644
index 70f00f1..0000000
--- a/src/test/examples/oneofproto/keep-rules.txt
+++ /dev/null
@@ -1,12 +0,0 @@
-# Copyright (c) 2017, 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.
-
-# Keep the application entry point. Get rid of everything that is not
-# reachable from there.
--keep public class oneofproto.Oneofproto {
-  public static void main(...);
-}
-
-# allow access modification to enable minification
--allowaccessmodification
diff --git a/src/test/examples/oneofproto/oneof.proto b/src/test/examples/oneofproto/oneof.proto
deleted file mode 100644
index c5a67a1..0000000
--- a/src/test/examples/oneofproto/oneof.proto
+++ /dev/null
@@ -1,17 +0,0 @@
-// Copyright (c) 2016, 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.
-syntax = "proto2";
-package oneofproto;
-
-option java_outer_classname = "GeneratedOneOfProto";
-
-message Oneof {
-  required int32 id = 1;
-  oneof otherfields {
-    float floatField = 2;
-    bool boolField = 3;
-    string stringField = 4;
-  }
-}
-
diff --git a/src/test/examples/protowithexts/withexts.proto b/src/test/examples/protowithexts/withexts.proto
deleted file mode 100644
index d384173..0000000
--- a/src/test/examples/protowithexts/withexts.proto
+++ /dev/null
@@ -1,19 +0,0 @@
-// Copyright (c) 2016, 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.
-syntax = "proto2";
-package protowithexts;
-
-option java_outer_classname = "GeneratedProtoWithExts";
-
-message Simple {
-  required int32 id = 1;
-
-  optional int32 other = 2;
-
-  extensions 10 to 19;
-}
-
-extend Simple {
-  optional string extra = 10;
-}
diff --git a/src/test/examples/repeatedproto/Repeatedproto.java b/src/test/examples/repeatedproto/Repeatedproto.java
deleted file mode 100644
index 280070d..0000000
--- a/src/test/examples/repeatedproto/Repeatedproto.java
+++ /dev/null
@@ -1,22 +0,0 @@
-// Copyright (c) 2017, 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 repeatedproto;
-
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import repeatedproto.GeneratedRepeatedProto.Repeated;
-
-public class Repeatedproto {
-
-  private static final byte[] WITH_ALL_FIELDS = new byte[]{29, 8, 123, 18, 3, 111, 110, 101, 18, 3,
-      116, 119, 111, 18, 5, 116, 104, 114, 101, 101, 24, 1, 34, 2, 8, 42, 34, 2, 8, 42};
-
-  public static void main(String... args) throws IOException {
-    ByteArrayInputStream input = new ByteArrayInputStream(WITH_ALL_FIELDS);
-    Repeated.Builder builder = Repeated.newBuilder();
-    builder.mergeDelimitedFrom(input);
-    Repeated repeated = builder.build();
-    System.out.println(repeated.getRepeatedList());
-  }
-}
diff --git a/src/test/examples/repeatedproto/keep-rules.txt b/src/test/examples/repeatedproto/keep-rules.txt
deleted file mode 100644
index 3d02352..0000000
--- a/src/test/examples/repeatedproto/keep-rules.txt
+++ /dev/null
@@ -1,12 +0,0 @@
-# Copyright (c) 2017, 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.
-
-# Keep the application entry point. Get rid of everything that is not
-# reachable from there.
--keep public class repeatedproto.Repeatedproto {
-  public static void main(...);
-}
-
-# allow access modification to enable minification
--allowaccessmodification
diff --git a/src/test/examples/repeatedproto/repeated.proto b/src/test/examples/repeatedproto/repeated.proto
deleted file mode 100644
index 7414e6f..0000000
--- a/src/test/examples/repeatedproto/repeated.proto
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright (c) 2016, 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.
-syntax = "proto2";
-package repeatedproto;
-
-option java_outer_classname = "GeneratedRepeatedProto";
-
-message Repeated {
-  required int32 id = 1;
-  repeated string repeated = 2;
-  repeated bool other = 3;
-
-  message Sub {
-    required int32 value = 1;
-  }
-
-  repeated Sub sub = 4;
-}
-
diff --git a/src/test/examples/repeatedproto/repeated_three.proto b/src/test/examples/repeatedproto/repeated_three.proto
deleted file mode 100644
index 7da7881..0000000
--- a/src/test/examples/repeatedproto/repeated_three.proto
+++ /dev/null
@@ -1,15 +0,0 @@
-// Copyright (c) 2016, 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.
-syntax = "proto3";
-package repeatedproto.three;
-
-option java_outer_classname = "GeneratedRepeatedProto";
-
-
-message RepeatedThree {
-  int32 id = 1;
-  repeated string repeated = 2;
-  repeated bool other = 3;
-}
-
diff --git a/src/test/examples/simpleproto1/Simpleproto.java b/src/test/examples/simpleproto1/Simpleproto.java
deleted file mode 100644
index d07ce8d..0000000
--- a/src/test/examples/simpleproto1/Simpleproto.java
+++ /dev/null
@@ -1,56 +0,0 @@
-// Copyright (c) 2017, 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 simpleproto1;
-
-import com.google.protobuf.UninitializedMessageException;
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.util.Arrays;
-import simpleproto1.GeneratedSimpleProto.Simple;
-
-public class Simpleproto {
-
-  private static final byte[] WITH_REQUIRED_FIELDS = new byte[]{7, 8, 42, 21, 0, 0, -10, 66};
-  private static final byte[] WITH_MISSING_FIELD = new byte[]{2, 8, 42};
-
-
-  public static void main(String... args) throws IOException {
-    readProtoWithAllReqFields();
-    partialBuildFails();
-    partialReadFails();
-  }
-
-  private static void partialBuildFails() {
-    Simple.Builder builder = Simple.newBuilder();
-    builder.setId(32);
-    try {
-      builder.build();
-    } catch (UninitializedMessageException e) {
-      System.out.println("got exception");
-    }
-  }
-
-  private static void partialReadFails() throws IOException {
-    ByteArrayInputStream input = new ByteArrayInputStream(WITH_MISSING_FIELD);
-    Simple.Builder builder = Simple.newBuilder();
-    builder.mergeDelimitedFrom(input);
-    try {
-      builder.build();
-    } catch (UninitializedMessageException e) {
-      System.out.println("got exception");
-    }
-  }
-
-  private static void readProtoWithAllReqFields() throws IOException {
-    ByteArrayInputStream input = new ByteArrayInputStream(WITH_REQUIRED_FIELDS);
-    Simple.Builder builder = Simple.newBuilder();
-    builder.mergeDelimitedFrom(input);
-    Simple simple = builder.build();
-    ByteArrayOutputStream output = new ByteArrayOutputStream(WITH_REQUIRED_FIELDS.length);
-    simple.writeDelimitedTo(output);
-    System.out.println(Arrays.toString(output.toByteArray()));
-    System.out.println(Arrays.equals(WITH_REQUIRED_FIELDS, output.toByteArray()));
-  }
-}
diff --git a/src/test/examples/simpleproto1/keep-rules.txt b/src/test/examples/simpleproto1/keep-rules.txt
deleted file mode 100644
index 3c3c33f..0000000
--- a/src/test/examples/simpleproto1/keep-rules.txt
+++ /dev/null
@@ -1,12 +0,0 @@
-# Copyright (c) 2017, 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.
-
-# Keep the application entry point. Get rid of everything that is not
-# reachable from there.
--keep public class simpleproto1.Simpleproto {
-  public static void main(...);
-}
-
-# allow access modification to enable minification
--allowaccessmodification
diff --git a/src/test/examples/simpleproto1/simple.proto b/src/test/examples/simpleproto1/simple.proto
deleted file mode 100644
index f4e1be4..0000000
--- a/src/test/examples/simpleproto1/simple.proto
+++ /dev/null
@@ -1,14 +0,0 @@
-// Copyright (c) 2016, 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.
-syntax = "proto2";
-package simpleproto1;
-
-option java_outer_classname = "GeneratedSimpleProto";
-
-message Simple {
-  required int32 id = 1;
-  required float unusedRequired = 2;
-  optional bool other = 3;
-}
-
diff --git a/src/test/examples/simpleproto2/Simpleproto.java b/src/test/examples/simpleproto2/Simpleproto.java
deleted file mode 100644
index f333d72..0000000
--- a/src/test/examples/simpleproto2/Simpleproto.java
+++ /dev/null
@@ -1,30 +0,0 @@
-// Copyright (c) 2017, 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 simpleproto2;
-
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import simpleproto2.GeneratedSimpleProto.Simple;
-
-/**
- * A class that only uses a has method but otherwise ignores the value of a field.
- */
-public class Simpleproto {
-
-  private static final byte[] WITHOUT_HASME_FIELD = new byte[]{2, 8, 42};
-  private static final byte[] WITH_HASME_FIELD = new byte[]{7, 8, 42, 21, 0, 0, -10, 66};
-
-  public static void main(String... args) throws IOException {
-    testHasWorks(WITHOUT_HASME_FIELD, false);
-    testHasWorks(WITH_HASME_FIELD, true);
-  }
-
-  private static void testHasWorks(byte[] msg, boolean expected) throws IOException {
-    ByteArrayInputStream input = new ByteArrayInputStream(msg);
-    Simple.Builder builder = Simple.newBuilder();
-    builder.mergeDelimitedFrom(input);
-    Simple simple = builder.build();
-    System.out.println("Expected " + expected + " and got " + simple.hasHasMe());
-  }
-}
diff --git a/src/test/examples/simpleproto2/keep-rules.txt b/src/test/examples/simpleproto2/keep-rules.txt
deleted file mode 100644
index 8f9c93e..0000000
--- a/src/test/examples/simpleproto2/keep-rules.txt
+++ /dev/null
@@ -1,12 +0,0 @@
-# Copyright (c) 2017, 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.
-
-# Keep the application entry point. Get rid of everything that is not
-# reachable from there.
--keep public class simpleproto2.Simpleproto {
-  public static void main(...);
-}
-
-# allow access modification to enable minification
--allowaccessmodification
diff --git a/src/test/examples/simpleproto2/simple.proto b/src/test/examples/simpleproto2/simple.proto
deleted file mode 100644
index b9173e9..0000000
--- a/src/test/examples/simpleproto2/simple.proto
+++ /dev/null
@@ -1,14 +0,0 @@
-// Copyright (c) 2016, 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.
-syntax = "proto2";
-package simpleproto2;
-
-option java_outer_classname = "GeneratedSimpleProto";
-
-message Simple {
-  required int32 id = 1;
-  optional float hasMe = 2;
-  optional int32 other = 3;
-}
-
diff --git a/src/test/examples/simpleproto3/Simpleproto.java b/src/test/examples/simpleproto3/Simpleproto.java
deleted file mode 100644
index 2cdbae8..0000000
--- a/src/test/examples/simpleproto3/Simpleproto.java
+++ /dev/null
@@ -1,65 +0,0 @@
-// Copyright (c) 2017, 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 simpleproto3;
-
-import com.google.protobuf.UninitializedMessageException;
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import simpleproto3.GeneratedSimpleProto.Simple;
-
-public class Simpleproto {
-
-  private static final byte[] WITH_REQUIRED_FIELDS = new byte[]{7, 8, 42, 21, 0, 0, -10, 66};
-  private static final byte[] WITH_MISSING_FIELD = new byte[]{2, 8, 42};
-
-
-  public static void main(String... args) throws IOException {
-    readProtoWithAllReqFields();
-    partialBuildFails();
-    partialReadFails();
-  }
-
-  private static void partialBuildFails() {
-    Simple.Builder builder = Simple.newBuilder();
-    builder.setId(32);
-    try {
-      builder.build();
-    } catch (UninitializedMessageException e) {
-      System.out.println("got exception");
-    }
-  }
-
-  private static void partialReadFails() throws IOException {
-    ByteArrayInputStream input = new ByteArrayInputStream(WITH_MISSING_FIELD);
-    Simple.Builder builder = Simple.newBuilder();
-    builder.mergeDelimitedFrom(input);
-    try {
-      builder.build();
-    } catch (UninitializedMessageException e) {
-      System.out.println("got exception");
-    }
-  }
-
-  private static void readProtoWithAllReqFields() throws IOException {
-    ByteArrayInputStream input = new ByteArrayInputStream(WITH_REQUIRED_FIELDS);
-    Simple.Builder builder = Simple.newBuilder();
-    builder.mergeDelimitedFrom(input);
-    Simple simple = builder.build();
-    ByteArrayOutputStream output = new ByteArrayOutputStream(WITH_REQUIRED_FIELDS.length);
-    simple.writeDelimitedTo(output);
-    System.out.println(isContained(WITH_REQUIRED_FIELDS, output.toByteArray()));
-  }
-
-  // After shaking, the serialized proto will no longer contain fields that are not referenced.
-  private static boolean isContained(byte[] fullBytes, byte[] reducedBytes) {
-    int j = 1;
-    for (int i = 1; i < fullBytes.length && j < reducedBytes.length; i++) {
-      if (fullBytes[i] == reducedBytes[j]) {
-        j++;
-      }
-    }
-    return j == reducedBytes.length;
-  }
-}
diff --git a/src/test/examples/simpleproto3/keep-rules.txt b/src/test/examples/simpleproto3/keep-rules.txt
deleted file mode 100644
index 186e9f8..0000000
--- a/src/test/examples/simpleproto3/keep-rules.txt
+++ /dev/null
@@ -1,12 +0,0 @@
-# Copyright (c) 2017, 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.
-
-# Keep the application entry point. Get rid of everything that is not
-# reachable from there.
--keep public class simpleproto3.Simpleproto {
-  public static void main(...);
-}
-
-# allow access modification to enable minification
--allowaccessmodification
diff --git a/src/test/examples/simpleproto3/simple.proto b/src/test/examples/simpleproto3/simple.proto
deleted file mode 100644
index 87512d1..0000000
--- a/src/test/examples/simpleproto3/simple.proto
+++ /dev/null
@@ -1,14 +0,0 @@
-// Copyright (c) 2016, 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.
-syntax = "proto3";
-package simpleproto3;
-
-option java_outer_classname = "GeneratedSimpleProto";
-
-message Simple {
-  int32 id = 1;
-  float unusedRequired = 2;
-  bool other = 3;
-}
-
diff --git a/src/test/java/com/android/tools/r8/TestBase.java b/src/test/java/com/android/tools/r8/TestBase.java
index b28ddd7..48e7d1a 100644
--- a/src/test/java/com/android/tools/r8/TestBase.java
+++ b/src/test/java/com/android/tools/r8/TestBase.java
@@ -641,6 +641,13 @@
     return ToolHelper.runJava(out, mainAndArgs.toArray(new String[0]));
   }
 
+  protected ProcessResult runOnJavaRawNoVerify(AndroidApp app, String mainClass, List<String> args)
+      throws IOException {
+    Path out = File.createTempFile("junit", ".zip", temp.getRoot()).toPath();
+    app.writeToZip(out, OutputMode.ClassFile);
+    return ToolHelper.runJavaNoVerify(out, mainClass, args.toArray(new String[0]));
+  }
+
   private String extractClassName(byte[] ccc) {
     class ClassNameExtractor extends ClassVisitor {
       private String className;
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/CheckCastRemovalTest.java b/src/test/java/com/android/tools/r8/ir/optimize/CheckCastRemovalTest.java
index f894322..e505499 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/CheckCastRemovalTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/CheckCastRemovalTest.java
@@ -50,7 +50,8 @@
     List<String> pgConfigs = ImmutableList.of(
         "-keep class " + CLASS_NAME + " { *; }",
         "-dontshrink");
-    AndroidApp app = compileWithR8(builder, pgConfigs, o -> o.enableClassInlining = false);
+    AndroidApp app =
+        compileWithR8(builder, pgConfigs, o -> o.enableClassInlining = false, Backend.DEX);
 
     DexEncodedMethod method = getMethod(app, CLASS_NAME, main);
     assertNotNull(method);
@@ -89,7 +90,8 @@
         "-keep class B { *; }",
         "-keep class C { *; }",
         "-dontshrink");
-    AndroidApp app = compileWithR8(builder, pgConfigs, opts -> opts.enableClassInlining = false);
+    AndroidApp app =
+        compileWithR8(builder, pgConfigs, opts -> opts.enableClassInlining = false, Backend.DEX);
 
     DexEncodedMethod method = getMethod(app, CLASS_NAME, main);
     assertNotNull(method);
@@ -129,7 +131,7 @@
         "-keep class C { *; }",
         "-dontoptimize",
         "-dontshrink");
-    AndroidApp app = compileWithR8(builder, pgConfigs, null);
+    AndroidApp app = compileWithR8(builder, pgConfigs, null, Backend.DEX);
 
     DexEncodedMethod method = getMethod(app, CLASS_NAME, main);
     assertNotNull(method);
@@ -168,7 +170,7 @@
     List<String> pgConfigs = ImmutableList.of(
         "-keep class " + CLASS_NAME + " { *; }",
         "-dontshrink");
-    AndroidApp app = compileWithR8(builder, pgConfigs, null);
+    AndroidApp app = compileWithR8(builder, pgConfigs, null, Backend.DEX);
 
     DexEncodedMethod method = getMethod(app, CLASS_NAME, main);
     assertNotNull(method);
@@ -205,7 +207,7 @@
     List<String> pgConfigs = ImmutableList.of(
         "-keep class " + CLASS_NAME + " { *; }",
         "-dontshrink");
-    AndroidApp app = compileWithR8(builder, pgConfigs, null);
+    AndroidApp app = compileWithR8(builder, pgConfigs, null, Backend.DEX);
 
     DexEncodedMethod method = getMethod(app, CLASS_NAME, main);
     assertNotNull(method);
diff --git a/src/test/java/com/android/tools/r8/jasmin/JasminTestBase.java b/src/test/java/com/android/tools/r8/jasmin/JasminTestBase.java
index c75ea7d..6500ca7 100644
--- a/src/test/java/com/android/tools/r8/jasmin/JasminTestBase.java
+++ b/src/test/java/com/android/tools/r8/jasmin/JasminTestBase.java
@@ -106,11 +106,12 @@
   protected AndroidApp compileWithR8(
       JasminBuilder builder,
       List<String> proguardConfigs,
-      Consumer<InternalOptions> optionsConsumer)
+      Consumer<InternalOptions> optionsConsumer,
+      Backend backend)
       throws Exception {
     R8Command command =
-        ToolHelper.prepareR8CommandBuilder(builder.build())
-            .addLibraryFiles(ToolHelper.getDefaultAndroidJar())
+        ToolHelper.prepareR8CommandBuilder(builder.build(), emptyConsumer(backend))
+            .addLibraryFiles(runtimeJar(backend))
             .addProguardConfiguration(proguardConfigs, Origin.unknown())
             .build();
     return ToolHelper.runR8(command, optionsConsumer);
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 efead2d..61274ee 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
@@ -9,23 +9,42 @@
 import static org.junit.Assert.assertTrue;
 
 import com.android.tools.r8.ToolHelper.ProcessResult;
-import com.android.tools.r8.VmTestRunner;
 import com.android.tools.r8.jasmin.JasminBuilder;
 import com.android.tools.r8.jasmin.JasminBuilder.ClassBuilder;
 import com.android.tools.r8.jasmin.JasminTestBase;
 import com.android.tools.r8.utils.AndroidApp;
+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.FieldSubject;
 import com.android.tools.r8.utils.codeinspector.MethodSubject;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.Iterables;
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
 import java.util.List;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
 
-@RunWith(VmTestRunner.class)
+@RunWith(Parameterized.class)
 public class ValidNameConflictTest extends JasminTestBase {
+  private static final String REPEATED_NAME = "hopeTheresNoSuchNameInRuntimeLibraries";
+
+  private final Backend backend;
+
+  @Parameterized.Parameters(name = "Backend: {0}")
+  public static Collection<Backend> data() {
+    return Arrays.asList(Backend.values());
+  }
+
+  public ValidNameConflictTest(Backend backend) {
+    this.backend = backend;
+  }
+
   private final String CLASS_NAME = "Example";
   private final String SUPER_CLASS = "Super";
   private final String ANOTHER_CLASS = "Test";
@@ -64,8 +83,8 @@
   private JasminBuilder buildFieldNameConflictClassFile() {
     JasminBuilder builder = new JasminBuilder();
     ClassBuilder classBuilder = builder.addClass(CLASS_NAME);
-    classBuilder.addStaticField("same", "Ljava/lang/Object;", null);
-    classBuilder.addStaticField("same", "Ljava/lang/String;", "\"" + MSG + "\"");
+    classBuilder.addStaticField(REPEATED_NAME, "Ljava/lang/Object;", null);
+    classBuilder.addStaticField(REPEATED_NAME, "Ljava/lang/String;", "\"" + MSG + "\"");
     classBuilder.addMainMethod(
         buildCodeForVisitingDeclaredMembers(
             ImmutableList.of(
@@ -79,6 +98,15 @@
     return builder;
   }
 
+  private ProcessResult runRaw(AndroidApp app, String main) throws IOException {
+    if (backend == Backend.DEX) {
+      return runOnArtRaw(app, main);
+    } else {
+      assert backend == Backend.CF;
+      return runOnJavaRawNoVerify(app, main, Collections.emptyList());
+    }
+  }
+
   @Test
   public void remainFieldNameConflict_keepRules() throws Exception {
     JasminBuilder builder = buildFieldNameConflictClassFile();
@@ -92,22 +120,22 @@
             + "}\n"
             + "-printmapping\n",
         "-dontshrink");
-    AndroidApp app = compileWithR8(builder, pgConfigs, null);
+    AndroidApp app = compileWithR8(builder, pgConfigs, null, backend);
 
     CodeInspector codeInspector = new CodeInspector(app);
     ClassSubject clazz = codeInspector.clazz(CLASS_NAME);
     assertTrue(clazz.isPresent());
-    FieldSubject f1 = clazz.field("java.lang.String", "same");
+    FieldSubject f1 = clazz.field("java.lang.String", REPEATED_NAME);
     assertTrue(f1.isPresent());
     assertFalse(f1.isRenamed());
-    FieldSubject f2 = clazz.field("java.lang.Object", "same");
+    FieldSubject f2 = clazz.field("java.lang.Object", REPEATED_NAME);
     assertTrue(f2.isPresent());
     assertFalse(f2.isRenamed());
     assertEquals(f1.getFinalName(), f2.getFinalName());
 
-    ProcessResult artOutput = runOnArtRaw(app, CLASS_NAME);
-    assertEquals(0, artOutput.exitCode);
-    assertEquals(javaOutput.stdout, artOutput.stdout);
+    ProcessResult output = runRaw(app, CLASS_NAME);
+    assertEquals(0, output.exitCode);
+    assertEquals(javaOutput.stdout, output.stdout);
   }
 
   @Test
@@ -120,22 +148,22 @@
         keepMainProguardConfiguration(CLASS_NAME),
         "-useuniqueclassmembernames",
         "-dontshrink");
-    AndroidApp app = compileWithR8(builder, pgConfigs, null);
+    AndroidApp app = compileWithR8(builder, pgConfigs, null, backend);
 
     CodeInspector codeInspector = new CodeInspector(app);
     ClassSubject clazz = codeInspector.clazz(CLASS_NAME);
     assertTrue(clazz.isPresent());
-    FieldSubject f1 = clazz.field("java.lang.String", "same");
+    FieldSubject f1 = clazz.field("java.lang.String", REPEATED_NAME);
     assertTrue(f1.isPresent());
     assertTrue(f1.isRenamed());
-    FieldSubject f2 = clazz.field("java.lang.Object", "same");
+    FieldSubject f2 = clazz.field("java.lang.Object", REPEATED_NAME);
     assertTrue(f2.isPresent());
     assertTrue(f2.isRenamed());
     assertEquals(f1.getFinalName(), f2.getFinalName());
 
-    ProcessResult artOutput = runOnArtRaw(app, CLASS_NAME);
-    assertEquals(0, artOutput.exitCode);
-    assertEquals(javaOutput.stdout, artOutput.stdout);
+    ProcessResult output = runRaw(app, CLASS_NAME);
+    assertEquals(0, output.exitCode);
+    assertEquals(javaOutput.stdout, output.stdout);
   }
 
   @Test
@@ -150,22 +178,22 @@
         "-useuniqueclassmembernames",
         "-overloadaggressively",  // no-op
         "-dontshrink");
-    AndroidApp app = compileWithR8(builder, pgConfigs, null);
+    AndroidApp app = compileWithR8(builder, pgConfigs, null, backend);
 
     CodeInspector codeInspector = new CodeInspector(app);
     ClassSubject clazz = codeInspector.clazz(CLASS_NAME);
     assertTrue(clazz.isPresent());
-    FieldSubject f1 = clazz.field("java.lang.String", "same");
+    FieldSubject f1 = clazz.field("java.lang.String", REPEATED_NAME);
     assertTrue(f1.isPresent());
     assertTrue(f1.isRenamed());
-    FieldSubject f2 = clazz.field("java.lang.Object", "same");
+    FieldSubject f2 = clazz.field("java.lang.Object", REPEATED_NAME);
     assertTrue(f2.isPresent());
     assertTrue(f2.isRenamed());
     assertEquals(f1.getFinalName(), f2.getFinalName());
 
-    ProcessResult artOutput = runOnArtRaw(app, CLASS_NAME);
-    assertEquals(0, artOutput.exitCode);
-    assertEquals(javaOutput.stdout, artOutput.stdout);
+    ProcessResult output = runRaw(app, CLASS_NAME);
+    assertEquals(0, output.exitCode);
+    assertEquals(javaOutput.stdout, output.stdout);
   }
 
   @Test
@@ -177,22 +205,22 @@
     List<String> pgConfigs = ImmutableList.of(
         keepMainProguardConfiguration(CLASS_NAME),
         "-dontshrink");
-    AndroidApp app = compileWithR8(builder, pgConfigs, null);
+    AndroidApp app = compileWithR8(builder, pgConfigs, null, backend);
 
     CodeInspector codeInspector = new CodeInspector(app);
     ClassSubject clazz = codeInspector.clazz(CLASS_NAME);
     assertTrue(clazz.isPresent());
-    FieldSubject f1 = clazz.field("java.lang.String", "same");
+    FieldSubject f1 = clazz.field("java.lang.String", REPEATED_NAME);
     assertTrue(f1.isPresent());
     assertTrue(f1.isRenamed());
-    FieldSubject f2 = clazz.field("java.lang.Object", "same");
+    FieldSubject f2 = clazz.field("java.lang.Object", REPEATED_NAME);
     assertTrue(f2.isPresent());
     assertTrue(f2.isRenamed());
     assertNotEquals(f1.getFinalName(), f2.getFinalName());
 
-    ProcessResult artOutput = runOnArtRaw(app, CLASS_NAME);
-    assertEquals(0, artOutput.exitCode);
-    assertEquals(javaOutput.stdout, artOutput.stdout);
+    ProcessResult output = runRaw(app, CLASS_NAME);
+    assertEquals(0, output.exitCode);
+    assertEquals(javaOutput.stdout, output.stdout);
   }
 
   @Test
@@ -205,33 +233,31 @@
         keepMainProguardConfiguration(CLASS_NAME),
         "-overloadaggressively",
         "-dontshrink");
-    AndroidApp app = compileWithR8(builder, pgConfigs, null);
+    AndroidApp app = compileWithR8(builder, pgConfigs, null, backend);
 
     CodeInspector codeInspector = new CodeInspector(app);
     ClassSubject clazz = codeInspector.clazz(CLASS_NAME);
     assertTrue(clazz.isPresent());
-    FieldSubject f1 = clazz.field("java.lang.String", "same");
+    FieldSubject f1 = clazz.field("java.lang.String", REPEATED_NAME);
     assertTrue(f1.isPresent());
     assertTrue(f1.isRenamed());
-    FieldSubject f2 = clazz.field("java.lang.Object", "same");
+    FieldSubject f2 = clazz.field("java.lang.Object", REPEATED_NAME);
     assertTrue(f2.isPresent());
     assertTrue(f2.isRenamed());
     assertEquals(f1.getFinalName(), f2.getFinalName());
 
-    ProcessResult artOutput = runOnArtRaw(app, CLASS_NAME);
-    assertEquals(0, artOutput.exitCode);
-    assertEquals(javaOutput.stdout, artOutput.stdout);
+    ProcessResult output = runRaw(app, CLASS_NAME);
+    assertEquals(0, output.exitCode);
+    assertEquals(javaOutput.stdout, output.stdout);
   }
 
   private JasminBuilder buildMethodNameConflictClassFile() {
     JasminBuilder builder = new JasminBuilder();
     ClassBuilder classBuilder = builder.addClass(ANOTHER_CLASS);
-    classBuilder.addStaticMethod("same", ImmutableList.of(), "Ljava/lang/Object;",
-        "aconst_null",
-        "areturn");
-    classBuilder.addStaticMethod("same", ImmutableList.of(), "Ljava/lang/String;",
-        "ldc \"" + MSG + "\"",
-        "areturn");
+    classBuilder.addStaticMethod(
+        REPEATED_NAME, ImmutableList.of(), "Ljava/lang/Object;", "aconst_null", "areturn");
+    classBuilder.addStaticMethod(
+        REPEATED_NAME, ImmutableList.of(), "Ljava/lang/String;", "ldc \"" + MSG + "\"", "areturn");
     classBuilder = builder.addClass(CLASS_NAME);
     classBuilder.addMainMethod(
         buildCodeForVisitingDeclaredMembers(
@@ -261,22 +287,22 @@
             + "}\n",
         keepMainProguardConfiguration(CLASS_NAME),
         "-dontshrink");
-    AndroidApp app = compileWithR8(builder, pgConfigs, null);
+    AndroidApp app = compileWithR8(builder, pgConfigs, null, backend);
 
     CodeInspector codeInspector = new CodeInspector(app);
     ClassSubject clazz = codeInspector.clazz(ANOTHER_CLASS);
     assertTrue(clazz.isPresent());
-    MethodSubject m1 = clazz.method("java.lang.String", "same", ImmutableList.of());
+    MethodSubject m1 = clazz.method("java.lang.String", REPEATED_NAME, ImmutableList.of());
     assertTrue(m1.isPresent());
     assertFalse(m1.isRenamed());
-    MethodSubject m2 = clazz.method("java.lang.Object", "same", ImmutableList.of());
+    MethodSubject m2 = clazz.method("java.lang.Object", REPEATED_NAME, ImmutableList.of());
     assertTrue(m2.isPresent());
     assertFalse(m2.isRenamed());
     assertEquals(m1.getFinalName(), m2.getFinalName());
 
-    ProcessResult artOutput = runOnArtRaw(app, CLASS_NAME);
-    assertEquals(0, artOutput.exitCode);
-    assertEquals(javaOutput.stdout, artOutput.stdout);
+    ProcessResult output = runRaw(app, CLASS_NAME);
+    assertEquals(0, output.exitCode);
+    assertEquals(javaOutput.stdout, output.stdout);
   }
 
   @Test
@@ -289,22 +315,22 @@
         keepMainProguardConfiguration(CLASS_NAME),
         "-useuniqueclassmembernames",
         "-dontshrink");
-    AndroidApp app = compileWithR8(builder, pgConfigs, null);
+    AndroidApp app = compileWithR8(builder, pgConfigs, null, backend);
 
     CodeInspector codeInspector = new CodeInspector(app);
     ClassSubject clazz = codeInspector.clazz(ANOTHER_CLASS);
     assertTrue(clazz.isPresent());
-    MethodSubject m1 = clazz.method("java.lang.String", "same", ImmutableList.of());
+    MethodSubject m1 = clazz.method("java.lang.String", REPEATED_NAME, ImmutableList.of());
     assertTrue(m1.isPresent());
     assertTrue(m1.isRenamed());
-    MethodSubject m2 = clazz.method("java.lang.Object", "same", ImmutableList.of());
+    MethodSubject m2 = clazz.method("java.lang.Object", REPEATED_NAME, ImmutableList.of());
     assertTrue(m2.isPresent());
     assertTrue(m2.isRenamed());
     assertEquals(m1.getFinalName(), m2.getFinalName());
 
-    ProcessResult artOutput = runOnArtRaw(app, CLASS_NAME);
-    assertEquals(0, artOutput.exitCode);
-    assertEquals(javaOutput.stdout, artOutput.stdout);
+    ProcessResult output = runRaw(app, CLASS_NAME);
+    assertEquals(0, output.exitCode);
+    assertEquals(javaOutput.stdout, output.stdout);
   }
 
   @Test
@@ -319,22 +345,22 @@
         "-useuniqueclassmembernames",
         "-overloadaggressively",  // no-op
         "-dontshrink");
-    AndroidApp app = compileWithR8(builder, pgConfigs, null);
+    AndroidApp app = compileWithR8(builder, pgConfigs, null, backend);
 
     CodeInspector codeInspector = new CodeInspector(app);
     ClassSubject clazz = codeInspector.clazz(ANOTHER_CLASS);
     assertTrue(clazz.isPresent());
-    MethodSubject m1 = clazz.method("java.lang.String", "same", ImmutableList.of());
+    MethodSubject m1 = clazz.method("java.lang.String", REPEATED_NAME, ImmutableList.of());
     assertTrue(m1.isPresent());
     assertTrue(m1.isRenamed());
-    MethodSubject m2 = clazz.method("java.lang.Object", "same", ImmutableList.of());
+    MethodSubject m2 = clazz.method("java.lang.Object", REPEATED_NAME, ImmutableList.of());
     assertTrue(m2.isPresent());
     assertTrue(m2.isRenamed());
     assertEquals(m1.getFinalName(), m2.getFinalName());
 
-    ProcessResult artOutput = runOnArtRaw(app, CLASS_NAME);
-    assertEquals(0, artOutput.exitCode);
-    assertEquals(javaOutput.stdout, artOutput.stdout);
+    ProcessResult output = runRaw(app, CLASS_NAME);
+    assertEquals(0, output.exitCode);
+    assertEquals(javaOutput.stdout, output.stdout);
   }
 
   @Test
@@ -346,22 +372,24 @@
     List<String> pgConfigs = ImmutableList.of(
         keepMainProguardConfiguration(CLASS_NAME),
         "-dontshrink");
-    AndroidApp app = compileWithR8(builder, pgConfigs, null);
+    AndroidApp app = compileWithR8(builder, pgConfigs, null, backend);
 
     CodeInspector codeInspector = new CodeInspector(app);
     ClassSubject clazz = codeInspector.clazz(ANOTHER_CLASS);
     assertTrue(clazz.isPresent());
-    MethodSubject m1 = clazz.method("java.lang.String", "same", ImmutableList.of());
+    MethodSubject m1 = clazz.method("java.lang.String", REPEATED_NAME, ImmutableList.of());
     assertTrue(m1.isPresent());
     assertTrue(m1.isRenamed());
-    MethodSubject m2 = clazz.method("java.lang.Object", "same", ImmutableList.of());
+    MethodSubject m2 = clazz.method("java.lang.Object", REPEATED_NAME, ImmutableList.of());
     assertTrue(m2.isPresent());
     assertTrue(m2.isRenamed());
     assertNotEquals(m1.getFinalName(), m2.getFinalName());
 
-    ProcessResult artOutput = runOnArtRaw(app, CLASS_NAME);
-    assertEquals(0, artOutput.exitCode);
-    assertEquals(javaOutput.stdout, artOutput.stdout);
+    ProcessResult output = runRaw(app, CLASS_NAME);
+    assertEquals(0, output.exitCode);
+    assertEquals(
+        new HashSet<String>(StringUtils.splitLines(javaOutput.stdout)),
+        new HashSet<String>(StringUtils.splitLines(output.stdout)));
   }
 
   @Test
@@ -374,41 +402,45 @@
         keepMainProguardConfiguration(CLASS_NAME),
         "-overloadaggressively",
         "-dontshrink");
-    AndroidApp app = compileWithR8(builder, pgConfigs, null);
+    AndroidApp app = compileWithR8(builder, pgConfigs, null, backend);
 
     CodeInspector codeInspector = new CodeInspector(app);
     ClassSubject clazz = codeInspector.clazz(ANOTHER_CLASS);
     assertTrue(clazz.isPresent());
-    MethodSubject m1 = clazz.method("java.lang.String", "same", ImmutableList.of());
+    MethodSubject m1 = clazz.method("java.lang.String", REPEATED_NAME, ImmutableList.of());
     assertTrue(m1.isPresent());
     assertTrue(m1.isRenamed());
-    MethodSubject m2 = clazz.method("java.lang.Object", "same", ImmutableList.of());
+    MethodSubject m2 = clazz.method("java.lang.Object", REPEATED_NAME, ImmutableList.of());
     assertTrue(m2.isPresent());
     assertTrue(m2.isRenamed());
     assertEquals(m1.getFinalName(), m2.getFinalName());
 
-    ProcessResult artOutput = runOnArtRaw(app, CLASS_NAME);
-    assertEquals(0, artOutput.exitCode);
-    assertEquals(javaOutput.stdout, artOutput.stdout);
+    ProcessResult output = runRaw(app, CLASS_NAME);
+    assertEquals(0, output.exitCode);
+    assertEquals(javaOutput.stdout, output.stdout);
   }
 
   private JasminBuilder buildMethodNameConflictInHierarchy() {
     JasminBuilder builder = new JasminBuilder();
     ClassBuilder classBuilder = builder.addClass(SUPER_CLASS);
-    classBuilder.addVirtualMethod("same", ImmutableList.of(), "Ljava/lang/Object;",
-        "aconst_null",
-        "areturn");
-    classBuilder.addVirtualMethod("same", ImmutableList.of(), "Ljava/lang/String;",
-        "ldc \"" + MSG + "\"",
-        "areturn");
+    classBuilder.addVirtualMethod(
+        REPEATED_NAME, ImmutableList.of(), "Ljava/lang/Object;", "aconst_null", "areturn");
+    classBuilder.addVirtualMethod(
+        REPEATED_NAME, ImmutableList.of(), "Ljava/lang/String;", "ldc \"" + MSG + "\"", "areturn");
     classBuilder = builder.addClass(ANOTHER_CLASS, SUPER_CLASS);
-    classBuilder.addVirtualMethod("same", ImmutableList.of(), "Ljava/lang/Object;",
+    classBuilder.addVirtualMethod(
+        REPEATED_NAME,
+        ImmutableList.of(),
+        "Ljava/lang/Object;",
         "aload_0",
-        "invokespecial " + SUPER_CLASS + "/same()Ljava/lang/Object;",
+        "invokespecial " + SUPER_CLASS + "/" + REPEATED_NAME + "()Ljava/lang/Object;",
         "areturn");
-    classBuilder.addVirtualMethod("same", ImmutableList.of(), "Ljava/lang/String;",
+    classBuilder.addVirtualMethod(
+        REPEATED_NAME,
+        ImmutableList.of(),
+        "Ljava/lang/String;",
         "aload_0",
-        "invokespecial " + SUPER_CLASS + "/same()Ljava/lang/String;",
+        "invokespecial " + SUPER_CLASS + "/" + REPEATED_NAME + "()Ljava/lang/String;",
         "areturn");
     classBuilder = builder.addClass(CLASS_NAME);
     classBuilder.addMainMethod(
@@ -443,25 +475,25 @@
             + "}\n",
         keepMainProguardConfiguration(CLASS_NAME),
         "-dontshrink");
-    AndroidApp app = compileWithR8(builder, pgConfigs, null);
+    AndroidApp app = compileWithR8(builder, pgConfigs, null, backend);
 
     CodeInspector codeInspector = new CodeInspector(app);
     ClassSubject sup = codeInspector.clazz(SUPER_CLASS);
     assertTrue(sup.isPresent());
-    MethodSubject m1 = sup.method("java.lang.String", "same", ImmutableList.of());
+    MethodSubject m1 = sup.method("java.lang.String", REPEATED_NAME, ImmutableList.of());
     assertTrue(m1.isPresent());
     assertFalse(m1.isRenamed());
-    MethodSubject m2 = sup.method("java.lang.Object", "same", ImmutableList.of());
+    MethodSubject m2 = sup.method("java.lang.Object", REPEATED_NAME, ImmutableList.of());
     assertTrue(m2.isPresent());
     assertFalse(m2.isRenamed());
     assertEquals(m1.getFinalName(), m2.getFinalName());
 
     ClassSubject sub = codeInspector.clazz(ANOTHER_CLASS);
     assertTrue(sub.isPresent());
-    MethodSubject subM1 = sub.method("java.lang.String", "same", ImmutableList.of());
+    MethodSubject subM1 = sub.method("java.lang.String", REPEATED_NAME, ImmutableList.of());
     assertTrue(subM1.isPresent());
     assertFalse(subM1.isRenamed());
-    MethodSubject subM2 = sub.method("java.lang.Object", "same", ImmutableList.of());
+    MethodSubject subM2 = sub.method("java.lang.Object", REPEATED_NAME, ImmutableList.of());
     assertTrue(subM2.isPresent());
     assertFalse(subM2.isRenamed());
     assertEquals(subM1.getFinalName(), subM2.getFinalName());
@@ -470,9 +502,9 @@
     assertEquals(m1.getFinalName(), subM1.getFinalName());
     assertEquals(m2.getFinalName(), subM2.getFinalName());
 
-    ProcessResult artOutput = runOnArtRaw(app, CLASS_NAME);
-    assertEquals(0, artOutput.exitCode);
-    assertEquals(javaOutput.stdout, artOutput.stdout);
+    ProcessResult output = runRaw(app, CLASS_NAME);
+    assertEquals(0, output.exitCode);
+    assertEquals(javaOutput.stdout, output.stdout);
   }
 
   @Test
@@ -485,25 +517,25 @@
         keepMainProguardConfiguration(CLASS_NAME),
         "-useuniqueclassmembernames",
         "-dontshrink");
-    AndroidApp app = compileWithR8(builder, pgConfigs, null);
+    AndroidApp app = compileWithR8(builder, pgConfigs, null, backend);
 
     CodeInspector codeInspector = new CodeInspector(app);
     ClassSubject sup = codeInspector.clazz(SUPER_CLASS);
     assertTrue(sup.isPresent());
-    MethodSubject m1 = sup.method("java.lang.String", "same", ImmutableList.of());
+    MethodSubject m1 = sup.method("java.lang.String", REPEATED_NAME, ImmutableList.of());
     assertTrue(m1.isPresent());
     assertTrue(m1.isRenamed());
-    MethodSubject m2 = sup.method("java.lang.Object", "same", ImmutableList.of());
+    MethodSubject m2 = sup.method("java.lang.Object", REPEATED_NAME, ImmutableList.of());
     assertTrue(m2.isPresent());
     assertTrue(m2.isRenamed());
     assertEquals(m1.getFinalName(), m2.getFinalName());
 
     ClassSubject sub = codeInspector.clazz(ANOTHER_CLASS);
     assertTrue(sub.isPresent());
-    MethodSubject subM1 = sub.method("java.lang.String", "same", ImmutableList.of());
+    MethodSubject subM1 = sub.method("java.lang.String", REPEATED_NAME, ImmutableList.of());
     assertTrue(subM1.isPresent());
     assertTrue(subM1.isRenamed());
-    MethodSubject subM2 = sub.method("java.lang.Object", "same", ImmutableList.of());
+    MethodSubject subM2 = sub.method("java.lang.Object", REPEATED_NAME, ImmutableList.of());
     assertTrue(subM2.isPresent());
     assertTrue(subM2.isRenamed());
     assertEquals(subM1.getFinalName(), subM2.getFinalName());
@@ -512,9 +544,9 @@
     assertEquals(m1.getFinalName(), subM1.getFinalName());
     assertEquals(m2.getFinalName(), subM2.getFinalName());
 
-    ProcessResult artOutput = runOnArtRaw(app, CLASS_NAME);
-    assertEquals(0, artOutput.exitCode);
-    assertEquals(javaOutput.stdout, artOutput.stdout);
+    ProcessResult output = runRaw(app, CLASS_NAME);
+    assertEquals(0, output.exitCode);
+    assertEquals(javaOutput.stdout, output.stdout);
   }
 
   @Test
@@ -529,25 +561,25 @@
         "-useuniqueclassmembernames",
         "-overloadaggressively",  // no-op
         "-dontshrink");
-    AndroidApp app = compileWithR8(builder, pgConfigs, null);
+    AndroidApp app = compileWithR8(builder, pgConfigs, null, backend);
 
     CodeInspector codeInspector = new CodeInspector(app);
     ClassSubject sup = codeInspector.clazz(SUPER_CLASS);
     assertTrue(sup.isPresent());
-    MethodSubject m1 = sup.method("java.lang.String", "same", ImmutableList.of());
+    MethodSubject m1 = sup.method("java.lang.String", REPEATED_NAME, ImmutableList.of());
     assertTrue(m1.isPresent());
     assertTrue(m1.isRenamed());
-    MethodSubject m2 = sup.method("java.lang.Object", "same", ImmutableList.of());
+    MethodSubject m2 = sup.method("java.lang.Object", REPEATED_NAME, ImmutableList.of());
     assertTrue(m2.isPresent());
     assertTrue(m2.isRenamed());
     assertEquals(m1.getFinalName(), m2.getFinalName());
 
     ClassSubject sub = codeInspector.clazz(ANOTHER_CLASS);
     assertTrue(sub.isPresent());
-    MethodSubject subM1 = sub.method("java.lang.String", "same", ImmutableList.of());
+    MethodSubject subM1 = sub.method("java.lang.String", REPEATED_NAME, ImmutableList.of());
     assertTrue(subM1.isPresent());
     assertTrue(subM1.isRenamed());
-    MethodSubject subM2 = sub.method("java.lang.Object", "same", ImmutableList.of());
+    MethodSubject subM2 = sub.method("java.lang.Object", REPEATED_NAME, ImmutableList.of());
     assertTrue(subM2.isPresent());
     assertTrue(subM2.isRenamed());
     assertEquals(subM1.getFinalName(), subM2.getFinalName());
@@ -556,9 +588,9 @@
     assertEquals(m1.getFinalName(), subM1.getFinalName());
     assertEquals(m2.getFinalName(), subM2.getFinalName());
 
-    ProcessResult artOutput = runOnArtRaw(app, CLASS_NAME);
-    assertEquals(0, artOutput.exitCode);
-    assertEquals(javaOutput.stdout, artOutput.stdout);
+    ProcessResult output = runRaw(app, CLASS_NAME);
+    assertEquals(0, output.exitCode);
+    assertEquals(javaOutput.stdout, output.stdout);
   }
 
   @Test
@@ -570,25 +602,25 @@
     List<String> pgConfigs = ImmutableList.of(
         keepMainProguardConfiguration(CLASS_NAME),
         "-dontshrink");
-    AndroidApp app = compileWithR8(builder, pgConfigs, null);
+    AndroidApp app = compileWithR8(builder, pgConfigs, null, backend);
 
     CodeInspector codeInspector = new CodeInspector(app);
     ClassSubject sup = codeInspector.clazz(SUPER_CLASS);
     assertTrue(sup.isPresent());
-    MethodSubject m1 = sup.method("java.lang.String", "same", ImmutableList.of());
+    MethodSubject m1 = sup.method("java.lang.String", REPEATED_NAME, ImmutableList.of());
     assertTrue(m1.isPresent());
     assertTrue(m1.isRenamed());
-    MethodSubject m2 = sup.method("java.lang.Object", "same", ImmutableList.of());
+    MethodSubject m2 = sup.method("java.lang.Object", REPEATED_NAME, ImmutableList.of());
     assertTrue(m2.isPresent());
     assertTrue(m2.isRenamed());
     assertNotEquals(m1.getFinalName(), m2.getFinalName());
 
     ClassSubject sub = codeInspector.clazz(ANOTHER_CLASS);
     assertTrue(sub.isPresent());
-    MethodSubject subM1 = sub.method("java.lang.String", "same", ImmutableList.of());
+    MethodSubject subM1 = sub.method("java.lang.String", REPEATED_NAME, ImmutableList.of());
     assertTrue(subM1.isPresent());
     assertTrue(subM1.isRenamed());
-    MethodSubject subM2 = sub.method("java.lang.Object", "same", ImmutableList.of());
+    MethodSubject subM2 = sub.method("java.lang.Object", REPEATED_NAME, ImmutableList.of());
     assertTrue(subM2.isPresent());
     assertTrue(subM2.isRenamed());
     assertNotEquals(subM1.getFinalName(), subM2.getFinalName());
@@ -597,9 +629,11 @@
     assertEquals(m1.getFinalName(), subM1.getFinalName());
     assertEquals(m2.getFinalName(), subM2.getFinalName());
 
-    ProcessResult artOutput = runOnArtRaw(app, CLASS_NAME);
-    assertEquals(0, artOutput.exitCode);
-    assertEquals(javaOutput.stdout, artOutput.stdout);
+    ProcessResult output = runRaw(app, CLASS_NAME);
+    assertEquals(0, output.exitCode);
+    assertEquals(
+        new HashSet<String>(StringUtils.splitLines(javaOutput.stdout)),
+        new HashSet<String>(StringUtils.splitLines(output.stdout)));
   }
 
   @Test
@@ -612,26 +646,26 @@
         keepMainProguardConfiguration(CLASS_NAME),
         "-overloadaggressively",
         "-dontshrink");
-    AndroidApp app = compileWithR8(builder, pgConfigs, null);
+    AndroidApp app = compileWithR8(builder, pgConfigs, null, backend);
 
     CodeInspector codeInspector = new CodeInspector(app);
 
     ClassSubject sup = codeInspector.clazz(SUPER_CLASS);
     assertTrue(sup.isPresent());
-    MethodSubject m1 = sup.method("java.lang.String", "same", ImmutableList.of());
+    MethodSubject m1 = sup.method("java.lang.String", REPEATED_NAME, ImmutableList.of());
     assertTrue(m1.isPresent());
     assertTrue(m1.isRenamed());
-    MethodSubject m2 = sup.method("java.lang.Object", "same", ImmutableList.of());
+    MethodSubject m2 = sup.method("java.lang.Object", REPEATED_NAME, ImmutableList.of());
     assertTrue(m2.isPresent());
     assertTrue(m2.isRenamed());
     assertEquals(m1.getFinalName(), m2.getFinalName());
 
     ClassSubject sub = codeInspector.clazz(ANOTHER_CLASS);
     assertTrue(sub.isPresent());
-    MethodSubject subM1 = sub.method("java.lang.String", "same", ImmutableList.of());
+    MethodSubject subM1 = sub.method("java.lang.String", REPEATED_NAME, ImmutableList.of());
     assertTrue(subM1.isPresent());
     assertTrue(subM1.isRenamed());
-    MethodSubject subM2 = sub.method("java.lang.Object", "same", ImmutableList.of());
+    MethodSubject subM2 = sub.method("java.lang.Object", REPEATED_NAME, ImmutableList.of());
     assertTrue(subM2.isPresent());
     assertTrue(subM2.isRenamed());
     assertEquals(subM1.getFinalName(), subM2.getFinalName());
@@ -640,8 +674,8 @@
     assertEquals(m1.getFinalName(), subM1.getFinalName());
     assertEquals(m2.getFinalName(), subM2.getFinalName());
 
-    ProcessResult artOutput = runOnArtRaw(app, CLASS_NAME);
-    assertEquals(0, artOutput.exitCode);
-    assertEquals(javaOutput.stdout, artOutput.stdout);
+    ProcessResult output = runRaw(app, CLASS_NAME);
+    assertEquals(0, output.exitCode);
+    assertEquals(javaOutput.stdout, output.stdout);
   }
 }
diff --git a/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingEnumprotoTest.java b/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingEnumprotoTest.java
deleted file mode 100644
index 7f211db..0000000
--- a/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingEnumprotoTest.java
+++ /dev/null
@@ -1,59 +0,0 @@
-// 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.shaking.examples;
-
-import com.android.tools.r8.TestBase.MinifyMode;
-import com.android.tools.r8.shaking.TreeShakingTest;
-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.ArrayList;
-import java.util.Collection;
-import java.util.List;
-import org.junit.Assert;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.Parameterized;
-import org.junit.runners.Parameterized.Parameters;
-
-@RunWith(Parameterized.class)
-public class TreeShakingEnumprotoTest extends TreeShakingTest {
-
-  @Parameters(name = "mode:{0}-{1} minify:{2}")
-  public static Collection<Object[]> data() {
-    List<Object[]> parameters = new ArrayList<>();
-    for (MinifyMode minify : MinifyMode.values()) {
-      parameters.add(new Object[] {Frontend.JAR, Backend.CF, minify});
-      parameters.add(new Object[] {Frontend.JAR, Backend.DEX, minify});
-      parameters.add(new Object[] {Frontend.DEX, Backend.DEX, minify});
-    }
-    return parameters;
-  }
-
-  public TreeShakingEnumprotoTest(Frontend frontend, Backend backend, MinifyMode minify) {
-    super("examples/enumproto", "enumproto.Enumproto", frontend, backend, minify);
-  }
-
-  @Test
-  public void test() throws Exception {
-    runTest(
-        TreeShakingEnumprotoTest::enumprotoUnusedFieldsAreGone,
-        null,
-        null,
-        ImmutableList.of("src/test/examples/enumproto/keep-rules.txt"));
-  }
-
-  private static void enumprotoUnusedFieldsAreGone(CodeInspector inspector) {
-    ClassSubject protoClass = inspector.clazz("enumproto.GeneratedEnumProto$Enum");
-    Assert.assertTrue(protoClass.isPresent());
-    Assert.assertFalse(protoClass.field("int", "id_").isPresent());
-    Assert.assertTrue(protoClass.field("int", "enum_").isPresent());
-    Assert.assertFalse(protoClass.field("int", "other_").isPresent());
-    ClassSubject protoThreeClass = inspector.clazz("enumproto.three.GeneratedEnumProto$EnumThree");
-    Assert.assertTrue(protoThreeClass.isPresent());
-    Assert.assertFalse(protoThreeClass.field("int", "id_").isPresent());
-    Assert.assertTrue(protoThreeClass.field("int", "enum_").isPresent());
-    Assert.assertFalse(protoThreeClass.field("int", "other_").isPresent());
-  }
-}
diff --git a/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingNestedproto1Test.java b/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingNestedproto1Test.java
deleted file mode 100644
index 16b5f59..0000000
--- a/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingNestedproto1Test.java
+++ /dev/null
@@ -1,61 +0,0 @@
-// 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.shaking.examples;
-
-import com.android.tools.r8.TestBase.MinifyMode;
-import com.android.tools.r8.shaking.TreeShakingTest;
-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.ArrayList;
-import java.util.Collection;
-import java.util.List;
-import org.junit.Assert;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.Parameterized;
-import org.junit.runners.Parameterized.Parameters;
-
-@RunWith(Parameterized.class)
-public class TreeShakingNestedproto1Test extends TreeShakingTest {
-
-  @Parameters(name = "mode:{0}-{1} minify:{2}")
-  public static Collection<Object[]> data() {
-    List<Object[]> parameters = new ArrayList<>();
-    for (MinifyMode minify : MinifyMode.values()) {
-      parameters.add(new Object[] {Frontend.JAR, Backend.CF, minify});
-      parameters.add(new Object[] {Frontend.JAR, Backend.DEX, minify});
-      parameters.add(new Object[] {Frontend.DEX, Backend.DEX, minify});
-    }
-    return parameters;
-  }
-
-  public TreeShakingNestedproto1Test(Frontend frontend, Backend backend, MinifyMode minify) {
-    super("examples/nestedproto1", "nestedproto1.Nestedproto", frontend, backend, minify);
-  }
-
-  @Test
-  public void test() throws Exception {
-    runTest(
-        TreeShakingNestedproto1Test::nestedproto1UnusedFieldsAreGone,
-        null,
-        null,
-        ImmutableList.of("src/test/examples/nestedproto1/keep-rules.txt"));
-  }
-
-  private static void nestedproto1UnusedFieldsAreGone(CodeInspector inspector) {
-    ClassSubject protoClass = inspector.clazz("nestedproto1.GeneratedNestedProto$Outer");
-    Assert.assertTrue(protoClass.isPresent());
-    Assert.assertFalse(protoClass.field("int", "id_").isPresent());
-    Assert.assertTrue(
-        protoClass.field("nestedproto1.GeneratedNestedProto$NestedOne", "inner_").isPresent());
-    Assert.assertFalse(
-        protoClass.field("nestedproto1.GeneratedNestedProto$NestedTwo", "inner2_").isPresent());
-    ClassSubject nestedOne = inspector.clazz("nestedproto1.GeneratedNestedProto$NestedOne");
-    Assert.assertTrue(nestedOne.isPresent());
-    Assert.assertTrue(nestedOne.field("java.lang.String", "other_").isPresent());
-    Assert.assertFalse(nestedOne.field("int", "id_").isPresent());
-    Assert.assertFalse(inspector.clazz("nestedproto1.GeneratedNestedProto$NestedTwo").isPresent());
-  }
-}
diff --git a/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingNestedproto2Test.java b/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingNestedproto2Test.java
deleted file mode 100644
index a679810..0000000
--- a/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingNestedproto2Test.java
+++ /dev/null
@@ -1,58 +0,0 @@
-// 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.shaking.examples;
-
-import com.android.tools.r8.TestBase.MinifyMode;
-import com.android.tools.r8.shaking.TreeShakingTest;
-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.ArrayList;
-import java.util.Collection;
-import java.util.List;
-import org.junit.Assert;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.Parameterized;
-import org.junit.runners.Parameterized.Parameters;
-
-@RunWith(Parameterized.class)
-public class TreeShakingNestedproto2Test extends TreeShakingTest {
-
-  @Parameters(name = "mode:{0}-{1} minify:{2}")
-  public static Collection<Object[]> data() {
-    List<Object[]> parameters = new ArrayList<>();
-    for (MinifyMode minify : MinifyMode.values()) {
-      parameters.add(new Object[] {Frontend.JAR, Backend.CF, minify});
-      parameters.add(new Object[] {Frontend.JAR, Backend.DEX, minify});
-      parameters.add(new Object[] {Frontend.DEX, Backend.DEX, minify});
-    }
-    return parameters;
-  }
-
-  public TreeShakingNestedproto2Test(Frontend frontend, Backend backend, MinifyMode minify) {
-    super("examples/nestedproto2", "nestedproto2.Nestedproto", frontend, backend, minify);
-  }
-
-  @Test
-  public void test() throws Exception {
-    runTest(
-        TreeShakingNestedproto2Test::nestedproto2UnusedFieldsAreGone,
-        null,
-        null,
-        ImmutableList.of("src/test/examples/nestedproto2/keep-rules.txt"));
-  }
-
-  private static void nestedproto2UnusedFieldsAreGone(CodeInspector inspector) {
-    ClassSubject protoClass = inspector.clazz("nestedproto2.GeneratedNestedProto$Outer");
-    Assert.assertTrue(protoClass.isPresent());
-    Assert.assertTrue(protoClass.field("int", "id_").isPresent());
-    Assert.assertFalse(
-        protoClass.field("nestedproto2.GeneratedNestedProto$NestedOne", "inner_").isPresent());
-    Assert.assertFalse(
-        protoClass.field("nestedproto2.GeneratedNestedProto$NestedTwo", "inner2_").isPresent());
-    Assert.assertFalse(inspector.clazz("nestedproto2.GeneratedNestedProto$NestedOne").isPresent());
-    Assert.assertFalse(inspector.clazz("nestedproto2.GeneratedNestedProto$NestedTwo").isPresent());
-  }
-}
diff --git a/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingOneofprotoTest.java b/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingOneofprotoTest.java
deleted file mode 100644
index e38258c..0000000
--- a/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingOneofprotoTest.java
+++ /dev/null
@@ -1,53 +0,0 @@
-// 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.shaking.examples;
-
-import com.android.tools.r8.TestBase.MinifyMode;
-import com.android.tools.r8.shaking.TreeShakingTest;
-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.ArrayList;
-import java.util.Collection;
-import java.util.List;
-import org.junit.Assert;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.Parameterized;
-import org.junit.runners.Parameterized.Parameters;
-
-@RunWith(Parameterized.class)
-public class TreeShakingOneofprotoTest extends TreeShakingTest {
-
-  @Parameters(name = "mode:{0}-{1} minify:{2}")
-  public static Collection<Object[]> data() {
-    List<Object[]> parameters = new ArrayList<>();
-    for (MinifyMode minify : MinifyMode.values()) {
-      parameters.add(new Object[] {Frontend.JAR, Backend.CF, minify});
-      parameters.add(new Object[] {Frontend.JAR, Backend.DEX, minify});
-      parameters.add(new Object[] {Frontend.DEX, Backend.DEX, minify});
-    }
-    return parameters;
-  }
-
-  public TreeShakingOneofprotoTest(Frontend frontend, Backend backend, MinifyMode minify) {
-    super("examples/oneofproto", "oneofproto.Oneofproto", frontend, backend, minify);
-  }
-
-  @Test
-  public void test() throws Exception {
-    runTest(
-        TreeShakingOneofprotoTest::oneofprotoUnusedFieldsAreGone,
-        null,
-        null,
-        ImmutableList.of("src/test/examples/oneofproto/keep-rules.txt"));
-  }
-
-  private static void oneofprotoUnusedFieldsAreGone(CodeInspector inspector) {
-    ClassSubject protoClass = inspector.clazz("oneofproto.GeneratedOneOfProto$Oneof");
-    Assert.assertTrue(protoClass.isPresent());
-    Assert.assertFalse(protoClass.field("int", "id_").isPresent());
-    Assert.assertFalse(protoClass.field("Object", "otherfields_").isPresent());
-  }
-}
diff --git a/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingRepeatedprotoTest.java b/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingRepeatedprotoTest.java
deleted file mode 100644
index 923cf34..0000000
--- a/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingRepeatedprotoTest.java
+++ /dev/null
@@ -1,58 +0,0 @@
-// 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.shaking.examples;
-
-import com.android.tools.r8.TestBase.MinifyMode;
-import com.android.tools.r8.shaking.TreeShakingTest;
-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.ArrayList;
-import java.util.Collection;
-import java.util.List;
-import org.junit.Assert;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.Parameterized;
-import org.junit.runners.Parameterized.Parameters;
-
-@RunWith(Parameterized.class)
-public class TreeShakingRepeatedprotoTest extends TreeShakingTest {
-
-  @Parameters(name = "mode:{0}-{1} minify:{2}")
-  public static Collection<Object[]> data() {
-    List<Object[]> parameters = new ArrayList<>();
-    for (MinifyMode minify : MinifyMode.values()) {
-      parameters.add(new Object[] {Frontend.JAR, Backend.CF, minify});
-      parameters.add(new Object[] {Frontend.JAR, Backend.DEX, minify});
-      parameters.add(new Object[] {Frontend.DEX, Backend.DEX, minify});
-    }
-    return parameters;
-  }
-
-  public TreeShakingRepeatedprotoTest(Frontend frontend, Backend backend, MinifyMode minify) {
-    super("examples/repeatedproto", "repeatedproto.Repeatedproto", frontend, backend, minify);
-  }
-
-  @Test
-  public void test() throws Exception {
-    runTest(
-        TreeShakingRepeatedprotoTest::repeatedUnusedFieldsAreGone,
-        null,
-        null,
-        ImmutableList.of("src/test/examples/repeatedproto/keep-rules.txt"));
-  }
-
-  private static void repeatedUnusedFieldsAreGone(CodeInspector inspector) {
-    ClassSubject protoClass = inspector.clazz("repeatedproto.GeneratedRepeatedProto$Repeated");
-    Assert.assertTrue(protoClass.isPresent());
-    Assert.assertFalse(protoClass.field("int", "id_").isPresent());
-    Assert.assertTrue(
-        protoClass.field("com.google.protobuf.Internal$ProtobufList", "repeated_").isPresent());
-    Assert.assertFalse(
-        protoClass.field("com.google.protobuf.Internal$ProtobufList", "sub_").isPresent());
-    Assert.assertFalse(
-        protoClass.field("com.google.protobuf.Internal$BooleanList", "other_").isPresent());
-  }
-}
diff --git a/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingSimpleproto1Test.java b/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingSimpleproto1Test.java
deleted file mode 100644
index 64e3839..0000000
--- a/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingSimpleproto1Test.java
+++ /dev/null
@@ -1,52 +0,0 @@
-// 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.shaking.examples;
-
-import com.android.tools.r8.TestBase.MinifyMode;
-import com.android.tools.r8.shaking.TreeShakingTest;
-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.ArrayList;
-import java.util.Collection;
-import java.util.List;
-import org.junit.Assert;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.Parameterized;
-import org.junit.runners.Parameterized.Parameters;
-
-@RunWith(Parameterized.class)
-public class TreeShakingSimpleproto1Test extends TreeShakingTest {
-
-  @Parameters(name = "mode:{0}-{1} minify:{2}")
-  public static Collection<Object[]> data() {
-    List<Object[]> parameters = new ArrayList<>();
-    for (MinifyMode minify : MinifyMode.values()) {
-      parameters.add(new Object[] {Frontend.JAR, Backend.CF, minify});
-      parameters.add(new Object[] {Frontend.JAR, Backend.DEX, minify});
-      parameters.add(new Object[] {Frontend.DEX, Backend.DEX, minify});
-    }
-    return parameters;
-  }
-
-  public TreeShakingSimpleproto1Test(Frontend frontend, Backend backend, MinifyMode minify) {
-    super("examples/simpleproto1", "simpleproto1.Simpleproto", frontend, backend, minify);
-  }
-
-  @Test
-  public void test() throws Exception {
-    runTest(
-        TreeShakingSimpleproto1Test::simpleproto1UnusedFieldIsGone,
-        null,
-        null,
-        ImmutableList.of("src/test/examples/simpleproto1/keep-rules.txt"));
-  }
-
-  private static void simpleproto1UnusedFieldIsGone(CodeInspector inspector) {
-    ClassSubject protoClass = inspector.clazz("simpleproto1.GeneratedSimpleProto$Simple");
-    Assert.assertTrue(protoClass.isPresent());
-    Assert.assertFalse(protoClass.field("boolean", "other_").isPresent());
-  }
-}
diff --git a/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingSimpleproto2Test.java b/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingSimpleproto2Test.java
deleted file mode 100644
index 5304dae..0000000
--- a/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingSimpleproto2Test.java
+++ /dev/null
@@ -1,54 +0,0 @@
-// 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.shaking.examples;
-
-import com.android.tools.r8.TestBase.MinifyMode;
-import com.android.tools.r8.shaking.TreeShakingTest;
-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.ArrayList;
-import java.util.Collection;
-import java.util.List;
-import org.junit.Assert;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.Parameterized;
-import org.junit.runners.Parameterized.Parameters;
-
-@RunWith(Parameterized.class)
-public class TreeShakingSimpleproto2Test extends TreeShakingTest {
-
-  @Parameters(name = "mode:{0}-{1} minify:{2}")
-  public static Collection<Object[]> data() {
-    List<Object[]> parameters = new ArrayList<>();
-    for (MinifyMode minify : MinifyMode.values()) {
-      parameters.add(new Object[] {Frontend.JAR, Backend.CF, minify});
-      parameters.add(new Object[] {Frontend.JAR, Backend.DEX, minify});
-      parameters.add(new Object[] {Frontend.DEX, Backend.DEX, minify});
-    }
-    return parameters;
-  }
-
-  public TreeShakingSimpleproto2Test(Frontend frontend, Backend backend, MinifyMode minify) {
-    super("examples/simpleproto2", "simpleproto2.Simpleproto", frontend, backend, minify);
-  }
-
-  @Test
-  public void test() throws Exception {
-    runTest(
-        TreeShakingSimpleproto2Test::simpleproto2UnusedFieldsAreGone,
-        null,
-        null,
-        ImmutableList.of("src/test/examples/simpleproto2/keep-rules.txt"));
-  }
-
-  private static void simpleproto2UnusedFieldsAreGone(CodeInspector inspector) {
-    ClassSubject protoClass = inspector.clazz("simpleproto2.GeneratedSimpleProto$Simple");
-    Assert.assertTrue(protoClass.isPresent());
-    Assert.assertFalse(protoClass.field("int", "id_").isPresent());
-    Assert.assertFalse(protoClass.field("float", "hasMe_").isPresent());
-    Assert.assertFalse(protoClass.field("int", "other_").isPresent());
-  }
-}
diff --git a/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingSimpleproto3Test.java b/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingSimpleproto3Test.java
deleted file mode 100644
index 896517a..0000000
--- a/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingSimpleproto3Test.java
+++ /dev/null
@@ -1,39 +0,0 @@
-// 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.shaking.examples;
-
-import com.android.tools.r8.TestBase.MinifyMode;
-import com.android.tools.r8.shaking.TreeShakingTest;
-import com.google.common.collect.ImmutableList;
-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;
-import org.junit.runners.Parameterized.Parameters;
-
-@RunWith(Parameterized.class)
-public class TreeShakingSimpleproto3Test extends TreeShakingTest {
-
-  @Parameters(name = "mode:{0}-{1} minify:{2}")
-  public static Collection<Object[]> data() {
-    List<Object[]> parameters = new ArrayList<>();
-    for (MinifyMode minify : MinifyMode.values()) {
-      parameters.add(new Object[] {Frontend.JAR, Backend.CF, minify});
-      parameters.add(new Object[] {Frontend.JAR, Backend.DEX, minify});
-      parameters.add(new Object[] {Frontend.DEX, Backend.DEX, minify});
-    }
-    return parameters;
-  }
-
-  public TreeShakingSimpleproto3Test(Frontend frontend, Backend backend, MinifyMode minify) {
-    super("examples/simpleproto3", "simpleproto3.Simpleproto", frontend, backend, minify);
-  }
-
-  @Test
-  public void test() throws Exception {
-    runTest(null, null, null, ImmutableList.of("src/test/examples/simpleproto3/keep-rules.txt"));
-  }
-}
diff --git a/tools/golem.py b/tools/golem.py
index cda9875..c4c554a 100755
--- a/tools/golem.py
+++ b/tools/golem.py
@@ -22,7 +22,7 @@
 ]
 
 # Path to our internally updated third party
-THIRD_PARTY_SOURCE = "/usr/local/google/home/golem/src/r8/third_party"
+THIRD_PARTY_SOURCE = "/usr/local/google/home/golem/r8/third_party"
 
 def link_third_party():
   assert os.path.exists('third_party')
diff --git a/tools/run_kotlin_benchmarks.py b/tools/run_kotlin_benchmarks.py
index c3f5b94..166c3e9 100755
--- a/tools/run_kotlin_benchmarks.py
+++ b/tools/run_kotlin_benchmarks.py
@@ -87,25 +87,25 @@
   (options, args) = parse_options()
   if options.golem:
     golem.link_third_party()
-  temp = '/tmp/output'
-  dex_path = os.path.join(temp, "classes.jar")
-  proguard_conf = os.path.join(temp, 'proguard.conf')
-  with open(proguard_conf, 'w') as f:
-    f.write(PROGUARD_CONF)
-  benchmark_jar = get_jar_for_benchmark(options.benchmark)
-  r8_args = [
-      '--lib', utils.get_android_jar(26), # Only works with api 26
-      '--output', dex_path,
-      '--pg-conf', proguard_conf,
-      '--min-api', str(options.api),
-      benchmark_jar
-  ]
-  toolhelper.run('r8', r8_args, build=not options.golem)
-  if options.use_device:
-    result = run_art_device(dex_path)
-  else:
-    result = run_art(dex_path)
-  print('Kotlin_{}(RunTimeRaw): {} ms'.format(options.benchmark, result))
+  with utils.TempDir() as temp:
+    dex_path = os.path.join(temp, "classes.jar")
+    proguard_conf = os.path.join(temp, 'proguard.conf')
+    with open(proguard_conf, 'w') as f:
+      f.write(PROGUARD_CONF)
+    benchmark_jar = get_jar_for_benchmark(options.benchmark)
+    r8_args = [
+        '--lib', utils.get_android_jar(26), # Only works with api 26
+        '--output', dex_path,
+        '--pg-conf', proguard_conf,
+        '--min-api', str(options.api),
+        benchmark_jar
+    ]
+    toolhelper.run('r8', r8_args, build=not options.golem)
+    if options.use_device:
+      result = run_art_device(dex_path)
+    else:
+      result = run_art(dex_path)
+    print('Kotlin_{}(RunTimeRaw): {} ms'.format(options.benchmark, result))
 
 if __name__ == '__main__':
   sys.exit(Main())