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