121957Sdist /*
2*62017Sbostic * Copyright (c) 1983, 1993
3*62017Sbostic * The Regents of the University of California. All rights reserved.
434199Sbostic *
542683Sbostic * %sccs.include.redist.c%
621957Sdist */
721957Sdist
84508Speter #ifndef lint
9*62017Sbostic static char sccsid[] = "@(#)arcs.c 8.1 (Berkeley) 06/06/93";
1034199Sbostic #endif /* not lint */
114508Speter
124561Speter #include "gprof.h"
134508Speter
1452652Smckusick #ifdef DEBUG
1552652Smckusick int visited;
1652652Smckusick int viable;
1752652Smckusick int newcycle;
1852652Smckusick int oldcycle;
1952652Smckusick #endif DEBUG
2052652Smckusick
214721Speter /*
224721Speter * add (or just increment) an arc
234721Speter */
addarc(parentp,childp,count)244721Speter addarc( parentp , childp , count )
254721Speter nltype *parentp;
264721Speter nltype *childp;
274721Speter long count;
284721Speter {
294721Speter arctype *arcp;
304721Speter
314721Speter # ifdef DEBUG
324721Speter if ( debug & TALLYDEBUG ) {
334721Speter printf( "[addarc] %d arcs from %s to %s\n" ,
344721Speter count , parentp -> name , childp -> name );
354721Speter }
364721Speter # endif DEBUG
374721Speter arcp = arclookup( parentp , childp );
384721Speter if ( arcp != 0 ) {
394721Speter /*
404721Speter * a hit: just increment the count.
414721Speter */
424721Speter # ifdef DEBUG
434721Speter if ( debug & TALLYDEBUG ) {
444721Speter printf( "[tally] hit %d += %d\n" ,
454721Speter arcp -> arc_count , count );
464721Speter }
474721Speter # endif DEBUG
484721Speter arcp -> arc_count += count;
494721Speter return;
504721Speter }
5154805Storek arcp = (arctype *)calloc( 1 , sizeof *arcp );
524721Speter arcp -> arc_parentp = parentp;
534721Speter arcp -> arc_childp = childp;
544721Speter arcp -> arc_count = count;
554721Speter /*
564721Speter * prepend this child to the children of this parent
574721Speter */
584721Speter arcp -> arc_childlist = parentp -> children;
594721Speter parentp -> children = arcp;
604721Speter /*
614721Speter * prepend this parent to the parents of this child
624721Speter */
634721Speter arcp -> arc_parentlist = childp -> parents;
644721Speter childp -> parents = arcp;
654721Speter }
664721Speter
677172Speter /*
687172Speter * the code below topologically sorts the graph (collapsing cycles),
697172Speter * and propagates time bottom up and flags top down.
707172Speter */
717172Speter
727172Speter /*
737172Speter * the topologically sorted name list pointers
747172Speter */
757172Speter nltype **topsortnlp;
767172Speter
topcmp(npp1,npp2)774508Speter topcmp( npp1 , npp2 )
784508Speter nltype **npp1;
794508Speter nltype **npp2;
804508Speter {
814508Speter return (*npp1) -> toporder - (*npp2) -> toporder;
824508Speter }
834508Speter
8416850Smckusick nltype **
doarcs()854508Speter doarcs()
864508Speter {
8716850Smckusick nltype *parentp, **timesortnlp;
884508Speter arctype *arcp;
894508Speter long index;
9052652Smckusick long pass;
914508Speter
924508Speter /*
934508Speter * initialize various things:
944508Speter * zero out child times.
954508Speter * count self-recursive calls.
964508Speter * indicate that nothing is on cycles.
974508Speter */
984508Speter for ( parentp = nl ; parentp < npe ; parentp++ ) {
994508Speter parentp -> childtime = 0.0;
1004508Speter arcp = arclookup( parentp , parentp );
1014508Speter if ( arcp != 0 ) {
1024508Speter parentp -> ncall -= arcp -> arc_count;
1034508Speter parentp -> selfcalls = arcp -> arc_count;
1044508Speter } else {
1054508Speter parentp -> selfcalls = 0;
1064508Speter }
10752652Smckusick parentp -> npropcall = parentp -> ncall;
1087221Speter parentp -> propfraction = 0.0;
1097221Speter parentp -> propself = 0.0;
1107221Speter parentp -> propchild = 0.0;
1117172Speter parentp -> printflag = FALSE;
11210284Speter parentp -> toporder = DFN_NAN;
1134508Speter parentp -> cycleno = 0;
1144508Speter parentp -> cyclehead = parentp;
1154508Speter parentp -> cnext = 0;
1167172Speter if ( cflag ) {
11725713Ssam findcall( parentp , parentp -> value , (parentp+1) -> value );
1187172Speter }
1194508Speter }
12052652Smckusick for ( pass = 1 ; ; pass++ ) {
12152652Smckusick /*
12252652Smckusick * topologically order things
12352652Smckusick * if any node is unnumbered,
12452652Smckusick * number it and any of its descendents.
12552652Smckusick */
12652652Smckusick for ( dfn_init() , parentp = nl ; parentp < npe ; parentp++ ) {
12752652Smckusick if ( parentp -> toporder == DFN_NAN ) {
12852652Smckusick dfn( parentp );
12952652Smckusick }
1304508Speter }
13152652Smckusick /*
13252652Smckusick * link together nodes on the same cycle
13352652Smckusick */
13452652Smckusick cyclelink();
13552652Smckusick /*
13652652Smckusick * if no cycles to break up, proceed
13752652Smckusick */
13852652Smckusick if ( ! Cflag )
13952652Smckusick break;
14052652Smckusick /*
14152652Smckusick * analyze cycles to determine breakup
14252652Smckusick */
14352652Smckusick # ifdef DEBUG
14452652Smckusick if ( debug & BREAKCYCLE ) {
14552652Smckusick printf("[doarcs] pass %d, cycle(s) %d\n" , pass , ncycle );
14652652Smckusick }
14752652Smckusick # endif DEBUG
14852652Smckusick if ( pass == 1 ) {
14952652Smckusick printf( "\n\n%s %s\n%s %d:\n" ,
15052652Smckusick "The following arcs were deleted" ,
15152652Smckusick "from the propagation calculation" ,
15252652Smckusick "to reduce the maximum cycle size to", cyclethreshold );
15352652Smckusick }
15452652Smckusick if ( cycleanalyze() )
15552652Smckusick break;
15652652Smckusick free ( cyclenl );
15752652Smckusick ncycle = 0;
15852652Smckusick for ( parentp = nl ; parentp < npe ; parentp++ ) {
15952652Smckusick parentp -> toporder = DFN_NAN;
16052652Smckusick parentp -> cycleno = 0;
16152652Smckusick parentp -> cyclehead = parentp;
16252652Smckusick parentp -> cnext = 0;
16352652Smckusick }
1644508Speter }
16552652Smckusick if ( pass > 1 ) {
16652652Smckusick printf( "\f\n" );
16752652Smckusick } else {
16852652Smckusick printf( "\tNone\n\n" );
16952652Smckusick }
1704508Speter /*
1714508Speter * Sort the symbol table in reverse topological order
1724508Speter */
1734508Speter topsortnlp = (nltype **) calloc( nname , sizeof(nltype *) );
1744508Speter if ( topsortnlp == (nltype **) 0 ) {
1754508Speter fprintf( stderr , "[doarcs] ran out of memory for topo sorting\n" );
1764508Speter }
1774508Speter for ( index = 0 ; index < nname ; index += 1 ) {
1784508Speter topsortnlp[ index ] = &nl[ index ];
1794508Speter }
1804508Speter qsort( topsortnlp , nname , sizeof(nltype *) , topcmp );
1814508Speter # ifdef DEBUG
1824508Speter if ( debug & DFNDEBUG ) {
1834508Speter printf( "[doarcs] topological sort listing\n" );
1844508Speter for ( index = 0 ; index < nname ; index += 1 ) {
1854508Speter printf( "[doarcs] " );
1864508Speter printf( "%d:" , topsortnlp[ index ] -> toporder );
1874508Speter printname( topsortnlp[ index ] );
1884508Speter printf( "\n" );
1894508Speter }
1904508Speter }
1914508Speter # endif DEBUG
1924508Speter /*
1937221Speter * starting from the topological top,
1947221Speter * propagate print flags to children.
1957221Speter * also, calculate propagation fractions.
1967221Speter * this happens before time propagation
1977221Speter * since time propagation uses the fractions.
1987221Speter */
1997221Speter doflags();
2007221Speter /*
2014508Speter * starting from the topological bottom,
2027172Speter * propogate children times up to parents.
2034508Speter */
2047172Speter dotime();
20516850Smckusick /*
20616850Smckusick * Now, sort by propself + propchild.
20716850Smckusick * sorting both the regular function names
20816850Smckusick * and cycle headers.
20916850Smckusick */
21016850Smckusick timesortnlp = (nltype **) calloc( nname + ncycle , sizeof(nltype *) );
21116850Smckusick if ( timesortnlp == (nltype **) 0 ) {
21216850Smckusick fprintf( stderr , "%s: ran out of memory for sorting\n" , whoami );
21316850Smckusick }
21416850Smckusick for ( index = 0 ; index < nname ; index++ ) {
21516850Smckusick timesortnlp[index] = &nl[index];
21616850Smckusick }
21716850Smckusick for ( index = 1 ; index <= ncycle ; index++ ) {
21816850Smckusick timesortnlp[nname+index-1] = &cyclenl[index];
21916850Smckusick }
22016850Smckusick qsort( timesortnlp , nname + ncycle , sizeof(nltype *) , totalcmp );
22116850Smckusick for ( index = 0 ; index < nname + ncycle ; index++ ) {
22216850Smckusick timesortnlp[ index ] -> index = index + 1;
22316850Smckusick }
22416850Smckusick return( timesortnlp );
2257172Speter }
2267172Speter
dotime()2277172Speter dotime()
2287172Speter {
2297172Speter int index;
2307172Speter
2317172Speter cycletime();
2324508Speter for ( index = 0 ; index < nname ; index += 1 ) {
2337172Speter timepropagate( topsortnlp[ index ] );
2347127Speter }
2357127Speter }
2367127Speter
timepropagate(parentp)2377172Speter timepropagate( parentp )
2387127Speter nltype *parentp;
2397127Speter {
2407127Speter arctype *arcp;
2417127Speter nltype *childp;
2427127Speter double share;
2437221Speter double propshare;
2447127Speter
2457221Speter if ( parentp -> propfraction == 0.0 ) {
2467221Speter return;
2477221Speter }
2487127Speter /*
2497127Speter * gather time from children of this parent.
2507127Speter */
2517172Speter for ( arcp = parentp -> children ; arcp ; arcp = arcp -> arc_childlist ) {
2527127Speter childp = arcp -> arc_childp;
25352652Smckusick if ( arcp -> arc_flags & DEADARC ) {
25452652Smckusick continue;
25552652Smckusick }
2567127Speter if ( arcp -> arc_count == 0 ) {
2577127Speter continue;
2587127Speter }
2597221Speter if ( childp == parentp ) {
2607127Speter continue;
2617127Speter }
2627221Speter if ( childp -> propfraction == 0.0 ) {
2637127Speter continue;
2647127Speter }
2657127Speter if ( childp -> cyclehead != childp ) {
2667127Speter if ( parentp -> cycleno == childp -> cycleno ) {
2677127Speter continue;
2687127Speter }
2697127Speter if ( parentp -> toporder <= childp -> toporder ) {
2707127Speter fprintf( stderr , "[propagate] toporder botches\n" );
2714508Speter }
2727127Speter childp = childp -> cyclehead;
2737127Speter } else {
2747127Speter if ( parentp -> toporder <= childp -> toporder ) {
2757127Speter fprintf( stderr , "[propagate] toporder botches\n" );
2764508Speter continue;
2774508Speter }
2787127Speter }
27952652Smckusick if ( childp -> npropcall == 0 ) {
2807221Speter continue;
2817221Speter }
2827127Speter /*
2837127Speter * distribute time for this arc
2847127Speter */
2857221Speter arcp -> arc_time = childp -> time
2867221Speter * ( ( (double) arcp -> arc_count ) /
28752652Smckusick ( (double) childp -> npropcall ) );
2887221Speter arcp -> arc_childtime = childp -> childtime
2897221Speter * ( ( (double) arcp -> arc_count ) /
29052652Smckusick ( (double) childp -> npropcall ) );
2917127Speter share = arcp -> arc_time + arcp -> arc_childtime;
2927127Speter parentp -> childtime += share;
2937127Speter /*
2947221Speter * ( 1 - propfraction ) gets lost along the way
2957127Speter */
2967221Speter propshare = parentp -> propfraction * share;
2977221Speter /*
2987221Speter * fix things for printing
2997221Speter */
3007221Speter parentp -> propchild += propshare;
3017221Speter arcp -> arc_time *= parentp -> propfraction;
3027221Speter arcp -> arc_childtime *= parentp -> propfraction;
3037221Speter /*
3047221Speter * add this share to the parent's cycle header, if any.
3057221Speter */
3067127Speter if ( parentp -> cyclehead != parentp ) {
3077127Speter parentp -> cyclehead -> childtime += share;
3087221Speter parentp -> cyclehead -> propchild += propshare;
3094508Speter }
3107221Speter # ifdef DEBUG
3117221Speter if ( debug & PROPDEBUG ) {
3127221Speter printf( "[dotime] child \t" );
3137221Speter printname( childp );
3147221Speter printf( " with %f %f %d/%d\n" ,
3157221Speter childp -> time , childp -> childtime ,
31652652Smckusick arcp -> arc_count , childp -> npropcall );
3177221Speter printf( "[dotime] parent\t" );
3187221Speter printname( parentp );
3197221Speter printf( "\n[dotime] share %f\n" , share );
3207221Speter }
3217221Speter # endif DEBUG
3224508Speter }
3234508Speter }
3244508Speter
cyclelink()3254508Speter cyclelink()
3264508Speter {
3274508Speter register nltype *nlp;
3284508Speter register nltype *cyclenlp;
3294508Speter int cycle;
3307172Speter nltype *memberp;
3317248Speter arctype *arcp;
3324508Speter
3334508Speter /*
3344508Speter * Count the number of cycles, and initialze the cycle lists
3354508Speter */
3367127Speter ncycle = 0;
3374508Speter for ( nlp = nl ; nlp < npe ; nlp++ ) {
3384508Speter /*
3394508Speter * this is how you find unattached cycles
3404508Speter */
3414508Speter if ( nlp -> cyclehead == nlp && nlp -> cnext != 0 ) {
3427127Speter ncycle += 1;
3434508Speter }
3444508Speter }
3457127Speter /*
3467127Speter * cyclenl is indexed by cycle number:
3477127Speter * i.e. it is origin 1, not origin 0.
3487127Speter */
3497127Speter cyclenl = (nltype *) calloc( ncycle + 1 , sizeof( nltype ) );
3507127Speter if ( cyclenl == 0 ) {
3517127Speter fprintf( stderr , "%s: No room for %d bytes of cycle headers\n" ,
3527127Speter whoami , ( ncycle + 1 ) * sizeof( nltype ) );
3537127Speter done();
3544508Speter }
3554508Speter /*
3564508Speter * now link cycles to true cycleheads,
3574508Speter * number them, accumulate the data for the cycle
3584508Speter */
3594508Speter cycle = 0;
3604508Speter for ( nlp = nl ; nlp < npe ; nlp++ ) {
36110284Speter if ( !( nlp -> cyclehead == nlp && nlp -> cnext != 0 ) ) {
3624508Speter continue;
3634508Speter }
3644508Speter cycle += 1;
3657127Speter cyclenlp = &cyclenl[cycle];
3667249Speter cyclenlp -> name = 0; /* the name */
3677221Speter cyclenlp -> value = 0; /* the pc entry point */
3687221Speter cyclenlp -> time = 0.0; /* ticks in this routine */
3697221Speter cyclenlp -> childtime = 0.0; /* cumulative ticks in children */
3707221Speter cyclenlp -> ncall = 0; /* how many times called */
3717221Speter cyclenlp -> selfcalls = 0; /* how many calls to self */
3727221Speter cyclenlp -> propfraction = 0.0; /* what % of time propagates */
3737221Speter cyclenlp -> propself = 0.0; /* how much self time propagates */
3747221Speter cyclenlp -> propchild = 0.0; /* how much child time propagates */
3757221Speter cyclenlp -> printflag = TRUE; /* should this be printed? */
3767221Speter cyclenlp -> index = 0; /* index in the graph list */
37710284Speter cyclenlp -> toporder = DFN_NAN; /* graph call chain top-sort order */
3787221Speter cyclenlp -> cycleno = cycle; /* internal number of cycle on */
3797221Speter cyclenlp -> cyclehead = cyclenlp; /* pointer to head of cycle */
3807221Speter cyclenlp -> cnext = nlp; /* pointer to next member of cycle */
3817221Speter cyclenlp -> parents = 0; /* list of caller arcs */
3827221Speter cyclenlp -> children = 0; /* list of callee arcs */
3834508Speter # ifdef DEBUG
3844508Speter if ( debug & CYCLEDEBUG ) {
3854508Speter printf( "[cyclelink] " );
3864508Speter printname( nlp );
3874508Speter printf( " is the head of cycle %d\n" , cycle );
3884508Speter }
3894508Speter # endif DEBUG
3907248Speter /*
3917248Speter * link members to cycle header
3927248Speter */
3937172Speter for ( memberp = nlp ; memberp ; memberp = memberp -> cnext ) {
3947172Speter memberp -> cycleno = cycle;
3957172Speter memberp -> cyclehead = cyclenlp;
3967172Speter }
3977248Speter /*
3987248Speter * count calls from outside the cycle
3997248Speter * and those among cycle members
4007248Speter */
4017248Speter for ( memberp = nlp ; memberp ; memberp = memberp -> cnext ) {
4027248Speter for ( arcp=memberp->parents ; arcp ; arcp=arcp->arc_parentlist ) {
4037248Speter if ( arcp -> arc_parentp == memberp ) {
4047248Speter continue;
4057248Speter }
4067248Speter if ( arcp -> arc_parentp -> cycleno == cycle ) {
4077248Speter cyclenlp -> selfcalls += arcp -> arc_count;
4087248Speter } else {
40952652Smckusick cyclenlp -> npropcall += arcp -> arc_count;
4107248Speter }
4117248Speter }
4127248Speter }
4137172Speter }
4147172Speter }
4157172Speter
41652652Smckusick /*
41752652Smckusick * analyze cycles to determine breakup
41852652Smckusick */
cycleanalyze()41952652Smckusick cycleanalyze()
42052652Smckusick {
42152652Smckusick arctype **cyclestack;
42252652Smckusick arctype **stkp;
42352652Smckusick arctype **arcpp;
42452652Smckusick arctype **endlist;
42552652Smckusick arctype *arcp;
42652652Smckusick nltype *nlp;
42752652Smckusick cltype *clp;
42852652Smckusick bool ret;
42952652Smckusick bool done;
43052652Smckusick int size;
43152652Smckusick int cycleno;
43252652Smckusick
43352652Smckusick /*
43452652Smckusick * calculate the size of the cycle, and find nodes that
43552652Smckusick * exit the cycle as they are desirable targets to cut
43652652Smckusick * some of their parents
43752652Smckusick */
43852652Smckusick for ( done = TRUE , cycleno = 1 ; cycleno <= ncycle ; cycleno++ ) {
43952652Smckusick size = 0;
44052652Smckusick for (nlp = cyclenl[ cycleno ] . cnext; nlp; nlp = nlp -> cnext) {
44152652Smckusick size += 1;
44252652Smckusick nlp -> parentcnt = 0;
44352652Smckusick nlp -> flags &= ~HASCYCLEXIT;
44452652Smckusick for ( arcp = nlp -> parents; arcp; arcp = arcp -> arc_parentlist ) {
44552652Smckusick nlp -> parentcnt += 1;
44652652Smckusick if ( arcp -> arc_parentp -> cycleno != cycleno )
44752652Smckusick nlp -> flags |= HASCYCLEXIT;
44852652Smckusick }
44952652Smckusick }
45052652Smckusick if ( size <= cyclethreshold )
45152652Smckusick continue;
45252652Smckusick done = FALSE;
45352652Smckusick cyclestack = (arctype **) calloc( size + 1 , sizeof( arctype *) );
45452652Smckusick if ( cyclestack == 0 ) {
45552652Smckusick fprintf( stderr , "%s: No room for %d bytes of cycle stack\n" ,
45652652Smckusick whoami , ( size + 1 ) * sizeof( arctype * ) );
45752652Smckusick return;
45852652Smckusick }
45952652Smckusick # ifdef DEBUG
46052652Smckusick if ( debug & BREAKCYCLE ) {
46152652Smckusick printf( "[cycleanalyze] starting cycle %d of %d, size %d\n" ,
46252652Smckusick cycleno , ncycle , size );
46352652Smckusick }
46452652Smckusick # endif DEBUG
46552652Smckusick for ( nlp = cyclenl[ cycleno ] . cnext ; nlp ; nlp = nlp -> cnext ) {
46652652Smckusick stkp = &cyclestack[0];
46752652Smckusick nlp -> flags |= CYCLEHEAD;
46852652Smckusick ret = descend ( nlp , cyclestack , stkp );
46952652Smckusick nlp -> flags &= ~CYCLEHEAD;
47052652Smckusick if ( ret == FALSE )
47152652Smckusick break;
47252652Smckusick }
47352652Smckusick free( cyclestack );
47452652Smckusick if ( cyclecnt > 0 ) {
47552652Smckusick compresslist();
47652652Smckusick for ( clp = cyclehead ; clp ; ) {
47752652Smckusick endlist = &clp -> list[ clp -> size ];
47852652Smckusick for ( arcpp = clp -> list ; arcpp < endlist ; arcpp++ )
47952652Smckusick (*arcpp) -> arc_cyclecnt--;
48052652Smckusick cyclecnt--;
48152652Smckusick clp = clp -> next;
48252652Smckusick free( clp );
48352652Smckusick }
48452652Smckusick cyclehead = 0;
48552652Smckusick }
48652652Smckusick }
48752652Smckusick # ifdef DEBUG
48852652Smckusick if ( debug & BREAKCYCLE ) {
48952652Smckusick printf("%s visited %d, viable %d, newcycle %d, oldcycle %d\n",
49052652Smckusick "[doarcs]" , visited , viable , newcycle , oldcycle);
49152652Smckusick }
49252652Smckusick # endif DEBUG
49352652Smckusick return( done );
49452652Smckusick }
49552652Smckusick
descend(node,stkstart,stkp)49652652Smckusick descend( node , stkstart , stkp )
49752652Smckusick nltype *node;
49852652Smckusick arctype **stkstart;
49952652Smckusick arctype **stkp;
50052652Smckusick {
50152652Smckusick arctype *arcp;
50252652Smckusick bool ret;
50352652Smckusick
50452652Smckusick for ( arcp = node -> children ; arcp ; arcp = arcp -> arc_childlist ) {
50552652Smckusick # ifdef DEBUG
50652652Smckusick visited++;
50752652Smckusick # endif DEBUG
50852652Smckusick if ( arcp -> arc_childp -> cycleno != node -> cycleno
50952652Smckusick || ( arcp -> arc_childp -> flags & VISITED )
51052652Smckusick || ( arcp -> arc_flags & DEADARC ) )
51152652Smckusick continue;
51252652Smckusick # ifdef DEBUG
51352652Smckusick viable++;
51452652Smckusick # endif DEBUG
51552652Smckusick *stkp = arcp;
51652652Smckusick if ( arcp -> arc_childp -> flags & CYCLEHEAD ) {
51752652Smckusick if ( addcycle( stkstart , stkp ) == FALSE )
51852652Smckusick return( FALSE );
51952652Smckusick continue;
52052652Smckusick }
52152652Smckusick arcp -> arc_childp -> flags |= VISITED;
52252652Smckusick ret = descend( arcp -> arc_childp , stkstart , stkp + 1 );
52352652Smckusick arcp -> arc_childp -> flags &= ~VISITED;
52452652Smckusick if ( ret == FALSE )
52552652Smckusick return( FALSE );
52652652Smckusick }
52752652Smckusick }
52852652Smckusick
addcycle(stkstart,stkend)52952652Smckusick addcycle( stkstart , stkend )
53052652Smckusick arctype **stkstart;
53152652Smckusick arctype **stkend;
53252652Smckusick {
53352652Smckusick arctype **arcpp;
53452652Smckusick arctype **stkloc;
53552652Smckusick arctype **stkp;
53652652Smckusick arctype **endlist;
53752652Smckusick arctype *minarc;
53852652Smckusick arctype *arcp;
53952652Smckusick cltype *clp;
54052652Smckusick int size;
54152652Smckusick
54252652Smckusick size = stkend - stkstart + 1;
54352652Smckusick if ( size <= 1 )
54452652Smckusick return( TRUE );
54552652Smckusick for ( arcpp = stkstart , minarc = *arcpp ; arcpp <= stkend ; arcpp++ ) {
54652652Smckusick if ( *arcpp > minarc )
54752652Smckusick continue;
54852652Smckusick minarc = *arcpp;
54952652Smckusick stkloc = arcpp;
55052652Smckusick }
55152652Smckusick for ( clp = cyclehead ; clp ; clp = clp -> next ) {
55252652Smckusick if ( clp -> size != size )
55352652Smckusick continue;
55452652Smckusick stkp = stkloc;
55552652Smckusick endlist = &clp -> list[ size ];
55652652Smckusick for ( arcpp = clp -> list ; arcpp < endlist ; arcpp++ ) {
55752652Smckusick if ( *stkp++ != *arcpp )
55852652Smckusick break;
55952652Smckusick if ( stkp > stkend )
56052652Smckusick stkp = stkstart;
56152652Smckusick }
56252652Smckusick if ( arcpp == endlist ) {
56352652Smckusick # ifdef DEBUG
56452652Smckusick oldcycle++;
56552652Smckusick # endif DEBUG
56652652Smckusick return( TRUE );
56752652Smckusick }
56852652Smckusick }
56952652Smckusick clp = (cltype *)
57052652Smckusick calloc( 1 , sizeof ( cltype ) + ( size - 1 ) * sizeof( arctype * ) );
57152652Smckusick if ( clp == 0 ) {
57252652Smckusick fprintf( stderr , "%s: No room for %d bytes of subcycle storage\n" ,
57352652Smckusick whoami , sizeof ( cltype ) + ( size - 1 ) * sizeof( arctype * ) );
57452652Smckusick return( FALSE );
57552652Smckusick }
57652652Smckusick stkp = stkloc;
57752652Smckusick endlist = &clp -> list[ size ];
57852652Smckusick for ( arcpp = clp -> list ; arcpp < endlist ; arcpp++ ) {
57952652Smckusick arcp = *arcpp = *stkp++;
58052652Smckusick if ( stkp > stkend )
58152652Smckusick stkp = stkstart;
58252652Smckusick arcp -> arc_cyclecnt++;
58352652Smckusick if ( ( arcp -> arc_flags & ONLIST ) == 0 ) {
58452652Smckusick arcp -> arc_flags |= ONLIST;
58552652Smckusick arcp -> arc_next = archead;
58652652Smckusick archead = arcp;
58752652Smckusick }
58852652Smckusick }
58952652Smckusick clp -> size = size;
59052652Smckusick clp -> next = cyclehead;
59152652Smckusick cyclehead = clp;
59252652Smckusick # ifdef DEBUG
59352652Smckusick newcycle++;
59452652Smckusick if ( debug & SUBCYCLELIST ) {
59552652Smckusick printsubcycle( clp );
59652652Smckusick }
59752652Smckusick # endif DEBUG
59852652Smckusick cyclecnt++;
59952652Smckusick if ( cyclecnt >= CYCLEMAX )
60052652Smckusick return( FALSE );
60152652Smckusick return( TRUE );
60252652Smckusick }
60352652Smckusick
compresslist()60452652Smckusick compresslist()
60552652Smckusick {
60652652Smckusick cltype *clp;
60752652Smckusick cltype **prev;
60852652Smckusick arctype **arcpp;
60952652Smckusick arctype **endlist;
61052652Smckusick arctype *arcp;
61152652Smckusick arctype *maxarcp;
61252652Smckusick arctype *maxexitarcp;
61352652Smckusick arctype *maxwithparentarcp;
61452652Smckusick arctype *maxnoparentarcp;
61552652Smckusick int maxexitcnt;
61652652Smckusick int maxwithparentcnt;
61752652Smckusick int maxnoparentcnt;
61852652Smckusick char *type;
61952652Smckusick
62052652Smckusick maxexitcnt = 0;
62152652Smckusick maxwithparentcnt = 0;
62252652Smckusick maxnoparentcnt = 0;
62352652Smckusick for ( endlist = &archead , arcp = archead ; arcp ; ) {
62452652Smckusick if ( arcp -> arc_cyclecnt == 0 ) {
62552652Smckusick arcp -> arc_flags &= ~ONLIST;
62652652Smckusick *endlist = arcp -> arc_next;
62752652Smckusick arcp -> arc_next = 0;
62852652Smckusick arcp = *endlist;
62952652Smckusick continue;
63052652Smckusick }
63152652Smckusick if ( arcp -> arc_childp -> flags & HASCYCLEXIT ) {
63252652Smckusick if ( arcp -> arc_cyclecnt > maxexitcnt ||
63352652Smckusick ( arcp -> arc_cyclecnt == maxexitcnt &&
63452652Smckusick arcp -> arc_cyclecnt < maxexitarcp -> arc_count ) ) {
63552652Smckusick maxexitcnt = arcp -> arc_cyclecnt;
63652652Smckusick maxexitarcp = arcp;
63752652Smckusick }
63852652Smckusick } else if ( arcp -> arc_childp -> parentcnt > 1 ) {
63952652Smckusick if ( arcp -> arc_cyclecnt > maxwithparentcnt ||
64052652Smckusick ( arcp -> arc_cyclecnt == maxwithparentcnt &&
64152652Smckusick arcp -> arc_cyclecnt < maxwithparentarcp -> arc_count ) ) {
64252652Smckusick maxwithparentcnt = arcp -> arc_cyclecnt;
64352652Smckusick maxwithparentarcp = arcp;
64452652Smckusick }
64552652Smckusick } else {
64652652Smckusick if ( arcp -> arc_cyclecnt > maxnoparentcnt ||
64752652Smckusick ( arcp -> arc_cyclecnt == maxnoparentcnt &&
64852652Smckusick arcp -> arc_cyclecnt < maxnoparentarcp -> arc_count ) ) {
64952652Smckusick maxnoparentcnt = arcp -> arc_cyclecnt;
65052652Smckusick maxnoparentarcp = arcp;
65152652Smckusick }
65252652Smckusick }
65352652Smckusick endlist = &arcp -> arc_next;
65452652Smckusick arcp = arcp -> arc_next;
65552652Smckusick }
65652652Smckusick if ( maxexitcnt > 0 ) {
65752652Smckusick /*
65852652Smckusick * first choice is edge leading to node with out-of-cycle parent
65952652Smckusick */
66052652Smckusick maxarcp = maxexitarcp;
66152652Smckusick # ifdef DEBUG
66252652Smckusick type = "exit";
66352652Smckusick # endif DEBUG
66452652Smckusick } else if ( maxwithparentcnt > 0 ) {
66552652Smckusick /*
66652652Smckusick * second choice is edge leading to node with at least one
66752652Smckusick * other in-cycle parent
66852652Smckusick */
66952652Smckusick maxarcp = maxwithparentarcp;
67052652Smckusick # ifdef DEBUG
67152652Smckusick type = "internal";
67252652Smckusick # endif DEBUG
67352652Smckusick } else {
67452652Smckusick /*
67552652Smckusick * last choice is edge leading to node with only this arc as
67652652Smckusick * a parent (as it will now be orphaned)
67752652Smckusick */
67852652Smckusick maxarcp = maxnoparentarcp;
67952652Smckusick # ifdef DEBUG
68052652Smckusick type = "orphan";
68152652Smckusick # endif DEBUG
68252652Smckusick }
68352652Smckusick maxarcp -> arc_flags |= DEADARC;
68452652Smckusick maxarcp -> arc_childp -> parentcnt -= 1;
68552652Smckusick maxarcp -> arc_childp -> npropcall -= maxarcp -> arc_count;
68652652Smckusick # ifdef DEBUG
68752652Smckusick if ( debug & BREAKCYCLE ) {
68852652Smckusick printf( "%s delete %s arc: %s (%d) -> %s from %d cycle(s)\n" ,
68952652Smckusick "[compresslist]" , type , maxarcp -> arc_parentp -> name ,
69052652Smckusick maxarcp -> arc_count , maxarcp -> arc_childp -> name ,
69152652Smckusick maxarcp -> arc_cyclecnt );
69252652Smckusick }
69352652Smckusick # endif DEBUG
69452652Smckusick printf( "\t%s to %s with %d calls\n" , maxarcp -> arc_parentp -> name ,
69552652Smckusick maxarcp -> arc_childp -> name , maxarcp -> arc_count );
69652652Smckusick prev = &cyclehead;
69752652Smckusick for ( clp = cyclehead ; clp ; ) {
69852652Smckusick endlist = &clp -> list[ clp -> size ];
69952652Smckusick for ( arcpp = clp -> list ; arcpp < endlist ; arcpp++ )
70052652Smckusick if ( (*arcpp) -> arc_flags & DEADARC )
70152652Smckusick break;
70252652Smckusick if ( arcpp == endlist ) {
70352652Smckusick prev = &clp -> next;
70452652Smckusick clp = clp -> next;
70552652Smckusick continue;
70652652Smckusick }
70752652Smckusick for ( arcpp = clp -> list ; arcpp < endlist ; arcpp++ )
70852652Smckusick (*arcpp) -> arc_cyclecnt--;
70952652Smckusick cyclecnt--;
71052652Smckusick *prev = clp -> next;
71152652Smckusick clp = clp -> next;
71252652Smckusick free( clp );
71352652Smckusick }
71452652Smckusick }
71552652Smckusick
71652652Smckusick #ifdef DEBUG
printsubcycle(clp)71752652Smckusick printsubcycle( clp )
71852652Smckusick cltype *clp;
71952652Smckusick {
72052652Smckusick arctype **arcpp;
72152652Smckusick arctype **endlist;
72252652Smckusick
72352652Smckusick arcpp = clp -> list;
72452652Smckusick printf( "%s <cycle %d>\n" , (*arcpp) -> arc_parentp -> name ,
72552652Smckusick (*arcpp) -> arc_parentp -> cycleno ) ;
72652652Smckusick for ( endlist = &clp -> list[ clp -> size ]; arcpp < endlist ; arcpp++ )
72752652Smckusick printf( "\t(%d) -> %s\n" , (*arcpp) -> arc_count ,
72852652Smckusick (*arcpp) -> arc_childp -> name ) ;
72952652Smckusick }
73052652Smckusick #endif DEBUG
73152652Smckusick
cycletime()7327172Speter cycletime()
7337172Speter {
7347172Speter int cycle;
7357172Speter nltype *cyclenlp;
7367172Speter nltype *childp;
7377172Speter
7387172Speter for ( cycle = 1 ; cycle <= ncycle ; cycle += 1 ) {
7397172Speter cyclenlp = &cyclenl[ cycle ];
7407221Speter for ( childp = cyclenlp -> cnext ; childp ; childp = childp -> cnext ) {
7417221Speter if ( childp -> propfraction == 0.0 ) {
7427221Speter /*
7437221Speter * all members have the same propfraction except those
7447221Speter * that were excluded with -E
7457221Speter */
7467221Speter continue;
7477221Speter }
7487221Speter cyclenlp -> time += childp -> time;
7494508Speter }
7507221Speter cyclenlp -> propself = cyclenlp -> propfraction * cyclenlp -> time;
7514508Speter }
7524508Speter }
7537172Speter
7547172Speter /*
7557172Speter * in one top to bottom pass over the topologically sorted namelist
7567221Speter * propagate:
7577221Speter * printflag as the union of parents' printflags
7587221Speter * propfraction as the sum of fractional parents' propfractions
7597221Speter * and while we're here, sum time for functions.
7607172Speter */
doflags()7617172Speter doflags()
7627172Speter {
7637172Speter int index;
7647172Speter nltype *childp;
7657172Speter nltype *oldhead;
7667172Speter
7677172Speter oldhead = 0;
7687172Speter for ( index = nname-1 ; index >= 0 ; index -= 1 ) {
7697172Speter childp = topsortnlp[ index ];
7707172Speter /*
7717172Speter * if we haven't done this function or cycle,
7727221Speter * inherit things from parent.
7737172Speter * this way, we are linear in the number of arcs
7747172Speter * since we do all members of a cycle (and the cycle itself)
7757172Speter * as we hit the first member of the cycle.
7767172Speter */
7777172Speter if ( childp -> cyclehead != oldhead ) {
7787172Speter oldhead = childp -> cyclehead;
7797221Speter inheritflags( childp );
7807172Speter }
7817221Speter # ifdef DEBUG
7827221Speter if ( debug & PROPDEBUG ) {
7837221Speter printf( "[doflags] " );
7847221Speter printname( childp );
7857221Speter printf( " inherits printflag %d and propfraction %f\n" ,
7867221Speter childp -> printflag , childp -> propfraction );
7877221Speter }
7887221Speter # endif DEBUG
7897172Speter if ( ! childp -> printflag ) {
7907172Speter /*
7917221Speter * printflag is off
7927221Speter * it gets turned on by
7937221Speter * being on -f list,
7947221Speter * or there not being any -f list and not being on -e list.
7957172Speter */
7967221Speter if ( onlist( flist , childp -> name )
7977221Speter || ( !fflag && !onlist( elist , childp -> name ) ) ) {
7987172Speter childp -> printflag = TRUE;
7997172Speter }
8007221Speter } else {
8017221Speter /*
8027221Speter * this function has printing parents:
8037221Speter * maybe someone wants to shut it up
8047221Speter * by putting it on -e list. (but favor -f over -e)
8057221Speter */
8067221Speter if ( ( !onlist( flist , childp -> name ) )
8077221Speter && onlist( elist , childp -> name ) ) {
8087221Speter childp -> printflag = FALSE;
8097172Speter }
8107221Speter }
8117221Speter if ( childp -> propfraction == 0.0 ) {
8127221Speter /*
8137221Speter * no parents to pass time to.
8147221Speter * collect time from children if
8157221Speter * its on -F list,
8167221Speter * or there isn't any -F list and its not on -E list.
8177221Speter */
8187221Speter if ( onlist( Flist , childp -> name )
8197221Speter || ( !Fflag && !onlist( Elist , childp -> name ) ) ) {
8207221Speter childp -> propfraction = 1.0;
8217172Speter }
8227221Speter } else {
8237221Speter /*
8247221Speter * it has parents to pass time to,
8257221Speter * but maybe someone wants to shut it up
8267221Speter * by puttting it on -E list. (but favor -F over -E)
8277221Speter */
8287221Speter if ( !onlist( Flist , childp -> name )
8297221Speter && onlist( Elist , childp -> name ) ) {
8307221Speter childp -> propfraction = 0.0;
8317221Speter }
8327172Speter }
8337221Speter childp -> propself = childp -> time * childp -> propfraction;
8347221Speter printtime += childp -> propself;
8357221Speter # ifdef DEBUG
8367221Speter if ( debug & PROPDEBUG ) {
8377221Speter printf( "[doflags] " );
8387221Speter printname( childp );
8397221Speter printf( " ends up with printflag %d and propfraction %f\n" ,
8407221Speter childp -> printflag , childp -> propfraction );
8418908Speter printf( "time %f propself %f printtime %f\n" ,
8428908Speter childp -> time , childp -> propself , printtime );
8437221Speter }
8447221Speter # endif DEBUG
8457172Speter }
8467172Speter }
8477172Speter
8487172Speter /*
8497172Speter * check if any parent of this child
8507172Speter * (or outside parents of this cycle)
8517172Speter * have their print flags on and set the
8527172Speter * print flag of the child (cycle) appropriately.
8537221Speter * similarly, deal with propagation fractions from parents.
8547172Speter */
inheritflags(childp)8557221Speter inheritflags( childp )
8567172Speter nltype *childp;
8577172Speter {
8587172Speter nltype *headp;
8597221Speter arctype *arcp;
8607221Speter nltype *parentp;
8617172Speter nltype *memp;
8627172Speter
8637172Speter headp = childp -> cyclehead;
8647172Speter if ( childp == headp ) {
8657172Speter /*
8667172Speter * just a regular child, check its parents
8677172Speter */
8687221Speter childp -> printflag = FALSE;
8697221Speter childp -> propfraction = 0.0;
8707221Speter for (arcp = childp -> parents ; arcp ; arcp = arcp -> arc_parentlist) {
8717221Speter parentp = arcp -> arc_parentp;
8728908Speter if ( childp == parentp ) {
8738908Speter continue;
8748908Speter }
8757221Speter childp -> printflag |= parentp -> printflag;
87614140Speter /*
87714140Speter * if the child was never actually called
87814140Speter * (e.g. this arc is static (and all others are, too))
87914140Speter * no time propagates along this arc.
88014140Speter */
88152652Smckusick if ( arcp -> arc_flags & DEADARC ) {
88252652Smckusick continue;
88352652Smckusick }
88452652Smckusick if ( childp -> npropcall ) {
88514140Speter childp -> propfraction += parentp -> propfraction
88652652Smckusick * ( ( (double) arcp -> arc_count )
88752652Smckusick / ( (double) childp -> npropcall ) );
88814140Speter }
8897172Speter }
8907221Speter } else {
8917221Speter /*
8927221Speter * its a member of a cycle, look at all parents from
8937221Speter * outside the cycle
8947221Speter */
8957221Speter headp -> printflag = FALSE;
8967221Speter headp -> propfraction = 0.0;
8977221Speter for ( memp = headp -> cnext ; memp ; memp = memp -> cnext ) {
8987221Speter for (arcp = memp->parents ; arcp ; arcp = arcp->arc_parentlist) {
8997221Speter if ( arcp -> arc_parentp -> cyclehead == headp ) {
9007221Speter continue;
9017221Speter }
9027221Speter parentp = arcp -> arc_parentp;
9037221Speter headp -> printflag |= parentp -> printflag;
90414140Speter /*
90514140Speter * if the cycle was never actually called
90614140Speter * (e.g. this arc is static (and all others are, too))
90714140Speter * no time propagates along this arc.
90814140Speter */
90952652Smckusick if ( arcp -> arc_flags & DEADARC ) {
91052652Smckusick continue;
91152652Smckusick }
91252652Smckusick if ( headp -> npropcall ) {
91314140Speter headp -> propfraction += parentp -> propfraction
91452652Smckusick * ( ( (double) arcp -> arc_count )
91552652Smckusick / ( (double) headp -> npropcall ) );
91614140Speter }
9177172Speter }
9187172Speter }
9197221Speter for ( memp = headp ; memp ; memp = memp -> cnext ) {
9207221Speter memp -> printflag = headp -> printflag;
9217221Speter memp -> propfraction = headp -> propfraction;
9227221Speter }
9237172Speter }
9247172Speter }
925