cfg.c 19 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 46 47 48 49 50 51 52 53 54 55
 */

#include "config.h"
#include "system.h"
#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"
56
#include "tm_p.h"
57 58 59 60 61 62 63 64 65
#include "obstack.h"

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

struct obstack flow_obstack;
static char *flow_firstobj;

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

66
int n_basic_blocks;
67

68 69 70 71
/* First free basic block number.  */

int last_basic_block;

72 73 74 75
/* Number of edges in the current function.  */

int n_edges;

76 77 78
/* First edge in the deleted edges chain.  */

edge first_deleted_edge;
79
static basic_block first_deleted_block;
80

81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99
/* 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 */
100 101
    NULL,			/* prev_bb */
    EXIT_BLOCK_PTR,		/* next_bb */
102
    0,				/* loop_depth */
103
    NULL,                       /* loop_father */
104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120
    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 */
121 122
    ENTRY_BLOCK_PTR,		/* prev_bb */
    NULL,			/* next_bb */
123
    0,				/* loop_depth */
124
    NULL,                       /* loop_father */
125 126 127 128 129 130 131
    0,				/* count */
    0,				/* frequency */
    0				/* flags */
  }
};

void debug_flow_info			PARAMS ((void));
132
static void free_edge			PARAMS ((edge));
133

134
/* Called once at initialization time.  */
135 136 137 138 139 140

void
init_flow ()
{
  static int initialized;

141
  first_deleted_edge = 0;
142
  first_deleted_block = 0;
143 144
  n_edges = 0;

145 146 147 148 149 150 151 152 153 154 155 156 157
  if (!initialized)
    {
      gcc_obstack_init (&flow_obstack);
      flow_firstobj = (char *) obstack_alloc (&flow_obstack, 0);
      initialized = 1;
    }
  else
    {
      obstack_free (&flow_obstack, flow_firstobj);
      flow_firstobj = (char *) obstack_alloc (&flow_obstack, 0);
    }
}

158 159 160 161 162 163 164 165
/* 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--;
166
  memset (e, 0, sizeof *e);
167 168 169 170
  e->succ_next = first_deleted_edge;
  first_deleted_edge = e;
}

171 172 173 174 175
/* Free the memory associated with the edge structures.  */

void
clear_edges ()
{
176
  basic_block bb;
177
  edge e;
178

179
  FOR_EACH_BB (bb)
180
    {
181
      edge e = bb->succ;
182

183 184 185 186 187 188 189
      while (e)
	{
	  edge next = e->succ_next;

	  free_edge (e);
	  e = next;
	}
190

191 192
      bb->succ = NULL;
      bb->pred = NULL;
193 194
    }

195 196 197 198 199 200 201 202
  e = ENTRY_BLOCK_PTR->succ;
  while (e)
    {
      edge next = e->succ_next;

      free_edge (e);
      e = next;
    }
203

204 205
  EXIT_BLOCK_PTR->pred = NULL;
  ENTRY_BLOCK_PTR->succ = NULL;
206

207 208
  if (n_edges)
    abort ();
209 210
}

211
/* Allocate memory for basic_block.  */
212

213
basic_block
214
alloc_block ()
215 216 217
{
  basic_block bb;

218
  if (first_deleted_block)
219
    {
220 221 222
      bb = first_deleted_block;
      first_deleted_block = (basic_block) bb->succ;
      bb->succ = NULL;
223 224 225
    }
  else
    {
226 227
      bb = (basic_block) obstack_alloc (&flow_obstack, sizeof *bb);
      memset (bb, 0, sizeof *bb);
228 229
    }
  return bb;
230 231
}

232 233 234 235 236 237 238 239 240 241
/* 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;
}
242

243 244 245 246 247 248 249 250
/* 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;
}
251

252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272
/* 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;
}

273

274
/* Remove block B from the basic block array.  */
275

276
void
277
expunge_block (b)
278 279
     basic_block b;
{
280
  unlink_block (b);
281 282
  BASIC_BLOCK (b->index) = NULL;
  n_basic_blocks--;
283

284 285 286 287 288
  /* Invalidate data to make bughunting easier.  */
  memset (b, 0, sizeof *b);
  b->index = -3;
  b->succ = (edge) first_deleted_block;
  first_deleted_block = (basic_block) b;
289
}
290

291
/* Create an edge connecting SRC and DST with FLAGS optionally using
292
   edge cache CACHE.  Return the new edge, NULL if already exist.  */
293

294 295
edge
cached_make_edge (edge_cache, src, dst, flags)
296 297 298 299 300 301 302
     sbitmap *edge_cache;
     basic_block src, dst;
     int flags;
{
  int use_edge_cache;
  edge e;

303 304
  /* 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.  */
305
  use_edge_cache = (edge_cache
306
		    && src != ENTRY_BLOCK_PTR && dst != EXIT_BLOCK_PTR);
307 308 309 310 311

  /* Make sure we don't add duplicate edges.  */
  switch (use_edge_cache)
    {
    default:
312
      /* Quick test for non-existence of the edge.  */
313
      if (! TEST_BIT (edge_cache[src->index], dst->index))
314 315 316 317
	break;

      /* The edge exists; early exit if no work to do.  */
      if (flags == 0)
318
	return NULL;
319 320 321 322 323 324 325

      /* FALLTHRU */
    case 0:
      for (e = src->succ; e; e = e->succ_next)
	if (e->dest == dst)
	  {
	    e->flags |= flags;
326
	    return NULL;
327 328 329 330
	  }
      break;
    }

331 332 333 334 335 336 337
  if (first_deleted_edge)
    {
      e = first_deleted_edge;
      first_deleted_edge = e->succ_next;
    }
  else
    {
338 339
      e = (edge) obstack_alloc (&flow_obstack, sizeof *e);
      memset (e, 0, sizeof *e);
340
    }
341 342 343 344 345 346 347 348 349 350 351 352
  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)
353
    SET_BIT (edge_cache[src->index], dst->index);
354 355 356 357 358 359 360 361 362 363 364 365 366 367 368

  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);
}

369
/* Create an edge connecting SRC to DEST and set probability by knowing
370 371 372 373 374 375 376 377 378 379 380 381
   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;
382 383 384 385 386 387 388 389 390 391 392 393
}

/* 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;
394

395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416
  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;

417
  free_edge (e);
418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439
}

/* 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;
}

440
/* Like previous but avoid possible duplicate edge.  */
441 442 443 444 445 446 447

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

449 450 451 452
  /* 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;
453

454 455 456 457
  if (s)
    {
      s->flags |= e->flags;
      s->probability += e->probability;
458 459
      if (s->probability > REG_BR_PROB_BASE)
	s->probability = REG_BR_PROB_BASE;
460 461 462 463 464 465
      s->count += e->count;
      remove_edge (e);
      e = s;
    }
  else
    redirect_edge_succ (e, new_succ);
466

467 468 469 470 471 472 473 474 475 476 477 478 479 480 481
  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;
482

483 484 485 486 487 488 489
  *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;
}
490 491 492 493

void
clear_bb_flags ()
{
494 495 496 497
  basic_block bb;

  FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, NULL, next_bb)
    bb->flags = 0;
498
}
499

500 501 502
void
dump_flow_info (file)
     FILE *file;
503
{
504
  int i;
505
  basic_block bb;
506 507 508 509 510 511 512
  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;
513

514 515 516 517 518 519 520
	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");
521
	if (regno_reg_rtx[i] != NULL && REG_USERVAR_P (regno_reg_rtx[i]))
522 523 524 525 526 527 528
	  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));
529 530
	if (regno_reg_rtx[i] != NULL
	    && PSEUDO_REGNO_BYTES (i) != UNITS_PER_WORD)
531
	  fprintf (file, "; %d bytes", PSEUDO_REGNO_BYTES (i));
532

533 534 535 536 537 538 539 540 541 542 543 544 545
	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]);
	  }
546

547
	if (regno_reg_rtx[i] != NULL && REG_POINTER (regno_reg_rtx[i]))
548 549 550 551
	  fprintf (file, "; pointer");
	fprintf (file, ".\n");
      }

552
  fprintf (file, "\n%d basic blocks, %d edges.\n", n_basic_blocks, n_edges);
553
  FOR_EACH_BB (bb)
554
    {
555
      edge e;
556 557
      int sum;
      gcov_type lsum;
558

559
      fprintf (file, "\nBasic block %d: first insn %d, last %d, ",
560
	       bb->index, INSN_UID (bb->head), INSN_UID (bb->end));
561 562
      fprintf (file, "prev %d, next %d, ",
	       bb->prev_bb->index, bb->next_bb->index);
563 564
      fprintf (file, "loop_depth %d, count ", bb->loop_depth);
      fprintf (file, HOST_WIDEST_INT_PRINT_DEC, bb->count);
565 566 567 568 569
      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");
570
      fprintf (file, ".\n");
571

572 573 574
      fprintf (file, "Predecessors: ");
      for (e = bb->pred; e; e = e->pred_next)
	dump_edge_info (file, e, 0);
575

576 577 578
      fprintf (file, "\nSuccessors: ");
      for (e = bb->succ; e; e = e->succ_next)
	dump_edge_info (file, e, 1);
579

580 581
      fprintf (file, "\nRegisters live at start:");
      dump_regset (bb->global_live_at_start, file);
582

583 584
      fprintf (file, "\nRegisters live at end:");
      dump_regset (bb->global_live_at_end, file);
585

586
      putc ('\n', file);
587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617

      /* Check the consistency of profile information.  We can't do that
	 in verify_flow_info, as the counts may get invalid for incompletely
	 solved graphs, later elliminating of conditionals or roundoff errors.
	 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);
618 619
    }

620
  putc ('\n', file);
621 622
}

623 624 625 626 627
void
debug_flow_info ()
{
  dump_flow_info (stderr);
}
628 629

void
630 631 632 633
dump_edge_info (file, e, do_succ)
     FILE *file;
     edge e;
     int do_succ;
634
{
635 636 637 638 639 640 641
  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
642
    fprintf (file, " %d", side->index);
643 644 645

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

647
  if (e->count)
648
    {
649
      fprintf (file, " count:");
650
      fprintf (file, HOST_WIDEST_INT_PRINT_DEC, e->count);
651 652
    }

653
  if (e->flags)
654
    {
655
      static const char * const bitnames[]
656
	= {"fallthru", "ab", "abcall", "eh", "fake", "dfs_back", "can_fallthru"};
657 658
      int comma = 0;
      int i, flags = e->flags;
659

660
      fputs (" (", file);
661 662 663 664 665 666 667 668 669 670 671 672 673
      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;
	  }
674

675 676 677 678
      fputc (')', file);
    }
}

679
/* Simple routines to easily allocate AUX fields of basic blocks.  */
680

681 682 683 684
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;
685

686 687
/* Allocate an memory block of SIZE as BB->aux.  The obstack must
   be first initialized by alloc_aux_for_blocks.  */
688

689 690
inline void
alloc_aux_for_block (bb, size)
691
     basic_block bb;
692
     int size;
693
{
694 695 696 697 698
  /* 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);
699 700
}

701 702
/* Initialize the block_aux_obstack and if SIZE is nonzero, call
   alloc_aux_for_block for each basic block.  */
703 704

void
705 706
alloc_aux_for_blocks (size)
     int size;
707
{
708
  static int initialized;
709

710
  if (!initialized)
711
    {
712 713
      gcc_obstack_init (&block_aux_obstack);
      initialized = 1;
714
    }
715

716 717 718 719 720
  /* 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)
721
    {
722
      basic_block bb;
723

724 725
      FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, NULL, next_bb)
	alloc_aux_for_block (bb, size);
726 727
    }
}
728

729
/* Clear AUX pointers of all blocks.  */
730 731

void
732
clear_aux_for_blocks ()
733
{
734
  basic_block bb;
735

736 737
  FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, NULL, next_bb)
    bb->aux = NULL;
738 739 740 741 742 743 744 745 746 747 748
}

/* 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);
749
  first_block_aux_obj = NULL;
750 751

  clear_aux_for_blocks ();
752
}
753

754 755
/* Allocate an memory edge of SIZE as BB->aux.  The obstack must
   be first initialized by alloc_aux_for_edges.  */
756

757 758 759 760 761 762 763 764 765 766 767
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);
}
768

769 770
/* Initialize the edge_aux_obstack and if SIZE is nonzero, call
   alloc_aux_for_edge for each basic edge.  */
771

772 773 774 775 776
void
alloc_aux_for_edges (size)
     int size;
{
  static int initialized;
777

778 779 780 781
  if (!initialized)
    {
      gcc_obstack_init (&edge_aux_obstack);
      initialized = 1;
782
    }
783

784 785 786
  /* Check whether AUX data are still allocated.  */
  else if (first_edge_aux_obj)
    abort ();
787

788 789
  first_edge_aux_obj = (char *) obstack_alloc (&edge_aux_obstack, 0);
  if (size)
790
    {
791 792 793
      basic_block bb;

      FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, EXIT_BLOCK_PTR, next_bb)
794
	{
795 796 797 798
	  edge e;

	  for (e = bb->succ; e; e = e->succ_next)
	    alloc_aux_for_edge (e, size);
799 800 801 802
	}
    }
}

803
/* Clear AUX pointers of all edges.  */
804 805

void
806
clear_aux_for_edges ()
807
{
808 809
  basic_block bb;
  edge e;
810

811
  FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, EXIT_BLOCK_PTR, next_bb)
812
    {
813 814
      for (e = bb->succ; e; e = e->succ_next)
	e->aux = NULL;
815
    }
816 817 818 819 820 821 822 823 824 825 826
}

/* 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);
827
  first_edge_aux_obj = NULL;
828 829

  clear_aux_for_edges ();
830
}