xref: /openbsd-src/gnu/usr.bin/binutils/gprof/cg_arcs.c (revision c074d1c999f3e07019cd5e9a2f190b057ef3b935)
12159047fSniklas /*
26e421504Sfgsch  * Copyright (c) 1983, 1993, 2001
36e421504Sfgsch  *      The Regents of the University of California.  All rights reserved.
42159047fSniklas  *
56e421504Sfgsch  * Redistribution and use in source and binary forms, with or without
66e421504Sfgsch  * modification, are permitted provided that the following conditions
76e421504Sfgsch  * are met:
86e421504Sfgsch  * 1. Redistributions of source code must retain the above copyright
96e421504Sfgsch  *    notice, this list of conditions and the following disclaimer.
106e421504Sfgsch  * 2. Redistributions in binary form must reproduce the above copyright
116e421504Sfgsch  *    notice, this list of conditions and the following disclaimer in the
126e421504Sfgsch  *    documentation and/or other materials provided with the distribution.
136e421504Sfgsch  * 3. Neither the name of the University nor the names of its contributors
146e421504Sfgsch  *    may be used to endorse or promote products derived from this software
156e421504Sfgsch  *    without specific prior written permission.
166e421504Sfgsch  *
176e421504Sfgsch  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
186e421504Sfgsch  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
196e421504Sfgsch  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
206e421504Sfgsch  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
216e421504Sfgsch  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
226e421504Sfgsch  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
236e421504Sfgsch  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
246e421504Sfgsch  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
256e421504Sfgsch  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
266e421504Sfgsch  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
276e421504Sfgsch  * SUCH DAMAGE.
282159047fSniklas  */
292159047fSniklas #include "libiberty.h"
302159047fSniklas #include "gprof.h"
31*c074d1c9Sdrahn #include "search_list.h"
32*c074d1c9Sdrahn #include "source.h"
33*c074d1c9Sdrahn #include "symtab.h"
342159047fSniklas #include "call_graph.h"
352159047fSniklas #include "cg_arcs.h"
362159047fSniklas #include "cg_dfn.h"
372159047fSniklas #include "cg_print.h"
382159047fSniklas #include "utils.h"
392159047fSniklas #include "sym_ids.h"
402159047fSniklas 
41*c074d1c9Sdrahn static int cmp_topo PARAMS ((const PTR, const PTR));
42*c074d1c9Sdrahn static void propagate_time PARAMS ((Sym *));
43*c074d1c9Sdrahn static void cycle_time PARAMS ((void));
44*c074d1c9Sdrahn static void cycle_link PARAMS ((void));
45*c074d1c9Sdrahn static void inherit_flags PARAMS ((Sym *));
46*c074d1c9Sdrahn static void propagate_flags PARAMS ((Sym **));
47*c074d1c9Sdrahn static int cmp_total PARAMS ((const PTR, const PTR));
48*c074d1c9Sdrahn 
492159047fSniklas Sym *cycle_header;
50b305b0f1Sespie unsigned int num_cycles;
51191aa565Sniklas Arc **arcs;
52b305b0f1Sespie unsigned int numarcs;
532159047fSniklas 
542159047fSniklas /*
552159047fSniklas  * Return TRUE iff PARENT has an arc to covers the address
562159047fSniklas  * range covered by CHILD.
572159047fSniklas  */
582159047fSniklas Arc *
arc_lookup(parent,child)59*c074d1c9Sdrahn arc_lookup (parent, child)
60*c074d1c9Sdrahn      Sym *parent;
61*c074d1c9Sdrahn      Sym *child;
622159047fSniklas {
632159047fSniklas   Arc *arc;
642159047fSniklas 
652159047fSniklas   if (!parent || !child)
662159047fSniklas     {
672159047fSniklas       printf ("[arc_lookup] parent == 0 || child == 0\n");
682159047fSniklas       return 0;
692159047fSniklas     }
702159047fSniklas   DBG (LOOKUPDEBUG, printf ("[arc_lookup] parent %s child %s\n",
712159047fSniklas 			    parent->name, child->name));
722159047fSniklas   for (arc = parent->cg.children; arc; arc = arc->next_child)
732159047fSniklas     {
742159047fSniklas       DBG (LOOKUPDEBUG, printf ("[arc_lookup]\t parent %s child %s\n",
752159047fSniklas 				arc->parent->name, arc->child->name));
762159047fSniklas       if (child->addr >= arc->child->addr
772159047fSniklas 	  && child->end_addr <= arc->child->end_addr)
782159047fSniklas 	{
792159047fSniklas 	  return arc;
802159047fSniklas 	}
812159047fSniklas     }
822159047fSniklas   return 0;
832159047fSniklas }
842159047fSniklas 
852159047fSniklas 
862159047fSniklas /*
872159047fSniklas  * Add (or just increment) an arc:
882159047fSniklas  */
892159047fSniklas void
arc_add(parent,child,count)90*c074d1c9Sdrahn arc_add (parent, child, count)
91*c074d1c9Sdrahn      Sym *parent;
92*c074d1c9Sdrahn      Sym *child;
93*c074d1c9Sdrahn      unsigned long count;
942159047fSniklas {
95b305b0f1Sespie   static unsigned int maxarcs = 0;
96191aa565Sniklas   Arc *arc, **newarcs;
972159047fSniklas 
98b305b0f1Sespie   DBG (TALLYDEBUG, printf ("[arc_add] %lu arcs from %s to %s\n",
992159047fSniklas 			   count, parent->name, child->name));
1002159047fSniklas   arc = arc_lookup (parent, child);
1012159047fSniklas   if (arc)
1022159047fSniklas     {
1032159047fSniklas       /*
1042159047fSniklas        * A hit: just increment the count.
1052159047fSniklas        */
106b305b0f1Sespie       DBG (TALLYDEBUG, printf ("[tally] hit %lu += %lu\n",
1072159047fSniklas 			       arc->count, count));
1082159047fSniklas       arc->count += count;
1092159047fSniklas       return;
1102159047fSniklas     }
1112159047fSniklas   arc = (Arc *) xmalloc (sizeof (*arc));
1126a4c786fSespie   memset (arc, 0, sizeof (*arc));
1132159047fSniklas   arc->parent = parent;
1142159047fSniklas   arc->child = child;
1152159047fSniklas   arc->count = count;
1162159047fSniklas 
117191aa565Sniklas   /* If this isn't an arc for a recursive call to parent, then add it
118191aa565Sniklas      to the array of arcs.  */
119191aa565Sniklas   if (parent != child)
120191aa565Sniklas     {
121191aa565Sniklas       /* If we've exhausted space in our current array, get a new one
122191aa565Sniklas 	 and copy the contents.   We might want to throttle the doubling
123191aa565Sniklas 	 factor one day.  */
124191aa565Sniklas       if (numarcs == maxarcs)
125191aa565Sniklas 	{
126191aa565Sniklas 	  /* Determine how much space we want to allocate.  */
127191aa565Sniklas 	  if (maxarcs == 0)
128191aa565Sniklas 	    maxarcs = 1;
129191aa565Sniklas 	  maxarcs *= 2;
130191aa565Sniklas 
131191aa565Sniklas 	  /* Allocate the new array.  */
132191aa565Sniklas 	  newarcs = (Arc **)xmalloc(sizeof (Arc *) * maxarcs);
133191aa565Sniklas 
134191aa565Sniklas 	  /* Copy the old array's contents into the new array.  */
135191aa565Sniklas 	  memcpy (newarcs, arcs, numarcs * sizeof (Arc *));
136191aa565Sniklas 
137191aa565Sniklas 	  /* Free up the old array.  */
138191aa565Sniklas 	  free (arcs);
139191aa565Sniklas 
140191aa565Sniklas 	  /* And make the new array be the current array.  */
141191aa565Sniklas 	  arcs = newarcs;
142191aa565Sniklas 	}
143191aa565Sniklas 
144191aa565Sniklas       /* Place this arc in the arc array.  */
145191aa565Sniklas       arcs[numarcs++] = arc;
146191aa565Sniklas     }
147191aa565Sniklas 
1482159047fSniklas   /* prepend this child to the children of this parent: */
1492159047fSniklas   arc->next_child = parent->cg.children;
1502159047fSniklas   parent->cg.children = arc;
1512159047fSniklas 
1522159047fSniklas   /* prepend this parent to the parents of this child: */
1532159047fSniklas   arc->next_parent = child->cg.parents;
1542159047fSniklas   child->cg.parents = arc;
1552159047fSniklas }
1562159047fSniklas 
1572159047fSniklas 
1582159047fSniklas static int
cmp_topo(lp,rp)159*c074d1c9Sdrahn cmp_topo (lp, rp)
160*c074d1c9Sdrahn      const PTR lp;
161*c074d1c9Sdrahn      const PTR rp;
1622159047fSniklas {
1632159047fSniklas   const Sym *left = *(const Sym **) lp;
1642159047fSniklas   const Sym *right = *(const Sym **) rp;
1652159047fSniklas 
1662159047fSniklas   return left->cg.top_order - right->cg.top_order;
1672159047fSniklas }
1682159047fSniklas 
1692159047fSniklas 
1702159047fSniklas static void
propagate_time(parent)171*c074d1c9Sdrahn propagate_time (parent)
172*c074d1c9Sdrahn      Sym *parent;
1732159047fSniklas {
1742159047fSniklas   Arc *arc;
1752159047fSniklas   Sym *child;
1762159047fSniklas   double share, prop_share;
1772159047fSniklas 
1782159047fSniklas   if (parent->cg.prop.fract == 0.0)
1792159047fSniklas     {
1802159047fSniklas       return;
1812159047fSniklas     }
1822159047fSniklas 
1832159047fSniklas   /* gather time from children of this parent: */
1842159047fSniklas 
1852159047fSniklas   for (arc = parent->cg.children; arc; arc = arc->next_child)
1862159047fSniklas     {
1872159047fSniklas       child = arc->child;
1882159047fSniklas       if (arc->count == 0 || child == parent || child->cg.prop.fract == 0)
1892159047fSniklas 	{
1902159047fSniklas 	  continue;
1912159047fSniklas 	}
1922159047fSniklas       if (child->cg.cyc.head != child)
1932159047fSniklas 	{
1942159047fSniklas 	  if (parent->cg.cyc.num == child->cg.cyc.num)
1952159047fSniklas 	    {
1962159047fSniklas 	      continue;
1972159047fSniklas 	    }
1982159047fSniklas 	  if (parent->cg.top_order <= child->cg.top_order)
1992159047fSniklas 	    {
2002159047fSniklas 	      fprintf (stderr, "[propagate] toporder botches\n");
2012159047fSniklas 	    }
2022159047fSniklas 	  child = child->cg.cyc.head;
2032159047fSniklas 	}
2042159047fSniklas       else
2052159047fSniklas 	{
2062159047fSniklas 	  if (parent->cg.top_order <= child->cg.top_order)
2072159047fSniklas 	    {
2082159047fSniklas 	      fprintf (stderr, "[propagate] toporder botches\n");
2092159047fSniklas 	      continue;
2102159047fSniklas 	    }
2112159047fSniklas 	}
2122159047fSniklas       if (child->ncalls == 0)
2132159047fSniklas 	{
2142159047fSniklas 	  continue;
2152159047fSniklas 	}
2162159047fSniklas 
2172159047fSniklas       /* distribute time for this arc: */
2182159047fSniklas       arc->time = child->hist.time * (((double) arc->count)
2192159047fSniklas 				      / ((double) child->ncalls));
2202159047fSniklas       arc->child_time = child->cg.child_time
2212159047fSniklas 	* (((double) arc->count) / ((double) child->ncalls));
2222159047fSniklas       share = arc->time + arc->child_time;
2232159047fSniklas       parent->cg.child_time += share;
2242159047fSniklas 
2252159047fSniklas       /* (1 - cg.prop.fract) gets lost along the way: */
2262159047fSniklas       prop_share = parent->cg.prop.fract * share;
2272159047fSniklas 
2282159047fSniklas       /* fix things for printing: */
2292159047fSniklas       parent->cg.prop.child += prop_share;
2302159047fSniklas       arc->time *= parent->cg.prop.fract;
2312159047fSniklas       arc->child_time *= parent->cg.prop.fract;
2322159047fSniklas 
2332159047fSniklas       /* add this share to the parent's cycle header, if any: */
2342159047fSniklas       if (parent->cg.cyc.head != parent)
2352159047fSniklas 	{
2362159047fSniklas 	  parent->cg.cyc.head->cg.child_time += share;
2372159047fSniklas 	  parent->cg.cyc.head->cg.prop.child += prop_share;
2382159047fSniklas 	}
2392159047fSniklas       DBG (PROPDEBUG,
2402159047fSniklas 	   printf ("[prop_time] child \t");
2412159047fSniklas 	   print_name (child);
242b305b0f1Sespie 	   printf (" with %f %f %lu/%lu\n", child->hist.time,
2432159047fSniklas 		   child->cg.child_time, arc->count, child->ncalls);
2442159047fSniklas 	   printf ("[prop_time] parent\t");
2452159047fSniklas 	   print_name (parent);
2462159047fSniklas 	   printf ("\n[prop_time] share %f\n", share));
2472159047fSniklas     }
2482159047fSniklas }
2492159047fSniklas 
2502159047fSniklas 
2512159047fSniklas /*
2522159047fSniklas  * Compute the time of a cycle as the sum of the times of all
2532159047fSniklas  * its members.
2542159047fSniklas  */
2552159047fSniklas static void
cycle_time()256*c074d1c9Sdrahn cycle_time ()
2572159047fSniklas {
2582159047fSniklas   Sym *member, *cyc;
2592159047fSniklas 
2602159047fSniklas   for (cyc = &cycle_header[1]; cyc <= &cycle_header[num_cycles]; ++cyc)
2612159047fSniklas     {
2622159047fSniklas       for (member = cyc->cg.cyc.next; member; member = member->cg.cyc.next)
2632159047fSniklas 	{
2642159047fSniklas 	  if (member->cg.prop.fract == 0.0)
2652159047fSniklas 	    {
2662159047fSniklas 	      /*
2672159047fSniklas 	       * All members have the same propfraction except those
2682159047fSniklas 	       * that were excluded with -E.
2692159047fSniklas 	       */
2702159047fSniklas 	      continue;
2712159047fSniklas 	    }
2722159047fSniklas 	  cyc->hist.time += member->hist.time;
2732159047fSniklas 	}
2742159047fSniklas       cyc->cg.prop.self = cyc->cg.prop.fract * cyc->hist.time;
2752159047fSniklas     }
2762159047fSniklas }
2772159047fSniklas 
2782159047fSniklas 
2792159047fSniklas static void
cycle_link()280*c074d1c9Sdrahn cycle_link ()
2812159047fSniklas {
2822159047fSniklas   Sym *sym, *cyc, *member;
2832159047fSniklas   Arc *arc;
2842159047fSniklas   int num;
2852159047fSniklas 
2862159047fSniklas   /* count the number of cycles, and initialize the cycle lists: */
2872159047fSniklas 
2882159047fSniklas   num_cycles = 0;
2892159047fSniklas   for (sym = symtab.base; sym < symtab.limit; ++sym)
2902159047fSniklas     {
2912159047fSniklas       /* this is how you find unattached cycles: */
2922159047fSniklas       if (sym->cg.cyc.head == sym && sym->cg.cyc.next)
2932159047fSniklas 	{
2942159047fSniklas 	  ++num_cycles;
2952159047fSniklas 	}
2962159047fSniklas     }
2972159047fSniklas 
2982159047fSniklas   /*
2992159047fSniklas    * cycle_header is indexed by cycle number: i.e. it is origin 1,
3002159047fSniklas    * not origin 0.
3012159047fSniklas    */
3022159047fSniklas   cycle_header = (Sym *) xmalloc ((num_cycles + 1) * sizeof (Sym));
3032159047fSniklas 
3042159047fSniklas   /*
3052159047fSniklas    * Now link cycles to true cycle-heads, number them, accumulate
3062159047fSniklas    * the data for the cycle.
3072159047fSniklas    */
3082159047fSniklas   num = 0;
3092159047fSniklas   cyc = cycle_header;
3102159047fSniklas   for (sym = symtab.base; sym < symtab.limit; ++sym)
3112159047fSniklas     {
3122159047fSniklas       if (!(sym->cg.cyc.head == sym && sym->cg.cyc.next != 0))
3132159047fSniklas 	{
3142159047fSniklas 	  continue;
3152159047fSniklas 	}
3162159047fSniklas       ++num;
3172159047fSniklas       ++cyc;
3182159047fSniklas       sym_init (cyc);
3192159047fSniklas       cyc->cg.print_flag = TRUE;	/* should this be printed? */
3202159047fSniklas       cyc->cg.top_order = DFN_NAN;	/* graph call chain top-sort order */
3212159047fSniklas       cyc->cg.cyc.num = num;	/* internal number of cycle on */
3222159047fSniklas       cyc->cg.cyc.head = cyc;	/* pointer to head of cycle */
3232159047fSniklas       cyc->cg.cyc.next = sym;	/* pointer to next member of cycle */
3242159047fSniklas       DBG (CYCLEDEBUG, printf ("[cycle_link] ");
3252159047fSniklas 	   print_name (sym);
3262159047fSniklas 	   printf (" is the head of cycle %d\n", num));
3272159047fSniklas 
3282159047fSniklas       /* link members to cycle header: */
3292159047fSniklas       for (member = sym; member; member = member->cg.cyc.next)
3302159047fSniklas 	{
3312159047fSniklas 	  member->cg.cyc.num = num;
3322159047fSniklas 	  member->cg.cyc.head = cyc;
3332159047fSniklas 	}
3342159047fSniklas 
3352159047fSniklas       /*
3362159047fSniklas        * Count calls from outside the cycle and those among cycle
3372159047fSniklas        * members:
3382159047fSniklas        */
3392159047fSniklas       for (member = sym; member; member = member->cg.cyc.next)
3402159047fSniklas 	{
3412159047fSniklas 	  for (arc = member->cg.parents; arc; arc = arc->next_parent)
3422159047fSniklas 	    {
3432159047fSniklas 	      if (arc->parent == member)
3442159047fSniklas 		{
3452159047fSniklas 		  continue;
3462159047fSniklas 		}
3472159047fSniklas 	      if (arc->parent->cg.cyc.num == num)
3482159047fSniklas 		{
3492159047fSniklas 		  cyc->cg.self_calls += arc->count;
3502159047fSniklas 		}
3512159047fSniklas 	      else
3522159047fSniklas 		{
3532159047fSniklas 		  cyc->ncalls += arc->count;
3542159047fSniklas 		}
3552159047fSniklas 	    }
3562159047fSniklas 	}
3572159047fSniklas     }
3582159047fSniklas }
3592159047fSniklas 
3602159047fSniklas 
3612159047fSniklas /*
3622159047fSniklas  * Check if any parent of this child (or outside parents of this
3632159047fSniklas  * cycle) have their print flags on and set the print flag of the
3642159047fSniklas  * child (cycle) appropriately.  Similarly, deal with propagation
3652159047fSniklas  * fractions from parents.
3662159047fSniklas  */
3672159047fSniklas static void
inherit_flags(child)368*c074d1c9Sdrahn inherit_flags (child)
369*c074d1c9Sdrahn      Sym *child;
3702159047fSniklas {
3712159047fSniklas   Sym *head, *parent, *member;
3722159047fSniklas   Arc *arc;
3732159047fSniklas 
3742159047fSniklas   head = child->cg.cyc.head;
3752159047fSniklas   if (child == head)
3762159047fSniklas     {
3772159047fSniklas       /* just a regular child, check its parents: */
3782159047fSniklas       child->cg.print_flag = FALSE;
3792159047fSniklas       child->cg.prop.fract = 0.0;
3802159047fSniklas       for (arc = child->cg.parents; arc; arc = arc->next_parent)
3812159047fSniklas 	{
3822159047fSniklas 	  parent = arc->parent;
3832159047fSniklas 	  if (child == parent)
3842159047fSniklas 	    {
3852159047fSniklas 	      continue;
3862159047fSniklas 	    }
3872159047fSniklas 	  child->cg.print_flag |= parent->cg.print_flag;
3882159047fSniklas 	  /*
3892159047fSniklas 	   * If the child was never actually called (e.g., this arc
3902159047fSniklas 	   * is static (and all others are, too)) no time propagates
3912159047fSniklas 	   * along this arc.
3922159047fSniklas 	   */
393b305b0f1Sespie 	  if (child->ncalls != 0)
3942159047fSniklas 	    {
3952159047fSniklas 	      child->cg.prop.fract += parent->cg.prop.fract
3962159047fSniklas 		* (((double) arc->count) / ((double) child->ncalls));
3972159047fSniklas 	    }
3982159047fSniklas 	}
3992159047fSniklas     }
4002159047fSniklas   else
4012159047fSniklas     {
4022159047fSniklas       /*
4032159047fSniklas        * Its a member of a cycle, look at all parents from outside
4042159047fSniklas        * the cycle.
4052159047fSniklas        */
4062159047fSniklas       head->cg.print_flag = FALSE;
4072159047fSniklas       head->cg.prop.fract = 0.0;
4082159047fSniklas       for (member = head->cg.cyc.next; member; member = member->cg.cyc.next)
4092159047fSniklas 	{
4102159047fSniklas 	  for (arc = member->cg.parents; arc; arc = arc->next_parent)
4112159047fSniklas 	    {
4122159047fSniklas 	      if (arc->parent->cg.cyc.head == head)
4132159047fSniklas 		{
4142159047fSniklas 		  continue;
4152159047fSniklas 		}
4162159047fSniklas 	      parent = arc->parent;
4172159047fSniklas 	      head->cg.print_flag |= parent->cg.print_flag;
4182159047fSniklas 	      /*
4192159047fSniklas 	       * If the cycle was never actually called (e.g. this
4202159047fSniklas 	       * arc is static (and all others are, too)) no time
4212159047fSniklas 	       * propagates along this arc.
4222159047fSniklas 	       */
423b305b0f1Sespie 	      if (head->ncalls != 0)
4242159047fSniklas 		{
4252159047fSniklas 		  head->cg.prop.fract += parent->cg.prop.fract
4262159047fSniklas 		    * (((double) arc->count) / ((double) head->ncalls));
4272159047fSniklas 		}
4282159047fSniklas 	    }
4292159047fSniklas 	}
4302159047fSniklas       for (member = head; member; member = member->cg.cyc.next)
4312159047fSniklas 	{
4322159047fSniklas 	  member->cg.print_flag = head->cg.print_flag;
4332159047fSniklas 	  member->cg.prop.fract = head->cg.prop.fract;
4342159047fSniklas 	}
4352159047fSniklas     }
4362159047fSniklas }
4372159047fSniklas 
4382159047fSniklas 
4392159047fSniklas /*
4402159047fSniklas  * In one top-to-bottom pass over the topologically sorted symbols
4412159047fSniklas  * propagate:
4422159047fSniklas  *      cg.print_flag as the union of parents' print_flags
4432159047fSniklas  *      propfraction as the sum of fractional parents' propfractions
4442159047fSniklas  * and while we're here, sum time for functions.
4452159047fSniklas  */
4462159047fSniklas static void
propagate_flags(symbols)447*c074d1c9Sdrahn propagate_flags (symbols)
448*c074d1c9Sdrahn      Sym **symbols;
4492159047fSniklas {
4502159047fSniklas   int index;
4512159047fSniklas   Sym *old_head, *child;
4522159047fSniklas 
4532159047fSniklas   old_head = 0;
4542159047fSniklas   for (index = symtab.len - 1; index >= 0; --index)
4552159047fSniklas     {
4562159047fSniklas       child = symbols[index];
4572159047fSniklas       /*
4582159047fSniklas        * If we haven't done this function or cycle, inherit things
4592159047fSniklas        * from parent.  This way, we are linear in the number of arcs
4602159047fSniklas        * since we do all members of a cycle (and the cycle itself)
4612159047fSniklas        * as we hit the first member of the cycle.
4622159047fSniklas        */
4632159047fSniklas       if (child->cg.cyc.head != old_head)
4642159047fSniklas 	{
4652159047fSniklas 	  old_head = child->cg.cyc.head;
4662159047fSniklas 	  inherit_flags (child);
4672159047fSniklas 	}
4682159047fSniklas       DBG (PROPDEBUG,
4692159047fSniklas 	   printf ("[prop_flags] ");
4702159047fSniklas 	   print_name (child);
4712159047fSniklas 	   printf ("inherits print-flag %d and prop-fract %f\n",
4722159047fSniklas 		   child->cg.print_flag, child->cg.prop.fract));
4732159047fSniklas       if (!child->cg.print_flag)
4742159047fSniklas 	{
4752159047fSniklas 	  /*
4762159047fSniklas 	   * Printflag is off. It gets turned on by being in the
4772159047fSniklas 	   * INCL_GRAPH table, or there being an empty INCL_GRAPH
4782159047fSniklas 	   * table and not being in the EXCL_GRAPH table.
4792159047fSniklas 	   */
4802159047fSniklas 	  if (sym_lookup (&syms[INCL_GRAPH], child->addr)
4812159047fSniklas 	      || (syms[INCL_GRAPH].len == 0
4822159047fSniklas 		  && !sym_lookup (&syms[EXCL_GRAPH], child->addr)))
4832159047fSniklas 	    {
4842159047fSniklas 	      child->cg.print_flag = TRUE;
4852159047fSniklas 	    }
4862159047fSniklas 	}
4872159047fSniklas       else
4882159047fSniklas 	{
4892159047fSniklas 	  /*
4902159047fSniklas 	   * This function has printing parents: maybe someone wants
4912159047fSniklas 	   * to shut it up by putting it in the EXCL_GRAPH table.
4922159047fSniklas 	   * (But favor INCL_GRAPH over EXCL_GRAPH.)
4932159047fSniklas 	   */
4942159047fSniklas 	  if (!sym_lookup (&syms[INCL_GRAPH], child->addr)
4952159047fSniklas 	      && sym_lookup (&syms[EXCL_GRAPH], child->addr))
4962159047fSniklas 	    {
4972159047fSniklas 	      child->cg.print_flag = FALSE;
4982159047fSniklas 	    }
4992159047fSniklas 	}
5002159047fSniklas       if (child->cg.prop.fract == 0.0)
5012159047fSniklas 	{
5022159047fSniklas 	  /*
5032159047fSniklas 	   * No parents to pass time to.  Collect time from children
5042159047fSniklas 	   * if its in the INCL_TIME table, or there is an empty
5052159047fSniklas 	   * INCL_TIME table and its not in the EXCL_TIME table.
5062159047fSniklas 	   */
5072159047fSniklas 	  if (sym_lookup (&syms[INCL_TIME], child->addr)
5082159047fSniklas 	      || (syms[INCL_TIME].len == 0
5092159047fSniklas 		  && !sym_lookup (&syms[EXCL_TIME], child->addr)))
5102159047fSniklas 	    {
5112159047fSniklas 	      child->cg.prop.fract = 1.0;
5122159047fSniklas 	    }
5132159047fSniklas 	}
5142159047fSniklas       else
5152159047fSniklas 	{
5162159047fSniklas 	  /*
5172159047fSniklas 	   * It has parents to pass time to, but maybe someone wants
5182159047fSniklas 	   * to shut it up by puttting it in the EXCL_TIME table.
5192159047fSniklas 	   * (But favor being in INCL_TIME tabe over being in
5202159047fSniklas 	   * EXCL_TIME table.)
5212159047fSniklas 	   */
5222159047fSniklas 	  if (!sym_lookup (&syms[INCL_TIME], child->addr)
5232159047fSniklas 	      && sym_lookup (&syms[EXCL_TIME], child->addr))
5242159047fSniklas 	    {
5252159047fSniklas 	      child->cg.prop.fract = 0.0;
5262159047fSniklas 	    }
5272159047fSniklas 	}
5282159047fSniklas       child->cg.prop.self = child->hist.time * child->cg.prop.fract;
5292159047fSniklas       print_time += child->cg.prop.self;
5302159047fSniklas       DBG (PROPDEBUG,
5312159047fSniklas 	   printf ("[prop_flags] ");
5322159047fSniklas 	   print_name (child);
5332159047fSniklas 	   printf (" ends up with printflag %d and prop-fract %f\n",
5342159047fSniklas 		   child->cg.print_flag, child->cg.prop.fract);
5352159047fSniklas 	   printf ("[prop_flags] time %f propself %f print_time %f\n",
5362159047fSniklas 		   child->hist.time, child->cg.prop.self, print_time));
5372159047fSniklas     }
5382159047fSniklas }
5392159047fSniklas 
5402159047fSniklas 
5412159047fSniklas /*
5422159047fSniklas  * Compare by decreasing propagated time.  If times are equal, but one
5432159047fSniklas  * is a cycle header, say that's first (e.g. less, i.e. -1).  If one's
5442159047fSniklas  * name doesn't have an underscore and the other does, say that one is
5452159047fSniklas  * first.  All else being equal, compare by names.
5462159047fSniklas  */
5472159047fSniklas static int
cmp_total(lp,rp)548*c074d1c9Sdrahn cmp_total (lp, rp)
549*c074d1c9Sdrahn      const PTR lp;
550*c074d1c9Sdrahn      const PTR rp;
5512159047fSniklas {
5522159047fSniklas   const Sym *left = *(const Sym **) lp;
5532159047fSniklas   const Sym *right = *(const Sym **) rp;
5542159047fSniklas   double diff;
5552159047fSniklas 
5562159047fSniklas   diff = (left->cg.prop.self + left->cg.prop.child)
5572159047fSniklas     - (right->cg.prop.self + right->cg.prop.child);
5582159047fSniklas   if (diff < 0.0)
5592159047fSniklas     {
5602159047fSniklas       return 1;
5612159047fSniklas     }
5622159047fSniklas   if (diff > 0.0)
5632159047fSniklas     {
5642159047fSniklas       return -1;
5652159047fSniklas     }
5662159047fSniklas   if (!left->name && left->cg.cyc.num != 0)
5672159047fSniklas     {
5682159047fSniklas       return -1;
5692159047fSniklas     }
5702159047fSniklas   if (!right->name && right->cg.cyc.num != 0)
5712159047fSniklas     {
5722159047fSniklas       return 1;
5732159047fSniklas     }
5742159047fSniklas   if (!left->name)
5752159047fSniklas     {
5762159047fSniklas       return -1;
5772159047fSniklas     }
5782159047fSniklas   if (!right->name)
5792159047fSniklas     {
5802159047fSniklas       return 1;
5812159047fSniklas     }
5822159047fSniklas   if (left->name[0] != '_' && right->name[0] == '_')
5832159047fSniklas     {
5842159047fSniklas       return -1;
5852159047fSniklas     }
5862159047fSniklas   if (left->name[0] == '_' && right->name[0] != '_')
5872159047fSniklas     {
5882159047fSniklas       return 1;
5892159047fSniklas     }
5902159047fSniklas   if (left->ncalls > right->ncalls)
5912159047fSniklas     {
5922159047fSniklas       return -1;
5932159047fSniklas     }
5942159047fSniklas   if (left->ncalls < right->ncalls)
5952159047fSniklas     {
5962159047fSniklas       return 1;
5972159047fSniklas     }
5982159047fSniklas   return strcmp (left->name, right->name);
5992159047fSniklas }
6002159047fSniklas 
6012159047fSniklas 
6022159047fSniklas /*
6032159047fSniklas  * Topologically sort the graph (collapsing cycles), and propagates
6042159047fSniklas  * time bottom up and flags top down.
6052159047fSniklas  */
6062159047fSniklas Sym **
cg_assemble()607*c074d1c9Sdrahn cg_assemble ()
6082159047fSniklas {
6092159047fSniklas   Sym *parent, **time_sorted_syms, **top_sorted_syms;
610b305b0f1Sespie   unsigned int index;
6112159047fSniklas   Arc *arc;
6126a4c786fSespie 
6132159047fSniklas   /*
6142159047fSniklas    * initialize various things:
6152159047fSniklas    *      zero out child times.
6162159047fSniklas    *      count self-recursive calls.
6172159047fSniklas    *      indicate that nothing is on cycles.
6182159047fSniklas    */
6192159047fSniklas   for (parent = symtab.base; parent < symtab.limit; parent++)
6202159047fSniklas     {
6212159047fSniklas       parent->cg.child_time = 0.0;
6222159047fSniklas       arc = arc_lookup (parent, parent);
6232159047fSniklas       if (arc && parent == arc->child)
6242159047fSniklas 	{
6252159047fSniklas 	  parent->ncalls -= arc->count;
6262159047fSniklas 	  parent->cg.self_calls = arc->count;
6272159047fSniklas 	}
6282159047fSniklas       else
6292159047fSniklas 	{
6302159047fSniklas 	  parent->cg.self_calls = 0;
6312159047fSniklas 	}
6322159047fSniklas       parent->cg.prop.fract = 0.0;
6332159047fSniklas       parent->cg.prop.self = 0.0;
6342159047fSniklas       parent->cg.prop.child = 0.0;
6352159047fSniklas       parent->cg.print_flag = FALSE;
6362159047fSniklas       parent->cg.top_order = DFN_NAN;
6372159047fSniklas       parent->cg.cyc.num = 0;
6382159047fSniklas       parent->cg.cyc.head = parent;
6392159047fSniklas       parent->cg.cyc.next = 0;
6402159047fSniklas       if (ignore_direct_calls)
6412159047fSniklas 	{
6422159047fSniklas 	  find_call (parent, parent->addr, (parent + 1)->addr);
6432159047fSniklas 	}
6442159047fSniklas     }
6452159047fSniklas   /*
6462159047fSniklas    * Topologically order things.  If any node is unnumbered, number
6472159047fSniklas    * it and any of its descendents.
6482159047fSniklas    */
6492159047fSniklas   for (parent = symtab.base; parent < symtab.limit; parent++)
6502159047fSniklas     {
6512159047fSniklas       if (parent->cg.top_order == DFN_NAN)
6522159047fSniklas 	{
6532159047fSniklas 	  cg_dfn (parent);
6542159047fSniklas 	}
6552159047fSniklas     }
6562159047fSniklas 
6572159047fSniklas   /* link together nodes on the same cycle: */
6582159047fSniklas   cycle_link ();
6592159047fSniklas 
6602159047fSniklas   /* sort the symbol table in reverse topological order: */
6612159047fSniklas   top_sorted_syms = (Sym **) xmalloc (symtab.len * sizeof (Sym *));
6622159047fSniklas   for (index = 0; index < symtab.len; ++index)
6632159047fSniklas     {
6642159047fSniklas       top_sorted_syms[index] = &symtab.base[index];
6652159047fSniklas     }
6662159047fSniklas   qsort (top_sorted_syms, symtab.len, sizeof (Sym *), cmp_topo);
6672159047fSniklas   DBG (DFNDEBUG,
6682159047fSniklas        printf ("[cg_assemble] topological sort listing\n");
6692159047fSniklas        for (index = 0; index < symtab.len; ++index)
6702159047fSniklas        {
6712159047fSniklas        printf ("[cg_assemble] ");
6722159047fSniklas        printf ("%d:", top_sorted_syms[index]->cg.top_order);
6732159047fSniklas        print_name (top_sorted_syms[index]);
6742159047fSniklas        printf ("\n");
6752159047fSniklas        }
6762159047fSniklas   );
6772159047fSniklas   /*
6782159047fSniklas    * Starting from the topological top, propagate print flags to
6792159047fSniklas    * children.  also, calculate propagation fractions.  this happens
6802159047fSniklas    * before time propagation since time propagation uses the
6812159047fSniklas    * fractions.
6822159047fSniklas    */
6832159047fSniklas   propagate_flags (top_sorted_syms);
6842159047fSniklas 
6852159047fSniklas   /*
6862159047fSniklas    * Starting from the topological bottom, propogate children times
6872159047fSniklas    * up to parents.
6882159047fSniklas    */
6892159047fSniklas   cycle_time ();
6902159047fSniklas   for (index = 0; index < symtab.len; ++index)
6912159047fSniklas     {
6922159047fSniklas       propagate_time (top_sorted_syms[index]);
6932159047fSniklas     }
6942159047fSniklas 
6952159047fSniklas   free (top_sorted_syms);
6962159047fSniklas 
6972159047fSniklas   /*
6982159047fSniklas    * Now, sort by CG.PROP.SELF + CG.PROP.CHILD.  Sorting both the regular
6992159047fSniklas    * function names and cycle headers.
7002159047fSniklas    */
7012159047fSniklas   time_sorted_syms = (Sym **) xmalloc ((symtab.len + num_cycles) * sizeof (Sym *));
7022159047fSniklas   for (index = 0; index < symtab.len; index++)
7032159047fSniklas     {
7042159047fSniklas       time_sorted_syms[index] = &symtab.base[index];
7052159047fSniklas     }
7062159047fSniklas   for (index = 1; index <= num_cycles; index++)
7072159047fSniklas     {
7082159047fSniklas       time_sorted_syms[symtab.len + index - 1] = &cycle_header[index];
7092159047fSniklas     }
7102159047fSniklas   qsort (time_sorted_syms, symtab.len + num_cycles, sizeof (Sym *),
7112159047fSniklas 	 cmp_total);
7122159047fSniklas   for (index = 0; index < symtab.len + num_cycles; index++)
7132159047fSniklas     {
7142159047fSniklas       time_sorted_syms[index]->cg.index = index + 1;
7152159047fSniklas     }
7162159047fSniklas   return time_sorted_syms;
7172159047fSniklas }
718