Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

perf util: Create branch.c/.h for common branch functions

Create new util/branch.c and util/branch.h to contain the common branch
functions. Such as:

branch_type_count(): Count the numbers of branch types
branch_type_name() : Return the name of branch type
branch_type_stat_display(): Display branch type statistics info
branch_type_str(): Construct the branch type string.

The branch type is saved in branch_flags.

Change log:

v8: Change PERF_BR_NONE to PERF_BR_UNKNOWN.

v7: Since the common branch type name is changed (e.g. JCC->COND),
this patch is performed the modification accordingly.

v6: Move that multiline conditional code inside {} brackets.
Move branch_type_stat_display() from builtin-report.c to
branch.c.
Move branch_type_str() from callchain.c to branch.c.

v5: It's a new patch in v5 patch series.

Signed-off-by: Yao Jin <yao.jin@linux.intel.com>
Acked-by: Jiri Olsa <jolsa@kernel.org>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Andi Kleen <ak@linux.intel.com>
Cc: Kan Liang <kan.liang@intel.com>
Cc: Michael Ellerman <mpe@ellerman.id.au>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/1500379995-6449-6-git-send-email-yao.jin@linux.intel.com
[ Don't use 'index' and 'stat' as names for variables, it shadows global decls in older distros ]
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>

authored by

Jin Yao and committed by
Arnaldo Carvalho de Melo
992c7e92 8d51735f

+174 -1
+1
tools/perf/util/Build
··· 93 93 libperf-y += units.o 94 94 libperf-y += time-utils.o 95 95 libperf-y += expr-bison.o 96 + libperf-y += branch.o 96 97 97 98 libperf-$(CONFIG_LIBBPF) += bpf-loader.o 98 99 libperf-$(CONFIG_BPF_PROLOGUE) += bpf-prologue.o
+147
tools/perf/util/branch.c
··· 1 + #include "perf.h" 2 + #include "util/util.h" 3 + #include "util/debug.h" 4 + #include "util/branch.h" 5 + 6 + static 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 + 19 + void 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 + 40 + const 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 + 62 + void 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 + 110 + static 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 + 115 + int 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 + }
+24
tools/perf/util/branch.h
··· 1 + #ifndef _PERF_BRANCH_H 2 + #define _PERF_BRANCH_H 1 3 + 4 + #include <stdint.h> 5 + #include "../perf.h" 6 + 7 + struct branch_type_stat { 8 + u64 counts[PERF_BR_MAX]; 9 + u64 cond_fwd; 10 + u64 cond_bwd; 11 + u64 cross_4k; 12 + u64 cross_2m; 13 + }; 14 + 15 + struct branch_flags; 16 + 17 + void branch_type_count(struct branch_type_stat *st, struct branch_flags *flags, 18 + u64 from, u64 to); 19 + 20 + const char *branch_type_name(int type); 21 + void branch_type_stat_display(FILE *fp, struct branch_type_stat *st); 22 + int branch_type_str(struct branch_type_stat *st, char *bf, int bfsize); 23 + 24 + #endif /* _PERF_BRANCH_H */
+2 -1
tools/perf/util/event.h
··· 142 142 u64 in_tx:1; 143 143 u64 abort:1; 144 144 u64 cycles:16; 145 - u64 reserved:44; 145 + u64 type:4; 146 + u64 reserved:40; 146 147 }; 147 148 148 149 struct branch_entry {