Minor updates and misc. APIs for argument propagation

Change-Id: If3e9f7138dea0a1b3c5f5497203b156e3ff7e6a9
diff --git a/src/main/java/com/android/tools/r8/graph/ImmediateProgramSubtypingInfo.java b/src/main/java/com/android/tools/r8/graph/ImmediateProgramSubtypingInfo.java
index ac08e3f..fa003ea 100644
--- a/src/main/java/com/android/tools/r8/graph/ImmediateProgramSubtypingInfo.java
+++ b/src/main/java/com/android/tools/r8/graph/ImmediateProgramSubtypingInfo.java
@@ -63,6 +63,24 @@
         });
   }
 
+  public void forEachImmediateProgramSuperClass(
+      DexProgramClass clazz, Consumer<? super DexProgramClass> consumer) {
+    forEachImmediateProgramSuperClassMatching(clazz, alwaysTrue(), consumer);
+  }
+
+  public void forEachImmediateProgramSuperClassMatching(
+      DexProgramClass clazz,
+      Predicate<? super DexProgramClass> predicate,
+      Consumer<? super DexProgramClass> consumer) {
+    clazz.forEachImmediateSupertype(
+        supertype -> {
+          DexProgramClass superclass = asProgramClassOrNull(appView.definitionFor(supertype));
+          if (superclass != null && predicate.test(superclass)) {
+            consumer.accept(superclass);
+          }
+        });
+  }
+
   public void forEachImmediateSubClass(
       DexProgramClass clazz, Consumer<? super DexProgramClass> consumer) {
     forEachImmediateSubClassMatching(clazz, alwaysTrue(), consumer);
diff --git a/src/main/java/com/android/tools/r8/graph/MethodResolutionResult.java b/src/main/java/com/android/tools/r8/graph/MethodResolutionResult.java
index 9f33913..f1e8ae1 100644
--- a/src/main/java/com/android/tools/r8/graph/MethodResolutionResult.java
+++ b/src/main/java/com/android/tools/r8/graph/MethodResolutionResult.java
@@ -98,6 +98,10 @@
     return null;
   }
 
+  public ProgramMethod getResolvedProgramMethod() {
+    return null;
+  }
+
   @Override
   public DexClassAndMethod getResolutionPair() {
     return null;
@@ -192,6 +196,7 @@
       return resolvedMethod;
     }
 
+    @Override
     public ProgramMethod getResolvedProgramMethod() {
       return resolvedHolder.isProgramClass()
           ? new ProgramMethod(resolvedHolder.asProgramClass(), resolvedMethod)
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/type/ClassTypeElement.java b/src/main/java/com/android/tools/r8/ir/analysis/type/ClassTypeElement.java
index 083c27f..c171e7d 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/type/ClassTypeElement.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/type/ClassTypeElement.java
@@ -140,6 +140,11 @@
   }
 
   @Override
+  public ClassTypeElement joinNullability(Nullability nullability) {
+    return getOrCreateVariant(nullability().join(nullability));
+  }
+
+  @Override
   public String toString() {
     StringBuilder builder = new StringBuilder();
     builder.append(nullability);
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/type/Nullability.java b/src/main/java/com/android/tools/r8/ir/analysis/type/Nullability.java
index 26b9030..e45ac9a 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/type/Nullability.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/type/Nullability.java
@@ -29,6 +29,10 @@
 
   private Nullability() {}
 
+  public boolean isBottom() {
+    return this == BOTTOM;
+  }
+
   public boolean isDefinitelyNull() {
     return this == DEFINITELY_NULL;
   }
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/type/ReferenceTypeElement.java b/src/main/java/com/android/tools/r8/ir/analysis/type/ReferenceTypeElement.java
index c150cfd..5a82ac4 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/type/ReferenceTypeElement.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/type/ReferenceTypeElement.java
@@ -78,6 +78,10 @@
     return getOrCreateVariant(nullability.meet(Nullability.definitelyNotNull()));
   }
 
+  public TypeElement asDefinitelyNull() {
+    return getOrCreateVariant(Nullability.definitelyNull());
+  }
+
   public TypeElement asDefinitelyNotNull() {
     return getOrCreateVariant(Nullability.definitelyNotNull());
   }
@@ -86,6 +90,10 @@
     return getOrCreateVariant(Nullability.maybeNull());
   }
 
+  public ReferenceTypeElement joinNullability(Nullability nullability) {
+    return getOrCreateVariant(nullability().join(nullability));
+  }
+
   @Override
   public boolean isReferenceType() {
     return true;
diff --git a/src/main/java/com/android/tools/r8/ir/code/Assume.java b/src/main/java/com/android/tools/r8/ir/code/Assume.java
index 3a51eec..f25c73b 100644
--- a/src/main/java/com/android/tools/r8/ir/code/Assume.java
+++ b/src/main/java/com/android/tools/r8/ir/code/Assume.java
@@ -311,6 +311,8 @@
     }
 
     public boolean verifyCorrectnessOfValues(Value dest, Value src, AppView<?> appView) {
+      assert !dynamicUpperBoundType.isBottom();
+      assert !dynamicUpperBoundType.isTop();
       assert dynamicUpperBoundType.lessThanOrEqualUpToNullability(src.getType(), appView);
       return true;
     }
diff --git a/src/main/java/com/android/tools/r8/ir/code/Value.java b/src/main/java/com/android/tools/r8/ir/code/Value.java
index ce8efd1..643fdcb 100644
--- a/src/main/java/com/android/tools/r8/ir/code/Value.java
+++ b/src/main/java/com/android/tools/r8/ir/code/Value.java
@@ -1156,7 +1156,7 @@
       DexType type = definition.asNewInstance().clazz;
       DexClass clazz = appView.definitionFor(type);
       if (clazz != null && !clazz.isInterface()) {
-        return ClassTypeElement.create(type, definitelyNotNull(), appView);
+        return TypeElement.fromDexType(type, definitelyNotNull(), appView).asClassType();
       }
       return 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 c2572cf..8595ecd 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
@@ -409,11 +409,11 @@
     reportNestDesugarDependencies();
     clearNestAttributes();
 
-    application = commitPendingSyntheticItems(appView, application);
+    application = commitPendingSyntheticItemsD8(appView, application);
 
     postProcessingDesugaringForD8(methodProcessor, executor);
 
-    application = commitPendingSyntheticItems(appView, application);
+    application = commitPendingSyntheticItemsD8(appView, application);
 
     // Build a new application with jumbo string info,
     Builder<?> builder = application.builder().setHighestSortingString(highestSortingString);
@@ -432,7 +432,7 @@
             appView.appInfo().getMainDexInfo()));
   }
 
-  private DexApplication commitPendingSyntheticItems(
+  private DexApplication commitPendingSyntheticItemsD8(
       AppView<AppInfo> appView, DexApplication application) {
     if (appView.getSyntheticItems().hasPendingSyntheticClasses()) {
       appView.setAppInfo(
@@ -444,6 +444,15 @@
     return application;
   }
 
+  private static void commitPendingSyntheticItemsR8(AppView<AppInfoWithLiveness> appView) {
+    if (appView.getSyntheticItems().hasPendingSyntheticClasses()) {
+      appView.setAppInfo(
+          appView
+              .appInfo()
+              .rebuildWithLiveness(appView.getSyntheticItems().commit(appView.appInfo().app())));
+    }
+  }
+
   public void l8ClassSynthesis(
       ExecutorService executorService,
       CfL8ClassSynthesizerEventConsumer l8ClassSynthesizerEventConsumer)
@@ -729,6 +738,9 @@
     // lenses with code rewriting are added.
     appView.clearCodeRewritings();
 
+    // Commit synthetics from the primary optimization pass.
+    commitPendingSyntheticItemsR8(appView);
+
     // Analyze the data collected by the argument propagator, use the analysis result to update
     // the parameter optimization infos, and rewrite the application.
     appView.withArgumentPropagator(
@@ -800,12 +812,8 @@
 
     // Commit synthetics before creating a builder (otherwise the builder will not include the
     // synthetics.)
-    if (appView.getSyntheticItems().hasPendingSyntheticClasses()) {
-      appView.setAppInfo(
-          appView
-              .appInfo()
-              .rebuildWithLiveness(appView.getSyntheticItems().commit(appView.appInfo().app())));
-    }
+    commitPendingSyntheticItemsR8(appView);
+
     // Build a new application with jumbo string info.
     Builder<?> builder = appView.appInfo().app().builder();
     builder.setHighestSortingString(highestSortingString);
@@ -1541,7 +1549,7 @@
         printMethod(code, "IR after idempotent function call canonicalization (SSA)", previous);
 
     // Insert code to log arguments if requested.
-    if (options.methodMatchesLogArgumentsFilter(method)) {
+    if (options.methodMatchesLogArgumentsFilter(method) && !method.isProcessed()) {
       codeRewriter.logArgumentTypes(method, code);
       assert code.isConsistentSSA();
     }
diff --git a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/ArgumentPropagatorOptimizationInfoPopulator.java b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/ArgumentPropagatorOptimizationInfoPopulator.java
index 13455ba..dbec312 100644
--- a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/ArgumentPropagatorOptimizationInfoPopulator.java
+++ b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/ArgumentPropagatorOptimizationInfoPopulator.java
@@ -80,10 +80,7 @@
     WorkList<DexProgramClass> worklist = WorkList.newIdentityWorkList(clazz);
     while (worklist.hasNext()) {
       DexProgramClass current = worklist.next();
-      immediateSubtypingInfo.forEachImmediateSuperClassMatching(
-          current,
-          (supertype, superclass) -> superclass != null && superclass.isProgramClass(),
-          (supertype, superclass) -> worklist.addIfNotSeen(superclass.asProgramClass()));
+      immediateSubtypingInfo.forEachImmediateProgramSuperClass(current, worklist::addIfNotSeen);
       worklist.addIfNotSeen(immediateSubtypingInfo.getSubclasses(current));
     }
     return worklist.getSeenSet();
diff --git a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/ArgumentPropagatorUnoptimizableMethods.java b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/ArgumentPropagatorUnoptimizableMethods.java
index 9a478bd..36dae85 100644
--- a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/ArgumentPropagatorUnoptimizableMethods.java
+++ b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/ArgumentPropagatorUnoptimizableMethods.java
@@ -137,12 +137,11 @@
           unoptimizableInterfaceMethods.computeIfAbsent(clazz, ignoreKey(Sets::newIdentityHashSet));
 
       // Add the unoptimizable interface methods from the parent interfaces.
-      immediateSubtypingInfo.forEachImmediateSuperClassMatching(
+      immediateSubtypingInfo.forEachImmediateProgramSuperClass(
           clazz,
-          (supertype, superclass) -> superclass != null && superclass.isProgramClass(),
-          (supertype, superclass) ->
+          superclass ->
               unoptimizableInterfaceMethodsForClass.addAll(
-                  unoptimizableInterfaceMethods.get(superclass.asProgramClass())));
+                  unoptimizableInterfaceMethods.get(superclass)));
 
       // Propagate the unoptimizable interface methods of this interface to all immediate
       // (non-interface) subclasses.
@@ -221,12 +220,9 @@
           unoptimizableMethods.computeIfAbsent(clazz, ignoreKey(DexMethodSignatureSet::create));
 
       // Add the unoptimizable methods from the parent classes.
-      immediateSubtypingInfo.forEachImmediateSuperClassMatching(
+      immediateSubtypingInfo.forEachImmediateProgramSuperClass(
           clazz,
-          (supertype, superclass) -> superclass != null && superclass.isProgramClass(),
-          (supertype, superclass) ->
-              unoptimizableMethodsForClass.addAll(
-                  unoptimizableMethods.get(superclass.asProgramClass())));
+          superclass -> unoptimizableMethodsForClass.addAll(unoptimizableMethods.get(superclass)));
 
       // Disable argument propagation for the unoptimizable methods of this class.
       clazz.forEachProgramVirtualMethod(
diff --git a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/propagation/InterfaceMethodArgumentPropagator.java b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/propagation/InterfaceMethodArgumentPropagator.java
index 99a0bac..69cbb7b 100644
--- a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/propagation/InterfaceMethodArgumentPropagator.java
+++ b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/propagation/InterfaceMethodArgumentPropagator.java
@@ -82,12 +82,11 @@
       DexProgramClass interfaceDefinition) {
     // Join the state for all parent interfaces into a fresh state created for this interface.
     MethodStateCollectionBySignature interfaceState = MethodStateCollectionBySignature.create();
-    immediateSubtypingInfo.forEachImmediateSuperClassMatching(
+    immediateSubtypingInfo.forEachImmediateProgramSuperClass(
         interfaceDefinition,
-        (supertype, superclass) -> superclass != null && superclass.isProgramClass(),
-        (supertype, superclass) -> {
+        superclass -> {
           MethodStateCollectionBySignature implementedInterfaceState =
-              methodStatesToPropagate.get(superclass.asProgramClass());
+              methodStatesToPropagate.get(superclass);
           assert implementedInterfaceState != null;
           interfaceState.addMethodStates(appView, implementedInterfaceState);
         });
diff --git a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/propagation/VirtualDispatchMethodArgumentPropagator.java b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/propagation/VirtualDispatchMethodArgumentPropagator.java
index 14c58f8..771a718 100644
--- a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/propagation/VirtualDispatchMethodArgumentPropagator.java
+++ b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/propagation/VirtualDispatchMethodArgumentPropagator.java
@@ -46,10 +46,8 @@
 
     PropagationState(DexProgramClass clazz) {
       // Join the argument information from each of the super types.
-      immediateSubtypingInfo.forEachImmediateSuperClassMatching(
-          clazz,
-          (supertype, superclass) -> superclass != null && superclass.isProgramClass(),
-          (supertype, superclass) -> addParentState(clazz, superclass.asProgramClass()));
+      immediateSubtypingInfo.forEachImmediateProgramSuperClass(
+          clazz, superclass -> addParentState(clazz, superclass));
     }
 
     // TODO(b/190154391): This currently copies the state of the superclass into its immediate