branch.c 2.9 KB

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