14508Speter #ifndef lint 2*8908Speter static char *sccsid = "@(#)arcs.c 1.12 (Berkeley) 10/26/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]; 2917249Speter 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 3477172Speter for ( cycle = 1 ; cycle <= ncycle ; cycle += 1 ) { 3487172Speter cyclenlp = &cyclenl[ cycle ]; 3497221Speter for ( childp = cyclenlp -> cnext ; childp ; childp = childp -> cnext ) { 3507221Speter if ( childp -> propfraction == 0.0 ) { 3517221Speter /* 3527221Speter * all members have the same propfraction except those 3537221Speter * that were excluded with -E 3547221Speter */ 3557221Speter continue; 3567221Speter } 3577221Speter cyclenlp -> time += childp -> time; 3584508Speter } 3597221Speter cyclenlp -> propself = cyclenlp -> propfraction * cyclenlp -> time; 3604508Speter } 3614508Speter } 3627172Speter 3637172Speter /* 3647172Speter * in one top to bottom pass over the topologically sorted namelist 3657221Speter * propagate: 3667221Speter * printflag as the union of parents' printflags 3677221Speter * propfraction as the sum of fractional parents' propfractions 3687221Speter * and while we're here, sum time for functions. 3697172Speter */ 3707172Speter doflags() 3717172Speter { 3727172Speter int index; 3737172Speter nltype *childp; 3747172Speter nltype *oldhead; 3757172Speter 3767172Speter oldhead = 0; 3777172Speter for ( index = nname-1 ; index >= 0 ; index -= 1 ) { 3787172Speter childp = topsortnlp[ index ]; 3797172Speter /* 3807172Speter * if we haven't done this function or cycle, 3817221Speter * inherit things from parent. 3827172Speter * this way, we are linear in the number of arcs 3837172Speter * since we do all members of a cycle (and the cycle itself) 3847172Speter * as we hit the first member of the cycle. 3857172Speter */ 3867172Speter if ( childp -> cyclehead != oldhead ) { 3877172Speter oldhead = childp -> cyclehead; 3887221Speter inheritflags( childp ); 3897172Speter } 3907221Speter # ifdef DEBUG 3917221Speter if ( debug & PROPDEBUG ) { 3927221Speter printf( "[doflags] " ); 3937221Speter printname( childp ); 3947221Speter printf( " inherits printflag %d and propfraction %f\n" , 3957221Speter childp -> printflag , childp -> propfraction ); 3967221Speter } 3977221Speter # endif DEBUG 3987172Speter if ( ! childp -> printflag ) { 3997172Speter /* 4007221Speter * printflag is off 4017221Speter * it gets turned on by 4027221Speter * being on -f list, 4037221Speter * or there not being any -f list and not being on -e list. 4047172Speter */ 4057221Speter if ( onlist( flist , childp -> name ) 4067221Speter || ( !fflag && !onlist( elist , childp -> name ) ) ) { 4077172Speter childp -> printflag = TRUE; 4087172Speter } 4097221Speter } else { 4107221Speter /* 4117221Speter * this function has printing parents: 4127221Speter * maybe someone wants to shut it up 4137221Speter * by putting it on -e list. (but favor -f over -e) 4147221Speter */ 4157221Speter if ( ( !onlist( flist , childp -> name ) ) 4167221Speter && onlist( elist , childp -> name ) ) { 4177221Speter childp -> printflag = FALSE; 4187172Speter } 4197221Speter } 4207221Speter if ( childp -> propfraction == 0.0 ) { 4217221Speter /* 4227221Speter * no parents to pass time to. 4237221Speter * collect time from children if 4247221Speter * its on -F list, 4257221Speter * or there isn't any -F list and its not on -E list. 4267221Speter */ 4277221Speter if ( onlist( Flist , childp -> name ) 4287221Speter || ( !Fflag && !onlist( Elist , childp -> name ) ) ) { 4297221Speter childp -> propfraction = 1.0; 4307172Speter } 4317221Speter } else { 4327221Speter /* 4337221Speter * it has parents to pass time to, 4347221Speter * but maybe someone wants to shut it up 4357221Speter * by puttting it on -E list. (but favor -F over -E) 4367221Speter */ 4377221Speter if ( !onlist( Flist , childp -> name ) 4387221Speter && onlist( Elist , childp -> name ) ) { 4397221Speter childp -> propfraction = 0.0; 4407221Speter } 4417172Speter } 4427221Speter childp -> propself = childp -> time * childp -> propfraction; 4437221Speter printtime += childp -> propself; 4447221Speter # ifdef DEBUG 4457221Speter if ( debug & PROPDEBUG ) { 4467221Speter printf( "[doflags] " ); 4477221Speter printname( childp ); 4487221Speter printf( " ends up with printflag %d and propfraction %f\n" , 4497221Speter childp -> printflag , childp -> propfraction ); 450*8908Speter printf( "time %f propself %f printtime %f\n" , 451*8908Speter childp -> time , childp -> propself , printtime ); 4527221Speter } 4537221Speter # endif DEBUG 4547172Speter } 4557172Speter } 4567172Speter 4577172Speter /* 4587172Speter * check if any parent of this child 4597172Speter * (or outside parents of this cycle) 4607172Speter * have their print flags on and set the 4617172Speter * print flag of the child (cycle) appropriately. 4627221Speter * similarly, deal with propagation fractions from parents. 4637172Speter */ 4647221Speter inheritflags( childp ) 4657172Speter nltype *childp; 4667172Speter { 4677172Speter nltype *headp; 4687221Speter arctype *arcp; 4697221Speter nltype *parentp; 4707172Speter nltype *memp; 4717172Speter 4727172Speter headp = childp -> cyclehead; 4737172Speter if ( childp == headp ) { 4747172Speter /* 4757172Speter * just a regular child, check its parents 4767172Speter */ 4777221Speter childp -> printflag = FALSE; 4787221Speter childp -> propfraction = 0.0; 4797221Speter for (arcp = childp -> parents ; arcp ; arcp = arcp -> arc_parentlist) { 4807221Speter parentp = arcp -> arc_parentp; 481*8908Speter if ( childp == parentp ) { 482*8908Speter continue; 483*8908Speter } 4847221Speter childp -> printflag |= parentp -> printflag; 4857221Speter childp -> propfraction += parentp -> propfraction 4867221Speter * ( ( (double) arcp -> arc_count ) 4877248Speter / ( (double) childp -> ncall ) ); 4887172Speter } 4897221Speter } else { 4907221Speter /* 4917221Speter * its a member of a cycle, look at all parents from 4927221Speter * outside the cycle 4937221Speter */ 4947221Speter headp -> printflag = FALSE; 4957221Speter headp -> propfraction = 0.0; 4967221Speter for ( memp = headp -> cnext ; memp ; memp = memp -> cnext ) { 4977221Speter for (arcp = memp->parents ; arcp ; arcp = arcp->arc_parentlist) { 4987221Speter if ( arcp -> arc_parentp -> cyclehead == headp ) { 4997221Speter continue; 5007221Speter } 5017221Speter parentp = arcp -> arc_parentp; 5027221Speter headp -> printflag |= parentp -> printflag; 5037248Speter headp -> propfraction += parentp -> propfraction 5047248Speter * ( ( (double) arcp -> arc_count ) 5057248Speter / ( (double) headp -> ncall ) ); 5067172Speter } 5077172Speter } 5087221Speter for ( memp = headp ; memp ; memp = memp -> cnext ) { 5097221Speter memp -> printflag = headp -> printflag; 5107221Speter memp -> propfraction = headp -> propfraction; 5117221Speter } 5127172Speter } 5137172Speter } 514