aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/main/java/com/android/tools/r8/ir/regalloc/LinearScanRegisterAllocator.java32
-rw-r--r--src/main/java/com/android/tools/r8/ir/regalloc/LiveIntervals.java28
-rw-r--r--src/main/java/com/android/tools/r8/ir/regalloc/LiveIntervalsUse.java6
3 files changed, 50 insertions, 16 deletions
diff --git a/src/main/java/com/android/tools/r8/ir/regalloc/LinearScanRegisterAllocator.java b/src/main/java/com/android/tools/r8/ir/regalloc/LinearScanRegisterAllocator.java
index 33dc79a97..a30f57440 100644
--- a/src/main/java/com/android/tools/r8/ir/regalloc/LinearScanRegisterAllocator.java
+++ b/src/main/java/com/android/tools/r8/ir/regalloc/LinearScanRegisterAllocator.java
@@ -567,18 +567,18 @@ public class LinearScanRegisterAllocator implements RegisterAllocator {
active.add(argumentInterval);
} else {
// Treat the argument interval as spilled which will require a load to a different
- // register for all usages.
+ // register for all register-constrained usages.
if (argumentInterval.getUses().size() > 1) {
LiveIntervalsUse use = argumentInterval.firstUseWithConstraint();
if (use != null) {
LiveIntervals split;
- if (argumentInterval.getUses().size() == 2) {
- // If there is only one real use (definition plus one real use), split before
+ if (argumentInterval.numberOfUsesWithConstraint() == 1) {
+ // If there is only one register-constrained use, split before
// that one use.
split = argumentInterval.splitBefore(use.getPosition());
} else {
- // If there are multiple real users, split right after the definition to make it
- // more likely that arguments get in usable registers from the start.
+ // If there are multiple register-constrained users, split right after the definition
+ // to make it more likely that arguments get in usable registers from the start.
split = argumentInterval
.splitBefore(argumentInterval.getValue().definition.getNumber() + 1);
}
@@ -1004,7 +1004,24 @@ public class LinearScanRegisterAllocator implements RegisterAllocator {
// argument reuse disallowed.
return false;
}
- allocateBlockedRegister(unhandledInterval);
+ // If the first use for these intervals is unconstrained, just spill this interval instead
+ // of finding another candidate to spill via allocateBlockedRegister.
+ if (!unhandledInterval.getUses().first().hasConstraint()) {
+ int nextConstrainedPosition = unhandledInterval.firstUseWithConstraint().getPosition();
+ int register;
+ // Arguments are always in the argument registers, so for arguments just use that register
+ // for the unconstrained prefix. For everything else, get a spill register.
+ if (unhandledInterval.isArgumentInterval()) {
+ register = unhandledInterval.getSplitParent().getRegister();
+ } else {
+ register = getSpillRegister(unhandledInterval);
+ }
+ LiveIntervals split = unhandledInterval.splitBefore(nextConstrainedPosition);
+ assignRegisterToUnhandledInterval(unhandledInterval, needsRegisterPair, register);
+ unhandled.add(split);
+ } else {
+ allocateBlockedRegister(unhandledInterval);
+ }
} else if (largestFreePosition >= unhandledInterval.getEnd()) {
// Free for the entire interval. Allocate the register.
assignRegisterToUnhandledInterval(unhandledInterval, needsRegisterPair, candidate);
@@ -1016,8 +1033,7 @@ public class LinearScanRegisterAllocator implements RegisterAllocator {
}
// The candidate is free for the beginning of an interval. We split the interval
// and use the register for as long as we can.
- int splitPosition = largestFreePosition;
- LiveIntervals split = unhandledInterval.splitBefore(splitPosition);
+ LiveIntervals split = unhandledInterval.splitBefore(largestFreePosition);
assert split != unhandledInterval;
assignRegisterToUnhandledInterval(unhandledInterval, needsRegisterPair, candidate);
unhandled.add(split);
diff --git a/src/main/java/com/android/tools/r8/ir/regalloc/LiveIntervals.java b/src/main/java/com/android/tools/r8/ir/regalloc/LiveIntervals.java
index cf44137fd..f01ed3adf 100644
--- a/src/main/java/com/android/tools/r8/ir/regalloc/LiveIntervals.java
+++ b/src/main/java/com/android/tools/r8/ir/regalloc/LiveIntervals.java
@@ -3,6 +3,7 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.ir.regalloc;
+import static com.android.tools.r8.dex.Constants.U16BIT_MAX;
import static com.android.tools.r8.ir.regalloc.LinearScanRegisterAllocator.NO_REGISTER;
import com.android.tools.r8.dex.Constants;
@@ -29,7 +30,7 @@ public class LiveIntervals {
private boolean spilled = false;
// Only registers up to and including the registerLimit are allowed for this interval.
- private int registerLimit = Constants.U16BIT_MAX;
+ private int registerLimit = U16BIT_MAX;
// Max register used for any of the non-spilled splits for these live intervals or for any of the
// live intervals that this live interval is connected to by phi moves. This is used to
@@ -331,7 +332,7 @@ public class LiveIntervals {
public LiveIntervalsUse firstUseWithConstraint() {
for (LiveIntervalsUse use : uses) {
- if (use.getLimit() < Constants.U16BIT_MAX) {
+ if (use.hasConstraint()) {
return use;
}
}
@@ -386,13 +387,14 @@ public class LiveIntervals {
}
private void recomputeLimit() {
- registerLimit = Constants.U16BIT_MAX;
+ registerLimit = U16BIT_MAX;
for (LiveIntervalsUse use : uses) {
updateRegisterConstraint(use.getLimit());
}
}
public LiveIntervals getSplitCovering(int instructionNumber) {
+ assert getSplitParent() == this;
// Check if this interval itself is covering the instruction.
if (getStart() <= instructionNumber && getEnd() > instructionNumber) {
return this;
@@ -417,6 +419,20 @@ public class LiveIntervals {
return null;
}
+ public boolean isConstantNumberInterval() {
+ return value.definition != null && value.definition.isConstNumber();
+ }
+
+ public int numberOfUsesWithConstraint() {
+ int count = 0;
+ for (LiveIntervalsUse use : getUses()) {
+ if (use.hasConstraint()) {
+ count++;
+ }
+ }
+ return count;
+ }
+
@Override
public String toString() {
StringBuilder builder = new StringBuilder();
@@ -468,8 +484,4 @@ public class LiveIntervals {
splitChild.print(printer, number + delta, number);
}
}
-
- public boolean isConstantNumberInterval() {
- return value.definition != null && value.definition.isConstNumber();
- }
-} \ No newline at end of file
+}
diff --git a/src/main/java/com/android/tools/r8/ir/regalloc/LiveIntervalsUse.java b/src/main/java/com/android/tools/r8/ir/regalloc/LiveIntervalsUse.java
index fd37af8f3..a60213453 100644
--- a/src/main/java/com/android/tools/r8/ir/regalloc/LiveIntervalsUse.java
+++ b/src/main/java/com/android/tools/r8/ir/regalloc/LiveIntervalsUse.java
@@ -3,6 +3,8 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.ir.regalloc;
+import static com.android.tools.r8.dex.Constants.U16BIT_MAX;
+
public class LiveIntervalsUse implements Comparable<LiveIntervalsUse> {
private int position;
private int limit;
@@ -41,4 +43,8 @@ public class LiveIntervalsUse implements Comparable<LiveIntervalsUse> {
}
return limit - o.limit;
}
+
+ public boolean hasConstraint() {
+ return limit < U16BIT_MAX;
+ }
}