Merge "Use an iterative implementation for depthFirstSorting."
diff --git a/src/main/java/com/android/tools/r8/Version.java b/src/main/java/com/android/tools/r8/Version.java
index eb6718d..3639d9e 100644
--- a/src/main/java/com/android/tools/r8/Version.java
+++ b/src/main/java/com/android/tools/r8/Version.java
@@ -11,7 +11,7 @@
 
   // This field is accessed from release scripts using simple pattern matching.
   // Therefore, changing this field could break our release scripts.
-  public static final String LABEL = "v1.2.7-dev";
+  public static final String LABEL = "v1.2.8-dev";
 
   private Version() {
   }
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 1e010ce..31eb337 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
@@ -2176,7 +2176,22 @@
             if (options.isGeneratingDex()) {
               int inConstraint = instruction.maxInValueRegister();
               LiveIntervals useIntervals = use.getLiveIntervals();
-              useIntervals.addUse(new LiveIntervalsUse(instruction.getNumber(), inConstraint));
+              // Arguments are always kept in their original, incoming register. For every
+              // unconstrained use of an argument we therefore use its incoming register.
+              // As a result, we do not need to record that the argument is being used at the
+              // current instruction.
+              //
+              // For ranged invoke instructions that use a subset of the arguments in the current
+              // order, registering a use for the arguments at the invoke can cause us to run out of
+              // registers. That is because all arguments are forced back into a chosen register at
+              // all uses. Therefore, if we register a use of an argument where we can actually use
+              // it in the argument register, the register allocator would use two registers for the
+              // argument but in reality only use one.
+              boolean isUnconstrainedArgumentUse =
+                  use.isArgument() && inConstraint == Constants.U16BIT_MAX;
+              if (!isUnconstrainedArgumentUse) {
+                useIntervals.addUse(new LiveIntervalsUse(instruction.getNumber(), inConstraint));
+              }
             }
           }
         }
diff --git a/src/test/java/com/android/tools/r8/ir/regalloc/B77240639.java b/src/test/java/com/android/tools/r8/ir/regalloc/B77240639.java
index 440f4f3..28a6fa3 100644
--- a/src/test/java/com/android/tools/r8/ir/regalloc/B77240639.java
+++ b/src/test/java/com/android/tools/r8/ir/regalloc/B77240639.java
@@ -16,7 +16,6 @@
 import org.junit.Test;
 
 public class B77240639 extends TestBase {
-  @Ignore("b/77240639")
   @Test
   public void test() throws Exception {
     AndroidApp app = compileWithD8(readClasses(TestClass.class));
diff --git a/tools/test_gradle_benchmarks.py b/tools/test_gradle_benchmarks.py
index 6720c4a..189b9da 100755
--- a/tools/test_gradle_benchmarks.py
+++ b/tools/test_gradle_benchmarks.py
@@ -3,7 +3,6 @@
 # for details. All rights reserved. Use of this source code is governed by a
 # BSD-style license that can be found in the LICENSE file.
 
-
 from __future__ import print_function
 import argparse
 import os
@@ -12,7 +11,6 @@
 import gradle
 from enum import Enum
 
-
 BENCHMARKS_ROOT_DIR = os.path.join(utils.REPO_ROOT, 'third_party', 'benchmarks')
 
 def parse_arguments():
@@ -24,9 +22,10 @@
                       choices=['dx', 'd8'],
                       required=True,
                       help='Compiler tool to use.')
+  parser.add_argument('--benchmark',
+                      help='Which benchmark to run, default all')
   return parser.parse_args()
 
-
 class Benchmark:
   class Tools(Enum):
     D8 = 1
@@ -88,7 +87,6 @@
   def EnsurePresence(self):
     EnsurePresence(self.rootDirPath, self.displayName)
 
-
 def EnsurePresence(dir, displayName):
   if not os.path.exists(dir) or os.path.getmtime(dir + '.tar.gz')\
           < os.path.getmtime(dir + '.tar.gz.sha1'):
@@ -111,7 +109,6 @@
 
   return any(namePattern in taskname for namePattern in acceptedGradleTasks)
 
-
 def PrintBuildTimeForGolem(benchmark, stdOut):
   for line in stdOut.splitlines():
     if 'BENCH' in line and benchmark.moduleName in line:
@@ -138,7 +135,6 @@
         print('{}(RunTimeRaw): {} ms'
               .format(benchmark.displayName + '-' + taskName, commaSplit[2]))
 
-
 def Main():
   args = parse_arguments()
 
@@ -191,10 +187,16 @@
 
   ]
 
-  EnsurePresence(os.path.join('third_party', 'benchmarks', 'android-sdk'), 'android SDK')
-  EnsurePresence(os.path.join('third_party', 'gradle-plugin'), 'Android Gradle plugin')
-
-  for benchmark in buildTimeBenchmarks:
+  EnsurePresence(os.path.join('third_party', 'benchmarks', 'android-sdk'),
+                 'android SDK')
+  EnsurePresence(os.path.join('third_party', 'gradle-plugin'),
+                 'Android Gradle plugin')
+  toRun = buildTimeBenchmarks
+  if args.benchmark:
+    toRun = [b for b in toRun if b.displayName == args.benchmark]
+    if len(toRun) != 1:
+      raise AssertionError("Unknown benchmark: " + args.benchmark)
+  for benchmark in toRun:
     benchmark.EnsurePresence()
     benchmark.Clean()
     stdOut = benchmark.Build(tool, desugarMode)