1 /*- 2 * SPDX-License-Identifier: BSD-3-Clause 3 * 4 * Copyright (c) 1983, 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. Neither the name of the University nor the names of its contributors 16 * may be used to endorse or promote products derived from this software 17 * without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 */ 31 32 #include <sys/cdefs.h> 33 #include <err.h> 34 #include "gprof.h" 35 36 #ifdef DEBUG 37 int visited; 38 int viable; 39 int newcycle; 40 int oldcycle; 41 #endif /* DEBUG */ 42 43 int topcmp(const void *, const void *); 44 45 /* 46 * add (or just increment) an arc 47 */ 48 void 49 addarc(nltype *parentp, nltype *childp, long count) 50 { 51 arctype *arcp; 52 53 # ifdef DEBUG 54 if ( debug & TALLYDEBUG ) { 55 printf( "[addarc] %ld arcs from %s to %s\n" , 56 count , parentp -> name , childp -> name ); 57 } 58 # endif /* DEBUG */ 59 arcp = arclookup( parentp , childp ); 60 if ( arcp != 0 ) { 61 /* 62 * a hit: just increment the count. 63 */ 64 # ifdef DEBUG 65 if ( debug & TALLYDEBUG ) { 66 printf( "[tally] hit %ld += %ld\n" , 67 arcp -> arc_count , count ); 68 } 69 # endif /* DEBUG */ 70 arcp -> arc_count += count; 71 return; 72 } 73 arcp = (arctype *)calloc( 1 , sizeof *arcp ); 74 if (arcp == NULL) 75 errx( 1 , "malloc failed" ); 76 arcp -> arc_parentp = parentp; 77 arcp -> arc_childp = childp; 78 arcp -> arc_count = count; 79 /* 80 * prepend this child to the children of this parent 81 */ 82 arcp -> arc_childlist = parentp -> children; 83 parentp -> children = arcp; 84 /* 85 * prepend this parent to the parents of this child 86 */ 87 arcp -> arc_parentlist = childp -> parents; 88 childp -> parents = arcp; 89 } 90 91 /* 92 * the code below topologically sorts the graph (collapsing cycles), 93 * and propagates time bottom up and flags top down. 94 */ 95 96 /* 97 * the topologically sorted name list pointers 98 */ 99 nltype **topsortnlp; 100 101 int 102 topcmp(const void *v1, const void *v2) 103 { 104 const nltype **npp1 = (const nltype **)v1; 105 const nltype **npp2 = (const nltype **)v2; 106 107 return (*npp1) -> toporder - (*npp2) -> toporder; 108 } 109 110 nltype ** 111 doarcs(void) 112 { 113 nltype *parentp, **timesortnlp; 114 arctype *arcp; 115 long index; 116 long pass; 117 118 /* 119 * initialize various things: 120 * zero out child times. 121 * count self-recursive calls. 122 * indicate that nothing is on cycles. 123 */ 124 for ( parentp = nl ; parentp < npe ; parentp++ ) { 125 parentp -> childtime = 0.0; 126 arcp = arclookup( parentp , parentp ); 127 if ( arcp != 0 ) { 128 parentp -> ncall -= arcp -> arc_count; 129 parentp -> selfcalls = arcp -> arc_count; 130 } else { 131 parentp -> selfcalls = 0; 132 } 133 parentp -> npropcall = parentp -> ncall; 134 parentp -> propfraction = 0.0; 135 parentp -> propself = 0.0; 136 parentp -> propchild = 0.0; 137 parentp -> printflag = FALSE; 138 parentp -> toporder = DFN_NAN; 139 parentp -> cycleno = 0; 140 parentp -> cyclehead = parentp; 141 parentp -> cnext = 0; 142 } 143 for ( pass = 1 ; ; pass++ ) { 144 /* 145 * topologically order things 146 * if any node is unnumbered, 147 * number it and any of its descendents. 148 */ 149 for ( dfn_init() , parentp = nl ; parentp < npe ; parentp++ ) { 150 if ( parentp -> toporder == DFN_NAN ) { 151 dfn( parentp ); 152 } 153 } 154 /* 155 * link together nodes on the same cycle 156 */ 157 cyclelink(); 158 /* 159 * if no cycles to break up, proceed 160 */ 161 if ( ! Cflag ) 162 break; 163 /* 164 * analyze cycles to determine breakup 165 */ 166 # ifdef DEBUG 167 if ( debug & BREAKCYCLE ) { 168 printf("[doarcs] pass %ld, cycle(s) %d\n" , pass , ncycle ); 169 } 170 # endif /* DEBUG */ 171 if ( pass == 1 ) { 172 printf( "\n\n%s %s\n%s %d:\n" , 173 "The following arcs were deleted" , 174 "from the propagation calculation" , 175 "to reduce the maximum cycle size to", cyclethreshold ); 176 } 177 if ( cycleanalyze() ) 178 break; 179 free ( cyclenl ); 180 ncycle = 0; 181 for ( parentp = nl ; parentp < npe ; parentp++ ) { 182 parentp -> toporder = DFN_NAN; 183 parentp -> cycleno = 0; 184 parentp -> cyclehead = parentp; 185 parentp -> cnext = 0; 186 } 187 } 188 if ( pass > 1 ) { 189 printf( "\f\n" ); 190 } else { 191 printf( "\tNone\n\n" ); 192 } 193 /* 194 * Sort the symbol table in reverse topological order 195 */ 196 topsortnlp = (nltype **) calloc( nname , sizeof(nltype *) ); 197 if ( topsortnlp == (nltype **) 0 ) 198 errx( 1 , "[doarcs] ran out of memory for topo sorting" ); 199 for ( index = 0 ; index < nname ; index += 1 ) { 200 topsortnlp[ index ] = &nl[ index ]; 201 } 202 qsort( topsortnlp , nname , sizeof(nltype *) , topcmp ); 203 # ifdef DEBUG 204 if ( debug & DFNDEBUG ) { 205 printf( "[doarcs] topological sort listing\n" ); 206 for ( index = 0 ; index < nname ; index += 1 ) { 207 printf( "[doarcs] " ); 208 printf( "%d:" , topsortnlp[ index ] -> toporder ); 209 printname( topsortnlp[ index ] ); 210 printf( "\n" ); 211 } 212 } 213 # endif /* DEBUG */ 214 /* 215 * starting from the topological top, 216 * propagate print flags to children. 217 * also, calculate propagation fractions. 218 * this happens before time propagation 219 * since time propagation uses the fractions. 220 */ 221 doflags(); 222 /* 223 * starting from the topological bottom, 224 * propagate children times up to parents. 225 */ 226 dotime(); 227 /* 228 * Now, sort by propself + propchild. 229 * sorting both the regular function names 230 * and cycle headers. 231 */ 232 timesortnlp = (nltype **) calloc( nname + ncycle , sizeof(nltype *) ); 233 if ( timesortnlp == (nltype **) 0 ) 234 errx( 1 , "ran out of memory for sorting" ); 235 for ( index = 0 ; index < nname ; index++ ) { 236 timesortnlp[index] = &nl[index]; 237 } 238 for ( index = 1 ; index <= ncycle ; index++ ) { 239 timesortnlp[nname+index-1] = &cyclenl[index]; 240 } 241 qsort( timesortnlp , nname + ncycle , sizeof(nltype *) , totalcmp ); 242 for ( index = 0 ; index < nname + ncycle ; index++ ) { 243 timesortnlp[ index ] -> index = index + 1; 244 } 245 return( timesortnlp ); 246 } 247 248 void 249 dotime(void) 250 { 251 int index; 252 253 cycletime(); 254 for ( index = 0 ; index < nname ; index += 1 ) { 255 timepropagate( topsortnlp[ index ] ); 256 } 257 } 258 259 void 260 timepropagate(nltype *parentp) 261 { 262 arctype *arcp; 263 nltype *childp; 264 double share; 265 double propshare; 266 267 if ( parentp -> propfraction == 0.0 ) { 268 return; 269 } 270 /* 271 * gather time from children of this parent. 272 */ 273 for ( arcp = parentp -> children ; arcp ; arcp = arcp -> arc_childlist ) { 274 childp = arcp -> arc_childp; 275 if ( arcp -> arc_flags & DEADARC ) { 276 continue; 277 } 278 if ( arcp -> arc_count == 0 ) { 279 continue; 280 } 281 if ( childp == parentp ) { 282 continue; 283 } 284 if ( childp -> propfraction == 0.0 ) { 285 continue; 286 } 287 if ( childp -> cyclehead != childp ) { 288 if ( parentp -> cycleno == childp -> cycleno ) { 289 continue; 290 } 291 if ( parentp -> toporder <= childp -> toporder ) { 292 fprintf( stderr , "[propagate] toporder botches\n" ); 293 } 294 childp = childp -> cyclehead; 295 } else { 296 if ( parentp -> toporder <= childp -> toporder ) { 297 fprintf( stderr , "[propagate] toporder botches\n" ); 298 continue; 299 } 300 } 301 if ( childp -> npropcall == 0 ) { 302 continue; 303 } 304 /* 305 * distribute time for this arc 306 */ 307 arcp -> arc_time = childp -> time 308 * ( ( (double) arcp -> arc_count ) / 309 ( (double) childp -> npropcall ) ); 310 arcp -> arc_childtime = childp -> childtime 311 * ( ( (double) arcp -> arc_count ) / 312 ( (double) childp -> npropcall ) ); 313 share = arcp -> arc_time + arcp -> arc_childtime; 314 parentp -> childtime += share; 315 /* 316 * ( 1 - propfraction ) gets lost along the way 317 */ 318 propshare = parentp -> propfraction * share; 319 /* 320 * fix things for printing 321 */ 322 parentp -> propchild += propshare; 323 arcp -> arc_time *= parentp -> propfraction; 324 arcp -> arc_childtime *= parentp -> propfraction; 325 /* 326 * add this share to the parent's cycle header, if any. 327 */ 328 if ( parentp -> cyclehead != parentp ) { 329 parentp -> cyclehead -> childtime += share; 330 parentp -> cyclehead -> propchild += propshare; 331 } 332 # ifdef DEBUG 333 if ( debug & PROPDEBUG ) { 334 printf( "[dotime] child \t" ); 335 printname( childp ); 336 printf( " with %f %f %ld/%ld\n" , 337 childp -> time , childp -> childtime , 338 arcp -> arc_count , childp -> npropcall ); 339 printf( "[dotime] parent\t" ); 340 printname( parentp ); 341 printf( "\n[dotime] share %f\n" , share ); 342 } 343 # endif /* DEBUG */ 344 } 345 } 346 347 void 348 cyclelink(void) 349 { 350 register nltype *nlp; 351 register nltype *cyclenlp; 352 int cycle; 353 nltype *memberp; 354 arctype *arcp; 355 356 /* 357 * Count the number of cycles, and initialize the cycle lists 358 */ 359 ncycle = 0; 360 for ( nlp = nl ; nlp < npe ; nlp++ ) { 361 /* 362 * this is how you find unattached cycles 363 */ 364 if ( nlp -> cyclehead == nlp && nlp -> cnext != 0 ) { 365 ncycle += 1; 366 } 367 } 368 /* 369 * cyclenl is indexed by cycle number: 370 * i.e. it is origin 1, not origin 0. 371 */ 372 cyclenl = (nltype *) calloc( ncycle + 1 , sizeof( nltype ) ); 373 if ( cyclenl == NULL ) 374 errx( 1 , "no room for %zu bytes of cycle headers" , 375 ( ncycle + 1 ) * sizeof( nltype ) ); 376 /* 377 * now link cycles to true cycleheads, 378 * number them, accumulate the data for the cycle 379 */ 380 cycle = 0; 381 for ( nlp = nl ; nlp < npe ; nlp++ ) { 382 if ( !( nlp -> cyclehead == nlp && nlp -> cnext != 0 ) ) { 383 continue; 384 } 385 cycle += 1; 386 cyclenlp = &cyclenl[cycle]; 387 cyclenlp -> name = 0; /* the name */ 388 cyclenlp -> value = 0; /* the pc entry point */ 389 cyclenlp -> time = 0.0; /* ticks in this routine */ 390 cyclenlp -> childtime = 0.0; /* cumulative ticks in children */ 391 cyclenlp -> ncall = 0; /* how many times called */ 392 cyclenlp -> selfcalls = 0; /* how many calls to self */ 393 cyclenlp -> propfraction = 0.0; /* what % of time propagates */ 394 cyclenlp -> propself = 0.0; /* how much self time propagates */ 395 cyclenlp -> propchild = 0.0; /* how much child time propagates */ 396 cyclenlp -> printflag = TRUE; /* should this be printed? */ 397 cyclenlp -> index = 0; /* index in the graph list */ 398 cyclenlp -> toporder = DFN_NAN; /* graph call chain top-sort order */ 399 cyclenlp -> cycleno = cycle; /* internal number of cycle on */ 400 cyclenlp -> cyclehead = cyclenlp; /* pointer to head of cycle */ 401 cyclenlp -> cnext = nlp; /* pointer to next member of cycle */ 402 cyclenlp -> parents = 0; /* list of caller arcs */ 403 cyclenlp -> children = 0; /* list of callee arcs */ 404 # ifdef DEBUG 405 if ( debug & CYCLEDEBUG ) { 406 printf( "[cyclelink] " ); 407 printname( nlp ); 408 printf( " is the head of cycle %d\n" , cycle ); 409 } 410 # endif /* DEBUG */ 411 /* 412 * link members to cycle header 413 */ 414 for ( memberp = nlp ; memberp ; memberp = memberp -> cnext ) { 415 memberp -> cycleno = cycle; 416 memberp -> cyclehead = cyclenlp; 417 } 418 /* 419 * count calls from outside the cycle 420 * and those among cycle members 421 */ 422 for ( memberp = nlp ; memberp ; memberp = memberp -> cnext ) { 423 for ( arcp=memberp->parents ; arcp ; arcp=arcp->arc_parentlist ) { 424 if ( arcp -> arc_parentp == memberp ) { 425 continue; 426 } 427 if ( arcp -> arc_parentp -> cycleno == cycle ) { 428 cyclenlp -> selfcalls += arcp -> arc_count; 429 } else { 430 cyclenlp -> npropcall += arcp -> arc_count; 431 } 432 } 433 } 434 } 435 } 436 437 /* 438 * analyze cycles to determine breakup 439 */ 440 bool 441 cycleanalyze(void) 442 { 443 arctype **cyclestack; 444 arctype **stkp; 445 arctype **arcpp; 446 arctype **endlist; 447 arctype *arcp; 448 nltype *nlp; 449 cltype *clp; 450 bool ret; 451 bool done; 452 int size; 453 int cycleno; 454 455 /* 456 * calculate the size of the cycle, and find nodes that 457 * exit the cycle as they are desirable targets to cut 458 * some of their parents 459 */ 460 for ( done = TRUE , cycleno = 1 ; cycleno <= ncycle ; cycleno++ ) { 461 size = 0; 462 for (nlp = cyclenl[ cycleno ] . cnext; nlp; nlp = nlp -> cnext) { 463 size += 1; 464 nlp -> parentcnt = 0; 465 nlp -> flags &= ~HASCYCLEXIT; 466 for ( arcp = nlp -> parents; arcp; arcp = arcp -> arc_parentlist ) { 467 nlp -> parentcnt += 1; 468 if ( arcp -> arc_parentp -> cycleno != cycleno ) 469 nlp -> flags |= HASCYCLEXIT; 470 } 471 } 472 if ( size <= cyclethreshold ) 473 continue; 474 done = FALSE; 475 cyclestack = (arctype **) calloc( size + 1 , sizeof( arctype *) ); 476 if ( cyclestack == NULL ) 477 errx( 1, "no room for %zu bytes of cycle stack" , 478 ( size + 1 ) * sizeof( arctype * ) ); 479 # ifdef DEBUG 480 if ( debug & BREAKCYCLE ) { 481 printf( "[cycleanalyze] starting cycle %d of %d, size %d\n" , 482 cycleno , ncycle , size ); 483 } 484 # endif /* DEBUG */ 485 for ( nlp = cyclenl[ cycleno ] . cnext ; nlp ; nlp = nlp -> cnext ) { 486 stkp = &cyclestack[0]; 487 nlp -> flags |= CYCLEHEAD; 488 ret = descend ( nlp , cyclestack , stkp ); 489 nlp -> flags &= ~CYCLEHEAD; 490 if ( ret == FALSE ) 491 break; 492 } 493 free( cyclestack ); 494 if ( cyclecnt > 0 ) { 495 compresslist(); 496 for ( clp = cyclehead ; clp ; ) { 497 endlist = &clp -> list[ clp -> size ]; 498 for ( arcpp = clp -> list ; arcpp < endlist ; arcpp++ ) 499 (*arcpp) -> arc_cyclecnt--; 500 cyclecnt--; 501 clp = clp -> next; 502 free( clp ); 503 } 504 cyclehead = 0; 505 } 506 } 507 # ifdef DEBUG 508 if ( debug & BREAKCYCLE ) { 509 printf("%s visited %d, viable %d, newcycle %d, oldcycle %d\n", 510 "[doarcs]" , visited , viable , newcycle , oldcycle); 511 } 512 # endif /* DEBUG */ 513 return( done ); 514 } 515 516 bool 517 descend(nltype *node, arctype **stkstart, arctype **stkp) 518 { 519 arctype *arcp; 520 bool ret; 521 522 for ( arcp = node -> children ; arcp ; arcp = arcp -> arc_childlist ) { 523 # ifdef DEBUG 524 visited++; 525 # endif /* DEBUG */ 526 if ( arcp -> arc_childp -> cycleno != node -> cycleno 527 || ( arcp -> arc_childp -> flags & VISITED ) 528 || ( arcp -> arc_flags & DEADARC ) ) 529 continue; 530 # ifdef DEBUG 531 viable++; 532 # endif /* DEBUG */ 533 *stkp = arcp; 534 if ( arcp -> arc_childp -> flags & CYCLEHEAD ) { 535 if ( addcycle( stkstart , stkp ) == FALSE ) 536 return( FALSE ); 537 continue; 538 } 539 arcp -> arc_childp -> flags |= VISITED; 540 ret = descend( arcp -> arc_childp , stkstart , stkp + 1 ); 541 arcp -> arc_childp -> flags &= ~VISITED; 542 if ( ret == FALSE ) 543 return( FALSE ); 544 } 545 return( TRUE ); 546 } 547 548 bool 549 addcycle(arctype **stkstart, arctype **stkend) 550 { 551 arctype **arcpp; 552 arctype **stkloc; 553 arctype **stkp; 554 arctype **endlist; 555 arctype *minarc; 556 arctype *arcp; 557 cltype *clp; 558 int size; 559 560 size = stkend - stkstart + 1; 561 if ( size <= 1 ) 562 return( TRUE ); 563 for ( arcpp = stkstart , minarc = *arcpp ; arcpp <= stkend ; arcpp++ ) { 564 if ( *arcpp > minarc ) 565 continue; 566 minarc = *arcpp; 567 stkloc = arcpp; 568 } 569 for ( clp = cyclehead ; clp ; clp = clp -> next ) { 570 if ( clp -> size != size ) 571 continue; 572 stkp = stkloc; 573 endlist = &clp -> list[ size ]; 574 for ( arcpp = clp -> list ; arcpp < endlist ; arcpp++ ) { 575 if ( *stkp++ != *arcpp ) 576 break; 577 if ( stkp > stkend ) 578 stkp = stkstart; 579 } 580 if ( arcpp == endlist ) { 581 # ifdef DEBUG 582 oldcycle++; 583 # endif /* DEBUG */ 584 return( TRUE ); 585 } 586 } 587 clp = (cltype *) 588 calloc( 1 , sizeof ( cltype ) + ( size - 1 ) * sizeof( arctype * ) ); 589 if ( clp == NULL ) { 590 warnx( "no room for %zu bytes of subcycle storage" , 591 sizeof ( cltype ) + ( size - 1 ) * sizeof( arctype * ) ); 592 return( FALSE ); 593 } 594 stkp = stkloc; 595 endlist = &clp -> list[ size ]; 596 for ( arcpp = clp -> list ; arcpp < endlist ; arcpp++ ) { 597 arcp = *arcpp = *stkp++; 598 if ( stkp > stkend ) 599 stkp = stkstart; 600 arcp -> arc_cyclecnt++; 601 if ( ( arcp -> arc_flags & ONLIST ) == 0 ) { 602 arcp -> arc_flags |= ONLIST; 603 arcp -> arc_next = archead; 604 archead = arcp; 605 } 606 } 607 clp -> size = size; 608 clp -> next = cyclehead; 609 cyclehead = clp; 610 # ifdef DEBUG 611 newcycle++; 612 if ( debug & SUBCYCLELIST ) { 613 printsubcycle( clp ); 614 } 615 # endif /* DEBUG */ 616 cyclecnt++; 617 if ( cyclecnt >= CYCLEMAX ) 618 return( FALSE ); 619 return( TRUE ); 620 } 621 622 void 623 compresslist(void) 624 { 625 cltype *clp; 626 cltype **prev; 627 arctype **arcpp; 628 arctype **endlist; 629 arctype *arcp; 630 arctype *maxarcp; 631 arctype *maxexitarcp; 632 arctype *maxwithparentarcp; 633 arctype *maxnoparentarcp; 634 int maxexitcnt; 635 int maxwithparentcnt; 636 int maxnoparentcnt; 637 # ifdef DEBUG 638 const char *type; 639 # endif /* DEBUG */ 640 641 maxexitcnt = 0; 642 maxwithparentcnt = 0; 643 maxnoparentcnt = 0; 644 for ( endlist = &archead , arcp = archead ; arcp ; ) { 645 if ( arcp -> arc_cyclecnt == 0 ) { 646 arcp -> arc_flags &= ~ONLIST; 647 *endlist = arcp -> arc_next; 648 arcp -> arc_next = 0; 649 arcp = *endlist; 650 continue; 651 } 652 if ( arcp -> arc_childp -> flags & HASCYCLEXIT ) { 653 if ( arcp -> arc_cyclecnt > maxexitcnt || 654 ( arcp -> arc_cyclecnt == maxexitcnt && 655 arcp -> arc_cyclecnt < maxexitarcp -> arc_count ) ) { 656 maxexitcnt = arcp -> arc_cyclecnt; 657 maxexitarcp = arcp; 658 } 659 } else if ( arcp -> arc_childp -> parentcnt > 1 ) { 660 if ( arcp -> arc_cyclecnt > maxwithparentcnt || 661 ( arcp -> arc_cyclecnt == maxwithparentcnt && 662 arcp -> arc_cyclecnt < maxwithparentarcp -> arc_count ) ) { 663 maxwithparentcnt = arcp -> arc_cyclecnt; 664 maxwithparentarcp = arcp; 665 } 666 } else { 667 if ( arcp -> arc_cyclecnt > maxnoparentcnt || 668 ( arcp -> arc_cyclecnt == maxnoparentcnt && 669 arcp -> arc_cyclecnt < maxnoparentarcp -> arc_count ) ) { 670 maxnoparentcnt = arcp -> arc_cyclecnt; 671 maxnoparentarcp = arcp; 672 } 673 } 674 endlist = &arcp -> arc_next; 675 arcp = arcp -> arc_next; 676 } 677 if ( maxexitcnt > 0 ) { 678 /* 679 * first choice is edge leading to node with out-of-cycle parent 680 */ 681 maxarcp = maxexitarcp; 682 # ifdef DEBUG 683 type = "exit"; 684 # endif /* DEBUG */ 685 } else if ( maxwithparentcnt > 0 ) { 686 /* 687 * second choice is edge leading to node with at least one 688 * other in-cycle parent 689 */ 690 maxarcp = maxwithparentarcp; 691 # ifdef DEBUG 692 type = "internal"; 693 # endif /* DEBUG */ 694 } else { 695 /* 696 * last choice is edge leading to node with only this arc as 697 * a parent (as it will now be orphaned) 698 */ 699 maxarcp = maxnoparentarcp; 700 # ifdef DEBUG 701 type = "orphan"; 702 # endif /* DEBUG */ 703 } 704 maxarcp -> arc_flags |= DEADARC; 705 maxarcp -> arc_childp -> parentcnt -= 1; 706 maxarcp -> arc_childp -> npropcall -= maxarcp -> arc_count; 707 # ifdef DEBUG 708 if ( debug & BREAKCYCLE ) { 709 printf( "%s delete %s arc: %s (%ld) -> %s from %u cycle(s)\n" , 710 "[compresslist]" , type , maxarcp -> arc_parentp -> name , 711 maxarcp -> arc_count , maxarcp -> arc_childp -> name , 712 maxarcp -> arc_cyclecnt ); 713 } 714 # endif /* DEBUG */ 715 printf( "\t%s to %s with %ld calls\n" , maxarcp -> arc_parentp -> name , 716 maxarcp -> arc_childp -> name , maxarcp -> arc_count ); 717 prev = &cyclehead; 718 for ( clp = cyclehead ; clp ; ) { 719 endlist = &clp -> list[ clp -> size ]; 720 for ( arcpp = clp -> list ; arcpp < endlist ; arcpp++ ) 721 if ( (*arcpp) -> arc_flags & DEADARC ) 722 break; 723 if ( arcpp == endlist ) { 724 prev = &clp -> next; 725 clp = clp -> next; 726 continue; 727 } 728 for ( arcpp = clp -> list ; arcpp < endlist ; arcpp++ ) 729 (*arcpp) -> arc_cyclecnt--; 730 cyclecnt--; 731 *prev = clp -> next; 732 clp = clp -> next; 733 free( clp ); 734 } 735 } 736 737 #ifdef DEBUG 738 void 739 printsubcycle(cltype *clp) 740 { 741 arctype **arcpp; 742 arctype **endlist; 743 744 arcpp = clp -> list; 745 printf( "%s <cycle %d>\n" , (*arcpp) -> arc_parentp -> name , 746 (*arcpp) -> arc_parentp -> cycleno ) ; 747 for ( endlist = &clp -> list[ clp -> size ]; arcpp < endlist ; arcpp++ ) 748 printf( "\t(%ld) -> %s\n" , (*arcpp) -> arc_count , 749 (*arcpp) -> arc_childp -> name ) ; 750 } 751 #endif /* DEBUG */ 752 753 void 754 cycletime(void) 755 { 756 int cycle; 757 nltype *cyclenlp; 758 nltype *childp; 759 760 for ( cycle = 1 ; cycle <= ncycle ; cycle += 1 ) { 761 cyclenlp = &cyclenl[ cycle ]; 762 for ( childp = cyclenlp -> cnext ; childp ; childp = childp -> cnext ) { 763 if ( childp -> propfraction == 0.0 ) { 764 /* 765 * all members have the same propfraction except those 766 * that were excluded with -E 767 */ 768 continue; 769 } 770 cyclenlp -> time += childp -> time; 771 } 772 cyclenlp -> propself = cyclenlp -> propfraction * cyclenlp -> time; 773 } 774 } 775 776 /* 777 * in one top to bottom pass over the topologically sorted namelist 778 * propagate: 779 * printflag as the union of parents' printflags 780 * propfraction as the sum of fractional parents' propfractions 781 * and while we're here, sum time for functions. 782 */ 783 void 784 doflags(void) 785 { 786 int index; 787 nltype *childp; 788 nltype *oldhead; 789 790 oldhead = 0; 791 for ( index = nname-1 ; index >= 0 ; index -= 1 ) { 792 childp = topsortnlp[ index ]; 793 /* 794 * if we haven't done this function or cycle, 795 * inherit things from parent. 796 * this way, we are linear in the number of arcs 797 * since we do all members of a cycle (and the cycle itself) 798 * as we hit the first member of the cycle. 799 */ 800 if ( childp -> cyclehead != oldhead ) { 801 oldhead = childp -> cyclehead; 802 inheritflags( childp ); 803 } 804 # ifdef DEBUG 805 if ( debug & PROPDEBUG ) { 806 printf( "[doflags] " ); 807 printname( childp ); 808 printf( " inherits printflag %d and propfraction %f\n" , 809 childp -> printflag , childp -> propfraction ); 810 } 811 # endif /* DEBUG */ 812 if ( ! childp -> printflag ) { 813 /* 814 * printflag is off 815 * it gets turned on by 816 * being on -f list, 817 * or there not being any -f list and not being on -e list. 818 */ 819 if ( onlist( flist , childp -> name ) 820 || ( !fflag && !onlist( elist , childp -> name ) ) ) { 821 childp -> printflag = TRUE; 822 } 823 } else { 824 /* 825 * this function has printing parents: 826 * maybe someone wants to shut it up 827 * by putting it on -e list. (but favor -f over -e) 828 */ 829 if ( ( !onlist( flist , childp -> name ) ) 830 && onlist( elist , childp -> name ) ) { 831 childp -> printflag = FALSE; 832 } 833 } 834 if ( childp -> propfraction == 0.0 ) { 835 /* 836 * no parents to pass time to. 837 * collect time from children if 838 * its on -F list, 839 * or there isn't any -F list and its not on -E list. 840 */ 841 if ( onlist( Flist , childp -> name ) 842 || ( !Fflag && !onlist( Elist , childp -> name ) ) ) { 843 childp -> propfraction = 1.0; 844 } 845 } else { 846 /* 847 * it has parents to pass time to, 848 * but maybe someone wants to shut it up 849 * by putting it on -E list. (but favor -F over -E) 850 */ 851 if ( !onlist( Flist , childp -> name ) 852 && onlist( Elist , childp -> name ) ) { 853 childp -> propfraction = 0.0; 854 } 855 } 856 childp -> propself = childp -> time * childp -> propfraction; 857 printtime += childp -> propself; 858 # ifdef DEBUG 859 if ( debug & PROPDEBUG ) { 860 printf( "[doflags] " ); 861 printname( childp ); 862 printf( " ends up with printflag %d and propfraction %f\n" , 863 childp -> printflag , childp -> propfraction ); 864 printf( "time %f propself %f printtime %f\n" , 865 childp -> time , childp -> propself , printtime ); 866 } 867 # endif /* DEBUG */ 868 } 869 } 870 871 /* 872 * check if any parent of this child 873 * (or outside parents of this cycle) 874 * have their print flags on and set the 875 * print flag of the child (cycle) appropriately. 876 * similarly, deal with propagation fractions from parents. 877 */ 878 void 879 inheritflags(nltype *childp) 880 { 881 nltype *headp; 882 arctype *arcp; 883 nltype *parentp; 884 nltype *memp; 885 886 headp = childp -> cyclehead; 887 if ( childp == headp ) { 888 /* 889 * just a regular child, check its parents 890 */ 891 childp -> printflag = FALSE; 892 childp -> propfraction = 0.0; 893 for (arcp = childp -> parents ; arcp ; arcp = arcp -> arc_parentlist) { 894 parentp = arcp -> arc_parentp; 895 if ( childp == parentp ) { 896 continue; 897 } 898 childp -> printflag |= parentp -> printflag; 899 /* 900 * if the child was never actually called 901 * (e.g. this arc is static (and all others are, too)) 902 * no time propagates along this arc. 903 */ 904 if ( arcp -> arc_flags & DEADARC ) { 905 continue; 906 } 907 if ( childp -> npropcall ) { 908 childp -> propfraction += parentp -> propfraction 909 * ( ( (double) arcp -> arc_count ) 910 / ( (double) childp -> npropcall ) ); 911 } 912 } 913 } else { 914 /* 915 * its a member of a cycle, look at all parents from 916 * outside the cycle 917 */ 918 headp -> printflag = FALSE; 919 headp -> propfraction = 0.0; 920 for ( memp = headp -> cnext ; memp ; memp = memp -> cnext ) { 921 for (arcp = memp->parents ; arcp ; arcp = arcp->arc_parentlist) { 922 if ( arcp -> arc_parentp -> cyclehead == headp ) { 923 continue; 924 } 925 parentp = arcp -> arc_parentp; 926 headp -> printflag |= parentp -> printflag; 927 /* 928 * if the cycle was never actually called 929 * (e.g. this arc is static (and all others are, too)) 930 * no time propagates along this arc. 931 */ 932 if ( arcp -> arc_flags & DEADARC ) { 933 continue; 934 } 935 if ( headp -> npropcall ) { 936 headp -> propfraction += parentp -> propfraction 937 * ( ( (double) arcp -> arc_count ) 938 / ( (double) headp -> npropcall ) ); 939 } 940 } 941 } 942 for ( memp = headp ; memp ; memp = memp -> cnext ) { 943 memp -> printflag = headp -> printflag; 944 memp -> propfraction = headp -> propfraction; 945 } 946 } 947 } 948