Merge commit 'fb5b6dad1e23261f8b70b94e6ea21de4045b335c' into dev-release

Change-Id: I257f80f1f9a1e34809c14f377deebb7aadce2f56
diff --git a/src/main/java/com/android/tools/r8/graph/ObjectAllocationInfoCollectionImpl.java b/src/main/java/com/android/tools/r8/graph/ObjectAllocationInfoCollectionImpl.java
index 2ffe096..669e86b 100644
--- a/src/main/java/com/android/tools/r8/graph/ObjectAllocationInfoCollectionImpl.java
+++ b/src/main/java/com/android/tools/r8/graph/ObjectAllocationInfoCollectionImpl.java
@@ -122,6 +122,16 @@
     return clazz.isInterface() && interfacesWithUnknownSubtypeHierarchy.contains(clazz);
   }
 
+  /**
+   * Returns true if the type is an annotation interface which (by design) has an unknown subtype
+   * hierarchy.
+   */
+  public boolean isAnnotationInterfaceWithUnknownSubtypeHierarchy(DexProgramClass iface) {
+    return iface.isInterface()
+        && iface.isAnnotation()
+        && annotationsWithUnknownSubtypeHierarchy.contains(iface);
+  }
+
   /** Returns true if the type is an immediate interface of an instantiated lambda. */
   @Override
   public boolean isImmediateInterfaceOfInstantiatedLambda(DexProgramClass iface) {
@@ -522,6 +532,18 @@
         assert !interfacesWithUnknownSubtypeHierarchy.contains(rewrittenClass);
         interfacesWithUnknownSubtypeHierarchy.add(rewrittenClass);
       }
+      for (DexProgramClass abstractType :
+          objectAllocationInfos.annotationsWithUnknownSubtypeHierarchy) {
+        DexType type = lens.lookupType(abstractType.type, appliedLens);
+        if (type.isPrimitiveType()) {
+          assert false;
+          continue;
+        }
+        DexProgramClass rewrittenClass = asProgramClassOrNull(definitions.definitionFor(type));
+        assert rewrittenClass != null;
+        assert !annotationsWithUnknownSubtypeHierarchy.contains(rewrittenClass);
+        annotationsWithUnknownSubtypeHierarchy.add(rewrittenClass);
+      }
       LensCodeRewriterUtils rewriter = new LensCodeRewriterUtils(definitions, lens, appliedLens);
       objectAllocationInfos.instantiatedLambdas.forEach(
           (iface, lambdas) -> {
diff --git a/src/main/java/com/android/tools/r8/ir/code/Invoke.java b/src/main/java/com/android/tools/r8/ir/code/Invoke.java
index d16fdc6..6aa12e5 100644
--- a/src/main/java/com/android/tools/r8/ir/code/Invoke.java
+++ b/src/main/java/com/android/tools/r8/ir/code/Invoke.java
@@ -258,8 +258,13 @@
   // Used to decide if this invoke should be emitted as invoke/range.
   protected boolean needsRangedInvoke(DexBuilder builder) {
     if (arguments().size() == 1) {
-      // Prefer invoke-range since this does not impose any constraints on the operand register.
-      return true;
+      // Prefer non-range invoke since ART's LSE does not always consider invoke/range
+      // (b/378823200).
+      int registerEnd =
+          builder.getRegisterAllocator().getRegisterForValue(getFirstArgument(), getNumber())
+              + getFirstArgument().requiredRegisters()
+              - 1;
+      return registerEnd > Constants.U4BIT_MAX;
     }
     if (requiredArgumentRegisters() > 5) {
       // No way around using an invoke-range instruction.
diff --git a/src/main/java/com/android/tools/r8/ir/regalloc/RegisterMoveCycleDetector.java b/src/main/java/com/android/tools/r8/ir/regalloc/RegisterMoveCycleDetector.java
index cdb321d..a6b2ad6 100644
--- a/src/main/java/com/android/tools/r8/ir/regalloc/RegisterMoveCycleDetector.java
+++ b/src/main/java/com/android/tools/r8/ir/regalloc/RegisterMoveCycleDetector.java
@@ -19,10 +19,7 @@
 
   @SuppressWarnings("MixedMutabilityReturnType")
   static List<RegisterMoveCycle> getMoveCycles(TreeSet<RegisterMove> moveSet) {
-    // Although there can be a cycle when there are two moves, we return no cycles, since the
-    // default move scheduling has the same behavior as the cycle-based move scheduling in this
-    // case.
-    if (moveSet.size() <= 2) {
+    if (moveSet.size() <= 1) {
       return Collections.emptyList();
     }
     List<RegisterMoveCycle> moveCycles = new ArrayList<>();
diff --git a/src/main/java/com/android/tools/r8/shaking/AppInfoWithLiveness.java b/src/main/java/com/android/tools/r8/shaking/AppInfoWithLiveness.java
index 022be10..cbba232 100644
--- a/src/main/java/com/android/tools/r8/shaking/AppInfoWithLiveness.java
+++ b/src/main/java/com/android/tools/r8/shaking/AppInfoWithLiveness.java
@@ -1156,8 +1156,10 @@
     // TODO(b/148769279): Disable lookup single target on lambda's for now.
     if (resolvedHolder.isInterface()
         && resolvedHolder.isProgramClass()
-        && objectAllocationInfoCollection.isImmediateInterfaceOfInstantiatedLambda(
-            resolvedHolder.asProgramClass())) {
+        && (objectAllocationInfoCollection.isImmediateInterfaceOfInstantiatedLambda(
+                resolvedHolder.asProgramClass())
+            || objectAllocationInfoCollection.isAnnotationInterfaceWithUnknownSubtypeHierarchy(
+                resolvedHolder.asProgramClass()))) {
       singleTargetLookupCache.addNoSingleTargetToCache(refinedReceiverType, method);
       return null;
     }
diff --git a/src/test/java/com/android/tools/r8/accessrelaxation/InvokeTypeConversionTest.java b/src/test/java/com/android/tools/r8/accessrelaxation/InvokeTypeConversionTest.java
index e1c7e00..f29440c 100644
--- a/src/test/java/com/android/tools/r8/accessrelaxation/InvokeTypeConversionTest.java
+++ b/src/test/java/com/android/tools/r8/accessrelaxation/InvokeTypeConversionTest.java
@@ -13,8 +13,8 @@
 import com.android.tools.r8.TestParameters;
 import com.android.tools.r8.TestParametersCollection;
 import com.android.tools.r8.ToolHelper.DexVm.Version;
-import com.android.tools.r8.dex.code.DexInvokeDirectRange;
-import com.android.tools.r8.dex.code.DexInvokeVirtualRange;
+import com.android.tools.r8.dex.code.DexInvokeDirect;
+import com.android.tools.r8.dex.code.DexInvokeVirtual;
 import com.android.tools.r8.graph.DexCode;
 import com.android.tools.r8.graph.DexEncodedMethod;
 import com.android.tools.r8.smali.SmaliBuilder;
@@ -121,7 +121,7 @@
           assertNotNull(method);
           DexCode code = method.getCode().asDexCode();
           // The given invoke line is remained as-is.
-          assertTrue(code.instructions[2] instanceof DexInvokeDirectRange);
+          assertTrue(code.instructions[2] instanceof DexInvokeDirect);
         });
   }
 
@@ -152,7 +152,7 @@
           assertNotNull(method);
           DexCode code = method.getCode().asDexCode();
           // The given invoke line is changed to invoke-virtual
-          assertTrue(code.instructions[2] instanceof DexInvokeVirtualRange);
+          assertTrue(code.instructions[2] instanceof DexInvokeVirtual);
         });
   }
 
diff --git a/src/test/java/com/android/tools/r8/compatproguard/ForNameTest.java b/src/test/java/com/android/tools/r8/compatproguard/ForNameTest.java
index d64aa20..9c7cf17 100644
--- a/src/test/java/com/android/tools/r8/compatproguard/ForNameTest.java
+++ b/src/test/java/com/android/tools/r8/compatproguard/ForNameTest.java
@@ -8,7 +8,7 @@
 import static org.junit.Assert.assertTrue;
 
 import com.android.tools.r8.dex.code.DexConstString;
-import com.android.tools.r8.dex.code.DexInvokeStaticRange;
+import com.android.tools.r8.dex.code.DexInvokeStatic;
 import com.android.tools.r8.dex.code.DexReturnVoid;
 import com.android.tools.r8.graph.DexCode;
 import com.android.tools.r8.smali.SmaliBuilder;
@@ -55,7 +55,7 @@
     assertTrue(code.instructions[0] instanceof DexConstString);
     DexConstString constString = (DexConstString) code.instructions[0];
     assertNotEquals(BOO, constString.getString().toString());
-    assertTrue(code.instructions[1] instanceof DexInvokeStaticRange);
+    assertTrue(code.instructions[1] instanceof DexInvokeStatic);
     assertTrue(code.instructions[2] instanceof DexReturnVoid);
   }
 
@@ -91,7 +91,7 @@
     assertTrue(code.instructions[0] instanceof DexConstString);
     DexConstString constString = (DexConstString) code.instructions[0];
     assertEquals(BOO, constString.getString().toString());
-    assertTrue(code.instructions[1] instanceof DexInvokeStaticRange);
+    assertTrue(code.instructions[1] instanceof DexInvokeStatic);
     assertTrue(code.instructions[2] instanceof DexReturnVoid);
   }
 
diff --git a/src/test/java/com/android/tools/r8/compatproguard/GetMembersTest.java b/src/test/java/com/android/tools/r8/compatproguard/GetMembersTest.java
index eb24283..3449aa1 100644
--- a/src/test/java/com/android/tools/r8/compatproguard/GetMembersTest.java
+++ b/src/test/java/com/android/tools/r8/compatproguard/GetMembersTest.java
@@ -15,7 +15,7 @@
 import com.android.tools.r8.dex.code.DexConst4;
 import com.android.tools.r8.dex.code.DexConstClass;
 import com.android.tools.r8.dex.code.DexConstString;
-import com.android.tools.r8.dex.code.DexFilledNewArrayRange;
+import com.android.tools.r8.dex.code.DexFilledNewArray;
 import com.android.tools.r8.dex.code.DexInvokeVirtual;
 import com.android.tools.r8.dex.code.DexMoveResultObject;
 import com.android.tools.r8.dex.code.DexNewArray;
@@ -75,9 +75,9 @@
   private void inspectGetMethodTest(MethodSubject method) {
     // Accept either array construction style (differs based on minSdkVersion).
     DexCode code = method.getMethod().getCode().asDexCode();
-    if (code.instructions[1] instanceof DexFilledNewArrayRange) {
+    if (code.instructions[1] instanceof DexFilledNewArray) {
       assertTrue(code.instructions[0] instanceof DexConstClass);
-      assertTrue(code.instructions[1] instanceof DexFilledNewArrayRange);
+      assertTrue(code.instructions[1] instanceof DexFilledNewArray);
       assertTrue(code.instructions[2] instanceof DexMoveResultObject);
       assertTrue(code.instructions[3] instanceof DexConstClass);
       assertTrue(code.instructions[4] instanceof DexConstString);
diff --git a/src/test/java/com/android/tools/r8/ir/regalloc/RegisterMoveSchedulerTest.java b/src/test/java/com/android/tools/r8/ir/regalloc/RegisterMoveSchedulerTest.java
index 804b482..7e42fa9 100644
--- a/src/test/java/com/android/tools/r8/ir/regalloc/RegisterMoveSchedulerTest.java
+++ b/src/test/java/com/android/tools/r8/ir/regalloc/RegisterMoveSchedulerTest.java
@@ -544,6 +544,21 @@
     assertEquals(2, scheduler.getUsedTempRegisters());
   }
 
+  @Test
+  public void regressionTestBug378850589() {
+    CollectMovesIterator moves = new CollectMovesIterator();
+    int temp = 42;
+    RegisterMoveScheduler scheduler = new RegisterMoveScheduler(moves, temp);
+    scheduler.addMove(new RegisterMove(9, 12, TypeElement.getLong()));
+    scheduler.addMove(new RegisterMove(11, 8, TypeElement.getLong()));
+    scheduler.schedule();
+    assertEquals(3, moves.size());
+    assertEquals("42 <- 12", toString(moves.get(0)));
+    assertEquals("11 <- 8", toString(moves.get(1)));
+    assertEquals("9 <- 42", toString(moves.get(3)));
+    assertEquals(2, scheduler.getUsedTempRegisters());
+  }
+
   // Debugging aid.
   private void printMoves(List<Instruction> moves) {
     System.out.println("Generated moves:");
diff --git a/src/test/java/com/android/tools/r8/naming/IdentifierNameStringMarkerTest.java b/src/test/java/com/android/tools/r8/naming/IdentifierNameStringMarkerTest.java
index 42a037e..cc150aa 100644
--- a/src/test/java/com/android/tools/r8/naming/IdentifierNameStringMarkerTest.java
+++ b/src/test/java/com/android/tools/r8/naming/IdentifierNameStringMarkerTest.java
@@ -18,10 +18,9 @@
 import com.android.tools.r8.dex.code.DexConst4;
 import com.android.tools.r8.dex.code.DexConstClass;
 import com.android.tools.r8.dex.code.DexConstString;
-import com.android.tools.r8.dex.code.DexFilledNewArrayRange;
-import com.android.tools.r8.dex.code.DexInvokeDirectRange;
+import com.android.tools.r8.dex.code.DexFilledNewArray;
+import com.android.tools.r8.dex.code.DexInvokeDirect;
 import com.android.tools.r8.dex.code.DexInvokeStatic;
-import com.android.tools.r8.dex.code.DexInvokeStaticRange;
 import com.android.tools.r8.dex.code.DexInvokeVirtual;
 import com.android.tools.r8.dex.code.DexIputObject;
 import com.android.tools.r8.dex.code.DexMoveResultObject;
@@ -86,10 +85,7 @@
     checkInstructions(
         code,
         ImmutableList.of(
-            DexInvokeDirectRange.class,
-            DexConstString.class,
-            DexIputObject.class,
-            DexReturnVoid.class));
+            DexInvokeDirect.class, DexConstString.class, DexIputObject.class, DexReturnVoid.class));
     DexConstString constString = (DexConstString) code.instructions[1];
     assertEquals(BOO, constString.getString().toString());
   }
@@ -123,7 +119,7 @@
     checkInstructions(
         code,
         ImmutableList.of(
-            DexInvokeDirectRange.class,
+            DexInvokeDirect.class,
             DexSgetObject.class,
             DexConstString.class,
             DexInvokeVirtual.class,
@@ -164,7 +160,7 @@
     checkInstructions(
         code,
         ImmutableList.of(
-            DexInvokeDirectRange.class,
+            DexInvokeDirect.class,
             DexSgetObject.class,
             DexConstString.class,
             DexInvokeVirtual.class,
@@ -415,7 +411,7 @@
     checkInstructions(
         code,
         ImmutableList.of(
-            DexInvokeDirectRange.class,
+            DexInvokeDirect.class,
             DexConstString.class,
             DexConstString.class,
             DexInvokeStatic.class,
@@ -459,11 +455,11 @@
     checkInstructions(
         code,
         ImmutableList.of(
-            DexInvokeDirectRange.class,
+            DexInvokeDirect.class,
             DexSgetObject.class,
             DexConstString.class,
             DexInvokeVirtual.class,
-            DexInvokeStaticRange.class,
+            DexInvokeStatic.class,
             DexReturnVoid.class));
     DexConstString constString = (DexConstString) code.instructions[2];
     assertEquals(BOO, constString.getString().toString());
@@ -504,12 +500,12 @@
     checkInstructions(
         code,
         ImmutableList.of(
-            DexInvokeDirectRange.class,
+            DexInvokeDirect.class,
             DexSgetObject.class,
             DexConstString.class,
             DexInvokeVirtual.class,
             DexConstString.class,
-            DexInvokeStaticRange.class,
+            DexInvokeStatic.class,
             DexReturnVoid.class));
     DexConstString constString = (DexConstString) code.instructions[2];
     assertEquals(BOO, constString.getString().toString());
@@ -559,7 +555,7 @@
     checkInstructions(
         code,
         ImmutableList.of(
-            DexInvokeDirectRange.class,
+            DexInvokeDirect.class,
             DexConstClass.class,
             DexConstString.class,
             DexInvokeStatic.class,
@@ -610,7 +606,7 @@
     checkInstructions(
         code,
         ImmutableList.of(
-            DexInvokeDirectRange.class,
+            DexInvokeDirect.class,
             DexConstClass.class,
             DexConstString.class,
             DexInvokeStatic.class,
@@ -666,13 +662,13 @@
 
     DexCode code = method.getCode().asDexCode();
     // Accept either array construction style (differs based on minSdkVersion).
-    if (code.instructions[2].getClass() == DexFilledNewArrayRange.class) {
+    if (code.instructions[2].getClass() == DexFilledNewArray.class) {
       checkInstructions(
           code,
           ImmutableList.of(
-              DexInvokeDirectRange.class,
+              DexInvokeDirect.class,
               DexConstClass.class,
-              DexFilledNewArrayRange.class,
+              DexFilledNewArray.class,
               DexMoveResultObject.class,
               DexConstString.class,
               DexInvokeStatic.class,
@@ -681,7 +677,7 @@
       checkInstructions(
           code,
           ImmutableList.of(
-              DexInvokeDirectRange.class,
+              DexInvokeDirect.class,
               DexConstClass.class,
               DexConst4.class,
               DexNewArray.class,
@@ -742,13 +738,13 @@
 
     DexCode code = method.getCode().asDexCode();
     // Accept either array construction style (differs based on minSdkVersion).
-    if (code.instructions[2].getClass() == DexFilledNewArrayRange.class) {
+    if (code.instructions[2].getClass() == DexFilledNewArray.class) {
       checkInstructions(
           code,
           ImmutableList.of(
-              DexInvokeDirectRange.class,
+              DexInvokeDirect.class,
               DexConstClass.class,
-              DexFilledNewArrayRange.class,
+              DexFilledNewArray.class,
               DexMoveResultObject.class,
               DexConstString.class,
               DexInvokeStatic.class,
@@ -757,7 +753,7 @@
       checkInstructions(
           code,
           ImmutableList.of(
-              DexInvokeDirectRange.class,
+              DexInvokeDirect.class,
               DexConstClass.class,
               DexConst4.class,
               DexNewArray.class,
diff --git a/src/test/java/com/android/tools/r8/optimize/ReproduceKT72888Test.java b/src/test/java/com/android/tools/r8/optimize/AnnotationImplementedAndInstantiatedInProgramTest.java
similarity index 93%
rename from src/test/java/com/android/tools/r8/optimize/ReproduceKT72888Test.java
rename to src/test/java/com/android/tools/r8/optimize/AnnotationImplementedAndInstantiatedInProgramTest.java
index a61ef15..83e0029 100644
--- a/src/test/java/com/android/tools/r8/optimize/ReproduceKT72888Test.java
+++ b/src/test/java/com/android/tools/r8/optimize/AnnotationImplementedAndInstantiatedInProgramTest.java
@@ -15,8 +15,9 @@
 import org.junit.runners.Parameterized.Parameter;
 import org.junit.runners.Parameterized.Parameters;
 
+// This is a reproduction of b/378473616 (extracted from KT-72888)
 @RunWith(Parameterized.class)
-public class ReproduceKT72888Test extends TestBase {
+public class AnnotationImplementedAndInstantiatedInProgramTest extends TestBase {
 
   @Parameter(0)
   public TestParameters parameters;
@@ -57,7 +58,7 @@
         .addKeepRuntimeVisibleAnnotations()
         .setMinApi(parameters)
         .run(parameters.getRuntime(), TestClass.class)
-        .assertFailureWithErrorThatThrows(ClassCastException.class);
+        .assertSuccessWithOutput(EXPECTED_OUTPUT);
   }
 
   @Retention(RetentionPolicy.RUNTIME)
diff --git a/src/test/java/com/android/tools/r8/smali/IfSimplificationTest.java b/src/test/java/com/android/tools/r8/smali/IfSimplificationTest.java
index c7adad6..9642e4e 100644
--- a/src/test/java/com/android/tools/r8/smali/IfSimplificationTest.java
+++ b/src/test/java/com/android/tools/r8/smali/IfSimplificationTest.java
@@ -14,7 +14,7 @@
 import com.android.tools.r8.dex.code.DexIfLez;
 import com.android.tools.r8.dex.code.DexIfLtz;
 import com.android.tools.r8.dex.code.DexIfNez;
-import com.android.tools.r8.dex.code.DexInvokeVirtualRange;
+import com.android.tools.r8.dex.code.DexInvokeVirtual;
 import com.android.tools.r8.dex.code.DexReturn;
 import com.android.tools.r8.dex.code.DexReturnObject;
 import com.android.tools.r8.graph.DexCode;
@@ -399,7 +399,7 @@
             "          goto                :label_7");
     DexCode code = method.getCode().asDexCode();
     assertEquals(3, code.instructions.length);
-    assertTrue(code.instructions[0] instanceof DexInvokeVirtualRange);
+    assertTrue(code.instructions[0] instanceof DexInvokeVirtual);
     assertTrue(code.instructions[1] instanceof DexConst4);
     assertEquals(0, ((DexConst4) code.instructions[1]).B);
     assertTrue(code.instructions[2] instanceof DexReturnObject);
diff --git a/src/test/java/com/android/tools/r8/smali/OutlineTest.java b/src/test/java/com/android/tools/r8/smali/OutlineTest.java
index b3a09bf..25e8d89 100644
--- a/src/test/java/com/android/tools/r8/smali/OutlineTest.java
+++ b/src/test/java/com/android/tools/r8/smali/OutlineTest.java
@@ -575,7 +575,7 @@
         DexInvokeStatic invoke = (DexInvokeStatic) mainCode.instructions[4];
         assertTrue(isOutlineMethodName(invoke.getMethod()));
       } else if (i == 3) {
-        DexInvokeStaticRange invoke = (DexInvokeStaticRange) mainCode.instructions[1];
+        DexInvokeStatic invoke = (DexInvokeStatic) mainCode.instructions[1];
         assertTrue(isOutlineMethodName(invoke.getMethod()));
       } else {
         assert i == 4 || i == 5;