Fix spilling of argument live intervals

Bug: b/382220159
Change-Id: I17f15ff6783a567b625fdac9b82dfafa3271d6c0
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 8e8cda3..7c8e08e 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
@@ -2901,17 +2901,20 @@
   private void splitRangesForSpilledArgument(LiveIntervals spilled) {
     assert spilled.isSpilled();
     assert spilled.isArgumentInterval();
-    // Argument intervals are spilled to the original argument register. We don't know what
-    // that is yet, and therefore we split before the next use to make sure we get a usable
+    // Argument intervals are spilled to the original argument register. We don't know what that is
+    // yet, and therefore we split before the next constrained use to make sure we get a usable
     // register at the next use.
-    if (!spilled.getUses().isEmpty()) {
-      LiveIntervals split = spilled.splitBefore(spilled.getUses().first().getPosition(), mode);
-      if (split != spilled) {
-        unhandled.add(split);
-      } else {
-        spilled.setRegister(spilled.getSplitParent().getRegister());
-      }
+    LiveIntervalsUse firstUseWithConstraint = spilled.firstUseWithConstraint(mode);
+    if (firstUseWithConstraint == null
+        || (mode.is8BitRefinement()
+            && spilled.getSplitParent().getRegisterEnd() < numberOf4BitArgumentRegisters)) {
+      spilled.setRegister(spilled.getSplitParent().getRegister());
+      spilled.setSpilled(false);
+      return;
     }
+    LiveIntervals splitOfSplit = spilled.splitBefore(firstUseWithConstraint.getPosition(), mode);
+    assert splitOfSplit != spilled;
+    unhandled.add(splitOfSplit);
   }
 
   private void splitRangesForSpilledInterval(LiveIntervals spilled) {