[PATCH 1/4] gprofng: group precise vs. non-precise HW counters
Claudiu Zissulescu
claziss@gmail.com
Fri Jun 26 11:33:19 GMT 2026
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(-)
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);
--
2.54.0
More information about the Binutils
mailing list