[PATCH 2/4] gprofng: mark non-precise HW counter columns
Claudiu Zissulescu
claziss@gmail.com
Fri Jun 26 11:33:20 GMT 2026
Mark the column header of any non-precise HW counter metric with "(*)"
and emit a single explanatory footnote below the column header block
when at least one displayed metric is non-precise. Precise PEBS/IBS
events (ABST_EXACT, ABST_EXACT_PEBS_PLUS1) are left unmarked. Also
point the user at the "Precise events" section of -h output.
gprofng/
* src/Metric.cc (Metric::set_name): Append "*" marker.
* src/Print.cc (print_label): Emit a footnote explaining the "*"
marker.
* src/Hist_data.cc (Hist_data::print_label): Likewise.
---
gprofng/src/Hist_data.cc | 27 +++++++++++++++++++++++++++
gprofng/src/Metric.cc | 16 +++++++++++++---
gprofng/src/Print.cc | 26 ++++++++++++++++++++++++++
3 files changed, 66 insertions(+), 3 deletions(-)
diff --git a/gprofng/src/Hist_data.cc b/gprofng/src/Hist_data.cc
index 41e3edf3ae4..8818e84f215 100644
--- a/gprofng/src/Hist_data.cc
+++ b/gprofng/src/Hist_data.cc
@@ -863,6 +863,33 @@ Hist_data::print_label (FILE *out_file, Metric::HistMetric *hist_metric,
sb1.toFileLn (out_file);
sb2.toFileLn (out_file);
sb3.toFileLn (out_file);
+
+ /* Footnote for non-precise HW counters (marked with " (*)" by
+ Metric::set_name). Emit once if any visible metric uses such a
+ counter, so users understand source-line attribution may skid.
+ Mirrors the equivalent block in the free print_label() in Print.cc. */
+ bool any_non_precise = false;
+ for (int i = 0; i < nmetrics && !any_non_precise; i++)
+ {
+ Metric *m = metrics->get (i);
+ if (!m->is_any_visible ())
+ continue;
+ if (m->get_type () != Metric::HWCNTR)
+ continue;
+ Hwcentry *hwc = m->get_hw_ctr ();
+ if (hwc != NULL
+ && !HWCENTRY_USES_SAMPLING (hwc)
+ && hwc->memop != ABST_EXACT)
+ any_non_precise = true;
+ }
+ if (any_non_precise)
+ fprintf (out_file, GTXT (
+ "%*s(*) Non-precise HW event: sample location may skid forward by\n"
+ "%*s several instructions, so cache/branch misses are often\n"
+ "%*s attributed to the next basic block (e.g. a loop header).\n"
+ "%*s For exact line attribution, prefer precise events\n"
+ "%*s (see the \"Precise events\" section of `gprofng collect app -h`).\n"),
+ space, "", space, "", space, "", space, "", space, "");
return name_offset;
}
diff --git a/gprofng/src/Metric.cc b/gprofng/src/Metric.cc
index a72bdaef6a3..f4264277bf9 100644
--- a/gprofng/src/Metric.cc
+++ b/gprofng/src/Metric.cc
@@ -306,7 +306,8 @@ Metric::set_subtype (SubType st)
case HWCNTR:
{
char *sstr, *estr1, *estr2;
- if (get_hw_ctr () == NULL)
+ Hwcentry *hwc = get_hw_ctr ();
+ if (hwc == NULL)
abort ();
sstr = get_username ();
if (st == EXCLUSIVE)
@@ -335,8 +336,17 @@ Metric::set_subtype (SubType st)
get_aux (), st);
estr2 = dbe_strdup (NTXT ("??"));
}
- name = dbe_sprintf (NTXT ("%s%s"), estr1, sstr);
- abbr = dbe_sprintf (NTXT ("%s%s"), estr2, sstr);
+ /* Mark non-precise counters so users don't over-trust source-line
+ attribution. Only PEBS/EXACT events tag the retiring instruction;
+ everything else may skid forward by several instructions. The (*)
+ should be explained by a footnote at report-print time. */
+ const char *mark = "";
+ if ((st == EXCLUSIVE || st == INCLUSIVE || st == DATASPACE)
+ && !HWCENTRY_USES_SAMPLING (hwc)
+ && hwc->memop != ABST_EXACT)
+ mark = " (*)";
+ name = dbe_sprintf (NTXT ("%s%s%s"), estr1, sstr, mark);
+ abbr = dbe_sprintf (NTXT ("%s%s%s"), estr2, sstr, mark);
break;
}
diff --git a/gprofng/src/Print.cc b/gprofng/src/Print.cc
index 564e3a638bc..8d3cef4ede4 100644
--- a/gprofng/src/Print.cc
+++ b/gprofng/src/Print.cc
@@ -306,6 +306,32 @@ print_label (FILE *out_file, MetricList *metrics_list,
fprintf (out_file, NTXT ("%*s%s\n"), space, NTXT (""), delTrailingBlanks (line1));
fprintf (out_file, NTXT ("%*s%s\n"), space, NTXT (""), delTrailingBlanks (line2));
fprintf (out_file, NTXT ("%*s%s\n"), space, NTXT (""), delTrailingBlanks (line3));
+
+ /* Footnote for non-precise HW counters (marked with " (*)" by
+ Metric::set_name). Emit once if any visible metric uses such a
+ counter, so users understand source-line attribution may skid. */
+ bool any_non_precise = false;
+ for (int i = 0, n = mlist->size (); i < n && !any_non_precise; i++)
+ {
+ Metric *m = mlist->fetch (i);
+ if (!(m->is_visible () || m->is_tvisible () || m->is_pvisible ()))
+ continue;
+ if (m->get_type () != Metric::HWCNTR)
+ continue;
+ Hwcentry *hwc = m->get_hw_ctr ();
+ if (hwc != NULL
+ && !HWCENTRY_USES_SAMPLING (hwc)
+ && hwc->memop != ABST_EXACT)
+ any_non_precise = true;
+ }
+ if (any_non_precise)
+ fprintf (out_file, GTXT (
+ "%*s(*) Non-precise HW event: sample location may skid forward by\n"
+ "%*s several instructions, so cache/branch misses are often\n"
+ "%*s attributed to the next basic block (e.g. a loop header).\n"
+ "%*s For exact line attribution, prefer precise events\n"
+ "%*s (see the \"Precise events\" section of `gprofng collect app -h`).\n"),
+ space, "", space, "", space, "", space, "", space, "");
return name_offset;
}
--
2.54.0
More information about the Binutils
mailing list