[llvm] [NFC][Coverage] Do not use recursion for GCOV propagateCounts. (PR #68455)

Fangrui Song via llvm-commits llvm-commits at lists.llvm.org
Tue Oct 10 21:49:39 PDT 2023


================
@@ -366,24 +366,80 @@ GCOVBlock &GCOVFunction::getExitBlock() const {
 // outgoing edge counts by Kirchoff's circuit law. If the unmeasured arcs form a
 // spanning tree, the count for each unmeasured arc (GCOV_ARC_ON_TREE) can be
 // uniquely identified.
-uint64_t GCOVFunction::propagateCounts(const GCOVBlock &v, GCOVArc *pred) {
-  // If GCOV_ARC_ON_TREE edges do form a tree, visited is not needed; otherwise
-  // this prevents infinite recursion.
-  if (!visited.insert(&v).second)
-    return 0;
+uint64_t GCOVFunction::propagateCounts(const GCOVBlock &V, GCOVArc *Pred) {
+  struct StackElem {
+    const GCOVBlock &Block;
+    GCOVArc *Pred;
+    size_t PrevStackElemIdx;
+    uint64_t Excess = 0;
+    bool IsInSrcs = true;
+    bool Visited = false;
+  };
+
+  std::vector<StackElem> BlockStack;
+  BlockStack.push_back({V, nullptr, 0});
+
+  while (!BlockStack.empty()) {
+    StackElem &Current = BlockStack.back();
+    size_t Idx = BlockStack.size() - 1;
+
+    if (!Current.Visited) {
+      Current.Visited = true;
+      // If GCOV_ARC_ON_TREE edges do form a tree, visited is not needed;
+      // otherwise this prevents infinite recursion.
+      if (!visited.insert(&Current.Block).second) {
+        BlockStack.pop_back();
+        continue;
+      }
+
+      std::vector<StackElem> ChildBlockStack;
+      for (GCOVArc *E : Current.Block.srcs()) {
+        if (E != Current.Pred) {
+          if (E->onTree()) {
+            ChildBlockStack.push_back({E->src, E, Idx});
+          } else {
+            Current.Excess += E->count;
+          }
+        }
+      }
+
+      for (GCOVArc *E : Current.Block.dsts()) {
+        if (E != Current.Pred) {
+          if (E->onTree()) {
+            ChildBlockStack.push_back({E->dst, E, Idx, 0, false});
+          } else {
+            Current.Excess -= E->count;
+          }
+        }
+      }
+
+      for (auto &E : ChildBlockStack)
+        BlockStack.emplace_back(std::move(E));
+    } else {
+      // second visit, ready to pop out the value
+      // Excess is already calculated from the children
+      if (static_cast<int64_t>(Current.Excess) < 0)
+        Current.Excess = -Current.Excess;
 
-  uint64_t excess = 0;
-  for (GCOVArc *e : v.srcs())
-    if (e != pred)
-      excess += e->onTree() ? propagateCounts(e->src, e) : e->count;
-  for (GCOVArc *e : v.dsts())
-    if (e != pred)
-      excess -= e->onTree() ? propagateCounts(e->dst, e) : e->count;
-  if (int64_t(excess) < 0)
-    excess = -excess;
-  if (pred)
-    pred->count = excess;
-  return excess;
+      if (Idx == 0) {
----------------
MaskRay wrote:

drop braces https://llvm.org/docs/CodingStandards.html#don-t-use-braces-on-simple-single-statement-bodies-of-if-else-loop-statements

https://github.com/llvm/llvm-project/pull/68455


More information about the llvm-commits mailing list