Version 0.1.9.

R=sgjesse@google.com

Merge: Fix register allocation bug triggering in rare situations in
debug mode.
CL: https://r8-review.googlesource.com/c/r8/+/5841
Change-Id: If049d5e99f08efab6716251a175dba54864f1e29
diff --git a/src/main/java/com/android/tools/r8/D8.java b/src/main/java/com/android/tools/r8/D8.java
index 5e43513..dda9a39 100644
--- a/src/main/java/com/android/tools/r8/D8.java
+++ b/src/main/java/com/android/tools/r8/D8.java
@@ -55,7 +55,7 @@
  */
 public final class D8 {
 
-  private static final String VERSION = "v0.1.8";
+  private static final String VERSION = "v0.1.9";
   private static final int STATUS_ERROR = 1;
 
   private D8() {}
diff --git a/src/main/java/com/android/tools/r8/R8.java b/src/main/java/com/android/tools/r8/R8.java
index e8efb59..a79a5cd 100644
--- a/src/main/java/com/android/tools/r8/R8.java
+++ b/src/main/java/com/android/tools/r8/R8.java
@@ -71,7 +71,7 @@
 
 public class R8 {
 
-  private static final String VERSION = "v0.1.8";
+  private static final String VERSION = "v0.1.9";
   private final Timing timing = new Timing("R8");
   private final InternalOptions options;
 
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 460fe92..300aece 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
@@ -992,9 +992,6 @@
   }
 
   private int getSpillRegister(LiveIntervals intervals) {
-    if (intervals.isArgumentInterval()) {
-      return intervals.getSplitParent().getRegister();
-    }
     int registerNumber = nextUnusedRegisterNumber++;
     maxRegisterNumber = registerNumber;
     if (intervals.getType() == MoveType.WIDE) {
@@ -1546,17 +1543,19 @@
       LiveIntervals unhandledInterval,
       boolean needsRegisterPair,
       int candidate) {
+    List<LiveIntervals> newInactive = new ArrayList<>();
     Iterator<LiveIntervals> inactiveIterator = inactive.iterator();
     while (inactiveIterator.hasNext()) {
       LiveIntervals intervals = inactiveIterator.next();
       if ((intervals.usesRegister(candidate) ||
           (needsRegisterPair && intervals.usesRegister(candidate + 1))) &&
           intervals.overlaps(unhandledInterval)) {
-        // If these assertions trigger we have changed the way blocked parts of intervals
-        // are handled. If we ever get intervals with fixed registers in here, we need
-        // to split them before the first use in the same way that we do when spilling
-        // overlapping active intervals.
-        assert !intervals.isLinked() || intervals.isArgumentInterval();
+        if (intervals.isLinked() && !intervals.isArgumentInterval()) {
+          int nextUsePosition = intervals.firstUseAfter(unhandledInterval.getStart());
+          LiveIntervals split = intervals.splitBefore(nextUsePosition);
+          split.setRegister(intervals.getRegister());
+          newInactive.add(split);
+        }
         if (intervals.getStart() > unhandledInterval.getStart()) {
           // The inactive live intervals hasn't started yet. Clear the temporary register
           // assignment and move back to unhandled for register reassignment.
@@ -1571,6 +1570,7 @@
         }
       }
     }
+    inactive.addAll(newInactive);
   }
 
   private void spillOverlappingActiveIntervals(
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 65628c3..18f193f 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
@@ -88,6 +88,9 @@
   }
 
   public boolean isRematerializable(LinearScanRegisterAllocator registerAllocator) {
+    if (value.isArgument()) {
+      return true;
+    }
     // TODO(ager): rematerialize const string as well.
     if (!value.isConstNumber()) {
       return false;
diff --git a/src/main/java/com/android/tools/r8/ir/regalloc/RegisterMove.java b/src/main/java/com/android/tools/r8/ir/regalloc/RegisterMove.java
index 9cb873e..0d267e9 100644
--- a/src/main/java/com/android/tools/r8/ir/regalloc/RegisterMove.java
+++ b/src/main/java/com/android/tools/r8/ir/regalloc/RegisterMove.java
@@ -26,7 +26,7 @@
     this.dst = dst;
     this.src = LinearScanRegisterAllocator.NO_REGISTER;
     this.type = type;
-    assert definition.isConstInstruction();
+    assert definition.isConstInstruction() || definition.isArgument();
     this.definition = definition;
   }
 
diff --git a/src/main/java/com/android/tools/r8/ir/regalloc/RegisterMoveScheduler.java b/src/main/java/com/android/tools/r8/ir/regalloc/RegisterMoveScheduler.java
index cc26729..d3c927c 100644
--- a/src/main/java/com/android/tools/r8/ir/regalloc/RegisterMoveScheduler.java
+++ b/src/main/java/com/android/tools/r8/ir/regalloc/RegisterMoveScheduler.java
@@ -121,8 +121,14 @@
     Instruction instruction;
     Value to = new FixedRegisterValue(move.type, move.dst);
     if (move.definition != null) {
-      ConstNumber number = move.definition.asConstNumber();
-      instruction = new ConstNumber(number.type, to, number.getRawValue());
+      if (move.definition.isArgument()) {
+        int argumentRegister = move.definition.outValue().getLiveIntervals().getRegister();
+        Value from = new FixedRegisterValue(move.type, argumentRegister);
+        instruction = new Move(to, from);
+      } else {
+        ConstNumber number = move.definition.asConstNumber();
+        instruction = new ConstNumber(number.type, to, number.getRawValue());
+      }
     } else {
       Value from = new FixedRegisterValue(move.type, valueMap.get(move.src));
       instruction = new Move(to, from);
diff --git a/src/main/java/com/android/tools/r8/ir/regalloc/SpillMoveSet.java b/src/main/java/com/android/tools/r8/ir/regalloc/SpillMoveSet.java
index 643a3c1..cd1d880 100644
--- a/src/main/java/com/android/tools/r8/ir/regalloc/SpillMoveSet.java
+++ b/src/main/java/com/android/tools/r8/ir/regalloc/SpillMoveSet.java
@@ -31,8 +31,6 @@
   // The register allocator generating moves.
   private LinearScanRegisterAllocator allocator;
   // All registers below this number are arguments.
-  // TODO(ager): Get rid of this field, we should deal with arguments and other values that can
-  // be rematerialized differently.
   private final int argumentRegisterLimit;
   // Mapping from instruction numbers to the block that start with that instruction if any.
   private final Map<Integer, BasicBlock> blockStartMap = new HashMap<>();
@@ -257,6 +255,10 @@
   // disallowed at this point we know that argument registers do not change value and
   // therefore we don't have to perform spill moves. Performing spill moves will also
   // make art reject the code because it loses type information for the argument.
+  //
+  // TODO(ager): We are dealing with some of these moves as rematerialization. However,
+  // we are still generating actual moves back to the original argument register.
+  // We should get rid of this method and avoid generating the moves in the first place.
   private void removeArgumentRestores(Set<SpillMove> moves) {
     Iterator<SpillMove> moveIterator = moves.iterator();
     while (moveIterator.hasNext()) {