Log type propagation for selected fields/parameters

Bug: b/338885156
Change-Id: I9332e40d20f9435c4962a26ddbcd4ba673b405ad
diff --git a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/BottomArrayTypeValueState.java b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/BottomArrayTypeValueState.java
index dafacba..19f1a3d 100644
--- a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/BottomArrayTypeValueState.java
+++ b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/BottomArrayTypeValueState.java
@@ -46,4 +46,9 @@
     }
     return new ConcreteArrayTypeValueState(nullability, concreteState.copyInFlow());
   }
+
+  @Override
+  public String toString() {
+    return "⊥(ARRAY)";
+  }
 }
diff --git a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/BottomClassTypeValueState.java b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/BottomClassTypeValueState.java
index b44361c..6eca904 100644
--- a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/BottomClassTypeValueState.java
+++ b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/BottomClassTypeValueState.java
@@ -64,4 +64,9 @@
       return joinedDynamicType;
     }
   }
+
+  @Override
+  public String toString() {
+    return "⊥(CLASS)";
+  }
 }
diff --git a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/BottomPrimitiveTypeValueState.java b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/BottomPrimitiveTypeValueState.java
index 67c0736..ba50708 100644
--- a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/BottomPrimitiveTypeValueState.java
+++ b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/BottomPrimitiveTypeValueState.java
@@ -37,4 +37,9 @@
     assert inState.isPrimitiveState();
     return cloner.mutableCopy(inState);
   }
+
+  @Override
+  public String toString() {
+    return "⊥(PRIMITIVE)";
+  }
 }
diff --git a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/BottomReceiverValueState.java b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/BottomReceiverValueState.java
index 9a9bb39..d027231 100644
--- a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/BottomReceiverValueState.java
+++ b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/BottomReceiverValueState.java
@@ -46,4 +46,9 @@
     }
     return new ConcreteReceiverValueState(dynamicType, concreteState.copyInFlow());
   }
+
+  @Override
+  public String toString() {
+    return "⊥(RECEIVER)";
+  }
 }
diff --git a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/ConcreteArrayTypeValueState.java b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/ConcreteArrayTypeValueState.java
index 6e17619..053d921 100644
--- a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/ConcreteArrayTypeValueState.java
+++ b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/ConcreteArrayTypeValueState.java
@@ -133,4 +133,10 @@
     nullability = nullability.join(otherNullability);
     return nullability != oldNullability;
   }
+
+  @Override
+  public String toString() {
+    assert !hasInFlow();
+    return "ArrayState(" + nullability + ")";
+  }
 }
diff --git a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/ConcreteClassTypeValueState.java b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/ConcreteClassTypeValueState.java
index f689576..6378112 100644
--- a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/ConcreteClassTypeValueState.java
+++ b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/ConcreteClassTypeValueState.java
@@ -186,4 +186,10 @@
   public ConcreteClassTypeValueState withDynamicType(DynamicType dynamicType) {
     return new ConcreteClassTypeValueState(abstractValue, dynamicType, copyInFlow());
   }
+
+  @Override
+  public String toString() {
+    assert !hasInFlow();
+    return "ClassState(type: " + dynamicType + ", value: " + abstractValue + ")";
+  }
 }
diff --git a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/ConcretePrimitiveTypeValueState.java b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/ConcretePrimitiveTypeValueState.java
index 816e303..dedf78d 100644
--- a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/ConcretePrimitiveTypeValueState.java
+++ b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/ConcretePrimitiveTypeValueState.java
@@ -126,4 +126,10 @@
   public ConcretePrimitiveTypeValueState asPrimitiveState() {
     return this;
   }
+
+  @Override
+  public String toString() {
+    assert !hasInFlow();
+    return "PrimitiveState(" + abstractValue + ")";
+  }
 }
diff --git a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/ConcreteReceiverValueState.java b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/ConcreteReceiverValueState.java
index 2d73c7b..abc4b6d 100644
--- a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/ConcreteReceiverValueState.java
+++ b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/ConcreteReceiverValueState.java
@@ -144,4 +144,10 @@
   public ConcreteReceiverValueState withDynamicType(DynamicType dynamicType) {
     return new ConcreteReceiverValueState(dynamicType, copyInFlow());
   }
+
+  @Override
+  public String toString() {
+    assert !hasInFlow();
+    return "ReceiverState(" + dynamicType + ")";
+  }
 }
diff --git a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/UnknownValueState.java b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/UnknownValueState.java
index 843e64d..dbc2069 100644
--- a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/UnknownValueState.java
+++ b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/UnknownValueState.java
@@ -46,4 +46,9 @@
       Action onChangedAction) {
     return this;
   }
+
+  @Override
+  public String toString() {
+    return "⊤";
+  }
 }
diff --git a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/propagation/InFlowPropagator.java b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/propagation/InFlowPropagator.java
index 039d486..67f7f65 100644
--- a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/propagation/InFlowPropagator.java
+++ b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/propagation/InFlowPropagator.java
@@ -173,6 +173,7 @@
     assert !successorNode.isUnknown();
     NonEmptyValueState stateToPropagate = narrowUnknownState(node, successorNode);
     if (stateToPropagate.isUnknown()) {
+      assert InFlowPropagatorDebugUtils.logPropagateUnknown(node, successorNode);
       successorNode.clearPredecessors(node);
       successorNode.setStateToUnknown();
       successorNode.addToWorkList(worklist);
@@ -235,6 +236,8 @@
           FlowGraphStateProvider.create(flowGraph, transferFunction);
       ValueState transferState =
           transferFunction.apply(appView, flowGraphStateProvider, stateToPropagate);
+      ValueState oldSuccessorStateForDebugging =
+          successorNode.getDebug() ? successorNode.getState().mutableCopy() : null;
       if (transferState.isBottom()) {
         // Nothing to propagate.
       } else if (transferState.isUnknown()) {
@@ -246,6 +249,15 @@
         successorNode.addState(
             appView, inState, inStaticType, () -> successorNode.addToWorkList(worklist));
       }
+
+      assert InFlowPropagatorDebugUtils.logPropagateConcrete(
+          node,
+          successorNode,
+          state,
+          transferFunction,
+          transferState,
+          oldSuccessorStateForDebugging);
+
       // If this successor has become unknown, there is no point in continuing to propagate
       // flow to it from any of its predecessors. We therefore clear the predecessors to
       // improve performance of the fixpoint computation.
diff --git a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/propagation/InFlowPropagatorDebugUtils.java b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/propagation/InFlowPropagatorDebugUtils.java
index 1ec6a85..d7f38d8 100644
--- a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/propagation/InFlowPropagatorDebugUtils.java
+++ b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/propagation/InFlowPropagatorDebugUtils.java
@@ -5,6 +5,9 @@
 
 import com.android.tools.r8.graph.ProgramField;
 import com.android.tools.r8.graph.ProgramMethod;
+import com.android.tools.r8.optimize.argumentpropagation.codescanner.AbstractFunction;
+import com.android.tools.r8.optimize.argumentpropagation.codescanner.ConcreteValueState;
+import com.android.tools.r8.optimize.argumentpropagation.codescanner.ValueState;
 import com.android.tools.r8.utils.WorkList;
 import java.util.List;
 
@@ -59,4 +62,40 @@
           }
         });
   }
+
+  public static boolean logPropagateUnknown(FlowGraphNode node, FlowGraphNode successorNode) {
+    if (successorNode.getDebug()) {
+      log("PROPAGATE UNKNOWN", "FROM: " + node, "TO: " + successorNode);
+    }
+    return true;
+  }
+
+  public static boolean logPropagateConcrete(
+      FlowGraphNode node,
+      FlowGraphNode successorNode,
+      ConcreteValueState nodeStateAfterNarrowing,
+      AbstractFunction transferFunction,
+      ValueState transferState,
+      ValueState oldSuccessorState) {
+    if (successorNode.getDebug()) {
+      log(
+          "PROPAGATE CONCRETE",
+          "FROM: " + node,
+          "TO: " + successorNode,
+          "NODE STATE: " + node.getState(),
+          "NODE STATE (NARROWED): " + nodeStateAfterNarrowing,
+          "TRANSFER FN: " + transferFunction,
+          "TRANSFER STATE: " + transferState,
+          "SUCCESSOR STATE: " + oldSuccessorState,
+          "SUCCESSOR STATE (NEW): " + successorNode.getState());
+    }
+    return true;
+  }
+
+  private static synchronized void log(String... lines) {
+    System.out.println("====================================");
+    for (String line : lines) {
+      System.out.println(line);
+    }
+  }
 }