|
@@ -23,6 +23,7 @@
|
|
#include "sort.h"
|
|
#include "sort.h"
|
|
#include "machine.h"
|
|
#include "machine.h"
|
|
#include "callchain.h"
|
|
#include "callchain.h"
|
|
|
|
+#include "branch.h"
|
|
|
|
|
|
#define CALLCHAIN_PARAM_DEFAULT \
|
|
#define CALLCHAIN_PARAM_DEFAULT \
|
|
.mode = CHAIN_GRAPH_ABS, \
|
|
.mode = CHAIN_GRAPH_ABS, \
|
|
@@ -571,6 +572,11 @@ fill_node(struct callchain_node *node, struct callchain_cursor *cursor)
|
|
call->cycles_count = cursor_node->branch_flags.cycles;
|
|
call->cycles_count = cursor_node->branch_flags.cycles;
|
|
call->iter_count = cursor_node->nr_loop_iter;
|
|
call->iter_count = cursor_node->nr_loop_iter;
|
|
call->samples_count = cursor_node->samples;
|
|
call->samples_count = cursor_node->samples;
|
|
|
|
+
|
|
|
|
+ branch_type_count(&call->brtype_stat,
|
|
|
|
+ &cursor_node->branch_flags,
|
|
|
|
+ cursor_node->branch_from,
|
|
|
|
+ cursor_node->ip);
|
|
}
|
|
}
|
|
|
|
|
|
list_add_tail(&call->list, &node->val);
|
|
list_add_tail(&call->list, &node->val);
|
|
@@ -688,6 +694,11 @@ static enum match_result match_chain(struct callchain_cursor_node *node,
|
|
cnode->cycles_count += node->branch_flags.cycles;
|
|
cnode->cycles_count += node->branch_flags.cycles;
|
|
cnode->iter_count += node->nr_loop_iter;
|
|
cnode->iter_count += node->nr_loop_iter;
|
|
cnode->samples_count += node->samples;
|
|
cnode->samples_count += node->samples;
|
|
|
|
+
|
|
|
|
+ branch_type_count(&cnode->brtype_stat,
|
|
|
|
+ &node->branch_flags,
|
|
|
|
+ node->branch_from,
|
|
|
|
+ node->ip);
|
|
}
|
|
}
|
|
|
|
|
|
return MATCH_EQ;
|
|
return MATCH_EQ;
|
|
@@ -922,7 +933,7 @@ merge_chain_branch(struct callchain_cursor *cursor,
|
|
list_for_each_entry_safe(list, next_list, &src->val, list) {
|
|
list_for_each_entry_safe(list, next_list, &src->val, list) {
|
|
callchain_cursor_append(cursor, list->ip,
|
|
callchain_cursor_append(cursor, list->ip,
|
|
list->ms.map, list->ms.sym,
|
|
list->ms.map, list->ms.sym,
|
|
- false, NULL, 0, 0);
|
|
|
|
|
|
+ false, NULL, 0, 0, 0);
|
|
list_del(&list->list);
|
|
list_del(&list->list);
|
|
map__zput(list->ms.map);
|
|
map__zput(list->ms.map);
|
|
free(list);
|
|
free(list);
|
|
@@ -962,7 +973,7 @@ int callchain_merge(struct callchain_cursor *cursor,
|
|
int callchain_cursor_append(struct callchain_cursor *cursor,
|
|
int callchain_cursor_append(struct callchain_cursor *cursor,
|
|
u64 ip, struct map *map, struct symbol *sym,
|
|
u64 ip, struct map *map, struct symbol *sym,
|
|
bool branch, struct branch_flags *flags,
|
|
bool branch, struct branch_flags *flags,
|
|
- int nr_loop_iter, int samples)
|
|
|
|
|
|
+ int nr_loop_iter, int samples, u64 branch_from)
|
|
{
|
|
{
|
|
struct callchain_cursor_node *node = *cursor->last;
|
|
struct callchain_cursor_node *node = *cursor->last;
|
|
|
|
|
|
@@ -986,6 +997,7 @@ int callchain_cursor_append(struct callchain_cursor *cursor,
|
|
memcpy(&node->branch_flags, flags,
|
|
memcpy(&node->branch_flags, flags,
|
|
sizeof(struct branch_flags));
|
|
sizeof(struct branch_flags));
|
|
|
|
|
|
|
|
+ node->branch_from = branch_from;
|
|
cursor->nr++;
|
|
cursor->nr++;
|
|
|
|
|
|
cursor->last = &node->next;
|
|
cursor->last = &node->next;
|
|
@@ -1235,14 +1247,19 @@ static int count_float_printf(int idx, const char *str, float value, char *bf, i
|
|
static int counts_str_build(char *bf, int bfsize,
|
|
static int counts_str_build(char *bf, int bfsize,
|
|
u64 branch_count, u64 predicted_count,
|
|
u64 branch_count, u64 predicted_count,
|
|
u64 abort_count, u64 cycles_count,
|
|
u64 abort_count, u64 cycles_count,
|
|
- u64 iter_count, u64 samples_count)
|
|
|
|
|
|
+ u64 iter_count, u64 samples_count,
|
|
|
|
+ struct branch_type_stat *brtype_stat)
|
|
{
|
|
{
|
|
u64 cycles;
|
|
u64 cycles;
|
|
- int printed = 0, i = 0;
|
|
|
|
|
|
+ int printed, i = 0;
|
|
|
|
|
|
if (branch_count == 0)
|
|
if (branch_count == 0)
|
|
return scnprintf(bf, bfsize, " (calltrace)");
|
|
return scnprintf(bf, bfsize, " (calltrace)");
|
|
|
|
|
|
|
|
+ printed = branch_type_str(brtype_stat, bf, bfsize);
|
|
|
|
+ if (printed)
|
|
|
|
+ i++;
|
|
|
|
+
|
|
if (predicted_count < branch_count) {
|
|
if (predicted_count < branch_count) {
|
|
printed += count_float_printf(i++, "predicted",
|
|
printed += count_float_printf(i++, "predicted",
|
|
predicted_count * 100.0 / branch_count,
|
|
predicted_count * 100.0 / branch_count,
|
|
@@ -1278,13 +1295,14 @@ static int counts_str_build(char *bf, int bfsize,
|
|
static int callchain_counts_printf(FILE *fp, char *bf, int bfsize,
|
|
static int callchain_counts_printf(FILE *fp, char *bf, int bfsize,
|
|
u64 branch_count, u64 predicted_count,
|
|
u64 branch_count, u64 predicted_count,
|
|
u64 abort_count, u64 cycles_count,
|
|
u64 abort_count, u64 cycles_count,
|
|
- u64 iter_count, u64 samples_count)
|
|
|
|
|
|
+ u64 iter_count, u64 samples_count,
|
|
|
|
+ struct branch_type_stat *brtype_stat)
|
|
{
|
|
{
|
|
- char str[128];
|
|
|
|
|
|
+ char str[256];
|
|
|
|
|
|
counts_str_build(str, sizeof(str), branch_count,
|
|
counts_str_build(str, sizeof(str), branch_count,
|
|
predicted_count, abort_count, cycles_count,
|
|
predicted_count, abort_count, cycles_count,
|
|
- iter_count, samples_count);
|
|
|
|
|
|
+ iter_count, samples_count, brtype_stat);
|
|
|
|
|
|
if (fp)
|
|
if (fp)
|
|
return fprintf(fp, "%s", str);
|
|
return fprintf(fp, "%s", str);
|
|
@@ -1316,7 +1334,8 @@ int callchain_list_counts__printf_value(struct callchain_node *node,
|
|
|
|
|
|
return callchain_counts_printf(fp, bf, bfsize, branch_count,
|
|
return callchain_counts_printf(fp, bf, bfsize, branch_count,
|
|
predicted_count, abort_count,
|
|
predicted_count, abort_count,
|
|
- cycles_count, iter_count, samples_count);
|
|
|
|
|
|
+ cycles_count, iter_count, samples_count,
|
|
|
|
+ &clist->brtype_stat);
|
|
}
|
|
}
|
|
|
|
|
|
static void free_callchain_node(struct callchain_node *node)
|
|
static void free_callchain_node(struct callchain_node *node)
|
|
@@ -1441,7 +1460,8 @@ int callchain_cursor__copy(struct callchain_cursor *dst,
|
|
|
|
|
|
rc = callchain_cursor_append(dst, node->ip, node->map, node->sym,
|
|
rc = callchain_cursor_append(dst, node->ip, node->map, node->sym,
|
|
node->branch, &node->branch_flags,
|
|
node->branch, &node->branch_flags,
|
|
- node->nr_loop_iter, node->samples);
|
|
|
|
|
|
+ node->nr_loop_iter, node->samples,
|
|
|
|
+ node->branch_from);
|
|
if (rc)
|
|
if (rc)
|
|
break;
|
|
break;
|
|
|
|
|