Compute live-at-entry state up-to but excluding the first instruction.

This also fixes an off-by-one error in the insertion of clobbered locals.

R=ager

Change-Id: Ied66ef15d49636878be07f53b426a6dd0a3109cf
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 6f1a9b2..99767fd 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
@@ -291,8 +291,34 @@
     }
 
     for (BasicBlock block : blocks) {
-      boolean blockEntry = true;
       ListIterator<Instruction> instructionIterator = block.listIterator();
+      // Update ranges up-to but excluding the index of the first instruction.
+      int entryIndex = block.entry().getNumber();
+      {
+        ListIterator<LocalRange> it = openRanges.listIterator(0);
+        while (it.hasNext()) {
+          LocalRange openRange = it.next();
+          if (openRange.end < entryIndex) {
+            it.remove();
+            assert currentLocals.get(openRange.register) == openRange.local;
+            currentLocals.remove(openRange.register);
+          }
+        }
+      }
+      while (nextStartingRange != null && nextStartingRange.start < entryIndex) {
+        // If the range is live at this index open it.
+        if (entryIndex < nextStartingRange.end) {
+          openRanges.add(nextStartingRange);
+          assert !currentLocals.containsKey(nextStartingRange.register);
+          currentLocals.put(nextStartingRange.register, nextStartingRange.local);
+        }
+        nextStartingRange = rangeIterator.hasNext() ? rangeIterator.next() : null;
+      }
+      if (block.entry().isMoveException()) {
+        fixupSpillMovesAtMoveException(block, instructionIterator, openRanges, currentLocals);
+      } else {
+        block.setLocalsAtEntry(new Int2ReferenceOpenHashMap<>(currentLocals));
+      }
       while (instructionIterator.hasNext()) {
         Instruction instruction = instructionIterator.next();
         int index = instruction.getNumber();
@@ -320,25 +346,15 @@
           }
           nextStartingRange = rangeIterator.hasNext() ? rangeIterator.next() : null;
         }
-
-        if (blockEntry) {
-          blockEntry = false;
-          if (instruction.isMoveException()) {
-            fixupSpillMovesAtMoveException(block, instructionIterator, openRanges, currentLocals);
-          } else {
-            block.setLocalsAtEntry(new Int2ReferenceOpenHashMap<>(currentLocals));
-          }
-        } else {
-          if (localsChanged && shouldEmitChangesAtInstruction(instruction)) {
-            DebugLocalsChange change = createLocalsChange(ending, starting);
-            if (change != null) {
-              if (instruction.isDebugPosition() || instruction.isJumpInstruction()) {
-                instructionIterator.previous();
-                instructionIterator.add(change);
-                instructionIterator.next();
-              } else {
-                instructionIterator.add(change);
-              }
+        if (localsChanged && shouldEmitChangesAtInstruction(instruction)) {
+          DebugLocalsChange change = createLocalsChange(ending, starting);
+          if (change != null) {
+            if (instruction.isDebugPosition() || instruction.isJumpInstruction()) {
+              instructionIterator.previous();
+              instructionIterator.add(change);
+              instructionIterator.next();
+            } else {
+              instructionIterator.add(change);
             }
           }
         }
@@ -359,11 +375,13 @@
       initialLocals.put(exceptionalRegister, open.local);
     }
     block.setLocalsAtEntry(new Int2ReferenceOpenHashMap<>(initialLocals));
-    Int2ReferenceMap<DebugLocalInfo> clobberedLocals = new Int2ReferenceOpenHashMap<>();
-    Iterator<Instruction> moveIterator = block.iterator();
+    Instruction entry = instructionIterator.next();
+    assert block.entry() == entry;
     assert block.entry().isMoveException();
-    int index = block.entry().getNumber();
+    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) {
@@ -392,10 +410,10 @@
     // Compute the final change in locals and emit it after all spill moves.
     while (instructionIterator.hasNext()) {
       if (instructionIterator.next().getNumber() != -1) {
-        instructionIterator.previous();
         break;
       }
     }
+    instructionIterator.previous();
     Int2ReferenceMap<DebugLocalInfo> ending = new Int2ReferenceOpenHashMap<>();
     Int2ReferenceMap<DebugLocalInfo> starting = new Int2ReferenceOpenHashMap<>();
     for (Entry<DebugLocalInfo> initialLocal : initialLocals.int2ReferenceEntrySet()) {