19b50d902SRodney W. Grimes /* 29b50d902SRodney W. Grimes * Copyright (c) 1983, 1993 39b50d902SRodney W. Grimes * The Regents of the University of California. All rights reserved. 49b50d902SRodney W. Grimes * 59b50d902SRodney W. Grimes * Redistribution and use in source and binary forms, with or without 69b50d902SRodney W. Grimes * modification, are permitted provided that the following conditions 79b50d902SRodney W. Grimes * are met: 89b50d902SRodney W. Grimes * 1. Redistributions of source code must retain the above copyright 99b50d902SRodney W. Grimes * notice, this list of conditions and the following disclaimer. 109b50d902SRodney W. Grimes * 2. Redistributions in binary form must reproduce the above copyright 119b50d902SRodney W. Grimes * notice, this list of conditions and the following disclaimer in the 129b50d902SRodney W. Grimes * documentation and/or other materials provided with the distribution. 139b50d902SRodney W. Grimes * 4. Neither the name of the University nor the names of its contributors 149b50d902SRodney W. Grimes * may be used to endorse or promote products derived from this software 159b50d902SRodney W. Grimes * without specific prior written permission. 169b50d902SRodney W. Grimes * 179b50d902SRodney W. Grimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 189b50d902SRodney W. Grimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 199b50d902SRodney W. Grimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 209b50d902SRodney W. Grimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 219b50d902SRodney W. Grimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 229b50d902SRodney W. Grimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 239b50d902SRodney W. Grimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 249b50d902SRodney W. Grimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 259b50d902SRodney W. Grimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 269b50d902SRodney W. Grimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 279b50d902SRodney W. Grimes * SUCH DAMAGE. 289b50d902SRodney W. Grimes */ 299b50d902SRodney W. Grimes 30b34f7debSPhilippe Charnier #if 0 3197fa9b77SPhilippe Charnier #ifndef lint 326451b2bfSPhilippe Charnier static char sccsid[] = "@(#)arcs.c 8.1 (Berkeley) 6/6/93"; 339b50d902SRodney W. Grimes #endif /* not lint */ 3497fa9b77SPhilippe Charnier #endif 3597fa9b77SPhilippe Charnier 36e026a48cSDavid E. O'Brien #include <sys/cdefs.h> 37e026a48cSDavid E. O'Brien __FBSDID("$FreeBSD$"); 389b50d902SRodney W. Grimes 39b34f7debSPhilippe Charnier #include <err.h> 409b50d902SRodney W. Grimes #include "gprof.h" 419b50d902SRodney W. Grimes 429b50d902SRodney W. Grimes #ifdef DEBUG 439b50d902SRodney W. Grimes int visited; 449b50d902SRodney W. Grimes int viable; 459b50d902SRodney W. Grimes int newcycle; 469b50d902SRodney W. Grimes int oldcycle; 470fb7a0beSGarrett Wollman #endif /* DEBUG */ 489b50d902SRodney W. Grimes 49*af2637dbSPhilippe Charnier int topcmp(const void *, const void *); 50*af2637dbSPhilippe Charnier 519b50d902SRodney W. Grimes /* 529b50d902SRodney W. Grimes * add (or just increment) an arc 539b50d902SRodney W. Grimes */ 5497fa9b77SPhilippe Charnier void 55*af2637dbSPhilippe Charnier addarc(nltype *parentp, nltype *childp, long count) 569b50d902SRodney W. Grimes { 579b50d902SRodney W. Grimes arctype *arcp; 589b50d902SRodney W. Grimes 599b50d902SRodney W. Grimes # ifdef DEBUG 609b50d902SRodney W. Grimes if ( debug & TALLYDEBUG ) { 618d57b8d3SBruce Evans printf( "[addarc] %ld arcs from %s to %s\n" , 629b50d902SRodney W. Grimes count , parentp -> name , childp -> name ); 639b50d902SRodney W. Grimes } 640fb7a0beSGarrett Wollman # endif /* DEBUG */ 659b50d902SRodney W. Grimes arcp = arclookup( parentp , childp ); 669b50d902SRodney W. Grimes if ( arcp != 0 ) { 679b50d902SRodney W. Grimes /* 689b50d902SRodney W. Grimes * a hit: just increment the count. 699b50d902SRodney W. Grimes */ 709b50d902SRodney W. Grimes # ifdef DEBUG 719b50d902SRodney W. Grimes if ( debug & TALLYDEBUG ) { 728d57b8d3SBruce Evans printf( "[tally] hit %ld += %ld\n" , 739b50d902SRodney W. Grimes arcp -> arc_count , count ); 749b50d902SRodney W. Grimes } 750fb7a0beSGarrett Wollman # endif /* DEBUG */ 769b50d902SRodney W. Grimes arcp -> arc_count += count; 779b50d902SRodney W. Grimes return; 789b50d902SRodney W. Grimes } 799b50d902SRodney W. Grimes arcp = (arctype *)calloc( 1 , sizeof *arcp ); 8097fa9b77SPhilippe Charnier if (arcp == NULL) 8197fa9b77SPhilippe Charnier errx( 1 , "malloc failed" ); 829b50d902SRodney W. Grimes arcp -> arc_parentp = parentp; 839b50d902SRodney W. Grimes arcp -> arc_childp = childp; 849b50d902SRodney W. Grimes arcp -> arc_count = count; 859b50d902SRodney W. Grimes /* 869b50d902SRodney W. Grimes * prepend this child to the children of this parent 879b50d902SRodney W. Grimes */ 889b50d902SRodney W. Grimes arcp -> arc_childlist = parentp -> children; 899b50d902SRodney W. Grimes parentp -> children = arcp; 909b50d902SRodney W. Grimes /* 919b50d902SRodney W. Grimes * prepend this parent to the parents of this child 929b50d902SRodney W. Grimes */ 939b50d902SRodney W. Grimes arcp -> arc_parentlist = childp -> parents; 949b50d902SRodney W. Grimes childp -> parents = arcp; 959b50d902SRodney W. Grimes } 969b50d902SRodney W. Grimes 979b50d902SRodney W. Grimes /* 989b50d902SRodney W. Grimes * the code below topologically sorts the graph (collapsing cycles), 999b50d902SRodney W. Grimes * and propagates time bottom up and flags top down. 1009b50d902SRodney W. Grimes */ 1019b50d902SRodney W. Grimes 1029b50d902SRodney W. Grimes /* 1039b50d902SRodney W. Grimes * the topologically sorted name list pointers 1049b50d902SRodney W. Grimes */ 1059b50d902SRodney W. Grimes nltype **topsortnlp; 1069b50d902SRodney W. Grimes 10797fa9b77SPhilippe Charnier int 108*af2637dbSPhilippe Charnier topcmp(const void *v1, const void *v2) 1099b50d902SRodney W. Grimes { 110*af2637dbSPhilippe Charnier const nltype **npp1 = (const nltype **)v1; 111*af2637dbSPhilippe Charnier const nltype **npp2 = (const nltype **)v2; 112*af2637dbSPhilippe Charnier 1139b50d902SRodney W. Grimes return (*npp1) -> toporder - (*npp2) -> toporder; 1149b50d902SRodney W. Grimes } 1159b50d902SRodney W. Grimes 1169b50d902SRodney W. Grimes nltype ** 117*af2637dbSPhilippe Charnier doarcs(void) 1189b50d902SRodney W. Grimes { 1199b50d902SRodney W. Grimes nltype *parentp, **timesortnlp; 1209b50d902SRodney W. Grimes arctype *arcp; 1219b50d902SRodney W. Grimes long index; 1229b50d902SRodney W. Grimes long pass; 1239b50d902SRodney W. Grimes 1249b50d902SRodney W. Grimes /* 1259b50d902SRodney W. Grimes * initialize various things: 1269b50d902SRodney W. Grimes * zero out child times. 1279b50d902SRodney W. Grimes * count self-recursive calls. 1289b50d902SRodney W. Grimes * indicate that nothing is on cycles. 1299b50d902SRodney W. Grimes */ 1309b50d902SRodney W. Grimes for ( parentp = nl ; parentp < npe ; parentp++ ) { 1319b50d902SRodney W. Grimes parentp -> childtime = 0.0; 1329b50d902SRodney W. Grimes arcp = arclookup( parentp , parentp ); 1339b50d902SRodney W. Grimes if ( arcp != 0 ) { 1349b50d902SRodney W. Grimes parentp -> ncall -= arcp -> arc_count; 1359b50d902SRodney W. Grimes parentp -> selfcalls = arcp -> arc_count; 1369b50d902SRodney W. Grimes } else { 1379b50d902SRodney W. Grimes parentp -> selfcalls = 0; 1389b50d902SRodney W. Grimes } 1399b50d902SRodney W. Grimes parentp -> npropcall = parentp -> ncall; 1409b50d902SRodney W. Grimes parentp -> propfraction = 0.0; 1419b50d902SRodney W. Grimes parentp -> propself = 0.0; 1429b50d902SRodney W. Grimes parentp -> propchild = 0.0; 1439b50d902SRodney W. Grimes parentp -> printflag = FALSE; 1449b50d902SRodney W. Grimes parentp -> toporder = DFN_NAN; 1459b50d902SRodney W. Grimes parentp -> cycleno = 0; 1469b50d902SRodney W. Grimes parentp -> cyclehead = parentp; 1479b50d902SRodney W. Grimes parentp -> cnext = 0; 1489b50d902SRodney W. Grimes } 1499b50d902SRodney W. Grimes for ( pass = 1 ; ; pass++ ) { 1509b50d902SRodney W. Grimes /* 1519b50d902SRodney W. Grimes * topologically order things 1529b50d902SRodney W. Grimes * if any node is unnumbered, 1539b50d902SRodney W. Grimes * number it and any of its descendents. 1549b50d902SRodney W. Grimes */ 1559b50d902SRodney W. Grimes for ( dfn_init() , parentp = nl ; parentp < npe ; parentp++ ) { 1569b50d902SRodney W. Grimes if ( parentp -> toporder == DFN_NAN ) { 1579b50d902SRodney W. Grimes dfn( parentp ); 1589b50d902SRodney W. Grimes } 1599b50d902SRodney W. Grimes } 1609b50d902SRodney W. Grimes /* 1619b50d902SRodney W. Grimes * link together nodes on the same cycle 1629b50d902SRodney W. Grimes */ 1639b50d902SRodney W. Grimes cyclelink(); 1649b50d902SRodney W. Grimes /* 1659b50d902SRodney W. Grimes * if no cycles to break up, proceed 1669b50d902SRodney W. Grimes */ 1679b50d902SRodney W. Grimes if ( ! Cflag ) 1689b50d902SRodney W. Grimes break; 1699b50d902SRodney W. Grimes /* 1709b50d902SRodney W. Grimes * analyze cycles to determine breakup 1719b50d902SRodney W. Grimes */ 1729b50d902SRodney W. Grimes # ifdef DEBUG 1739b50d902SRodney W. Grimes if ( debug & BREAKCYCLE ) { 1748d57b8d3SBruce Evans printf("[doarcs] pass %ld, cycle(s) %d\n" , pass , ncycle ); 1759b50d902SRodney W. Grimes } 1760fb7a0beSGarrett Wollman # endif /* DEBUG */ 1779b50d902SRodney W. Grimes if ( pass == 1 ) { 1789b50d902SRodney W. Grimes printf( "\n\n%s %s\n%s %d:\n" , 1799b50d902SRodney W. Grimes "The following arcs were deleted" , 1809b50d902SRodney W. Grimes "from the propagation calculation" , 1819b50d902SRodney W. Grimes "to reduce the maximum cycle size to", cyclethreshold ); 1829b50d902SRodney W. Grimes } 1839b50d902SRodney W. Grimes if ( cycleanalyze() ) 1849b50d902SRodney W. Grimes break; 1859b50d902SRodney W. Grimes free ( cyclenl ); 1869b50d902SRodney W. Grimes ncycle = 0; 1879b50d902SRodney W. Grimes for ( parentp = nl ; parentp < npe ; parentp++ ) { 1889b50d902SRodney W. Grimes parentp -> toporder = DFN_NAN; 1899b50d902SRodney W. Grimes parentp -> cycleno = 0; 1909b50d902SRodney W. Grimes parentp -> cyclehead = parentp; 1919b50d902SRodney W. Grimes parentp -> cnext = 0; 1929b50d902SRodney W. Grimes } 1939b50d902SRodney W. Grimes } 1949b50d902SRodney W. Grimes if ( pass > 1 ) { 1959b50d902SRodney W. Grimes printf( "\f\n" ); 1969b50d902SRodney W. Grimes } else { 1979b50d902SRodney W. Grimes printf( "\tNone\n\n" ); 1989b50d902SRodney W. Grimes } 1999b50d902SRodney W. Grimes /* 2009b50d902SRodney W. Grimes * Sort the symbol table in reverse topological order 2019b50d902SRodney W. Grimes */ 2029b50d902SRodney W. Grimes topsortnlp = (nltype **) calloc( nname , sizeof(nltype *) ); 20397fa9b77SPhilippe Charnier if ( topsortnlp == (nltype **) 0 ) 20497fa9b77SPhilippe Charnier errx( 1 , "[doarcs] ran out of memory for topo sorting" ); 2059b50d902SRodney W. Grimes for ( index = 0 ; index < nname ; index += 1 ) { 2069b50d902SRodney W. Grimes topsortnlp[ index ] = &nl[ index ]; 2079b50d902SRodney W. Grimes } 2089b50d902SRodney W. Grimes qsort( topsortnlp , nname , sizeof(nltype *) , topcmp ); 2099b50d902SRodney W. Grimes # ifdef DEBUG 2109b50d902SRodney W. Grimes if ( debug & DFNDEBUG ) { 2119b50d902SRodney W. Grimes printf( "[doarcs] topological sort listing\n" ); 2129b50d902SRodney W. Grimes for ( index = 0 ; index < nname ; index += 1 ) { 2139b50d902SRodney W. Grimes printf( "[doarcs] " ); 2149b50d902SRodney W. Grimes printf( "%d:" , topsortnlp[ index ] -> toporder ); 2159b50d902SRodney W. Grimes printname( topsortnlp[ index ] ); 2169b50d902SRodney W. Grimes printf( "\n" ); 2179b50d902SRodney W. Grimes } 2189b50d902SRodney W. Grimes } 2190fb7a0beSGarrett Wollman # endif /* DEBUG */ 2209b50d902SRodney W. Grimes /* 2219b50d902SRodney W. Grimes * starting from the topological top, 2229b50d902SRodney W. Grimes * propagate print flags to children. 2239b50d902SRodney W. Grimes * also, calculate propagation fractions. 2249b50d902SRodney W. Grimes * this happens before time propagation 2259b50d902SRodney W. Grimes * since time propagation uses the fractions. 2269b50d902SRodney W. Grimes */ 2279b50d902SRodney W. Grimes doflags(); 2289b50d902SRodney W. Grimes /* 2299b50d902SRodney W. Grimes * starting from the topological bottom, 23097fa9b77SPhilippe Charnier * propagate children times up to parents. 2319b50d902SRodney W. Grimes */ 2329b50d902SRodney W. Grimes dotime(); 2339b50d902SRodney W. Grimes /* 2349b50d902SRodney W. Grimes * Now, sort by propself + propchild. 2359b50d902SRodney W. Grimes * sorting both the regular function names 2369b50d902SRodney W. Grimes * and cycle headers. 2379b50d902SRodney W. Grimes */ 2389b50d902SRodney W. Grimes timesortnlp = (nltype **) calloc( nname + ncycle , sizeof(nltype *) ); 23997fa9b77SPhilippe Charnier if ( timesortnlp == (nltype **) 0 ) 24097fa9b77SPhilippe Charnier errx( 1 , "ran out of memory for sorting" ); 2419b50d902SRodney W. Grimes for ( index = 0 ; index < nname ; index++ ) { 2429b50d902SRodney W. Grimes timesortnlp[index] = &nl[index]; 2439b50d902SRodney W. Grimes } 2449b50d902SRodney W. Grimes for ( index = 1 ; index <= ncycle ; index++ ) { 2459b50d902SRodney W. Grimes timesortnlp[nname+index-1] = &cyclenl[index]; 2469b50d902SRodney W. Grimes } 2479b50d902SRodney W. Grimes qsort( timesortnlp , nname + ncycle , sizeof(nltype *) , totalcmp ); 2489b50d902SRodney W. Grimes for ( index = 0 ; index < nname + ncycle ; index++ ) { 2499b50d902SRodney W. Grimes timesortnlp[ index ] -> index = index + 1; 2509b50d902SRodney W. Grimes } 2519b50d902SRodney W. Grimes return( timesortnlp ); 2529b50d902SRodney W. Grimes } 2539b50d902SRodney W. Grimes 25497fa9b77SPhilippe Charnier void 255*af2637dbSPhilippe Charnier dotime(void) 2569b50d902SRodney W. Grimes { 2579b50d902SRodney W. Grimes int index; 2589b50d902SRodney W. Grimes 2599b50d902SRodney W. Grimes cycletime(); 2609b50d902SRodney W. Grimes for ( index = 0 ; index < nname ; index += 1 ) { 2619b50d902SRodney W. Grimes timepropagate( topsortnlp[ index ] ); 2629b50d902SRodney W. Grimes } 2639b50d902SRodney W. Grimes } 2649b50d902SRodney W. Grimes 26597fa9b77SPhilippe Charnier void 266*af2637dbSPhilippe Charnier timepropagate(nltype *parentp) 2679b50d902SRodney W. Grimes { 2689b50d902SRodney W. Grimes arctype *arcp; 2699b50d902SRodney W. Grimes nltype *childp; 2709b50d902SRodney W. Grimes double share; 2719b50d902SRodney W. Grimes double propshare; 2729b50d902SRodney W. Grimes 2739b50d902SRodney W. Grimes if ( parentp -> propfraction == 0.0 ) { 2749b50d902SRodney W. Grimes return; 2759b50d902SRodney W. Grimes } 2769b50d902SRodney W. Grimes /* 2779b50d902SRodney W. Grimes * gather time from children of this parent. 2789b50d902SRodney W. Grimes */ 2799b50d902SRodney W. Grimes for ( arcp = parentp -> children ; arcp ; arcp = arcp -> arc_childlist ) { 2809b50d902SRodney W. Grimes childp = arcp -> arc_childp; 2819b50d902SRodney W. Grimes if ( arcp -> arc_flags & DEADARC ) { 2829b50d902SRodney W. Grimes continue; 2839b50d902SRodney W. Grimes } 2849b50d902SRodney W. Grimes if ( arcp -> arc_count == 0 ) { 2859b50d902SRodney W. Grimes continue; 2869b50d902SRodney W. Grimes } 2879b50d902SRodney W. Grimes if ( childp == parentp ) { 2889b50d902SRodney W. Grimes continue; 2899b50d902SRodney W. Grimes } 2909b50d902SRodney W. Grimes if ( childp -> propfraction == 0.0 ) { 2919b50d902SRodney W. Grimes continue; 2929b50d902SRodney W. Grimes } 2939b50d902SRodney W. Grimes if ( childp -> cyclehead != childp ) { 2949b50d902SRodney W. Grimes if ( parentp -> cycleno == childp -> cycleno ) { 2959b50d902SRodney W. Grimes continue; 2969b50d902SRodney W. Grimes } 2979b50d902SRodney W. Grimes if ( parentp -> toporder <= childp -> toporder ) { 2989b50d902SRodney W. Grimes fprintf( stderr , "[propagate] toporder botches\n" ); 2999b50d902SRodney W. Grimes } 3009b50d902SRodney W. Grimes childp = childp -> cyclehead; 3019b50d902SRodney W. Grimes } else { 3029b50d902SRodney W. Grimes if ( parentp -> toporder <= childp -> toporder ) { 3039b50d902SRodney W. Grimes fprintf( stderr , "[propagate] toporder botches\n" ); 3049b50d902SRodney W. Grimes continue; 3059b50d902SRodney W. Grimes } 3069b50d902SRodney W. Grimes } 3079b50d902SRodney W. Grimes if ( childp -> npropcall == 0 ) { 3089b50d902SRodney W. Grimes continue; 3099b50d902SRodney W. Grimes } 3109b50d902SRodney W. Grimes /* 3119b50d902SRodney W. Grimes * distribute time for this arc 3129b50d902SRodney W. Grimes */ 3139b50d902SRodney W. Grimes arcp -> arc_time = childp -> time 3149b50d902SRodney W. Grimes * ( ( (double) arcp -> arc_count ) / 3159b50d902SRodney W. Grimes ( (double) childp -> npropcall ) ); 3169b50d902SRodney W. Grimes arcp -> arc_childtime = childp -> childtime 3179b50d902SRodney W. Grimes * ( ( (double) arcp -> arc_count ) / 3189b50d902SRodney W. Grimes ( (double) childp -> npropcall ) ); 3199b50d902SRodney W. Grimes share = arcp -> arc_time + arcp -> arc_childtime; 3209b50d902SRodney W. Grimes parentp -> childtime += share; 3219b50d902SRodney W. Grimes /* 3229b50d902SRodney W. Grimes * ( 1 - propfraction ) gets lost along the way 3239b50d902SRodney W. Grimes */ 3249b50d902SRodney W. Grimes propshare = parentp -> propfraction * share; 3259b50d902SRodney W. Grimes /* 3269b50d902SRodney W. Grimes * fix things for printing 3279b50d902SRodney W. Grimes */ 3289b50d902SRodney W. Grimes parentp -> propchild += propshare; 3299b50d902SRodney W. Grimes arcp -> arc_time *= parentp -> propfraction; 3309b50d902SRodney W. Grimes arcp -> arc_childtime *= parentp -> propfraction; 3319b50d902SRodney W. Grimes /* 3329b50d902SRodney W. Grimes * add this share to the parent's cycle header, if any. 3339b50d902SRodney W. Grimes */ 3349b50d902SRodney W. Grimes if ( parentp -> cyclehead != parentp ) { 3359b50d902SRodney W. Grimes parentp -> cyclehead -> childtime += share; 3369b50d902SRodney W. Grimes parentp -> cyclehead -> propchild += propshare; 3379b50d902SRodney W. Grimes } 3389b50d902SRodney W. Grimes # ifdef DEBUG 3399b50d902SRodney W. Grimes if ( debug & PROPDEBUG ) { 3409b50d902SRodney W. Grimes printf( "[dotime] child \t" ); 3419b50d902SRodney W. Grimes printname( childp ); 3428d57b8d3SBruce Evans printf( " with %f %f %ld/%ld\n" , 3439b50d902SRodney W. Grimes childp -> time , childp -> childtime , 3449b50d902SRodney W. Grimes arcp -> arc_count , childp -> npropcall ); 3459b50d902SRodney W. Grimes printf( "[dotime] parent\t" ); 3469b50d902SRodney W. Grimes printname( parentp ); 3479b50d902SRodney W. Grimes printf( "\n[dotime] share %f\n" , share ); 3489b50d902SRodney W. Grimes } 3490fb7a0beSGarrett Wollman # endif /* DEBUG */ 3509b50d902SRodney W. Grimes } 3519b50d902SRodney W. Grimes } 3529b50d902SRodney W. Grimes 35397fa9b77SPhilippe Charnier void 354*af2637dbSPhilippe Charnier cyclelink(void) 3559b50d902SRodney W. Grimes { 3569b50d902SRodney W. Grimes register nltype *nlp; 3579b50d902SRodney W. Grimes register nltype *cyclenlp; 3589b50d902SRodney W. Grimes int cycle; 3599b50d902SRodney W. Grimes nltype *memberp; 3609b50d902SRodney W. Grimes arctype *arcp; 3619b50d902SRodney W. Grimes 3629b50d902SRodney W. Grimes /* 36397fa9b77SPhilippe Charnier * Count the number of cycles, and initialize the cycle lists 3649b50d902SRodney W. Grimes */ 3659b50d902SRodney W. Grimes ncycle = 0; 3669b50d902SRodney W. Grimes for ( nlp = nl ; nlp < npe ; nlp++ ) { 3679b50d902SRodney W. Grimes /* 3689b50d902SRodney W. Grimes * this is how you find unattached cycles 3699b50d902SRodney W. Grimes */ 3709b50d902SRodney W. Grimes if ( nlp -> cyclehead == nlp && nlp -> cnext != 0 ) { 3719b50d902SRodney W. Grimes ncycle += 1; 3729b50d902SRodney W. Grimes } 3739b50d902SRodney W. Grimes } 3749b50d902SRodney W. Grimes /* 3759b50d902SRodney W. Grimes * cyclenl is indexed by cycle number: 3769b50d902SRodney W. Grimes * i.e. it is origin 1, not origin 0. 3779b50d902SRodney W. Grimes */ 3789b50d902SRodney W. Grimes cyclenl = (nltype *) calloc( ncycle + 1 , sizeof( nltype ) ); 37997fa9b77SPhilippe Charnier if ( cyclenl == 0 ) 3807853817dSDimitry Andric errx( 1 , "no room for %zu bytes of cycle headers" , 381297b9492SPhilippe Charnier ( ncycle + 1 ) * sizeof( nltype ) ); 3829b50d902SRodney W. Grimes /* 3839b50d902SRodney W. Grimes * now link cycles to true cycleheads, 3849b50d902SRodney W. Grimes * number them, accumulate the data for the cycle 3859b50d902SRodney W. Grimes */ 3869b50d902SRodney W. Grimes cycle = 0; 3879b50d902SRodney W. Grimes for ( nlp = nl ; nlp < npe ; nlp++ ) { 3889b50d902SRodney W. Grimes if ( !( nlp -> cyclehead == nlp && nlp -> cnext != 0 ) ) { 3899b50d902SRodney W. Grimes continue; 3909b50d902SRodney W. Grimes } 3919b50d902SRodney W. Grimes cycle += 1; 3929b50d902SRodney W. Grimes cyclenlp = &cyclenl[cycle]; 3939b50d902SRodney W. Grimes cyclenlp -> name = 0; /* the name */ 3949b50d902SRodney W. Grimes cyclenlp -> value = 0; /* the pc entry point */ 3959b50d902SRodney W. Grimes cyclenlp -> time = 0.0; /* ticks in this routine */ 3969b50d902SRodney W. Grimes cyclenlp -> childtime = 0.0; /* cumulative ticks in children */ 3979b50d902SRodney W. Grimes cyclenlp -> ncall = 0; /* how many times called */ 3989b50d902SRodney W. Grimes cyclenlp -> selfcalls = 0; /* how many calls to self */ 3999b50d902SRodney W. Grimes cyclenlp -> propfraction = 0.0; /* what % of time propagates */ 4009b50d902SRodney W. Grimes cyclenlp -> propself = 0.0; /* how much self time propagates */ 4019b50d902SRodney W. Grimes cyclenlp -> propchild = 0.0; /* how much child time propagates */ 4029b50d902SRodney W. Grimes cyclenlp -> printflag = TRUE; /* should this be printed? */ 4039b50d902SRodney W. Grimes cyclenlp -> index = 0; /* index in the graph list */ 4049b50d902SRodney W. Grimes cyclenlp -> toporder = DFN_NAN; /* graph call chain top-sort order */ 4059b50d902SRodney W. Grimes cyclenlp -> cycleno = cycle; /* internal number of cycle on */ 4069b50d902SRodney W. Grimes cyclenlp -> cyclehead = cyclenlp; /* pointer to head of cycle */ 4079b50d902SRodney W. Grimes cyclenlp -> cnext = nlp; /* pointer to next member of cycle */ 4089b50d902SRodney W. Grimes cyclenlp -> parents = 0; /* list of caller arcs */ 4099b50d902SRodney W. Grimes cyclenlp -> children = 0; /* list of callee arcs */ 4109b50d902SRodney W. Grimes # ifdef DEBUG 4119b50d902SRodney W. Grimes if ( debug & CYCLEDEBUG ) { 4129b50d902SRodney W. Grimes printf( "[cyclelink] " ); 4139b50d902SRodney W. Grimes printname( nlp ); 4149b50d902SRodney W. Grimes printf( " is the head of cycle %d\n" , cycle ); 4159b50d902SRodney W. Grimes } 4160fb7a0beSGarrett Wollman # endif /* DEBUG */ 4179b50d902SRodney W. Grimes /* 4189b50d902SRodney W. Grimes * link members to cycle header 4199b50d902SRodney W. Grimes */ 4209b50d902SRodney W. Grimes for ( memberp = nlp ; memberp ; memberp = memberp -> cnext ) { 4219b50d902SRodney W. Grimes memberp -> cycleno = cycle; 4229b50d902SRodney W. Grimes memberp -> cyclehead = cyclenlp; 4239b50d902SRodney W. Grimes } 4249b50d902SRodney W. Grimes /* 4259b50d902SRodney W. Grimes * count calls from outside the cycle 4269b50d902SRodney W. Grimes * and those among cycle members 4279b50d902SRodney W. Grimes */ 4289b50d902SRodney W. Grimes for ( memberp = nlp ; memberp ; memberp = memberp -> cnext ) { 4299b50d902SRodney W. Grimes for ( arcp=memberp->parents ; arcp ; arcp=arcp->arc_parentlist ) { 4309b50d902SRodney W. Grimes if ( arcp -> arc_parentp == memberp ) { 4319b50d902SRodney W. Grimes continue; 4329b50d902SRodney W. Grimes } 4339b50d902SRodney W. Grimes if ( arcp -> arc_parentp -> cycleno == cycle ) { 4349b50d902SRodney W. Grimes cyclenlp -> selfcalls += arcp -> arc_count; 4359b50d902SRodney W. Grimes } else { 4369b50d902SRodney W. Grimes cyclenlp -> npropcall += arcp -> arc_count; 4379b50d902SRodney W. Grimes } 4389b50d902SRodney W. Grimes } 4399b50d902SRodney W. Grimes } 4409b50d902SRodney W. Grimes } 4419b50d902SRodney W. Grimes } 4429b50d902SRodney W. Grimes 4439b50d902SRodney W. Grimes /* 4449b50d902SRodney W. Grimes * analyze cycles to determine breakup 4459b50d902SRodney W. Grimes */ 44697fa9b77SPhilippe Charnier bool 447*af2637dbSPhilippe Charnier cycleanalyze(void) 4489b50d902SRodney W. Grimes { 4499b50d902SRodney W. Grimes arctype **cyclestack; 4509b50d902SRodney W. Grimes arctype **stkp; 4519b50d902SRodney W. Grimes arctype **arcpp; 4529b50d902SRodney W. Grimes arctype **endlist; 4539b50d902SRodney W. Grimes arctype *arcp; 4549b50d902SRodney W. Grimes nltype *nlp; 4559b50d902SRodney W. Grimes cltype *clp; 4569b50d902SRodney W. Grimes bool ret; 4579b50d902SRodney W. Grimes bool done; 4589b50d902SRodney W. Grimes int size; 4599b50d902SRodney W. Grimes int cycleno; 4609b50d902SRodney W. Grimes 4619b50d902SRodney W. Grimes /* 4629b50d902SRodney W. Grimes * calculate the size of the cycle, and find nodes that 4639b50d902SRodney W. Grimes * exit the cycle as they are desirable targets to cut 4649b50d902SRodney W. Grimes * some of their parents 4659b50d902SRodney W. Grimes */ 4669b50d902SRodney W. Grimes for ( done = TRUE , cycleno = 1 ; cycleno <= ncycle ; cycleno++ ) { 4679b50d902SRodney W. Grimes size = 0; 4689b50d902SRodney W. Grimes for (nlp = cyclenl[ cycleno ] . cnext; nlp; nlp = nlp -> cnext) { 4699b50d902SRodney W. Grimes size += 1; 4709b50d902SRodney W. Grimes nlp -> parentcnt = 0; 4719b50d902SRodney W. Grimes nlp -> flags &= ~HASCYCLEXIT; 4729b50d902SRodney W. Grimes for ( arcp = nlp -> parents; arcp; arcp = arcp -> arc_parentlist ) { 4739b50d902SRodney W. Grimes nlp -> parentcnt += 1; 4749b50d902SRodney W. Grimes if ( arcp -> arc_parentp -> cycleno != cycleno ) 4759b50d902SRodney W. Grimes nlp -> flags |= HASCYCLEXIT; 4769b50d902SRodney W. Grimes } 4779b50d902SRodney W. Grimes } 4789b50d902SRodney W. Grimes if ( size <= cyclethreshold ) 4799b50d902SRodney W. Grimes continue; 4809b50d902SRodney W. Grimes done = FALSE; 4819b50d902SRodney W. Grimes cyclestack = (arctype **) calloc( size + 1 , sizeof( arctype *) ); 48297fa9b77SPhilippe Charnier if ( cyclestack == 0 ) 4837853817dSDimitry Andric errx( 1, "no room for %zu bytes of cycle stack" , 484297b9492SPhilippe Charnier ( size + 1 ) * sizeof( arctype * ) ); 4859b50d902SRodney W. Grimes # ifdef DEBUG 4869b50d902SRodney W. Grimes if ( debug & BREAKCYCLE ) { 4879b50d902SRodney W. Grimes printf( "[cycleanalyze] starting cycle %d of %d, size %d\n" , 4889b50d902SRodney W. Grimes cycleno , ncycle , size ); 4899b50d902SRodney W. Grimes } 4900fb7a0beSGarrett Wollman # endif /* DEBUG */ 4919b50d902SRodney W. Grimes for ( nlp = cyclenl[ cycleno ] . cnext ; nlp ; nlp = nlp -> cnext ) { 4929b50d902SRodney W. Grimes stkp = &cyclestack[0]; 4939b50d902SRodney W. Grimes nlp -> flags |= CYCLEHEAD; 4949b50d902SRodney W. Grimes ret = descend ( nlp , cyclestack , stkp ); 4959b50d902SRodney W. Grimes nlp -> flags &= ~CYCLEHEAD; 4969b50d902SRodney W. Grimes if ( ret == FALSE ) 4979b50d902SRodney W. Grimes break; 4989b50d902SRodney W. Grimes } 4999b50d902SRodney W. Grimes free( cyclestack ); 5009b50d902SRodney W. Grimes if ( cyclecnt > 0 ) { 5019b50d902SRodney W. Grimes compresslist(); 5029b50d902SRodney W. Grimes for ( clp = cyclehead ; clp ; ) { 5039b50d902SRodney W. Grimes endlist = &clp -> list[ clp -> size ]; 5049b50d902SRodney W. Grimes for ( arcpp = clp -> list ; arcpp < endlist ; arcpp++ ) 5059b50d902SRodney W. Grimes (*arcpp) -> arc_cyclecnt--; 5069b50d902SRodney W. Grimes cyclecnt--; 5079b50d902SRodney W. Grimes clp = clp -> next; 5089b50d902SRodney W. Grimes free( clp ); 5099b50d902SRodney W. Grimes } 5109b50d902SRodney W. Grimes cyclehead = 0; 5119b50d902SRodney W. Grimes } 5129b50d902SRodney W. Grimes } 5139b50d902SRodney W. Grimes # ifdef DEBUG 5149b50d902SRodney W. Grimes if ( debug & BREAKCYCLE ) { 5159b50d902SRodney W. Grimes printf("%s visited %d, viable %d, newcycle %d, oldcycle %d\n", 5169b50d902SRodney W. Grimes "[doarcs]" , visited , viable , newcycle , oldcycle); 5179b50d902SRodney W. Grimes } 5180fb7a0beSGarrett Wollman # endif /* DEBUG */ 5199b50d902SRodney W. Grimes return( done ); 5209b50d902SRodney W. Grimes } 5219b50d902SRodney W. Grimes 52297fa9b77SPhilippe Charnier bool 523*af2637dbSPhilippe Charnier descend(nltype *node, arctype **stkstart, arctype **stkp) 5249b50d902SRodney W. Grimes { 5259b50d902SRodney W. Grimes arctype *arcp; 5269b50d902SRodney W. Grimes bool ret; 5279b50d902SRodney W. Grimes 5289b50d902SRodney W. Grimes for ( arcp = node -> children ; arcp ; arcp = arcp -> arc_childlist ) { 5299b50d902SRodney W. Grimes # ifdef DEBUG 5309b50d902SRodney W. Grimes visited++; 5310fb7a0beSGarrett Wollman # endif /* DEBUG */ 5329b50d902SRodney W. Grimes if ( arcp -> arc_childp -> cycleno != node -> cycleno 5339b50d902SRodney W. Grimes || ( arcp -> arc_childp -> flags & VISITED ) 5349b50d902SRodney W. Grimes || ( arcp -> arc_flags & DEADARC ) ) 5359b50d902SRodney W. Grimes continue; 5369b50d902SRodney W. Grimes # ifdef DEBUG 5379b50d902SRodney W. Grimes viable++; 5380fb7a0beSGarrett Wollman # endif /* DEBUG */ 5399b50d902SRodney W. Grimes *stkp = arcp; 5409b50d902SRodney W. Grimes if ( arcp -> arc_childp -> flags & CYCLEHEAD ) { 5419b50d902SRodney W. Grimes if ( addcycle( stkstart , stkp ) == FALSE ) 5429b50d902SRodney W. Grimes return( FALSE ); 5439b50d902SRodney W. Grimes continue; 5449b50d902SRodney W. Grimes } 5459b50d902SRodney W. Grimes arcp -> arc_childp -> flags |= VISITED; 5469b50d902SRodney W. Grimes ret = descend( arcp -> arc_childp , stkstart , stkp + 1 ); 5479b50d902SRodney W. Grimes arcp -> arc_childp -> flags &= ~VISITED; 5489b50d902SRodney W. Grimes if ( ret == FALSE ) 5499b50d902SRodney W. Grimes return( FALSE ); 5509b50d902SRodney W. Grimes } 55197fa9b77SPhilippe Charnier return( TRUE ); 5529b50d902SRodney W. Grimes } 5539b50d902SRodney W. Grimes 55497fa9b77SPhilippe Charnier bool 555*af2637dbSPhilippe Charnier addcycle(arctype **stkstart, arctype **stkend) 5569b50d902SRodney W. Grimes { 5579b50d902SRodney W. Grimes arctype **arcpp; 5589b50d902SRodney W. Grimes arctype **stkloc; 5599b50d902SRodney W. Grimes arctype **stkp; 5609b50d902SRodney W. Grimes arctype **endlist; 5619b50d902SRodney W. Grimes arctype *minarc; 5629b50d902SRodney W. Grimes arctype *arcp; 5639b50d902SRodney W. Grimes cltype *clp; 5649b50d902SRodney W. Grimes int size; 5659b50d902SRodney W. Grimes 5669b50d902SRodney W. Grimes size = stkend - stkstart + 1; 5679b50d902SRodney W. Grimes if ( size <= 1 ) 5689b50d902SRodney W. Grimes return( TRUE ); 5699b50d902SRodney W. Grimes for ( arcpp = stkstart , minarc = *arcpp ; arcpp <= stkend ; arcpp++ ) { 5709b50d902SRodney W. Grimes if ( *arcpp > minarc ) 5719b50d902SRodney W. Grimes continue; 5729b50d902SRodney W. Grimes minarc = *arcpp; 5739b50d902SRodney W. Grimes stkloc = arcpp; 5749b50d902SRodney W. Grimes } 5759b50d902SRodney W. Grimes for ( clp = cyclehead ; clp ; clp = clp -> next ) { 5769b50d902SRodney W. Grimes if ( clp -> size != size ) 5779b50d902SRodney W. Grimes continue; 5789b50d902SRodney W. Grimes stkp = stkloc; 5799b50d902SRodney W. Grimes endlist = &clp -> list[ size ]; 5809b50d902SRodney W. Grimes for ( arcpp = clp -> list ; arcpp < endlist ; arcpp++ ) { 5819b50d902SRodney W. Grimes if ( *stkp++ != *arcpp ) 5829b50d902SRodney W. Grimes break; 5839b50d902SRodney W. Grimes if ( stkp > stkend ) 5849b50d902SRodney W. Grimes stkp = stkstart; 5859b50d902SRodney W. Grimes } 5869b50d902SRodney W. Grimes if ( arcpp == endlist ) { 5879b50d902SRodney W. Grimes # ifdef DEBUG 5889b50d902SRodney W. Grimes oldcycle++; 5890fb7a0beSGarrett Wollman # endif /* DEBUG */ 5909b50d902SRodney W. Grimes return( TRUE ); 5919b50d902SRodney W. Grimes } 5929b50d902SRodney W. Grimes } 5939b50d902SRodney W. Grimes clp = (cltype *) 5949b50d902SRodney W. Grimes calloc( 1 , sizeof ( cltype ) + ( size - 1 ) * sizeof( arctype * ) ); 5959b50d902SRodney W. Grimes if ( clp == 0 ) { 5967853817dSDimitry Andric warnx( "no room for %zu bytes of subcycle storage" , 597b34f7debSPhilippe Charnier sizeof ( cltype ) + ( size - 1 ) * sizeof( arctype * ) ); 5989b50d902SRodney W. Grimes return( FALSE ); 5999b50d902SRodney W. Grimes } 6009b50d902SRodney W. Grimes stkp = stkloc; 6019b50d902SRodney W. Grimes endlist = &clp -> list[ size ]; 6029b50d902SRodney W. Grimes for ( arcpp = clp -> list ; arcpp < endlist ; arcpp++ ) { 6039b50d902SRodney W. Grimes arcp = *arcpp = *stkp++; 6049b50d902SRodney W. Grimes if ( stkp > stkend ) 6059b50d902SRodney W. Grimes stkp = stkstart; 6069b50d902SRodney W. Grimes arcp -> arc_cyclecnt++; 6079b50d902SRodney W. Grimes if ( ( arcp -> arc_flags & ONLIST ) == 0 ) { 6089b50d902SRodney W. Grimes arcp -> arc_flags |= ONLIST; 6099b50d902SRodney W. Grimes arcp -> arc_next = archead; 6109b50d902SRodney W. Grimes archead = arcp; 6119b50d902SRodney W. Grimes } 6129b50d902SRodney W. Grimes } 6139b50d902SRodney W. Grimes clp -> size = size; 6149b50d902SRodney W. Grimes clp -> next = cyclehead; 6159b50d902SRodney W. Grimes cyclehead = clp; 6169b50d902SRodney W. Grimes # ifdef DEBUG 6179b50d902SRodney W. Grimes newcycle++; 6189b50d902SRodney W. Grimes if ( debug & SUBCYCLELIST ) { 6199b50d902SRodney W. Grimes printsubcycle( clp ); 6209b50d902SRodney W. Grimes } 6210fb7a0beSGarrett Wollman # endif /* DEBUG */ 6229b50d902SRodney W. Grimes cyclecnt++; 6239b50d902SRodney W. Grimes if ( cyclecnt >= CYCLEMAX ) 6249b50d902SRodney W. Grimes return( FALSE ); 6259b50d902SRodney W. Grimes return( TRUE ); 6269b50d902SRodney W. Grimes } 6279b50d902SRodney W. Grimes 62897fa9b77SPhilippe Charnier void 629*af2637dbSPhilippe Charnier compresslist(void) 6309b50d902SRodney W. Grimes { 6319b50d902SRodney W. Grimes cltype *clp; 6329b50d902SRodney W. Grimes cltype **prev; 6339b50d902SRodney W. Grimes arctype **arcpp; 6349b50d902SRodney W. Grimes arctype **endlist; 6359b50d902SRodney W. Grimes arctype *arcp; 6369b50d902SRodney W. Grimes arctype *maxarcp; 6379b50d902SRodney W. Grimes arctype *maxexitarcp; 6389b50d902SRodney W. Grimes arctype *maxwithparentarcp; 6399b50d902SRodney W. Grimes arctype *maxnoparentarcp; 6409b50d902SRodney W. Grimes int maxexitcnt; 6419b50d902SRodney W. Grimes int maxwithparentcnt; 6429b50d902SRodney W. Grimes int maxnoparentcnt; 64307ac83f0SBruce Evans # ifdef DEBUG 64407ac83f0SBruce Evans const char *type; 6450fb7a0beSGarrett Wollman # endif /* DEBUG */ 6469b50d902SRodney W. Grimes 6479b50d902SRodney W. Grimes maxexitcnt = 0; 6489b50d902SRodney W. Grimes maxwithparentcnt = 0; 6499b50d902SRodney W. Grimes maxnoparentcnt = 0; 6509b50d902SRodney W. Grimes for ( endlist = &archead , arcp = archead ; arcp ; ) { 6519b50d902SRodney W. Grimes if ( arcp -> arc_cyclecnt == 0 ) { 6529b50d902SRodney W. Grimes arcp -> arc_flags &= ~ONLIST; 6539b50d902SRodney W. Grimes *endlist = arcp -> arc_next; 6549b50d902SRodney W. Grimes arcp -> arc_next = 0; 6559b50d902SRodney W. Grimes arcp = *endlist; 6569b50d902SRodney W. Grimes continue; 6579b50d902SRodney W. Grimes } 6589b50d902SRodney W. Grimes if ( arcp -> arc_childp -> flags & HASCYCLEXIT ) { 6599b50d902SRodney W. Grimes if ( arcp -> arc_cyclecnt > maxexitcnt || 6609b50d902SRodney W. Grimes ( arcp -> arc_cyclecnt == maxexitcnt && 6619b50d902SRodney W. Grimes arcp -> arc_cyclecnt < maxexitarcp -> arc_count ) ) { 6629b50d902SRodney W. Grimes maxexitcnt = arcp -> arc_cyclecnt; 6639b50d902SRodney W. Grimes maxexitarcp = arcp; 6649b50d902SRodney W. Grimes } 6659b50d902SRodney W. Grimes } else if ( arcp -> arc_childp -> parentcnt > 1 ) { 6669b50d902SRodney W. Grimes if ( arcp -> arc_cyclecnt > maxwithparentcnt || 6679b50d902SRodney W. Grimes ( arcp -> arc_cyclecnt == maxwithparentcnt && 6689b50d902SRodney W. Grimes arcp -> arc_cyclecnt < maxwithparentarcp -> arc_count ) ) { 6699b50d902SRodney W. Grimes maxwithparentcnt = arcp -> arc_cyclecnt; 6709b50d902SRodney W. Grimes maxwithparentarcp = arcp; 6719b50d902SRodney W. Grimes } 6729b50d902SRodney W. Grimes } else { 6739b50d902SRodney W. Grimes if ( arcp -> arc_cyclecnt > maxnoparentcnt || 6749b50d902SRodney W. Grimes ( arcp -> arc_cyclecnt == maxnoparentcnt && 6759b50d902SRodney W. Grimes arcp -> arc_cyclecnt < maxnoparentarcp -> arc_count ) ) { 6769b50d902SRodney W. Grimes maxnoparentcnt = arcp -> arc_cyclecnt; 6779b50d902SRodney W. Grimes maxnoparentarcp = arcp; 6789b50d902SRodney W. Grimes } 6799b50d902SRodney W. Grimes } 6809b50d902SRodney W. Grimes endlist = &arcp -> arc_next; 6819b50d902SRodney W. Grimes arcp = arcp -> arc_next; 6829b50d902SRodney W. Grimes } 6839b50d902SRodney W. Grimes if ( maxexitcnt > 0 ) { 6849b50d902SRodney W. Grimes /* 6859b50d902SRodney W. Grimes * first choice is edge leading to node with out-of-cycle parent 6869b50d902SRodney W. Grimes */ 6879b50d902SRodney W. Grimes maxarcp = maxexitarcp; 6889b50d902SRodney W. Grimes # ifdef DEBUG 6899b50d902SRodney W. Grimes type = "exit"; 6900fb7a0beSGarrett Wollman # endif /* DEBUG */ 6919b50d902SRodney W. Grimes } else if ( maxwithparentcnt > 0 ) { 6929b50d902SRodney W. Grimes /* 6939b50d902SRodney W. Grimes * second choice is edge leading to node with at least one 6949b50d902SRodney W. Grimes * other in-cycle parent 6959b50d902SRodney W. Grimes */ 6969b50d902SRodney W. Grimes maxarcp = maxwithparentarcp; 6979b50d902SRodney W. Grimes # ifdef DEBUG 6989b50d902SRodney W. Grimes type = "internal"; 6990fb7a0beSGarrett Wollman # endif /* DEBUG */ 7009b50d902SRodney W. Grimes } else { 7019b50d902SRodney W. Grimes /* 7029b50d902SRodney W. Grimes * last choice is edge leading to node with only this arc as 7039b50d902SRodney W. Grimes * a parent (as it will now be orphaned) 7049b50d902SRodney W. Grimes */ 7059b50d902SRodney W. Grimes maxarcp = maxnoparentarcp; 7069b50d902SRodney W. Grimes # ifdef DEBUG 7079b50d902SRodney W. Grimes type = "orphan"; 7080fb7a0beSGarrett Wollman # endif /* DEBUG */ 7099b50d902SRodney W. Grimes } 7109b50d902SRodney W. Grimes maxarcp -> arc_flags |= DEADARC; 7119b50d902SRodney W. Grimes maxarcp -> arc_childp -> parentcnt -= 1; 7129b50d902SRodney W. Grimes maxarcp -> arc_childp -> npropcall -= maxarcp -> arc_count; 7139b50d902SRodney W. Grimes # ifdef DEBUG 7149b50d902SRodney W. Grimes if ( debug & BREAKCYCLE ) { 7158d57b8d3SBruce Evans printf( "%s delete %s arc: %s (%ld) -> %s from %u cycle(s)\n" , 7169b50d902SRodney W. Grimes "[compresslist]" , type , maxarcp -> arc_parentp -> name , 7179b50d902SRodney W. Grimes maxarcp -> arc_count , maxarcp -> arc_childp -> name , 7189b50d902SRodney W. Grimes maxarcp -> arc_cyclecnt ); 7199b50d902SRodney W. Grimes } 7200fb7a0beSGarrett Wollman # endif /* DEBUG */ 7218d57b8d3SBruce Evans printf( "\t%s to %s with %ld calls\n" , maxarcp -> arc_parentp -> name , 7229b50d902SRodney W. Grimes maxarcp -> arc_childp -> name , maxarcp -> arc_count ); 7239b50d902SRodney W. Grimes prev = &cyclehead; 7249b50d902SRodney W. Grimes for ( clp = cyclehead ; clp ; ) { 7259b50d902SRodney W. Grimes endlist = &clp -> list[ clp -> size ]; 7269b50d902SRodney W. Grimes for ( arcpp = clp -> list ; arcpp < endlist ; arcpp++ ) 7279b50d902SRodney W. Grimes if ( (*arcpp) -> arc_flags & DEADARC ) 7289b50d902SRodney W. Grimes break; 7299b50d902SRodney W. Grimes if ( arcpp == endlist ) { 7309b50d902SRodney W. Grimes prev = &clp -> next; 7319b50d902SRodney W. Grimes clp = clp -> next; 7329b50d902SRodney W. Grimes continue; 7339b50d902SRodney W. Grimes } 7349b50d902SRodney W. Grimes for ( arcpp = clp -> list ; arcpp < endlist ; arcpp++ ) 7359b50d902SRodney W. Grimes (*arcpp) -> arc_cyclecnt--; 7369b50d902SRodney W. Grimes cyclecnt--; 7379b50d902SRodney W. Grimes *prev = clp -> next; 7389b50d902SRodney W. Grimes clp = clp -> next; 7399b50d902SRodney W. Grimes free( clp ); 7409b50d902SRodney W. Grimes } 7419b50d902SRodney W. Grimes } 7429b50d902SRodney W. Grimes 7439b50d902SRodney W. Grimes #ifdef DEBUG 74497fa9b77SPhilippe Charnier void 745*af2637dbSPhilippe Charnier printsubcycle(cltype *clp) 7469b50d902SRodney W. Grimes { 7479b50d902SRodney W. Grimes arctype **arcpp; 7489b50d902SRodney W. Grimes arctype **endlist; 7499b50d902SRodney W. Grimes 7509b50d902SRodney W. Grimes arcpp = clp -> list; 7519b50d902SRodney W. Grimes printf( "%s <cycle %d>\n" , (*arcpp) -> arc_parentp -> name , 7529b50d902SRodney W. Grimes (*arcpp) -> arc_parentp -> cycleno ) ; 7539b50d902SRodney W. Grimes for ( endlist = &clp -> list[ clp -> size ]; arcpp < endlist ; arcpp++ ) 7548d57b8d3SBruce Evans printf( "\t(%ld) -> %s\n" , (*arcpp) -> arc_count , 7559b50d902SRodney W. Grimes (*arcpp) -> arc_childp -> name ) ; 7569b50d902SRodney W. Grimes } 7570fb7a0beSGarrett Wollman #endif /* DEBUG */ 7589b50d902SRodney W. Grimes 75997fa9b77SPhilippe Charnier void 760*af2637dbSPhilippe Charnier cycletime(void) 7619b50d902SRodney W. Grimes { 7629b50d902SRodney W. Grimes int cycle; 7639b50d902SRodney W. Grimes nltype *cyclenlp; 7649b50d902SRodney W. Grimes nltype *childp; 7659b50d902SRodney W. Grimes 7669b50d902SRodney W. Grimes for ( cycle = 1 ; cycle <= ncycle ; cycle += 1 ) { 7679b50d902SRodney W. Grimes cyclenlp = &cyclenl[ cycle ]; 7689b50d902SRodney W. Grimes for ( childp = cyclenlp -> cnext ; childp ; childp = childp -> cnext ) { 7699b50d902SRodney W. Grimes if ( childp -> propfraction == 0.0 ) { 7709b50d902SRodney W. Grimes /* 7719b50d902SRodney W. Grimes * all members have the same propfraction except those 7729b50d902SRodney W. Grimes * that were excluded with -E 7739b50d902SRodney W. Grimes */ 7749b50d902SRodney W. Grimes continue; 7759b50d902SRodney W. Grimes } 7769b50d902SRodney W. Grimes cyclenlp -> time += childp -> time; 7779b50d902SRodney W. Grimes } 7789b50d902SRodney W. Grimes cyclenlp -> propself = cyclenlp -> propfraction * cyclenlp -> time; 7799b50d902SRodney W. Grimes } 7809b50d902SRodney W. Grimes } 7819b50d902SRodney W. Grimes 7829b50d902SRodney W. Grimes /* 7839b50d902SRodney W. Grimes * in one top to bottom pass over the topologically sorted namelist 7849b50d902SRodney W. Grimes * propagate: 7859b50d902SRodney W. Grimes * printflag as the union of parents' printflags 7869b50d902SRodney W. Grimes * propfraction as the sum of fractional parents' propfractions 7879b50d902SRodney W. Grimes * and while we're here, sum time for functions. 7889b50d902SRodney W. Grimes */ 78997fa9b77SPhilippe Charnier void 790*af2637dbSPhilippe Charnier doflags(void) 7919b50d902SRodney W. Grimes { 7929b50d902SRodney W. Grimes int index; 7939b50d902SRodney W. Grimes nltype *childp; 7949b50d902SRodney W. Grimes nltype *oldhead; 7959b50d902SRodney W. Grimes 7969b50d902SRodney W. Grimes oldhead = 0; 7979b50d902SRodney W. Grimes for ( index = nname-1 ; index >= 0 ; index -= 1 ) { 7989b50d902SRodney W. Grimes childp = topsortnlp[ index ]; 7999b50d902SRodney W. Grimes /* 8009b50d902SRodney W. Grimes * if we haven't done this function or cycle, 8019b50d902SRodney W. Grimes * inherit things from parent. 8029b50d902SRodney W. Grimes * this way, we are linear in the number of arcs 8039b50d902SRodney W. Grimes * since we do all members of a cycle (and the cycle itself) 8049b50d902SRodney W. Grimes * as we hit the first member of the cycle. 8059b50d902SRodney W. Grimes */ 8069b50d902SRodney W. Grimes if ( childp -> cyclehead != oldhead ) { 8079b50d902SRodney W. Grimes oldhead = childp -> cyclehead; 8089b50d902SRodney W. Grimes inheritflags( childp ); 8099b50d902SRodney W. Grimes } 8109b50d902SRodney W. Grimes # ifdef DEBUG 8119b50d902SRodney W. Grimes if ( debug & PROPDEBUG ) { 8129b50d902SRodney W. Grimes printf( "[doflags] " ); 8139b50d902SRodney W. Grimes printname( childp ); 8149b50d902SRodney W. Grimes printf( " inherits printflag %d and propfraction %f\n" , 8159b50d902SRodney W. Grimes childp -> printflag , childp -> propfraction ); 8169b50d902SRodney W. Grimes } 8170fb7a0beSGarrett Wollman # endif /* DEBUG */ 8189b50d902SRodney W. Grimes if ( ! childp -> printflag ) { 8199b50d902SRodney W. Grimes /* 8209b50d902SRodney W. Grimes * printflag is off 8219b50d902SRodney W. Grimes * it gets turned on by 8229b50d902SRodney W. Grimes * being on -f list, 8239b50d902SRodney W. Grimes * or there not being any -f list and not being on -e list. 8249b50d902SRodney W. Grimes */ 8259b50d902SRodney W. Grimes if ( onlist( flist , childp -> name ) 8269b50d902SRodney W. Grimes || ( !fflag && !onlist( elist , childp -> name ) ) ) { 8279b50d902SRodney W. Grimes childp -> printflag = TRUE; 8289b50d902SRodney W. Grimes } 8299b50d902SRodney W. Grimes } else { 8309b50d902SRodney W. Grimes /* 8319b50d902SRodney W. Grimes * this function has printing parents: 8329b50d902SRodney W. Grimes * maybe someone wants to shut it up 8339b50d902SRodney W. Grimes * by putting it on -e list. (but favor -f over -e) 8349b50d902SRodney W. Grimes */ 8359b50d902SRodney W. Grimes if ( ( !onlist( flist , childp -> name ) ) 8369b50d902SRodney W. Grimes && onlist( elist , childp -> name ) ) { 8379b50d902SRodney W. Grimes childp -> printflag = FALSE; 8389b50d902SRodney W. Grimes } 8399b50d902SRodney W. Grimes } 8409b50d902SRodney W. Grimes if ( childp -> propfraction == 0.0 ) { 8419b50d902SRodney W. Grimes /* 8429b50d902SRodney W. Grimes * no parents to pass time to. 8439b50d902SRodney W. Grimes * collect time from children if 8449b50d902SRodney W. Grimes * its on -F list, 8459b50d902SRodney W. Grimes * or there isn't any -F list and its not on -E list. 8469b50d902SRodney W. Grimes */ 8479b50d902SRodney W. Grimes if ( onlist( Flist , childp -> name ) 8489b50d902SRodney W. Grimes || ( !Fflag && !onlist( Elist , childp -> name ) ) ) { 8499b50d902SRodney W. Grimes childp -> propfraction = 1.0; 8509b50d902SRodney W. Grimes } 8519b50d902SRodney W. Grimes } else { 8529b50d902SRodney W. Grimes /* 8539b50d902SRodney W. Grimes * it has parents to pass time to, 8549b50d902SRodney W. Grimes * but maybe someone wants to shut it up 85597fa9b77SPhilippe Charnier * by putting it on -E list. (but favor -F over -E) 8569b50d902SRodney W. Grimes */ 8579b50d902SRodney W. Grimes if ( !onlist( Flist , childp -> name ) 8589b50d902SRodney W. Grimes && onlist( Elist , childp -> name ) ) { 8599b50d902SRodney W. Grimes childp -> propfraction = 0.0; 8609b50d902SRodney W. Grimes } 8619b50d902SRodney W. Grimes } 8629b50d902SRodney W. Grimes childp -> propself = childp -> time * childp -> propfraction; 8639b50d902SRodney W. Grimes printtime += childp -> propself; 8649b50d902SRodney W. Grimes # ifdef DEBUG 8659b50d902SRodney W. Grimes if ( debug & PROPDEBUG ) { 8669b50d902SRodney W. Grimes printf( "[doflags] " ); 8679b50d902SRodney W. Grimes printname( childp ); 8689b50d902SRodney W. Grimes printf( " ends up with printflag %d and propfraction %f\n" , 8699b50d902SRodney W. Grimes childp -> printflag , childp -> propfraction ); 8709b50d902SRodney W. Grimes printf( "time %f propself %f printtime %f\n" , 8719b50d902SRodney W. Grimes childp -> time , childp -> propself , printtime ); 8729b50d902SRodney W. Grimes } 8730fb7a0beSGarrett Wollman # endif /* DEBUG */ 8749b50d902SRodney W. Grimes } 8759b50d902SRodney W. Grimes } 8769b50d902SRodney W. Grimes 8779b50d902SRodney W. Grimes /* 8789b50d902SRodney W. Grimes * check if any parent of this child 8799b50d902SRodney W. Grimes * (or outside parents of this cycle) 8809b50d902SRodney W. Grimes * have their print flags on and set the 8819b50d902SRodney W. Grimes * print flag of the child (cycle) appropriately. 8829b50d902SRodney W. Grimes * similarly, deal with propagation fractions from parents. 8839b50d902SRodney W. Grimes */ 88497fa9b77SPhilippe Charnier void 885*af2637dbSPhilippe Charnier inheritflags(nltype *childp) 8869b50d902SRodney W. Grimes { 8879b50d902SRodney W. Grimes nltype *headp; 8889b50d902SRodney W. Grimes arctype *arcp; 8899b50d902SRodney W. Grimes nltype *parentp; 8909b50d902SRodney W. Grimes nltype *memp; 8919b50d902SRodney W. Grimes 8929b50d902SRodney W. Grimes headp = childp -> cyclehead; 8939b50d902SRodney W. Grimes if ( childp == headp ) { 8949b50d902SRodney W. Grimes /* 8959b50d902SRodney W. Grimes * just a regular child, check its parents 8969b50d902SRodney W. Grimes */ 8979b50d902SRodney W. Grimes childp -> printflag = FALSE; 8989b50d902SRodney W. Grimes childp -> propfraction = 0.0; 8999b50d902SRodney W. Grimes for (arcp = childp -> parents ; arcp ; arcp = arcp -> arc_parentlist) { 9009b50d902SRodney W. Grimes parentp = arcp -> arc_parentp; 9019b50d902SRodney W. Grimes if ( childp == parentp ) { 9029b50d902SRodney W. Grimes continue; 9039b50d902SRodney W. Grimes } 9049b50d902SRodney W. Grimes childp -> printflag |= parentp -> printflag; 9059b50d902SRodney W. Grimes /* 9069b50d902SRodney W. Grimes * if the child was never actually called 9079b50d902SRodney W. Grimes * (e.g. this arc is static (and all others are, too)) 9089b50d902SRodney W. Grimes * no time propagates along this arc. 9099b50d902SRodney W. Grimes */ 9109b50d902SRodney W. Grimes if ( arcp -> arc_flags & DEADARC ) { 9119b50d902SRodney W. Grimes continue; 9129b50d902SRodney W. Grimes } 9139b50d902SRodney W. Grimes if ( childp -> npropcall ) { 9149b50d902SRodney W. Grimes childp -> propfraction += parentp -> propfraction 9159b50d902SRodney W. Grimes * ( ( (double) arcp -> arc_count ) 9169b50d902SRodney W. Grimes / ( (double) childp -> npropcall ) ); 9179b50d902SRodney W. Grimes } 9189b50d902SRodney W. Grimes } 9199b50d902SRodney W. Grimes } else { 9209b50d902SRodney W. Grimes /* 9219b50d902SRodney W. Grimes * its a member of a cycle, look at all parents from 9229b50d902SRodney W. Grimes * outside the cycle 9239b50d902SRodney W. Grimes */ 9249b50d902SRodney W. Grimes headp -> printflag = FALSE; 9259b50d902SRodney W. Grimes headp -> propfraction = 0.0; 9269b50d902SRodney W. Grimes for ( memp = headp -> cnext ; memp ; memp = memp -> cnext ) { 9279b50d902SRodney W. Grimes for (arcp = memp->parents ; arcp ; arcp = arcp->arc_parentlist) { 9289b50d902SRodney W. Grimes if ( arcp -> arc_parentp -> cyclehead == headp ) { 9299b50d902SRodney W. Grimes continue; 9309b50d902SRodney W. Grimes } 9319b50d902SRodney W. Grimes parentp = arcp -> arc_parentp; 9329b50d902SRodney W. Grimes headp -> printflag |= parentp -> printflag; 9339b50d902SRodney W. Grimes /* 9349b50d902SRodney W. Grimes * if the cycle was never actually called 9359b50d902SRodney W. Grimes * (e.g. this arc is static (and all others are, too)) 9369b50d902SRodney W. Grimes * no time propagates along this arc. 9379b50d902SRodney W. Grimes */ 9389b50d902SRodney W. Grimes if ( arcp -> arc_flags & DEADARC ) { 9399b50d902SRodney W. Grimes continue; 9409b50d902SRodney W. Grimes } 9419b50d902SRodney W. Grimes if ( headp -> npropcall ) { 9429b50d902SRodney W. Grimes headp -> propfraction += parentp -> propfraction 9439b50d902SRodney W. Grimes * ( ( (double) arcp -> arc_count ) 9449b50d902SRodney W. Grimes / ( (double) headp -> npropcall ) ); 9459b50d902SRodney W. Grimes } 9469b50d902SRodney W. Grimes } 9479b50d902SRodney W. Grimes } 9489b50d902SRodney W. Grimes for ( memp = headp ; memp ; memp = memp -> cnext ) { 9499b50d902SRodney W. Grimes memp -> printflag = headp -> printflag; 9509b50d902SRodney W. Grimes memp -> propfraction = headp -> propfraction; 9519b50d902SRodney W. Grimes } 9529b50d902SRodney W. Grimes } 9539b50d902SRodney W. Grimes } 954