Use ranged invokes when out args are in args in high registers.
This allows us to use high registers for all invokes that are just
passing along incoming arguments in the right order. Using
ranged invokes we do not have to move the incoming arguments to
low registers for the call.
This saves 38kB on debug mode dexing of gmscore v10 deploy jar.
R=mikaelpeltier@google.com
Change-Id: I0c53c451636a57c7b78c58f67babe2200fb1568c
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 87edec8..14104d7 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
@@ -91,7 +91,7 @@
}
protected int argumentRegisterValue(int i, DexBuilder builder) {
- assert requiredArgumentRegisters() > 5;
+ assert needsRangedInvoke(builder);
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
@@ -168,9 +168,45 @@
if (requiredArgumentRegisters() > 5) {
return Constants.U16BIT_MAX;
}
+ if (argumentsAreConsecutiveInputArguments()) {
+ return Constants.U16BIT_MAX;
+ }
return Constants.U4BIT_MAX;
}
+ private boolean argumentsAreConsecutiveInputArguments() {
+ if (arguments().size() == 0) {
+ return false;
+ }
+ Value current = arguments().get(0);
+ if (!current.isArgument()) {
+ return false;
+ }
+ for (int i = 1; i < arguments().size(); i++) {
+ Value next = arguments().get(i);
+ if (current.getNextConsecutive() != next) {
+ return false;
+ }
+ current = next;
+ }
+ 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);
+ }
+
@Override
public int maxOutValueRegister() {
return Constants.U8BIT_MAX;
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 2c7ea4b..d0d0739 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
@@ -50,7 +50,7 @@
com.android.tools.r8.code.Instruction instruction;
int argumentRegisters = requiredArgumentRegisters();
builder.requestOutgoingRegisters(argumentRegisters);
- if (argumentRegisters > 5 || hasHighArgumentRegister(builder)) {
+ if (needsRangedInvoke(builder)) {
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 95776f4..f11d62f 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
@@ -39,7 +39,7 @@
com.android.tools.r8.code.Instruction instruction;
int argumentRegisters = requiredArgumentRegisters();
builder.requestOutgoingRegisters(argumentRegisters);
- if (argumentRegisters > 5 || hasHighArgumentRegister(builder)) {
+ if (needsRangedInvoke(builder)) {
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 f1c1d65..9d0c01f 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
@@ -38,7 +38,7 @@
com.android.tools.r8.code.Instruction instruction;
int argumentRegisters = requiredArgumentRegisters();
builder.requestOutgoingRegisters(argumentRegisters);
- if (argumentRegisters > 5 || hasHighArgumentRegister(builder)) {
+ if (needsRangedInvoke(builder)) {
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 0725fed..2912c1a 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
@@ -49,7 +49,7 @@
com.android.tools.r8.code.Instruction instruction;
int argumentRegisters = requiredArgumentRegisters();
builder.requestOutgoingRegisters(argumentRegisters);
- if (argumentRegisters > 5 || hasHighArgumentRegister(builder)) {
+ if (needsRangedInvoke(builder)) {
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 9c87144..efc12db 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
@@ -47,7 +47,7 @@
com.android.tools.r8.code.Instruction instruction;
int argumentRegisters = requiredArgumentRegisters();
builder.requestOutgoingRegisters(argumentRegisters);
- if (argumentRegisters > 5 || hasHighArgumentRegister(builder)) {
+ if (needsRangedInvoke(builder)) {
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 0c4fe14..dc22e2e 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
@@ -38,7 +38,7 @@
com.android.tools.r8.code.Instruction instruction;
int argumentRegisters = requiredArgumentRegisters();
builder.requestOutgoingRegisters(argumentRegisters);
- if (argumentRegisters > 5 || hasHighArgumentRegister(builder)) {
+ if (needsRangedInvoke(builder)) {
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 2e1e3e7..fc79c11 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
@@ -38,7 +38,7 @@
com.android.tools.r8.code.Instruction instruction;
int argumentRegisters = requiredArgumentRegisters();
builder.requestOutgoingRegisters(argumentRegisters);
- if (argumentRegisters > 5 || hasHighArgumentRegister(builder)) {
+ if (needsRangedInvoke(builder)) {
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 339ae71..3988980 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
@@ -38,7 +38,7 @@
com.android.tools.r8.code.Instruction instruction;
int argumentRegisters = requiredArgumentRegisters();
builder.requestOutgoingRegisters(argumentRegisters);
- if (argumentRegisters > 5 || hasHighArgumentRegister(builder)) {
+ if (needsRangedInvoke(builder)) {
assert argumentsConsecutive(builder);
int firstRegister = argumentRegisterValue(0, builder);
instruction = new InvokeVirtualRange(firstRegister, argumentRegisters, getInvokedMethod());