[PATCH 2/4] gprofng: mark non-precise HW counter columns

Claudiu Zissulescu <[email protected]>
Newsgroups gmane.comp.gnu.binutils
Message-ID <[email protected]>
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
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.