diff options
Diffstat (limited to 'contrib/llvm-project/llvm/lib/ProfileData/GCOV.cpp')
| -rw-r--r-- | contrib/llvm-project/llvm/lib/ProfileData/GCOV.cpp | 90 |
1 files changed, 58 insertions, 32 deletions
diff --git a/contrib/llvm-project/llvm/lib/ProfileData/GCOV.cpp b/contrib/llvm-project/llvm/lib/ProfileData/GCOV.cpp index 1e70431a1fae..f7bf42e5c4d2 100644 --- a/contrib/llvm-project/llvm/lib/ProfileData/GCOV.cpp +++ b/contrib/llvm-project/llvm/lib/ProfileData/GCOV.cpp @@ -237,23 +237,14 @@ bool GCOVFile::readGCDA(GCOVBuffer &buf) { if (tag == GCOV_TAG_OBJECT_SUMMARY) { buf.readInt(runCount); buf.readInt(dummy); - // clang<11 uses a fake 4.2 format which sets length to 9. - if (length == 9) - buf.readInt(runCount); } else if (tag == GCOV_TAG_PROGRAM_SUMMARY) { - // clang<11 uses a fake 4.2 format which sets length to 0. - if (length > 0) { - buf.readInt(dummy); - buf.readInt(dummy); - buf.readInt(runCount); - } + buf.readInt(dummy); + buf.readInt(dummy); + buf.readInt(runCount); ++programCount; } else if (tag == GCOV_TAG_FUNCTION) { if (length == 0) // Placeholder continue; - // As of GCC 10, GCOV_TAG_FUNCTION_LENGTH has never been larger than 3. - // However, clang<11 uses a fake 4.2 format which may set length larger - // than 3. if (length < 2 || !buf.readInt(ident)) return false; auto It = identToFunction.find(ident); @@ -346,7 +337,7 @@ StringRef GCOVFunction::getName(bool demangle) const { return Name; if (demangled.empty()) { do { - if (Name.startswith("_Z")) { + if (Name.starts_with("_Z")) { // Name is guaranteed to be NUL-terminated. if (char *res = itaniumDemangle(Name.data())) { demangled = res; @@ -374,25 +365,60 @@ GCOVBlock &GCOVFunction::getExitBlock() const { // For each basic block, the sum of incoming edge counts equals the sum of // 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 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; +// uniquely identified. Use an iterative algorithm to decrease stack usage for +// library users in threads. See the edge propagation algorithm in Optimally +// Profiling and Tracing Programs, ACM Transactions on Programming Languages and +// Systems, 1994. +void GCOVFunction::propagateCounts(const GCOVBlock &v, GCOVArc *pred) { + struct Elem { + const GCOVBlock &v; + GCOVArc *pred; + bool inDst; + size_t i = 0; + uint64_t excess = 0; + }; + + SmallVector<Elem, 0> stack; + stack.push_back({v, pred, false}); + for (;;) { + Elem &u = stack.back(); + // If GCOV_ARC_ON_TREE edges do form a tree, visited is not needed; + // otherwise, this prevents infinite recursion for bad input. + if (u.i == 0 && !visited.insert(&u.v).second) { + stack.pop_back(); + if (stack.empty()) + break; + continue; + } + if (u.i < u.v.pred.size()) { + GCOVArc *e = u.v.pred[u.i++]; + if (e != u.pred) { + if (e->onTree()) + stack.push_back({e->src, e, /*inDst=*/false}); + else + u.excess += e->count; + } + } else if (u.i < u.v.pred.size() + u.v.succ.size()) { + GCOVArc *e = u.v.succ[u.i++ - u.v.pred.size()]; + if (e != u.pred) { + if (e->onTree()) + stack.push_back({e->dst, e, /*inDst=*/true}); + else + u.excess -= e->count; + } + } else { + uint64_t excess = u.excess; + if (static_cast<int64_t>(excess) < 0) + excess = -excess; + if (u.pred) + u.pred->count = excess; + bool inDst = u.inDst; + stack.pop_back(); + if (stack.empty()) + break; + stack.back().excess += inDst ? -excess : excess; + } + } } void GCOVFunction::print(raw_ostream &OS) const { |
