Add a test for using invoke-range for consecutive arguments
Bug: b/375147913
Change-Id: Ia2033940224ddb3e6ddbf2ebfac05881b754d260
diff --git a/src/test/java/com/android/tools/r8/ir/regalloc/InvokeRangeForConsecutiveArgumentsTest.java b/src/test/java/com/android/tools/r8/ir/regalloc/InvokeRangeForConsecutiveArgumentsTest.java
new file mode 100644
index 0000000..642eb7e
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/ir/regalloc/InvokeRangeForConsecutiveArgumentsTest.java
@@ -0,0 +1,65 @@
+// Copyright (c) 2024, 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.ir.regalloc;
+
+import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.Assert.assertTrue;
+
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.utils.codeinspector.InstructionSubject;
+import com.android.tools.r8.utils.codeinspector.MethodSubject;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameter;
+import org.junit.runners.Parameterized.Parameters;
+
+@RunWith(Parameterized.class)
+public class InvokeRangeForConsecutiveArgumentsTest extends TestBase {
+
+ @Parameter(0)
+ public TestParameters parameters;
+
+ @Parameters(name = "{0}")
+ public static TestParametersCollection data() {
+ return getTestParameters().withDefaultDexRuntime().withMaximumApiLevel().build();
+ }
+
+ @Test
+ public void testD8() throws Exception {
+ testForD8()
+ .addInnerClasses(getClass())
+ .addOptionsModification(
+ options -> options.getTestingOptions().enableRegisterAllocation8BitRefinement = true)
+ .release()
+ .setMinApi(parameters)
+ .compile()
+ .inspect(
+ inspector -> {
+ MethodSubject testMethodSubject =
+ inspector.clazz(Main.class).uniqueMethodWithOriginalName("test");
+ assertThat(testMethodSubject, isPresent());
+ assertTrue(
+ testMethodSubject
+ .streamInstructions()
+ .filter(InstructionSubject::isInvokeMethod)
+ .allMatch(InstructionSubject::isInvokeRange));
+ assertTrue(
+ testMethodSubject.streamInstructions().noneMatch(InstructionSubject::isMove));
+ });
+ }
+
+ static class Main {
+
+ void test(long a, long b, long c, long d, long e, long f, long g, long h) {
+ test(a, b, c, d, e, f, g, h);
+ testPartial(g, h);
+ }
+
+ static void testPartial(long a, long b) {}
+ }
+}
diff --git a/src/test/testbase/java/com/android/tools/r8/utils/codeinspector/CfInstructionSubject.java b/src/test/testbase/java/com/android/tools/r8/utils/codeinspector/CfInstructionSubject.java
index 6cc23c2..aa3e569 100644
--- a/src/test/testbase/java/com/android/tools/r8/utils/codeinspector/CfInstructionSubject.java
+++ b/src/test/testbase/java/com/android/tools/r8/utils/codeinspector/CfInstructionSubject.java
@@ -140,6 +140,11 @@
}
@Override
+ public boolean isInvokeRange() {
+ return false;
+ }
+
+ @Override
public boolean isPop() {
return instruction instanceof CfStackInstruction
&& ((CfStackInstruction) instruction).getOpcode() == Opcode.Pop;
diff --git a/src/test/testbase/java/com/android/tools/r8/utils/codeinspector/DexInstructionSubject.java b/src/test/testbase/java/com/android/tools/r8/utils/codeinspector/DexInstructionSubject.java
index 8c1d4a2..aec79c9 100644
--- a/src/test/testbase/java/com/android/tools/r8/utils/codeinspector/DexInstructionSubject.java
+++ b/src/test/testbase/java/com/android/tools/r8/utils/codeinspector/DexInstructionSubject.java
@@ -80,6 +80,7 @@
import com.android.tools.r8.dex.code.DexInvokeDirectRange;
import com.android.tools.r8.dex.code.DexInvokeInterface;
import com.android.tools.r8.dex.code.DexInvokeInterfaceRange;
+import com.android.tools.r8.dex.code.DexInvokePolymorphicRange;
import com.android.tools.r8.dex.code.DexInvokeStatic;
import com.android.tools.r8.dex.code.DexInvokeStaticRange;
import com.android.tools.r8.dex.code.DexInvokeSuper;
@@ -317,6 +318,17 @@
}
@Override
+ public boolean isInvokeRange() {
+ return instruction instanceof DexInvokeCustomRange
+ || instruction instanceof DexInvokeDirectRange
+ || instruction instanceof DexInvokeInterfaceRange
+ || instruction instanceof DexInvokeStaticRange
+ || instruction instanceof DexInvokeSuperRange
+ || instruction instanceof DexInvokeVirtualRange
+ || instruction instanceof DexInvokePolymorphicRange;
+ }
+
+ @Override
public DexMethod getMethod() {
assert isInvoke();
return instruction.getMethod();
diff --git a/src/test/testbase/java/com/android/tools/r8/utils/codeinspector/InstructionSubject.java b/src/test/testbase/java/com/android/tools/r8/utils/codeinspector/InstructionSubject.java
index b23719d..82b9263 100644
--- a/src/test/testbase/java/com/android/tools/r8/utils/codeinspector/InstructionSubject.java
+++ b/src/test/testbase/java/com/android/tools/r8/utils/codeinspector/InstructionSubject.java
@@ -51,6 +51,8 @@
boolean isInvokeDynamic();
+ boolean isInvokeRange();
+
default boolean isInvokeSpecialOrDirect() {
if (isCfInstruction()) {
return asCfInstruction().isInvokeSpecial();