Merge "Use ranged invoke if input arguments are consecutive"
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 af6d5a3..6f535bb 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
@@ -103,7 +103,7 @@
   }
 
   protected int argumentRegisterValue(int i, DexBuilder builder) {
-    assert needsRangedInvoke(builder);
+    assert needsRangedInvoke();
     if (i < arguments().size()) {
       // If argument values flow into ranged invokes, all the ranged invoke arguments
       // are arguments to this method in order. Therefore, we use the incoming registers
@@ -116,9 +116,11 @@
   }
 
   protected int fillArgumentRegisters(DexBuilder builder, int[] registers) {
+    assert !needsRangedInvoke();
     int i = 0;
     for (Value value : arguments()) {
       int register = builder.allocatedRegister(value, getNumber());
+      assert register <= Constants.U4BIT_MAX;
       for (int j = 0; j < value.requiredRegisters(); j++) {
         assert i < 5;
         registers[i++] = register++;
@@ -127,15 +129,6 @@
     return i;
   }
 
-  protected boolean hasHighArgumentRegister(DexBuilder builder) {
-    for (Value value : arguments()) {
-      if (builder.argumentValueUsesHighRegister(value, getNumber())) {
-        return true;
-      }
-    }
-    return false;
-  }
-
   protected boolean argumentsConsecutive(DexBuilder builder) {
     Value value = arguments().get(0);
     int next = builder.argumentOrAllocateRegister(value, getNumber()) + value.requiredRegisters();
@@ -206,19 +199,8 @@
     return true;
   }
 
-  private boolean argumentsAreConsecutiveInputArgumentsWithHighRegisters(
-      DexBuilder builder) {
-    if (!argumentsAreConsecutiveInputArguments()) {
-      return false;
-    }
-    Value lastArgument = arguments().get(arguments().size() - 1);
-    return builder.argumentOrAllocateRegister(lastArgument, getNumber()) > Constants.U4BIT_MAX;
-  }
-
-  protected boolean needsRangedInvoke(DexBuilder builder) {
-    return requiredArgumentRegisters() > 5
-        || hasHighArgumentRegister(builder)
-        || argumentsAreConsecutiveInputArgumentsWithHighRegisters(builder);
+  protected boolean needsRangedInvoke() {
+    return requiredArgumentRegisters() > 5 || argumentsAreConsecutiveInputArguments();
   }
 
   @Override
diff --git a/src/main/java/com/android/tools/r8/ir/code/InvokeCustom.java b/src/main/java/com/android/tools/r8/ir/code/InvokeCustom.java
index 0579362..9d95514 100644
--- a/src/main/java/com/android/tools/r8/ir/code/InvokeCustom.java
+++ b/src/main/java/com/android/tools/r8/ir/code/InvokeCustom.java
@@ -54,7 +54,7 @@
     com.android.tools.r8.code.Instruction instruction;
     int argumentRegisters = requiredArgumentRegisters();
     builder.requestOutgoingRegisters(argumentRegisters);
-    if (needsRangedInvoke(builder)) {
+    if (needsRangedInvoke()) {
       assert argumentsConsecutive(builder);
       int firstRegister = argumentRegisterValue(0, builder);
       instruction = new InvokeCustomRange(firstRegister, argumentRegisters, getCallSite());
diff --git a/src/main/java/com/android/tools/r8/ir/code/InvokeDirect.java b/src/main/java/com/android/tools/r8/ir/code/InvokeDirect.java
index fa85845..12c991d 100644
--- a/src/main/java/com/android/tools/r8/ir/code/InvokeDirect.java
+++ b/src/main/java/com/android/tools/r8/ir/code/InvokeDirect.java
@@ -52,7 +52,7 @@
     com.android.tools.r8.code.Instruction instruction;
     int argumentRegisters = requiredArgumentRegisters();
     builder.requestOutgoingRegisters(argumentRegisters);
-    if (needsRangedInvoke(builder)) {
+    if (needsRangedInvoke()) {
       assert argumentsConsecutive(builder);
       int firstRegister = argumentRegisterValue(0, builder);
       instruction = new InvokeDirectRange(firstRegister, argumentRegisters, getInvokedMethod());
diff --git a/src/main/java/com/android/tools/r8/ir/code/InvokeInterface.java b/src/main/java/com/android/tools/r8/ir/code/InvokeInterface.java
index d29e3eb..e886f27 100644
--- a/src/main/java/com/android/tools/r8/ir/code/InvokeInterface.java
+++ b/src/main/java/com/android/tools/r8/ir/code/InvokeInterface.java
@@ -46,7 +46,7 @@
     com.android.tools.r8.code.Instruction instruction;
     int argumentRegisters = requiredArgumentRegisters();
     builder.requestOutgoingRegisters(argumentRegisters);
-    if (needsRangedInvoke(builder)) {
+    if (needsRangedInvoke()) {
       assert argumentsConsecutive(builder);
       int firstRegister = argumentRegisterValue(0, builder);
       instruction = new InvokeInterfaceRange(firstRegister, argumentRegisters, getInvokedMethod());
diff --git a/src/main/java/com/android/tools/r8/ir/code/InvokeNewArray.java b/src/main/java/com/android/tools/r8/ir/code/InvokeNewArray.java
index 41e4ccf..746f87a 100644
--- a/src/main/java/com/android/tools/r8/ir/code/InvokeNewArray.java
+++ b/src/main/java/com/android/tools/r8/ir/code/InvokeNewArray.java
@@ -56,7 +56,7 @@
     com.android.tools.r8.code.Instruction instruction;
     int argumentRegisters = requiredArgumentRegisters();
     builder.requestOutgoingRegisters(argumentRegisters);
-    if (needsRangedInvoke(builder)) {
+    if (needsRangedInvoke()) {
       assert argumentsConsecutive(builder);
       int firstRegister = argumentRegisterValue(0, builder);
       instruction = new FilledNewArrayRange(firstRegister, argumentRegisters, type);
diff --git a/src/main/java/com/android/tools/r8/ir/code/InvokePolymorphic.java b/src/main/java/com/android/tools/r8/ir/code/InvokePolymorphic.java
index 0e63cc7..624c534 100644
--- a/src/main/java/com/android/tools/r8/ir/code/InvokePolymorphic.java
+++ b/src/main/java/com/android/tools/r8/ir/code/InvokePolymorphic.java
@@ -60,7 +60,7 @@
     com.android.tools.r8.code.Instruction instruction;
     int argumentRegisters = requiredArgumentRegisters();
     builder.requestOutgoingRegisters(argumentRegisters);
-    if (needsRangedInvoke(builder)) {
+    if (needsRangedInvoke()) {
       assert argumentsConsecutive(builder);
       int firstRegister = argumentRegisterValue(0, builder);
       instruction = new InvokePolymorphicRange(
diff --git a/src/main/java/com/android/tools/r8/ir/code/InvokeStatic.java b/src/main/java/com/android/tools/r8/ir/code/InvokeStatic.java
index 896fca9..1930948 100644
--- a/src/main/java/com/android/tools/r8/ir/code/InvokeStatic.java
+++ b/src/main/java/com/android/tools/r8/ir/code/InvokeStatic.java
@@ -53,7 +53,7 @@
     com.android.tools.r8.code.Instruction instruction;
     int argumentRegisters = requiredArgumentRegisters();
     builder.requestOutgoingRegisters(argumentRegisters);
-    if (needsRangedInvoke(builder)) {
+    if (needsRangedInvoke()) {
       assert argumentsConsecutive(builder);
       int firstRegister = argumentRegisterValue(0, builder);
       instruction = new InvokeStaticRange(firstRegister, argumentRegisters, getInvokedMethod());
diff --git a/src/main/java/com/android/tools/r8/ir/code/InvokeSuper.java b/src/main/java/com/android/tools/r8/ir/code/InvokeSuper.java
index c761184..3a70bac 100644
--- a/src/main/java/com/android/tools/r8/ir/code/InvokeSuper.java
+++ b/src/main/java/com/android/tools/r8/ir/code/InvokeSuper.java
@@ -58,7 +58,7 @@
     com.android.tools.r8.code.Instruction instruction;
     int argumentRegisters = requiredArgumentRegisters();
     builder.requestOutgoingRegisters(argumentRegisters);
-    if (needsRangedInvoke(builder)) {
+    if (needsRangedInvoke()) {
       assert argumentsConsecutive(builder);
       int firstRegister = argumentRegisterValue(0, builder);
       instruction = new InvokeSuperRange(firstRegister, argumentRegisters, getInvokedMethod());
diff --git a/src/main/java/com/android/tools/r8/ir/code/InvokeVirtual.java b/src/main/java/com/android/tools/r8/ir/code/InvokeVirtual.java
index 5ef74b8..50b83c6 100644
--- a/src/main/java/com/android/tools/r8/ir/code/InvokeVirtual.java
+++ b/src/main/java/com/android/tools/r8/ir/code/InvokeVirtual.java
@@ -46,7 +46,7 @@
     com.android.tools.r8.code.Instruction instruction;
     int argumentRegisters = requiredArgumentRegisters();
     builder.requestOutgoingRegisters(argumentRegisters);
-    if (needsRangedInvoke(builder)) {
+    if (needsRangedInvoke()) {
       assert argumentsConsecutive(builder);
       int firstRegister = argumentRegisterValue(0, builder);
       instruction = new InvokeVirtualRange(firstRegister, argumentRegisters, getInvokedMethod());
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/lambda/kotlin/JStyleLambdaGroup.java b/src/main/java/com/android/tools/r8/ir/optimize/lambda/kotlin/JStyleLambdaGroup.java
index b4a1865..c4e2ab6 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/lambda/kotlin/JStyleLambdaGroup.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/lambda/kotlin/JStyleLambdaGroup.java
@@ -160,8 +160,9 @@
     int validateInstanceInitializerEpilogue(
         com.android.tools.r8.code.Instruction[] instructions, int index)
         throws LambdaStructureError {
-      if (!(instructions[index] instanceof com.android.tools.r8.code.InvokeDirect) ||
-          instructions[index].getMethod() != kotlin.factory.objectMethods.constructor) {
+      if (!(instructions[index] instanceof com.android.tools.r8.code.InvokeDirect
+              || instructions[index] instanceof com.android.tools.r8.code.InvokeDirectRange)
+          || instructions[index].getMethod() != kotlin.factory.objectMethods.constructor) {
         throw structureError(LAMBDA_INIT_CODE_VERIFICATION_FAILED);
       }
       index++;
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/lambda/kotlin/KStyleLambdaGroup.java b/src/main/java/com/android/tools/r8/ir/optimize/lambda/kotlin/KStyleLambdaGroup.java
index 46c14e9..46add5f 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/lambda/kotlin/KStyleLambdaGroup.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/lambda/kotlin/KStyleLambdaGroup.java
@@ -170,8 +170,9 @@
         throw structureError(LAMBDA_INIT_CODE_VERIFICATION_FAILED);
       }
       index++;
-      if (!(instructions[index] instanceof com.android.tools.r8.code.InvokeDirect) ||
-          instructions[index].getMethod() != kotlin.functional.lambdaInitializerMethod) {
+      if (!(instructions[index] instanceof com.android.tools.r8.code.InvokeDirect
+              || instructions[index] instanceof com.android.tools.r8.code.InvokeDirectRange)
+          || instructions[index].getMethod() != kotlin.functional.lambdaInitializerMethod) {
         throw structureError(LAMBDA_INIT_CODE_VERIFICATION_FAILED);
       }
       index++;
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/lambda/kotlin/KotlinLambdaClassValidator.java b/src/main/java/com/android/tools/r8/ir/optimize/lambda/kotlin/KotlinLambdaClassValidator.java
index 3410703..2385f35 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/lambda/kotlin/KotlinLambdaClassValidator.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/lambda/kotlin/KotlinLambdaClassValidator.java
@@ -225,8 +225,9 @@
         ((com.android.tools.r8.code.NewInstance) instructions[0]).getType() != lambda.type) {
       throw structureError(LAMBDA_CLINIT_CODE_VERIFICATION_FAILED);
     }
-    if (!(instructions[1] instanceof com.android.tools.r8.code.InvokeDirect) ||
-        !isLambdaInitializerMethod(lambda, instructions[1].getMethod())) {
+    if (!(instructions[1] instanceof com.android.tools.r8.code.InvokeDirect
+            || instructions[1] instanceof com.android.tools.r8.code.InvokeDirectRange)
+        || !isLambdaInitializerMethod(lambda, instructions[1].getMethod())) {
       throw structureError(LAMBDA_CLINIT_CODE_VERIFICATION_FAILED);
     }
     if (!(instructions[2] instanceof SputObject) ||
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/MemberValuePropagationTest.java b/src/test/java/com/android/tools/r8/ir/optimize/MemberValuePropagationTest.java
index f1a3c49..488b545 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/MemberValuePropagationTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/MemberValuePropagationTest.java
@@ -13,6 +13,7 @@
 import com.android.tools.r8.ToolHelper;
 import com.android.tools.r8.code.Const4;
 import com.android.tools.r8.code.InvokeDirect;
+import com.android.tools.r8.code.InvokeDirectRange;
 import com.android.tools.r8.code.IputObject;
 import com.android.tools.r8.code.NewInstance;
 import com.android.tools.r8.code.ReturnVoid;
@@ -46,26 +47,27 @@
     Path processedApp = runR8(EXAMPLE_KEEP);
     DexInspector inspector = new DexInspector(processedApp);
     ClassSubject clazz = inspector.clazz(WRITE_ONLY_FIELD + ".WriteOnlyCls");
-    clazz.forAllMethods(methodSubject -> {
-      if (methodSubject.isClassInitializer()) {
-        DexEncodedMethod encodedMethod = methodSubject.getMethod();
-        DexCode code = encodedMethod.getCode().asDexCode();
-        assertEquals(4, code.instructions.length);
-        assertTrue(code.instructions[0] instanceof NewInstance);
-        assertTrue(code.instructions[1] instanceof Const4);
-        assertTrue(code.instructions[2] instanceof InvokeDirect);
-        assertTrue(code.instructions[3] instanceof ReturnVoid);
-      }
-      if (methodSubject.isInstanceInitializer()) {
-        DexEncodedMethod encodedMethod = methodSubject.getMethod();
-        DexCode code = encodedMethod.getCode().asDexCode();
-        assertEquals(4, code.instructions.length);
-        assertTrue(code.instructions[0] instanceof InvokeDirect);
-        assertTrue(code.instructions[1] instanceof NewInstance);
-        assertTrue(code.instructions[2] instanceof InvokeDirect);
-        assertTrue(code.instructions[3] instanceof ReturnVoid);
-      }
-    });
+    clazz.forAllMethods(
+        methodSubject -> {
+          if (methodSubject.isClassInitializer()) {
+            DexEncodedMethod encodedMethod = methodSubject.getMethod();
+            DexCode code = encodedMethod.getCode().asDexCode();
+            assertEquals(4, code.instructions.length);
+            assertTrue(code.instructions[0] instanceof NewInstance);
+            assertTrue(code.instructions[1] instanceof Const4);
+            assertTrue(code.instructions[2] instanceof InvokeDirect);
+            assertTrue(code.instructions[3] instanceof ReturnVoid);
+          }
+          if (methodSubject.isInstanceInitializer()) {
+            DexEncodedMethod encodedMethod = methodSubject.getMethod();
+            DexCode code = encodedMethod.getCode().asDexCode();
+            assertEquals(4, code.instructions.length);
+            assertTrue(code.instructions[0] instanceof InvokeDirectRange);
+            assertTrue(code.instructions[1] instanceof NewInstance);
+            assertTrue(code.instructions[2] instanceof InvokeDirect);
+            assertTrue(code.instructions[3] instanceof ReturnVoid);
+          }
+        });
   }
 
   @Test
@@ -73,28 +75,29 @@
     Path processedApp = runR8(DONT_OPTIMIZE);
     DexInspector inspector = new DexInspector(processedApp);
     ClassSubject clazz = inspector.clazz(WRITE_ONLY_FIELD + ".WriteOnlyCls");
-    clazz.forAllMethods(methodSubject -> {
-      if (methodSubject.isClassInitializer()) {
-        DexEncodedMethod encodedMethod = methodSubject.getMethod();
-        DexCode code = encodedMethod.getCode().asDexCode();
-        assertEquals(5, code.instructions.length);
-        assertTrue(code.instructions[0] instanceof NewInstance);
-        assertTrue(code.instructions[1] instanceof Const4);
-        assertTrue(code.instructions[2] instanceof InvokeDirect);
-        assertTrue(code.instructions[3] instanceof SputObject);
-        assertTrue(code.instructions[4] instanceof ReturnVoid);
-      }
-      if (methodSubject.isInstanceInitializer()) {
-        DexEncodedMethod encodedMethod = methodSubject.getMethod();
-        DexCode code = encodedMethod.getCode().asDexCode();
-        assertEquals(5, code.instructions.length);
-        assertTrue(code.instructions[0] instanceof InvokeDirect);
-        assertTrue(code.instructions[1] instanceof NewInstance);
-        assertTrue(code.instructions[2] instanceof InvokeDirect);
-        assertTrue(code.instructions[3] instanceof IputObject);
-        assertTrue(code.instructions[4] instanceof ReturnVoid);
-      }
-    });
+    clazz.forAllMethods(
+        methodSubject -> {
+          if (methodSubject.isClassInitializer()) {
+            DexEncodedMethod encodedMethod = methodSubject.getMethod();
+            DexCode code = encodedMethod.getCode().asDexCode();
+            assertEquals(5, code.instructions.length);
+            assertTrue(code.instructions[0] instanceof NewInstance);
+            assertTrue(code.instructions[1] instanceof Const4);
+            assertTrue(code.instructions[2] instanceof InvokeDirect);
+            assertTrue(code.instructions[3] instanceof SputObject);
+            assertTrue(code.instructions[4] instanceof ReturnVoid);
+          }
+          if (methodSubject.isInstanceInitializer()) {
+            DexEncodedMethod encodedMethod = methodSubject.getMethod();
+            DexCode code = encodedMethod.getCode().asDexCode();
+            assertEquals(5, code.instructions.length);
+            assertTrue(code.instructions[0] instanceof InvokeDirectRange);
+            assertTrue(code.instructions[1] instanceof NewInstance);
+            assertTrue(code.instructions[2] instanceof InvokeDirect);
+            assertTrue(code.instructions[3] instanceof IputObject);
+            assertTrue(code.instructions[4] instanceof ReturnVoid);
+          }
+        });
   }
 
   private Path runR8(Path proguardConfig)
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/R8InliningTest.java b/src/test/java/com/android/tools/r8/ir/optimize/R8InliningTest.java
index 1c72986..45b99e3 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/R8InliningTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/R8InliningTest.java
@@ -18,7 +18,7 @@
 import com.android.tools.r8.code.IfEqz;
 import com.android.tools.r8.code.Iget;
 import com.android.tools.r8.code.Instruction;
-import com.android.tools.r8.code.InvokeVirtual;
+import com.android.tools.r8.code.InvokeVirtualRange;
 import com.android.tools.r8.code.MoveResult;
 import com.android.tools.r8.code.MulInt2Addr;
 import com.android.tools.r8.code.PackedSwitch;
@@ -179,23 +179,27 @@
     MethodSubject m = clazz.method("int", "inlinable", ImmutableList.of("inlining.A"));
     assertTrue(m.isPresent());
     DexCode code = m.getMethod().getCode().asDexCode();
-    checkInstructions(code, ImmutableList.of(
-        Iget.class,
-        // TODO(b/70572176): below two could be replaced with Iget via inlining
-        InvokeVirtual.class,
-        MoveResult.class,
-        AddInt2Addr.class,
-        Return.class));
+    checkInstructions(
+        code,
+        ImmutableList.of(
+            Iget.class,
+            // TODO(b/70572176): below two could be replaced with Iget via inlining
+            InvokeVirtualRange.class,
+            MoveResult.class,
+            AddInt2Addr.class,
+            Return.class));
 
     m = clazz.method("int", "notInlinable", ImmutableList.of("inlining.A"));
     assertTrue(m.isPresent());
     code = m.getMethod().getCode().asDexCode();
-    checkInstructions(code, ImmutableList.of(
-        InvokeVirtual.class,
-        MoveResult.class,
-        Iget.class,
-        AddInt2Addr.class,
-        Return.class));
+    checkInstructions(
+        code,
+        ImmutableList.of(
+            InvokeVirtualRange.class,
+            MoveResult.class,
+            Iget.class,
+            AddInt2Addr.class,
+            Return.class));
 
     m = clazz.method("int", "notInlinableDueToMissingNpe", ImmutableList.of("inlining.A"));
     assertTrue(m.isPresent());
@@ -210,13 +214,15 @@
     m = clazz.method("int", "notInlinableDueToSideEffect", ImmutableList.of("inlining.A"));
     assertTrue(m.isPresent());
     code = m.getMethod().getCode().asDexCode();
-    checkInstructions(code, ImmutableList.of(
-        IfEqz.class,
-        InvokeVirtual.class,
-        MoveResult.class,
-        Goto.class,
-        Iget.class,
-        Return.class));
+    checkInstructions(
+        code,
+        ImmutableList.of(
+            IfEqz.class,
+            InvokeVirtualRange.class,
+            MoveResult.class,
+            Goto.class,
+            Iget.class,
+            Return.class));
 
     m = clazz.method("int", "notInlinableOnThrow", ImmutableList.of("java.lang.Throwable"));
     assertTrue(m.isPresent());
@@ -241,15 +247,17 @@
     MethodSubject m = clazz.method("int", "conditionalOperator", ImmutableList.of("inlining.A"));
     assertTrue(m.isPresent());
     DexCode code = m.getMethod().getCode().asDexCode();
-    checkInstructions(code, ImmutableList.of(
-        IfEqz.class,
-        // TODO(b/70794661): below two could be replaced with Iget via inlining if access
-        // modification is allowed.
-        InvokeVirtual.class,
-        MoveResult.class,
-        Goto.class,
-        Const4.class,
-        Return.class));
+    checkInstructions(
+        code,
+        ImmutableList.of(
+            IfEqz.class,
+            // TODO(b/70794661): below two could be replaced with Iget via inlining if access
+            // modification is allowed.
+            InvokeVirtualRange.class,
+            MoveResult.class,
+            Goto.class,
+            Const4.class,
+            Return.class));
 
     m = clazz.method("int", "moreControlFlows",
         ImmutableList.of("inlining.A", "inlining.Nullability$Factor"));
@@ -257,7 +265,7 @@
     code = m.getMethod().getCode().asDexCode();
     ImmutableList.Builder<Class<? extends Instruction>> builder = ImmutableList.builder();
     // Enum#ordinal
-    builder.add(InvokeVirtual.class);
+    builder.add(InvokeVirtualRange.class);
     builder.add(MoveResult.class);
     builder.add(PackedSwitch.class);
     for (int i = 0; i < 4; ++i) {
@@ -268,7 +276,7 @@
     builder.add(IfEqz.class);
     builder.add(IfEqz.class);
     // TODO(b/70794661): below two could be replaced with Iget via inlining
-    builder.add(InvokeVirtual.class);
+    builder.add(InvokeVirtualRange.class);
     builder.add(MoveResult.class);
     builder.add(MulInt2Addr.class);
     builder.add(Return.class);
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 b0e1131..f86d6e0 100644
--- a/src/test/java/com/android/tools/r8/naming/IdentifierNameStringMarkerTest.java
+++ b/src/test/java/com/android/tools/r8/naming/IdentifierNameStringMarkerTest.java
@@ -12,7 +12,7 @@
 import com.android.tools.r8.code.Const4;
 import com.android.tools.r8.code.ConstClass;
 import com.android.tools.r8.code.ConstString;
-import com.android.tools.r8.code.InvokeDirect;
+import com.android.tools.r8.code.InvokeDirectRange;
 import com.android.tools.r8.code.InvokeStatic;
 import com.android.tools.r8.code.InvokeVirtual;
 import com.android.tools.r8.code.IputObject;
@@ -60,11 +60,10 @@
     assertNotNull(method);
 
     DexCode code = method.getCode().asDexCode();
-    checkInstructions(code, ImmutableList.of(
-        InvokeDirect.class,
-        ConstString.class,
-        IputObject.class,
-        ReturnVoid.class));
+    checkInstructions(
+        code,
+        ImmutableList.of(
+            InvokeDirectRange.class, ConstString.class, IputObject.class, ReturnVoid.class));
     ConstString constString = (ConstString) code.instructions[1];
     assertEquals(BOO, constString.getString().toString());
   }
@@ -93,14 +92,16 @@
     assertNotNull(method);
 
     DexCode code = method.getCode().asDexCode();
-    checkInstructions(code, ImmutableList.of(
-        InvokeDirect.class,
-        SgetObject.class,
-        ConstString.class,
-        InvokeVirtual.class,
-        ConstString.class,
-        IputObject.class,
-        ReturnVoid.class));
+    checkInstructions(
+        code,
+        ImmutableList.of(
+            InvokeDirectRange.class,
+            SgetObject.class,
+            ConstString.class,
+            InvokeVirtual.class,
+            ConstString.class,
+            IputObject.class,
+            ReturnVoid.class));
     ConstString constString = (ConstString) code.instructions[2];
     assertEquals(BOO, constString.getString().toString());
     constString = (ConstString) code.instructions[4];
@@ -133,14 +134,16 @@
     assertNotNull(method);
 
     DexCode code = method.getCode().asDexCode();
-    checkInstructions(code, ImmutableList.of(
-        InvokeDirect.class,
-        SgetObject.class,
-        ConstString.class,
-        InvokeVirtual.class,
-        ConstString.class,
-        IputObject.class,
-        ReturnVoid.class));
+    checkInstructions(
+        code,
+        ImmutableList.of(
+            InvokeDirectRange.class,
+            SgetObject.class,
+            ConstString.class,
+            InvokeVirtual.class,
+            ConstString.class,
+            IputObject.class,
+            ReturnVoid.class));
     ConstString constString = (ConstString) code.instructions[2];
     assertEquals(BOO, constString.getString().toString());
     constString = (ConstString) code.instructions[4];
@@ -367,12 +370,14 @@
     assertNotNull(method);
 
     DexCode code = method.getCode().asDexCode();
-    checkInstructions(code, ImmutableList.of(
-        InvokeDirect.class,
-        ConstString.class,
-        ConstString.class,
-        InvokeStatic.class,
-        ReturnVoid.class));
+    checkInstructions(
+        code,
+        ImmutableList.of(
+            InvokeDirectRange.class,
+            ConstString.class,
+            ConstString.class,
+            InvokeStatic.class,
+            ReturnVoid.class));
     ConstString constString = (ConstString) code.instructions[1];
     assertEquals("Mixed/form.Boo", constString.getString().toString());
     constString = (ConstString) code.instructions[2];
@@ -407,14 +412,16 @@
     assertNotNull(method);
 
     DexCode code = method.getCode().asDexCode();
-    checkInstructions(code, ImmutableList.of(
-        InvokeDirect.class,
-        SgetObject.class,
-        ConstString.class,
-        InvokeVirtual.class,
-        ConstString.class,
-        InvokeStatic.class,
-        ReturnVoid.class));
+    checkInstructions(
+        code,
+        ImmutableList.of(
+            InvokeDirectRange.class,
+            SgetObject.class,
+            ConstString.class,
+            InvokeVirtual.class,
+            ConstString.class,
+            InvokeStatic.class,
+            ReturnVoid.class));
     ConstString constString = (ConstString) code.instructions[2];
     assertEquals(BOO, constString.getString().toString());
     constString = (ConstString) code.instructions[4];
@@ -451,14 +458,16 @@
     assertNotNull(method);
 
     DexCode code = method.getCode().asDexCode();
-    checkInstructions(code, ImmutableList.of(
-        InvokeDirect.class,
-        SgetObject.class,
-        ConstString.class,
-        InvokeVirtual.class,
-        ConstString.class,
-        InvokeStatic.class,
-        ReturnVoid.class));
+    checkInstructions(
+        code,
+        ImmutableList.of(
+            InvokeDirectRange.class,
+            SgetObject.class,
+            ConstString.class,
+            InvokeVirtual.class,
+            ConstString.class,
+            InvokeStatic.class,
+            ReturnVoid.class));
     ConstString constString = (ConstString) code.instructions[2];
     assertEquals(BOO, constString.getString().toString());
     constString = (ConstString) code.instructions[4];
@@ -503,12 +512,14 @@
     assertNotNull(method);
 
     DexCode code = method.getCode().asDexCode();
-    checkInstructions(code, ImmutableList.of(
-        InvokeDirect.class,
-        ConstClass.class,
-        ConstString.class,
-        InvokeStatic.class,
-        ReturnVoid.class));
+    checkInstructions(
+        code,
+        ImmutableList.of(
+            InvokeDirectRange.class,
+            ConstClass.class,
+            ConstString.class,
+            InvokeStatic.class,
+            ReturnVoid.class));
     ConstString constString = (ConstString) code.instructions[2];
     assertEquals("foo", constString.getString().toString());
   }
@@ -551,12 +562,14 @@
     assertNotNull(method);
 
     DexCode code = method.getCode().asDexCode();
-    checkInstructions(code, ImmutableList.of(
-        InvokeDirect.class,
-        ConstClass.class,
-        ConstString.class,
-        InvokeStatic.class,
-        ReturnVoid.class));
+    checkInstructions(
+        code,
+        ImmutableList.of(
+            InvokeDirectRange.class,
+            ConstClass.class,
+            ConstString.class,
+            InvokeStatic.class,
+            ReturnVoid.class));
     ConstString constString = (ConstString) code.instructions[2];
     assertNotEquals("foo", constString.getString().toString());
   }
@@ -606,16 +619,18 @@
     assertNotNull(method);
 
     DexCode code = method.getCode().asDexCode();
-    checkInstructions(code, ImmutableList.of(
-        InvokeDirect.class,
-        ConstClass.class,
-        Const4.class,
-        NewArray.class,
-        Const4.class,
-        AputObject.class,
-        ConstString.class,
-        InvokeStatic.class,
-        ReturnVoid.class));
+    checkInstructions(
+        code,
+        ImmutableList.of(
+            InvokeDirectRange.class,
+            ConstClass.class,
+            Const4.class,
+            NewArray.class,
+            Const4.class,
+            AputObject.class,
+            ConstString.class,
+            InvokeStatic.class,
+            ReturnVoid.class));
     ConstString constString = (ConstString) code.instructions[6];
     assertEquals("foo", constString.getString().toString());
   }
@@ -665,16 +680,18 @@
     assertNotNull(method);
 
     DexCode code = method.getCode().asDexCode();
-    checkInstructions(code, ImmutableList.of(
-        InvokeDirect.class,
-        ConstClass.class,
-        Const4.class,
-        NewArray.class,
-        Const4.class,
-        AputObject.class,
-        ConstString.class,
-        InvokeStatic.class,
-        ReturnVoid.class));
+    checkInstructions(
+        code,
+        ImmutableList.of(
+            InvokeDirectRange.class,
+            ConstClass.class,
+            Const4.class,
+            NewArray.class,
+            Const4.class,
+            AputObject.class,
+            ConstString.class,
+            InvokeStatic.class,
+            ReturnVoid.class));
     ConstString constString = (ConstString) code.instructions[6];
     assertNotEquals("foo", constString.getString().toString());
   }
diff --git a/src/test/java/com/android/tools/r8/shaking/proxy/ProxiesTest.java b/src/test/java/com/android/tools/r8/shaking/proxy/ProxiesTest.java
index 8e39b67..6c0bfe7 100644
--- a/src/test/java/com/android/tools/r8/shaking/proxy/ProxiesTest.java
+++ b/src/test/java/com/android/tools/r8/shaking/proxy/ProxiesTest.java
@@ -11,8 +11,8 @@
 import com.android.tools.r8.TestBase;
 import com.android.tools.r8.ToolHelper;
 import com.android.tools.r8.code.Instruction;
-import com.android.tools.r8.code.InvokeInterface;
-import com.android.tools.r8.code.InvokeVirtual;
+import com.android.tools.r8.code.InvokeInterfaceRange;
+import com.android.tools.r8.code.InvokeVirtualRange;
 import com.android.tools.r8.graph.DexCode;
 import com.android.tools.r8.graph.invokesuper.Consumer;
 import com.android.tools.r8.naming.MemberNaming.MethodSignature;
@@ -92,9 +92,9 @@
 
   private void noInterfaceKept(DexInspector inspector) {
     // Indirectly assert that method is inlined into x, y and z.
-    assertEquals(1, countInstructionInX(inspector, InvokeInterface.class));
-    assertEquals(1, countInstructionInY(inspector, InvokeInterface.class));
-    assertEquals(1, countInstructionInZ(inspector, InvokeVirtual.class));
+    assertEquals(1, countInstructionInX(inspector, InvokeInterfaceRange.class));
+    assertEquals(1, countInstructionInY(inspector, InvokeInterfaceRange.class));
+    assertEquals(1, countInstructionInZ(inspector, InvokeVirtualRange.class));
   }
 
   @Test
@@ -106,11 +106,11 @@
 
   private void baseInterfaceKept(DexInspector inspector) {
     // Indirectly assert that method is not inlined into x.
-    assertEquals(3, countInstructionInX(inspector, InvokeInterface.class));
+    assertEquals(3, countInstructionInX(inspector, InvokeInterfaceRange.class));
     // Indirectly assert that method is inlined into y and z.
-    assertEquals(1, countInstructionInY(inspector, InvokeInterface.class));
-    assertEquals(1, countInstructionInZ(inspector, InvokeVirtual.class));
-    assertEquals(1, countInstructionInZSubClass(inspector, InvokeVirtual.class));
+    assertEquals(1, countInstructionInY(inspector, InvokeInterfaceRange.class));
+    assertEquals(1, countInstructionInZ(inspector, InvokeVirtualRange.class));
+    assertEquals(1, countInstructionInZSubClass(inspector, InvokeVirtualRange.class));
   }
 
   @Test
@@ -126,11 +126,11 @@
 
   private void subInterfaceKept(DexInspector inspector) {
     // Indirectly assert that method is not inlined into x or y.
-    assertEquals(3, countInstructionInX(inspector, InvokeInterface.class));
-    assertEquals(3, countInstructionInY(inspector, InvokeInterface.class));
+    assertEquals(3, countInstructionInX(inspector, InvokeInterfaceRange.class));
+    assertEquals(3, countInstructionInY(inspector, InvokeInterfaceRange.class));
     // Indirectly assert that method is inlined into z.
-    assertEquals(1, countInstructionInZ(inspector, InvokeVirtual.class));
-    assertEquals(1, countInstructionInZSubClass(inspector, InvokeVirtual.class));
+    assertEquals(1, countInstructionInZ(inspector, InvokeVirtualRange.class));
+    assertEquals(1, countInstructionInZSubClass(inspector, InvokeVirtualRange.class));
   }
 
   @Test
@@ -148,10 +148,10 @@
 
   private void classKept(DexInspector inspector) {
     // Indirectly assert that method is not inlined into x, y or z.
-    assertEquals(3, countInstructionInX(inspector, InvokeInterface.class));
-    assertEquals(3, countInstructionInY(inspector, InvokeInterface.class));
-    assertEquals(3, countInstructionInZ(inspector, InvokeVirtual.class));
-    assertEquals(3, countInstructionInZSubClass(inspector, InvokeVirtual.class));
+    assertEquals(3, countInstructionInX(inspector, InvokeInterfaceRange.class));
+    assertEquals(3, countInstructionInY(inspector, InvokeInterfaceRange.class));
+    assertEquals(3, countInstructionInZ(inspector, InvokeVirtualRange.class));
+    assertEquals(3, countInstructionInZSubClass(inspector, InvokeVirtualRange.class));
   }
 
   @Test
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 162db06..f8aae30 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.code.IfLez;
 import com.android.tools.r8.code.IfLtz;
 import com.android.tools.r8.code.IfNez;
-import com.android.tools.r8.code.InvokeVirtual;
+import com.android.tools.r8.code.InvokeVirtualRange;
 import com.android.tools.r8.code.Return;
 import com.android.tools.r8.code.ReturnObject;
 import com.android.tools.r8.graph.DexCode;
@@ -391,7 +391,7 @@
     );
     DexCode code = method.getCode().asDexCode();
     assertEquals(3, code.instructions.length);
-    assertTrue(code.instructions[0] instanceof InvokeVirtual);
+    assertTrue(code.instructions[0] instanceof InvokeVirtualRange);
     assertTrue(code.instructions[1] instanceof Const4);
     assertEquals(0, ((Const4) code.instructions[1]).B);
     assertTrue(code.instructions[2] instanceof ReturnObject);
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 5088aeb..9f75c9c 100644
--- a/src/test/java/com/android/tools/r8/smali/OutlineTest.java
+++ b/src/test/java/com/android/tools/r8/smali/OutlineTest.java
@@ -15,7 +15,9 @@
 import com.android.tools.r8.code.DivInt2Addr;
 import com.android.tools.r8.code.Goto;
 import com.android.tools.r8.code.InvokeStatic;
+import com.android.tools.r8.code.InvokeStaticRange;
 import com.android.tools.r8.code.InvokeVirtual;
+import com.android.tools.r8.code.InvokeVirtualRange;
 import com.android.tools.r8.code.MoveResult;
 import com.android.tools.r8.code.MoveResultWide;
 import com.android.tools.r8.code.Return;
@@ -844,7 +846,7 @@
     List<DexType> r = new ArrayList<>();
     for (int i = 0; i < clazz.getDexClass().directMethods().length; i++) {
       if (clazz.getDexClass().directMethods()[i].getCode().asDexCode().instructions[0]
-          instanceof InvokeVirtual) {
+          instanceof InvokeVirtualRange) {
         r.add(clazz.getDexClass().directMethods()[i].method.proto.returnType);
       }
     }
@@ -1090,9 +1092,9 @@
     DexEncodedMethod method = getMethod(processedApplication, signature);
     DexCode code = method.getCode().asDexCode();
     assertEquals(2, code.instructions.length);
-    assertTrue(code.instructions[0] instanceof InvokeStatic);
+    assertTrue(code.instructions[0] instanceof InvokeStaticRange);
     assertTrue(code.instructions[1] instanceof ReturnObject);
-    InvokeStatic invoke = (InvokeStatic) code.instructions[0];
+    InvokeStaticRange invoke = (InvokeStaticRange) code.instructions[0];
     assertEquals(firstOutlineMethodName(), invoke.getMethod().qualifiedName());
 
     // Run code and check result.
@@ -1294,9 +1296,9 @@
     DexEncodedMethod method = getMethod(processedApplication, signature);
     DexCode code = method.getCode().asDexCode();
     assertEquals(2, code.instructions.length);
-    assertTrue(code.instructions[0] instanceof InvokeStatic);
+    assertTrue(code.instructions[0] instanceof InvokeStaticRange);
     assertTrue(code.instructions[1] instanceof ReturnVoid);
-    InvokeStatic invoke = (InvokeStatic) code.instructions[0];
+    InvokeStaticRange invoke = (InvokeStaticRange) code.instructions[0];
     assertEquals(firstOutlineMethodName(), invoke.getMethod().qualifiedName());
 
     // Run code and check result.