14508Speter #ifndef lint 2*7249Speter static char *sccsid = "@(#)arcs.c 1.10 (Berkeley) 06/20/82"; 34508Speter #endif lint 44508Speter 54561Speter #include "gprof.h" 64508Speter 74721Speter /* 84721Speter * add (or just increment) an arc 94721Speter */ 104721Speter addarc( parentp , childp , count ) 114721Speter nltype *parentp; 124721Speter nltype *childp; 134721Speter long count; 144721Speter { 154750Speter arctype *calloc(); 164721Speter arctype *arcp; 174721Speter 184721Speter # ifdef DEBUG 194721Speter if ( debug & TALLYDEBUG ) { 204721Speter printf( "[addarc] %d arcs from %s to %s\n" , 214721Speter count , parentp -> name , childp -> name ); 224721Speter } 234721Speter # endif DEBUG 244721Speter arcp = arclookup( parentp , childp ); 254721Speter if ( arcp != 0 ) { 264721Speter /* 274721Speter * a hit: just increment the count. 284721Speter */ 294721Speter # ifdef DEBUG 304721Speter if ( debug & TALLYDEBUG ) { 314721Speter printf( "[tally] hit %d += %d\n" , 324721Speter arcp -> arc_count , count ); 334721Speter } 344721Speter # endif DEBUG 354721Speter arcp -> arc_count += count; 364721Speter return; 374721Speter } 384750Speter arcp = calloc( 1 , sizeof *arcp ); 394721Speter arcp -> arc_parentp = parentp; 404721Speter arcp -> arc_childp = childp; 414721Speter arcp -> arc_count = count; 424721Speter /* 434721Speter * prepend this child to the children of this parent 444721Speter */ 454721Speter arcp -> arc_childlist = parentp -> children; 464721Speter parentp -> children = arcp; 474721Speter /* 484721Speter * prepend this parent to the parents of this child 494721Speter */ 504721Speter arcp -> arc_parentlist = childp -> parents; 514721Speter childp -> parents = arcp; 524721Speter } 534721Speter 547172Speter /* 557172Speter * the code below topologically sorts the graph (collapsing cycles), 567172Speter * and propagates time bottom up and flags top down. 577172Speter */ 587172Speter 597172Speter /* 607172Speter * the topologically sorted name list pointers 617172Speter */ 627172Speter nltype **topsortnlp; 637172Speter 644508Speter topcmp( npp1 , npp2 ) 654508Speter nltype **npp1; 664508Speter nltype **npp2; 674508Speter { 684508Speter return (*npp1) -> toporder - (*npp2) -> toporder; 694508Speter } 704508Speter 714508Speter doarcs() 724508Speter { 734508Speter nltype *parentp; 744508Speter arctype *arcp; 754508Speter long index; 764508Speter 774508Speter /* 784508Speter * initialize various things: 794508Speter * zero out child times. 804508Speter * count self-recursive calls. 814508Speter * indicate that nothing is on cycles. 824508Speter */ 834508Speter for ( parentp = nl ; parentp < npe ; parentp++ ) { 844508Speter parentp -> childtime = 0.0; 854508Speter arcp = arclookup( parentp , parentp ); 864508Speter if ( arcp != 0 ) { 874508Speter parentp -> ncall -= arcp -> arc_count; 884508Speter parentp -> selfcalls = arcp -> arc_count; 894508Speter } else { 904508Speter parentp -> selfcalls = 0; 914508Speter } 927221Speter parentp -> propfraction = 0.0; 937221Speter parentp -> propself = 0.0; 947221Speter parentp -> propchild = 0.0; 957172Speter parentp -> printflag = FALSE; 964508Speter parentp -> toporder = 0; 974508Speter parentp -> cycleno = 0; 984508Speter parentp -> cyclehead = parentp; 994508Speter parentp -> cnext = 0; 1007172Speter if ( cflag ) { 1017172Speter findcalls( parentp , parentp -> value , (parentp+1) -> value ); 1027172Speter } 1034508Speter } 1044508Speter /* 1054508Speter * topologically order things 1064508Speter * from each of the roots of the call graph 1074508Speter */ 1084508Speter for ( parentp = nl ; parentp < npe ; parentp++ ) { 1094508Speter if ( parentp -> parents == 0 ) { 1104508Speter dfn( parentp ); 1114508Speter } 1124508Speter } 1134508Speter /* 1144508Speter * link together nodes on the same cycle 1154508Speter */ 1164508Speter cyclelink(); 1174508Speter /* 1184508Speter * Sort the symbol table in reverse topological order 1194508Speter */ 1204508Speter topsortnlp = (nltype **) calloc( nname , sizeof(nltype *) ); 1214508Speter if ( topsortnlp == (nltype **) 0 ) { 1224508Speter fprintf( stderr , "[doarcs] ran out of memory for topo sorting\n" ); 1234508Speter } 1244508Speter for ( index = 0 ; index < nname ; index += 1 ) { 1254508Speter topsortnlp[ index ] = &nl[ index ]; 1264508Speter } 1274508Speter qsort( topsortnlp , nname , sizeof(nltype *) , topcmp ); 1284508Speter # ifdef DEBUG 1294508Speter if ( debug & DFNDEBUG ) { 1304508Speter printf( "[doarcs] topological sort listing\n" ); 1314508Speter for ( index = 0 ; index < nname ; index += 1 ) { 1324508Speter printf( "[doarcs] " ); 1334508Speter printf( "%d:" , topsortnlp[ index ] -> toporder ); 1344508Speter printname( topsortnlp[ index ] ); 1354508Speter printf( "\n" ); 1364508Speter } 1374508Speter } 1384508Speter # endif DEBUG 1394508Speter /* 1407221Speter * starting from the topological top, 1417221Speter * propagate print flags to children. 1427221Speter * also, calculate propagation fractions. 1437221Speter * this happens before time propagation 1447221Speter * since time propagation uses the fractions. 1457221Speter */ 1467221Speter doflags(); 1477221Speter /* 1484508Speter * starting from the topological bottom, 1497172Speter * propogate children times up to parents. 1504508Speter */ 1517172Speter dotime(); 1527172Speter printgprof(); 1537172Speter } 1547172Speter 1557172Speter dotime() 1567172Speter { 1577172Speter int index; 1587172Speter 1597172Speter cycletime(); 1604508Speter for ( index = 0 ; index < nname ; index += 1 ) { 1617172Speter timepropagate( topsortnlp[ index ] ); 1627127Speter } 1637127Speter } 1647127Speter 1657172Speter timepropagate( parentp ) 1667127Speter nltype *parentp; 1677127Speter { 1687127Speter arctype *arcp; 1697127Speter nltype *childp; 1707127Speter double share; 1717221Speter double propshare; 1727127Speter 1737221Speter if ( parentp -> propfraction == 0.0 ) { 1747221Speter return; 1757221Speter } 1767127Speter /* 1777127Speter * gather time from children of this parent. 1787127Speter */ 1797172Speter for ( arcp = parentp -> children ; arcp ; arcp = arcp -> arc_childlist ) { 1807127Speter childp = arcp -> arc_childp; 1817127Speter if ( arcp -> arc_count == 0 ) { 1827127Speter continue; 1837127Speter } 1847221Speter if ( childp == parentp ) { 1857127Speter continue; 1867127Speter } 1877221Speter if ( childp -> propfraction == 0.0 ) { 1887127Speter continue; 1897127Speter } 1907127Speter if ( childp -> cyclehead != childp ) { 1917127Speter if ( parentp -> cycleno == childp -> cycleno ) { 1927127Speter continue; 1937127Speter } 1947127Speter if ( parentp -> toporder <= childp -> toporder ) { 1957127Speter fprintf( stderr , "[propagate] toporder botches\n" ); 1964508Speter } 1977127Speter childp = childp -> cyclehead; 1987127Speter } else { 1997127Speter if ( parentp -> toporder <= childp -> toporder ) { 2007127Speter fprintf( stderr , "[propagate] toporder botches\n" ); 2014508Speter continue; 2024508Speter } 2037127Speter } 2047221Speter if ( childp -> ncall == 0 ) { 2057221Speter continue; 2067221Speter } 2077127Speter /* 2087127Speter * distribute time for this arc 2097127Speter */ 2107221Speter arcp -> arc_time = childp -> time 2117221Speter * ( ( (double) arcp -> arc_count ) / 2127221Speter ( (double) childp -> ncall ) ); 2137221Speter arcp -> arc_childtime = childp -> childtime 2147221Speter * ( ( (double) arcp -> arc_count ) / 2157221Speter ( (double) childp -> ncall ) ); 2167127Speter share = arcp -> arc_time + arcp -> arc_childtime; 2177127Speter parentp -> childtime += share; 2187127Speter /* 2197221Speter * ( 1 - propfraction ) gets lost along the way 2207127Speter */ 2217221Speter propshare = parentp -> propfraction * share; 2227221Speter /* 2237221Speter * fix things for printing 2247221Speter */ 2257221Speter parentp -> propchild += propshare; 2267221Speter arcp -> arc_time *= parentp -> propfraction; 2277221Speter arcp -> arc_childtime *= parentp -> propfraction; 2287221Speter /* 2297221Speter * add this share to the parent's cycle header, if any. 2307221Speter */ 2317127Speter if ( parentp -> cyclehead != parentp ) { 2327127Speter parentp -> cyclehead -> childtime += share; 2337221Speter parentp -> cyclehead -> propchild += propshare; 2344508Speter } 2357221Speter # ifdef DEBUG 2367221Speter if ( debug & PROPDEBUG ) { 2377221Speter printf( "[dotime] child \t" ); 2387221Speter printname( childp ); 2397221Speter printf( " with %f %f %d/%d\n" , 2407221Speter childp -> time , childp -> childtime , 2417221Speter arcp -> arc_count , childp -> ncall ); 2427221Speter printf( "[dotime] parent\t" ); 2437221Speter printname( parentp ); 2447221Speter printf( "\n[dotime] share %f\n" , share ); 2457221Speter } 2467221Speter # endif DEBUG 2474508Speter } 2484508Speter } 2494508Speter 2504508Speter cyclelink() 2514508Speter { 2524508Speter register nltype *nlp; 2534508Speter register nltype *cyclenlp; 2544508Speter int cycle; 2557172Speter nltype *memberp; 2567248Speter arctype *arcp; 2574508Speter 2584508Speter /* 2594508Speter * Count the number of cycles, and initialze the cycle lists 2604508Speter */ 2617127Speter ncycle = 0; 2624508Speter for ( nlp = nl ; nlp < npe ; nlp++ ) { 2634508Speter /* 2644508Speter * this is how you find unattached cycles 2654508Speter */ 2664508Speter if ( nlp -> cyclehead == nlp && nlp -> cnext != 0 ) { 2677127Speter ncycle += 1; 2684508Speter } 2694508Speter } 2707127Speter /* 2717127Speter * cyclenl is indexed by cycle number: 2727127Speter * i.e. it is origin 1, not origin 0. 2737127Speter */ 2747127Speter cyclenl = (nltype *) calloc( ncycle + 1 , sizeof( nltype ) ); 2757127Speter if ( cyclenl == 0 ) { 2767127Speter fprintf( stderr , "%s: No room for %d bytes of cycle headers\n" , 2777127Speter whoami , ( ncycle + 1 ) * sizeof( nltype ) ); 2787127Speter done(); 2794508Speter } 2804508Speter /* 2814508Speter * now link cycles to true cycleheads, 2824508Speter * number them, accumulate the data for the cycle 2834508Speter */ 2844508Speter cycle = 0; 2854508Speter for ( nlp = nl ; nlp < npe ; nlp++ ) { 2864508Speter if ( nlp -> cyclehead != nlp || nlp -> cnext == 0 ) { 2874508Speter continue; 2884508Speter } 2894508Speter cycle += 1; 2907127Speter cyclenlp = &cyclenl[cycle]; 291*7249Speter cyclenlp -> name = 0; /* the name */ 2927221Speter cyclenlp -> value = 0; /* the pc entry point */ 2937221Speter cyclenlp -> time = 0.0; /* ticks in this routine */ 2947221Speter cyclenlp -> childtime = 0.0; /* cumulative ticks in children */ 2957221Speter cyclenlp -> ncall = 0; /* how many times called */ 2967221Speter cyclenlp -> selfcalls = 0; /* how many calls to self */ 2977221Speter cyclenlp -> propfraction = 0.0; /* what % of time propagates */ 2987221Speter cyclenlp -> propself = 0.0; /* how much self time propagates */ 2997221Speter cyclenlp -> propchild = 0.0; /* how much child time propagates */ 3007221Speter cyclenlp -> printflag = TRUE; /* should this be printed? */ 3017221Speter cyclenlp -> index = 0; /* index in the graph list */ 3027221Speter cyclenlp -> toporder = 0; /* graph call chain top-sort order */ 3037221Speter cyclenlp -> cycleno = cycle; /* internal number of cycle on */ 3047221Speter cyclenlp -> cyclehead = cyclenlp; /* pointer to head of cycle */ 3057221Speter cyclenlp -> cnext = nlp; /* pointer to next member of cycle */ 3067221Speter cyclenlp -> parents = 0; /* list of caller arcs */ 3077221Speter cyclenlp -> children = 0; /* list of callee arcs */ 3084508Speter # ifdef DEBUG 3094508Speter if ( debug & CYCLEDEBUG ) { 3104508Speter printf( "[cyclelink] " ); 3114508Speter printname( nlp ); 3124508Speter printf( " is the head of cycle %d\n" , cycle ); 3134508Speter } 3144508Speter # endif DEBUG 3157248Speter /* 3167248Speter * link members to cycle header 3177248Speter */ 3187172Speter for ( memberp = nlp ; memberp ; memberp = memberp -> cnext ) { 3197172Speter memberp -> cycleno = cycle; 3207172Speter memberp -> cyclehead = cyclenlp; 3217172Speter } 3227248Speter /* 3237248Speter * count calls from outside the cycle 3247248Speter * and those among cycle members 3257248Speter */ 3267248Speter for ( memberp = nlp ; memberp ; memberp = memberp -> cnext ) { 3277248Speter for ( arcp=memberp->parents ; arcp ; arcp=arcp->arc_parentlist ) { 3287248Speter if ( arcp -> arc_parentp == memberp ) { 3297248Speter continue; 3307248Speter } 3317248Speter if ( arcp -> arc_parentp -> cycleno == cycle ) { 3327248Speter cyclenlp -> selfcalls += arcp -> arc_count; 3337248Speter } else { 3347248Speter cyclenlp -> ncall += arcp -> arc_count; 3357248Speter } 3367248Speter } 3377248Speter } 3387172Speter } 3397172Speter } 3407172Speter 3417172Speter cycletime() 3427172Speter { 3437172Speter int cycle; 3447172Speter nltype *cyclenlp; 3457172Speter nltype *childp; 3467172Speter arctype *arcp; 3477221Speter nltype *parentp; 3487172Speter 3497172Speter for ( cycle = 1 ; cycle <= ncycle ; cycle += 1 ) { 3507172Speter cyclenlp = &cyclenl[ cycle ]; 3517221Speter for ( childp = cyclenlp -> cnext ; childp ; childp = childp -> cnext ) { 3527221Speter if ( childp -> propfraction == 0.0 ) { 3537221Speter /* 3547221Speter * all members have the same propfraction except those 3557221Speter * that were excluded with -E 3567221Speter */ 3577221Speter continue; 3587221Speter } 3597221Speter cyclenlp -> time += childp -> time; 3604508Speter } 3617221Speter cyclenlp -> propself = cyclenlp -> propfraction * cyclenlp -> time; 3624508Speter } 3634508Speter } 3647172Speter 3657172Speter /* 3667172Speter * in one top to bottom pass over the topologically sorted namelist 3677221Speter * propagate: 3687221Speter * printflag as the union of parents' printflags 3697221Speter * propfraction as the sum of fractional parents' propfractions 3707221Speter * and while we're here, sum time for functions. 3717172Speter */ 3727172Speter doflags() 3737172Speter { 3747172Speter int index; 3757172Speter nltype *childp; 3767172Speter nltype *oldhead; 3777172Speter 3787172Speter oldhead = 0; 3797172Speter for ( index = nname-1 ; index >= 0 ; index -= 1 ) { 3807172Speter childp = topsortnlp[ index ]; 3817172Speter /* 3827172Speter * if we haven't done this function or cycle, 3837221Speter * inherit things from parent. 3847172Speter * this way, we are linear in the number of arcs 3857172Speter * since we do all members of a cycle (and the cycle itself) 3867172Speter * as we hit the first member of the cycle. 3877172Speter */ 3887172Speter if ( childp -> cyclehead != oldhead ) { 3897172Speter oldhead = childp -> cyclehead; 3907221Speter inheritflags( childp ); 3917172Speter } 3927221Speter # ifdef DEBUG 3937221Speter if ( debug & PROPDEBUG ) { 3947221Speter printf( "[doflags] " ); 3957221Speter printname( childp ); 3967221Speter printf( " inherits printflag %d and propfraction %f\n" , 3977221Speter childp -> printflag , childp -> propfraction ); 3987221Speter } 3997221Speter # endif DEBUG 4007172Speter if ( ! childp -> printflag ) { 4017172Speter /* 4027221Speter * printflag is off 4037221Speter * it gets turned on by 4047221Speter * being on -f list, 4057221Speter * or there not being any -f list and not being on -e list. 4067172Speter */ 4077221Speter if ( onlist( flist , childp -> name ) 4087221Speter || ( !fflag && !onlist( elist , childp -> name ) ) ) { 4097172Speter childp -> printflag = TRUE; 4107172Speter } 4117221Speter } else { 4127221Speter /* 4137221Speter * this function has printing parents: 4147221Speter * maybe someone wants to shut it up 4157221Speter * by putting it on -e list. (but favor -f over -e) 4167221Speter */ 4177221Speter if ( ( !onlist( flist , childp -> name ) ) 4187221Speter && onlist( elist , childp -> name ) ) { 4197221Speter childp -> printflag = FALSE; 4207172Speter } 4217221Speter } 4227221Speter if ( childp -> propfraction == 0.0 ) { 4237221Speter /* 4247221Speter * no parents to pass time to. 4257221Speter * collect time from children if 4267221Speter * its on -F list, 4277221Speter * or there isn't any -F list and its not on -E list. 4287221Speter */ 4297221Speter if ( onlist( Flist , childp -> name ) 4307221Speter || ( !Fflag && !onlist( Elist , childp -> name ) ) ) { 4317221Speter childp -> propfraction = 1.0; 4327172Speter } 4337221Speter } else { 4347221Speter /* 4357221Speter * it has parents to pass time to, 4367221Speter * but maybe someone wants to shut it up 4377221Speter * by puttting it on -E list. (but favor -F over -E) 4387221Speter */ 4397221Speter if ( !onlist( Flist , childp -> name ) 4407221Speter && onlist( Elist , childp -> name ) ) { 4417221Speter childp -> propfraction = 0.0; 4427221Speter } 4437172Speter } 4447221Speter childp -> propself = childp -> time * childp -> propfraction; 4457221Speter printtime += childp -> propself; 4467221Speter # ifdef DEBUG 4477221Speter if ( debug & PROPDEBUG ) { 4487221Speter printf( "[doflags] " ); 4497221Speter printname( childp ); 4507221Speter printf( " ends up with printflag %d and propfraction %f\n" , 4517221Speter childp -> printflag , childp -> propfraction ); 4527221Speter printf( "time %f propself %f\n" , 4537221Speter childp -> time , childp -> propself ); 4547221Speter } 4557221Speter # endif DEBUG 4567172Speter } 4577172Speter } 4587172Speter 4597172Speter /* 4607172Speter * check if any parent of this child 4617172Speter * (or outside parents of this cycle) 4627172Speter * have their print flags on and set the 4637172Speter * print flag of the child (cycle) appropriately. 4647221Speter * similarly, deal with propagation fractions from parents. 4657172Speter */ 4667221Speter inheritflags( childp ) 4677172Speter nltype *childp; 4687172Speter { 4697172Speter nltype *headp; 4707221Speter arctype *arcp; 4717221Speter nltype *parentp; 4727172Speter nltype *memp; 4737172Speter 4747172Speter headp = childp -> cyclehead; 4757172Speter if ( childp == headp ) { 4767172Speter /* 4777172Speter * just a regular child, check its parents 4787172Speter */ 4797221Speter childp -> printflag = FALSE; 4807221Speter childp -> propfraction = 0.0; 4817221Speter for (arcp = childp -> parents ; arcp ; arcp = arcp -> arc_parentlist) { 4827221Speter parentp = arcp -> arc_parentp; 4837221Speter childp -> printflag |= parentp -> printflag; 4847221Speter childp -> propfraction += parentp -> propfraction 4857221Speter * ( ( (double) arcp -> arc_count ) 4867248Speter / ( (double) childp -> ncall ) ); 4877172Speter } 4887221Speter } else { 4897221Speter /* 4907221Speter * its a member of a cycle, look at all parents from 4917221Speter * outside the cycle 4927221Speter */ 4937221Speter headp -> printflag = FALSE; 4947221Speter headp -> propfraction = 0.0; 4957221Speter for ( memp = headp -> cnext ; memp ; memp = memp -> cnext ) { 4967221Speter for (arcp = memp->parents ; arcp ; arcp = arcp->arc_parentlist) { 4977221Speter if ( arcp -> arc_parentp -> cyclehead == headp ) { 4987221Speter continue; 4997221Speter } 5007221Speter parentp = arcp -> arc_parentp; 5017221Speter headp -> printflag |= parentp -> printflag; 5027248Speter headp -> propfraction += parentp -> propfraction 5037248Speter * ( ( (double) arcp -> arc_count ) 5047248Speter / ( (double) headp -> ncall ) ); 5057172Speter } 5067172Speter } 5077221Speter for ( memp = headp ; memp ; memp = memp -> cnext ) { 5087221Speter memp -> printflag = headp -> printflag; 5097221Speter memp -> propfraction = headp -> propfraction; 5107221Speter } 5117172Speter } 5127172Speter } 513