]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - gprof/cg_print.c
* config/sh/tm-sh.h (BELIEVE_PCC_PROMOTION): Define, so that
[thirdparty/binutils-gdb.git] / gprof / cg_print.c
CommitLineData
5489fcc3
KR
1#include "libiberty.h"
2#include "cg_arcs.h"
3#include "cg_print.h"
4#include "hist.h"
5#include "utils.h"
6
7/*
8 * Return value of comparison functions used to sort tables:
9 */
10#define LESSTHAN -1
11#define EQUALTO 0
12#define GREATERTHAN 1
13
64c50fc5
JL
14static void order_and_dump_functions_by_arcs PARAMS ((Arc **, unsigned long,
15 int, Arc **,
16 unsigned long *));
5489fcc3 17/* declarations of automatically generated functions to output blurbs: */
12516a37
KR
18extern void bsd_callg_blurb PARAMS ((FILE * fp));
19extern void fsf_callg_blurb PARAMS ((FILE * fp));
5489fcc3
KR
20
21double print_time = 0.0;
22
23
24static void
12516a37 25DEFUN_VOID (print_header)
5489fcc3 26{
12516a37
KR
27 if (first_output)
28 {
29 first_output = FALSE;
30 }
31 else
32 {
33 printf ("\f\n");
03c35bcb 34 }
12516a37
KR
35 if (!bsd_style_output)
36 {
37 if (print_descriptions)
38 {
16a02269 39 printf (_("\t\t Call graph (explanation follows)\n\n"));
12516a37
KR
40 }
41 else
42 {
16a02269 43 printf (_("\t\t\tCall graph\n\n"));
03c35bcb
KR
44 }
45 }
16a02269 46 printf (_("\ngranularity: each sample hit covers %ld byte(s)"),
12516a37
KR
47 (long) hist_scale * sizeof (UNIT));
48 if (print_time > 0.0)
49 {
16a02269 50 printf (_(" for %.2f%% of %.2f seconds\n\n"),
12516a37
KR
51 100.0 / print_time, print_time / hz);
52 }
53 else
54 {
16a02269 55 printf (_(" no time propagated\n\n"));
12516a37
KR
56 /*
57 * This doesn't hurt, since all the numerators will be 0.0:
58 */
59 print_time = 1.0;
03c35bcb 60 }
12516a37
KR
61 if (bsd_style_output)
62 {
63 printf ("%6.6s %5.5s %7.7s %11.11s %7.7s/%-7.7s %-8.8s\n",
16a02269 64 "", "", "", "", _("called"), _("total"), _("parents"));
12516a37 65 printf ("%-6.6s %5.5s %7.7s %11.11s %7.7s+%-7.7s %-8.8s\t%5.5s\n",
16a02269
TT
66 _("index"), _("%time"), _("self"), _("descendents"),
67 _("called"), _("self"), _("name"), _("index"));
12516a37 68 printf ("%6.6s %5.5s %7.7s %11.11s %7.7s/%-7.7s %-8.8s\n",
16a02269 69 "", "", "", "", _("called"), _("total"), _("children"));
12516a37
KR
70 printf ("\n");
71 }
72 else
73 {
16a02269 74 printf (_("index %% time self children called name\n"));
03c35bcb
KR
75 }
76}
5489fcc3
KR
77
78
79/*
80 * Print a cycle header.
81 */
82static void
12516a37 83DEFUN (print_cycle, (cyc), Sym * cyc)
5489fcc3 84{
12516a37 85 char buf[BUFSIZ];
5489fcc3 86
12516a37 87 sprintf (buf, "[%d]", cyc->cg.index);
869b94c5 88 printf (bsd_style_output
8c73afb3
ILT
89 ? "%-6.6s %5.1f %7.2f %11.2f %7lu"
90 : "%-6.6s %5.1f %7.2f %7.2f %7lu", buf,
12516a37
KR
91 100 * (cyc->cg.prop.self + cyc->cg.prop.child) / print_time,
92 cyc->cg.prop.self / hz, cyc->cg.prop.child / hz, cyc->ncalls);
93 if (cyc->cg.self_calls != 0)
94 {
8c73afb3 95 printf ("+%-7lu", cyc->cg.self_calls);
12516a37
KR
96 }
97 else
98 {
99 printf (" %7.7s", "");
03c35bcb 100 }
16a02269 101 printf (_(" <cycle %d as a whole> [%d]\n"), cyc->cg.cyc.num, cyc->cg.index);
03c35bcb 102}
5489fcc3
KR
103
104
105/*
106 * Compare LEFT and RIGHT membmer. Major comparison key is
107 * CG.PROP.SELF+CG.PROP.CHILD, secondary key is NCALLS+CG.SELF_CALLS.
108 */
109static int
12516a37 110DEFUN (cmp_member, (left, right), Sym * left AND Sym * right)
5489fcc3 111{
12516a37
KR
112 double left_time = left->cg.prop.self + left->cg.prop.child;
113 double right_time = right->cg.prop.self + right->cg.prop.child;
8c73afb3
ILT
114 unsigned long left_calls = left->ncalls + left->cg.self_calls;
115 unsigned long right_calls = right->ncalls + right->cg.self_calls;
12516a37
KR
116
117 if (left_time > right_time)
118 {
119 return GREATERTHAN;
03c35bcb 120 }
12516a37
KR
121 if (left_time < right_time)
122 {
123 return LESSTHAN;
03c35bcb 124 }
12516a37
KR
125
126 if (left_calls > right_calls)
127 {
128 return GREATERTHAN;
03c35bcb 129 }
12516a37
KR
130 if (left_calls < right_calls)
131 {
132 return LESSTHAN;
03c35bcb 133 }
12516a37 134 return EQUALTO;
03c35bcb 135}
5489fcc3
KR
136
137
138/*
139 * Sort members of a cycle.
140 */
141static void
12516a37 142DEFUN (sort_members, (cyc), Sym * cyc)
5489fcc3 143{
12516a37
KR
144 Sym *todo, *doing, *prev;
145 /*
146 * Detach cycle members from cyclehead, and insertion sort them
147 * back on.
148 */
149 todo = cyc->cg.cyc.next;
150 cyc->cg.cyc.next = 0;
151 for (doing = todo; doing && doing->cg.cyc.next; doing = todo)
152 {
153 todo = doing->cg.cyc.next;
154 for (prev = cyc; prev->cg.cyc.next; prev = prev->cg.cyc.next)
155 {
156 if (cmp_member (doing, prev->cg.cyc.next) == GREATERTHAN)
157 {
158 break;
03c35bcb
KR
159 }
160 }
12516a37
KR
161 doing->cg.cyc.next = prev->cg.cyc.next;
162 prev->cg.cyc.next = doing;
03c35bcb
KR
163 }
164}
5489fcc3
KR
165
166
167/*
168 * Print the members of a cycle.
169 */
170static void
12516a37 171DEFUN (print_members, (cyc), Sym * cyc)
5489fcc3 172{
12516a37
KR
173 Sym *member;
174
175 sort_members (cyc);
176 for (member = cyc->cg.cyc.next; member; member = member->cg.cyc.next)
177 {
869b94c5 178 printf (bsd_style_output
8c73afb3
ILT
179 ? "%6.6s %5.5s %7.2f %11.2f %7lu"
180 : "%6.6s %5.5s %7.2f %7.2f %7lu",
12516a37
KR
181 "", "", member->cg.prop.self / hz, member->cg.prop.child / hz,
182 member->ncalls);
183 if (member->cg.self_calls != 0)
184 {
8c73afb3 185 printf ("+%-7lu", member->cg.self_calls);
12516a37
KR
186 }
187 else
188 {
189 printf (" %7.7s", "");
03c35bcb 190 }
12516a37
KR
191 printf (" ");
192 print_name (member);
193 printf ("\n");
03c35bcb
KR
194 }
195}
5489fcc3
KR
196
197
198/*
199 * Compare two arcs to/from the same child/parent.
12516a37
KR
200 * - if one arc is a self arc, it's least.
201 * - if one arc is within a cycle, it's less than.
202 * - if both arcs are within a cycle, compare arc counts.
203 * - if neither arc is within a cycle, compare with
204 * time + child_time as major key
205 * arc count as minor key
5489fcc3
KR
206 */
207static int
12516a37 208DEFUN (cmp_arc, (left, right), Arc * left AND Arc * right)
5489fcc3 209{
12516a37
KR
210 Sym *left_parent = left->parent;
211 Sym *left_child = left->child;
212 Sym *right_parent = right->parent;
213 Sym *right_child = right->child;
214 double left_time, right_time;
215
216 DBG (TIMEDEBUG,
217 printf ("[cmp_arc] ");
218 print_name (left_parent);
219 printf (" calls ");
220 print_name (left_child);
8c73afb3 221 printf (" %f + %f %lu/%lu\n", left->time, left->child_time,
5489fcc3 222 left->count, left_child->ncalls);
12516a37
KR
223 printf ("[cmp_arc] ");
224 print_name (right_parent);
225 printf (" calls ");
226 print_name (right_child);
8c73afb3 227 printf (" %f + %f %lu/%lu\n", right->time, right->child_time,
5489fcc3 228 right->count, right_child->ncalls);
12516a37
KR
229 printf ("\n");
230 );
231 if (left_parent == left_child)
232 {
233 return LESSTHAN; /* left is a self call */
03c35bcb 234 }
12516a37
KR
235 if (right_parent == right_child)
236 {
237 return GREATERTHAN; /* right is a self call */
03c35bcb 238 }
12516a37
KR
239
240 if (left_parent->cg.cyc.num != 0 && left_child->cg.cyc.num != 0
241 && left_parent->cg.cyc.num == left_child->cg.cyc.num)
242 {
243 /* left is a call within a cycle */
244 if (right_parent->cg.cyc.num != 0 && right_child->cg.cyc.num != 0
245 && right_parent->cg.cyc.num == right_child->cg.cyc.num)
246 {
247 /* right is a call within the cycle, too */
248 if (left->count < right->count)
249 {
250 return LESSTHAN;
03c35bcb 251 }
12516a37
KR
252 if (left->count > right->count)
253 {
254 return GREATERTHAN;
03c35bcb 255 }
12516a37
KR
256 return EQUALTO;
257 }
258 else
5489fcc3 259 {
12516a37
KR
260 /* right isn't a call within the cycle */
261 return LESSTHAN;
03c35bcb 262 }
12516a37
KR
263 }
264 else
265 {
266 /* left isn't a call within a cycle */
267 if (right_parent->cg.cyc.num != 0 && right_child->cg.cyc.num != 0
268 && right_parent->cg.cyc.num == right_child->cg.cyc.num)
5489fcc3 269 {
12516a37
KR
270 /* right is a call within a cycle */
271 return GREATERTHAN;
272 }
273 else
274 {
275 /* neither is a call within a cycle */
276 left_time = left->time + left->child_time;
277 right_time = right->time + right->child_time;
278 if (left_time < right_time)
279 {
280 return LESSTHAN;
03c35bcb 281 }
12516a37
KR
282 if (left_time > right_time)
283 {
284 return GREATERTHAN;
03c35bcb 285 }
12516a37
KR
286 if (left->count < right->count)
287 {
288 return LESSTHAN;
03c35bcb 289 }
12516a37
KR
290 if (left->count > right->count)
291 {
292 return GREATERTHAN;
03c35bcb 293 }
12516a37 294 return EQUALTO;
03c35bcb
KR
295 }
296 }
297}
5489fcc3
KR
298
299
300static void
12516a37 301DEFUN (sort_parents, (child), Sym * child)
5489fcc3 302{
12516a37
KR
303 Arc *arc, *detached, sorted, *prev;
304
305 /*
306 * Unlink parents from child, then insertion sort back on to
307 * sorted's parents.
308 * *arc the arc you have detached and are inserting.
309 * *detached the rest of the arcs to be sorted.
310 * sorted arc list onto which you insertion sort.
311 * *prev arc before the arc you are comparing.
312 */
313 sorted.next_parent = 0;
314 for (arc = child->cg.parents; arc; arc = detached)
315 {
316 detached = arc->next_parent;
317
318 /* consider *arc as disconnected; insert it into sorted: */
319 for (prev = &sorted; prev->next_parent; prev = prev->next_parent)
320 {
321 if (cmp_arc (arc, prev->next_parent) != GREATERTHAN)
322 {
323 break;
03c35bcb
KR
324 }
325 }
12516a37
KR
326 arc->next_parent = prev->next_parent;
327 prev->next_parent = arc;
03c35bcb 328 }
12516a37
KR
329
330 /* reattach sorted arcs to child: */
331 child->cg.parents = sorted.next_parent;
03c35bcb 332}
5489fcc3
KR
333
334
335static void
12516a37 336DEFUN (print_parents, (child), Sym * child)
5489fcc3 337{
12516a37
KR
338 Sym *parent;
339 Arc *arc;
340 Sym *cycle_head;
341
342 if (child->cg.cyc.head != 0)
343 {
344 cycle_head = child->cg.cyc.head;
345 }
346 else
347 {
348 cycle_head = child;
03c35bcb 349 }
12516a37
KR
350 if (!child->cg.parents)
351 {
352 printf (bsd_style_output
16a02269
TT
353 ? _("%6.6s %5.5s %7.7s %11.11s %7.7s %7.7s <spontaneous>\n")
354 : _("%6.6s %5.5s %7.7s %7.7s %7.7s %7.7s <spontaneous>\n"),
12516a37
KR
355 "", "", "", "", "", "");
356 return;
03c35bcb 357 }
12516a37
KR
358 sort_parents (child);
359 for (arc = child->cg.parents; arc; arc = arc->next_parent)
360 {
361 parent = arc->parent;
362 if (child == parent || (child->cg.cyc.num != 0
363 && parent->cg.cyc.num == child->cg.cyc.num))
5489fcc3 364 {
12516a37
KR
365 /* selfcall or call among siblings: */
366 printf (bsd_style_output
8c73afb3
ILT
367 ? "%6.6s %5.5s %7.7s %11.11s %7lu %7.7s "
368 : "%6.6s %5.5s %7.7s %7.7s %7lu %7.7s ",
12516a37
KR
369 "", "", "", "",
370 arc->count, "");
371 print_name (parent);
372 printf ("\n");
373 }
374 else
375 {
376 /* regular parent of child: */
377 printf (bsd_style_output
8c73afb3
ILT
378 ? "%6.6s %5.5s %7.2f %11.2f %7lu/%-7lu "
379 : "%6.6s %5.5s %7.2f %7.2f %7lu/%-7lu ",
12516a37
KR
380 "", "",
381 arc->time / hz, arc->child_time / hz,
382 arc->count, cycle_head->ncalls);
383 print_name (parent);
384 printf ("\n");
03c35bcb
KR
385 }
386 }
387}
5489fcc3
KR
388
389
390static void
12516a37 391DEFUN (sort_children, (parent), Sym * parent)
5489fcc3 392{
12516a37
KR
393 Arc *arc, *detached, sorted, *prev;
394 /*
395 * Unlink children from parent, then insertion sort back on to
396 * sorted's children.
397 * *arc the arc you have detached and are inserting.
398 * *detached the rest of the arcs to be sorted.
399 * sorted arc list onto which you insertion sort.
400 * *prev arc before the arc you are comparing.
401 */
402 sorted.next_child = 0;
403 for (arc = parent->cg.children; arc; arc = detached)
404 {
405 detached = arc->next_child;
406
407 /* consider *arc as disconnected; insert it into sorted: */
408 for (prev = &sorted; prev->next_child; prev = prev->next_child)
409 {
410 if (cmp_arc (arc, prev->next_child) != LESSTHAN)
411 {
412 break;
03c35bcb
KR
413 }
414 }
12516a37
KR
415 arc->next_child = prev->next_child;
416 prev->next_child = arc;
03c35bcb 417 }
12516a37
KR
418
419 /* reattach sorted children to parent: */
420 parent->cg.children = sorted.next_child;
03c35bcb 421}
5489fcc3
KR
422
423
424static void
12516a37 425DEFUN (print_children, (parent), Sym * parent)
5489fcc3 426{
12516a37
KR
427 Sym *child;
428 Arc *arc;
429
430 sort_children (parent);
431 arc = parent->cg.children;
432 for (arc = parent->cg.children; arc; arc = arc->next_child)
433 {
434 child = arc->child;
435 if (child == parent || (child->cg.cyc.num != 0
436 && child->cg.cyc.num == parent->cg.cyc.num))
437 {
438 /* self call or call to sibling: */
439 printf (bsd_style_output
8c73afb3
ILT
440 ? "%6.6s %5.5s %7.7s %11.11s %7lu %7.7s "
441 : "%6.6s %5.5s %7.7s %7.7s %7lu %7.7s ",
12516a37
KR
442 "", "", "", "", arc->count, "");
443 print_name (child);
444 printf ("\n");
445 }
446 else
5489fcc3 447 {
12516a37
KR
448 /* regular child of parent: */
449 printf (bsd_style_output
8c73afb3
ILT
450 ? "%6.6s %5.5s %7.2f %11.2f %7lu/%-7lu "
451 : "%6.6s %5.5s %7.2f %7.2f %7lu/%-7lu ",
12516a37
KR
452 "", "",
453 arc->time / hz, arc->child_time / hz,
454 arc->count, child->cg.cyc.head->ncalls);
455 print_name (child);
456 printf ("\n");
03c35bcb
KR
457 }
458 }
459}
5489fcc3
KR
460
461
462static void
12516a37 463DEFUN (print_line, (np), Sym * np)
5489fcc3 464{
12516a37
KR
465 char buf[BUFSIZ];
466
467 sprintf (buf, "[%d]", np->cg.index);
468 printf (bsd_style_output
469 ? "%-6.6s %5.1f %7.2f %11.2f"
470 : "%-6.6s %5.1f %7.2f %7.2f", buf,
471 100 * (np->cg.prop.self + np->cg.prop.child) / print_time,
472 np->cg.prop.self / hz, np->cg.prop.child / hz);
473 if ((np->ncalls + np->cg.self_calls) != 0)
474 {
8c73afb3 475 printf (" %7lu", np->ncalls);
12516a37
KR
476 if (np->cg.self_calls != 0)
477 {
8c73afb3 478 printf ("+%-7lu ", np->cg.self_calls);
12516a37
KR
479 }
480 else
481 {
482 printf (" %7.7s ", "");
03c35bcb 483 }
12516a37
KR
484 }
485 else
486 {
487 printf (" %7.7s %7.7s ", "", "");
03c35bcb 488 }
12516a37
KR
489 print_name (np);
490 printf ("\n");
03c35bcb 491}
5489fcc3
KR
492
493
494/*
495 * Print dynamic call graph.
496 */
497void
12516a37 498DEFUN (cg_print, (timesortsym), Sym ** timesortsym)
5489fcc3 499{
6b84886a 500 unsigned int index;
12516a37 501 Sym *parent;
5489fcc3 502
12516a37
KR
503 if (print_descriptions && bsd_style_output)
504 {
505 bsd_callg_blurb (stdout);
03c35bcb 506 }
5489fcc3 507
12516a37 508 print_header ();
5489fcc3 509
12516a37
KR
510 for (index = 0; index < symtab.len + num_cycles; ++index)
511 {
512 parent = timesortsym[index];
513 if ((ignore_zeros && parent->ncalls == 0
514 && parent->cg.self_calls == 0 && parent->cg.prop.self == 0
515 && parent->cg.prop.child == 0)
7862d7d0
ILT
516 || !parent->cg.print_flag
517 || (line_granularity && ! parent->is_func))
12516a37
KR
518 {
519 continue;
03c35bcb 520 }
12516a37 521 if (!parent->name && parent->cg.cyc.num != 0)
5489fcc3 522 {
12516a37
KR
523 /* cycle header: */
524 print_cycle (parent);
525 print_members (parent);
526 }
527 else
528 {
529 print_parents (parent);
530 print_line (parent);
531 print_children (parent);
03c35bcb 532 }
12516a37
KR
533 if (bsd_style_output)
534 printf ("\n");
535 printf ("-----------------------------------------------\n");
536 if (bsd_style_output)
537 printf ("\n");
5489fcc3 538 }
12516a37
KR
539 free (timesortsym);
540 if (print_descriptions && !bsd_style_output)
541 {
542 fsf_callg_blurb (stdout);
5489fcc3 543 }
03c35bcb 544}
5489fcc3
KR
545
546
547static int
12516a37 548DEFUN (cmp_name, (left, right), const PTR left AND const PTR right)
5489fcc3 549{
12516a37
KR
550 const Sym **npp1 = (const Sym **) left;
551 const Sym **npp2 = (const Sym **) right;
5489fcc3 552
12516a37 553 return strcmp ((*npp1)->name, (*npp2)->name);
03c35bcb 554}
5489fcc3
KR
555
556
557void
12516a37 558DEFUN_VOID (cg_print_index)
5489fcc3 559{
6b84886a
ILT
560 unsigned int index;
561 unsigned int nnames, todo, i, j;
562 int col, starting_col;
12516a37
KR
563 Sym **name_sorted_syms, *sym;
564 const char *filename;
565 char buf[20];
566 int column_width = (output_width - 1) / 3; /* don't write in last col! */
567 /*
568 * Now, sort regular function name alphabetically to create an
569 * index:
570 */
571 name_sorted_syms = (Sym **) xmalloc ((symtab.len + num_cycles) * sizeof (Sym *));
572 for (index = 0, nnames = 0; index < symtab.len; index++)
573 {
574 if (ignore_zeros && symtab.base[index].ncalls == 0
575 && symtab.base[index].hist.time == 0)
576 {
577 continue;
03c35bcb 578 }
12516a37 579 name_sorted_syms[nnames++] = &symtab.base[index];
03c35bcb 580 }
12516a37
KR
581 qsort (name_sorted_syms, nnames, sizeof (Sym *), cmp_name);
582 for (index = 1, todo = nnames; index <= num_cycles; index++)
583 {
584 name_sorted_syms[todo++] = &cycle_header[index];
03c35bcb 585 }
eb5382d2
ILT
586 printf ("\f\n");
587 printf (_("Index by function name\n\n"));
12516a37
KR
588 index = (todo + 2) / 3;
589 for (i = 0; i < index; i++)
590 {
591 col = 0;
592 starting_col = 0;
593 for (j = i; j < todo; j += index)
5489fcc3 594 {
12516a37
KR
595 sym = name_sorted_syms[j];
596 if (sym->cg.print_flag)
597 {
598 sprintf (buf, "[%d]", sym->cg.index);
599 }
600 else
601 {
602 sprintf (buf, "(%d)", sym->cg.index);
03c35bcb 603 }
12516a37
KR
604 if (j < nnames)
605 {
606 if (bsd_style_output)
607 {
608 printf ("%6.6s %-19.19s", buf, sym->name);
609 }
610 else
611 {
612 col += strlen (buf);
613 for (; col < starting_col + 5; ++col)
614 {
615 putchar (' ');
03c35bcb 616 }
12516a37
KR
617 printf (" %s ", buf);
618 col += print_name_only (sym);
619 if (!line_granularity && sym->is_static && sym->file)
620 {
621 filename = sym->file->name;
622 if (!print_path)
623 {
624 filename = strrchr (filename, '/');
625 if (filename)
626 {
627 ++filename;
628 }
629 else
630 {
631 filename = sym->file->name;
03c35bcb
KR
632 }
633 }
12516a37
KR
634 printf (" (%s)", filename);
635 col += strlen (filename) + 3;
03c35bcb
KR
636 }
637 }
12516a37
KR
638 }
639 else
640 {
869b94c5
KR
641 if (bsd_style_output)
642 {
643 printf ("%6.6s ", buf);
16a02269 644 sprintf (buf, _("<cycle %d>"), sym->cg.cyc.num);
869b94c5
KR
645 printf ("%-19.19s", buf);
646 }
647 else
648 {
649 col += strlen (buf);
650 for (; col < starting_col + 5; ++col)
651 putchar (' ');
652 printf (" %s ", buf);
16a02269 653 sprintf (buf, _("<cycle %d>"), sym->cg.cyc.num);
869b94c5
KR
654 printf ("%s", buf);
655 col += strlen (buf);
656 }
03c35bcb 657 }
12516a37 658 starting_col += column_width;
03c35bcb 659 }
12516a37 660 printf ("\n");
03c35bcb 661 }
12516a37 662 free (name_sorted_syms);
03c35bcb 663}
64c50fc5
JL
664
665/* Compare two arcs based on their usage counts. We want to sort
666 in descending order. */
667static int
668DEFUN (cmp_arc_count, (left, right), const PTR left AND const PTR right)
669{
670 const Arc **npp1 = (const Arc **) left;
671 const Arc **npp2 = (const Arc **) right;
672
673 if ((*npp1)->count > (*npp2)->count)
674 return -1;
675 else if ((*npp1)->count < (*npp2)->count)
676 return 1;
677 else
678 return 0;
679}
680
681/* Compare two funtions based on their usage counts. We want to sort
682 in descending order. */
683static int
684DEFUN (cmp_fun_nuses, (left, right), const PTR left AND const PTR right)
685{
686 const Sym **npp1 = (const Sym **) left;
687 const Sym **npp2 = (const Sym **) right;
688
689 if ((*npp1)->nuses > (*npp2)->nuses)
690 return -1;
691 else if ((*npp1)->nuses < (*npp2)->nuses)
692 return 1;
693 else
694 return 0;
695}
696
697/* Print a suggested function ordering based on the profiling data.
698
699 We perform 4 major steps when ordering functions:
700
701 * Group unused functions together and place them at the
702 end of the function order.
703
704 * Search the highest use arcs (those which account for 90% of
705 the total arc count) for functions which have several parents.
706
707 Group those with the most call sites together (currently the
708 top 1.25% which have at least five different call sites).
709
710 These are emitted at the start of the function order.
711
712 * Use a greedy placement algorithm to place functions which
713 occur in the top 99% of the arcs in the profile. Some provisions
714 are made to handle high usage arcs where the parent and/or
715 child has already been placed.
716
717 * Run the same greedy placement algorithm on the remaining
718 arcs to place the leftover functions.
719
720
721 The various "magic numbers" should (one day) be tuneable by command
722 line options. They were arrived at by benchmarking a few applications
723 with various values to see which values produced better overall function
724 orderings.
725
726 Of course, profiling errors, machine limitations (PA long calls), and
727 poor cutoff values for the placement algorithm may limit the usefullness
728 of the resulting function order. Improvements would be greatly appreciated.
729
730 Suggestions:
731
732 * Place the functions with many callers near the middle of the
733 list to reduce long calls.
734
735 * Propagate arc usage changes as functions are placed. Ie if
736 func1 and func2 are placed together, arcs to/from those arcs
737 to the same parent/child should be combined, then resort the
738 arcs to choose the next one.
739
740 * Implement some global positioning algorithm to place the
741 chains made by the greedy local positioning algorithm. Probably
742 by examining arcs which haven't been placed yet to tie two
743 chains together.
744
745 * Take a function's size and time into account in the algorithm;
746 size in particular is important on the PA (long calls). Placing
747 many small functions onto their own page may be wise.
748
749 * Use better profiling information; many published algorithms
750 are based on call sequences through time, rather than just
751 arc counts.
752
753 * Prodecure cloning could improve performance when a small number
754 of arcs account for most of the calls to a particular function.
755
756 * Use relocation information to avoid moving unused functions
757 completely out of the code stream; this would avoid severe lossage
758 when the profile data bears little resemblance to actual runs.
759
760 * Propagation of arc usages should also improve .o link line
761 ordering which shares the same arc placement algorithm with
762 the function ordering code (in fact it is a degenerate case
763 of function ordering). */
764
765void
766DEFUN_VOID (cg_print_function_ordering)
767{
768 unsigned long index, used, unused, scratch_index;
769 unsigned long unplaced_arc_count, high_arc_count, scratch_arc_count;
7a542ed9 770#ifdef __GNUC__
64c50fc5
JL
771 unsigned long long total_arcs, tmp_arcs_count;
772#else
773 unsigned long total_arcs, tmp_arcs_count;
774#endif
775 Sym **unused_syms, **used_syms, **scratch_syms;
776 Arc **unplaced_arcs, **high_arcs, **scratch_arcs;
777
778 index = 0;
779 used = 0;
780 unused = 0;
781 scratch_index = 0;
782 unplaced_arc_count = 0;
783 high_arc_count = 0;
784 scratch_arc_count = 0;
785
786 /* First group all the unused functions together. */
787 unused_syms = (Sym **) xmalloc (symtab.len * sizeof (Sym *));
788 used_syms = (Sym **) xmalloc (symtab.len * sizeof (Sym *));
789 scratch_syms = (Sym **) xmalloc (symtab.len * sizeof (Sym *));
790 high_arcs = (Arc **) xmalloc (numarcs * sizeof (Arc *));
791 scratch_arcs = (Arc **) xmalloc (numarcs * sizeof (Arc *));
792 unplaced_arcs = (Arc **) xmalloc (numarcs * sizeof (Arc *));
793
794 /* Walk through all the functions; mark those which are never
795 called as placed (we'll emit them as a group later). */
796 for (index = 0, used = 0, unused = 0; index < symtab.len; index++)
797 {
798 if (symtab.base[index].ncalls == 0)
799 {
800 /* Filter out gprof generated names. */
801 if (strcmp (symtab.base[index].name, "<locore>")
802 && strcmp (symtab.base[index].name, "<hicore>"))
803 {
804 unused_syms[unused++] = &symtab.base[index];
805 symtab.base[index].has_been_placed = 1;
806 }
807 }
808 else
809 {
810 used_syms[used++] = &symtab.base[index];
811 symtab.base[index].has_been_placed = 0;
812 symtab.base[index].next = 0;
813 symtab.base[index].prev = 0;
814 symtab.base[index].nuses = 0;
815 }
816 }
817
818 /* Sort the arcs from most used to least used. */
819 qsort (arcs, numarcs, sizeof (Arc *), cmp_arc_count);
820
821 /* Compute the total arc count. Also mark arcs as unplaced.
822
823 Note we don't compensate for overflow if that happens!
824 Overflow is much less likely when this file is compiled
825 with GCC as it can double-wide integers via long long. */
826 total_arcs = 0;
827 for (index = 0; index < numarcs; index++)
828 {
829 total_arcs += arcs[index]->count;
830 arcs[index]->has_been_placed = 0;
831 }
832
833 /* We want to pull out those functions which are referenced
834 by many highly used arcs and emit them as a group. This
835 could probably use some tuning. */
836 tmp_arcs_count = 0;
837 for (index = 0; index < numarcs; index++)
838 {
839 tmp_arcs_count += arcs[index]->count;
840
841 /* Count how many times each parent and child are used up
842 to our threshhold of arcs (90%). */
843 if ((double)tmp_arcs_count / (double)total_arcs > 0.90)
844 break;
845
846 arcs[index]->child->nuses++;
847 }
848
849 /* Now sort a temporary symbol table based on the number of
850 times each function was used in the highest used arcs. */
df928c8f 851 memcpy (scratch_syms, used_syms, used * sizeof (Sym *));
64c50fc5
JL
852 qsort (scratch_syms, used, sizeof (Sym *), cmp_fun_nuses);
853
854 /* Now pick out those symbols we're going to emit as
855 a group. We take up to 1.25% of the used symbols. */
856 for (index = 0; index < used / 80; index++)
857 {
858 Sym *sym = scratch_syms[index];
859 Arc *arc;
860
861 /* If we hit symbols that aren't used from many call sites,
862 then we can quit. We choose five as the low limit for
863 no particular reason. */
864 if (sym->nuses == 5)
865 break;
866
867 /* We're going to need the arcs between these functions.
868 Unfortunately, we don't know all these functions
869 until we're done. So we keep track of all the arcs
870 to the functions we care about, then prune out those
871 which are uninteresting.
872
873 An interesting variation would be to quit when we found
874 multi-call site functions which account for some percentage
875 of the arcs. */
876
877 arc = sym->cg.children;
878 while (arc)
879 {
880 if (arc->parent != arc->child)
881 scratch_arcs[scratch_arc_count++] = arc;
882 arc->has_been_placed = 1;
883 arc = arc->next_child;
884 }
885
886 arc = sym->cg.parents;
887 while (arc)
888 {
889 if (arc->parent != arc->child)
890 scratch_arcs[scratch_arc_count++] = arc;
891 arc->has_been_placed = 1;
892 arc = arc->next_parent;
893 }
894
895 /* Keep track of how many symbols we're going to place. */
896 scratch_index = index;
897
898 /* A lie, but it makes identifying these functions easier
899 later. */
900 sym->has_been_placed = 1;
901 }
902
903 /* Now walk through the temporary arcs and copy those we care about
904 into the high arcs array. */
905 for (index = 0; index < scratch_arc_count; index++)
906 {
907 Arc *arc = scratch_arcs[index];
908
909 /* If this arc refers to highly used functions, then
910 then we want to keep it. */
911 if (arc->child->has_been_placed
912 && arc->parent->has_been_placed)
913 {
914 high_arcs[high_arc_count++] = scratch_arcs[index];
915
916 /* We need to turn of has_been_placed since we're going to
917 use the main arc placement algorithm on these arcs. */
918 arc->child->has_been_placed = 0;
919 arc->parent->has_been_placed = 0;
920 }
921 }
922
923 /* Dump the multi-site high usage functions which are not going
924 to be ordered by the main ordering algorithm. */
925 for (index = 0; index < scratch_index; index++)
926 {
927 if (scratch_syms[index]->has_been_placed)
928 printf ("%s\n", scratch_syms[index]->name);
929 }
930
931 /* Now we can order the multi-site high use functions based on the
932 arcs between them. */
933 qsort (high_arcs, high_arc_count, sizeof (Arc *), cmp_arc_count);
934 order_and_dump_functions_by_arcs (high_arcs, high_arc_count, 1,
935 unplaced_arcs, &unplaced_arc_count);
936
937 /* Order and dump the high use functions left, these typically
938 have only a few call sites. */
939 order_and_dump_functions_by_arcs (arcs, numarcs, 0,
940 unplaced_arcs, &unplaced_arc_count);
941
942 /* Now place the rarely used functions. */
943 order_and_dump_functions_by_arcs (unplaced_arcs, unplaced_arc_count, 1,
944 scratch_arcs, &scratch_arc_count);
945
946 /* Output any functions not emitted by the order_and_dump calls. */
947 for (index = 0; index < used; index++)
948 if (used_syms[index]->has_been_placed == 0)
949 printf("%s\n", used_syms[index]->name);
950
951 /* Output the unused functions. */
952 for (index = 0; index < unused; index++)
953 printf("%s\n", unused_syms[index]->name);
954
955 unused_syms = (Sym **) xmalloc (symtab.len * sizeof (Sym *));
956 used_syms = (Sym **) xmalloc (symtab.len * sizeof (Sym *));
957 scratch_syms = (Sym **) xmalloc (symtab.len * sizeof (Sym *));
958 high_arcs = (Arc **) xmalloc (numarcs * sizeof (Arc *));
959 scratch_arcs = (Arc **) xmalloc (numarcs * sizeof (Arc *));
960 unplaced_arcs = (Arc **) xmalloc (numarcs * sizeof (Arc *));
961
962 free (unused_syms);
963 free (used_syms);
964 free (scratch_syms);
965 free (high_arcs);
966 free (scratch_arcs);
967 free (unplaced_arcs);
968}
969
970/* Place functions based on the arcs in ARCS with NUMARCS entries;
971 place unused arcs into UNPLACED_ARCS/UNPLACED_ARC_COUNT.
972
973 If ALL is nonzero, then place all functions referenced by ARCS,
974 else only place those referenced in the top 99% of the arcs in ARCS. */
975
976#define MOST 0.99
977static void
978order_and_dump_functions_by_arcs (arcs, numarcs, all,
979 unplaced_arcs, unplaced_arc_count)
980 Arc **arcs;
981 unsigned long numarcs;
982 int all;
983 Arc **unplaced_arcs;
984 unsigned long *unplaced_arc_count;
985{
7a542ed9 986#ifdef __GNUC__
64c50fc5
JL
987 unsigned long long tmp_arcs, total_arcs;
988#else
989 unsigned long tmp_arcs, total_arcs;
990#endif
991 unsigned int index;
992
993 /* If needed, compute the total arc count.
994
995 Note we don't compensate for overflow if that happens! */
996 if (! all)
997 {
998 total_arcs = 0;
999 for (index = 0; index < numarcs; index++)
1000 total_arcs += arcs[index]->count;
1001 }
1002 else
1003 total_arcs = 0;
1004
1005 tmp_arcs = 0;
1006 for (index = 0; index < numarcs; index++)
1007 {
1008 Sym *sym1, *sym2;
1009 Sym *child, *parent;
1010
1011 tmp_arcs += arcs[index]->count;
1012
1013 /* Ignore this arc if it's already been placed. */
1014 if (arcs[index]->has_been_placed)
1015 continue;
1016
1017 child = arcs[index]->child;
1018 parent = arcs[index]->parent;
1019
1020 /* If we're not using all arcs, and this is a rarely used
1021 arc, then put it on the unplaced_arc list. Similarly
1022 if both the parent and child of this arc have been placed. */
1023 if ((! all && (double)tmp_arcs / (double)total_arcs > MOST)
1024 || child->has_been_placed || parent->has_been_placed)
1025 {
1026 unplaced_arcs[(*unplaced_arc_count)++] = arcs[index];
1027 continue;
1028 }
1029
1030 /* If all slots in the parent and child are full, then there isn't
1031 anything we can do right now. We'll place this arc on the
1032 unplaced arc list in the hope that a global positioning
1033 algorithm can use it to place function chains. */
1034 if (parent->next && parent->prev && child->next && child->prev)
1035 {
1036 unplaced_arcs[(*unplaced_arc_count)++] = arcs[index];
1037 continue;
1038 }
1039
1040 /* If the parent is unattached, then find the closest
1041 place to attach it onto child's chain. Similarly
1042 for the opposite case. */
1043 if (!parent->next && !parent->prev)
1044 {
1045 int next_count = 0;
1046 int prev_count = 0;
1047 Sym *prev = child;
1048 Sym *next = child;
1049
1050 /* Walk to the beginning and end of the child's chain. */
1051 while (next->next)
1052 {
1053 next = next->next;
1054 next_count++;
1055 }
1056
1057 while (prev->prev)
1058 {
1059 prev = prev->prev;
1060 prev_count++;
1061 }
1062
1063 /* Choose the closest. */
1064 child = next_count < prev_count ? next : prev;
1065 }
1066 else if (! child->next && !child->prev)
1067 {
1068 int next_count = 0;
1069 int prev_count = 0;
1070 Sym *prev = parent;
1071 Sym *next = parent;
1072
1073 while (next->next)
1074 {
1075 next = next->next;
1076 next_count++;
1077 }
1078
1079 while (prev->prev)
1080 {
1081 prev = prev->prev;
1082 prev_count++;
1083 }
1084
1085 parent = prev_count < next_count ? prev : next;
1086 }
1087 else
1088 {
1089 /* Couldn't find anywhere to attach the functions,
1090 put the arc on the unplaced arc list. */
1091 unplaced_arcs[(*unplaced_arc_count)++] = arcs[index];
1092 continue;
1093 }
1094
1095 /* Make sure we don't tie two ends together. */
1096 sym1 = parent;
1097 if (sym1->next)
1098 while (sym1->next)
1099 sym1 = sym1->next;
1100 else
1101 while (sym1->prev)
1102 sym1 = sym1->prev;
1103
1104 sym2 = child;
1105 if (sym2->next)
1106 while (sym2->next)
1107 sym2 = sym2->next;
1108 else
1109 while (sym2->prev)
1110 sym2 = sym2->prev;
1111
1112 if (sym1 == child
1113 && sym2 == parent)
1114 {
1115 /* This would tie two ends together. */
1116 unplaced_arcs[(*unplaced_arc_count)++] = arcs[index];
1117 continue;
1118 }
1119
1120 if (parent->next)
1121 {
1122 /* Must attach to the parent's prev field. */
1123 if (! child->next)
1124 {
1125 /* parent-prev and child-next */
1126 parent->prev = child;
1127 child->next = parent;
1128 arcs[index]->has_been_placed = 1;
1129 }
1130 }
1131 else if (parent->prev)
1132 {
1133 /* Must attach to the parent's next field. */
1134 if (! child->prev)
1135 {
1136 /* parent-next and child-prev */
1137 parent->next = child;
1138 child->prev = parent;
1139 arcs[index]->has_been_placed = 1;
1140 }
1141 }
1142 else
1143 {
1144 /* Can attach to either field in the parent, depends
1145 on where we've got space in the child. */
1146 if (child->prev)
1147 {
1148 /* parent-prev and child-next */
1149 parent->prev = child;
1150 child->next = parent;
1151 arcs[index]->has_been_placed = 1;
1152 }
1153 else
1154 {
1155 /* parent-next and child-prev */
1156 parent->next = child;
1157 child->prev = parent;
1158 arcs[index]->has_been_placed = 1;
1159 }
1160 }
1161 }
1162
1163 /* Dump the chains of functions we've made. */
1164 for (index = 0; index < numarcs; index++)
1165 {
1166 Sym *sym;
1167 if (arcs[index]->parent->has_been_placed
1168 || arcs[index]->child->has_been_placed)
1169 continue;
1170
1171 sym = arcs[index]->parent;
1172
1173 /* If this symbol isn't attached to any other
1174 symbols, then we've got a rarely used arc.
1175
1176 Skip it for now, we'll deal with them later. */
1177 if (sym->next == NULL
1178 && sym->prev == NULL)
1179 continue;
1180
1181 /* Get to the start of this chain. */
1182 while (sym->prev)
1183 sym = sym->prev;
1184
1185 while (sym)
1186 {
1187 /* Mark it as placed. */
1188 sym->has_been_placed = 1;
1189 printf ("%s\n", sym->name);
1190 sym = sym->next;
1191 }
1192 }
1193
1194 /* If we want to place all the arcs, then output those which weren't
1195 placed by the main algorithm. */
1196 if (all)
1197 for (index = 0; index < numarcs; index++)
1198 {
1199 Sym *sym;
1200 if (arcs[index]->parent->has_been_placed
1201 || arcs[index]->child->has_been_placed)
1202 continue;
1203
1204 sym = arcs[index]->parent;
1205
1206 sym->has_been_placed = 1;
1207 printf ("%s\n", sym->name);
1208 }
1209}
1210
1211/* Print a suggested .o ordering for files on a link line based
1212 on profiling information. This uses the function placement
1213 code for the bulk of its work. */
1214
1215struct function_map {
1216 char *function_name;
1217 char *file_name;
1218};
1219
1220void
1221DEFUN_VOID (cg_print_file_ordering)
1222{
1223 unsigned long scratch_arc_count, index;
1224 Arc **scratch_arcs;
1225 extern struct function_map *symbol_map;
6b84886a 1226 extern unsigned int symbol_map_count;
64c50fc5
JL
1227 char *last;
1228
1229 scratch_arc_count = 0;
1230
1231 scratch_arcs = (Arc **) xmalloc (numarcs * sizeof (Arc *));
1232 for (index = 0; index < numarcs; index++)
1233 {
1234 if (! arcs[index]->parent->mapped
1235 || ! arcs[index]->child->mapped)
1236 arcs[index]->has_been_placed = 1;
1237 }
1238
1239 order_and_dump_functions_by_arcs (arcs, numarcs, 0,
1240 scratch_arcs, &scratch_arc_count);
1241
1242 /* Output .o's not handled by the main placement algorithm. */
1243 for (index = 0; index < symtab.len; index++)
1244 {
1245 if (symtab.base[index].mapped
1246 && ! symtab.base[index].has_been_placed)
1247 printf ("%s\n", symtab.base[index].name);
1248 }
1249
1250 /* Now output any .o's that didn't have any text symbols. */
1251 last = NULL;
1252 for (index = 0; index < symbol_map_count; index++)
1253 {
6b84886a 1254 unsigned int index2;
64c50fc5
JL
1255
1256 /* Don't bother searching if this symbol is the
1257 same as the previous one. */
1258 if (last && !strcmp (last, symbol_map[index].file_name))
1259 continue;
1260
1261 for (index2 = 0; index2 < symtab.len; index2++)
1262 {
1263 if (! symtab.base[index2].mapped)
1264 continue;
1265
1266 if (!strcmp (symtab.base[index2].name, symbol_map[index].file_name))
1267 break;
1268 }
1269
1270 /* If we didn't find it in the symbol table, then it must be a .o
1271 with no text symbols. Output it last. */
1272 if (index2 == symtab.len)
1273 printf ("%s\n", symbol_map[index].file_name);
1274 last = symbol_map[index].file_name;
1275 }
1276}