Blame gprof/cg_arcs.c

Packit bbfece
/*
Packit bbfece
 * Copyright (c) 1983, 1993, 2001
Packit bbfece
 *      The Regents of the University of California.  All rights reserved.
Packit bbfece
 *
Packit bbfece
 * Redistribution and use in source and binary forms, with or without
Packit bbfece
 * modification, are permitted provided that the following conditions
Packit bbfece
 * are met:
Packit bbfece
 * 1. Redistributions of source code must retain the above copyright
Packit bbfece
 *    notice, this list of conditions and the following disclaimer.
Packit bbfece
 * 2. Redistributions in binary form must reproduce the above copyright
Packit bbfece
 *    notice, this list of conditions and the following disclaimer in the
Packit bbfece
 *    documentation and/or other materials provided with the distribution.
Packit bbfece
 * 3. Neither the name of the University nor the names of its contributors
Packit bbfece
 *    may be used to endorse or promote products derived from this software
Packit bbfece
 *    without specific prior written permission.
Packit bbfece
 *
Packit bbfece
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
Packit bbfece
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
Packit bbfece
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
Packit bbfece
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
Packit bbfece
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
Packit bbfece
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
Packit bbfece
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
Packit bbfece
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
Packit bbfece
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
Packit bbfece
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
Packit bbfece
 * SUCH DAMAGE.
Packit bbfece
 */
Packit bbfece
#include "gprof.h"
Packit bbfece
#include "libiberty.h"
Packit bbfece
#include "search_list.h"
Packit bbfece
#include "source.h"
Packit bbfece
#include "symtab.h"
Packit bbfece
#include "call_graph.h"
Packit bbfece
#include "cg_arcs.h"
Packit bbfece
#include "cg_dfn.h"
Packit bbfece
#include "cg_print.h"
Packit bbfece
#include "utils.h"
Packit bbfece
#include "sym_ids.h"
Packit bbfece
Packit bbfece
static int cmp_topo (const PTR, const PTR);
Packit bbfece
static void propagate_time (Sym *);
Packit bbfece
static void cycle_time (void);
Packit bbfece
static void cycle_link (void);
Packit bbfece
static void inherit_flags (Sym *);
Packit bbfece
static void propagate_flags (Sym **);
Packit bbfece
static int cmp_total (const PTR, const PTR);
Packit bbfece
Packit bbfece
Sym *cycle_header;
Packit bbfece
unsigned int num_cycles;
Packit bbfece
Arc **arcs;
Packit bbfece
unsigned int numarcs;
Packit bbfece
Packit bbfece
/*
Packit bbfece
 * Return TRUE iff PARENT has an arc to covers the address
Packit bbfece
 * range covered by CHILD.
Packit bbfece
 */
Packit bbfece
Arc *
Packit bbfece
arc_lookup (Sym *parent, Sym *child)
Packit bbfece
{
Packit bbfece
  Arc *arc;
Packit bbfece
Packit bbfece
  if (!parent || !child)
Packit bbfece
    {
Packit bbfece
      printf ("[arc_lookup] parent == 0 || child == 0\n");
Packit bbfece
      return 0;
Packit bbfece
    }
Packit bbfece
  DBG (LOOKUPDEBUG, printf ("[arc_lookup] parent %s child %s\n",
Packit bbfece
			    parent->name, child->name));
Packit bbfece
  for (arc = parent->cg.children; arc; arc = arc->next_child)
Packit bbfece
    {
Packit bbfece
      DBG (LOOKUPDEBUG, printf ("[arc_lookup]\t parent %s child %s\n",
Packit bbfece
				arc->parent->name, arc->child->name));
Packit bbfece
      if (child->addr >= arc->child->addr
Packit bbfece
	  && child->end_addr <= arc->child->end_addr)
Packit bbfece
	{
Packit bbfece
	  return arc;
Packit bbfece
	}
Packit bbfece
    }
Packit bbfece
  return 0;
Packit bbfece
}
Packit bbfece
Packit bbfece
Packit bbfece
/*
Packit bbfece
 * Add (or just increment) an arc:
Packit bbfece
 */
Packit bbfece
void
Packit bbfece
arc_add (Sym *parent, Sym *child, unsigned long count)
Packit bbfece
{
Packit bbfece
  static unsigned int maxarcs = 0;
Packit bbfece
  Arc *arc, **newarcs;
Packit bbfece
Packit bbfece
  DBG (TALLYDEBUG, printf ("[arc_add] %lu arcs from %s to %s\n",
Packit bbfece
			   count, parent->name, child->name));
Packit bbfece
  arc = arc_lookup (parent, child);
Packit bbfece
  if (arc)
Packit bbfece
    {
Packit bbfece
      /*
Packit bbfece
       * A hit: just increment the count.
Packit bbfece
       */
Packit bbfece
      DBG (TALLYDEBUG, printf ("[tally] hit %lu += %lu\n",
Packit bbfece
			       arc->count, count));
Packit bbfece
      arc->count += count;
Packit bbfece
      return;
Packit bbfece
    }
Packit bbfece
  arc = (Arc *) xmalloc (sizeof (*arc));
Packit bbfece
  memset (arc, 0, sizeof (*arc));
Packit bbfece
  arc->parent = parent;
Packit bbfece
  arc->child = child;
Packit bbfece
  arc->count = count;
Packit bbfece
Packit bbfece
  /* If this isn't an arc for a recursive call to parent, then add it
Packit bbfece
     to the array of arcs.  */
Packit bbfece
  if (parent != child)
Packit bbfece
    {
Packit bbfece
      /* If we've exhausted space in our current array, get a new one
Packit bbfece
	 and copy the contents.   We might want to throttle the doubling
Packit bbfece
	 factor one day.  */
Packit bbfece
      if (numarcs == maxarcs)
Packit bbfece
	{
Packit bbfece
	  /* Determine how much space we want to allocate.  */
Packit bbfece
	  if (maxarcs == 0)
Packit bbfece
	    maxarcs = 1;
Packit bbfece
	  maxarcs *= 2;
Packit bbfece
Packit bbfece
	  /* Allocate the new array.  */
Packit bbfece
	  newarcs = (Arc **)xmalloc(sizeof (Arc *) * maxarcs);
Packit bbfece
Packit bbfece
	  /* Copy the old array's contents into the new array.  */
Packit bbfece
	  memcpy (newarcs, arcs, numarcs * sizeof (Arc *));
Packit bbfece
Packit bbfece
	  /* Free up the old array.  */
Packit bbfece
	  free (arcs);
Packit bbfece
Packit bbfece
	  /* And make the new array be the current array.  */
Packit bbfece
	  arcs = newarcs;
Packit bbfece
	}
Packit bbfece
Packit bbfece
      /* Place this arc in the arc array.  */
Packit bbfece
      arcs[numarcs++] = arc;
Packit bbfece
    }
Packit bbfece
Packit bbfece
  /* prepend this child to the children of this parent: */
Packit bbfece
  arc->next_child = parent->cg.children;
Packit bbfece
  parent->cg.children = arc;
Packit bbfece
Packit bbfece
  /* prepend this parent to the parents of this child: */
Packit bbfece
  arc->next_parent = child->cg.parents;
Packit bbfece
  child->cg.parents = arc;
Packit bbfece
}
Packit bbfece
Packit bbfece
Packit bbfece
static int
Packit bbfece
cmp_topo (const PTR lp, const PTR rp)
Packit bbfece
{
Packit bbfece
  const Sym *left = *(const Sym **) lp;
Packit bbfece
  const Sym *right = *(const Sym **) rp;
Packit bbfece
Packit bbfece
  return left->cg.top_order - right->cg.top_order;
Packit bbfece
}
Packit bbfece
Packit bbfece
Packit bbfece
static void
Packit bbfece
propagate_time (Sym *parent)
Packit bbfece
{
Packit bbfece
  Arc *arc;
Packit bbfece
  Sym *child;
Packit bbfece
  double share, prop_share;
Packit bbfece
Packit bbfece
  if (parent->cg.prop.fract == 0.0)
Packit bbfece
    {
Packit bbfece
      return;
Packit bbfece
    }
Packit bbfece
Packit bbfece
  /* gather time from children of this parent: */
Packit bbfece
Packit bbfece
  for (arc = parent->cg.children; arc; arc = arc->next_child)
Packit bbfece
    {
Packit bbfece
      child = arc->child;
Packit bbfece
      if (arc->count == 0 || child == parent || child->cg.prop.fract == 0)
Packit bbfece
	{
Packit bbfece
	  continue;
Packit bbfece
	}
Packit bbfece
      if (child->cg.cyc.head != child)
Packit bbfece
	{
Packit bbfece
	  if (parent->cg.cyc.num == child->cg.cyc.num)
Packit bbfece
	    {
Packit bbfece
	      continue;
Packit bbfece
	    }
Packit bbfece
	  if (parent->cg.top_order <= child->cg.top_order)
Packit bbfece
	    {
Packit bbfece
	      fprintf (stderr, "[propagate] toporder botches\n");
Packit bbfece
	    }
Packit bbfece
	  child = child->cg.cyc.head;
Packit bbfece
	}
Packit bbfece
      else
Packit bbfece
	{
Packit bbfece
	  if (parent->cg.top_order <= child->cg.top_order)
Packit bbfece
	    {
Packit bbfece
	      fprintf (stderr, "[propagate] toporder botches\n");
Packit bbfece
	      continue;
Packit bbfece
	    }
Packit bbfece
	}
Packit bbfece
      if (child->ncalls == 0)
Packit bbfece
	{
Packit bbfece
	  continue;
Packit bbfece
	}
Packit bbfece
Packit bbfece
      /* distribute time for this arc: */
Packit bbfece
      arc->time = child->hist.time * (((double) arc->count)
Packit bbfece
				      / ((double) child->ncalls));
Packit bbfece
      arc->child_time = child->cg.child_time
Packit bbfece
	* (((double) arc->count) / ((double) child->ncalls));
Packit bbfece
      share = arc->time + arc->child_time;
Packit bbfece
      parent->cg.child_time += share;
Packit bbfece
Packit bbfece
      /* (1 - cg.prop.fract) gets lost along the way: */
Packit bbfece
      prop_share = parent->cg.prop.fract * share;
Packit bbfece
Packit bbfece
      /* fix things for printing: */
Packit bbfece
      parent->cg.prop.child += prop_share;
Packit bbfece
      arc->time *= parent->cg.prop.fract;
Packit bbfece
      arc->child_time *= parent->cg.prop.fract;
Packit bbfece
Packit bbfece
      /* add this share to the parent's cycle header, if any: */
Packit bbfece
      if (parent->cg.cyc.head != parent)
Packit bbfece
	{
Packit bbfece
	  parent->cg.cyc.head->cg.child_time += share;
Packit bbfece
	  parent->cg.cyc.head->cg.prop.child += prop_share;
Packit bbfece
	}
Packit bbfece
      DBG (PROPDEBUG,
Packit bbfece
	   printf ("[prop_time] child \t");
Packit bbfece
	   print_name (child);
Packit bbfece
	   printf (" with %f %f %lu/%lu\n", child->hist.time,
Packit bbfece
		   child->cg.child_time, arc->count, child->ncalls);
Packit bbfece
	   printf ("[prop_time] parent\t");
Packit bbfece
	   print_name (parent);
Packit bbfece
	   printf ("\n[prop_time] share %f\n", share));
Packit bbfece
    }
Packit bbfece
}
Packit bbfece
Packit bbfece
Packit bbfece
/*
Packit bbfece
 * Compute the time of a cycle as the sum of the times of all
Packit bbfece
 * its members.
Packit bbfece
 */
Packit bbfece
static void
Packit bbfece
cycle_time (void)
Packit bbfece
{
Packit bbfece
  Sym *member, *cyc;
Packit bbfece
Packit bbfece
  for (cyc = &cycle_header[1]; cyc <= &cycle_header[num_cycles]; ++cyc)
Packit bbfece
    {
Packit bbfece
      for (member = cyc->cg.cyc.next; member; member = member->cg.cyc.next)
Packit bbfece
	{
Packit bbfece
	  if (member->cg.prop.fract == 0.0)
Packit bbfece
	    {
Packit bbfece
	      /*
Packit bbfece
	       * All members have the same propfraction except those
Packit bbfece
	       * that were excluded with -E.
Packit bbfece
	       */
Packit bbfece
	      continue;
Packit bbfece
	    }
Packit bbfece
	  cyc->hist.time += member->hist.time;
Packit bbfece
	}
Packit bbfece
      cyc->cg.prop.self = cyc->cg.prop.fract * cyc->hist.time;
Packit bbfece
    }
Packit bbfece
}
Packit bbfece
Packit bbfece
Packit bbfece
static void
Packit bbfece
cycle_link (void)
Packit bbfece
{
Packit bbfece
  Sym *sym, *cyc, *member;
Packit bbfece
  Arc *arc;
Packit bbfece
  int num;
Packit bbfece
Packit bbfece
  /* count the number of cycles, and initialize the cycle lists: */
Packit bbfece
Packit bbfece
  num_cycles = 0;
Packit bbfece
  for (sym = symtab.base; sym < symtab.limit; ++sym)
Packit bbfece
    {
Packit bbfece
      /* this is how you find unattached cycles: */
Packit bbfece
      if (sym->cg.cyc.head == sym && sym->cg.cyc.next)
Packit bbfece
	{
Packit bbfece
	  ++num_cycles;
Packit bbfece
	}
Packit bbfece
    }
Packit bbfece
Packit bbfece
  /*
Packit bbfece
   * cycle_header is indexed by cycle number: i.e. it is origin 1,
Packit bbfece
   * not origin 0.
Packit bbfece
   */
Packit bbfece
  cycle_header = (Sym *) xmalloc ((num_cycles + 1) * sizeof (Sym));
Packit bbfece
Packit bbfece
  /*
Packit bbfece
   * Now link cycles to true cycle-heads, number them, accumulate
Packit bbfece
   * the data for the cycle.
Packit bbfece
   */
Packit bbfece
  num = 0;
Packit bbfece
  cyc = cycle_header;
Packit bbfece
  for (sym = symtab.base; sym < symtab.limit; ++sym)
Packit bbfece
    {
Packit bbfece
      if (!(sym->cg.cyc.head == sym && sym->cg.cyc.next != 0))
Packit bbfece
	{
Packit bbfece
	  continue;
Packit bbfece
	}
Packit bbfece
      ++num;
Packit bbfece
      ++cyc;
Packit bbfece
      sym_init (cyc);
Packit bbfece
      cyc->cg.print_flag = TRUE;	/* should this be printed? */
Packit bbfece
      cyc->cg.top_order = DFN_NAN;	/* graph call chain top-sort order */
Packit bbfece
      cyc->cg.cyc.num = num;	/* internal number of cycle on */
Packit bbfece
      cyc->cg.cyc.head = cyc;	/* pointer to head of cycle */
Packit bbfece
      cyc->cg.cyc.next = sym;	/* pointer to next member of cycle */
Packit bbfece
      DBG (CYCLEDEBUG, printf ("[cycle_link] ");
Packit bbfece
	   print_name (sym);
Packit bbfece
	   printf (" is the head of cycle %d\n", num));
Packit bbfece
Packit bbfece
      /* link members to cycle header: */
Packit bbfece
      for (member = sym; member; member = member->cg.cyc.next)
Packit bbfece
	{
Packit bbfece
	  member->cg.cyc.num = num;
Packit bbfece
	  member->cg.cyc.head = cyc;
Packit bbfece
	}
Packit bbfece
Packit bbfece
      /*
Packit bbfece
       * Count calls from outside the cycle and those among cycle
Packit bbfece
       * members:
Packit bbfece
       */
Packit bbfece
      for (member = sym; member; member = member->cg.cyc.next)
Packit bbfece
	{
Packit bbfece
	  for (arc = member->cg.parents; arc; arc = arc->next_parent)
Packit bbfece
	    {
Packit bbfece
	      if (arc->parent == member)
Packit bbfece
		{
Packit bbfece
		  continue;
Packit bbfece
		}
Packit bbfece
	      if (arc->parent->cg.cyc.num == num)
Packit bbfece
		{
Packit bbfece
		  cyc->cg.self_calls += arc->count;
Packit bbfece
		}
Packit bbfece
	      else
Packit bbfece
		{
Packit bbfece
		  cyc->ncalls += arc->count;
Packit bbfece
		}
Packit bbfece
	    }
Packit bbfece
	}
Packit bbfece
    }
Packit bbfece
}
Packit bbfece
Packit bbfece
Packit bbfece
/*
Packit bbfece
 * Check if any parent of this child (or outside parents of this
Packit bbfece
 * cycle) have their print flags on and set the print flag of the
Packit bbfece
 * child (cycle) appropriately.  Similarly, deal with propagation
Packit bbfece
 * fractions from parents.
Packit bbfece
 */
Packit bbfece
static void
Packit bbfece
inherit_flags (Sym *child)
Packit bbfece
{
Packit bbfece
  Sym *head, *parent, *member;
Packit bbfece
  Arc *arc;
Packit bbfece
Packit bbfece
  head = child->cg.cyc.head;
Packit bbfece
  if (child == head)
Packit bbfece
    {
Packit bbfece
      /* just a regular child, check its parents: */
Packit bbfece
      child->cg.print_flag = FALSE;
Packit bbfece
      child->cg.prop.fract = 0.0;
Packit bbfece
      for (arc = child->cg.parents; arc; arc = arc->next_parent)
Packit bbfece
	{
Packit bbfece
	  parent = arc->parent;
Packit bbfece
	  if (child == parent)
Packit bbfece
	    {
Packit bbfece
	      continue;
Packit bbfece
	    }
Packit bbfece
	  child->cg.print_flag |= parent->cg.print_flag;
Packit bbfece
	  /*
Packit bbfece
	   * If the child was never actually called (e.g., this arc
Packit bbfece
	   * is static (and all others are, too)) no time propagates
Packit bbfece
	   * along this arc.
Packit bbfece
	   */
Packit bbfece
	  if (child->ncalls != 0)
Packit bbfece
	    {
Packit bbfece
	      child->cg.prop.fract += parent->cg.prop.fract
Packit bbfece
		* (((double) arc->count) / ((double) child->ncalls));
Packit bbfece
	    }
Packit bbfece
	}
Packit bbfece
    }
Packit bbfece
  else
Packit bbfece
    {
Packit bbfece
      /*
Packit bbfece
       * Its a member of a cycle, look at all parents from outside
Packit bbfece
       * the cycle.
Packit bbfece
       */
Packit bbfece
      head->cg.print_flag = FALSE;
Packit bbfece
      head->cg.prop.fract = 0.0;
Packit bbfece
      for (member = head->cg.cyc.next; member; member = member->cg.cyc.next)
Packit bbfece
	{
Packit bbfece
	  for (arc = member->cg.parents; arc; arc = arc->next_parent)
Packit bbfece
	    {
Packit bbfece
	      if (arc->parent->cg.cyc.head == head)
Packit bbfece
		{
Packit bbfece
		  continue;
Packit bbfece
		}
Packit bbfece
	      parent = arc->parent;
Packit bbfece
	      head->cg.print_flag |= parent->cg.print_flag;
Packit bbfece
	      /*
Packit bbfece
	       * If the cycle was never actually called (e.g. this
Packit bbfece
	       * arc is static (and all others are, too)) no time
Packit bbfece
	       * propagates along this arc.
Packit bbfece
	       */
Packit bbfece
	      if (head->ncalls != 0)
Packit bbfece
		{
Packit bbfece
		  head->cg.prop.fract += parent->cg.prop.fract
Packit bbfece
		    * (((double) arc->count) / ((double) head->ncalls));
Packit bbfece
		}
Packit bbfece
	    }
Packit bbfece
	}
Packit bbfece
      for (member = head; member; member = member->cg.cyc.next)
Packit bbfece
	{
Packit bbfece
	  member->cg.print_flag = head->cg.print_flag;
Packit bbfece
	  member->cg.prop.fract = head->cg.prop.fract;
Packit bbfece
	}
Packit bbfece
    }
Packit bbfece
}
Packit bbfece
Packit bbfece
Packit bbfece
/*
Packit bbfece
 * In one top-to-bottom pass over the topologically sorted symbols
Packit bbfece
 * propagate:
Packit bbfece
 *      cg.print_flag as the union of parents' print_flags
Packit bbfece
 *      propfraction as the sum of fractional parents' propfractions
Packit bbfece
 * and while we're here, sum time for functions.
Packit bbfece
 */
Packit bbfece
static void
Packit bbfece
propagate_flags (Sym **symbols)
Packit bbfece
{
Packit bbfece
  int sym_index;
Packit bbfece
  Sym *old_head, *child;
Packit bbfece
Packit bbfece
  old_head = 0;
Packit bbfece
  for (sym_index = symtab.len - 1; sym_index >= 0; --sym_index)
Packit bbfece
    {
Packit bbfece
      child = symbols[sym_index];
Packit bbfece
      /*
Packit bbfece
       * If we haven't done this function or cycle, inherit things
Packit bbfece
       * from parent.  This way, we are linear in the number of arcs
Packit bbfece
       * since we do all members of a cycle (and the cycle itself)
Packit bbfece
       * as we hit the first member of the cycle.
Packit bbfece
       */
Packit bbfece
      if (child->cg.cyc.head != old_head)
Packit bbfece
	{
Packit bbfece
	  old_head = child->cg.cyc.head;
Packit bbfece
	  inherit_flags (child);
Packit bbfece
	}
Packit bbfece
      DBG (PROPDEBUG,
Packit bbfece
	   printf ("[prop_flags] ");
Packit bbfece
	   print_name (child);
Packit bbfece
	   printf ("inherits print-flag %d and prop-fract %f\n",
Packit bbfece
		   child->cg.print_flag, child->cg.prop.fract));
Packit bbfece
      if (!child->cg.print_flag)
Packit bbfece
	{
Packit bbfece
	  /*
Packit bbfece
	   * Printflag is off. It gets turned on by being in the
Packit bbfece
	   * INCL_GRAPH table, or there being an empty INCL_GRAPH
Packit bbfece
	   * table and not being in the EXCL_GRAPH table.
Packit bbfece
	   */
Packit bbfece
	  if (sym_lookup (&syms[INCL_GRAPH], child->addr)
Packit bbfece
	      || (syms[INCL_GRAPH].len == 0
Packit bbfece
		  && !sym_lookup (&syms[EXCL_GRAPH], child->addr)))
Packit bbfece
	    {
Packit bbfece
	      child->cg.print_flag = TRUE;
Packit bbfece
	    }
Packit bbfece
	}
Packit bbfece
      else
Packit bbfece
	{
Packit bbfece
	  /*
Packit bbfece
	   * This function has printing parents: maybe someone wants
Packit bbfece
	   * to shut it up by putting it in the EXCL_GRAPH table.
Packit bbfece
	   * (But favor INCL_GRAPH over EXCL_GRAPH.)
Packit bbfece
	   */
Packit bbfece
	  if (!sym_lookup (&syms[INCL_GRAPH], child->addr)
Packit bbfece
	      && sym_lookup (&syms[EXCL_GRAPH], child->addr))
Packit bbfece
	    {
Packit bbfece
	      child->cg.print_flag = FALSE;
Packit bbfece
	    }
Packit bbfece
	}
Packit bbfece
      if (child->cg.prop.fract == 0.0)
Packit bbfece
	{
Packit bbfece
	  /*
Packit bbfece
	   * No parents to pass time to.  Collect time from children
Packit bbfece
	   * if its in the INCL_TIME table, or there is an empty
Packit bbfece
	   * INCL_TIME table and its not in the EXCL_TIME table.
Packit bbfece
	   */
Packit bbfece
	  if (sym_lookup (&syms[INCL_TIME], child->addr)
Packit bbfece
	      || (syms[INCL_TIME].len == 0
Packit bbfece
		  && !sym_lookup (&syms[EXCL_TIME], child->addr)))
Packit bbfece
	    {
Packit bbfece
	      child->cg.prop.fract = 1.0;
Packit bbfece
	    }
Packit bbfece
	}
Packit bbfece
      else
Packit bbfece
	{
Packit bbfece
	  /*
Packit bbfece
	   * It has parents to pass time to, but maybe someone wants
Packit bbfece
	   * to shut it up by puttting it in the EXCL_TIME table.
Packit bbfece
	   * (But favor being in INCL_TIME tabe over being in
Packit bbfece
	   * EXCL_TIME table.)
Packit bbfece
	   */
Packit bbfece
	  if (!sym_lookup (&syms[INCL_TIME], child->addr)
Packit bbfece
	      && sym_lookup (&syms[EXCL_TIME], child->addr))
Packit bbfece
	    {
Packit bbfece
	      child->cg.prop.fract = 0.0;
Packit bbfece
	    }
Packit bbfece
	}
Packit bbfece
      child->cg.prop.self = child->hist.time * child->cg.prop.fract;
Packit bbfece
      print_time += child->cg.prop.self;
Packit bbfece
      DBG (PROPDEBUG,
Packit bbfece
	   printf ("[prop_flags] ");
Packit bbfece
	   print_name (child);
Packit bbfece
	   printf (" ends up with printflag %d and prop-fract %f\n",
Packit bbfece
		   child->cg.print_flag, child->cg.prop.fract);
Packit bbfece
	   printf ("[prop_flags] time %f propself %f print_time %f\n",
Packit bbfece
		   child->hist.time, child->cg.prop.self, print_time));
Packit bbfece
    }
Packit bbfece
}
Packit bbfece
Packit bbfece
Packit bbfece
/*
Packit bbfece
 * Compare by decreasing propagated time.  If times are equal, but one
Packit bbfece
 * is a cycle header, say that's first (e.g. less, i.e. -1).  If one's
Packit bbfece
 * name doesn't have an underscore and the other does, say that one is
Packit bbfece
 * first.  All else being equal, compare by names.
Packit bbfece
 */
Packit bbfece
static int
Packit bbfece
cmp_total (const PTR lp, const PTR rp)
Packit bbfece
{
Packit bbfece
  const Sym *left = *(const Sym **) lp;
Packit bbfece
  const Sym *right = *(const Sym **) rp;
Packit bbfece
  double diff;
Packit bbfece
Packit bbfece
  diff = (left->cg.prop.self + left->cg.prop.child)
Packit bbfece
    - (right->cg.prop.self + right->cg.prop.child);
Packit bbfece
  if (diff < 0.0)
Packit bbfece
    {
Packit bbfece
      return 1;
Packit bbfece
    }
Packit bbfece
  if (diff > 0.0)
Packit bbfece
    {
Packit bbfece
      return -1;
Packit bbfece
    }
Packit bbfece
  if (!left->name && left->cg.cyc.num != 0)
Packit bbfece
    {
Packit bbfece
      return -1;
Packit bbfece
    }
Packit bbfece
  if (!right->name && right->cg.cyc.num != 0)
Packit bbfece
    {
Packit bbfece
      return 1;
Packit bbfece
    }
Packit bbfece
  if (!left->name)
Packit bbfece
    {
Packit bbfece
      return -1;
Packit bbfece
    }
Packit bbfece
  if (!right->name)
Packit bbfece
    {
Packit bbfece
      return 1;
Packit bbfece
    }
Packit bbfece
  if (left->name[0] != '_' && right->name[0] == '_')
Packit bbfece
    {
Packit bbfece
      return -1;
Packit bbfece
    }
Packit bbfece
  if (left->name[0] == '_' && right->name[0] != '_')
Packit bbfece
    {
Packit bbfece
      return 1;
Packit bbfece
    }
Packit bbfece
  if (left->ncalls > right->ncalls)
Packit bbfece
    {
Packit bbfece
      return -1;
Packit bbfece
    }
Packit bbfece
  if (left->ncalls < right->ncalls)
Packit bbfece
    {
Packit bbfece
      return 1;
Packit bbfece
    }
Packit bbfece
  return strcmp (left->name, right->name);
Packit bbfece
}
Packit bbfece
Packit bbfece
Packit bbfece
/* Topologically sort the graph (collapsing cycles), and propagates
Packit bbfece
   time bottom up and flags top down.  */
Packit bbfece
Packit bbfece
Sym **
Packit bbfece
cg_assemble (void)
Packit bbfece
{
Packit bbfece
  Sym *parent, **time_sorted_syms, **top_sorted_syms;
Packit bbfece
  unsigned int sym_index;
Packit bbfece
  Arc *arc;
Packit bbfece
Packit bbfece
  /* Initialize various things:
Packit bbfece
       Zero out child times.
Packit bbfece
       Count self-recursive calls.
Packit bbfece
       Indicate that nothing is on cycles.  */
Packit bbfece
  for (parent = symtab.base; parent < symtab.limit; parent++)
Packit bbfece
    {
Packit bbfece
      parent->cg.child_time = 0.0;
Packit bbfece
      arc = arc_lookup (parent, parent);
Packit bbfece
      if (arc && parent == arc->child)
Packit bbfece
	{
Packit bbfece
	  parent->ncalls -= arc->count;
Packit bbfece
	  parent->cg.self_calls = arc->count;
Packit bbfece
	}
Packit bbfece
      else
Packit bbfece
	{
Packit bbfece
	  parent->cg.self_calls = 0;
Packit bbfece
	}
Packit bbfece
      parent->cg.prop.fract = 0.0;
Packit bbfece
      parent->cg.prop.self = 0.0;
Packit bbfece
      parent->cg.prop.child = 0.0;
Packit bbfece
      parent->cg.print_flag = FALSE;
Packit bbfece
      parent->cg.top_order = DFN_NAN;
Packit bbfece
      parent->cg.cyc.num = 0;
Packit bbfece
      parent->cg.cyc.head = parent;
Packit bbfece
      parent->cg.cyc.next = 0;
Packit bbfece
      if (ignore_direct_calls)
Packit bbfece
	find_call (parent, parent->addr, (parent + 1)->addr);
Packit bbfece
    }
Packit bbfece
Packit bbfece
  /* Topologically order things.  If any node is unnumbered, number
Packit bbfece
     it and any of its descendents.  */
Packit bbfece
  for (parent = symtab.base; parent < symtab.limit; parent++)
Packit bbfece
    {
Packit bbfece
      if (parent->cg.top_order == DFN_NAN)
Packit bbfece
	cg_dfn (parent);
Packit bbfece
    }
Packit bbfece
Packit bbfece
  /* Link together nodes on the same cycle.  */
Packit bbfece
  cycle_link ();
Packit bbfece
Packit bbfece
  /* Sort the symbol table in reverse topological order.  */
Packit bbfece
  top_sorted_syms = (Sym **) xmalloc (symtab.len * sizeof (Sym *));
Packit bbfece
  for (sym_index = 0; sym_index < symtab.len; ++sym_index)
Packit bbfece
    top_sorted_syms[sym_index] = &symtab.base[sym_index];
Packit bbfece
Packit bbfece
  qsort (top_sorted_syms, symtab.len, sizeof (Sym *), cmp_topo);
Packit bbfece
  DBG (DFNDEBUG,
Packit bbfece
       printf ("[cg_assemble] topological sort listing\n");
Packit bbfece
       for (sym_index = 0; sym_index < symtab.len; ++sym_index)
Packit bbfece
	 {
Packit bbfece
	   printf ("[cg_assemble] ");
Packit bbfece
	   printf ("%d:", top_sorted_syms[sym_index]->cg.top_order);
Packit bbfece
	   print_name (top_sorted_syms[sym_index]);
Packit bbfece
	   printf ("\n");
Packit bbfece
	 }
Packit bbfece
  );
Packit bbfece
Packit bbfece
  /* Starting from the topological top, propagate print flags to
Packit bbfece
     children.  also, calculate propagation fractions.  this happens
Packit bbfece
     before time propagation since time propagation uses the
Packit bbfece
     fractions.  */
Packit bbfece
  propagate_flags (top_sorted_syms);
Packit bbfece
Packit bbfece
  /* Starting from the topological bottom, propagate children times
Packit bbfece
     up to parents.  */
Packit bbfece
  cycle_time ();
Packit bbfece
  for (sym_index = 0; sym_index < symtab.len; ++sym_index)
Packit bbfece
    propagate_time (top_sorted_syms[sym_index]);
Packit bbfece
Packit bbfece
  free (top_sorted_syms);
Packit bbfece
Packit bbfece
  /* Now, sort by CG.PROP.SELF + CG.PROP.CHILD.  Sorting both the regular
Packit bbfece
     function names and cycle headers.  */
Packit bbfece
  time_sorted_syms = (Sym **) xmalloc ((symtab.len + num_cycles) * sizeof (Sym *));
Packit bbfece
  for (sym_index = 0; sym_index < symtab.len; sym_index++)
Packit bbfece
    time_sorted_syms[sym_index] = &symtab.base[sym_index];
Packit bbfece
Packit bbfece
  for (sym_index = 1; sym_index <= num_cycles; sym_index++)
Packit bbfece
    time_sorted_syms[symtab.len + sym_index - 1] = &cycle_header[sym_index];
Packit bbfece
Packit bbfece
  qsort (time_sorted_syms, symtab.len + num_cycles, sizeof (Sym *),
Packit bbfece
	 cmp_total);
Packit bbfece
Packit bbfece
  for (sym_index = 0; sym_index < symtab.len + num_cycles; sym_index++)
Packit bbfece
    time_sorted_syms[sym_index]->cg.index = sym_index + 1;
Packit bbfece
Packit bbfece
  return time_sorted_syms;
Packit bbfece
}