121957Sdist /* 221957Sdist * Copyright (c) 1983 Regents of the University of California. 334199Sbostic * All rights reserved. 434199Sbostic * 542683Sbostic * %sccs.include.redist.c% 621957Sdist */ 721957Sdist 84508Speter #ifndef lint 9*54805Storek static char sccsid[] = "@(#)arcs.c 5.8 (Berkeley) 07/08/92"; 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 */ 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 } 51*54805Storek 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 774508Speter topcmp( npp1 , npp2 ) 784508Speter nltype **npp1; 794508Speter nltype **npp2; 804508Speter { 814508Speter return (*npp1) -> toporder - (*npp2) -> toporder; 824508Speter } 834508Speter 8416850Smckusick nltype ** 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 2277172Speter dotime() 2287172Speter { 2297172Speter int index; 2307172Speter 2317172Speter cycletime(); 2324508Speter for ( index = 0 ; index < nname ; index += 1 ) { 2337172Speter timepropagate( topsortnlp[ index ] ); 2347127Speter } 2357127Speter } 2367127Speter 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 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 */ 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 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 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 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 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 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 */ 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 */ 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