18c2ecf20Sopenharmony_ci#include "util/map_symbol.h" 28c2ecf20Sopenharmony_ci#include "util/branch.h" 38c2ecf20Sopenharmony_ci#include <linux/kernel.h> 48c2ecf20Sopenharmony_ci 58c2ecf20Sopenharmony_cistatic bool cross_area(u64 addr1, u64 addr2, int size) 68c2ecf20Sopenharmony_ci{ 78c2ecf20Sopenharmony_ci u64 align1, align2; 88c2ecf20Sopenharmony_ci 98c2ecf20Sopenharmony_ci align1 = addr1 & ~(size - 1); 108c2ecf20Sopenharmony_ci align2 = addr2 & ~(size - 1); 118c2ecf20Sopenharmony_ci 128c2ecf20Sopenharmony_ci return (align1 != align2) ? true : false; 138c2ecf20Sopenharmony_ci} 148c2ecf20Sopenharmony_ci 158c2ecf20Sopenharmony_ci#define AREA_4K 4096 168c2ecf20Sopenharmony_ci#define AREA_2M (2 * 1024 * 1024) 178c2ecf20Sopenharmony_ci 188c2ecf20Sopenharmony_civoid branch_type_count(struct branch_type_stat *st, struct branch_flags *flags, 198c2ecf20Sopenharmony_ci u64 from, u64 to) 208c2ecf20Sopenharmony_ci{ 218c2ecf20Sopenharmony_ci if (flags->type == PERF_BR_UNKNOWN || from == 0) 228c2ecf20Sopenharmony_ci return; 238c2ecf20Sopenharmony_ci 248c2ecf20Sopenharmony_ci st->counts[flags->type]++; 258c2ecf20Sopenharmony_ci 268c2ecf20Sopenharmony_ci if (flags->type == PERF_BR_COND) { 278c2ecf20Sopenharmony_ci if (to > from) 288c2ecf20Sopenharmony_ci st->cond_fwd++; 298c2ecf20Sopenharmony_ci else 308c2ecf20Sopenharmony_ci st->cond_bwd++; 318c2ecf20Sopenharmony_ci } 328c2ecf20Sopenharmony_ci 338c2ecf20Sopenharmony_ci if (cross_area(from, to, AREA_2M)) 348c2ecf20Sopenharmony_ci st->cross_2m++; 358c2ecf20Sopenharmony_ci else if (cross_area(from, to, AREA_4K)) 368c2ecf20Sopenharmony_ci st->cross_4k++; 378c2ecf20Sopenharmony_ci} 388c2ecf20Sopenharmony_ci 398c2ecf20Sopenharmony_ciconst char *branch_type_name(int type) 408c2ecf20Sopenharmony_ci{ 418c2ecf20Sopenharmony_ci const char *branch_names[PERF_BR_MAX] = { 428c2ecf20Sopenharmony_ci "N/A", 438c2ecf20Sopenharmony_ci "COND", 448c2ecf20Sopenharmony_ci "UNCOND", 458c2ecf20Sopenharmony_ci "IND", 468c2ecf20Sopenharmony_ci "CALL", 478c2ecf20Sopenharmony_ci "IND_CALL", 488c2ecf20Sopenharmony_ci "RET", 498c2ecf20Sopenharmony_ci "SYSCALL", 508c2ecf20Sopenharmony_ci "SYSRET", 518c2ecf20Sopenharmony_ci "COND_CALL", 528c2ecf20Sopenharmony_ci "COND_RET" 538c2ecf20Sopenharmony_ci }; 548c2ecf20Sopenharmony_ci 558c2ecf20Sopenharmony_ci if (type >= 0 && type < PERF_BR_MAX) 568c2ecf20Sopenharmony_ci return branch_names[type]; 578c2ecf20Sopenharmony_ci 588c2ecf20Sopenharmony_ci return NULL; 598c2ecf20Sopenharmony_ci} 608c2ecf20Sopenharmony_ci 618c2ecf20Sopenharmony_civoid branch_type_stat_display(FILE *fp, struct branch_type_stat *st) 628c2ecf20Sopenharmony_ci{ 638c2ecf20Sopenharmony_ci u64 total = 0; 648c2ecf20Sopenharmony_ci int i; 658c2ecf20Sopenharmony_ci 668c2ecf20Sopenharmony_ci for (i = 0; i < PERF_BR_MAX; i++) 678c2ecf20Sopenharmony_ci total += st->counts[i]; 688c2ecf20Sopenharmony_ci 698c2ecf20Sopenharmony_ci if (total == 0) 708c2ecf20Sopenharmony_ci return; 718c2ecf20Sopenharmony_ci 728c2ecf20Sopenharmony_ci fprintf(fp, "\n#"); 738c2ecf20Sopenharmony_ci fprintf(fp, "\n# Branch Statistics:"); 748c2ecf20Sopenharmony_ci fprintf(fp, "\n#"); 758c2ecf20Sopenharmony_ci 768c2ecf20Sopenharmony_ci if (st->cond_fwd > 0) { 778c2ecf20Sopenharmony_ci fprintf(fp, "\n%8s: %5.1f%%", 788c2ecf20Sopenharmony_ci "COND_FWD", 798c2ecf20Sopenharmony_ci 100.0 * (double)st->cond_fwd / (double)total); 808c2ecf20Sopenharmony_ci } 818c2ecf20Sopenharmony_ci 828c2ecf20Sopenharmony_ci if (st->cond_bwd > 0) { 838c2ecf20Sopenharmony_ci fprintf(fp, "\n%8s: %5.1f%%", 848c2ecf20Sopenharmony_ci "COND_BWD", 858c2ecf20Sopenharmony_ci 100.0 * (double)st->cond_bwd / (double)total); 868c2ecf20Sopenharmony_ci } 878c2ecf20Sopenharmony_ci 888c2ecf20Sopenharmony_ci if (st->cross_4k > 0) { 898c2ecf20Sopenharmony_ci fprintf(fp, "\n%8s: %5.1f%%", 908c2ecf20Sopenharmony_ci "CROSS_4K", 918c2ecf20Sopenharmony_ci 100.0 * (double)st->cross_4k / (double)total); 928c2ecf20Sopenharmony_ci } 938c2ecf20Sopenharmony_ci 948c2ecf20Sopenharmony_ci if (st->cross_2m > 0) { 958c2ecf20Sopenharmony_ci fprintf(fp, "\n%8s: %5.1f%%", 968c2ecf20Sopenharmony_ci "CROSS_2M", 978c2ecf20Sopenharmony_ci 100.0 * (double)st->cross_2m / (double)total); 988c2ecf20Sopenharmony_ci } 998c2ecf20Sopenharmony_ci 1008c2ecf20Sopenharmony_ci for (i = 0; i < PERF_BR_MAX; i++) { 1018c2ecf20Sopenharmony_ci if (st->counts[i] > 0) 1028c2ecf20Sopenharmony_ci fprintf(fp, "\n%8s: %5.1f%%", 1038c2ecf20Sopenharmony_ci branch_type_name(i), 1048c2ecf20Sopenharmony_ci 100.0 * 1058c2ecf20Sopenharmony_ci (double)st->counts[i] / (double)total); 1068c2ecf20Sopenharmony_ci } 1078c2ecf20Sopenharmony_ci} 1088c2ecf20Sopenharmony_ci 1098c2ecf20Sopenharmony_cistatic int count_str_scnprintf(int idx, const char *str, char *bf, int size) 1108c2ecf20Sopenharmony_ci{ 1118c2ecf20Sopenharmony_ci return scnprintf(bf, size, "%s%s", (idx) ? " " : " (", str); 1128c2ecf20Sopenharmony_ci} 1138c2ecf20Sopenharmony_ci 1148c2ecf20Sopenharmony_ciint branch_type_str(struct branch_type_stat *st, char *bf, int size) 1158c2ecf20Sopenharmony_ci{ 1168c2ecf20Sopenharmony_ci int i, j = 0, printed = 0; 1178c2ecf20Sopenharmony_ci u64 total = 0; 1188c2ecf20Sopenharmony_ci 1198c2ecf20Sopenharmony_ci for (i = 0; i < PERF_BR_MAX; i++) 1208c2ecf20Sopenharmony_ci total += st->counts[i]; 1218c2ecf20Sopenharmony_ci 1228c2ecf20Sopenharmony_ci if (total == 0) 1238c2ecf20Sopenharmony_ci return 0; 1248c2ecf20Sopenharmony_ci 1258c2ecf20Sopenharmony_ci if (st->cond_fwd > 0) 1268c2ecf20Sopenharmony_ci printed += count_str_scnprintf(j++, "COND_FWD", bf + printed, size - printed); 1278c2ecf20Sopenharmony_ci 1288c2ecf20Sopenharmony_ci if (st->cond_bwd > 0) 1298c2ecf20Sopenharmony_ci printed += count_str_scnprintf(j++, "COND_BWD", bf + printed, size - printed); 1308c2ecf20Sopenharmony_ci 1318c2ecf20Sopenharmony_ci for (i = 0; i < PERF_BR_MAX; i++) { 1328c2ecf20Sopenharmony_ci if (i == PERF_BR_COND) 1338c2ecf20Sopenharmony_ci continue; 1348c2ecf20Sopenharmony_ci 1358c2ecf20Sopenharmony_ci if (st->counts[i] > 0) 1368c2ecf20Sopenharmony_ci printed += count_str_scnprintf(j++, branch_type_name(i), bf + printed, size - printed); 1378c2ecf20Sopenharmony_ci } 1388c2ecf20Sopenharmony_ci 1398c2ecf20Sopenharmony_ci if (st->cross_4k > 0) 1408c2ecf20Sopenharmony_ci printed += count_str_scnprintf(j++, "CROSS_4K", bf + printed, size - printed); 1418c2ecf20Sopenharmony_ci 1428c2ecf20Sopenharmony_ci if (st->cross_2m > 0) 1438c2ecf20Sopenharmony_ci printed += count_str_scnprintf(j++, "CROSS_2M", bf + printed, size - printed); 1448c2ecf20Sopenharmony_ci 1458c2ecf20Sopenharmony_ci return printed; 1468c2ecf20Sopenharmony_ci} 147