1/*
2 * Copyright (c) 1983, 1993, 2001
3 *      The Regents of the University of California.  All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the University nor the names of its contributors
14 *    may be used to endorse or promote products derived from this software
15 *    without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29#include "libiberty.h"
30#include "gprof.h"
31#include "search_list.h"
32#include "source.h"
33#include "symtab.h"
34#include "call_graph.h"
35#include "cg_arcs.h"
36#include "cg_dfn.h"
37#include "cg_print.h"
38#include "utils.h"
39#include "sym_ids.h"
40
41static int cmp_topo (const PTR, const PTR);
42static void propagate_time (Sym *);
43static void cycle_time (void);
44static void cycle_link (void);
45static void inherit_flags (Sym *);
46static void propagate_flags (Sym **);
47static int cmp_total (const PTR, const PTR);
48
49Sym *cycle_header;
50unsigned int num_cycles;
51Arc **arcs;
52unsigned int numarcs;
53
54/*
55 * Return TRUE iff PARENT has an arc to covers the address
56 * range covered by CHILD.
57 */
58Arc *
59arc_lookup (Sym *parent, Sym *child)
60{
61  Arc *arc;
62
63  if (!parent || !child)
64    {
65      printf ("[arc_lookup] parent == 0 || child == 0\n");
66      return 0;
67    }
68  DBG (LOOKUPDEBUG, printf ("[arc_lookup] parent %s child %s\n",
69			    parent->name, child->name));
70  for (arc = parent->cg.children; arc; arc = arc->next_child)
71    {
72      DBG (LOOKUPDEBUG, printf ("[arc_lookup]\t parent %s child %s\n",
73				arc->parent->name, arc->child->name));
74      if (child->addr >= arc->child->addr
75	  && child->end_addr <= arc->child->end_addr)
76	{
77	  return arc;
78	}
79    }
80  return 0;
81}
82
83
84/*
85 * Add (or just increment) an arc:
86 */
87void
88arc_add (Sym *parent, Sym *child, unsigned long count)
89{
90  static unsigned int maxarcs = 0;
91  Arc *arc, **newarcs;
92
93  DBG (TALLYDEBUG, printf ("[arc_add] %lu arcs from %s to %s\n",
94			   count, parent->name, child->name));
95  arc = arc_lookup (parent, child);
96  if (arc)
97    {
98      /*
99       * A hit: just increment the count.
100       */
101      DBG (TALLYDEBUG, printf ("[tally] hit %lu += %lu\n",
102			       arc->count, count));
103      arc->count += count;
104      return;
105    }
106  arc = (Arc *) xmalloc (sizeof (*arc));
107  memset (arc, 0, sizeof (*arc));
108  arc->parent = parent;
109  arc->child = child;
110  arc->count = count;
111
112  /* If this isn't an arc for a recursive call to parent, then add it
113     to the array of arcs.  */
114  if (parent != child)
115    {
116      /* If we've exhausted space in our current array, get a new one
117	 and copy the contents.   We might want to throttle the doubling
118	 factor one day.  */
119      if (numarcs == maxarcs)
120	{
121	  /* Determine how much space we want to allocate.  */
122	  if (maxarcs == 0)
123	    maxarcs = 1;
124	  maxarcs *= 2;
125
126	  /* Allocate the new array.  */
127	  newarcs = (Arc **)xmalloc(sizeof (Arc *) * maxarcs);
128
129	  /* Copy the old array's contents into the new array.  */
130	  memcpy (newarcs, arcs, numarcs * sizeof (Arc *));
131
132	  /* Free up the old array.  */
133	  free (arcs);
134
135	  /* And make the new array be the current array.  */
136	  arcs = newarcs;
137	}
138
139      /* Place this arc in the arc array.  */
140      arcs[numarcs++] = arc;
141    }
142
143  /* prepend this child to the children of this parent: */
144  arc->next_child = parent->cg.children;
145  parent->cg.children = arc;
146
147  /* prepend this parent to the parents of this child: */
148  arc->next_parent = child->cg.parents;
149  child->cg.parents = arc;
150}
151
152
153static int
154cmp_topo (const PTR lp, const PTR rp)
155{
156  const Sym *left = *(const Sym **) lp;
157  const Sym *right = *(const Sym **) rp;
158
159  return left->cg.top_order - right->cg.top_order;
160}
161
162
163static void
164propagate_time (Sym *parent)
165{
166  Arc *arc;
167  Sym *child;
168  double share, prop_share;
169
170  if (parent->cg.prop.fract == 0.0)
171    {
172      return;
173    }
174
175  /* gather time from children of this parent: */
176
177  for (arc = parent->cg.children; arc; arc = arc->next_child)
178    {
179      child = arc->child;
180      if (arc->count == 0 || child == parent || child->cg.prop.fract == 0)
181	{
182	  continue;
183	}
184      if (child->cg.cyc.head != child)
185	{
186	  if (parent->cg.cyc.num == child->cg.cyc.num)
187	    {
188	      continue;
189	    }
190	  if (parent->cg.top_order <= child->cg.top_order)
191	    {
192	      fprintf (stderr, "[propagate] toporder botches\n");
193	    }
194	  child = child->cg.cyc.head;
195	}
196      else
197	{
198	  if (parent->cg.top_order <= child->cg.top_order)
199	    {
200	      fprintf (stderr, "[propagate] toporder botches\n");
201	      continue;
202	    }
203	}
204      if (child->ncalls == 0)
205	{
206	  continue;
207	}
208
209      /* distribute time for this arc: */
210      arc->time = child->hist.time * (((double) arc->count)
211				      / ((double) child->ncalls));
212      arc->child_time = child->cg.child_time
213	* (((double) arc->count) / ((double) child->ncalls));
214      share = arc->time + arc->child_time;
215      parent->cg.child_time += share;
216
217      /* (1 - cg.prop.fract) gets lost along the way: */
218      prop_share = parent->cg.prop.fract * share;
219
220      /* fix things for printing: */
221      parent->cg.prop.child += prop_share;
222      arc->time *= parent->cg.prop.fract;
223      arc->child_time *= parent->cg.prop.fract;
224
225      /* add this share to the parent's cycle header, if any: */
226      if (parent->cg.cyc.head != parent)
227	{
228	  parent->cg.cyc.head->cg.child_time += share;
229	  parent->cg.cyc.head->cg.prop.child += prop_share;
230	}
231      DBG (PROPDEBUG,
232	   printf ("[prop_time] child \t");
233	   print_name (child);
234	   printf (" with %f %f %lu/%lu\n", child->hist.time,
235		   child->cg.child_time, arc->count, child->ncalls);
236	   printf ("[prop_time] parent\t");
237	   print_name (parent);
238	   printf ("\n[prop_time] share %f\n", share));
239    }
240}
241
242
243/*
244 * Compute the time of a cycle as the sum of the times of all
245 * its members.
246 */
247static void
248cycle_time ()
249{
250  Sym *member, *cyc;
251
252  for (cyc = &cycle_header[1]; cyc <= &cycle_header[num_cycles]; ++cyc)
253    {
254      for (member = cyc->cg.cyc.next; member; member = member->cg.cyc.next)
255	{
256	  if (member->cg.prop.fract == 0.0)
257	    {
258	      /*
259	       * All members have the same propfraction except those
260	       * that were excluded with -E.
261	       */
262	      continue;
263	    }
264	  cyc->hist.time += member->hist.time;
265	}
266      cyc->cg.prop.self = cyc->cg.prop.fract * cyc->hist.time;
267    }
268}
269
270
271static void
272cycle_link ()
273{
274  Sym *sym, *cyc, *member;
275  Arc *arc;
276  int num;
277
278  /* count the number of cycles, and initialize the cycle lists: */
279
280  num_cycles = 0;
281  for (sym = symtab.base; sym < symtab.limit; ++sym)
282    {
283      /* this is how you find unattached cycles: */
284      if (sym->cg.cyc.head == sym && sym->cg.cyc.next)
285	{
286	  ++num_cycles;
287	}
288    }
289
290  /*
291   * cycle_header is indexed by cycle number: i.e. it is origin 1,
292   * not origin 0.
293   */
294  cycle_header = (Sym *) xmalloc ((num_cycles + 1) * sizeof (Sym));
295
296  /*
297   * Now link cycles to true cycle-heads, number them, accumulate
298   * the data for the cycle.
299   */
300  num = 0;
301  cyc = cycle_header;
302  for (sym = symtab.base; sym < symtab.limit; ++sym)
303    {
304      if (!(sym->cg.cyc.head == sym && sym->cg.cyc.next != 0))
305	{
306	  continue;
307	}
308      ++num;
309      ++cyc;
310      sym_init (cyc);
311      cyc->cg.print_flag = TRUE;	/* should this be printed? */
312      cyc->cg.top_order = DFN_NAN;	/* graph call chain top-sort order */
313      cyc->cg.cyc.num = num;	/* internal number of cycle on */
314      cyc->cg.cyc.head = cyc;	/* pointer to head of cycle */
315      cyc->cg.cyc.next = sym;	/* pointer to next member of cycle */
316      DBG (CYCLEDEBUG, printf ("[cycle_link] ");
317	   print_name (sym);
318	   printf (" is the head of cycle %d\n", num));
319
320      /* link members to cycle header: */
321      for (member = sym; member; member = member->cg.cyc.next)
322	{
323	  member->cg.cyc.num = num;
324	  member->cg.cyc.head = cyc;
325	}
326
327      /*
328       * Count calls from outside the cycle and those among cycle
329       * members:
330       */
331      for (member = sym; member; member = member->cg.cyc.next)
332	{
333	  for (arc = member->cg.parents; arc; arc = arc->next_parent)
334	    {
335	      if (arc->parent == member)
336		{
337		  continue;
338		}
339	      if (arc->parent->cg.cyc.num == num)
340		{
341		  cyc->cg.self_calls += arc->count;
342		}
343	      else
344		{
345		  cyc->ncalls += arc->count;
346		}
347	    }
348	}
349    }
350}
351
352
353/*
354 * Check if any parent of this child (or outside parents of this
355 * cycle) have their print flags on and set the print flag of the
356 * child (cycle) appropriately.  Similarly, deal with propagation
357 * fractions from parents.
358 */
359static void
360inherit_flags (Sym *child)
361{
362  Sym *head, *parent, *member;
363  Arc *arc;
364
365  head = child->cg.cyc.head;
366  if (child == head)
367    {
368      /* just a regular child, check its parents: */
369      child->cg.print_flag = FALSE;
370      child->cg.prop.fract = 0.0;
371      for (arc = child->cg.parents; arc; arc = arc->next_parent)
372	{
373	  parent = arc->parent;
374	  if (child == parent)
375	    {
376	      continue;
377	    }
378	  child->cg.print_flag |= parent->cg.print_flag;
379	  /*
380	   * If the child was never actually called (e.g., this arc
381	   * is static (and all others are, too)) no time propagates
382	   * along this arc.
383	   */
384	  if (child->ncalls != 0)
385	    {
386	      child->cg.prop.fract += parent->cg.prop.fract
387		* (((double) arc->count) / ((double) child->ncalls));
388	    }
389	}
390    }
391  else
392    {
393      /*
394       * Its a member of a cycle, look at all parents from outside
395       * the cycle.
396       */
397      head->cg.print_flag = FALSE;
398      head->cg.prop.fract = 0.0;
399      for (member = head->cg.cyc.next; member; member = member->cg.cyc.next)
400	{
401	  for (arc = member->cg.parents; arc; arc = arc->next_parent)
402	    {
403	      if (arc->parent->cg.cyc.head == head)
404		{
405		  continue;
406		}
407	      parent = arc->parent;
408	      head->cg.print_flag |= parent->cg.print_flag;
409	      /*
410	       * If the cycle was never actually called (e.g. this
411	       * arc is static (and all others are, too)) no time
412	       * propagates along this arc.
413	       */
414	      if (head->ncalls != 0)
415		{
416		  head->cg.prop.fract += parent->cg.prop.fract
417		    * (((double) arc->count) / ((double) head->ncalls));
418		}
419	    }
420	}
421      for (member = head; member; member = member->cg.cyc.next)
422	{
423	  member->cg.print_flag = head->cg.print_flag;
424	  member->cg.prop.fract = head->cg.prop.fract;
425	}
426    }
427}
428
429
430/*
431 * In one top-to-bottom pass over the topologically sorted symbols
432 * propagate:
433 *      cg.print_flag as the union of parents' print_flags
434 *      propfraction as the sum of fractional parents' propfractions
435 * and while we're here, sum time for functions.
436 */
437static void
438propagate_flags (Sym **symbols)
439{
440  int index;
441  Sym *old_head, *child;
442
443  old_head = 0;
444  for (index = symtab.len - 1; index >= 0; --index)
445    {
446      child = symbols[index];
447      /*
448       * If we haven't done this function or cycle, inherit things
449       * from parent.  This way, we are linear in the number of arcs
450       * since we do all members of a cycle (and the cycle itself)
451       * as we hit the first member of the cycle.
452       */
453      if (child->cg.cyc.head != old_head)
454	{
455	  old_head = child->cg.cyc.head;
456	  inherit_flags (child);
457	}
458      DBG (PROPDEBUG,
459	   printf ("[prop_flags] ");
460	   print_name (child);
461	   printf ("inherits print-flag %d and prop-fract %f\n",
462		   child->cg.print_flag, child->cg.prop.fract));
463      if (!child->cg.print_flag)
464	{
465	  /*
466	   * Printflag is off. It gets turned on by being in the
467	   * INCL_GRAPH table, or there being an empty INCL_GRAPH
468	   * table and not being in the EXCL_GRAPH table.
469	   */
470	  if (sym_lookup (&syms[INCL_GRAPH], child->addr)
471	      || (syms[INCL_GRAPH].len == 0
472		  && !sym_lookup (&syms[EXCL_GRAPH], child->addr)))
473	    {
474	      child->cg.print_flag = TRUE;
475	    }
476	}
477      else
478	{
479	  /*
480	   * This function has printing parents: maybe someone wants
481	   * to shut it up by putting it in the EXCL_GRAPH table.
482	   * (But favor INCL_GRAPH over EXCL_GRAPH.)
483	   */
484	  if (!sym_lookup (&syms[INCL_GRAPH], child->addr)
485	      && sym_lookup (&syms[EXCL_GRAPH], child->addr))
486	    {
487	      child->cg.print_flag = FALSE;
488	    }
489	}
490      if (child->cg.prop.fract == 0.0)
491	{
492	  /*
493	   * No parents to pass time to.  Collect time from children
494	   * if its in the INCL_TIME table, or there is an empty
495	   * INCL_TIME table and its not in the EXCL_TIME table.
496	   */
497	  if (sym_lookup (&syms[INCL_TIME], child->addr)
498	      || (syms[INCL_TIME].len == 0
499		  && !sym_lookup (&syms[EXCL_TIME], child->addr)))
500	    {
501	      child->cg.prop.fract = 1.0;
502	    }
503	}
504      else
505	{
506	  /*
507	   * It has parents to pass time to, but maybe someone wants
508	   * to shut it up by puttting it in the EXCL_TIME table.
509	   * (But favor being in INCL_TIME tabe over being in
510	   * EXCL_TIME table.)
511	   */
512	  if (!sym_lookup (&syms[INCL_TIME], child->addr)
513	      && sym_lookup (&syms[EXCL_TIME], child->addr))
514	    {
515	      child->cg.prop.fract = 0.0;
516	    }
517	}
518      child->cg.prop.self = child->hist.time * child->cg.prop.fract;
519      print_time += child->cg.prop.self;
520      DBG (PROPDEBUG,
521	   printf ("[prop_flags] ");
522	   print_name (child);
523	   printf (" ends up with printflag %d and prop-fract %f\n",
524		   child->cg.print_flag, child->cg.prop.fract);
525	   printf ("[prop_flags] time %f propself %f print_time %f\n",
526		   child->hist.time, child->cg.prop.self, print_time));
527    }
528}
529
530
531/*
532 * Compare by decreasing propagated time.  If times are equal, but one
533 * is a cycle header, say that's first (e.g. less, i.e. -1).  If one's
534 * name doesn't have an underscore and the other does, say that one is
535 * first.  All else being equal, compare by names.
536 */
537static int
538cmp_total (const PTR lp, const PTR rp)
539{
540  const Sym *left = *(const Sym **) lp;
541  const Sym *right = *(const Sym **) rp;
542  double diff;
543
544  diff = (left->cg.prop.self + left->cg.prop.child)
545    - (right->cg.prop.self + right->cg.prop.child);
546  if (diff < 0.0)
547    {
548      return 1;
549    }
550  if (diff > 0.0)
551    {
552      return -1;
553    }
554  if (!left->name && left->cg.cyc.num != 0)
555    {
556      return -1;
557    }
558  if (!right->name && right->cg.cyc.num != 0)
559    {
560      return 1;
561    }
562  if (!left->name)
563    {
564      return -1;
565    }
566  if (!right->name)
567    {
568      return 1;
569    }
570  if (left->name[0] != '_' && right->name[0] == '_')
571    {
572      return -1;
573    }
574  if (left->name[0] == '_' && right->name[0] != '_')
575    {
576      return 1;
577    }
578  if (left->ncalls > right->ncalls)
579    {
580      return -1;
581    }
582  if (left->ncalls < right->ncalls)
583    {
584      return 1;
585    }
586  return strcmp (left->name, right->name);
587}
588
589
590/*
591 * Topologically sort the graph (collapsing cycles), and propagates
592 * time bottom up and flags top down.
593 */
594Sym **
595cg_assemble ()
596{
597  Sym *parent, **time_sorted_syms, **top_sorted_syms;
598  unsigned int index;
599  Arc *arc;
600
601  /*
602   * initialize various things:
603   *      zero out child times.
604   *      count self-recursive calls.
605   *      indicate that nothing is on cycles.
606   */
607  for (parent = symtab.base; parent < symtab.limit; parent++)
608    {
609      parent->cg.child_time = 0.0;
610      arc = arc_lookup (parent, parent);
611      if (arc && parent == arc->child)
612	{
613	  parent->ncalls -= arc->count;
614	  parent->cg.self_calls = arc->count;
615	}
616      else
617	{
618	  parent->cg.self_calls = 0;
619	}
620      parent->cg.prop.fract = 0.0;
621      parent->cg.prop.self = 0.0;
622      parent->cg.prop.child = 0.0;
623      parent->cg.print_flag = FALSE;
624      parent->cg.top_order = DFN_NAN;
625      parent->cg.cyc.num = 0;
626      parent->cg.cyc.head = parent;
627      parent->cg.cyc.next = 0;
628      if (ignore_direct_calls)
629	{
630	  find_call (parent, parent->addr, (parent + 1)->addr);
631	}
632    }
633  /*
634   * Topologically order things.  If any node is unnumbered, number
635   * it and any of its descendents.
636   */
637  for (parent = symtab.base; parent < symtab.limit; parent++)
638    {
639      if (parent->cg.top_order == DFN_NAN)
640	{
641	  cg_dfn (parent);
642	}
643    }
644
645  /* link together nodes on the same cycle: */
646  cycle_link ();
647
648  /* sort the symbol table in reverse topological order: */
649  top_sorted_syms = (Sym **) xmalloc (symtab.len * sizeof (Sym *));
650  for (index = 0; index < symtab.len; ++index)
651    {
652      top_sorted_syms[index] = &symtab.base[index];
653    }
654  qsort (top_sorted_syms, symtab.len, sizeof (Sym *), cmp_topo);
655  DBG (DFNDEBUG,
656       printf ("[cg_assemble] topological sort listing\n");
657       for (index = 0; index < symtab.len; ++index)
658       {
659       printf ("[cg_assemble] ");
660       printf ("%d:", top_sorted_syms[index]->cg.top_order);
661       print_name (top_sorted_syms[index]);
662       printf ("\n");
663       }
664  );
665  /*
666   * Starting from the topological top, propagate print flags to
667   * children.  also, calculate propagation fractions.  this happens
668   * before time propagation since time propagation uses the
669   * fractions.
670   */
671  propagate_flags (top_sorted_syms);
672
673  /*
674   * Starting from the topological bottom, propogate children times
675   * up to parents.
676   */
677  cycle_time ();
678  for (index = 0; index < symtab.len; ++index)
679    {
680      propagate_time (top_sorted_syms[index]);
681    }
682
683  free (top_sorted_syms);
684
685  /*
686   * Now, sort by CG.PROP.SELF + CG.PROP.CHILD.  Sorting both the regular
687   * function names and cycle headers.
688   */
689  time_sorted_syms = (Sym **) xmalloc ((symtab.len + num_cycles) * sizeof (Sym *));
690  for (index = 0; index < symtab.len; index++)
691    {
692      time_sorted_syms[index] = &symtab.base[index];
693    }
694  for (index = 1; index <= num_cycles; index++)
695    {
696      time_sorted_syms[symtab.len + index - 1] = &cycle_header[index];
697    }
698  qsort (time_sorted_syms, symtab.len + num_cycles, sizeof (Sym *),
699	 cmp_total);
700  for (index = 0; index < symtab.len + num_cycles; index++)
701    {
702      time_sorted_syms[index]->cg.index = index + 1;
703    }
704  return time_sorted_syms;
705}
706