[1/4] gprofng: group precise vs. non-precise HW counters

Message ID 20260626113840.44715-2-claziss@gmail.com
State New
Headers
Series gprofng: Improve HW counter markings and documentation |

Commit Message

Claudiu Zissulescu June 26, 2026, 11:33 a.m. UTC
  The -h listing prints all available HW counters in a single,
undifferentiated block. In that view, "type" column shows
"memoryspace" for PEBS/IBS events. Users can't tell from listing
alone that "memoryspace" means precise sample attribution, while
other event types may attribute samples slightly "late". This mismatch
is the most common source of confusion when reading source-view
reports.

To make this clearer, split the "std-ctrs" and "raw-ctrs" listings
into two sub-sections each ("Precise events" and "Standard events"),
and append "(precise)" to the type label for ABST_EXACT /
ABST_EXACT_PEBS_PLUS1 counters.

This change is only a reordering of existing entries—no counters are
added, removed, or renamed.

gprofng/
	* common/hwctable.c (hwc_memop_string): Tag ABST_EXACT and
	ABST_EXACT_PEBS_PLUS1 as precise.
	(hwc_usage_internal): Emit std and raw counter lists in two
	passes: precise events and standard events.
---
 gprofng/common/hwctable.c | 78 ++++++++++++++++++++++++++++++++-------
 1 file changed, 65 insertions(+), 13 deletions(-)
  

Patch

diff --git a/gprofng/common/hwctable.c b/gprofng/common/hwctable.c
index 52b28f21dc5..cb8a5e43763 100644
--- a/gprofng/common/hwctable.c
+++ b/gprofng/common/hwctable.c
@@ -2946,7 +2946,7 @@  hwc_memop_string (ABST_type memop)
       break;
     case ABST_EXACT_PEBS_PLUS1:
     case ABST_EXACT:
-      s = GTXT ("memoryspace ");
+      s = GTXT ("memoryspace (precise) ");
       break;
     case ABST_COUNT:
       s = GTXT ("count ");
@@ -3656,31 +3656,83 @@  hwc_usage_internal (int forKernel, FILE *f_usage, const char *cmd, const char *d
 
   /* long listings */
   char tmp[1024];
+  /* Counters whose memop is ABST_EXACT or ABST_EXACT_PEBS_PLUS1 deliver
+     precise PC attribution (IBS on AMD, PEBS on Intel).  All others can
+     skid forward by several instructions, which is the single most common
+     source of user confusion when reading source-view reports.  Group the
+     listing so the precise events are visible and labeled.  */
+#define HWC_IS_PRECISE(ctr) \
+  (HWCENTRY_USES_SAMPLING (ctr) || (ctr)->memop == ABST_EXACT)
+
   if (has_std_ctrs)
     {
-      fprintf (f_usage, GTXT ("\nAliases for most useful HW counters:\n\n"));
-      format_columns (tmp, 1024, "alias", "raw name", "type ", "units", "description");
-      fprintf (f_usage, NTXT ("    %s\n\n"), tmp);
+      int n_precise = 0;
       for (Hwcentry **pctr = std_ctrs; *pctr; pctr++)
+	if (HWC_IS_PRECISE (*pctr))
+	  n_precise++;
+
+      fprintf (f_usage, GTXT ("\nAliases for most useful HW counters:\n"));
+      if (n_precise)
 	{
-	  Hwcentry *ctr = *pctr;
-	  hwc_hwcentry_string_internal (tmp, sizeof (tmp), ctr, 0);
-	  fprintf (f_usage, NTXT ("    %s\n"), tmp);
+	  fprintf (f_usage, GTXT ("\n  Precise events (recommended for accurate"
+				  " instruction/line attribution):\n\n"));
+	  format_columns (tmp, 1024, "alias", "raw name", "type ", "units", "description");
+	  fprintf (f_usage, NTXT ("    %s\n\n"), tmp);
+	  for (Hwcentry **pctr = std_ctrs; *pctr; pctr++)
+	    if (HWC_IS_PRECISE (*pctr))
+	      {
+		hwc_hwcentry_string_internal (tmp, sizeof (tmp), *pctr, 0);
+		fprintf (f_usage, NTXT ("    %s\n"), tmp);
+	      }
 	}
+
+      fprintf (f_usage, GTXT ("\n  Standard events (sample location may"
+			      " skid forward several instructions):\n\n"));
+      format_columns (tmp, 1024, "alias", "raw name", "type ", "units", "description");
+      fprintf (f_usage, NTXT ("    %s\n\n"), tmp);
+      for (Hwcentry **pctr = std_ctrs; *pctr; pctr++)
+	if (!HWC_IS_PRECISE (*pctr))
+	  {
+	    hwc_hwcentry_string_internal (tmp, sizeof (tmp), *pctr, 0);
+	    fprintf (f_usage, NTXT ("    %s\n"), tmp);
+	  }
     }
   if (has_raw_ctrs)
     {
-      fprintf (f_usage, GTXT ("\nRaw HW counters:\n\n"));
+      int n_precise = 0;
+      for (Hwcentry **pctr = raw_ctrs; *pctr; pctr++)
+	if (HWC_IS_PRECISE (*pctr))
+	  n_precise++;
+
+      fprintf (f_usage, GTXT ("\nRaw HW counters:\n"));
       hwc_usage_raw_overview_sparc (f_usage, cpuver);
+
+      if (n_precise)
+	{
+	  fprintf (f_usage, GTXT ("\n  Precise events (recommended for accurate"
+				  " instruction/line attribution):\n\n"));
+	  format_columns (tmp, 1024, "name", NULL, "type ", "units", "description");
+	  fprintf (f_usage, NTXT ("    %s\n\n"), tmp);
+	  for (Hwcentry **pctr = raw_ctrs; *pctr; pctr++)
+	    if (HWC_IS_PRECISE (*pctr))
+	      {
+		hwc_hwcentry_string_internal (tmp, sizeof (tmp), *pctr, show_short_desc);
+		fprintf (f_usage, NTXT ("    %s\n"), tmp);
+	      }
+	}
+
+      fprintf (f_usage, GTXT ("\n  Standard events (sample location may"
+			      " skid forward several instructions):\n\n"));
       format_columns (tmp, 1024, "name", NULL, "type ", "units", "description");
       fprintf (f_usage, NTXT ("    %s\n\n"), tmp);
       for (Hwcentry **pctr = raw_ctrs; *pctr; pctr++)
-	{
-	  Hwcentry *ctr = *pctr;
-	  hwc_hwcentry_string_internal (tmp, sizeof (tmp), ctr, show_short_desc);
-	  fprintf (f_usage, NTXT ("    %s\n"), tmp);
-	}
+	if (!HWC_IS_PRECISE (*pctr))
+	  {
+	    hwc_hwcentry_string_internal (tmp, sizeof (tmp), *pctr, show_short_desc);
+	    fprintf (f_usage, NTXT ("    %s\n"), tmp);
+	  }
     }
+#undef HWC_IS_PRECISE
 
   /* documentation notice */
   hwc_get_docref (tmp, 1024);