diff --git a/src/main/java/com/android/tools/r8/JarSizeCompare.java b/src/main/java/com/android/tools/r8/JarSizeCompare.java
new file mode 100644
index 0000000..aa16b1f
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/JarSizeCompare.java
@@ -0,0 +1,482 @@
+// 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;
+
+import com.android.tools.r8.dex.ApplicationReader;
+import com.android.tools.r8.errors.Unreachable;
+import com.android.tools.r8.graph.Code;
+import com.android.tools.r8.graph.DexApplication;
+import com.android.tools.r8.graph.DexClass;
+import com.android.tools.r8.graph.DexEncodedField;
+import com.android.tools.r8.graph.DexEncodedMethod;
+import com.android.tools.r8.graph.DexProgramClass;
+import com.android.tools.r8.naming.ClassNameMapper;
+import com.android.tools.r8.naming.ClassNamingForNameMapper;
+import com.android.tools.r8.naming.MemberNaming.FieldSignature;
+import com.android.tools.r8.naming.MemberNaming.MethodSignature;
+import com.android.tools.r8.utils.AndroidApiLevel;
+import com.android.tools.r8.utils.AndroidApp;
+import com.android.tools.r8.utils.AndroidAppConsumers;
+import com.android.tools.r8.utils.DescriptorUtils;
+import com.android.tools.r8.utils.InternalOptions;
+import com.android.tools.r8.utils.Timing;
+import com.google.common.base.Strings;
+import com.google.common.collect.ImmutableMap;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.function.BiConsumer;
+
+/**
+ * JarSizeCompare outputs the class, method, field sizes of the given JAR files. For each input, a
+ * ProGuard map can be passed that is used to resolve minified names.
+ *
+ * <p>By default, only shows methods where R8's DEX output is 5 or more instructions larger than
+ * ProGuard+D8's output. Pass {@code --threshold 0} to display all methods.
+ */
+public class JarSizeCompare {
+
+  private static final String USAGE =
+      "Arguments:\n"
+          + "    [--threshold <threshold>]\n"
+          + "    [--lib <lib.jar>]\n"
+          + "    --input <name1> <input1.jar> [<map1.txt>]\n"
+          + "    --input <name2> <input2.jar> [<map2.txt>] ...\n"
+          + "\n"
+          + "JarSizeCompare outputs the class, method, field sizes of the given JAR files.\n"
+          + "For each input, a ProGuard map can be passed that is used to resolve minified names.\n";
+
+  private static final ImmutableMap<String, String> R8_RELOCATIONS =
+      ImmutableMap.<String, String>builder()
+          .put("com.google.common", "com.android.tools.r8.com.google.common")
+          .put("com.google.gson", "com.android.tools.r8.com.google.gson")
+          .put("com.google.thirdparty", "com.android.tools.r8.com.google.thirdparty")
+          .put("joptsimple", "com.android.tools.r8.joptsimple")
+          .put("org.apache.commons", "com.android.tools.r8.org.apache.commons")
+          .put("org.objectweb.asm", "com.android.tools.r8.org.objectweb.asm")
+          .put("it.unimi.dsi.fastutil", "com.android.tools.r8.it.unimi.dsi.fastutil")
+          .build();
+
+  private final List<Path> libraries;
+  private final List<InputParameter> inputParameters;
+  private final int threshold;
+  private final InternalOptions options;
+  private int pgIndex;
+  private int r8Index;
+
+  private JarSizeCompare(
+      List<Path> libraries, List<InputParameter> inputParameters, int threshold) {
+    this.libraries = libraries;
+    this.inputParameters = inputParameters;
+    this.threshold = threshold;
+    options = new InternalOptions();
+    options.enableCfFrontend = true;
+  }
+
+  public void run() throws Exception {
+    List<String> names = new ArrayList<>();
+    List<InputApplication> inputApplicationList = new ArrayList<>();
+    Timing timing = new Timing("JarSizeCompare");
+    for (InputParameter inputParameter : inputParameters) {
+      AndroidApp inputApp = inputParameter.getInputApp(libraries);
+      DexApplication input = inputParameter.getReader(options, inputApp, timing);
+      AndroidAppConsumers appConsumer = new AndroidAppConsumers();
+      D8.run(
+          D8Command.builder(inputApp)
+              .setMinApiLevel(AndroidApiLevel.P.getLevel())
+              .setProgramConsumer(appConsumer.wrapDexIndexedConsumer(null))
+              .build());
+      DexApplication d8Input = inputParameter.getReader(options, appConsumer.build(), timing);
+      InputApplication inputApplication =
+          new InputApplication(input, translateClassNames(input, input.classes()));
+      InputApplication d8Classes =
+          new InputApplication(input, translateClassNames(input, d8Input.classes()));
+      names.add(inputParameter.name + "-input");
+      inputApplicationList.add(inputApplication);
+      names.add(inputParameter.name + "-d8");
+      inputApplicationList.add(d8Classes);
+    }
+    if (threshold != 0) {
+      pgIndex = names.indexOf("pg-d8");
+      r8Index = names.indexOf("r8-d8");
+    }
+    Map<String, InputClass[]> inputClasses = new HashMap<>();
+    for (int i = 0; i < names.size(); i++) {
+      InputApplication classes = inputApplicationList.get(i);
+      for (String className : classes.getClasses()) {
+        inputClasses.computeIfAbsent(className, k -> new InputClass[names.size()])[i] =
+            classes.getInputClass(className);
+      }
+    }
+    for (Entry<String, Map<String, InputClass[]>> library : byLibrary(inputClasses)) {
+      System.out.println("");
+      System.out.println(Strings.repeat("=", 100));
+      String commonPrefix = getCommonPrefix(library.getValue().keySet());
+      if (library.getKey().isEmpty()) {
+        System.out.println("PROGRAM (" + commonPrefix + ")");
+      } else {
+        System.out.println("LIBRARY: " + library.getKey() + " (" + commonPrefix + ")");
+      }
+      printLibrary(library.getValue(), commonPrefix);
+    }
+  }
+
+  private Map<String, DexProgramClass> translateClassNames(
+      DexApplication input, List<DexProgramClass> classes) {
+    Map<String, DexProgramClass> result = new HashMap<>();
+    ClassNameMapper classNameMapper = input.getProguardMap();
+    for (DexProgramClass programClass : classes) {
+      ClassNamingForNameMapper classNaming;
+      if (classNameMapper == null) {
+        classNaming = null;
+      } else {
+        classNaming = classNameMapper.getClassNaming(programClass.type);
+      }
+      String type =
+          classNaming == null ? programClass.type.toSourceString() : classNaming.originalName;
+      result.put(type, programClass);
+    }
+    return result;
+  }
+
+  private String getCommonPrefix(Set<String> classes) {
+    if (classes.size() <= 1) {
+      return "";
+    }
+    String commonPrefix = null;
+    for (String clazz : classes) {
+      if (clazz.equals("r8.GeneratedOutlineSupport")) {
+        continue;
+      }
+      if (commonPrefix == null) {
+        commonPrefix = clazz;
+      } else {
+        int i = 0;
+        while (i < clazz.length()
+            && i < commonPrefix.length()
+            && clazz.charAt(i) == commonPrefix.charAt(i)) {
+          i++;
+        }
+        commonPrefix = commonPrefix.substring(0, i);
+      }
+    }
+    return commonPrefix;
+  }
+
+  private void printLibrary(Map<String, InputClass[]> classMap, String commonPrefix) {
+    List<Entry<String, InputClass[]>> classes = new ArrayList<>(classMap.entrySet());
+    classes.sort(Comparator.comparing(Entry::getKey));
+    for (Entry<String, InputClass[]> clazz : classes) {
+      printClass(
+          clazz.getKey().substring(commonPrefix.length()), new ClassCompare(clazz.getValue()));
+    }
+  }
+
+  private void printClass(String name, ClassCompare inputClasses) {
+    List<MethodSignature> methods = getMethods(inputClasses);
+    List<FieldSignature> fields = getFields(inputClasses);
+    if (methods.isEmpty() && fields.isEmpty()) {
+      return;
+    }
+    System.out.println(name);
+    for (MethodSignature sig : methods) {
+      printSignature(getMethodString(sig), inputClasses.sizes(sig));
+    }
+    for (FieldSignature sig : fields) {
+      printSignature(getFieldString(sig), inputClasses.sizes(sig));
+    }
+  }
+
+  private String getMethodString(MethodSignature sig) {
+    StringBuilder builder = new StringBuilder().append('(');
+    for (int i = 0; i < sig.parameters.length; i++) {
+      builder.append(DescriptorUtils.javaTypeToShorty(sig.parameters[i]));
+    }
+    builder.append(')').append(DescriptorUtils.javaTypeToShorty(sig.type)).append(' ');
+    return builder.append(sig.name).toString();
+  }
+
+  private String getFieldString(FieldSignature sig) {
+    return DescriptorUtils.javaTypeToShorty(sig.type) + ' ' + sig.name;
+  }
+
+  private void printSignature(String key, int[] sizes) {
+    System.out.print(padItem(key));
+    for (int size : sizes) {
+      System.out.print(padValue(size));
+    }
+    System.out.print('\n');
+  }
+
+  private List<MethodSignature> getMethods(ClassCompare inputClasses) {
+    List<MethodSignature> methods = new ArrayList<>();
+    for (MethodSignature methodSignature : inputClasses.getMethods()) {
+      if (threshold == 0 || methodExceedsThreshold(inputClasses, methodSignature)) {
+        methods.add(methodSignature);
+      }
+    }
+    return methods;
+  }
+
+  private boolean methodExceedsThreshold(
+      ClassCompare inputClasses, MethodSignature methodSignature) {
+    assert threshold > 0;
+    assert pgIndex != r8Index;
+    int pgSize = inputClasses.size(methodSignature, pgIndex);
+    int r8Size = inputClasses.size(methodSignature, r8Index);
+    return pgSize != -1 && r8Size != -1 && pgSize + threshold <= r8Size;
+  }
+
+  private List<FieldSignature> getFields(ClassCompare inputClasses) {
+    return threshold == 0 ? inputClasses.getFields() : Collections.emptyList();
+  }
+
+  private String padItem(String s) {
+    return String.format("%-52s", s);
+  }
+
+  private String padValue(int v) {
+    return String.format("%8s", v == -1 ? "---" : v);
+  }
+
+  private List<Map.Entry<String, Map<String, InputClass[]>>> byLibrary(
+      Map<String, InputClass[]> inputClasses) {
+    Map<String, Map<String, InputClass[]>> byLibrary = new HashMap<>();
+    for (Entry<String, InputClass[]> entry : inputClasses.entrySet()) {
+      Map<String, InputClass[]> library =
+          byLibrary.computeIfAbsent(getLibraryName(entry.getKey()), k -> new HashMap<>());
+      library.put(entry.getKey(), entry.getValue());
+    }
+    List<Entry<String, Map<String, InputClass[]>>> list = new ArrayList<>(byLibrary.entrySet());
+    list.sort(Comparator.comparing(Entry::getKey));
+    return list;
+  }
+
+  private String getLibraryName(String className) {
+    for (Entry<String, String> relocation : R8_RELOCATIONS.entrySet()) {
+      if (className.startsWith(relocation.getValue())) {
+        return relocation.getKey();
+      }
+    }
+    return "";
+  }
+
+  static class InputParameter {
+
+    private final String name;
+    private final Path jar;
+    private final Path map;
+
+    InputParameter(String name, Path jar, Path map) {
+      this.name = name;
+      this.jar = jar;
+      this.map = map;
+    }
+
+    DexApplication getReader(InternalOptions options, AndroidApp inputApp, Timing timing)
+        throws Exception {
+      ApplicationReader applicationReader = new ApplicationReader(inputApp, options, timing);
+      return applicationReader.read(map == null ? null : StringResource.fromFile(map)).toDirect();
+    }
+
+    AndroidApp getInputApp(List<Path> libraries) throws Exception {
+      return AndroidApp.builder().addLibraryFiles(libraries).addProgramFiles(jar).build();
+    }
+  }
+
+  static class InputApplication {
+
+    private final DexApplication dexApplication;
+    private final Map<String, DexProgramClass> classMap;
+
+    private InputApplication(DexApplication dexApplication, Map<String, DexProgramClass> classMap) {
+      this.dexApplication = dexApplication;
+      this.classMap = classMap;
+    }
+
+    public Set<String> getClasses() {
+      return classMap.keySet();
+    }
+
+    private InputClass getInputClass(String type) {
+      DexProgramClass inputClass = classMap.get(type);
+      ClassNameMapper proguardMap = dexApplication.getProguardMap();
+      return new InputClass(inputClass, proguardMap);
+    }
+  }
+
+  static class InputClass {
+    private final DexProgramClass programClass;
+    private final ClassNameMapper proguardMap;
+
+    InputClass(DexClass dexClass, ClassNameMapper proguardMap) {
+      this.programClass = dexClass == null ? null : dexClass.asProgramClass();
+      this.proguardMap = proguardMap;
+    }
+
+    void forEachMethod(BiConsumer<MethodSignature, DexEncodedMethod> consumer) {
+      if (programClass == null) {
+        return;
+      }
+      programClass.forEachMethod(
+          dexEncodedMethod -> {
+            MethodSignature originalSignature =
+                proguardMap == null
+                    ? null
+                    : ((MethodSignature) proguardMap.originalSignatureOf(dexEncodedMethod.method));
+            MethodSignature signature = MethodSignature.fromDexMethod(dexEncodedMethod.method);
+            consumer.accept(
+                originalSignature == null ? signature : originalSignature, dexEncodedMethod);
+          });
+    }
+
+    void forEachField(BiConsumer<FieldSignature, DexEncodedField> consumer) {
+      if (programClass == null) {
+        return;
+      }
+      programClass.forEachField(
+          dexEncodedField -> {
+            FieldSignature originalSignature =
+                proguardMap == null ? null : proguardMap.originalSignatureOf(dexEncodedField.field);
+            FieldSignature signature = FieldSignature.fromDexField(dexEncodedField.field);
+            consumer.accept(
+                originalSignature == null ? signature : originalSignature, dexEncodedField);
+          });
+    }
+  }
+
+  private static class ClassCompare {
+    final Map<MethodSignature, DexEncodedMethod[]> methods = new HashMap<>();
+    final Map<FieldSignature, DexEncodedField[]> fields = new HashMap<>();
+    final int classes;
+
+    ClassCompare(InputClass[] inputs) {
+      for (int i = 0; i < inputs.length; i++) {
+        InputClass inputClass = inputs[i];
+        int finalI = i;
+        if (inputClass == null) {
+          continue;
+        }
+        inputClass.forEachMethod(
+            (sig, m) ->
+                methods.computeIfAbsent(sig, o -> new DexEncodedMethod[inputs.length])[finalI] = m);
+        inputClass.forEachField(
+            (sig, f) ->
+                fields.computeIfAbsent(sig, o -> new DexEncodedField[inputs.length])[finalI] = f);
+      }
+      classes = inputs.length;
+    }
+
+    List<MethodSignature> getMethods() {
+      List<MethodSignature> methods = new ArrayList<>(this.methods.keySet());
+      methods.sort(Comparator.comparing(MethodSignature::toString));
+      return methods;
+    }
+
+    List<FieldSignature> getFields() {
+      List<FieldSignature> fields = new ArrayList<>(this.fields.keySet());
+      fields.sort(Comparator.comparing(FieldSignature::toString));
+      return fields;
+    }
+
+    int size(MethodSignature method, int classIndex) {
+      DexEncodedMethod dexEncodedMethod = methods.get(method)[classIndex];
+      if (dexEncodedMethod == null) {
+        return -1;
+      }
+      Code code = dexEncodedMethod.getCode();
+      if (code == null) {
+        return 0;
+      }
+      if (code.isCfCode()) {
+        return code.asCfCode().getInstructions().size();
+      }
+      if (code.isDexCode()) {
+        return code.asDexCode().instructions.length;
+      }
+      throw new Unreachable();
+    }
+
+    int[] sizes(MethodSignature method) {
+      int[] result = new int[classes];
+      for (int i = 0; i < classes; i++) {
+        result[i] = size(method, i);
+      }
+      return result;
+    }
+
+    int size(FieldSignature field, int classIndex) {
+      return fields.get(field)[classIndex] == null ? -1 : 1;
+    }
+
+    int[] sizes(FieldSignature field) {
+      int[] result = new int[classes];
+      for (int i = 0; i < classes; i++) {
+        result[i] = size(field, i);
+      }
+      return result;
+    }
+  }
+
+  public static void main(String[] args) throws Exception {
+    JarSizeCompare program = JarSizeCompare.parse(args);
+    if (program == null) {
+      System.out.println(USAGE);
+    } else {
+      program.run();
+    }
+  }
+
+  public static JarSizeCompare parse(String[] args) {
+    int i = 0;
+    int threshold = 0;
+    List<Path> libraries = new ArrayList<>();
+    List<InputParameter> inputs = new ArrayList<>();
+    Set<String> names = new HashSet<>();
+    while (i < args.length) {
+      if (args[i].equals("--threshold") && i + 1 < args.length) {
+        threshold = Integer.parseInt(args[i + 1]);
+        i += 2;
+      } else if (args[i].equals("--lib") && i + 1 < args.length) {
+        libraries.add(Paths.get(args[i + 1]));
+        i += 2;
+      } else if (args[i].equals("--input") && i + 2 < args.length) {
+        String name = args[i + 1];
+        Path jar = Paths.get(args[i + 2]);
+        Path map = null;
+        if (i + 3 < args.length && !args[i + 3].startsWith("-")) {
+          map = Paths.get(args[i + 3]);
+          i += 4;
+        } else {
+          i += 3;
+        }
+        inputs.add(new InputParameter(name, jar, map));
+        if (!names.add(name)) {
+          System.out.println("Duplicate name: " + name);
+          return null;
+        }
+      } else {
+        return null;
+      }
+    }
+    if (inputs.size() < 2) {
+      return null;
+    }
+    if (threshold != 0 && (!names.contains("r8") || !names.contains("pg"))) {
+      System.out.println(
+          "You must either specify names \"pg\" and \"r8\" for input files "
+              + "or use \"--threshold 0\".");
+      return null;
+    }
+    return new JarSizeCompare(libraries, inputs, threshold);
+  }
+}
diff --git a/src/main/java/com/android/tools/r8/SwissArmyKnife.java b/src/main/java/com/android/tools/r8/SwissArmyKnife.java
index 28e1f93..f54233b 100644
--- a/src/main/java/com/android/tools/r8/SwissArmyKnife.java
+++ b/src/main/java/com/android/tools/r8/SwissArmyKnife.java
@@ -61,6 +61,9 @@
       case "jardiff":
         JarDiff.main(shift(args));
         break;
+      case "jarsizecompare":
+        JarSizeCompare.main(shift(args));
+        break;
       case "maindex":
         GenerateMainDexList.main(shift(args));
         break;
diff --git a/tools/build_r8lib.py b/tools/build_r8lib.py
index c855bc5..4b7473e 100755
--- a/tools/build_r8lib.py
+++ b/tools/build_r8lib.py
@@ -25,16 +25,21 @@
 ANDROID_JAR = 'third_party/android_jar/lib-v%s/android.jar' % API_LEVEL
 
 
-def build_r8lib():
+def build_r8lib(output_path=None, output_map=None, **kwargs):
+  if output_path is None:
+    output_path = R8LIB_JAR
+  if output_map is None:
+    output_map = R8LIB_MAP_FILE
   toolhelper.run(
       'r8',
       ('--release',
        '--classfile',
        '--lib', utils.RT_JAR,
        utils.R8_JAR,
-       '--output', R8LIB_JAR,
+       '--output', output_path,
        '--pg-conf', utils.R8LIB_KEEP_RULES,
-       '--pg-map-output', R8LIB_MAP_FILE))
+       '--pg-map-output', output_map),
+      **kwargs)
 
 
 def test_d8sample():
diff --git a/tools/r8lib_size_compare.py b/tools/r8lib_size_compare.py
new file mode 100755
index 0000000..4bb49eb
--- /dev/null
+++ b/tools/r8lib_size_compare.py
@@ -0,0 +1,105 @@
+#!/usr/bin/env python
+# 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.
+
+'''
+Build r8lib.jar with both R8 and ProGuard and print a size comparison.
+
+By default, inlining is disabled in both R8 and ProGuard to make
+method-by-method comparison much easier. Pass --inlining to enable inlining.
+
+By default, only shows methods where R8's DEX output is 5 or more instructions
+larger than ProGuard+D8's output. Pass --threshold 0 to display all methods.
+'''
+
+import argparse
+import build_r8lib
+import os
+import subprocess
+import toolhelper
+import utils
+
+
+parser = argparse.ArgumentParser(description=__doc__.strip(),
+                                 formatter_class=argparse.RawTextHelpFormatter)
+parser.add_argument('-t', '--tmpdir',
+                    help='Store auxiliary files in given directory')
+parser.add_argument('-i', '--inlining', action='store_true',
+                    help='Enable inlining')
+parser.add_argument('--threshold')
+
+R8_RELOCATIONS = [
+  ('com.google.common', 'com.android.tools.r8.com.google.common'),
+  ('com.google.gson', 'com.android.tools.r8.com.google.gson'),
+  ('com.google.thirdparty', 'com.android.tools.r8.com.google.thirdparty'),
+  ('joptsimple', 'com.android.tools.r8.joptsimple'),
+  ('org.apache.commons', 'com.android.tools.r8.org.apache.commons'),
+  ('org.objectweb.asm', 'com.android.tools.r8.org.objectweb.asm'),
+  ('it.unimi.dsi.fastutil', 'com.android.tools.r8.it.unimi.dsi.fastutil'),
+]
+
+
+def is_output_newer(input, output):
+  if not os.path.exists(output):
+    return False
+  return os.stat(input).st_mtime < os.stat(output).st_mtime
+
+
+def check_call(args, **kwargs):
+  utils.PrintCmd(args)
+  return subprocess.check_call(args, **kwargs)
+
+
+def main(tmpdir=None, inlining=True,
+         run_jarsizecompare=True, threshold=None):
+  if tmpdir is None:
+    with utils.TempDir() as tmpdir:
+      return main(tmpdir, inlining)
+
+  inline_suffix = '-inline' if inlining else '-noinline'
+
+  pg_config = utils.R8LIB_KEEP_RULES
+  r8lib_jar = os.path.join(utils.LIBS, 'r8lib%s.jar' % inline_suffix)
+  r8lib_map = os.path.join(utils.LIBS, 'r8lib%s-map.txt' % inline_suffix)
+  r8lib_args = None
+  if not inlining:
+    r8lib_args = ['-Dcom.android.tools.r8.disableinlining=1']
+    pg_config = os.path.join(tmpdir, 'keep-noinline.txt')
+    with open(pg_config, 'w') as new_config:
+      with open(utils.R8LIB_KEEP_RULES) as old_config:
+        new_config.write(old_config.read().rstrip('\n') +
+                         '\n-optimizations !method/inlining/*\n')
+
+  if not is_output_newer(utils.R8_JAR, r8lib_jar):
+    r8lib_memory = os.path.join(tmpdir, 'r8lib%s-memory.txt' % inline_suffix)
+    build_r8lib.build_r8lib(
+        output_path=r8lib_jar, output_map=r8lib_map,
+        extra_args=r8lib_args, track_memory_file=r8lib_memory)
+
+  pg_output = os.path.join(tmpdir, 'r8lib-pg%s.jar' % inline_suffix)
+  pg_memory = os.path.join(tmpdir, 'r8lib-pg%s-memory.txt' % inline_suffix)
+  pg_map = os.path.join(tmpdir, 'r8lib-pg%s-map.txt' % inline_suffix)
+  pg_args = ['tools/track_memory.sh', pg_memory,
+             'third_party/proguard/proguard6.0.2/bin/proguard.sh',
+             '@' + pg_config,
+             '-lib', utils.RT_JAR,
+             '-injar', utils.R8_JAR,
+             '-printmapping', pg_map,
+             '-outjar', pg_output]
+  for library_name, relocated_package in utils.R8_RELOCATIONS:
+    pg_args.extend(['-dontwarn', relocated_package + '.**',
+                    '-dontnote', relocated_package + '.**'])
+  check_call(pg_args)
+  if threshold is None:
+    threshold = 5
+  toolhelper.run('jarsizecompare',
+                 ['--threshold', str(threshold),
+                  '--lib', utils.RT_JAR,
+                  '--input', 'input', utils.R8_JAR,
+                  '--input', 'r8', r8lib_jar, r8lib_map,
+                  '--input', 'pg', pg_output, pg_map])
+
+
+if __name__ == '__main__':
+  main(**vars(parser.parse_args()))
diff --git a/tools/toolhelper.py b/tools/toolhelper.py
index a7f509c..82a2824 100644
--- a/tools/toolhelper.py
+++ b/tools/toolhelper.py
@@ -9,7 +9,7 @@
 import utils
 
 def run(tool, args, build=None, debug=True,
-        profile=False, track_memory_file=None):
+        profile=False, track_memory_file=None, extra_args=None):
   if build is None:
     build, args = extract_build_from_args(args)
   if build:
@@ -18,6 +18,8 @@
   if track_memory_file:
     cmd.extend(['tools/track_memory.sh', track_memory_file])
   cmd.append('java')
+  if extra_args:
+    cmd.extend(extra_args)
   if debug:
     cmd.append('-ea')
   if profile:
