Back to index

cell-binutils  2.17cvs20070401
Functions | Variables
cg_print.h File Reference
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Functions

void cg_print (Sym **)
void cg_print_index (void)
void cg_print_file_ordering (void)
void cg_print_function_ordering (void)

Variables

double print_time

Function Documentation

void cg_print ( Sym **  )

Definition at line 499 of file cg_print.c.

{
  unsigned int index;
  Sym *parent;

  if (print_descriptions && bsd_style_output)
    bsd_callg_blurb (stdout);

  print_header ();

  for (index = 0; index < symtab.len + num_cycles; ++index)
    {
      parent = timesortsym[index];

      if ((ignore_zeros && parent->ncalls == 0
          && parent->cg.self_calls == 0 && parent->cg.prop.self == 0
          && parent->cg.prop.child == 0)
         || !parent->cg.print_flag
         || (line_granularity && ! parent->is_func))
       continue;

      if (!parent->name && parent->cg.cyc.num != 0)
       {
         /* Cycle header.  */
         print_cycle (parent);
         print_members (parent);
       }
      else
       {
         print_parents (parent);
         print_line (parent);
         print_children (parent);
       }

      if (bsd_style_output)
       printf ("\n");

      printf ("-----------------------------------------------\n");

      if (bsd_style_output)
       printf ("\n");
    }

  free (timesortsym);

  if (print_descriptions && !bsd_style_output)
    fsf_callg_blurb (stdout);
}

Here is the call graph for this function:

Here is the caller graph for this function:

void cg_print_file_ordering ( void  )

Definition at line 1225 of file cg_print.c.

{
  unsigned long scratch_arc_count, index;
  Arc **scratch_arcs;
  char *last;

  scratch_arc_count = 0;

  scratch_arcs = (Arc **) xmalloc (numarcs * sizeof (Arc *));
  for (index = 0; index < numarcs; index++)
    {
      if (! arcs[index]->parent->mapped
         || ! arcs[index]->child->mapped)
       arcs[index]->has_been_placed = 1;
    }

  order_and_dump_functions_by_arcs (arcs, numarcs, 0,
                                scratch_arcs, &scratch_arc_count);

  /* Output .o's not handled by the main placement algorithm.  */
  for (index = 0; index < symtab.len; index++)
    {
      if (symtab.base[index].mapped
         && ! symtab.base[index].has_been_placed)
       printf ("%s\n", symtab.base[index].name);
    }

  /* Now output any .o's that didn't have any text symbols.  */
  last = NULL;
  for (index = 0; index < symbol_map_count; index++)
    {
      unsigned int index2;

      /* Don't bother searching if this symbol
        is the same as the previous one.  */
      if (last && !strcmp (last, symbol_map[index].file_name))
       continue;

      for (index2 = 0; index2 < symtab.len; index2++)
       {
         if (! symtab.base[index2].mapped)
           continue;

         if (!strcmp (symtab.base[index2].name, symbol_map[index].file_name))
           break;
       }

      /* If we didn't find it in the symbol table, then it must
        be a .o with no text symbols.  Output it last.  */
      if (index2 == symtab.len)
       printf ("%s\n", symbol_map[index].file_name);
      last = symbol_map[index].file_name;
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

void cg_print_function_ordering ( void  )

Definition at line 773 of file cg_print.c.

{
  unsigned long index, used, unused, scratch_index;
  unsigned long  unplaced_arc_count, high_arc_count, scratch_arc_count;
#ifdef __GNUC__
  unsigned long long total_arcs, tmp_arcs_count;
#else
  unsigned long total_arcs, tmp_arcs_count;
#endif
  Sym **unused_syms, **used_syms, **scratch_syms;
  Arc **unplaced_arcs, **high_arcs, **scratch_arcs;

  index = 0;
  used = 0;
  unused = 0;
  scratch_index = 0;
  unplaced_arc_count = 0;
  high_arc_count = 0;
  scratch_arc_count = 0;

  /* First group all the unused functions together.  */
  unused_syms = (Sym **) xmalloc (symtab.len * sizeof (Sym *));
  used_syms = (Sym **) xmalloc (symtab.len * sizeof (Sym *));
  scratch_syms = (Sym **) xmalloc (symtab.len * sizeof (Sym *));
  high_arcs = (Arc **) xmalloc (numarcs * sizeof (Arc *));
  scratch_arcs = (Arc **) xmalloc (numarcs * sizeof (Arc *));
  unplaced_arcs = (Arc **) xmalloc (numarcs * sizeof (Arc *));

  /* Walk through all the functions; mark those which are never
     called as placed (we'll emit them as a group later).  */
  for (index = 0, used = 0, unused = 0; index < symtab.len; index++)
    {
      if (symtab.base[index].ncalls == 0)
       {
         /* Filter out gprof generated names.  */
         if (strcmp (symtab.base[index].name, "<locore>")
             && strcmp (symtab.base[index].name, "<hicore>"))
           {
             unused_syms[unused++] = &symtab.base[index];
             symtab.base[index].has_been_placed = 1;
           }
       }
      else
       {
         used_syms[used++] = &symtab.base[index];
         symtab.base[index].has_been_placed = 0;
         symtab.base[index].next = 0;
         symtab.base[index].prev = 0;
         symtab.base[index].nuses = 0;
       }
    }

  /* Sort the arcs from most used to least used.  */
  qsort (arcs, numarcs, sizeof (Arc *), cmp_arc_count);

  /* Compute the total arc count.  Also mark arcs as unplaced.

     Note we don't compensate for overflow if that happens!
     Overflow is much less likely when this file is compiled
     with GCC as it can double-wide integers via long long.  */
  total_arcs = 0;
  for (index = 0; index < numarcs; index++)
    {
      total_arcs += arcs[index]->count;
      arcs[index]->has_been_placed = 0;
    }

  /* We want to pull out those functions which are referenced
     by many highly used arcs and emit them as a group.  This
     could probably use some tuning.  */
  tmp_arcs_count = 0;
  for (index = 0; index < numarcs; index++)
    {
      tmp_arcs_count += arcs[index]->count;

      /* Count how many times each parent and child are used up
        to our threshhold of arcs (90%).  */
      if ((double)tmp_arcs_count / (double)total_arcs > 0.90)
       break;

      arcs[index]->child->nuses++;
    }

  /* Now sort a temporary symbol table based on the number of
     times each function was used in the highest used arcs.  */
  memcpy (scratch_syms, used_syms, used * sizeof (Sym *));
  qsort (scratch_syms, used, sizeof (Sym *), cmp_fun_nuses);

  /* Now pick out those symbols we're going to emit as
     a group.  We take up to 1.25% of the used symbols.  */
  for (index = 0; index < used / 80; index++)
    {
      Sym *sym = scratch_syms[index];
      Arc *arc;

      /* If we hit symbols that aren't used from many call sites,
        then we can quit.  We choose five as the low limit for
        no particular reason.  */
      if (sym->nuses == 5)
       break;

      /* We're going to need the arcs between these functions.
        Unfortunately, we don't know all these functions
        until we're done.  So we keep track of all the arcs
        to the functions we care about, then prune out those
        which are uninteresting.

        An interesting variation would be to quit when we found
        multi-call site functions which account for some percentage
        of the arcs.  */
      arc = sym->cg.children;

      while (arc)
       {
         if (arc->parent != arc->child)
           scratch_arcs[scratch_arc_count++] = arc;
         arc->has_been_placed = 1;
         arc = arc->next_child;
       }

      arc = sym->cg.parents;

      while (arc)
       {
         if (arc->parent != arc->child)
           scratch_arcs[scratch_arc_count++] = arc;
         arc->has_been_placed = 1;
         arc = arc->next_parent;
       }

      /* Keep track of how many symbols we're going to place.  */
      scratch_index = index;

      /* A lie, but it makes identifying
        these functions easier later.  */
      sym->has_been_placed = 1;
    }

  /* Now walk through the temporary arcs and copy
     those we care about into the high arcs array.  */
  for (index = 0; index < scratch_arc_count; index++)
    {
      Arc *arc = scratch_arcs[index];

      /* If this arc refers to highly used functions, then
        then we want to keep it.  */
      if (arc->child->has_been_placed
         && arc->parent->has_been_placed)
       {
         high_arcs[high_arc_count++] = scratch_arcs[index];

         /* We need to turn of has_been_placed since we're going to
            use the main arc placement algorithm on these arcs.  */
         arc->child->has_been_placed = 0;
         arc->parent->has_been_placed = 0;
       }
    }

  /* Dump the multi-site high usage functions which are not
     going to be ordered by the main ordering algorithm.  */
  for (index = 0; index < scratch_index; index++)
    {
      if (scratch_syms[index]->has_been_placed)
       printf ("%s\n", scratch_syms[index]->name);
    }

  /* Now we can order the multi-site high use
     functions based on the arcs between them.  */
  qsort (high_arcs, high_arc_count, sizeof (Arc *), cmp_arc_count);
  order_and_dump_functions_by_arcs (high_arcs, high_arc_count, 1,
                                unplaced_arcs, &unplaced_arc_count);

  /* Order and dump the high use functions left,
     these typically have only a few call sites.  */
  order_and_dump_functions_by_arcs (arcs, numarcs, 0,
                                unplaced_arcs, &unplaced_arc_count);

  /* Now place the rarely used functions.  */
  order_and_dump_functions_by_arcs (unplaced_arcs, unplaced_arc_count, 1,
                                scratch_arcs, &scratch_arc_count);

  /* Output any functions not emitted by the order_and_dump calls.  */
  for (index = 0; index < used; index++)
    if (used_syms[index]->has_been_placed == 0)
      printf("%s\n", used_syms[index]->name);

  /* Output the unused functions.  */
  for (index = 0; index < unused; index++)
    printf("%s\n", unused_syms[index]->name);

  unused_syms = (Sym **) xmalloc (symtab.len * sizeof (Sym *));
  used_syms = (Sym **) xmalloc (symtab.len * sizeof (Sym *));
  scratch_syms = (Sym **) xmalloc (symtab.len * sizeof (Sym *));
  high_arcs = (Arc **) xmalloc (numarcs * sizeof (Arc *));
  scratch_arcs = (Arc **) xmalloc (numarcs * sizeof (Arc *));
  unplaced_arcs = (Arc **) xmalloc (numarcs * sizeof (Arc *));

  free (unused_syms);
  free (used_syms);
  free (scratch_syms);
  free (high_arcs);
  free (scratch_arcs);
  free (unplaced_arcs);
}

Here is the call graph for this function:

Here is the caller graph for this function:

void cg_print_index ( void  )

Definition at line 560 of file cg_print.c.

{
  unsigned int index;
  unsigned int nnames, todo, i, j;
  int col, starting_col;
  Sym **name_sorted_syms, *sym;
  const char *filename;
  char buf[20];
  int column_width = (output_width - 1) / 3;     /* Don't write in last col!  */

  /* Now, sort regular function name
     alphabetically to create an index.  */
  name_sorted_syms = (Sym **) xmalloc ((symtab.len + num_cycles) * sizeof (Sym *));

  for (index = 0, nnames = 0; index < symtab.len; index++)
    {
      if (ignore_zeros && symtab.base[index].ncalls == 0
         && symtab.base[index].hist.time == 0)
       continue;

      name_sorted_syms[nnames++] = &symtab.base[index];
    }

  qsort (name_sorted_syms, nnames, sizeof (Sym *), cmp_name);

  for (index = 1, todo = nnames; index <= num_cycles; index++)
    name_sorted_syms[todo++] = &cycle_header[index];

  printf ("\f\n");
  printf (_("Index by function name\n\n"));
  index = (todo + 2) / 3;

  for (i = 0; i < index; i++)
    {
      col = 0;
      starting_col = 0;

      for (j = i; j < todo; j += index)
       {
         sym = name_sorted_syms[j];

         if (sym->cg.print_flag)
           sprintf (buf, "[%d]", sym->cg.index);
         else
           sprintf (buf, "(%d)", sym->cg.index);

         if (j < nnames)
           {
             if (bsd_style_output)
              {
                printf ("%6.6s %-19.19s", buf, sym->name);
              }
             else
              {
                col += strlen (buf);

                for (; col < starting_col + 5; ++col)
                  putchar (' ');

                printf (" %s ", buf);
                col += print_name_only (sym);

                if (!line_granularity && sym->is_static && sym->file)
                  {
                    filename = sym->file->name;

                    if (!print_path)
                     {
                       filename = strrchr (filename, '/');

                       if (filename)
                         ++filename;
                       else
                         filename = sym->file->name;
                     }

                    printf (" (%s)", filename);
                    col += strlen (filename) + 3;
                  }
              }
           }
         else
           {
             if (bsd_style_output)
              {
                printf ("%6.6s ", buf);
                sprintf (buf, _("<cycle %d>"), sym->cg.cyc.num);
                printf ("%-19.19s", buf);
              }
             else
              {
                col += strlen (buf);
                for (; col < starting_col + 5; ++col)
                  putchar (' ');
                printf (" %s ", buf);
                sprintf (buf, _("<cycle %d>"), sym->cg.cyc.num);
                printf ("%s", buf);
                col += strlen (buf);
              }
           }

         starting_col += column_width;
       }

      printf ("\n");
    }

  free (name_sorted_syms);
}

Here is the call graph for this function:

Here is the caller graph for this function:


Variable Documentation

Definition at line 59 of file cg_print.c.