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
init_flow()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
free_edge(e)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
clear_edges()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
alloc_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
link_block(b,after)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
unlink_block(b)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
compact_blocks()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
expunge_block(b)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
unchecked_make_edge(src,dst,flags)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
cached_make_edge(edge_cache,src,dst,flags)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
make_edge(src,dest,flags)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
make_single_succ_edge(src,dest,flags)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
remove_edge(e)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
redirect_edge_succ(e,new_succ)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
redirect_edge_succ_nodup(e,new_succ)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
redirect_edge_pred(e,new_pred)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
clear_bb_flags()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
dump_flow_info(file)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
debug_flow_info()640 debug_flow_info ()
641 {
642 dump_flow_info (stderr);
643 }
644
645 void
dump_edge_info(file,e,do_succ)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
alloc_aux_for_block(bb,size)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
alloc_aux_for_blocks(size)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
clear_aux_for_blocks()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
free_aux_for_blocks()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
alloc_aux_for_edge(e,size)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
alloc_aux_for_edges(size)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
clear_aux_for_edges()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
free_aux_for_edges()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