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