Home | History | Annotate | Line # | Download | only in gprof
      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