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