linux/tools/perf/util/branch.c
<<
>>
Prefs
   1#include "perf.h"
   2#include "util/util.h"
   3#include "util/debug.h"
   4#include "util/branch.h"
   5
   6static bool cross_area(u64 addr1, u64 addr2, int size)
   7{
   8        u64 align1, align2;
   9
  10        align1 = addr1 & ~(size - 1);
  11        align2 = addr2 & ~(size - 1);
  12
  13        return (align1 != align2) ? true : false;
  14}
  15
  16#define AREA_4K         4096
  17#define AREA_2M         (2 * 1024 * 1024)
  18
  19void branch_type_count(struct branch_type_stat *st, struct branch_flags *flags,
  20                       u64 from, u64 to)
  21{
  22        if (flags->type == PERF_BR_UNKNOWN || from == 0)
  23                return;
  24
  25        st->counts[flags->type]++;
  26
  27        if (flags->type == PERF_BR_COND) {
  28                if (to > from)
  29                        st->cond_fwd++;
  30                else
  31                        st->cond_bwd++;
  32        }
  33
  34        if (cross_area(from, to, AREA_2M))
  35                st->cross_2m++;
  36        else if (cross_area(from, to, AREA_4K))
  37                st->cross_4k++;
  38}
  39
  40const char *branch_type_name(int type)
  41{
  42        const char *branch_names[PERF_BR_MAX] = {
  43                "N/A",
  44                "COND",
  45                "UNCOND",
  46                "IND",
  47                "CALL",
  48                "IND_CALL",
  49                "RET",
  50                "SYSCALL",
  51                "SYSRET",
  52                "COND_CALL",
  53                "COND_RET"
  54        };
  55
  56        if (type >= 0 && type < PERF_BR_MAX)
  57                return branch_names[type];
  58
  59        return NULL;
  60}
  61
  62void branch_type_stat_display(FILE *fp, struct branch_type_stat *st)
  63{
  64        u64 total = 0;
  65        int i;
  66
  67        for (i = 0; i < PERF_BR_MAX; i++)
  68                total += st->counts[i];
  69
  70        if (total == 0)
  71                return;
  72
  73        fprintf(fp, "\n#");
  74        fprintf(fp, "\n# Branch Statistics:");
  75        fprintf(fp, "\n#");
  76
  77        if (st->cond_fwd > 0) {
  78                fprintf(fp, "\n%8s: %5.1f%%",
  79                        "COND_FWD",
  80                        100.0 * (double)st->cond_fwd / (double)total);
  81        }
  82
  83        if (st->cond_bwd > 0) {
  84                fprintf(fp, "\n%8s: %5.1f%%",
  85                        "COND_BWD",
  86                        100.0 * (double)st->cond_bwd / (double)total);
  87        }
  88
  89        if (st->cross_4k > 0) {
  90                fprintf(fp, "\n%8s: %5.1f%%",
  91                        "CROSS_4K",
  92                        100.0 * (double)st->cross_4k / (double)total);
  93        }
  94
  95        if (st->cross_2m > 0) {
  96                fprintf(fp, "\n%8s: %5.1f%%",
  97                        "CROSS_2M",
  98                        100.0 * (double)st->cross_2m / (double)total);
  99        }
 100
 101        for (i = 0; i < PERF_BR_MAX; i++) {
 102                if (st->counts[i] > 0)
 103                        fprintf(fp, "\n%8s: %5.1f%%",
 104                                branch_type_name(i),
 105                                100.0 *
 106                                (double)st->counts[i] / (double)total);
 107        }
 108}
 109
 110static int count_str_scnprintf(int idx, const char *str, char *bf, int size)
 111{
 112        return scnprintf(bf, size, "%s%s", (idx) ? " " : " (", str);
 113}
 114
 115int branch_type_str(struct branch_type_stat *st, char *bf, int size)
 116{
 117        int i, j = 0, printed = 0;
 118        u64 total = 0;
 119
 120        for (i = 0; i < PERF_BR_MAX; i++)
 121                total += st->counts[i];
 122
 123        if (total == 0)
 124                return 0;
 125
 126        if (st->cond_fwd > 0)
 127                printed += count_str_scnprintf(j++, "COND_FWD", bf + printed, size - printed);
 128
 129        if (st->cond_bwd > 0)
 130                printed += count_str_scnprintf(j++, "COND_BWD", bf + printed, size - printed);
 131
 132        for (i = 0; i < PERF_BR_MAX; i++) {
 133                if (i == PERF_BR_COND)
 134                        continue;
 135
 136                if (st->counts[i] > 0)
 137                        printed += count_str_scnprintf(j++, branch_type_name(i), bf + printed, size - printed);
 138        }
 139
 140        if (st->cross_4k > 0)
 141                printed += count_str_scnprintf(j++, "CROSS_4K", bf + printed, size - printed);
 142
 143        if (st->cross_2m > 0)
 144                printed += count_str_scnprintf(j++, "CROSS_2M", bf + printed, size - printed);
 145
 146        return printed;
 147}
 148