1 /* Control flow graph manipulation code for GNU compiler. 2 Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 3 1999, 2000, 2001, 2002 Free Software Foundation, Inc. 4 5 This file is part of GCC. 6 7 GCC is free software; you can redistribute it and/or modify it under 8 the terms of the GNU General Public License as published by the Free 9 Software Foundation; either version 2, or (at your option) any later 10 version. 11 12 GCC is distributed in the hope that it will be useful, but WITHOUT ANY 13 WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 15 for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with GCC; see the file COPYING. If not, write to the Free 19 Software Foundation, 59 Temple Place - Suite 330, Boston, MA 20 02111-1307, USA. */ 21 22 /* This file contains low level functions to manipulate the CFG and 23 analyze it. All other modules should not transform the datastructure 24 directly and use abstraction instead. The file is supposed to be 25 ordered bottom-up and should not contain any code dependent on a 26 particular intermediate language (RTL or trees). 27 28 Available functionality: 29 - Initialization/deallocation 30 init_flow, clear_edges 31 - Low level basic block manipulation 32 alloc_block, expunge_block 33 - Edge manipulation 34 make_edge, make_single_succ_edge, cached_make_edge, remove_edge 35 - Low level edge redirection (without updating instruction chain) 36 redirect_edge_succ, redirect_edge_succ_nodup, redirect_edge_pred 37 - Dumping and debugging 38 dump_flow_info, debug_flow_info, dump_edge_info 39 - Allocation of AUX fields for basic blocks 40 alloc_aux_for_blocks, free_aux_for_blocks, alloc_aux_for_block 41 - clear_bb_flags 42 */ 43 44 #include "config.h" 45 #include "system.h" 46 #include "tree.h" 47 #include "rtl.h" 48 #include "hard-reg-set.h" 49 #include "basic-block.h" 50 #include "regs.h" 51 #include "flags.h" 52 #include "output.h" 53 #include "function.h" 54 #include "except.h" 55 #include "toplev.h" 56 #include "tm_p.h" 57 #include "obstack.h" 58 59 /* The obstack on which the flow graph components are allocated. */ 60 61 struct obstack flow_obstack; 62 static char *flow_firstobj; 63 64 /* Number of basic blocks in the current function. */ 65 66 int n_basic_blocks; 67 68 /* First free basic block number. */ 69 70 int last_basic_block; 71 72 /* Number of edges in the current function. */ 73 74 int n_edges; 75 76 /* First edge in the deleted edges chain. */ 77 78 edge first_deleted_edge; 79 static basic_block first_deleted_block; 80 81 /* The basic block array. */ 82 83 varray_type basic_block_info; 84 85 /* The special entry and exit blocks. */ 86 87 struct basic_block_def entry_exit_blocks[2] 88 = {{NULL, /* head */ 89 NULL, /* end */ 90 NULL, /* head_tree */ 91 NULL, /* end_tree */ 92 NULL, /* pred */ 93 NULL, /* succ */ 94 NULL, /* local_set */ 95 NULL, /* cond_local_set */ 96 NULL, /* global_live_at_start */ 97 NULL, /* global_live_at_end */ 98 NULL, /* aux */ 99 ENTRY_BLOCK, /* index */ 100 NULL, /* prev_bb */ 101 EXIT_BLOCK_PTR, /* next_bb */ 102 0, /* loop_depth */ 103 NULL, /* loop_father */ 104 0, /* count */ 105 0, /* frequency */ 106 0 /* flags */ 107 }, 108 { 109 NULL, /* head */ 110 NULL, /* end */ 111 NULL, /* head_tree */ 112 NULL, /* end_tree */ 113 NULL, /* pred */ 114 NULL, /* succ */ 115 NULL, /* local_set */ 116 NULL, /* cond_local_set */ 117 NULL, /* global_live_at_start */ 118 NULL, /* global_live_at_end */ 119 NULL, /* aux */ 120 EXIT_BLOCK, /* index */ 121 ENTRY_BLOCK_PTR, /* prev_bb */ 122 NULL, /* next_bb */ 123 0, /* loop_depth */ 124 NULL, /* loop_father */ 125 0, /* count */ 126 0, /* frequency */ 127 0 /* flags */ 128 } 129 }; 130 131 void debug_flow_info PARAMS ((void)); 132 static void free_edge PARAMS ((edge)); 133 134 /* Called once at initialization time. */ 135 136 void 137 init_flow () 138 { 139 static int initialized; 140 141 first_deleted_edge = 0; 142 first_deleted_block = 0; 143 n_edges = 0; 144 145 if (!initialized) 146 { 147 gcc_obstack_init (&flow_obstack); 148 flow_firstobj = (char *) obstack_alloc (&flow_obstack, 0); 149 initialized = 1; 150 } 151 else 152 { 153 obstack_free (&flow_obstack, flow_firstobj); 154 flow_firstobj = (char *) obstack_alloc (&flow_obstack, 0); 155 } 156 } 157 158 /* Helper function for remove_edge and clear_edges. Frees edge structure 159 without actually unlinking it from the pred/succ lists. */ 160 161 static void 162 free_edge (e) 163 edge e; 164 { 165 n_edges--; 166 memset (e, 0, sizeof *e); 167 e->succ_next = first_deleted_edge; 168 first_deleted_edge = e; 169 } 170 171 /* Free the memory associated with the edge structures. */ 172 173 void 174 clear_edges () 175 { 176 basic_block bb; 177 edge e; 178 179 FOR_EACH_BB (bb) 180 { 181 edge e = bb->succ; 182 183 while (e) 184 { 185 edge next = e->succ_next; 186 187 free_edge (e); 188 e = next; 189 } 190 191 bb->succ = NULL; 192 bb->pred = NULL; 193 } 194 195 e = ENTRY_BLOCK_PTR->succ; 196 while (e) 197 { 198 edge next = e->succ_next; 199 200 free_edge (e); 201 e = next; 202 } 203 204 EXIT_BLOCK_PTR->pred = NULL; 205 ENTRY_BLOCK_PTR->succ = NULL; 206 207 if (n_edges) 208 abort (); 209 } 210 211 /* Allocate memory for basic_block. */ 212 213 basic_block 214 alloc_block () 215 { 216 basic_block bb; 217 218 if (first_deleted_block) 219 { 220 bb = first_deleted_block; 221 first_deleted_block = (basic_block) bb->succ; 222 bb->succ = NULL; 223 } 224 else 225 { 226 bb = (basic_block) obstack_alloc (&flow_obstack, sizeof *bb); 227 memset (bb, 0, sizeof *bb); 228 } 229 return bb; 230 } 231 232 /* Link block B to chain after AFTER. */ 233 void 234 link_block (b, after) 235 basic_block b, after; 236 { 237 b->next_bb = after->next_bb; 238 b->prev_bb = after; 239 after->next_bb = b; 240 b->next_bb->prev_bb = b; 241 } 242 243 /* Unlink block B from chain. */ 244 void 245 unlink_block (b) 246 basic_block b; 247 { 248 b->next_bb->prev_bb = b->prev_bb; 249 b->prev_bb->next_bb = b->next_bb; 250 } 251 252 /* Sequentially order blocks and compact the arrays. */ 253 void 254 compact_blocks () 255 { 256 int i; 257 basic_block bb; 258 259 i = 0; 260 FOR_EACH_BB (bb) 261 { 262 BASIC_BLOCK (i) = bb; 263 bb->index = i; 264 i++; 265 } 266 267 if (i != n_basic_blocks) 268 abort (); 269 270 last_basic_block = n_basic_blocks; 271 } 272 273 274 /* Remove block B from the basic block array. */ 275 276 void 277 expunge_block (b) 278 basic_block b; 279 { 280 unlink_block (b); 281 BASIC_BLOCK (b->index) = NULL; 282 n_basic_blocks--; 283 284 /* Invalidate data to make bughunting easier. */ 285 memset (b, 0, sizeof *b); 286 b->index = -3; 287 b->succ = (edge) first_deleted_block; 288 first_deleted_block = (basic_block) b; 289 } 290 291 /* Create an edge connecting SRC and DEST with flags FLAGS. Return newly 292 created edge. Use this only if you are sure that this edge can't 293 possibly already exist. */ 294 295 edge 296 unchecked_make_edge (src, dst, flags) 297 basic_block src, dst; 298 int flags; 299 { 300 edge e; 301 302 if (first_deleted_edge) 303 { 304 e = first_deleted_edge; 305 first_deleted_edge = e->succ_next; 306 } 307 else 308 { 309 e = (edge) obstack_alloc (&flow_obstack, sizeof *e); 310 memset (e, 0, sizeof *e); 311 } 312 n_edges++; 313 314 e->succ_next = src->succ; 315 e->pred_next = dst->pred; 316 e->src = src; 317 e->dest = dst; 318 e->flags = flags; 319 320 src->succ = e; 321 dst->pred = e; 322 323 return e; 324 } 325 /* Create an edge connecting SRC and DST with FLAGS optionally using 326 edge cache CACHE. Return the new edge, NULL if already exist. */ 327 328 edge 329 cached_make_edge (edge_cache, src, dst, flags) 330 sbitmap *edge_cache; 331 basic_block src, dst; 332 int flags; 333 { 334 int use_edge_cache; 335 edge e; 336 337 /* Don't bother with edge cache for ENTRY or EXIT, if there aren't that 338 many edges to them, or we didn't allocate memory for it. */ 339 use_edge_cache = (edge_cache 340 && src != ENTRY_BLOCK_PTR && dst != EXIT_BLOCK_PTR); 341 342 /* Make sure we don't add duplicate edges. */ 343 switch (use_edge_cache) 344 { 345 default: 346 /* Quick test for non-existence of the edge. */ 347 if (! TEST_BIT (edge_cache[src->index], dst->index)) 348 break; 349 350 /* The edge exists; early exit if no work to do. */ 351 if (flags == 0) 352 return NULL; 353 354 /* FALLTHRU */ 355 case 0: 356 for (e = src->succ; e; e = e->succ_next) 357 if (e->dest == dst) 358 { 359 e->flags |= flags; 360 return NULL; 361 } 362 break; 363 } 364 365 e = unchecked_make_edge (src, dst, flags); 366 367 if (use_edge_cache) 368 SET_BIT (edge_cache[src->index], dst->index); 369 370 return e; 371 } 372 373 /* Create an edge connecting SRC and DEST with flags FLAGS. Return newly 374 created edge or NULL if already exist. */ 375 376 edge 377 make_edge (src, dest, flags) 378 basic_block src, dest; 379 int flags; 380 { 381 return cached_make_edge (NULL, src, dest, flags); 382 } 383 384 /* Create an edge connecting SRC to DEST and set probability by knowing 385 that it is the single edge leaving SRC. */ 386 387 edge 388 make_single_succ_edge (src, dest, flags) 389 basic_block src, dest; 390 int flags; 391 { 392 edge e = make_edge (src, dest, flags); 393 394 e->probability = REG_BR_PROB_BASE; 395 e->count = src->count; 396 return e; 397 } 398 399 /* This function will remove an edge from the flow graph. */ 400 401 void 402 remove_edge (e) 403 edge e; 404 { 405 edge last_pred = NULL; 406 edge last_succ = NULL; 407 edge tmp; 408 basic_block src, dest; 409 410 src = e->src; 411 dest = e->dest; 412 for (tmp = src->succ; tmp && tmp != e; tmp = tmp->succ_next) 413 last_succ = tmp; 414 415 if (!tmp) 416 abort (); 417 if (last_succ) 418 last_succ->succ_next = e->succ_next; 419 else 420 src->succ = e->succ_next; 421 422 for (tmp = dest->pred; tmp && tmp != e; tmp = tmp->pred_next) 423 last_pred = tmp; 424 425 if (!tmp) 426 abort (); 427 if (last_pred) 428 last_pred->pred_next = e->pred_next; 429 else 430 dest->pred = e->pred_next; 431 432 free_edge (e); 433 } 434 435 /* Redirect an edge's successor from one block to another. */ 436 437 void 438 redirect_edge_succ (e, new_succ) 439 edge e; 440 basic_block new_succ; 441 { 442 edge *pe; 443 444 /* Disconnect the edge from the old successor block. */ 445 for (pe = &e->dest->pred; *pe != e; pe = &(*pe)->pred_next) 446 continue; 447 *pe = (*pe)->pred_next; 448 449 /* Reconnect the edge to the new successor block. */ 450 e->pred_next = new_succ->pred; 451 new_succ->pred = e; 452 e->dest = new_succ; 453 } 454 455 /* Like previous but avoid possible duplicate edge. */ 456 457 edge 458 redirect_edge_succ_nodup (e, new_succ) 459 edge e; 460 basic_block new_succ; 461 { 462 edge s; 463 464 /* Check whether the edge is already present. */ 465 for (s = e->src->succ; s; s = s->succ_next) 466 if (s->dest == new_succ && s != e) 467 break; 468 469 if (s) 470 { 471 s->flags |= e->flags; 472 s->probability += e->probability; 473 if (s->probability > REG_BR_PROB_BASE) 474 s->probability = REG_BR_PROB_BASE; 475 s->count += e->count; 476 remove_edge (e); 477 e = s; 478 } 479 else 480 redirect_edge_succ (e, new_succ); 481 482 return e; 483 } 484 485 /* Redirect an edge's predecessor from one block to another. */ 486 487 void 488 redirect_edge_pred (e, new_pred) 489 edge e; 490 basic_block new_pred; 491 { 492 edge *pe; 493 494 /* Disconnect the edge from the old predecessor block. */ 495 for (pe = &e->src->succ; *pe != e; pe = &(*pe)->succ_next) 496 continue; 497 498 *pe = (*pe)->succ_next; 499 500 /* Reconnect the edge to the new predecessor block. */ 501 e->succ_next = new_pred->succ; 502 new_pred->succ = e; 503 e->src = new_pred; 504 } 505 506 void 507 clear_bb_flags () 508 { 509 basic_block bb; 510 511 FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, NULL, next_bb) 512 bb->flags = 0; 513 } 514 515 void 516 dump_flow_info (file) 517 FILE *file; 518 { 519 int i; 520 int max_regno = max_reg_num (); 521 basic_block bb; 522 static const char * const reg_class_names[] = REG_CLASS_NAMES; 523 524 fprintf (file, "%d registers.\n", max_regno); 525 for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++) 526 if (REG_N_REFS (i)) 527 { 528 enum reg_class class, altclass; 529 530 fprintf (file, "\nRegister %d used %d times across %d insns", 531 i, REG_N_REFS (i), REG_LIVE_LENGTH (i)); 532 if (REG_BASIC_BLOCK (i) >= 0) 533 fprintf (file, " in block %d", REG_BASIC_BLOCK (i)); 534 if (REG_N_SETS (i)) 535 fprintf (file, "; set %d time%s", REG_N_SETS (i), 536 (REG_N_SETS (i) == 1) ? "" : "s"); 537 if (regno_reg_rtx[i] != NULL && REG_USERVAR_P (regno_reg_rtx[i])) 538 fprintf (file, "; user var"); 539 if (REG_N_DEATHS (i) != 1) 540 fprintf (file, "; dies in %d places", REG_N_DEATHS (i)); 541 if (REG_N_CALLS_CROSSED (i) == 1) 542 fprintf (file, "; crosses 1 call"); 543 else if (REG_N_CALLS_CROSSED (i)) 544 fprintf (file, "; crosses %d calls", REG_N_CALLS_CROSSED (i)); 545 if (regno_reg_rtx[i] != NULL 546 && PSEUDO_REGNO_BYTES (i) != UNITS_PER_WORD) 547 fprintf (file, "; %d bytes", PSEUDO_REGNO_BYTES (i)); 548 549 class = reg_preferred_class (i); 550 altclass = reg_alternate_class (i); 551 if (class != GENERAL_REGS || altclass != ALL_REGS) 552 { 553 if (altclass == ALL_REGS || class == ALL_REGS) 554 fprintf (file, "; pref %s", reg_class_names[(int) class]); 555 else if (altclass == NO_REGS) 556 fprintf (file, "; %s or none", reg_class_names[(int) class]); 557 else 558 fprintf (file, "; pref %s, else %s", 559 reg_class_names[(int) class], 560 reg_class_names[(int) altclass]); 561 } 562 563 if (regno_reg_rtx[i] != NULL && REG_POINTER (regno_reg_rtx[i])) 564 fprintf (file, "; pointer"); 565 fprintf (file, ".\n"); 566 } 567 568 fprintf (file, "\n%d basic blocks, %d edges.\n", n_basic_blocks, n_edges); 569 FOR_EACH_BB (bb) 570 { 571 edge e; 572 int sum; 573 gcov_type lsum; 574 575 fprintf (file, "\nBasic block %d: first insn %d, last %d, ", 576 bb->index, INSN_UID (bb->head), INSN_UID (bb->end)); 577 fprintf (file, "prev %d, next %d, ", 578 bb->prev_bb->index, bb->next_bb->index); 579 fprintf (file, "loop_depth %d, count ", bb->loop_depth); 580 fprintf (file, HOST_WIDEST_INT_PRINT_DEC, bb->count); 581 fprintf (file, ", freq %i", bb->frequency); 582 if (maybe_hot_bb_p (bb)) 583 fprintf (file, ", maybe hot"); 584 if (probably_never_executed_bb_p (bb)) 585 fprintf (file, ", probably never executed"); 586 fprintf (file, ".\n"); 587 588 fprintf (file, "Predecessors: "); 589 for (e = bb->pred; e; e = e->pred_next) 590 dump_edge_info (file, e, 0); 591 592 fprintf (file, "\nSuccessors: "); 593 for (e = bb->succ; e; e = e->succ_next) 594 dump_edge_info (file, e, 1); 595 596 fprintf (file, "\nRegisters live at start:"); 597 dump_regset (bb->global_live_at_start, file); 598 599 fprintf (file, "\nRegisters live at end:"); 600 dump_regset (bb->global_live_at_end, file); 601 602 putc ('\n', file); 603 604 /* Check the consistency of profile information. We can't do that 605 in verify_flow_info, as the counts may get invalid for incompletely 606 solved graphs, later elliminating of conditionals or roundoff errors. 607 It is still practical to have them reported for debugging of simple 608 testcases. */ 609 sum = 0; 610 for (e = bb->succ; e; e = e->succ_next) 611 sum += e->probability; 612 if (bb->succ && abs (sum - REG_BR_PROB_BASE) > 100) 613 fprintf (file, "Invalid sum of outgoing probabilities %.1f%%\n", 614 sum * 100.0 / REG_BR_PROB_BASE); 615 sum = 0; 616 for (e = bb->pred; e; e = e->pred_next) 617 sum += EDGE_FREQUENCY (e); 618 if (abs (sum - bb->frequency) > 100) 619 fprintf (file, 620 "Invalid sum of incomming frequencies %i, should be %i\n", 621 sum, bb->frequency); 622 lsum = 0; 623 for (e = bb->pred; e; e = e->pred_next) 624 lsum += e->count; 625 if (lsum - bb->count > 100 || lsum - bb->count < -100) 626 fprintf (file, "Invalid sum of incomming counts %i, should be %i\n", 627 (int)lsum, (int)bb->count); 628 lsum = 0; 629 for (e = bb->succ; e; e = e->succ_next) 630 lsum += e->count; 631 if (bb->succ && (lsum - bb->count > 100 || lsum - bb->count < -100)) 632 fprintf (file, "Invalid sum of incomming counts %i, should be %i\n", 633 (int)lsum, (int)bb->count); 634 } 635 636 putc ('\n', file); 637 } 638 639 void 640 debug_flow_info () 641 { 642 dump_flow_info (stderr); 643 } 644 645 void 646 dump_edge_info (file, e, do_succ) 647 FILE *file; 648 edge e; 649 int do_succ; 650 { 651 basic_block side = (do_succ ? e->dest : e->src); 652 653 if (side == ENTRY_BLOCK_PTR) 654 fputs (" ENTRY", file); 655 else if (side == EXIT_BLOCK_PTR) 656 fputs (" EXIT", file); 657 else 658 fprintf (file, " %d", side->index); 659 660 if (e->probability) 661 fprintf (file, " [%.1f%%] ", e->probability * 100.0 / REG_BR_PROB_BASE); 662 663 if (e->count) 664 { 665 fprintf (file, " count:"); 666 fprintf (file, HOST_WIDEST_INT_PRINT_DEC, e->count); 667 } 668 669 if (e->flags) 670 { 671 static const char * const bitnames[] 672 = {"fallthru", "ab", "abcall", "eh", "fake", "dfs_back", "can_fallthru"}; 673 int comma = 0; 674 int i, flags = e->flags; 675 676 fputs (" (", file); 677 for (i = 0; flags; i++) 678 if (flags & (1 << i)) 679 { 680 flags &= ~(1 << i); 681 682 if (comma) 683 fputc (',', file); 684 if (i < (int) ARRAY_SIZE (bitnames)) 685 fputs (bitnames[i], file); 686 else 687 fprintf (file, "%d", i); 688 comma = 1; 689 } 690 691 fputc (')', file); 692 } 693 } 694 695 /* Simple routines to easily allocate AUX fields of basic blocks. */ 696 697 static struct obstack block_aux_obstack; 698 static void *first_block_aux_obj = 0; 699 static struct obstack edge_aux_obstack; 700 static void *first_edge_aux_obj = 0; 701 702 /* Allocate a memory block of SIZE as BB->aux. The obstack must 703 be first initialized by alloc_aux_for_blocks. */ 704 705 inline void 706 alloc_aux_for_block (bb, size) 707 basic_block bb; 708 int size; 709 { 710 /* Verify that aux field is clear. */ 711 if (bb->aux || !first_block_aux_obj) 712 abort (); 713 bb->aux = obstack_alloc (&block_aux_obstack, size); 714 memset (bb->aux, 0, size); 715 } 716 717 /* Initialize the block_aux_obstack and if SIZE is nonzero, call 718 alloc_aux_for_block for each basic block. */ 719 720 void 721 alloc_aux_for_blocks (size) 722 int size; 723 { 724 static int initialized; 725 726 if (!initialized) 727 { 728 gcc_obstack_init (&block_aux_obstack); 729 initialized = 1; 730 } 731 732 /* Check whether AUX data are still allocated. */ 733 else if (first_block_aux_obj) 734 abort (); 735 first_block_aux_obj = (char *) obstack_alloc (&block_aux_obstack, 0); 736 if (size) 737 { 738 basic_block bb; 739 740 FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, NULL, next_bb) 741 alloc_aux_for_block (bb, size); 742 } 743 } 744 745 /* Clear AUX pointers of all blocks. */ 746 747 void 748 clear_aux_for_blocks () 749 { 750 basic_block bb; 751 752 FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, NULL, next_bb) 753 bb->aux = NULL; 754 } 755 756 /* Free data allocated in block_aux_obstack and clear AUX pointers 757 of all blocks. */ 758 759 void 760 free_aux_for_blocks () 761 { 762 if (!first_block_aux_obj) 763 abort (); 764 obstack_free (&block_aux_obstack, first_block_aux_obj); 765 first_block_aux_obj = NULL; 766 767 clear_aux_for_blocks (); 768 } 769 770 /* Allocate a memory edge of SIZE as BB->aux. The obstack must 771 be first initialized by alloc_aux_for_edges. */ 772 773 inline void 774 alloc_aux_for_edge (e, size) 775 edge e; 776 int size; 777 { 778 /* Verify that aux field is clear. */ 779 if (e->aux || !first_edge_aux_obj) 780 abort (); 781 e->aux = obstack_alloc (&edge_aux_obstack, size); 782 memset (e->aux, 0, size); 783 } 784 785 /* Initialize the edge_aux_obstack and if SIZE is nonzero, call 786 alloc_aux_for_edge for each basic edge. */ 787 788 void 789 alloc_aux_for_edges (size) 790 int size; 791 { 792 static int initialized; 793 794 if (!initialized) 795 { 796 gcc_obstack_init (&edge_aux_obstack); 797 initialized = 1; 798 } 799 800 /* Check whether AUX data are still allocated. */ 801 else if (first_edge_aux_obj) 802 abort (); 803 804 first_edge_aux_obj = (char *) obstack_alloc (&edge_aux_obstack, 0); 805 if (size) 806 { 807 basic_block bb; 808 809 FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, EXIT_BLOCK_PTR, next_bb) 810 { 811 edge e; 812 813 for (e = bb->succ; e; e = e->succ_next) 814 alloc_aux_for_edge (e, size); 815 } 816 } 817 } 818 819 /* Clear AUX pointers of all edges. */ 820 821 void 822 clear_aux_for_edges () 823 { 824 basic_block bb; 825 edge e; 826 827 FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, EXIT_BLOCK_PTR, next_bb) 828 { 829 for (e = bb->succ; e; e = e->succ_next) 830 e->aux = NULL; 831 } 832 } 833 834 /* Free data allocated in edge_aux_obstack and clear AUX pointers 835 of all edges. */ 836 837 void 838 free_aux_for_edges () 839 { 840 if (!first_edge_aux_obj) 841 abort (); 842 obstack_free (&edge_aux_obstack, first_edge_aux_obj); 843 first_edge_aux_obj = NULL; 844 845 clear_aux_for_edges (); 846 } 847