cfg.c 18.7 KB
Newer Older
1 2
/* Control flow graph manipulation code for GNU compiler.
   Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
3
   1999, 2000, 2001, 2002 Free Software Foundation, Inc.
4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21

This file is part of GCC.

GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 2, or (at your option) any later
version.

GCC is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
for more details.

You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING.  If not, write to the Free
Software Foundation, 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA.  */

22 23 24 25 26
/* This file contains low level functions to manipulate the CFG and
   analyze it.  All other modules should not transform the datastructure
   directly and use abstraction instead.  The file is supposed to be
   ordered bottom-up and should not contain any code dependent on a
   particular intermediate language (RTL or trees).
27 28 29 30

   Available functionality:
     - Initialization/deallocation
	 init_flow, clear_edges
31 32
     - Low level basic block manipulation
	 alloc_block, expunge_block
33
     - Edge manipulation
34
	 make_edge, make_single_succ_edge, cached_make_edge, remove_edge
35 36
	 - Low level edge redirection (without updating instruction chain)
	     redirect_edge_succ, redirect_edge_succ_nodup, redirect_edge_pred
37
     - Dumping and debugging
38 39 40
	 dump_flow_info, debug_flow_info, dump_edge_info
     - Allocation of AUX fields for basic blocks
	 alloc_aux_for_blocks, free_aux_for_blocks, alloc_aux_for_block
41
     - clear_bb_flags
42 43 44 45
 */

#include "config.h"
#include "system.h"
46 47
#include "coretypes.h"
#include "tm.h"
48 49 50 51 52 53 54 55 56 57
#include "tree.h"
#include "rtl.h"
#include "hard-reg-set.h"
#include "basic-block.h"
#include "regs.h"
#include "flags.h"
#include "output.h"
#include "function.h"
#include "except.h"
#include "toplev.h"
58
#include "tm_p.h"
59
#include "obstack.h"
60
#include "alloc-pool.h"
61 62 63 64 65 66

/* The obstack on which the flow graph components are allocated.  */

struct obstack flow_obstack;
static char *flow_firstobj;

67 68 69 70 71 72 73 74
/* Basic block object pool.  */

static alloc_pool bb_pool;

/* Edge object pool.  */

static alloc_pool edge_pool;

75 76
/* Number of basic blocks in the current function.  */

77
int n_basic_blocks;
78

79 80 81 82
/* First free basic block number.  */

int last_basic_block;

83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105
/* Number of edges in the current function.  */

int n_edges;

/* The basic block array.  */

varray_type basic_block_info;

/* The special entry and exit blocks.  */

struct basic_block_def entry_exit_blocks[2]
= {{NULL,			/* head */
    NULL,			/* end */
    NULL,			/* head_tree */
    NULL,			/* end_tree */
    NULL,			/* pred */
    NULL,			/* succ */
    NULL,			/* local_set */
    NULL,			/* cond_local_set */
    NULL,			/* global_live_at_start */
    NULL,			/* global_live_at_end */
    NULL,			/* aux */
    ENTRY_BLOCK,		/* index */
106 107
    NULL,			/* prev_bb */
    EXIT_BLOCK_PTR,		/* next_bb */
108
    0,				/* loop_depth */
109
    NULL,                       /* loop_father */
110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126
    0,				/* count */
    0,				/* frequency */
    0				/* flags */
  },
  {
    NULL,			/* head */
    NULL,			/* end */
    NULL,			/* head_tree */
    NULL,			/* end_tree */
    NULL,			/* pred */
    NULL,			/* succ */
    NULL,			/* local_set */
    NULL,			/* cond_local_set */
    NULL,			/* global_live_at_start */
    NULL,			/* global_live_at_end */
    NULL,			/* aux */
    EXIT_BLOCK,			/* index */
127 128
    ENTRY_BLOCK_PTR,		/* prev_bb */
    NULL,			/* next_bb */
129
    0,				/* loop_depth */
130
    NULL,                       /* loop_father */
131 132 133 134 135 136 137
    0,				/* count */
    0,				/* frequency */
    0				/* flags */
  }
};

void debug_flow_info			PARAMS ((void));
138
static void free_edge			PARAMS ((edge));
139

140
/* Called once at initialization time.  */
141 142 143 144 145 146

void
init_flow ()
{
  static int initialized;

147 148
  n_edges = 0;

149 150 151 152 153 154 155 156
  if (!initialized)
    {
      gcc_obstack_init (&flow_obstack);
      flow_firstobj = (char *) obstack_alloc (&flow_obstack, 0);
      initialized = 1;
    }
  else
    {
157 158
      free_alloc_pool (bb_pool);
      free_alloc_pool (edge_pool);
159 160 161
      obstack_free (&flow_obstack, flow_firstobj);
      flow_firstobj = (char *) obstack_alloc (&flow_obstack, 0);
    }
162 163 164 165
  bb_pool = create_alloc_pool ("Basic block pool", 
			       sizeof (struct basic_block_def), 100);
  edge_pool = create_alloc_pool ("Edge pool",
			       sizeof (struct edge_def), 100);
166 167
}

168 169 170 171 172 173 174 175
/* Helper function for remove_edge and clear_edges.  Frees edge structure
   without actually unlinking it from the pred/succ lists.  */

static void
free_edge (e)
     edge e;
{
  n_edges--;
176
  pool_free (edge_pool, e);
177 178
}

179 180 181 182 183
/* Free the memory associated with the edge structures.  */

void
clear_edges ()
{
184
  basic_block bb;
185
  edge e;
186

187
  FOR_EACH_BB (bb)
188
    {
189
      edge e = bb->succ;
190

191 192 193 194 195 196 197
      while (e)
	{
	  edge next = e->succ_next;

	  free_edge (e);
	  e = next;
	}
198

199 200
      bb->succ = NULL;
      bb->pred = NULL;
201 202
    }

203 204 205 206 207 208 209 210
  e = ENTRY_BLOCK_PTR->succ;
  while (e)
    {
      edge next = e->succ_next;

      free_edge (e);
      e = next;
    }
211

212 213
  EXIT_BLOCK_PTR->pred = NULL;
  ENTRY_BLOCK_PTR->succ = NULL;
214

215 216
  if (n_edges)
    abort ();
217 218
}

219
/* Allocate memory for basic_block.  */
220

221
basic_block
222
alloc_block ()
223 224
{
  basic_block bb;
225 226
  bb = pool_alloc (bb_pool);
  memset (bb, 0, sizeof (*bb));
227
  return bb;
228 229
}

230 231 232 233 234 235 236 237 238 239
/* Link block B to chain after AFTER.  */
void
link_block (b, after)
     basic_block b, after;
{
  b->next_bb = after->next_bb;
  b->prev_bb = after;
  after->next_bb = b;
  b->next_bb->prev_bb = b;
}
240

241 242 243 244 245 246 247 248
/* Unlink block B from chain.  */
void
unlink_block (b)
     basic_block b;
{
  b->next_bb->prev_bb = b->prev_bb;
  b->prev_bb->next_bb = b->next_bb;
}
249

250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271
/* Sequentially order blocks and compact the arrays.  */
void
compact_blocks ()
{
  int i;
  basic_block bb;
 
  i = 0;
  FOR_EACH_BB (bb)
    {
      BASIC_BLOCK (i) = bb;
      bb->index = i;
      i++;
    }

  if (i != n_basic_blocks)
    abort ();

  last_basic_block = n_basic_blocks;
}

/* Remove block B from the basic block array.  */
272

273
void
274
expunge_block (b)
275 276
     basic_block b;
{
277
  unlink_block (b);
278 279
  BASIC_BLOCK (b->index) = NULL;
  n_basic_blocks--;
280
  pool_free (bb_pool, b);
281
}
282

283
/* Create an edge connecting SRC and DST with FLAGS optionally using
284
   edge cache CACHE.  Return the new edge, NULL if already exist.  */
285

286 287
edge
cached_make_edge (edge_cache, src, dst, flags)
288 289 290 291 292 293 294
     sbitmap *edge_cache;
     basic_block src, dst;
     int flags;
{
  int use_edge_cache;
  edge e;

295 296
  /* Don't bother with edge cache for ENTRY or EXIT, if there aren't that
     many edges to them, or we didn't allocate memory for it.  */
297
  use_edge_cache = (edge_cache
298
		    && src != ENTRY_BLOCK_PTR && dst != EXIT_BLOCK_PTR);
299 300 301 302 303

  /* Make sure we don't add duplicate edges.  */
  switch (use_edge_cache)
    {
    default:
304
      /* Quick test for non-existence of the edge.  */
305
      if (! TEST_BIT (edge_cache[src->index], dst->index))
306 307 308 309
	break;

      /* The edge exists; early exit if no work to do.  */
      if (flags == 0)
310
	return NULL;
311 312 313 314 315 316 317

      /* FALLTHRU */
    case 0:
      for (e = src->succ; e; e = e->succ_next)
	if (e->dest == dst)
	  {
	    e->flags |= flags;
318
	    return NULL;
319 320 321
	  }
      break;
    }
322 323 324 325
  
  
  e = pool_alloc (edge_pool);
  memset (e, 0, sizeof (*e));
326 327 328 329 330 331 332 333 334 335 336 337
  n_edges++;

  e->succ_next = src->succ;
  e->pred_next = dst->pred;
  e->src = src;
  e->dest = dst;
  e->flags = flags;

  src->succ = e;
  dst->pred = e;

  if (use_edge_cache)
338
    SET_BIT (edge_cache[src->index], dst->index);
339 340 341 342 343 344 345 346 347 348 349 350 351 352 353

  return e;
}

/* Create an edge connecting SRC and DEST with flags FLAGS.  Return newly
   created edge or NULL if already exist.  */

edge
make_edge (src, dest, flags)
     basic_block src, dest;
     int flags;
{
  return cached_make_edge (NULL, src, dest, flags);
}

354
/* Create an edge connecting SRC to DEST and set probability by knowing
355 356 357 358 359 360 361 362 363 364 365 366
   that it is the single edge leaving SRC.  */

edge
make_single_succ_edge (src, dest, flags)
     basic_block src, dest;
     int flags;
{
  edge e = make_edge (src, dest, flags);

  e->probability = REG_BR_PROB_BASE;
  e->count = src->count;
  return e;
367 368 369 370 371 372 373 374 375 376 377 378
}

/* This function will remove an edge from the flow graph.  */

void
remove_edge (e)
     edge e;
{
  edge last_pred = NULL;
  edge last_succ = NULL;
  edge tmp;
  basic_block src, dest;
379

380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401
  src = e->src;
  dest = e->dest;
  for (tmp = src->succ; tmp && tmp != e; tmp = tmp->succ_next)
    last_succ = tmp;

  if (!tmp)
    abort ();
  if (last_succ)
    last_succ->succ_next = e->succ_next;
  else
    src->succ = e->succ_next;

  for (tmp = dest->pred; tmp && tmp != e; tmp = tmp->pred_next)
    last_pred = tmp;

  if (!tmp)
    abort ();
  if (last_pred)
    last_pred->pred_next = e->pred_next;
  else
    dest->pred = e->pred_next;

402
  free_edge (e);
403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424
}

/* Redirect an edge's successor from one block to another.  */

void
redirect_edge_succ (e, new_succ)
     edge e;
     basic_block new_succ;
{
  edge *pe;

  /* Disconnect the edge from the old successor block.  */
  for (pe = &e->dest->pred; *pe != e; pe = &(*pe)->pred_next)
    continue;
  *pe = (*pe)->pred_next;

  /* Reconnect the edge to the new successor block.  */
  e->pred_next = new_succ->pred;
  new_succ->pred = e;
  e->dest = new_succ;
}

425
/* Like previous but avoid possible duplicate edge.  */
426 427 428 429 430 431 432

edge
redirect_edge_succ_nodup (e, new_succ)
     edge e;
     basic_block new_succ;
{
  edge s;
433

434 435 436 437
  /* Check whether the edge is already present.  */
  for (s = e->src->succ; s; s = s->succ_next)
    if (s->dest == new_succ && s != e)
      break;
438

439 440 441 442
  if (s)
    {
      s->flags |= e->flags;
      s->probability += e->probability;
443 444
      if (s->probability > REG_BR_PROB_BASE)
	s->probability = REG_BR_PROB_BASE;
445 446 447 448 449 450
      s->count += e->count;
      remove_edge (e);
      e = s;
    }
  else
    redirect_edge_succ (e, new_succ);
451

452 453 454 455 456 457 458 459 460 461 462 463 464 465 466
  return e;
}

/* Redirect an edge's predecessor from one block to another.  */

void
redirect_edge_pred (e, new_pred)
     edge e;
     basic_block new_pred;
{
  edge *pe;

  /* Disconnect the edge from the old predecessor block.  */
  for (pe = &e->src->succ; *pe != e; pe = &(*pe)->succ_next)
    continue;
467

468 469 470 471 472 473 474
  *pe = (*pe)->succ_next;

  /* Reconnect the edge to the new predecessor block.  */
  e->succ_next = new_pred->succ;
  new_pred->succ = e;
  e->src = new_pred;
}
475 476 477 478

void
clear_bb_flags ()
{
479 480 481 482
  basic_block bb;

  FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, NULL, next_bb)
    bb->flags = 0;
483
}
484

485 486 487
void
dump_flow_info (file)
     FILE *file;
488
{
489
  int i;
490
  basic_block bb;
491 492 493 494 495 496 497
  static const char * const reg_class_names[] = REG_CLASS_NAMES;

  fprintf (file, "%d registers.\n", max_regno);
  for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++)
    if (REG_N_REFS (i))
      {
	enum reg_class class, altclass;
498

499 500 501 502 503 504 505
	fprintf (file, "\nRegister %d used %d times across %d insns",
		 i, REG_N_REFS (i), REG_LIVE_LENGTH (i));
	if (REG_BASIC_BLOCK (i) >= 0)
	  fprintf (file, " in block %d", REG_BASIC_BLOCK (i));
	if (REG_N_SETS (i))
	  fprintf (file, "; set %d time%s", REG_N_SETS (i),
		   (REG_N_SETS (i) == 1) ? "" : "s");
506
	if (regno_reg_rtx[i] != NULL && REG_USERVAR_P (regno_reg_rtx[i]))
507 508 509 510 511 512 513
	  fprintf (file, "; user var");
	if (REG_N_DEATHS (i) != 1)
	  fprintf (file, "; dies in %d places", REG_N_DEATHS (i));
	if (REG_N_CALLS_CROSSED (i) == 1)
	  fprintf (file, "; crosses 1 call");
	else if (REG_N_CALLS_CROSSED (i))
	  fprintf (file, "; crosses %d calls", REG_N_CALLS_CROSSED (i));
514 515
	if (regno_reg_rtx[i] != NULL
	    && PSEUDO_REGNO_BYTES (i) != UNITS_PER_WORD)
516
	  fprintf (file, "; %d bytes", PSEUDO_REGNO_BYTES (i));
517

518 519 520 521 522 523 524 525 526 527 528 529 530
	class = reg_preferred_class (i);
	altclass = reg_alternate_class (i);
	if (class != GENERAL_REGS || altclass != ALL_REGS)
	  {
	    if (altclass == ALL_REGS || class == ALL_REGS)
	      fprintf (file, "; pref %s", reg_class_names[(int) class]);
	    else if (altclass == NO_REGS)
	      fprintf (file, "; %s or none", reg_class_names[(int) class]);
	    else
	      fprintf (file, "; pref %s, else %s",
		       reg_class_names[(int) class],
		       reg_class_names[(int) altclass]);
	  }
531

532
	if (regno_reg_rtx[i] != NULL && REG_POINTER (regno_reg_rtx[i]))
533 534 535 536
	  fprintf (file, "; pointer");
	fprintf (file, ".\n");
      }

537
  fprintf (file, "\n%d basic blocks, %d edges.\n", n_basic_blocks, n_edges);
538
  FOR_EACH_BB (bb)
539
    {
540
      edge e;
541 542
      int sum;
      gcov_type lsum;
543

544
      fprintf (file, "\nBasic block %d: first insn %d, last %d, ",
545
	       bb->index, INSN_UID (bb->head), INSN_UID (bb->end));
546 547
      fprintf (file, "prev %d, next %d, ",
	       bb->prev_bb->index, bb->next_bb->index);
548 549
      fprintf (file, "loop_depth %d, count ", bb->loop_depth);
      fprintf (file, HOST_WIDEST_INT_PRINT_DEC, bb->count);
550 551 552 553 554
      fprintf (file, ", freq %i", bb->frequency);
      if (maybe_hot_bb_p (bb))
	fprintf (file, ", maybe hot");
      if (probably_never_executed_bb_p (bb))
	fprintf (file, ", probably never executed");
555
      fprintf (file, ".\n");
556

557 558 559
      fprintf (file, "Predecessors: ");
      for (e = bb->pred; e; e = e->pred_next)
	dump_edge_info (file, e, 0);
560

561 562 563
      fprintf (file, "\nSuccessors: ");
      for (e = bb->succ; e; e = e->succ_next)
	dump_edge_info (file, e, 1);
564

565 566
      fprintf (file, "\nRegisters live at start:");
      dump_regset (bb->global_live_at_start, file);
567

568 569
      fprintf (file, "\nRegisters live at end:");
      dump_regset (bb->global_live_at_end, file);
570

571
      putc ('\n', file);
572 573 574

      /* Check the consistency of profile information.  We can't do that
	 in verify_flow_info, as the counts may get invalid for incompletely
575
	 solved graphs, later eliminating of conditionals or roundoff errors.
576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602
	 It is still practical to have them reported for debugging of simple
	 testcases.  */
      sum = 0;
      for (e = bb->succ; e; e = e->succ_next)
	sum += e->probability;
      if (bb->succ && abs (sum - REG_BR_PROB_BASE) > 100)
	fprintf (file, "Invalid sum of outgoing probabilities %.1f%%\n",
		 sum * 100.0 / REG_BR_PROB_BASE);
      sum = 0;
      for (e = bb->pred; e; e = e->pred_next)
	sum += EDGE_FREQUENCY (e);
      if (abs (sum - bb->frequency) > 100)
	fprintf (file,
		 "Invalid sum of incomming frequencies %i, should be %i\n",
		 sum, bb->frequency);
      lsum = 0;
      for (e = bb->pred; e; e = e->pred_next)
	lsum += e->count;
      if (lsum - bb->count > 100 || lsum - bb->count < -100)
	fprintf (file, "Invalid sum of incomming counts %i, should be %i\n",
		 (int)lsum, (int)bb->count);
      lsum = 0;
      for (e = bb->succ; e; e = e->succ_next)
	lsum += e->count;
      if (bb->succ && (lsum - bb->count > 100 || lsum - bb->count < -100))
	fprintf (file, "Invalid sum of incomming counts %i, should be %i\n",
		 (int)lsum, (int)bb->count);
603 604
    }

605
  putc ('\n', file);
606 607
}

608 609 610 611 612
void
debug_flow_info ()
{
  dump_flow_info (stderr);
}
613 614

void
615 616 617 618
dump_edge_info (file, e, do_succ)
     FILE *file;
     edge e;
     int do_succ;
619
{
620 621 622 623 624 625 626
  basic_block side = (do_succ ? e->dest : e->src);

  if (side == ENTRY_BLOCK_PTR)
    fputs (" ENTRY", file);
  else if (side == EXIT_BLOCK_PTR)
    fputs (" EXIT", file);
  else
627
    fprintf (file, " %d", side->index);
628 629 630

  if (e->probability)
    fprintf (file, " [%.1f%%] ", e->probability * 100.0 / REG_BR_PROB_BASE);
631

632
  if (e->count)
633
    {
634
      fprintf (file, " count:");
635
      fprintf (file, HOST_WIDEST_INT_PRINT_DEC, e->count);
636 637
    }

638
  if (e->flags)
639
    {
640
      static const char * const bitnames[]
641
	= {"fallthru", "ab", "abcall", "eh", "fake", "dfs_back", "can_fallthru"};
642 643
      int comma = 0;
      int i, flags = e->flags;
644

645
      fputs (" (", file);
646 647 648 649 650 651 652 653 654 655 656 657 658
      for (i = 0; flags; i++)
	if (flags & (1 << i))
	  {
	    flags &= ~(1 << i);

	    if (comma)
	      fputc (',', file);
	    if (i < (int) ARRAY_SIZE (bitnames))
	      fputs (bitnames[i], file);
	    else
	      fprintf (file, "%d", i);
	    comma = 1;
	  }
659

660 661 662 663
      fputc (')', file);
    }
}

664
/* Simple routines to easily allocate AUX fields of basic blocks.  */
665

666 667 668 669
static struct obstack block_aux_obstack;
static void *first_block_aux_obj = 0;
static struct obstack edge_aux_obstack;
static void *first_edge_aux_obj = 0;
670

671
/* Allocate a memory block of SIZE as BB->aux.  The obstack must
672
   be first initialized by alloc_aux_for_blocks.  */
673

674 675
inline void
alloc_aux_for_block (bb, size)
676
     basic_block bb;
677
     int size;
678
{
679 680 681 682 683
  /* Verify that aux field is clear.  */
  if (bb->aux || !first_block_aux_obj)
    abort ();
  bb->aux = obstack_alloc (&block_aux_obstack, size);
  memset (bb->aux, 0, size);
684 685
}

686 687
/* Initialize the block_aux_obstack and if SIZE is nonzero, call
   alloc_aux_for_block for each basic block.  */
688 689

void
690 691
alloc_aux_for_blocks (size)
     int size;
692
{
693
  static int initialized;
694

695
  if (!initialized)
696
    {
697 698
      gcc_obstack_init (&block_aux_obstack);
      initialized = 1;
699
    }
700

701 702 703 704 705
  /* Check whether AUX data are still allocated.  */
  else if (first_block_aux_obj)
    abort ();
  first_block_aux_obj = (char *) obstack_alloc (&block_aux_obstack, 0);
  if (size)
706
    {
707
      basic_block bb;
708

709 710
      FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, NULL, next_bb)
	alloc_aux_for_block (bb, size);
711 712
    }
}
713

714
/* Clear AUX pointers of all blocks.  */
715 716

void
717
clear_aux_for_blocks ()
718
{
719
  basic_block bb;
720

721 722
  FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, NULL, next_bb)
    bb->aux = NULL;
723 724 725 726 727 728 729 730 731 732 733
}

/* Free data allocated in block_aux_obstack and clear AUX pointers
   of all blocks.  */

void
free_aux_for_blocks ()
{
  if (!first_block_aux_obj)
    abort ();
  obstack_free (&block_aux_obstack, first_block_aux_obj);
734
  first_block_aux_obj = NULL;
735 736

  clear_aux_for_blocks ();
737
}
738

739
/* Allocate a memory edge of SIZE as BB->aux.  The obstack must
740
   be first initialized by alloc_aux_for_edges.  */
741

742 743 744 745 746 747 748 749 750 751 752
inline void
alloc_aux_for_edge (e, size)
     edge e;
     int size;
{
  /* Verify that aux field is clear.  */
  if (e->aux || !first_edge_aux_obj)
    abort ();
  e->aux = obstack_alloc (&edge_aux_obstack, size);
  memset (e->aux, 0, size);
}
753

754 755
/* Initialize the edge_aux_obstack and if SIZE is nonzero, call
   alloc_aux_for_edge for each basic edge.  */
756

757 758 759 760 761
void
alloc_aux_for_edges (size)
     int size;
{
  static int initialized;
762

763 764 765 766
  if (!initialized)
    {
      gcc_obstack_init (&edge_aux_obstack);
      initialized = 1;
767
    }
768

769 770 771
  /* Check whether AUX data are still allocated.  */
  else if (first_edge_aux_obj)
    abort ();
772

773 774
  first_edge_aux_obj = (char *) obstack_alloc (&edge_aux_obstack, 0);
  if (size)
775
    {
776 777 778
      basic_block bb;

      FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, EXIT_BLOCK_PTR, next_bb)
779
	{
780 781 782 783
	  edge e;

	  for (e = bb->succ; e; e = e->succ_next)
	    alloc_aux_for_edge (e, size);
784 785 786 787
	}
    }
}

788
/* Clear AUX pointers of all edges.  */
789 790

void
791
clear_aux_for_edges ()
792
{
793 794
  basic_block bb;
  edge e;
795

796
  FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, EXIT_BLOCK_PTR, next_bb)
797
    {
798 799
      for (e = bb->succ; e; e = e->succ_next)
	e->aux = NULL;
800
    }
801 802 803 804 805 806 807 808 809 810 811
}

/* Free data allocated in edge_aux_obstack and clear AUX pointers
   of all edges.  */

void
free_aux_for_edges ()
{
  if (!first_edge_aux_obj)
    abort ();
  obstack_free (&edge_aux_obstack, first_edge_aux_obj);
812
  first_edge_aux_obj = NULL;
813 814

  clear_aux_for_edges ();
815
}