Add mechanism for setting debug flag on relevant field/parameter nodes

Bug: b/338885156
Change-Id: I176c0a90d3803f00296db2fdfe2d87eaeda31313
diff --git a/src/main/java/com/android/tools/r8/annotations/AssumeNoSideEffects.java b/src/main/java/com/android/tools/r8/annotations/AssumeNoSideEffects.java
new file mode 100644
index 0000000..37bcebd
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/annotations/AssumeNoSideEffects.java
@@ -0,0 +1,13 @@
+// Copyright (c) 2024, 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 com.android.tools.r8.annotations;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Retention(RetentionPolicy.CLASS)
+@Target(ElementType.METHOD)
+public @interface AssumeNoSideEffects {}
diff --git a/src/main/java/com/android/tools/r8/annotations/CheckDiscard.java b/src/main/java/com/android/tools/r8/annotations/CheckDiscard.java
new file mode 100644
index 0000000..89f9b4f
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/annotations/CheckDiscard.java
@@ -0,0 +1,13 @@
+// Copyright (c) 2024, 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 com.android.tools.r8.annotations;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Retention(RetentionPolicy.CLASS)
+@Target(ElementType.FIELD)
+public @interface CheckDiscard {}
diff --git a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/propagation/FlowGraph.java b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/propagation/FlowGraph.java
index 01a65d2..e0e8d9f 100644
--- a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/propagation/FlowGraph.java
+++ b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/propagation/FlowGraph.java
@@ -67,6 +67,12 @@
     fieldNodes.values().forEach(consumer);
   }
 
+  public void forEachParameterNode(Consumer<? super FlowGraphParameterNode> consumer) {
+    parameterNodes
+        .values()
+        .forEach(parameterNodesForMethod -> parameterNodesForMethod.values().forEach(consumer));
+  }
+
   @Override
   public void forEachNeighbor(FlowGraphNode node, Consumer<? super FlowGraphNode> consumer) {
     node.getPredecessors().forEach(consumer);
diff --git a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/propagation/FlowGraphNode.java b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/propagation/FlowGraphNode.java
index 5649bbc..ba8f33b 100644
--- a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/propagation/FlowGraphNode.java
+++ b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/propagation/FlowGraphNode.java
@@ -5,6 +5,8 @@
 
 import static com.android.tools.r8.utils.MapUtils.ignoreKey;
 
+import com.android.tools.r8.annotations.AssumeNoSideEffects;
+import com.android.tools.r8.annotations.CheckDiscard;
 import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.DexType;
 import com.android.tools.r8.optimize.argumentpropagation.codescanner.AbstractFunction;
@@ -27,6 +29,8 @@
   private final Set<FlowGraphNode> predecessors = Sets.newIdentityHashSet();
   private final Map<FlowGraphNode, Set<AbstractFunction>> successors = new IdentityHashMap<>();
 
+  @CheckDiscard private boolean debug = false;
+
   private boolean inWorklist = true;
 
   void addState(
@@ -49,10 +53,19 @@
     }
   }
 
+  boolean getDebug() {
+    return debug;
+  }
+
   abstract ValueState getState();
 
   abstract DexType getStaticType();
 
+  @AssumeNoSideEffects
+  void setDebug(boolean debug) {
+    this.debug = debug;
+  }
+
   abstract void setState(ValueState valueState);
 
   void setStateToUnknown() {
diff --git a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/propagation/FlowGraphParameterNode.java b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/propagation/FlowGraphParameterNode.java
index 242faa1..555e6c8 100644
--- a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/propagation/FlowGraphParameterNode.java
+++ b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/propagation/FlowGraphParameterNode.java
@@ -9,7 +9,7 @@
 import com.android.tools.r8.optimize.argumentpropagation.codescanner.MethodState;
 import com.android.tools.r8.optimize.argumentpropagation.codescanner.ValueState;
 
-class FlowGraphParameterNode extends FlowGraphNode {
+public class FlowGraphParameterNode extends FlowGraphNode {
 
   private final ProgramMethod method;
   private final MethodState methodState;
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 4404d74..039d486 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
@@ -62,6 +62,7 @@
     // Compute strongly connected components so that we can compute the fixpoint of multiple flow
     // graphs in parallel.
     List<FlowGraph> flowGraphs = computeStronglyConnectedFlowGraphs();
+    assert InFlowPropagatorDebugUtils.setEnableLoggingBits(flowGraphs);
     processFlowGraphs(flowGraphs, executorService);
 
     // Account for the fact that fields that are read before they are written also needs to include
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
new file mode 100644
index 0000000..1ec6a85
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/propagation/InFlowPropagatorDebugUtils.java
@@ -0,0 +1,62 @@
+// Copyright (c) 2024, 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 com.android.tools.r8.optimize.argumentpropagation.propagation;
+
+import com.android.tools.r8.graph.ProgramField;
+import com.android.tools.r8.graph.ProgramMethod;
+import com.android.tools.r8.utils.WorkList;
+import java.util.List;
+
+public class InFlowPropagatorDebugUtils {
+
+  // Return true for a given field here to enable extensive logging.
+  @SuppressWarnings("UnusedVariable")
+  private static boolean isLoggingEnabledFor(ProgramField field) {
+    return false;
+  }
+
+  // Return true for a given method parameter here to enable extensive logging.
+  @SuppressWarnings("UnusedVariable")
+  private static boolean isLoggingEnabledFor(ProgramMethod method, int parameterIndex) {
+    return false;
+  }
+
+  public static boolean setEnableLoggingBits(List<FlowGraph> flowGraphs) {
+    for (FlowGraph flowGraph : flowGraphs) {
+      setEnableLoggingBits(flowGraph);
+    }
+    return true;
+  }
+
+  private static void setEnableLoggingBits(FlowGraph flowGraph) {
+    // Set the debug flag for the fields/parameters that we want to debug.
+    flowGraph.forEachFieldNode(node -> node.setDebug(isLoggingEnabledFor(node.getField())));
+    flowGraph.forEachParameterNode(
+        node -> node.setDebug(isLoggingEnabledFor(node.getMethod(), node.getParameterIndex())));
+
+    // Create a worklist containing these fields/parameters.
+    WorkList<FlowGraphNode> worklist = WorkList.newIdentityWorkList();
+    flowGraph.forEachNode(
+        node -> {
+          if (node.getDebug()) {
+            worklist.addIfNotSeen(node);
+          }
+        });
+
+    // Propagate the debug flag to all (transitive) predecessors to enable extensive logging for
+    // these nodes as well.
+    worklist.process(
+        node -> {
+          assert node.getDebug();
+          for (FlowGraphNode predecessor : node.getPredecessors()) {
+            if (predecessor.getDebug()) {
+              assert worklist.isSeen(predecessor);
+              continue;
+            }
+            predecessor.setDebug(true);
+            worklist.addIfNotSeen(predecessor);
+          }
+        });
+  }
+}
diff --git a/src/main/keep.txt b/src/main/keep.txt
index 83f70b1..5faed98 100644
--- a/src/main/keep.txt
+++ b/src/main/keep.txt
@@ -27,5 +27,13 @@
 # TODO(b/176783536): Avoid need to use -dontwarn.
 -include dontwarn.txt
 
+# Annotations for stripping debug code from r8lib.
+-assumenosideeffects class * {
+  @com.android.tools.r8.annotations.AssumeNoSideEffects <methods>;
+}
+-checkdiscard class * {
+  @com.android.tools.r8.annotations.CheckDiscard <fields>;
+}
+
 # Test in this class is using the class name to fing the original .java file.
 -keep class com.android.tools.r8.ir.desugar.varhandle.VarHandleDesugaringMethods