Merge "Update Proguard 6.0 to Proguard 6.0.1"
diff --git a/build.gradle b/build.gradle
index 6a821a5..716f983 100644
--- a/build.gradle
+++ b/build.gradle
@@ -36,7 +36,7 @@
     joptSimpleVersion = '4.6'
     jsonSimpleVersion = '1.1'
     junitVersion = '4.12'
-    kotlinVersion = '1.2.0'
+    kotlinVersion = '1.2.30'
     protobufVersion = '3.0.0'
     smaliVersion = '2.2b4'
 }
diff --git a/src/main/java/com/android/tools/r8/Version.java b/src/main/java/com/android/tools/r8/Version.java
index 670211f..9404e68 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.1.9-dev";
+  public static final String LABEL = "v1.1.10-dev";
 
   private Version() {
   }
diff --git a/src/main/java/com/android/tools/r8/graph/DexClass.java b/src/main/java/com/android/tools/r8/graph/DexClass.java
index 42acb7c..d6b15eb 100644
--- a/src/main/java/com/android/tools/r8/graph/DexClass.java
+++ b/src/main/java/com/android/tools/r8/graph/DexClass.java
@@ -146,6 +146,46 @@
     return result;
   }
 
+  /**
+   * For all annotations on the class and all annotations on its methods and fields apply the
+   * specified consumer.
+   */
+  public void forEachAnnotation(Consumer<DexAnnotation> consumer) {
+    for (DexAnnotation annotation : annotations.annotations) {
+      consumer.accept(annotation);
+    }
+    for (DexEncodedMethod method : directMethods()) {
+      for (DexAnnotation annotation : method.annotations.annotations) {
+        consumer.accept(annotation);
+      }
+      for (DexAnnotationSet parameterAnnotations : method.parameterAnnotations.values) {
+        for (DexAnnotation annotation : parameterAnnotations.annotations) {
+          consumer.accept(annotation);
+        }
+      }
+    }
+    for (DexEncodedMethod method : virtualMethods()) {
+      for (DexAnnotation annotation : method.annotations.annotations) {
+        consumer.accept(annotation);
+      }
+      for (DexAnnotationSet parameterAnnotations : method.parameterAnnotations.values) {
+        for (DexAnnotation annotation : parameterAnnotations.annotations) {
+          consumer.accept(annotation);
+        }
+      }
+    }
+    for (DexEncodedField field : instanceFields()) {
+      for (DexAnnotation annotation : field.annotations.annotations) {
+        consumer.accept(annotation);
+      }
+    }
+    for (DexEncodedField field : staticFields()) {
+      for (DexAnnotation annotation : field.annotations.annotations) {
+        consumer.accept(annotation);
+      }
+    }
+  }
+
   public void forEachField(Consumer<DexEncodedField> consumer) {
     for (DexEncodedField field : staticFields()) {
       consumer.accept(field);
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/IRBuilder.java b/src/main/java/com/android/tools/r8/ir/conversion/IRBuilder.java
index 76a1a43..20051f9 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/IRBuilder.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/IRBuilder.java
@@ -396,10 +396,6 @@
     // necessary.
     ir.splitCriticalEdges();
 
-    // Create block order and make sure that all blocks are immediately followed by their
-    // fallthrough block if any.
-    ir.traceBlocks();
-
     // Clear the code so we don't build multiple times.
     source.clear();
     source = null;
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java b/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java
index 42b06ef..0f0b44a 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java
@@ -476,6 +476,7 @@
       Log.debug(getClass(), "Initial (SSA) flow graph for %s:\n%s", method.toSourceString(), code);
     }
     assert code.isConsistentSSA();
+    code.traceBlocks();
     RegisterAllocator registerAllocator = performRegisterAllocation(code, method);
     method.setCode(code, registerAllocator, options);
     if (Log.ENABLED) {
@@ -635,7 +636,6 @@
 
     if (options.testing.invertConditionals) {
       invertConditionalsForTesting(code);
-      code.traceBlocks();
     }
 
     if (options.enableNonNullTracking && nonNullTracker != null) {
@@ -699,6 +699,7 @@
   }
 
   private void finalizeIR(DexEncodedMethod method, IRCode code, OptimizationFeedback feedback) {
+    code.traceBlocks();
     if (options.isGeneratingClassFiles()) {
       finalizeToCf(method, code, feedback);
     } else {
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/CodeRewriter.java b/src/main/java/com/android/tools/r8/ir/optimize/CodeRewriter.java
index a6b29e8..30e9bae4 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/CodeRewriter.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/CodeRewriter.java
@@ -565,7 +565,6 @@
     // being split on the way in but does not maintain this property. We therefore split
     // critical edges at exit.
     code.splitCriticalEdges();
-    code.traceBlocks();
     assert code.isConsistentSSA();
   }
 
@@ -2028,9 +2027,6 @@
     }
     code.removeMarkedBlocks(color);
     code.returnMarkingColor(color);
-    if (ifBranchFlipped) {
-      code.traceBlocks();
-    }
     assert code.isConsistentSSA();
   }
 
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 acf4395..85e0060 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
@@ -54,6 +54,8 @@
 import java.util.PriorityQueue;
 import java.util.Set;
 import java.util.TreeSet;
+import java.util.function.BiPredicate;
+import java.util.function.Predicate;
 
 /**
  * Linear scan register allocator.
@@ -1348,10 +1350,17 @@
     // free position.
     int candidate = getLargestValidCandidate(
         unhandledInterval, registerConstraint, needsRegisterPair, freePositions, Type.ANY);
-    assert candidate != REGISTER_CANDIDATE_NOT_FOUND;
-    int largestFreePosition = freePositions.get(candidate);
-    if (needsRegisterPair) {
-      largestFreePosition = Math.min(largestFreePosition, freePositions.get(candidate + 1));
+
+    // It is not always possible to find a largest valid candidate. If none of the usable register
+    // are free we typically get the last candidate. However, if that candidate has to be
+    // discarded in order to workaround bugs we get REGISTER_CANDIDATE_NOT_FOUND. In both cases
+    // we need to spill a valid candidate. That path is triggered when largestFreePosition is 0.
+    int largestFreePosition = 0;
+    if (candidate != REGISTER_CANDIDATE_NOT_FOUND) {
+      largestFreePosition = freePositions.get(candidate);
+      if (needsRegisterPair) {
+        largestFreePosition = Math.min(largestFreePosition, freePositions.get(candidate + 1));
+      }
     }
 
     // Determine what to do based on how long the selected candidate is free.
@@ -1554,57 +1563,47 @@
     return candidate;
   }
 
+  private int handleWorkaround(
+      Predicate<LiveIntervals> workaroundNeeded,
+      BiPredicate<LiveIntervals, Integer> workaroundNeededForCandidate,
+      int candidate, LiveIntervals unhandledInterval, int registerConstraint,
+      boolean needsRegisterPair, RegisterPositions freePositions, RegisterPositions.Type type) {
+    if (workaroundNeeded.test(unhandledInterval)) {
+      int lastCandidate = candidate;
+      while (workaroundNeededForCandidate.test(unhandledInterval, candidate)) {
+        // Make the unusable register unavailable for allocation and try again.
+        freePositions.set(candidate, 0);
+        candidate = getLargestCandidate(registerConstraint, freePositions, needsRegisterPair, type);
+        // If there are only invalid candidates of the give type we will end up with the same
+        // candidate returned again once we have tried them all. In that case we didn't find a
+        // valid register candidate and we need to broaden the search to other types.
+        if (lastCandidate == candidate) {
+          return REGISTER_CANDIDATE_NOT_FOUND;
+        }
+        lastCandidate = candidate;
+      }
+    }
+    return candidate;
+  }
+
   private int getLargestValidCandidate(LiveIntervals unhandledInterval, int registerConstraint,
       boolean needsRegisterPair, RegisterPositions freePositions, RegisterPositions.Type type) {
     int candidate = getLargestCandidate(registerConstraint, freePositions, needsRegisterPair, type);
     if (candidate == REGISTER_CANDIDATE_NOT_FOUND) {
       return candidate;
     }
-    if (needsLongResultOverlappingLongOperandsWorkaround(unhandledInterval)) {
-      int lastCandidate = candidate;
-      while (isLongResultOverlappingLongOperands(unhandledInterval, candidate)) {
-        // Make the overlapping register unavailable for allocation and try again.
-        freePositions.set(candidate, 0);
-        candidate = getLargestCandidate(registerConstraint, freePositions, needsRegisterPair, type);
-        // If there are only invalid candidates of the give type we will end up with the same
-        // candidate returned again once we have tried them all. In that case we didn't find a
-        // valid register candidate and we need to broaden the search to other types.
-        if (lastCandidate == candidate) {
-          return REGISTER_CANDIDATE_NOT_FOUND;
-        }
-        lastCandidate = candidate;
-      }
-    }
-    if (needsSingleResultOverlappingLongOperandsWorkaround(unhandledInterval)) {
-      int lastCandidate = candidate;
-      while (isSingleResultOverlappingLongOperands(unhandledInterval, candidate)) {
-        // Make the overlapping register unavailable for allocation and try again.
-        freePositions.set(candidate, 0);
-        candidate = getLargestCandidate(registerConstraint, freePositions, needsRegisterPair, type);
-        // If there are only invalid candidates of the give type we will end up with the same
-        // candidate returned again once we have tried them all. In that case we didn't find a
-        // valid register candidate and we need to broaden the search to other types.
-        if (lastCandidate == candidate) {
-          return REGISTER_CANDIDATE_NOT_FOUND;
-        }
-        lastCandidate = candidate;
-      }
-    }
-    if (needsArrayGetWideWorkaround(unhandledInterval)) {
-      int lastCandidate = candidate;
-      while (isArrayGetArrayRegister(unhandledInterval, candidate)) {
-        // Make the overlapping register unavailable for allocation and try again.
-        freePositions.set(candidate, 0);
-        candidate = getLargestCandidate(registerConstraint, freePositions, needsRegisterPair, type);
-        // If there are only invalid candidates of the give type we will end up with the same
-        // candidate returned again once we have tried them all. In that case we didn't find a
-        // valid register candidate and we need to broaden the search to other types.
-        if (lastCandidate == candidate) {
-          return REGISTER_CANDIDATE_NOT_FOUND;
-        }
-        lastCandidate = candidate;
-      }
-    }
+    candidate = handleWorkaround(
+        this::needsLongResultOverlappingLongOperandsWorkaround,
+        this::isLongResultOverlappingLongOperands,
+        candidate, unhandledInterval, registerConstraint, needsRegisterPair, freePositions, type);
+    candidate = handleWorkaround(
+        this::needsSingleResultOverlappingLongOperandsWorkaround,
+        this::isSingleResultOverlappingLongOperands,
+        candidate, unhandledInterval, registerConstraint, needsRegisterPair, freePositions, type);
+    candidate = handleWorkaround(
+        this::needsArrayGetWideWorkaround,
+        this::isArrayGetArrayRegister,
+        candidate, unhandledInterval, registerConstraint, needsRegisterPair, freePositions, type);
     return candidate;
   }
 
diff --git a/src/main/java/com/android/tools/r8/shaking/MainDexListBuilder.java b/src/main/java/com/android/tools/r8/shaking/MainDexListBuilder.java
index de21187..5c51786 100644
--- a/src/main/java/com/android/tools/r8/shaking/MainDexListBuilder.java
+++ b/src/main/java/com/android/tools/r8/shaking/MainDexListBuilder.java
@@ -85,13 +85,13 @@
         addMainDexType(dexType);
         continue;
       }
-      for (DexAnnotation annotation : clazz.annotations.annotations) {
-        if (annotation.visibility == DexAnnotation.VISIBILITY_RUNTIME
+      clazz.forEachAnnotation(annotation -> {
+        if (!mainDexTypes.contains(dexType)
+            && annotation.visibility == DexAnnotation.VISIBILITY_RUNTIME
             && isAnnotationWithEnum(annotation.annotation.type)) {
           addMainDexType(dexType);
-          break;
         }
-      }
+      });
     }
   }
 
diff --git a/src/main/java/com/android/tools/r8/shaking/ProguardConfigurationParser.java b/src/main/java/com/android/tools/r8/shaking/ProguardConfigurationParser.java
index b526973..e96de6f 100644
--- a/src/main/java/com/android/tools/r8/shaking/ProguardConfigurationParser.java
+++ b/src/main/java/com/android/tools/r8/shaking/ProguardConfigurationParser.java
@@ -535,7 +535,7 @@
     private ProguardIfRule parseIfRule(TextPosition optionStart)
         throws ProguardRuleParserException {
       ProguardIfRule.Builder ifRuleBuilder = ProguardIfRule.builder();
-      parseClassSpec(ifRuleBuilder, true);
+      parseClassSpec(ifRuleBuilder, false);
 
       // Required a subsequent keep rule.
       skipWhitespace();
@@ -1086,15 +1086,52 @@
       return Integer.parseInt(s);
     }
 
+    private final Predicate<Character> CLASS_NAME_PREDICATE =
+        character -> IdentifierUtils.isDexIdentifierPart(character)
+            || character == '.'
+            || character == '*'
+            || character == '?'
+            || character == '%'
+            || character == '['
+            || character == ']';
+
     private String acceptClassName() {
-      return acceptString(character ->
-          IdentifierUtils.isDexIdentifierPart(character)
-              || character == '.'
-              || character == '*'
-              || character == '?'
-              || character == '%'
-              || character == '['
-              || character == ']');
+      return acceptString(CLASS_NAME_PREDICATE);
+    }
+
+    private String acceptClassNameWithNthWildcard() {
+      StringBuilder nthWildcard = null;
+      skipWhitespace();
+      int start = position;
+      int end = position;
+      while (!eof(end)) {
+        char current = contents.charAt(end);
+        if (nthWildcard != null) {
+          if (current == '>') {
+            try {
+              Integer.parseUnsignedInt(nthWildcard.toString());
+            } catch (NullPointerException | NumberFormatException e) {
+              return null;
+            }
+            nthWildcard = null;
+          } else {
+            nthWildcard.append(current);
+          }
+          end++;
+        } else if (CLASS_NAME_PREDICATE.test(current)) {
+          end++;
+        } else if (current == '<') {
+          nthWildcard = new StringBuilder();
+          end++;
+        } else {
+          break;
+        }
+      }
+      if (start == end) {
+        return null;
+      }
+      position = end;
+      return contents.substring(start, end);
     }
 
     private String acceptFieldNameOrIntegerForReturn() {
@@ -1194,7 +1231,7 @@
     }
 
     private String parseClassName() throws ProguardRuleParserException {
-      String name = acceptClassName();
+      String name = acceptClassNameWithNthWildcard();
       if (name == null) {
         throw parseError("Class name expected");
       }
diff --git a/src/main/java/com/android/tools/r8/shaking/protolite/ProtoLitePruner.java b/src/main/java/com/android/tools/r8/shaking/protolite/ProtoLitePruner.java
index 46669ec..c37102c 100644
--- a/src/main/java/com/android/tools/r8/shaking/protolite/ProtoLitePruner.java
+++ b/src/main/java/com/android/tools/r8/shaking/protolite/ProtoLitePruner.java
@@ -348,7 +348,6 @@
     // the fallthrough label. This can introduce critical edges. Therefore, we split critical
     // edges to maintain our edge-split form.
     code.splitCriticalEdges();
-    code.traceBlocks();
     assert code.isConsistentSSA();
   }
 
diff --git a/src/test/examples/multidex002/AnnotatedDirectMethod.java b/src/test/examples/multidex002/AnnotatedDirectMethod.java
new file mode 100644
index 0000000..761ea9a
--- /dev/null
+++ b/src/test/examples/multidex002/AnnotatedDirectMethod.java
@@ -0,0 +1,12 @@
+// Copyright (c) 2017, the R8 project authors. Please see the AUTHORS file
+// 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.
+
+package multidex002;
+
+public class AnnotatedDirectMethod {
+
+  @AnnotationWithEnum3(AnnotationWithEnum3.Value3.VAL3_2)
+  private void foo() {
+  }
+}
diff --git a/src/test/examples/multidex002/AnnotatedInstanceField.java b/src/test/examples/multidex002/AnnotatedInstanceField.java
new file mode 100644
index 0000000..0209f44
--- /dev/null
+++ b/src/test/examples/multidex002/AnnotatedInstanceField.java
@@ -0,0 +1,11 @@
+// Copyright (c) 2017, the R8 project authors. Please see the AUTHORS file
+// 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.
+
+package multidex002;
+
+public class AnnotatedInstanceField {
+
+  @AnnotationWithEnum3(AnnotationWithEnum3.Value3.VAL3_2)
+  public String value = "myValue";
+}
diff --git a/src/test/examples/multidex002/AnnotatedMethodParameter.java b/src/test/examples/multidex002/AnnotatedMethodParameter.java
new file mode 100644
index 0000000..49a9e6d
--- /dev/null
+++ b/src/test/examples/multidex002/AnnotatedMethodParameter.java
@@ -0,0 +1,11 @@
+// Copyright (c) 2017, the R8 project authors. Please see the AUTHORS file
+// 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.
+
+package multidex002;
+
+public class AnnotatedMethodParameter {
+
+  public void foo(@AnnotationWithEnum3(AnnotationWithEnum3.Value3.VAL3_2) String val) {
+  }
+}
diff --git a/src/test/examples/multidex002/AnnotatedNotKept.java b/src/test/examples/multidex002/AnnotatedNotKept.java
new file mode 100644
index 0000000..500e7f0
--- /dev/null
+++ b/src/test/examples/multidex002/AnnotatedNotKept.java
@@ -0,0 +1,10 @@
+// Copyright (c) 2017, the R8 project authors. Please see the AUTHORS file
+// 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.
+
+package multidex002;
+
+@AnnotationWithoutEnum
+public class AnnotatedNotKept {
+
+}
diff --git a/src/test/examples/multidex002/AnnotatedStaticField.java b/src/test/examples/multidex002/AnnotatedStaticField.java
new file mode 100644
index 0000000..385d1d9
--- /dev/null
+++ b/src/test/examples/multidex002/AnnotatedStaticField.java
@@ -0,0 +1,9 @@
+// Copyright (c) 2017, the R8 project authors. Please see the AUTHORS file
+// 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.
+
+package multidex002;
+
+public class AnnotatedStaticField {
+  @AnnotationWithEnum3(AnnotationWithEnum3.Value3.VAL3_2) public static String sValue = "myValue";
+}
diff --git a/src/test/examples/multidex002/AnnotatedVirtualMethod.java b/src/test/examples/multidex002/AnnotatedVirtualMethod.java
new file mode 100644
index 0000000..569bf84
--- /dev/null
+++ b/src/test/examples/multidex002/AnnotatedVirtualMethod.java
@@ -0,0 +1,13 @@
+// Copyright (c) 2017, the R8 project authors. Please see the AUTHORS file
+// 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.
+
+package multidex002;
+
+public class AnnotatedVirtualMethod {
+
+  @AnnotationWithEnum3(AnnotationWithEnum3.Value3.VAL3_2)
+  public void foo() {
+
+  }
+}
diff --git a/src/test/examples/multidex002/AnnotationWithEnum3.java b/src/test/examples/multidex002/AnnotationWithEnum3.java
new file mode 100644
index 0000000..a8f8344
--- /dev/null
+++ b/src/test/examples/multidex002/AnnotationWithEnum3.java
@@ -0,0 +1,19 @@
+// Copyright (c) 2017, the R8 project authors. Please see the AUTHORS file
+// 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.
+
+package multidex002;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+@Retention(RetentionPolicy.RUNTIME)
+public @interface AnnotationWithEnum3 {
+
+  enum Value3 {
+    VAL3_1,
+    VAL3_2,
+  }
+
+  Value3 value();
+}
diff --git a/src/test/examples/multidex002/AnnotationWithoutEnum.java b/src/test/examples/multidex002/AnnotationWithoutEnum.java
new file mode 100644
index 0000000..5244971
--- /dev/null
+++ b/src/test/examples/multidex002/AnnotationWithoutEnum.java
@@ -0,0 +1,13 @@
+// Copyright (c) 2017, the R8 project authors. Please see the AUTHORS file
+// 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.
+
+package multidex002;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+@Retention(RetentionPolicy.RUNTIME)
+public @interface AnnotationWithoutEnum {
+
+}
diff --git a/src/test/examples/multidex002/ref-list-1.txt b/src/test/examples/multidex002/ref-list-1.txt
index 26dae34..922d417 100644
--- a/src/test/examples/multidex002/ref-list-1.txt
+++ b/src/test/examples/multidex002/ref-list-1.txt
@@ -1,8 +1,15 @@
 Lmultidex002/Annotated2;
 Lmultidex002/Annotated;
+Lmultidex002/AnnotatedDirectMethod;
+Lmultidex002/AnnotatedInstanceField;
+Lmultidex002/AnnotatedMethodParameter;
+Lmultidex002/AnnotatedStaticField;
+Lmultidex002/AnnotatedVirtualMethod;
 Lmultidex002/AnnotationWithClass;
 Lmultidex002/AnnotationWithEnum2;
+Lmultidex002/AnnotationWithEnum3;
 Lmultidex002/AnnotationWithEnum;
+Lmultidex002/AnnotationWithoutEnum;
 Lmultidex002/InterfaceWithEnum;
 Lmultidex002/IntermediateClass;
 Lmultidex002/MainActivity;
diff --git a/src/test/java/com/android/tools/r8/JctfTestSpecifications.java b/src/test/java/com/android/tools/r8/JctfTestSpecifications.java
index 8ff72c7..c4351ce 100644
--- a/src/test/java/com/android/tools/r8/JctfTestSpecifications.java
+++ b/src/test/java/com/android/tools/r8/JctfTestSpecifications.java
@@ -4542,7 +4542,7 @@
           // java.lang.AssertionError: Failed to load serialization resource file: serialization/com/google/jctf/test/lib/java/util/concurrent/PriorityBlockingQueue/serialization/PriorityBlockingQueue_serialization_A01.golden.0.ser
 
           .put("lang.ThreadGroup.destroy.ThreadGroup_destroy_A01",
-              match(D8_COMPILER, runtimesUpTo(Version.V6_0_1)))
+              match(runtimesUpTo(Version.V6_0_1)))
           // 1) t02
           // java.lang.IllegalThreadStateException: Thread group still contains threads: Test group
           // 2) t04
diff --git a/src/test/java/com/android/tools/r8/R8RunArtTestsTest.java b/src/test/java/com/android/tools/r8/R8RunArtTestsTest.java
index bf409d8..32c0175 100644
--- a/src/test/java/com/android/tools/r8/R8RunArtTestsTest.java
+++ b/src/test/java/com/android/tools/r8/R8RunArtTestsTest.java
@@ -145,10 +145,6 @@
           .put("974-verify-interface-super", AndroidApiLevel.N)
           // Desugaring of interface private methods is not yet supported.
           .put("975-iface-private", AndroidApiLevel.N)
-          // The extended check for overlapping long registers cause this to run out of registers.
-          .put("421-large-frame", AndroidApiLevel.N)
-          // The extended check for overlapping long registers cause this to run out of registers.
-          .put("551-checker-shifter-operand", AndroidApiLevel.N)
           .build();
 
   // Tests that timeout when run with Art.
diff --git a/src/test/java/com/android/tools/r8/shaking/ProguardConfigurationParserTest.java b/src/test/java/com/android/tools/r8/shaking/ProguardConfigurationParserTest.java
index 5f6a5cc..84f6a08 100644
--- a/src/test/java/com/android/tools/r8/shaking/ProguardConfigurationParserTest.java
+++ b/src/test/java/com/android/tools/r8/shaking/ProguardConfigurationParserTest.java
@@ -37,6 +37,7 @@
 import java.util.Collections;
 import java.util.List;
 import org.junit.Before;
+import org.junit.Ignore;
 import org.junit.Test;
 
 public class ProguardConfigurationParserTest extends TestBase {
@@ -544,7 +545,7 @@
     assertTrue(
         config.getAdaptClassStrings().matches(dexItemFactory.createType("Lboobaz;")));
     assertTrue(
-        config.getAdaptClassStrings().matches(dexItemFactory.createType("Lboobaz;")));
+        config.getAdaptClassStrings().matches(dexItemFactory.createType("Lboobar;")));
     assertTrue(
         config.getAdaptClassStrings().matches(dexItemFactory.createType("Lfoobar;")));
   }
@@ -561,12 +562,47 @@
     assertTrue(
         config.getAdaptClassStrings().matches(dexItemFactory.createType("Lboobaz;")));
     assertTrue(
-        config.getAdaptClassStrings().matches(dexItemFactory.createType("Lboobaz;")));
+        config.getAdaptClassStrings().matches(dexItemFactory.createType("Lboobar;")));
     assertTrue(
         config.getAdaptClassStrings().matches(dexItemFactory.createType("Lfoobar;")));
   }
 
   @Test
+  public void testAdaptClassStringsNthWildcard() throws Exception {
+    DexItemFactory dexItemFactory = new DexItemFactory();
+    ProguardConfigurationParser parser =
+        new ProguardConfigurationParser(dexItemFactory, reporter);
+    String wildcard = "-adaptclassstrings *foo<1>";
+    parser.parse(createConfigurationForTesting(ImmutableList.of(wildcard)));
+    verifyParserEndsCleanly();
+    ProguardConfiguration config = parser.getConfig();
+    assertFalse(
+        config.getAdaptClassStrings().matches(dexItemFactory.createType("Lfoobar;")));
+    assertFalse(
+        config.getAdaptClassStrings().matches(dexItemFactory.createType("Lboofoobar;")));
+    // TODO(b/73800755): Use <n> while matching class name list.
+    //assertTrue(
+    //    config.getAdaptClassStrings().matches(dexItemFactory.createType("Lboofooboo;")));
+  }
+
+  @Ignore("b/73800755: verify the range of <n>")
+  @Test
+  public void testAdaptClassStringsNthWildcard_outOfRange() throws Exception {
+    Path proguardConfig = writeTextToTempFile(
+        "-adaptclassstrings *foo<2>"
+    );
+    try {
+      ProguardConfigurationParser parser =
+          new ProguardConfigurationParser(new DexItemFactory(), reporter);
+      parser.parse(proguardConfig);
+      fail();
+    } catch (AbortException e) {
+      checkDiagnostic(handler.errors, proguardConfig, 1, 1,
+          "wildcard", "out", "range");
+    }
+  }
+
+  @Test
   public void testIdentifierNameString() throws Exception {
     ProguardConfigurationParser parser =
         new ProguardConfigurationParser(new DexItemFactory(), reporter);
@@ -1173,6 +1209,43 @@
   }
 
   @Test
+  public void parse_if_nthWildcard() throws Exception {
+    Path proguardConfig = writeTextToTempFile(
+        "-if class **$R**",
+        "-keep class **$D<2>"  // <2> corresponds to the 2nd ** in -if rule.
+    );
+    ProguardConfigurationParser parser =
+        new ProguardConfigurationParser(new DexItemFactory(), reporter);
+    parser.parse(proguardConfig);
+    checkDiagnostic(handler.warnings, proguardConfig, 1, 1,
+        "Ignoring", "-if");
+    ProguardConfiguration config = parser.getConfig();
+    assertEquals(1, config.getRules().size());
+    ProguardIfRule if0 = (ProguardIfRule) config.getRules().get(0);
+    assertEquals("**$R**", if0.getClassNames().toString());
+    assertEquals(ProguardKeepRuleType.KEEP, if0.subsequentRule.getType());
+    assertEquals("**$D<2>", if0.subsequentRule.getClassNames().toString());
+  }
+
+  @Ignore("b/73800755: verify the range of <n>")
+  @Test
+  public void parse_if_nthWildcard_outOfRange() throws Exception {
+    Path proguardConfig = writeTextToTempFile(
+        "-if class **$R**",
+        "-keep class **D<4>"  // There are 3 ** in this rule.
+    );
+    try {
+      ProguardConfigurationParser parser =
+          new ProguardConfigurationParser(new DexItemFactory(), reporter);
+      parser.parse(proguardConfig);
+      fail();
+    } catch (AbortException e) {
+      checkDiagnostic(handler.errors, proguardConfig, 1, 1,
+          "wildcard", "out", "range");
+    }
+  }
+
+  @Test
   public void parse_if_if() throws Exception {
     Path proguardConfig = writeTextToTempFile(
         "-if   class **$$ModuleAdapter",
diff --git a/third_party/kotlin.tar.gz.sha1 b/third_party/kotlin.tar.gz.sha1
index e55712d..40f26fa 100644
--- a/third_party/kotlin.tar.gz.sha1
+++ b/third_party/kotlin.tar.gz.sha1
@@ -1 +1 @@
-6dc49791e5fcf4318ae5246eacc73718180508ce
\ No newline at end of file
+4b18d827485f53990ad47b81db2a025abaa325d1
\ No newline at end of file