xref: /openbsd-src/gnu/usr.bin/gcc/gcc/cfg.c (revision c87b03e512fc05ed6e0222f6fb0ae86264b1d05b)
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