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*52652Smckusick static char sccsid[] = "@(#)arcs.c 5.7 (Berkeley) 02/24/92"; 1034199Sbostic #endif /* not lint */ 114508Speter 124561Speter #include "gprof.h" 134508Speter 14*52652Smckusick #ifdef DEBUG 15*52652Smckusick int visited; 16*52652Smckusick int viable; 17*52652Smckusick int newcycle; 18*52652Smckusick int oldcycle; 19*52652Smckusick #endif DEBUG 20*52652Smckusick 214721Speter /* 224721Speter * add (or just increment) an arc 234721Speter */ 244721Speter addarc( parentp , childp , count ) 254721Speter nltype *parentp; 264721Speter nltype *childp; 274721Speter long count; 284721Speter { 294750Speter arctype *calloc(); 304721Speter arctype *arcp; 314721Speter 324721Speter # ifdef DEBUG 334721Speter if ( debug & TALLYDEBUG ) { 344721Speter printf( "[addarc] %d arcs from %s to %s\n" , 354721Speter count , parentp -> name , childp -> name ); 364721Speter } 374721Speter # endif DEBUG 384721Speter arcp = arclookup( parentp , childp ); 394721Speter if ( arcp != 0 ) { 404721Speter /* 414721Speter * a hit: just increment the count. 424721Speter */ 434721Speter # ifdef DEBUG 444721Speter if ( debug & TALLYDEBUG ) { 454721Speter printf( "[tally] hit %d += %d\n" , 464721Speter arcp -> arc_count , count ); 474721Speter } 484721Speter # endif DEBUG 494721Speter arcp -> arc_count += count; 504721Speter return; 514721Speter } 524750Speter arcp = calloc( 1 , sizeof *arcp ); 534721Speter arcp -> arc_parentp = parentp; 544721Speter arcp -> arc_childp = childp; 554721Speter arcp -> arc_count = count; 564721Speter /* 574721Speter * prepend this child to the children of this parent 584721Speter */ 594721Speter arcp -> arc_childlist = parentp -> children; 604721Speter parentp -> children = arcp; 614721Speter /* 624721Speter * prepend this parent to the parents of this child 634721Speter */ 644721Speter arcp -> arc_parentlist = childp -> parents; 654721Speter childp -> parents = arcp; 664721Speter } 674721Speter 687172Speter /* 697172Speter * the code below topologically sorts the graph (collapsing cycles), 707172Speter * and propagates time bottom up and flags top down. 717172Speter */ 727172Speter 737172Speter /* 747172Speter * the topologically sorted name list pointers 757172Speter */ 767172Speter nltype **topsortnlp; 777172Speter 784508Speter topcmp( npp1 , npp2 ) 794508Speter nltype **npp1; 804508Speter nltype **npp2; 814508Speter { 824508Speter return (*npp1) -> toporder - (*npp2) -> toporder; 834508Speter } 844508Speter 8516850Smckusick nltype ** 864508Speter doarcs() 874508Speter { 8816850Smckusick nltype *parentp, **timesortnlp; 894508Speter arctype *arcp; 904508Speter long index; 91*52652Smckusick long pass; 924508Speter 934508Speter /* 944508Speter * initialize various things: 954508Speter * zero out child times. 964508Speter * count self-recursive calls. 974508Speter * indicate that nothing is on cycles. 984508Speter */ 994508Speter for ( parentp = nl ; parentp < npe ; parentp++ ) { 1004508Speter parentp -> childtime = 0.0; 1014508Speter arcp = arclookup( parentp , parentp ); 1024508Speter if ( arcp != 0 ) { 1034508Speter parentp -> ncall -= arcp -> arc_count; 1044508Speter parentp -> selfcalls = arcp -> arc_count; 1054508Speter } else { 1064508Speter parentp -> selfcalls = 0; 1074508Speter } 108*52652Smckusick parentp -> npropcall = parentp -> ncall; 1097221Speter parentp -> propfraction = 0.0; 1107221Speter parentp -> propself = 0.0; 1117221Speter parentp -> propchild = 0.0; 1127172Speter parentp -> printflag = FALSE; 11310284Speter parentp -> toporder = DFN_NAN; 1144508Speter parentp -> cycleno = 0; 1154508Speter parentp -> cyclehead = parentp; 1164508Speter parentp -> cnext = 0; 1177172Speter if ( cflag ) { 11825713Ssam findcall( parentp , parentp -> value , (parentp+1) -> value ); 1197172Speter } 1204508Speter } 121*52652Smckusick for ( pass = 1 ; ; pass++ ) { 122*52652Smckusick /* 123*52652Smckusick * topologically order things 124*52652Smckusick * if any node is unnumbered, 125*52652Smckusick * number it and any of its descendents. 126*52652Smckusick */ 127*52652Smckusick for ( dfn_init() , parentp = nl ; parentp < npe ; parentp++ ) { 128*52652Smckusick if ( parentp -> toporder == DFN_NAN ) { 129*52652Smckusick dfn( parentp ); 130*52652Smckusick } 1314508Speter } 132*52652Smckusick /* 133*52652Smckusick * link together nodes on the same cycle 134*52652Smckusick */ 135*52652Smckusick cyclelink(); 136*52652Smckusick /* 137*52652Smckusick * if no cycles to break up, proceed 138*52652Smckusick */ 139*52652Smckusick if ( ! Cflag ) 140*52652Smckusick break; 141*52652Smckusick /* 142*52652Smckusick * analyze cycles to determine breakup 143*52652Smckusick */ 144*52652Smckusick # ifdef DEBUG 145*52652Smckusick if ( debug & BREAKCYCLE ) { 146*52652Smckusick printf("[doarcs] pass %d, cycle(s) %d\n" , pass , ncycle ); 147*52652Smckusick } 148*52652Smckusick # endif DEBUG 149*52652Smckusick if ( pass == 1 ) { 150*52652Smckusick printf( "\n\n%s %s\n%s %d:\n" , 151*52652Smckusick "The following arcs were deleted" , 152*52652Smckusick "from the propagation calculation" , 153*52652Smckusick "to reduce the maximum cycle size to", cyclethreshold ); 154*52652Smckusick } 155*52652Smckusick if ( cycleanalyze() ) 156*52652Smckusick break; 157*52652Smckusick free ( cyclenl ); 158*52652Smckusick ncycle = 0; 159*52652Smckusick for ( parentp = nl ; parentp < npe ; parentp++ ) { 160*52652Smckusick parentp -> toporder = DFN_NAN; 161*52652Smckusick parentp -> cycleno = 0; 162*52652Smckusick parentp -> cyclehead = parentp; 163*52652Smckusick parentp -> cnext = 0; 164*52652Smckusick } 1654508Speter } 166*52652Smckusick if ( pass > 1 ) { 167*52652Smckusick printf( "\f\n" ); 168*52652Smckusick } else { 169*52652Smckusick printf( "\tNone\n\n" ); 170*52652Smckusick } 1714508Speter /* 1724508Speter * Sort the symbol table in reverse topological order 1734508Speter */ 1744508Speter topsortnlp = (nltype **) calloc( nname , sizeof(nltype *) ); 1754508Speter if ( topsortnlp == (nltype **) 0 ) { 1764508Speter fprintf( stderr , "[doarcs] ran out of memory for topo sorting\n" ); 1774508Speter } 1784508Speter for ( index = 0 ; index < nname ; index += 1 ) { 1794508Speter topsortnlp[ index ] = &nl[ index ]; 1804508Speter } 1814508Speter qsort( topsortnlp , nname , sizeof(nltype *) , topcmp ); 1824508Speter # ifdef DEBUG 1834508Speter if ( debug & DFNDEBUG ) { 1844508Speter printf( "[doarcs] topological sort listing\n" ); 1854508Speter for ( index = 0 ; index < nname ; index += 1 ) { 1864508Speter printf( "[doarcs] " ); 1874508Speter printf( "%d:" , topsortnlp[ index ] -> toporder ); 1884508Speter printname( topsortnlp[ index ] ); 1894508Speter printf( "\n" ); 1904508Speter } 1914508Speter } 1924508Speter # endif DEBUG 1934508Speter /* 1947221Speter * starting from the topological top, 1957221Speter * propagate print flags to children. 1967221Speter * also, calculate propagation fractions. 1977221Speter * this happens before time propagation 1987221Speter * since time propagation uses the fractions. 1997221Speter */ 2007221Speter doflags(); 2017221Speter /* 2024508Speter * starting from the topological bottom, 2037172Speter * propogate children times up to parents. 2044508Speter */ 2057172Speter dotime(); 20616850Smckusick /* 20716850Smckusick * Now, sort by propself + propchild. 20816850Smckusick * sorting both the regular function names 20916850Smckusick * and cycle headers. 21016850Smckusick */ 21116850Smckusick timesortnlp = (nltype **) calloc( nname + ncycle , sizeof(nltype *) ); 21216850Smckusick if ( timesortnlp == (nltype **) 0 ) { 21316850Smckusick fprintf( stderr , "%s: ran out of memory for sorting\n" , whoami ); 21416850Smckusick } 21516850Smckusick for ( index = 0 ; index < nname ; index++ ) { 21616850Smckusick timesortnlp[index] = &nl[index]; 21716850Smckusick } 21816850Smckusick for ( index = 1 ; index <= ncycle ; index++ ) { 21916850Smckusick timesortnlp[nname+index-1] = &cyclenl[index]; 22016850Smckusick } 22116850Smckusick qsort( timesortnlp , nname + ncycle , sizeof(nltype *) , totalcmp ); 22216850Smckusick for ( index = 0 ; index < nname + ncycle ; index++ ) { 22316850Smckusick timesortnlp[ index ] -> index = index + 1; 22416850Smckusick } 22516850Smckusick return( timesortnlp ); 2267172Speter } 2277172Speter 2287172Speter dotime() 2297172Speter { 2307172Speter int index; 2317172Speter 2327172Speter cycletime(); 2334508Speter for ( index = 0 ; index < nname ; index += 1 ) { 2347172Speter timepropagate( topsortnlp[ index ] ); 2357127Speter } 2367127Speter } 2377127Speter 2387172Speter timepropagate( parentp ) 2397127Speter nltype *parentp; 2407127Speter { 2417127Speter arctype *arcp; 2427127Speter nltype *childp; 2437127Speter double share; 2447221Speter double propshare; 2457127Speter 2467221Speter if ( parentp -> propfraction == 0.0 ) { 2477221Speter return; 2487221Speter } 2497127Speter /* 2507127Speter * gather time from children of this parent. 2517127Speter */ 2527172Speter for ( arcp = parentp -> children ; arcp ; arcp = arcp -> arc_childlist ) { 2537127Speter childp = arcp -> arc_childp; 254*52652Smckusick if ( arcp -> arc_flags & DEADARC ) { 255*52652Smckusick continue; 256*52652Smckusick } 2577127Speter if ( arcp -> arc_count == 0 ) { 2587127Speter continue; 2597127Speter } 2607221Speter if ( childp == parentp ) { 2617127Speter continue; 2627127Speter } 2637221Speter if ( childp -> propfraction == 0.0 ) { 2647127Speter continue; 2657127Speter } 2667127Speter if ( childp -> cyclehead != childp ) { 2677127Speter if ( parentp -> cycleno == childp -> cycleno ) { 2687127Speter continue; 2697127Speter } 2707127Speter if ( parentp -> toporder <= childp -> toporder ) { 2717127Speter fprintf( stderr , "[propagate] toporder botches\n" ); 2724508Speter } 2737127Speter childp = childp -> cyclehead; 2747127Speter } else { 2757127Speter if ( parentp -> toporder <= childp -> toporder ) { 2767127Speter fprintf( stderr , "[propagate] toporder botches\n" ); 2774508Speter continue; 2784508Speter } 2797127Speter } 280*52652Smckusick if ( childp -> npropcall == 0 ) { 2817221Speter continue; 2827221Speter } 2837127Speter /* 2847127Speter * distribute time for this arc 2857127Speter */ 2867221Speter arcp -> arc_time = childp -> time 2877221Speter * ( ( (double) arcp -> arc_count ) / 288*52652Smckusick ( (double) childp -> npropcall ) ); 2897221Speter arcp -> arc_childtime = childp -> childtime 2907221Speter * ( ( (double) arcp -> arc_count ) / 291*52652Smckusick ( (double) childp -> npropcall ) ); 2927127Speter share = arcp -> arc_time + arcp -> arc_childtime; 2937127Speter parentp -> childtime += share; 2947127Speter /* 2957221Speter * ( 1 - propfraction ) gets lost along the way 2967127Speter */ 2977221Speter propshare = parentp -> propfraction * share; 2987221Speter /* 2997221Speter * fix things for printing 3007221Speter */ 3017221Speter parentp -> propchild += propshare; 3027221Speter arcp -> arc_time *= parentp -> propfraction; 3037221Speter arcp -> arc_childtime *= parentp -> propfraction; 3047221Speter /* 3057221Speter * add this share to the parent's cycle header, if any. 3067221Speter */ 3077127Speter if ( parentp -> cyclehead != parentp ) { 3087127Speter parentp -> cyclehead -> childtime += share; 3097221Speter parentp -> cyclehead -> propchild += propshare; 3104508Speter } 3117221Speter # ifdef DEBUG 3127221Speter if ( debug & PROPDEBUG ) { 3137221Speter printf( "[dotime] child \t" ); 3147221Speter printname( childp ); 3157221Speter printf( " with %f %f %d/%d\n" , 3167221Speter childp -> time , childp -> childtime , 317*52652Smckusick arcp -> arc_count , childp -> npropcall ); 3187221Speter printf( "[dotime] parent\t" ); 3197221Speter printname( parentp ); 3207221Speter printf( "\n[dotime] share %f\n" , share ); 3217221Speter } 3227221Speter # endif DEBUG 3234508Speter } 3244508Speter } 3254508Speter 3264508Speter cyclelink() 3274508Speter { 3284508Speter register nltype *nlp; 3294508Speter register nltype *cyclenlp; 3304508Speter int cycle; 3317172Speter nltype *memberp; 3327248Speter arctype *arcp; 3334508Speter 3344508Speter /* 3354508Speter * Count the number of cycles, and initialze the cycle lists 3364508Speter */ 3377127Speter ncycle = 0; 3384508Speter for ( nlp = nl ; nlp < npe ; nlp++ ) { 3394508Speter /* 3404508Speter * this is how you find unattached cycles 3414508Speter */ 3424508Speter if ( nlp -> cyclehead == nlp && nlp -> cnext != 0 ) { 3437127Speter ncycle += 1; 3444508Speter } 3454508Speter } 3467127Speter /* 3477127Speter * cyclenl is indexed by cycle number: 3487127Speter * i.e. it is origin 1, not origin 0. 3497127Speter */ 3507127Speter cyclenl = (nltype *) calloc( ncycle + 1 , sizeof( nltype ) ); 3517127Speter if ( cyclenl == 0 ) { 3527127Speter fprintf( stderr , "%s: No room for %d bytes of cycle headers\n" , 3537127Speter whoami , ( ncycle + 1 ) * sizeof( nltype ) ); 3547127Speter done(); 3554508Speter } 3564508Speter /* 3574508Speter * now link cycles to true cycleheads, 3584508Speter * number them, accumulate the data for the cycle 3594508Speter */ 3604508Speter cycle = 0; 3614508Speter for ( nlp = nl ; nlp < npe ; nlp++ ) { 36210284Speter if ( !( nlp -> cyclehead == nlp && nlp -> cnext != 0 ) ) { 3634508Speter continue; 3644508Speter } 3654508Speter cycle += 1; 3667127Speter cyclenlp = &cyclenl[cycle]; 3677249Speter cyclenlp -> name = 0; /* the name */ 3687221Speter cyclenlp -> value = 0; /* the pc entry point */ 3697221Speter cyclenlp -> time = 0.0; /* ticks in this routine */ 3707221Speter cyclenlp -> childtime = 0.0; /* cumulative ticks in children */ 3717221Speter cyclenlp -> ncall = 0; /* how many times called */ 3727221Speter cyclenlp -> selfcalls = 0; /* how many calls to self */ 3737221Speter cyclenlp -> propfraction = 0.0; /* what % of time propagates */ 3747221Speter cyclenlp -> propself = 0.0; /* how much self time propagates */ 3757221Speter cyclenlp -> propchild = 0.0; /* how much child time propagates */ 3767221Speter cyclenlp -> printflag = TRUE; /* should this be printed? */ 3777221Speter cyclenlp -> index = 0; /* index in the graph list */ 37810284Speter cyclenlp -> toporder = DFN_NAN; /* graph call chain top-sort order */ 3797221Speter cyclenlp -> cycleno = cycle; /* internal number of cycle on */ 3807221Speter cyclenlp -> cyclehead = cyclenlp; /* pointer to head of cycle */ 3817221Speter cyclenlp -> cnext = nlp; /* pointer to next member of cycle */ 3827221Speter cyclenlp -> parents = 0; /* list of caller arcs */ 3837221Speter cyclenlp -> children = 0; /* list of callee arcs */ 3844508Speter # ifdef DEBUG 3854508Speter if ( debug & CYCLEDEBUG ) { 3864508Speter printf( "[cyclelink] " ); 3874508Speter printname( nlp ); 3884508Speter printf( " is the head of cycle %d\n" , cycle ); 3894508Speter } 3904508Speter # endif DEBUG 3917248Speter /* 3927248Speter * link members to cycle header 3937248Speter */ 3947172Speter for ( memberp = nlp ; memberp ; memberp = memberp -> cnext ) { 3957172Speter memberp -> cycleno = cycle; 3967172Speter memberp -> cyclehead = cyclenlp; 3977172Speter } 3987248Speter /* 3997248Speter * count calls from outside the cycle 4007248Speter * and those among cycle members 4017248Speter */ 4027248Speter for ( memberp = nlp ; memberp ; memberp = memberp -> cnext ) { 4037248Speter for ( arcp=memberp->parents ; arcp ; arcp=arcp->arc_parentlist ) { 4047248Speter if ( arcp -> arc_parentp == memberp ) { 4057248Speter continue; 4067248Speter } 4077248Speter if ( arcp -> arc_parentp -> cycleno == cycle ) { 4087248Speter cyclenlp -> selfcalls += arcp -> arc_count; 4097248Speter } else { 410*52652Smckusick cyclenlp -> npropcall += arcp -> arc_count; 4117248Speter } 4127248Speter } 4137248Speter } 4147172Speter } 4157172Speter } 4167172Speter 417*52652Smckusick /* 418*52652Smckusick * analyze cycles to determine breakup 419*52652Smckusick */ 420*52652Smckusick cycleanalyze() 421*52652Smckusick { 422*52652Smckusick arctype **cyclestack; 423*52652Smckusick arctype **stkp; 424*52652Smckusick arctype **arcpp; 425*52652Smckusick arctype **endlist; 426*52652Smckusick arctype *arcp; 427*52652Smckusick nltype *nlp; 428*52652Smckusick cltype *clp; 429*52652Smckusick bool ret; 430*52652Smckusick bool done; 431*52652Smckusick int size; 432*52652Smckusick int cycleno; 433*52652Smckusick 434*52652Smckusick /* 435*52652Smckusick * calculate the size of the cycle, and find nodes that 436*52652Smckusick * exit the cycle as they are desirable targets to cut 437*52652Smckusick * some of their parents 438*52652Smckusick */ 439*52652Smckusick for ( done = TRUE , cycleno = 1 ; cycleno <= ncycle ; cycleno++ ) { 440*52652Smckusick size = 0; 441*52652Smckusick for (nlp = cyclenl[ cycleno ] . cnext; nlp; nlp = nlp -> cnext) { 442*52652Smckusick size += 1; 443*52652Smckusick nlp -> parentcnt = 0; 444*52652Smckusick nlp -> flags &= ~HASCYCLEXIT; 445*52652Smckusick for ( arcp = nlp -> parents; arcp; arcp = arcp -> arc_parentlist ) { 446*52652Smckusick nlp -> parentcnt += 1; 447*52652Smckusick if ( arcp -> arc_parentp -> cycleno != cycleno ) 448*52652Smckusick nlp -> flags |= HASCYCLEXIT; 449*52652Smckusick } 450*52652Smckusick } 451*52652Smckusick if ( size <= cyclethreshold ) 452*52652Smckusick continue; 453*52652Smckusick done = FALSE; 454*52652Smckusick cyclestack = (arctype **) calloc( size + 1 , sizeof( arctype *) ); 455*52652Smckusick if ( cyclestack == 0 ) { 456*52652Smckusick fprintf( stderr , "%s: No room for %d bytes of cycle stack\n" , 457*52652Smckusick whoami , ( size + 1 ) * sizeof( arctype * ) ); 458*52652Smckusick return; 459*52652Smckusick } 460*52652Smckusick # ifdef DEBUG 461*52652Smckusick if ( debug & BREAKCYCLE ) { 462*52652Smckusick printf( "[cycleanalyze] starting cycle %d of %d, size %d\n" , 463*52652Smckusick cycleno , ncycle , size ); 464*52652Smckusick } 465*52652Smckusick # endif DEBUG 466*52652Smckusick for ( nlp = cyclenl[ cycleno ] . cnext ; nlp ; nlp = nlp -> cnext ) { 467*52652Smckusick stkp = &cyclestack[0]; 468*52652Smckusick nlp -> flags |= CYCLEHEAD; 469*52652Smckusick ret = descend ( nlp , cyclestack , stkp ); 470*52652Smckusick nlp -> flags &= ~CYCLEHEAD; 471*52652Smckusick if ( ret == FALSE ) 472*52652Smckusick break; 473*52652Smckusick } 474*52652Smckusick free( cyclestack ); 475*52652Smckusick if ( cyclecnt > 0 ) { 476*52652Smckusick compresslist(); 477*52652Smckusick for ( clp = cyclehead ; clp ; ) { 478*52652Smckusick endlist = &clp -> list[ clp -> size ]; 479*52652Smckusick for ( arcpp = clp -> list ; arcpp < endlist ; arcpp++ ) 480*52652Smckusick (*arcpp) -> arc_cyclecnt--; 481*52652Smckusick cyclecnt--; 482*52652Smckusick clp = clp -> next; 483*52652Smckusick free( clp ); 484*52652Smckusick } 485*52652Smckusick cyclehead = 0; 486*52652Smckusick } 487*52652Smckusick } 488*52652Smckusick # ifdef DEBUG 489*52652Smckusick if ( debug & BREAKCYCLE ) { 490*52652Smckusick printf("%s visited %d, viable %d, newcycle %d, oldcycle %d\n", 491*52652Smckusick "[doarcs]" , visited , viable , newcycle , oldcycle); 492*52652Smckusick } 493*52652Smckusick # endif DEBUG 494*52652Smckusick return( done ); 495*52652Smckusick } 496*52652Smckusick 497*52652Smckusick descend( node , stkstart , stkp ) 498*52652Smckusick nltype *node; 499*52652Smckusick arctype **stkstart; 500*52652Smckusick arctype **stkp; 501*52652Smckusick { 502*52652Smckusick arctype *arcp; 503*52652Smckusick bool ret; 504*52652Smckusick 505*52652Smckusick for ( arcp = node -> children ; arcp ; arcp = arcp -> arc_childlist ) { 506*52652Smckusick # ifdef DEBUG 507*52652Smckusick visited++; 508*52652Smckusick # endif DEBUG 509*52652Smckusick if ( arcp -> arc_childp -> cycleno != node -> cycleno 510*52652Smckusick || ( arcp -> arc_childp -> flags & VISITED ) 511*52652Smckusick || ( arcp -> arc_flags & DEADARC ) ) 512*52652Smckusick continue; 513*52652Smckusick # ifdef DEBUG 514*52652Smckusick viable++; 515*52652Smckusick # endif DEBUG 516*52652Smckusick *stkp = arcp; 517*52652Smckusick if ( arcp -> arc_childp -> flags & CYCLEHEAD ) { 518*52652Smckusick if ( addcycle( stkstart , stkp ) == FALSE ) 519*52652Smckusick return( FALSE ); 520*52652Smckusick continue; 521*52652Smckusick } 522*52652Smckusick arcp -> arc_childp -> flags |= VISITED; 523*52652Smckusick ret = descend( arcp -> arc_childp , stkstart , stkp + 1 ); 524*52652Smckusick arcp -> arc_childp -> flags &= ~VISITED; 525*52652Smckusick if ( ret == FALSE ) 526*52652Smckusick return( FALSE ); 527*52652Smckusick } 528*52652Smckusick } 529*52652Smckusick 530*52652Smckusick addcycle( stkstart , stkend ) 531*52652Smckusick arctype **stkstart; 532*52652Smckusick arctype **stkend; 533*52652Smckusick { 534*52652Smckusick arctype **arcpp; 535*52652Smckusick arctype **stkloc; 536*52652Smckusick arctype **stkp; 537*52652Smckusick arctype **endlist; 538*52652Smckusick arctype *minarc; 539*52652Smckusick arctype *arcp; 540*52652Smckusick cltype *clp; 541*52652Smckusick int size; 542*52652Smckusick 543*52652Smckusick size = stkend - stkstart + 1; 544*52652Smckusick if ( size <= 1 ) 545*52652Smckusick return( TRUE ); 546*52652Smckusick for ( arcpp = stkstart , minarc = *arcpp ; arcpp <= stkend ; arcpp++ ) { 547*52652Smckusick if ( *arcpp > minarc ) 548*52652Smckusick continue; 549*52652Smckusick minarc = *arcpp; 550*52652Smckusick stkloc = arcpp; 551*52652Smckusick } 552*52652Smckusick for ( clp = cyclehead ; clp ; clp = clp -> next ) { 553*52652Smckusick if ( clp -> size != size ) 554*52652Smckusick continue; 555*52652Smckusick stkp = stkloc; 556*52652Smckusick endlist = &clp -> list[ size ]; 557*52652Smckusick for ( arcpp = clp -> list ; arcpp < endlist ; arcpp++ ) { 558*52652Smckusick if ( *stkp++ != *arcpp ) 559*52652Smckusick break; 560*52652Smckusick if ( stkp > stkend ) 561*52652Smckusick stkp = stkstart; 562*52652Smckusick } 563*52652Smckusick if ( arcpp == endlist ) { 564*52652Smckusick # ifdef DEBUG 565*52652Smckusick oldcycle++; 566*52652Smckusick # endif DEBUG 567*52652Smckusick return( TRUE ); 568*52652Smckusick } 569*52652Smckusick } 570*52652Smckusick clp = (cltype *) 571*52652Smckusick calloc( 1 , sizeof ( cltype ) + ( size - 1 ) * sizeof( arctype * ) ); 572*52652Smckusick if ( clp == 0 ) { 573*52652Smckusick fprintf( stderr , "%s: No room for %d bytes of subcycle storage\n" , 574*52652Smckusick whoami , sizeof ( cltype ) + ( size - 1 ) * sizeof( arctype * ) ); 575*52652Smckusick return( FALSE ); 576*52652Smckusick } 577*52652Smckusick stkp = stkloc; 578*52652Smckusick endlist = &clp -> list[ size ]; 579*52652Smckusick for ( arcpp = clp -> list ; arcpp < endlist ; arcpp++ ) { 580*52652Smckusick arcp = *arcpp = *stkp++; 581*52652Smckusick if ( stkp > stkend ) 582*52652Smckusick stkp = stkstart; 583*52652Smckusick arcp -> arc_cyclecnt++; 584*52652Smckusick if ( ( arcp -> arc_flags & ONLIST ) == 0 ) { 585*52652Smckusick arcp -> arc_flags |= ONLIST; 586*52652Smckusick arcp -> arc_next = archead; 587*52652Smckusick archead = arcp; 588*52652Smckusick } 589*52652Smckusick } 590*52652Smckusick clp -> size = size; 591*52652Smckusick clp -> next = cyclehead; 592*52652Smckusick cyclehead = clp; 593*52652Smckusick # ifdef DEBUG 594*52652Smckusick newcycle++; 595*52652Smckusick if ( debug & SUBCYCLELIST ) { 596*52652Smckusick printsubcycle( clp ); 597*52652Smckusick } 598*52652Smckusick # endif DEBUG 599*52652Smckusick cyclecnt++; 600*52652Smckusick if ( cyclecnt >= CYCLEMAX ) 601*52652Smckusick return( FALSE ); 602*52652Smckusick return( TRUE ); 603*52652Smckusick } 604*52652Smckusick 605*52652Smckusick compresslist() 606*52652Smckusick { 607*52652Smckusick cltype *clp; 608*52652Smckusick cltype **prev; 609*52652Smckusick arctype **arcpp; 610*52652Smckusick arctype **endlist; 611*52652Smckusick arctype *arcp; 612*52652Smckusick arctype *maxarcp; 613*52652Smckusick arctype *maxexitarcp; 614*52652Smckusick arctype *maxwithparentarcp; 615*52652Smckusick arctype *maxnoparentarcp; 616*52652Smckusick int maxexitcnt; 617*52652Smckusick int maxwithparentcnt; 618*52652Smckusick int maxnoparentcnt; 619*52652Smckusick char *type; 620*52652Smckusick 621*52652Smckusick maxexitcnt = 0; 622*52652Smckusick maxwithparentcnt = 0; 623*52652Smckusick maxnoparentcnt = 0; 624*52652Smckusick for ( endlist = &archead , arcp = archead ; arcp ; ) { 625*52652Smckusick if ( arcp -> arc_cyclecnt == 0 ) { 626*52652Smckusick arcp -> arc_flags &= ~ONLIST; 627*52652Smckusick *endlist = arcp -> arc_next; 628*52652Smckusick arcp -> arc_next = 0; 629*52652Smckusick arcp = *endlist; 630*52652Smckusick continue; 631*52652Smckusick } 632*52652Smckusick if ( arcp -> arc_childp -> flags & HASCYCLEXIT ) { 633*52652Smckusick if ( arcp -> arc_cyclecnt > maxexitcnt || 634*52652Smckusick ( arcp -> arc_cyclecnt == maxexitcnt && 635*52652Smckusick arcp -> arc_cyclecnt < maxexitarcp -> arc_count ) ) { 636*52652Smckusick maxexitcnt = arcp -> arc_cyclecnt; 637*52652Smckusick maxexitarcp = arcp; 638*52652Smckusick } 639*52652Smckusick } else if ( arcp -> arc_childp -> parentcnt > 1 ) { 640*52652Smckusick if ( arcp -> arc_cyclecnt > maxwithparentcnt || 641*52652Smckusick ( arcp -> arc_cyclecnt == maxwithparentcnt && 642*52652Smckusick arcp -> arc_cyclecnt < maxwithparentarcp -> arc_count ) ) { 643*52652Smckusick maxwithparentcnt = arcp -> arc_cyclecnt; 644*52652Smckusick maxwithparentarcp = arcp; 645*52652Smckusick } 646*52652Smckusick } else { 647*52652Smckusick if ( arcp -> arc_cyclecnt > maxnoparentcnt || 648*52652Smckusick ( arcp -> arc_cyclecnt == maxnoparentcnt && 649*52652Smckusick arcp -> arc_cyclecnt < maxnoparentarcp -> arc_count ) ) { 650*52652Smckusick maxnoparentcnt = arcp -> arc_cyclecnt; 651*52652Smckusick maxnoparentarcp = arcp; 652*52652Smckusick } 653*52652Smckusick } 654*52652Smckusick endlist = &arcp -> arc_next; 655*52652Smckusick arcp = arcp -> arc_next; 656*52652Smckusick } 657*52652Smckusick if ( maxexitcnt > 0 ) { 658*52652Smckusick /* 659*52652Smckusick * first choice is edge leading to node with out-of-cycle parent 660*52652Smckusick */ 661*52652Smckusick maxarcp = maxexitarcp; 662*52652Smckusick # ifdef DEBUG 663*52652Smckusick type = "exit"; 664*52652Smckusick # endif DEBUG 665*52652Smckusick } else if ( maxwithparentcnt > 0 ) { 666*52652Smckusick /* 667*52652Smckusick * second choice is edge leading to node with at least one 668*52652Smckusick * other in-cycle parent 669*52652Smckusick */ 670*52652Smckusick maxarcp = maxwithparentarcp; 671*52652Smckusick # ifdef DEBUG 672*52652Smckusick type = "internal"; 673*52652Smckusick # endif DEBUG 674*52652Smckusick } else { 675*52652Smckusick /* 676*52652Smckusick * last choice is edge leading to node with only this arc as 677*52652Smckusick * a parent (as it will now be orphaned) 678*52652Smckusick */ 679*52652Smckusick maxarcp = maxnoparentarcp; 680*52652Smckusick # ifdef DEBUG 681*52652Smckusick type = "orphan"; 682*52652Smckusick # endif DEBUG 683*52652Smckusick } 684*52652Smckusick maxarcp -> arc_flags |= DEADARC; 685*52652Smckusick maxarcp -> arc_childp -> parentcnt -= 1; 686*52652Smckusick maxarcp -> arc_childp -> npropcall -= maxarcp -> arc_count; 687*52652Smckusick # ifdef DEBUG 688*52652Smckusick if ( debug & BREAKCYCLE ) { 689*52652Smckusick printf( "%s delete %s arc: %s (%d) -> %s from %d cycle(s)\n" , 690*52652Smckusick "[compresslist]" , type , maxarcp -> arc_parentp -> name , 691*52652Smckusick maxarcp -> arc_count , maxarcp -> arc_childp -> name , 692*52652Smckusick maxarcp -> arc_cyclecnt ); 693*52652Smckusick } 694*52652Smckusick # endif DEBUG 695*52652Smckusick printf( "\t%s to %s with %d calls\n" , maxarcp -> arc_parentp -> name , 696*52652Smckusick maxarcp -> arc_childp -> name , maxarcp -> arc_count ); 697*52652Smckusick prev = &cyclehead; 698*52652Smckusick for ( clp = cyclehead ; clp ; ) { 699*52652Smckusick endlist = &clp -> list[ clp -> size ]; 700*52652Smckusick for ( arcpp = clp -> list ; arcpp < endlist ; arcpp++ ) 701*52652Smckusick if ( (*arcpp) -> arc_flags & DEADARC ) 702*52652Smckusick break; 703*52652Smckusick if ( arcpp == endlist ) { 704*52652Smckusick prev = &clp -> next; 705*52652Smckusick clp = clp -> next; 706*52652Smckusick continue; 707*52652Smckusick } 708*52652Smckusick for ( arcpp = clp -> list ; arcpp < endlist ; arcpp++ ) 709*52652Smckusick (*arcpp) -> arc_cyclecnt--; 710*52652Smckusick cyclecnt--; 711*52652Smckusick *prev = clp -> next; 712*52652Smckusick clp = clp -> next; 713*52652Smckusick free( clp ); 714*52652Smckusick } 715*52652Smckusick } 716*52652Smckusick 717*52652Smckusick #ifdef DEBUG 718*52652Smckusick printsubcycle( clp ) 719*52652Smckusick cltype *clp; 720*52652Smckusick { 721*52652Smckusick arctype **arcpp; 722*52652Smckusick arctype **endlist; 723*52652Smckusick 724*52652Smckusick arcpp = clp -> list; 725*52652Smckusick printf( "%s <cycle %d>\n" , (*arcpp) -> arc_parentp -> name , 726*52652Smckusick (*arcpp) -> arc_parentp -> cycleno ) ; 727*52652Smckusick for ( endlist = &clp -> list[ clp -> size ]; arcpp < endlist ; arcpp++ ) 728*52652Smckusick printf( "\t(%d) -> %s\n" , (*arcpp) -> arc_count , 729*52652Smckusick (*arcpp) -> arc_childp -> name ) ; 730*52652Smckusick } 731*52652Smckusick #endif DEBUG 732*52652Smckusick 7337172Speter cycletime() 7347172Speter { 7357172Speter int cycle; 7367172Speter nltype *cyclenlp; 7377172Speter nltype *childp; 7387172Speter 7397172Speter for ( cycle = 1 ; cycle <= ncycle ; cycle += 1 ) { 7407172Speter cyclenlp = &cyclenl[ cycle ]; 7417221Speter for ( childp = cyclenlp -> cnext ; childp ; childp = childp -> cnext ) { 7427221Speter if ( childp -> propfraction == 0.0 ) { 7437221Speter /* 7447221Speter * all members have the same propfraction except those 7457221Speter * that were excluded with -E 7467221Speter */ 7477221Speter continue; 7487221Speter } 7497221Speter cyclenlp -> time += childp -> time; 7504508Speter } 7517221Speter cyclenlp -> propself = cyclenlp -> propfraction * cyclenlp -> time; 7524508Speter } 7534508Speter } 7547172Speter 7557172Speter /* 7567172Speter * in one top to bottom pass over the topologically sorted namelist 7577221Speter * propagate: 7587221Speter * printflag as the union of parents' printflags 7597221Speter * propfraction as the sum of fractional parents' propfractions 7607221Speter * and while we're here, sum time for functions. 7617172Speter */ 7627172Speter doflags() 7637172Speter { 7647172Speter int index; 7657172Speter nltype *childp; 7667172Speter nltype *oldhead; 7677172Speter 7687172Speter oldhead = 0; 7697172Speter for ( index = nname-1 ; index >= 0 ; index -= 1 ) { 7707172Speter childp = topsortnlp[ index ]; 7717172Speter /* 7727172Speter * if we haven't done this function or cycle, 7737221Speter * inherit things from parent. 7747172Speter * this way, we are linear in the number of arcs 7757172Speter * since we do all members of a cycle (and the cycle itself) 7767172Speter * as we hit the first member of the cycle. 7777172Speter */ 7787172Speter if ( childp -> cyclehead != oldhead ) { 7797172Speter oldhead = childp -> cyclehead; 7807221Speter inheritflags( childp ); 7817172Speter } 7827221Speter # ifdef DEBUG 7837221Speter if ( debug & PROPDEBUG ) { 7847221Speter printf( "[doflags] " ); 7857221Speter printname( childp ); 7867221Speter printf( " inherits printflag %d and propfraction %f\n" , 7877221Speter childp -> printflag , childp -> propfraction ); 7887221Speter } 7897221Speter # endif DEBUG 7907172Speter if ( ! childp -> printflag ) { 7917172Speter /* 7927221Speter * printflag is off 7937221Speter * it gets turned on by 7947221Speter * being on -f list, 7957221Speter * or there not being any -f list and not being on -e list. 7967172Speter */ 7977221Speter if ( onlist( flist , childp -> name ) 7987221Speter || ( !fflag && !onlist( elist , childp -> name ) ) ) { 7997172Speter childp -> printflag = TRUE; 8007172Speter } 8017221Speter } else { 8027221Speter /* 8037221Speter * this function has printing parents: 8047221Speter * maybe someone wants to shut it up 8057221Speter * by putting it on -e list. (but favor -f over -e) 8067221Speter */ 8077221Speter if ( ( !onlist( flist , childp -> name ) ) 8087221Speter && onlist( elist , childp -> name ) ) { 8097221Speter childp -> printflag = FALSE; 8107172Speter } 8117221Speter } 8127221Speter if ( childp -> propfraction == 0.0 ) { 8137221Speter /* 8147221Speter * no parents to pass time to. 8157221Speter * collect time from children if 8167221Speter * its on -F list, 8177221Speter * or there isn't any -F list and its not on -E list. 8187221Speter */ 8197221Speter if ( onlist( Flist , childp -> name ) 8207221Speter || ( !Fflag && !onlist( Elist , childp -> name ) ) ) { 8217221Speter childp -> propfraction = 1.0; 8227172Speter } 8237221Speter } else { 8247221Speter /* 8257221Speter * it has parents to pass time to, 8267221Speter * but maybe someone wants to shut it up 8277221Speter * by puttting it on -E list. (but favor -F over -E) 8287221Speter */ 8297221Speter if ( !onlist( Flist , childp -> name ) 8307221Speter && onlist( Elist , childp -> name ) ) { 8317221Speter childp -> propfraction = 0.0; 8327221Speter } 8337172Speter } 8347221Speter childp -> propself = childp -> time * childp -> propfraction; 8357221Speter printtime += childp -> propself; 8367221Speter # ifdef DEBUG 8377221Speter if ( debug & PROPDEBUG ) { 8387221Speter printf( "[doflags] " ); 8397221Speter printname( childp ); 8407221Speter printf( " ends up with printflag %d and propfraction %f\n" , 8417221Speter childp -> printflag , childp -> propfraction ); 8428908Speter printf( "time %f propself %f printtime %f\n" , 8438908Speter childp -> time , childp -> propself , printtime ); 8447221Speter } 8457221Speter # endif DEBUG 8467172Speter } 8477172Speter } 8487172Speter 8497172Speter /* 8507172Speter * check if any parent of this child 8517172Speter * (or outside parents of this cycle) 8527172Speter * have their print flags on and set the 8537172Speter * print flag of the child (cycle) appropriately. 8547221Speter * similarly, deal with propagation fractions from parents. 8557172Speter */ 8567221Speter inheritflags( childp ) 8577172Speter nltype *childp; 8587172Speter { 8597172Speter nltype *headp; 8607221Speter arctype *arcp; 8617221Speter nltype *parentp; 8627172Speter nltype *memp; 8637172Speter 8647172Speter headp = childp -> cyclehead; 8657172Speter if ( childp == headp ) { 8667172Speter /* 8677172Speter * just a regular child, check its parents 8687172Speter */ 8697221Speter childp -> printflag = FALSE; 8707221Speter childp -> propfraction = 0.0; 8717221Speter for (arcp = childp -> parents ; arcp ; arcp = arcp -> arc_parentlist) { 8727221Speter parentp = arcp -> arc_parentp; 8738908Speter if ( childp == parentp ) { 8748908Speter continue; 8758908Speter } 8767221Speter childp -> printflag |= parentp -> printflag; 87714140Speter /* 87814140Speter * if the child was never actually called 87914140Speter * (e.g. this arc is static (and all others are, too)) 88014140Speter * no time propagates along this arc. 88114140Speter */ 882*52652Smckusick if ( arcp -> arc_flags & DEADARC ) { 883*52652Smckusick continue; 884*52652Smckusick } 885*52652Smckusick if ( childp -> npropcall ) { 88614140Speter childp -> propfraction += parentp -> propfraction 887*52652Smckusick * ( ( (double) arcp -> arc_count ) 888*52652Smckusick / ( (double) childp -> npropcall ) ); 88914140Speter } 8907172Speter } 8917221Speter } else { 8927221Speter /* 8937221Speter * its a member of a cycle, look at all parents from 8947221Speter * outside the cycle 8957221Speter */ 8967221Speter headp -> printflag = FALSE; 8977221Speter headp -> propfraction = 0.0; 8987221Speter for ( memp = headp -> cnext ; memp ; memp = memp -> cnext ) { 8997221Speter for (arcp = memp->parents ; arcp ; arcp = arcp->arc_parentlist) { 9007221Speter if ( arcp -> arc_parentp -> cyclehead == headp ) { 9017221Speter continue; 9027221Speter } 9037221Speter parentp = arcp -> arc_parentp; 9047221Speter headp -> printflag |= parentp -> printflag; 90514140Speter /* 90614140Speter * if the cycle was never actually called 90714140Speter * (e.g. this arc is static (and all others are, too)) 90814140Speter * no time propagates along this arc. 90914140Speter */ 910*52652Smckusick if ( arcp -> arc_flags & DEADARC ) { 911*52652Smckusick continue; 912*52652Smckusick } 913*52652Smckusick if ( headp -> npropcall ) { 91414140Speter headp -> propfraction += parentp -> propfraction 915*52652Smckusick * ( ( (double) arcp -> arc_count ) 916*52652Smckusick / ( (double) headp -> npropcall ) ); 91714140Speter } 9187172Speter } 9197172Speter } 9207221Speter for ( memp = headp ; memp ; memp = memp -> cnext ) { 9217221Speter memp -> printflag = headp -> printflag; 9227221Speter memp -> propfraction = headp -> propfraction; 9237221Speter } 9247172Speter } 9257172Speter } 926