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 } 148