Revert "Combine Long.compare/Objects.requireNonNull with Java 8 rewriter"

This reverts commit 237112500c62bdce32d0cdb2832007bfdedab5d0.

Reason for revert: Unrelated tests asserting generated types fail as a result of new Java 7 deugaring technique

Change-Id: I166f60abac36b1b28333b2dda9e6f515158593a5
diff --git a/src/main/java/com/android/tools/r8/graph/DexType.java b/src/main/java/com/android/tools/r8/graph/DexType.java
index be60042..801d6f8 100644
--- a/src/main/java/com/android/tools/r8/graph/DexType.java
+++ b/src/main/java/com/android/tools/r8/graph/DexType.java
@@ -10,7 +10,7 @@
 
 import com.android.tools.r8.dex.IndexedItemCollection;
 import com.android.tools.r8.errors.Unreachable;
-import com.android.tools.r8.ir.desugar.BackportedMethodRewriter;
+import com.android.tools.r8.ir.desugar.Java8MethodRewriter;
 import com.android.tools.r8.ir.desugar.NestBasedAccessDesugaring;
 import com.android.tools.r8.ir.desugar.TwrCloseResourceRewriter;
 import com.android.tools.r8.naming.NamingLens;
@@ -250,7 +250,7 @@
         || name.contains(OutlineOptions.CLASS_NAME)
         || name.contains(TwrCloseResourceRewriter.UTILITY_CLASS_NAME)
         || name.contains(NestBasedAccessDesugaring.NEST_CONSTRUCTOR_NAME)
-        || name.contains(BackportedMethodRewriter.UTILITY_CLASS_NAME_PREFIX);
+        || name.contains(Java8MethodRewriter.UTILITY_CLASS_NAME_PREFIX);
   }
 
   public boolean isProgramType(DexDefinitionSupplier definitions) {
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 f0f1613..c6c1ba8 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
@@ -42,7 +42,7 @@
 import com.android.tools.r8.ir.code.Value;
 import com.android.tools.r8.ir.desugar.CovariantReturnTypeAnnotationTransformer;
 import com.android.tools.r8.ir.desugar.InterfaceMethodRewriter;
-import com.android.tools.r8.ir.desugar.BackportedMethodRewriter;
+import com.android.tools.r8.ir.desugar.Java8MethodRewriter;
 import com.android.tools.r8.ir.desugar.LambdaRewriter;
 import com.android.tools.r8.ir.desugar.NestBasedAccessDesugaringRewriter;
 import com.android.tools.r8.ir.desugar.StringConcatRewriter;
@@ -123,7 +123,7 @@
   private final NestBasedAccessDesugaringRewriter nestBasedAccessDesugaringRewriter;
   private final InterfaceMethodRewriter interfaceMethodRewriter;
   private final TwrCloseResourceRewriter twrCloseResourceRewriter;
-  private final BackportedMethodRewriter backportedMethodRewriter;
+  private final Java8MethodRewriter java8MethodRewriter;
   private final LambdaMerger lambdaMerger;
   private final ClassInliner classInliner;
   private final ClassStaticizer classStaticizer;
@@ -180,9 +180,9 @@
         (options.enableDesugaring && enableTwrCloseResourceDesugaring())
             ? new TwrCloseResourceRewriter(appView, this)
             : null;
-    this.backportedMethodRewriter =
+    this.java8MethodRewriter =
         options.enableDesugaring
-            ? new BackportedMethodRewriter(appView, this)
+            ? new Java8MethodRewriter(appView, this)
             : null;
     this.lambdaMerger = options.enableLambdaMerging ? new LambdaMerger(appView) : null;
     this.covariantReturnTypeAnnotationTransformer =
@@ -344,8 +344,8 @@
 
   private void synthesizeJava8UtilityClass(
       Builder<?> builder, ExecutorService executorService) throws ExecutionException {
-    if (backportedMethodRewriter != null) {
-      backportedMethodRewriter.synthesizeUtilityClass(builder, executorService, options);
+    if (java8MethodRewriter != null) {
+      java8MethodRewriter.synthesizeUtilityClass(builder, executorService, options);
     }
   }
 
@@ -983,6 +983,7 @@
     assert code.verifyTypes(appView);
     codeRewriter.removeTrivialCheckCastAndInstanceOfInstructions(code);
 
+    codeRewriter.rewriteLongCompareAndRequireNonNull(code, options);
     codeRewriter.commonSubexpressionElimination(code);
     codeRewriter.simplifyArrayConstruction(code);
     codeRewriter.rewriteMoveResult(code);
@@ -1024,8 +1025,8 @@
     if (options.enableDesugaring && enableTryWithResourcesDesugaring()) {
       codeRewriter.rewriteThrowableAddAndGetSuppressed(code);
     }
-    if (backportedMethodRewriter != null) {
-      backportedMethodRewriter.desugar(code);
+    if (java8MethodRewriter != null) {
+      java8MethodRewriter.desugar(code);
     }
 
     stringConcatRewriter.desugarStringConcats(method.method, code);
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/InterfaceMethodRewriter.java b/src/main/java/com/android/tools/r8/ir/desugar/InterfaceMethodRewriter.java
index ff03181..b949b72 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/InterfaceMethodRewriter.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/InterfaceMethodRewriter.java
@@ -154,7 +154,7 @@
           InvokeStatic invokeStatic = instruction.asInvokeStatic();
           DexMethod method = invokeStatic.getInvokedMethod();
           DexClass clazz = appInfo.definitionFor(method.holder);
-          if (BackportedMethodRewriter.hasRewrittenMethodPrefix(method.holder)) {
+          if (Java8MethodRewriter.hasJava8MethodRewritePrefix(method.holder)) {
             // We did not create this code yet, but it will not require rewriting.
             continue;
           }
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/BackportedMethodRewriter.java b/src/main/java/com/android/tools/r8/ir/desugar/Java8MethodRewriter.java
similarity index 85%
rename from src/main/java/com/android/tools/r8/ir/desugar/BackportedMethodRewriter.java
rename to src/main/java/com/android/tools/r8/ir/desugar/Java8MethodRewriter.java
index ac911f2..69d0b48 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/BackportedMethodRewriter.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/Java8MethodRewriter.java
@@ -27,7 +27,7 @@
 import com.android.tools.r8.ir.code.InstructionIterator;
 import com.android.tools.r8.ir.code.InvokeStatic;
 import com.android.tools.r8.ir.conversion.IRConverter;
-import com.android.tools.r8.ir.desugar.BackportedMethodRewriter.RewritableMethods.MethodGenerator;
+import com.android.tools.r8.ir.desugar.Java8MethodRewriter.RewritableMethods.MethodGenerator;
 import com.android.tools.r8.ir.synthetic.TemplateMethodCode;
 import com.android.tools.r8.origin.SynthesizedOrigin;
 import com.android.tools.r8.utils.DescriptorUtils;
@@ -43,9 +43,9 @@
 import java.util.concurrent.ExecutorService;
 import java.util.function.BiFunction;
 
-public final class BackportedMethodRewriter {
-  public static final String UTILITY_CLASS_NAME_PREFIX = "$r8$backportedMethods$utility";
-  private static final String UTILITY_CLASS_DESCRIPTOR_PREFIX = "L" + UTILITY_CLASS_NAME_PREFIX;
+public final class Java8MethodRewriter {
+  public static final String UTILITY_CLASS_NAME_PREFIX = "$r8$java8methods$utility";
+  private static final String UTILITY_CLASS_DESCRIPTOR_PREFIX = "L$r8$java8methods$utility";
   private final Set<DexType> holders = Sets.newConcurrentHashSet();
 
   private final AppView<?> appView;
@@ -55,7 +55,7 @@
 
   private Map<DexMethod, MethodGenerator> methodGenerators = new ConcurrentHashMap<>();
 
-  public BackportedMethodRewriter(AppView<?> appView, IRConverter converter) {
+  public Java8MethodRewriter(AppView<?> appView, IRConverter converter) {
     this.appView = appView;
     this.converter = converter;
     this.factory = appView.dexItemFactory();
@@ -96,7 +96,7 @@
     return null;
   }
 
-  public static boolean hasRewrittenMethodPrefix(DexType clazz) {
+  public static boolean hasJava8MethodRewritePrefix(DexType clazz) {
     return clazz.descriptor.toString().startsWith(UTILITY_CLASS_DESCRIPTOR_PREFIX);
   }
 
@@ -173,17 +173,9 @@
       return new ByteMethods(options, method, "hashCodeImpl");
     }
 
-    public static ByteMethods compareCode(InternalOptions options, DexMethod method) {
-      return new ByteMethods(options, method, "compareImpl");
-    }
-
     public static int hashCodeImpl(byte i) {
       return Byte.valueOf(i).hashCode();
     }
-
-    public static int compareImpl(byte a, byte b) {
-      return Byte.valueOf(a).compareTo(Byte.valueOf(b));
-    }
   }
 
 
@@ -196,17 +188,9 @@
       return new ShortMethods(options, method, "hashCodeImpl");
     }
 
-    public static ShortMethods compareCode(InternalOptions options, DexMethod method) {
-      return new ShortMethods(options, method, "compareImpl");
-    }
-
     public static int hashCodeImpl(short i) {
       return Short.valueOf(i).hashCode();
     }
-
-    public static int compareImpl(short a, short b) {
-      return Short.valueOf(a).compareTo(Short.valueOf(b));
-    }
   }
 
   private static final class IntegerMethods extends TemplateMethodCode {
@@ -218,10 +202,6 @@
       return new IntegerMethods(options, method, "hashCodeImpl");
     }
 
-    public static IntegerMethods compareCode(InternalOptions options, DexMethod method) {
-      return new IntegerMethods(options, method, "compareImpl");
-    }
-
     public static IntegerMethods maxCode(InternalOptions options, DexMethod method) {
       return new IntegerMethods(options, method, "maxImpl");
     }
@@ -250,10 +230,6 @@
       return Integer.valueOf(i).hashCode();
     }
 
-    public static int compareImpl(int a, int b) {
-      return Integer.valueOf(a).compareTo(Integer.valueOf(b));
-    }
-
     public static int maxImpl(int a, int b) {
       return java.lang.Math.max(a, b);
     }
@@ -388,10 +364,6 @@
       return new BooleanMethods(options, method, "hashCodeImpl");
     }
 
-    public static BooleanMethods compareCode(InternalOptions options, DexMethod method) {
-      return new BooleanMethods(options, method, "compareImpl");
-    }
-
     public static BooleanMethods logicalAndCode(InternalOptions options, DexMethod method) {
       return new BooleanMethods(options, method, "logicalAndImpl");
     }
@@ -408,10 +380,6 @@
       return Boolean.valueOf(b).hashCode();
     }
 
-    public static int compareImpl(boolean a, boolean b) {
-      return Boolean.valueOf(a).compareTo(Boolean.valueOf(b));
-    }
-
     public static boolean logicalAndImpl(boolean a, boolean b) {
       return a && b;
     }
@@ -434,10 +402,6 @@
       return new LongMethods(options, method, "hashCodeImpl");
     }
 
-    public static LongMethods compareCode(InternalOptions options, DexMethod method) {
-      return new LongMethods(options, method, "compareImpl");
-    }
-
     public static LongMethods maxCode(InternalOptions options, DexMethod method) {
       return new LongMethods(options, method, "maxImpl");
     }
@@ -466,10 +430,6 @@
       return Long.valueOf(i).hashCode();
     }
 
-    public static int compareImpl(long a, long b) {
-      return Long.valueOf(a).compareTo(Long.valueOf(b));
-    }
-
     public static long maxImpl(long a, long b) {
       return java.lang.Math.max(a, b);
     }
@@ -570,34 +530,9 @@
       return new CharacterMethods(options, method, "hashCodeImpl");
     }
 
-    public static CharacterMethods compareCode(InternalOptions options, DexMethod method) {
-      return new CharacterMethods(options, method, "compareImpl");
-    }
-
     public static int hashCodeImpl(char i) {
       return Character.valueOf(i).hashCode();
     }
-
-    public static int compareImpl(char a, char b) {
-      return Character.valueOf(a).compareTo(Character.valueOf(b));
-    }
-  }
-
-  private static final class ObjectMethods extends TemplateMethodCode {
-    ObjectMethods(InternalOptions options, DexMethod method, String methodName) {
-      super(options, method, methodName, method.proto.toDescriptorString());
-    }
-
-    public static ObjectMethods requireNonNullCode(InternalOptions options, DexMethod method) {
-      // Rewrite calls to Objects.requireNonNull(Object) because Javac 9 started to use it for
-      // synthesized null checks.
-      return new ObjectMethods(options, method, "requireNonNullImpl");
-    }
-
-    public static Object requireNonNullImpl(Object a) {
-      a.getClass();
-      return a;
-    }
   }
 
   public static final class RewritableMethods {
@@ -606,9 +541,6 @@
         new HashMap<>();
 
     public RewritableMethods(DexItemFactory factory, InternalOptions options) {
-      if (!options.canUseJava7CompareAndObjectsOperations()) {
-        initializeJava7CompareOperations(factory);
-      }
       if (!options.canUseJava8SignedOperations()) {
         initializeJava8SignedOperations(factory);
       }
@@ -621,64 +553,6 @@
       return rewritable.isEmpty();
     }
 
-    private void initializeJava7CompareOperations(DexItemFactory factory) {
-      // Byte
-      DexString clazz = factory.boxedByteDescriptor;
-      // int Byte.compare(byte a, byte b)
-      DexString method = factory.createString("compare");
-      DexProto proto = factory.createProto(factory.intType, factory.byteType, factory.byteType);
-      addOrGetMethod(clazz, method)
-          .put(proto, new MethodGenerator(ByteMethods::compareCode, clazz, method, proto));
-
-      // Short
-      clazz = factory.boxedShortDescriptor;
-      // int Short.compare(short a, short b)
-      method = factory.createString("compare");
-      proto = factory.createProto(factory.intType, factory.shortType, factory.shortType);
-      addOrGetMethod(clazz, method)
-          .put(proto, new MethodGenerator(ShortMethods::compareCode, clazz, method, proto));
-
-      // Integer
-      clazz = factory.boxedIntDescriptor;
-      // int Integer.compare(int a, int b)
-      method = factory.createString("compare");
-      proto = factory.createProto(factory.intType, factory.intType, factory.intType);
-      addOrGetMethod(clazz, method)
-          .put(proto, new MethodGenerator(IntegerMethods::compareCode, clazz, method, proto));
-
-      // Boolean
-      clazz = factory.boxedBooleanDescriptor;
-      // int Boolean.compare(boolean a, boolean b)
-      method = factory.createString("compare");
-      proto = factory.createProto(factory.intType, factory.booleanType, factory.booleanType);
-      addOrGetMethod(clazz, method)
-          .put(proto, new MethodGenerator(BooleanMethods::compareCode, clazz, method, proto));
-
-      // Long
-      clazz = factory.boxedLongDescriptor;
-      // int Long.compare(long a, long b)
-      method = factory.createString("compare");
-      proto = factory.createProto(factory.intType, factory.longType, factory.longType);
-      addOrGetMethod(clazz, method)
-          .put(proto, new MethodGenerator(LongMethods::compareCode, clazz, method, proto));
-
-      // Character
-      clazz = factory.boxedCharDescriptor;
-      // int Character.compare(char a, char b)
-      method = factory.createString("compare");
-      proto = factory.createProto(factory.intType, factory.charType, factory.charType);
-      addOrGetMethod(clazz, method)
-          .put(proto, new MethodGenerator(CharacterMethods::compareCode, clazz, method, proto));
-
-      // Object
-      clazz = factory.objectsDescriptor;
-      // Object Objects.requireNonNull(Object a)
-      method = factory.createString("requireNonNull");
-      proto = factory.createProto(factory.objectType, factory.objectType);
-      addOrGetMethod(clazz, method)
-          .put(proto, new MethodGenerator(ObjectMethods::requireNonNullCode, clazz, method, proto));
-    }
-
     private void initializeJava8SignedOperations(DexItemFactory factory) {
       // Byte
       DexString clazz = factory.boxedByteDescriptor;
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/CodeRewriter.java b/src/main/java/com/android/tools/r8/ir/optimize/CodeRewriter.java
index 48b81ae..87c28bf 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/CodeRewriter.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/CodeRewriter.java
@@ -43,6 +43,8 @@
 import com.android.tools.r8.ir.code.Binop;
 import com.android.tools.r8.ir.code.CatchHandlers;
 import com.android.tools.r8.ir.code.CheckCast;
+import com.android.tools.r8.ir.code.Cmp;
+import com.android.tools.r8.ir.code.Cmp.Bias;
 import com.android.tools.r8.ir.code.ConstInstruction;
 import com.android.tools.r8.ir.code.ConstNumber;
 import com.android.tools.r8.ir.code.ConstString;
@@ -3507,6 +3509,39 @@
     return true;
   }
 
+  public void rewriteLongCompareAndRequireNonNull(IRCode code, InternalOptions options) {
+    if (options.canUseLongCompareAndObjectsNonNull()) {
+      return;
+    }
+
+    InstructionIterator iterator = code.instructionIterator();
+    while (iterator.hasNext()) {
+      Instruction current = iterator.next();
+      if (current.isInvokeMethod()) {
+        DexMethod invokedMethod = current.asInvokeMethod().getInvokedMethod();
+        if (invokedMethod == dexItemFactory.longMethods.compare) {
+          // Rewrite calls to Long.compare for sdk versions that do not have that method.
+          List<Value> inValues = current.inValues();
+          assert inValues.size() == 2;
+          iterator.replaceCurrentInstruction(
+              new Cmp(NumericType.LONG, Bias.NONE, current.outValue(), inValues.get(0),
+                  inValues.get(1)));
+        } else if (invokedMethod == dexItemFactory.objectsMethods.requireNonNull) {
+          // Rewrite calls to Objects.requireNonNull(Object) because Javac 9 start to use it for
+          // synthesized null checks.
+          InvokeVirtual callToGetClass = new InvokeVirtual(dexItemFactory.objectMethods.getClass,
+              null, current.inValues());
+          if (current.outValue() != null) {
+            current.outValue().replaceUsers(current.inValues().get(0));
+            current.setOutValue(null);
+          }
+          iterator.replaceCurrentInstruction(callToGetClass);
+        }
+      }
+    }
+    assert code.isConsistentSSA();
+  }
+
   /**
    * Remove moves that are not actually used by instructions in exiting paths. These moves can arise
    * due to debug local info needing a particular value and the live-interval for it then moves it
diff --git a/src/main/java/com/android/tools/r8/utils/InternalOptions.java b/src/main/java/com/android/tools/r8/utils/InternalOptions.java
index 99eb7ea..7fafc4b 100644
--- a/src/main/java/com/android/tools/r8/utils/InternalOptions.java
+++ b/src/main/java/com/android/tools/r8/utils/InternalOptions.java
@@ -719,7 +719,7 @@
     return intermediate || hasMinApi(AndroidApiLevel.L);
   }
 
-  public boolean canUseJava7CompareAndObjectsOperations() {
+  public boolean canUseLongCompareAndObjectsNonNull() {
     return isGeneratingClassFiles() || hasMinApi(AndroidApiLevel.K);
   }
 
diff --git a/src/main/java/com/android/tools/r8/utils/ProgramClassCollection.java b/src/main/java/com/android/tools/r8/utils/ProgramClassCollection.java
index edc1873..1cf61c0 100644
--- a/src/main/java/com/android/tools/r8/utils/ProgramClassCollection.java
+++ b/src/main/java/com/android/tools/r8/utils/ProgramClassCollection.java
@@ -9,7 +9,7 @@
 import com.android.tools.r8.graph.DexProgramClass;
 import com.android.tools.r8.graph.DexType;
 import com.android.tools.r8.ir.desugar.InterfaceMethodRewriter;
-import com.android.tools.r8.ir.desugar.BackportedMethodRewriter;
+import com.android.tools.r8.ir.desugar.Java8MethodRewriter;
 import com.android.tools.r8.ir.desugar.LambdaRewriter;
 import com.android.tools.r8.ir.desugar.TwrCloseResourceRewriter;
 import java.util.List;
@@ -69,7 +69,7 @@
 
   private static boolean assumeClassesAreEqual(DexProgramClass a) {
     return LambdaRewriter.hasLambdaClassPrefix(a.type)
-        || BackportedMethodRewriter.hasRewrittenMethodPrefix(a.type)
+        || Java8MethodRewriter.hasJava8MethodRewritePrefix(a.type)
         || InterfaceMethodRewriter.hasDispatchClassSuffix(a.type)
         || a.type.descriptor.toString().equals(TwrCloseResourceRewriter.UTILITY_CLASS_DESCRIPTOR);
   }
diff --git a/src/test/examples/rewrite/LongCompare.java b/src/test/examples/rewrite/LongCompare.java
new file mode 100644
index 0000000..7c96c10
--- /dev/null
+++ b/src/test/examples/rewrite/LongCompare.java
@@ -0,0 +1,40 @@
+// 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 rewrite;
+
+public class LongCompare {
+
+  public static int simpleCompare(long l1, long l2) {
+    try {
+      return Long.compare(l1, l2);
+    } catch (Throwable t) {
+      System.out.println(t);
+    }
+    return 2;
+  }
+
+  public static long getValue1() {
+    return 123456789L;
+  }
+
+  public static long getValue2() {
+    return 0;
+  }
+
+  public static boolean complexCompare(long l1, long l2) {
+    return Long.compare(getValue1(), l1) == 0 && Long.compare(l2, getValue2()) > 0;
+  }
+
+  public static void main(String[] args) {
+    System.out.println(simpleCompare(123456789L, 987654321L));
+    System.out.println(simpleCompare(Long.MAX_VALUE, 0L));
+    System.out.println(simpleCompare(Long.MIN_VALUE, 0L));
+    System.out.println(simpleCompare(Long.MAX_VALUE, Long.MAX_VALUE));
+
+    System.out.println(complexCompare(123456789L, 1));
+    System.out.println(complexCompare(123456789L, -1));
+    System.out.println(complexCompare(1234567890L, 1));
+    System.out.println(complexCompare(1234567890L, -1));
+  }
+}
diff --git a/src/test/examples/rewrite/RequireNonNull.java b/src/test/examples/rewrite/RequireNonNull.java
new file mode 100644
index 0000000..d8868bf
--- /dev/null
+++ b/src/test/examples/rewrite/RequireNonNull.java
@@ -0,0 +1,39 @@
+// 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 rewrite;
+
+import java.util.Objects;
+
+public class RequireNonNull {
+
+  public static void main(String[] args) {
+    RequireNonNull o = new RequireNonNull();
+    System.out.println(o.nonnullRemove().toString());
+    System.out.println(o.nonnullRemove(o).toString());
+    o.nonnullWithPhiInstruction(true, o);
+    o.nonnullWithPhiInstruction(false, o);
+  }
+
+  private Object nonnullRemove() {
+    return Objects.requireNonNull(this);
+  }
+
+  private Object nonnullRemove(Object o) {
+    Objects.requireNonNull(o);
+    return o;
+  }
+
+  private void nonnullWithPhiInstruction(boolean b, Object input) {
+    Object o = null;
+    if (b) {
+      o = Objects.requireNonNull(input);
+    }
+    System.out.println(o);
+  }
+
+  @Override
+  public String toString() {
+    return "toString";
+  }
+}
diff --git a/src/test/java/com/android/tools/r8/desugar/BackportedMethodRewriterTest.java b/src/test/java/com/android/tools/r8/desugar/Java8MethodsTest.java
similarity index 74%
rename from src/test/java/com/android/tools/r8/desugar/BackportedMethodRewriterTest.java
rename to src/test/java/com/android/tools/r8/desugar/Java8MethodsTest.java
index a130c0f..cb4c9b7 100644
--- a/src/test/java/com/android/tools/r8/desugar/BackportedMethodRewriterTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/Java8MethodsTest.java
@@ -16,58 +16,56 @@
 import com.android.tools.r8.utils.codeinspector.MethodSubject;
 import java.nio.file.Path;
 import java.util.List;
-import java.util.Objects;
 import org.junit.Before;
 import org.junit.Test;
 
-public class BackportedMethodRewriterTest extends TestBase {
+public class Java8MethodsTest extends TestBase {
   static String expectedOutput = "";
 
   @Before
   public void testJvm() throws Exception {
     expectedOutput = testForJvm()
         .addTestClasspath()
-        .run(TestMethods.class).getStdOut();
+        .run(Java8Methods.class).getStdOut();
   }
 
   @Test
   public void testD8() throws Exception {
     testForD8()
-        .addProgramClasses(TestMethods.class)
-        .run(TestMethods.class)
+        .addProgramClasses(Java8Methods.class)
+        .run(Java8Methods.class)
         .assertSuccessWithOutput(expectedOutput);
 
-    assertDesugaring(AndroidApiLevel.O, 39);
-    assertDesugaring(AndroidApiLevel.N, 33);
-    assertDesugaring(AndroidApiLevel.K, 8);
-    assertDesugaring(AndroidApiLevel.J_MR2, 0);
+    assertDesugaring(AndroidApiLevel.O, 31);
+    assertDesugaring(AndroidApiLevel.N, 25);
+    assertDesugaring(AndroidApiLevel.M, 0);
   }
 
-  private void assertDesugaring(AndroidApiLevel apiLevel, int expectedJavaInvokeStatics)
+  private void assertDesugaring(AndroidApiLevel apilevel, int expectedJavaLangInvokeStatics)
       throws Exception {
     D8TestCompileResult runResult = testForD8()
-        .addProgramClasses(TestMethods.class)
-        .setMinApi(apiLevel)
+        .addProgramClasses(Java8Methods.class)
+        .setMinApi(apilevel)
         .compile();
 
     MethodSubject mainMethod = runResult.inspector()
-        .clazz(TestMethods.class)
+        .clazz(Java8Methods.class)
         .mainMethod();
     assertThat(mainMethod, isPresent());
 
-    List<InstructionSubject> javaInvokeStatics = mainMethod
+    List<InstructionSubject> javaLangInvokeStatics = mainMethod
         .streamInstructions()
         .filter(InstructionSubject::isInvokeStatic)
-        .filter(is -> is.getMethod().holder.toDescriptorString().startsWith("Ljava/"))
+        .filter(is -> is.getMethod().holder.toDescriptorString().startsWith("Ljava/lang/"))
         .collect(toList());
 
-    int actualJavaInvokeStatics = javaInvokeStatics.size();
+    int actualJavaLangInvokeStatics = javaLangInvokeStatics.size();
     assertEquals("Expected "
-        + expectedJavaInvokeStatics
-        + " invoke-static on java/*/<Type> but found "
-        + actualJavaInvokeStatics
+        + expectedJavaLangInvokeStatics
+        + " invoke-static on java/lang/<Type> but found "
+        + actualJavaLangInvokeStatics
         + ": "
-        + javaInvokeStatics, expectedJavaInvokeStatics, actualJavaInvokeStatics);
+        + javaLangInvokeStatics, expectedJavaLangInvokeStatics, actualJavaLangInvokeStatics);
   }
 
   @Test
@@ -124,29 +122,16 @@
     }
   }
 
-  static class TestMethods {
-    // Defined as a static method on this class to avoid affecting invoke-static counts in main().
-    private static int signum(int value) {
-      return (int) Math.signum(value);
-    }
-
+  static class Java8Methods {
     public static void main(String[] args) {
       byte[] aBytes = new byte[]{42, 1, -1, Byte.MAX_VALUE, Byte.MIN_VALUE};
       for (byte aByte : aBytes) {
         System.out.println(Byte.hashCode(aByte));
-        for (byte bByte : aBytes) {
-          // Normalize comparison to [-1, 1] since the values differ across versions but signs match
-          System.out.println(signum(Byte.compare(aByte, bByte)));
-        }
       }
 
       short[] aShorts = new short[]{42, 1, -1, Short.MAX_VALUE, Short.MIN_VALUE};
       for (short aShort : aShorts) {
         System.out.println(Short.hashCode(aShort));
-        for (short bShort : aShorts) {
-          // Normalize comparison to [-1, 1] since the values differ across versions but signs match
-          System.out.println(signum(Short.compare(aShort, bShort)));
-        }
       }
 
       int[] aInts = new int[]{42, 1, -1, Integer.MAX_VALUE, Integer.MIN_VALUE};
@@ -154,7 +139,6 @@
       for (int aInt : aInts) {
         System.out.println(Integer.hashCode(aInt));
         for (int bInt : bInts) {
-          System.out.println(Integer.compare(aInt, bInt));
           System.out.println(Integer.max(aInt, bInt));
           System.out.println(Integer.min(aInt, bInt));
           System.out.println(Integer.sum(aInt, bInt));
@@ -199,7 +183,6 @@
       for (boolean aBoolean : new boolean[]{true, false}) {
         System.out.println(Boolean.hashCode(aBoolean));
         for (boolean bBoolean : new boolean[]{true, false}) {
-          System.out.println(Boolean.compare(aBoolean, bBoolean));
           System.out.println(Boolean.logicalAnd(aBoolean, bBoolean));
           System.out.println(Boolean.logicalOr(aBoolean, bBoolean));
           System.out.println(Boolean.logicalXor(aBoolean, bBoolean));
@@ -213,7 +196,6 @@
       for (long aLong : aLongs) {
         System.out.println(Long.hashCode(aLong));
         for (long bLong : bLongs) {
-          System.out.println(Long.compare(aLong, bLong));
           System.out.println(Long.max(aLong, bLong));
           System.out.println(Long.min(aLong, bLong));
           System.out.println(Long.sum(aLong, bLong));
@@ -226,21 +208,6 @@
       char[] aChars = new char[]{'s', 'u', 'p', Character.MAX_VALUE, Character.MIN_VALUE};
       for (char aChar : aChars) {
         System.out.println(Character.hashCode(aChar));
-        for (char bChar : aChars) {
-          System.out.println(Character.compare(aChar, bChar));
-        }
-      }
-
-      // Use a runtime conditional so nullability analysis doesn't remove the requireNonNull call.
-      String nonNullString = args.length < Integer.MAX_VALUE ? "non-null string" : null;
-      System.out.println(Objects.requireNonNull(nonNullString));
-
-      try {
-        // Use a runtime conditional so nullability analysis doesn't remove the requireNonNull call.
-        String nullString = args.length == 0 ? null : "non-null string";
-        throw new AssertionError(Objects.requireNonNull(nullString));
-      } catch (NullPointerException expected) {
-        System.out.println("null");
       }
     }
   }
diff --git a/src/test/java/com/android/tools/r8/rewrite/longcompare/LongCompare.java b/src/test/java/com/android/tools/r8/rewrite/longcompare/LongCompare.java
new file mode 100644
index 0000000..16b7922
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/rewrite/longcompare/LongCompare.java
@@ -0,0 +1,80 @@
+// 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.rewrite.longcompare;
+
+import com.android.tools.r8.CompilationFailedException;
+import com.android.tools.r8.D8;
+import com.android.tools.r8.D8Command;
+import com.android.tools.r8.OutputMode;
+import com.android.tools.r8.ToolHelper;
+import com.android.tools.r8.ToolHelper.ArtCommandBuilder;
+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.InstructionSubject;
+import com.android.tools.r8.utils.codeinspector.InvokeInstructionSubject;
+import com.android.tools.r8.utils.codeinspector.MethodSubject;
+import java.io.IOException;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Arrays;
+import java.util.Iterator;
+import org.junit.Assert;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+
+/**
+ * Tests checking that Long.compare() is always rewritten into long compare instruction.
+ */
+public class LongCompare {
+
+  @Rule
+  public TemporaryFolder tmpOutputDir = ToolHelper.getTemporaryFolderForTest();
+
+  void compileWithD8(Path intputPath, Path outputPath)
+      throws IOException, CompilationFailedException {
+    D8.run(
+        D8Command.builder()
+            .addProgramFiles(intputPath)
+            .setOutput(outputPath, OutputMode.DexIndexed)
+            .build());
+  }
+
+  void runTest(Path dexFile) {
+    ArtCommandBuilder builder = new ArtCommandBuilder(ToolHelper.getDexVm());
+    builder.appendClasspath(dexFile.toString());
+    builder.setMainClass("rewrite.LongCompare");
+    try {
+      String output = ToolHelper.runArt(builder);
+      Assert
+          .assertEquals(StringUtils.lines("-1", "1", "-1", "0", "true", "false", "false", "false"),
+              output);
+    } catch (IOException e) {
+      Assert.fail();
+    }
+  }
+
+  @Test
+  public void testLongCompareIsRewritten() throws Exception {
+    final Path inputPath = Paths.get(ToolHelper.EXAMPLES_BUILD_DIR + "/rewrite.jar");
+    Path outputPath = tmpOutputDir.newFolder().toPath();
+
+    compileWithD8(inputPath, outputPath);
+
+    Path dexPath = outputPath.resolve("classes.dex");
+
+    CodeInspector codeInspector = new CodeInspector(dexPath);
+    ClassSubject classSubject = codeInspector.clazz("rewrite.LongCompare");
+    MethodSubject methodSubject = classSubject
+        .method("int", "simpleCompare", Arrays.asList("long", "long"));
+    // Check that exception handler is removed since it is no longer needed.
+    Assert.assertFalse(methodSubject.getMethod().getCode().asDexCode().usesExceptionHandling());
+    Iterator<InvokeInstructionSubject> iterator =
+        methodSubject.iterateInstructions(InstructionSubject::isInvoke);
+    Assert.assertFalse(iterator.hasNext());
+
+    runTest(dexPath);
+  }
+}
diff --git a/src/test/java/com/android/tools/r8/rewrite/longcompare/RequireNonNullRewriteTest.java b/src/test/java/com/android/tools/r8/rewrite/longcompare/RequireNonNullRewriteTest.java
new file mode 100644
index 0000000..278bc8b
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/rewrite/longcompare/RequireNonNullRewriteTest.java
@@ -0,0 +1,91 @@
+// 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.rewrite.longcompare;
+
+import com.android.tools.r8.CompilationFailedException;
+import com.android.tools.r8.CompilationMode;
+import com.android.tools.r8.D8;
+import com.android.tools.r8.D8Command;
+import com.android.tools.r8.OutputMode;
+import com.android.tools.r8.ToolHelper;
+import com.android.tools.r8.ToolHelper.ArtCommandBuilder;
+import com.android.tools.r8.ToolHelper.ProcessResult;
+import com.android.tools.r8.utils.codeinspector.ClassSubject;
+import com.android.tools.r8.utils.codeinspector.CodeInspector;
+import com.android.tools.r8.utils.codeinspector.InstructionSubject;
+import com.android.tools.r8.utils.codeinspector.InvokeInstructionSubject;
+import com.android.tools.r8.utils.codeinspector.MethodSubject;
+import java.io.IOException;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.concurrent.ExecutionException;
+import org.junit.Assert;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+
+public class RequireNonNullRewriteTest {
+
+  @Rule
+  public TemporaryFolder tmpOutputDir = ToolHelper.getTemporaryFolderForTest();
+
+  void compileWithD8(Path intputPath, Path outputPath, CompilationMode mode)
+      throws IOException, CompilationFailedException {
+    D8.run(
+        D8Command.builder()
+            .setMode(mode)
+            .addProgramFiles(intputPath)
+            .setOutput(outputPath, OutputMode.DexIndexed)
+            .build());
+  }
+
+  void runTest(Path jarFile, Path dexFile) {
+    String mainClass = "rewrite.RequireNonNull";
+    ArtCommandBuilder builder = new ArtCommandBuilder(ToolHelper.getDexVm());
+    builder.appendClasspath(dexFile.toString());
+    builder.setMainClass(mainClass);
+    try {
+      String output = ToolHelper.runArt(builder);
+      ProcessResult javaResult = ToolHelper.runJava(jarFile, mainClass);
+      Assert.assertEquals(javaResult.stdout, output);
+    } catch (IOException e) {
+      Assert.fail();
+    }
+  }
+
+  @Test
+  public void testDebugRequireNonNullIsRewritten() throws Exception {
+    runTest(CompilationMode.DEBUG);
+  }
+
+  @Test
+  public void testReleaseRequireNonNullIsRewritten() throws Exception {
+    runTest(CompilationMode.RELEASE);
+  }
+
+  private void runTest(CompilationMode mode)
+      throws IOException, ExecutionException, CompilationFailedException {
+    final Path inputPath = Paths.get(ToolHelper.EXAMPLES_BUILD_DIR + "/rewrite.jar");
+    Path outputPath = tmpOutputDir.newFolder().toPath();
+
+    compileWithD8(inputPath, outputPath, mode);
+
+    Path dexPath = outputPath.resolve("classes.dex");
+
+    CodeInspector codeInspector = new CodeInspector(dexPath);
+    ClassSubject classSubject = codeInspector.clazz("rewrite.RequireNonNull");
+    MethodSubject methodSubject = classSubject
+        .method("java.lang.Object", "nonnullRemove", Collections.emptyList());
+
+    Iterator<InvokeInstructionSubject> iterator =
+        methodSubject.iterateInstructions(InstructionSubject::isInvoke);
+    Assert.assertTrue(iterator.hasNext());
+    Assert.assertEquals("getClass", iterator.next().invokedMethod().name.toString());
+    Assert.assertFalse(iterator.hasNext());
+
+    runTest(inputPath, dexPath);
+  }
+}