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