#include <stdlib.h>
#include "gprof.h"
double printtime;
sztype total_names;
int ncycle;
nltype *cyclenl;
void
addarc(nltype *parentp, nltype *childp, actype count)
{
arctype *arcp;
#ifdef DEBUG
if (debug & TALLYDEBUG) {
(void) printf("[addarc] %lld arcs from %s to %s\n",
count, parentp->name, childp->name);
}
#endif
arcp = arclookup(parentp, childp);
if (arcp != 0) {
#ifdef DEBUG
if (!Dflag) {
if (debug & TALLYDEBUG) {
(void) printf("[tally] hit %lld += %lld\n",
arcp->arc_count, count);
}
} else {
if (debug & TALLYDEBUG) {
(void) printf("[tally] hit %lld -= %lld\n",
arcp->arc_count, count);
}
}
#endif
if (!Dflag)
arcp->arc_count += count;
else {
arcp->arc_count -= count;
if (arcp->arc_count < 0)
arcp->arc_count = 0;
}
return;
}
arcp = (arctype *)calloc(1, sizeof (*arcp));
arcp->arc_parentp = parentp;
arcp->arc_childp = childp;
arcp->arc_count = count;
arcp->arc_childlist = parentp->children;
parentp->children = arcp;
arcp->arc_parentlist = childp->parents;
childp->parents = arcp;
}
nltype **topsortnlp;
static int
topcmp(const void *arg1, const void *arg2)
{
nltype **npp1 = (nltype **)arg1;
nltype **npp2 = (nltype **)arg2;
return ((*npp1)->toporder - (*npp2)->toporder);
}
static void
timepropagate(nltype *parentp)
{
arctype *arcp;
nltype *childp;
double share;
double propshare;
if (parentp->propfraction == 0.0) {
return;
}
for (arcp = parentp->children; arcp; arcp = arcp->arc_childlist) {
childp = arcp->arc_childp;
if (arcp->arc_count == 0) {
continue;
}
if (childp == parentp) {
continue;
}
if (childp->propfraction == 0.0) {
continue;
}
if (childp->cyclehead != childp) {
if (parentp->cycleno == childp->cycleno) {
continue;
}
if (parentp->toporder <= childp->toporder) {
(void) fprintf(stderr,
"[propagate] toporder botches\n");
}
childp = childp->cyclehead;
} else {
if (parentp->toporder <= childp->toporder) {
(void) fprintf(stderr,
"[propagate] toporder botches\n");
continue;
}
}
if (childp->ncall == 0) {
continue;
}
arcp->arc_time = childp->time
* (((double)arcp->arc_count) /
((double)childp->ncall));
arcp->arc_childtime = childp->childtime
* (((double)arcp->arc_count) /
((double)childp->ncall));
share = arcp->arc_time + arcp->arc_childtime;
parentp->childtime += share;
propshare = parentp->propfraction * share;
parentp->propchild += propshare;
arcp->arc_time *= parentp->propfraction;
arcp->arc_childtime *= parentp->propfraction;
if (parentp->cyclehead != parentp) {
parentp->cyclehead->childtime += share;
parentp->cyclehead->propchild += propshare;
}
#ifdef DEBUG
if (debug & PROPDEBUG) {
(void) printf("[dotime] child \t");
printname(childp);
(void) printf(" with %f %f %lld/%lld\n",
childp->time, childp->childtime,
arcp->arc_count, childp->ncall);
(void) printf("[dotime] parent\t");
printname(parentp);
(void) printf("\n[dotime] share %f\n", share);
}
#endif
}
}
static void
cycletime(void)
{
int cycle;
nltype *cyclenlp;
nltype *childp;
for (cycle = 1; cycle <= ncycle; cycle += 1) {
cyclenlp = &cyclenl[cycle];
for (childp = cyclenlp->cnext; childp; childp = childp->cnext) {
if (childp->propfraction == 0.0) {
continue;
}
cyclenlp->time += childp->time;
}
cyclenlp->propself = cyclenlp->propfraction * cyclenlp->time;
}
}
static void
dotime(void)
{
int index;
cycletime();
for (index = 0; index < total_names; index += 1) {
timepropagate(topsortnlp[index]);
}
}
static void
cyclelink(void)
{
nltype *nlp;
nltype *cyclenlp;
int cycle;
nltype *memberp;
arctype *arcp;
mod_info_t *mi;
ncycle = 0;
for (mi = &modules; mi; mi = mi->next) {
for (nlp = mi->nl; nlp < mi->npe; nlp++) {
if (nlp->cyclehead == nlp && nlp->cnext != 0) {
ncycle += 1;
}
}
}
cyclenl = (nltype *) calloc(ncycle + 1, sizeof (nltype));
if (cyclenl == 0) {
(void) fprintf(stderr,
"%s: No room for %d bytes of cycle headers\n",
whoami, (ncycle + 1) * sizeof (nltype));
done();
}
cycle = 0;
for (mi = &modules; mi; mi = mi->next) {
for (nlp = mi->nl; nlp < mi->npe; nlp++) {
if (!(nlp->cyclehead == nlp && nlp->cnext != 0)) {
continue;
}
cycle += 1;
cyclenlp = &cyclenl[cycle];
cyclenlp->name = 0;
cyclenlp->value = 0;
cyclenlp->time = 0.0;
cyclenlp->childtime = 0.0;
cyclenlp->ncall = 0;
cyclenlp->selfcalls = 0;
cyclenlp->propfraction = 0.0;
cyclenlp->propself = 0.0;
cyclenlp->propchild = 0.0;
cyclenlp->printflag = TRUE;
cyclenlp->index = 0;
cyclenlp->toporder = DFN_NAN;
cyclenlp->cycleno = cycle;
cyclenlp->cyclehead = cyclenlp;
cyclenlp->cnext = nlp;
cyclenlp->parents = 0;
cyclenlp->children = 0;
#ifdef DEBUG
if (debug & CYCLEDEBUG) {
(void) printf("[cyclelink] ");
printname(nlp);
(void) printf(" is the head of cycle %d\n",
cycle);
}
#endif
for (memberp = nlp; memberp; memberp = memberp->cnext) {
memberp->cycleno = cycle;
memberp->cyclehead = cyclenlp;
}
for (memberp = nlp; memberp; memberp = memberp->cnext) {
for (arcp = memberp->parents; arcp;
arcp = arcp->arc_parentlist) {
if (arcp->arc_parentp == memberp)
continue;
if (arcp->arc_parentp->cycleno ==
cycle) {
cyclenlp->selfcalls +=
arcp->arc_count;
} else {
cyclenlp->ncall +=
arcp->arc_count;
}
}
}
}
}
}
static void
inheritflags(nltype *childp)
{
nltype *headp;
arctype *arcp;
nltype *parentp;
nltype *memp;
headp = childp->cyclehead;
if (childp == headp) {
childp->printflag = FALSE;
childp->propfraction = 0.0;
for (arcp = childp->parents; arcp;
arcp = arcp->arc_parentlist) {
parentp = arcp->arc_parentp;
if (childp == parentp) {
continue;
}
childp->printflag |= parentp->printflag;
if (childp->ncall) {
childp->propfraction += parentp->propfraction
* (((double)arcp->arc_count)
/ ((double)childp->ncall));
}
}
} else {
headp->printflag = FALSE;
headp->propfraction = 0.0;
for (memp = headp->cnext; memp; memp = memp->cnext) {
for (arcp = memp->parents; arcp;
arcp = arcp->arc_parentlist) {
if (arcp->arc_parentp->cyclehead == headp) {
continue;
}
parentp = arcp->arc_parentp;
headp->printflag |= parentp->printflag;
if (headp->ncall) {
headp->propfraction +=
parentp->propfraction
* (((double)arcp->arc_count)
/ ((double)headp->ncall));
}
}
}
for (memp = headp; memp; memp = memp->cnext) {
memp->printflag = headp->printflag;
memp->propfraction = headp->propfraction;
}
}
}
static int
check_ancestors(nltype *siblingp)
{
arctype *parentsp;
if (!siblingp->parents)
return (1);
for (parentsp = siblingp->parents; parentsp;
parentsp = parentsp->arc_parentlist) {
if (parentsp->arc_parentp->printflag)
return (1);
}
return (0);
}
static int
check_parents(nltype *siblingp)
{
arctype *parentsp;
if (!siblingp->parents)
return (1);
for (parentsp = siblingp->parents; parentsp;
parentsp = parentsp->arc_parentlist) {
if (!onlist(Elist, parentsp->arc_parentp->name))
return (1);
}
return (0);
}
static void
doflags(void)
{
int index;
nltype *childp;
nltype *oldhead;
oldhead = 0;
for (index = total_names - 1; index >= 0; index -= 1) {
childp = topsortnlp[index];
if (childp->cyclehead != oldhead) {
oldhead = childp->cyclehead;
inheritflags(childp);
}
#ifdef DEBUG
if (debug & PROPDEBUG) {
(void) printf("[doflags] ");
printname(childp);
(void) printf(
" inherits printflag %d and propfraction %f\n",
childp->printflag, childp->propfraction);
}
#endif
if (!childp->printflag) {
bool on_flist;
if (((on_flist = onlist(flist, childp->name)) != 0) ||
(!fflag && !onlist(elist, childp->name))) {
if (on_flist || check_ancestors(childp))
childp->printflag = TRUE;
}
} else {
if ((!onlist(flist, childp->name)) &&
onlist(elist, childp->name)) {
childp->printflag = FALSE;
}
}
if (childp->propfraction == 0.0) {
if (onlist(Flist, childp->name) ||
(!Fflag && !onlist(Elist, childp->name))) {
childp->propfraction = 1.0;
}
} else {
if (!onlist(Flist, childp->name) &&
onlist(Elist, childp->name)) {
if (check_parents(childp))
childp->propfraction = 0.0;
}
}
childp->propself = childp->time * childp->propfraction;
printtime += childp->propself;
#ifdef DEBUG
if (debug & PROPDEBUG) {
(void) printf("[doflags] ");
printname(childp);
(void) printf(" ends up with printflag %d and "
"propfraction %f\n",
childp->printflag, childp->propfraction);
(void) printf("time %f propself %f printtime %f\n",
childp->time, childp->propself, printtime);
}
#endif
}
}
nltype **
doarcs(void)
{
nltype *parentp, **timesortnlp;
arctype *arcp;
long i, index;
extern mod_info_t modules;
mod_info_t *mi;
for (mi = &modules; mi; mi = mi->next) {
for (parentp = mi->nl; parentp < mi->npe; parentp++) {
parentp->childtime = 0.0;
arcp = arclookup(parentp, parentp);
if (arcp != 0) {
parentp->ncall -= arcp->arc_count;
parentp->selfcalls = arcp->arc_count;
} else {
parentp->selfcalls = 0;
}
parentp->propfraction = 0.0;
parentp->propself = 0.0;
parentp->propchild = 0.0;
parentp->printflag = FALSE;
parentp->toporder = DFN_NAN;
parentp->cycleno = 0;
parentp->cyclehead = parentp;
parentp->cnext = 0;
if (cflag && (mi == &modules)) {
findcalls(parentp, parentp->value,
parentp->value + parentp->sz);
}
}
}
for (mi = &modules; mi; mi = mi->next) {
for (parentp = mi->nl; parentp < mi->npe; parentp++) {
if (parentp->toporder == DFN_NAN) {
dfn(parentp);
}
}
}
cyclelink();
topsortnlp = (nltype **) calloc(total_names, sizeof (nltype *));
if (topsortnlp == (nltype **) 0) {
(void) fprintf(stderr,
"[doarcs] ran out of memory for topo sorting\n");
}
index = 0;
for (mi = &modules; mi; mi = mi->next) {
for (i = 0; i < mi->nname; i++)
topsortnlp[index++] = &(mi->nl[i]);
}
qsort(topsortnlp, total_names, sizeof (nltype *), topcmp);
#ifdef DEBUG
if (debug & DFNDEBUG) {
(void) printf("[doarcs] topological sort listing\n");
for (index = 0; index < total_names; index += 1) {
(void) printf("[doarcs] ");
(void) printf("%d:", topsortnlp[ index ]->toporder);
printname(topsortnlp[ index ]);
(void) printf("\n");
}
}
#endif
doflags();
dotime();
timesortnlp = (nltype **) calloc(total_names + ncycle,
sizeof (nltype *));
if (timesortnlp == (nltype **) 0) {
(void) fprintf(stderr,
"%s: ran out of memory for sorting\n", whoami);
}
index = 0;
for (mi = &modules; mi; mi = mi->next) {
for (i = 0; i < mi->nname; i++)
timesortnlp[index++] = &(mi->nl[i]);
}
for (index = 1; index <= ncycle; index++)
timesortnlp[total_names+index-1] = &cyclenl[index];
qsort(timesortnlp, total_names + ncycle, sizeof (nltype *), totalcmp);
for (index = 0; index < total_names + ncycle; index++)
timesortnlp[index]->index = index + 1;
return (timesortnlp);
}