Close locals clobbered by spill instructions.
R=ager
Change-Id: I1458a66e1d0e2eb6f1ddb39649a51ac1fa9b7865
diff --git a/src/main/java/com/android/tools/r8/ir/code/DebugPosition.java b/src/main/java/com/android/tools/r8/ir/code/DebugPosition.java
index ee6b65f..7a5acc5 100644
--- a/src/main/java/com/android/tools/r8/ir/code/DebugPosition.java
+++ b/src/main/java/com/android/tools/r8/ir/code/DebugPosition.java
@@ -64,10 +64,14 @@
@Override
public String toString() {
StringBuilder builder = new StringBuilder(super.toString());
+ printLineInfo(builder);
+ return builder.toString();
+ }
+
+ public void printLineInfo(StringBuilder builder) {
if (file != null) {
builder.append(file).append(":");
}
builder.append(line);
- return builder.toString();
}
}
diff --git a/src/main/java/com/android/tools/r8/ir/code/MoveException.java b/src/main/java/com/android/tools/r8/ir/code/MoveException.java
index 554e71f..023e6f0 100644
--- a/src/main/java/com/android/tools/r8/ir/code/MoveException.java
+++ b/src/main/java/com/android/tools/r8/ir/code/MoveException.java
@@ -70,4 +70,16 @@
public boolean canBeDeadCode(IRCode code, InternalOptions options) {
return !options.debug;
}
+
+ @Override
+ public String toString() {
+ if (position != null) {
+ StringBuilder builder = new StringBuilder(super.toString());
+ builder.append("(DebugPosition ");
+ position.printLineInfo(builder);
+ builder.append(')');
+ return builder.toString();
+ }
+ return super.toString();
+ }
}
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 398c87e..2e4a434 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
@@ -318,13 +318,21 @@
nextStartingRange = rangeIterator.hasNext() ? rangeIterator.next() : null;
}
if (block.entry().isMoveException()) {
- fixupSpillMovesAtMoveException(block, instructionIterator, openRanges, currentLocals);
+ fixupLocalsLiveAtMoveException(block, instructionIterator, openRanges, currentLocals);
} else {
block.setLocalsAtEntry(new Int2ReferenceOpenHashMap<>(currentLocals));
}
+ int spillCount = 0;
while (instructionIterator.hasNext()) {
Instruction instruction = instructionIterator.next();
int index = instruction.getNumber();
+ if (index == -1) {
+ spillCount++;
+ continue;
+ }
+ // If there is more than one spill instruction we may need to end clobbered locals.
+ Int2ReferenceMap<DebugLocalInfo> preSpillLocals =
+ spillCount > 1 ? new Int2ReferenceOpenHashMap<>(currentLocals) : null;
ListIterator<LocalRange> it = openRanges.listIterator(0);
Int2ReferenceMap<DebugLocalInfo> ending = new Int2ReferenceOpenHashMap<>();
Int2ReferenceMap<DebugLocalInfo> starting = new Int2ReferenceOpenHashMap<>();
@@ -349,6 +357,18 @@
}
nextStartingRange = rangeIterator.hasNext() ? rangeIterator.next() : null;
}
+ if (preSpillLocals != null) {
+ for (int i = 0; i <= spillCount; i++) {
+ instructionIterator.previous();
+ }
+ Int2ReferenceMap<DebugLocalInfo> clobbered =
+ endClobberedLocals(instructionIterator, preSpillLocals, currentLocals);
+ for (Entry<DebugLocalInfo> entry : clobbered.int2ReferenceEntrySet()) {
+ assert ending.get(entry.getIntKey()) == entry.getValue();
+ ending.remove(entry.getIntKey());
+ }
+ }
+ spillCount = 0;
if (localsChanged && shouldEmitChangesAtInstruction(instruction)) {
DebugLocalsChange change = createLocalsChange(ending, starting);
if (change != null) {
@@ -366,7 +386,7 @@
}
}
- private void fixupSpillMovesAtMoveException(
+ private void fixupLocalsLiveAtMoveException(
BasicBlock block,
ListIterator<Instruction> instructionIterator,
List<LocalRange> openRanges,
@@ -381,42 +401,15 @@
Instruction entry = instructionIterator.next();
assert block.entry() == entry;
assert block.entry().isMoveException();
- Iterator<Instruction> moveIterator = block.iterator();
- moveIterator.next();
- int index = entry.getNumber();
- Int2ReferenceMap<DebugLocalInfo> clobberedLocals = new Int2ReferenceOpenHashMap<>();
- while (moveIterator.hasNext()) {
- Instruction next = moveIterator.next();
- if (next.getNumber() != -1) {
- break;
- }
- if (clobberedLocals.isEmpty()) {
- // Advance the iterator so it ends up at the first move that clobbers a local.
- instructionIterator.next();
- }
- if (next.isMove()) {
- Move move = next.asMove();
- int dstRegister = getArgumentOrAllocateRegisterForValue(move.dest(), index);
- DebugLocalInfo dstInitialLocal = initialLocals.get(dstRegister);
- DebugLocalInfo dstFinalLocal = finalLocals.get(dstRegister);
- if (dstInitialLocal != null && dstInitialLocal != dstFinalLocal) {
- initialLocals.remove(dstRegister);
- clobberedLocals.put(dstRegister, dstInitialLocal);
- }
- }
- }
- // Add an initial local change for all clobbered locals after the first clobbered local.
- if (!clobberedLocals.isEmpty()) {
- instructionIterator.add(new DebugLocalsChange(
- clobberedLocals, Int2ReferenceMaps.emptyMap()));
- }
- // Compute the final change in locals and emit it after all spill moves.
- while (instructionIterator.hasNext()) {
- if (instructionIterator.next().getNumber() != -1) {
- break;
- }
+ // Moves may have clobber current locals so they must be closed.
+ Int2ReferenceMap<DebugLocalInfo> clobbered =
+ endClobberedLocals(instructionIterator, initialLocals, finalLocals);
+ for (Entry<DebugLocalInfo> ended : clobbered.int2ReferenceEntrySet()) {
+ assert initialLocals.get(ended.getIntKey()) == ended.getValue();
+ initialLocals.remove(ended.getIntKey());
}
instructionIterator.previous();
+ // Compute the final change in locals and insert it after the last move.
Int2ReferenceMap<DebugLocalInfo> ending = new Int2ReferenceOpenHashMap<>();
Int2ReferenceMap<DebugLocalInfo> starting = new Int2ReferenceOpenHashMap<>();
for (Entry<DebugLocalInfo> initialLocal : initialLocals.int2ReferenceEntrySet()) {
@@ -435,6 +428,46 @@
}
}
+ private Int2ReferenceMap<DebugLocalInfo> endClobberedLocals(
+ ListIterator<Instruction> instructionIterator,
+ Int2ReferenceMap<DebugLocalInfo> initialLocals,
+ Int2ReferenceMap<DebugLocalInfo> finalLocals) {
+ int spillCount;
+ int firstClobberedMove = -1;
+ Int2ReferenceMap<DebugLocalInfo> clobberedLocals = Int2ReferenceMaps.emptyMap();
+ for (spillCount = 0; instructionIterator.hasNext(); spillCount++) {
+ Instruction next = instructionIterator.next();
+ if (next.getNumber() != -1) {
+ break;
+ }
+ if (next.isMove()) {
+ Move move = next.asMove();
+ int dst = getRegisterForValue(move.dest(), move.getNumber());
+ DebugLocalInfo initialLocal = initialLocals.get(dst);
+ if (initialLocal != null && initialLocal != finalLocals.get(dst)) {
+ if (firstClobberedMove == -1) {
+ firstClobberedMove = spillCount;
+ clobberedLocals = new Int2ReferenceOpenHashMap<>();
+ }
+ clobberedLocals.put(dst, initialLocal);
+ }
+ }
+ }
+ // Add an initial local change for all clobbered locals after the first clobbered local.
+ if (firstClobberedMove != -1) {
+ int tail = spillCount - firstClobberedMove;
+ for (int i = 0; i < tail; i++) {
+ instructionIterator.previous();
+ }
+ instructionIterator.add(new DebugLocalsChange(
+ clobberedLocals, Int2ReferenceMaps.emptyMap()));
+ for (int i = 0; i < tail; i++) {
+ instructionIterator.next();
+ }
+ }
+ return clobberedLocals;
+ }
+
private DebugLocalsChange createLocalsChange(
Int2ReferenceMap<DebugLocalInfo> ending, Int2ReferenceMap<DebugLocalInfo> starting) {
if (ending.isEmpty() && starting.isEmpty()) {