dce.c 22.7 KB
Newer Older
1
/* RTL dead code elimination.
2
   Copyright (C) 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
3 4 5 6 7

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
8
Software Foundation; either version 3, or (at your option) any later
9 10 11 12 13 14 15 16
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
17 18
along with GCC; see the file COPYING3.  If not see
<http://www.gnu.org/licenses/>.  */
19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44

#include "config.h"
#include "system.h"
#include "coretypes.h"
#include "hashtab.h"
#include "tm.h"
#include "rtl.h"
#include "tree.h"
#include "regs.h"
#include "hard-reg-set.h"
#include "flags.h"
#include "df.h"
#include "cselib.h"
#include "dce.h"
#include "timevar.h"
#include "tree-pass.h"
#include "dbgcnt.h"

DEF_VEC_I(int);
DEF_VEC_ALLOC_I(int,heap);


/* -------------------------------------------------------------------------
   Core mark/delete routines
   ------------------------------------------------------------------------- */

45 46
/* True if we are invoked while the df engine is running; in this case,
   we don't want to reenter it.  */
47 48 49 50 51 52
static bool df_in_progress = false;

/* Instructions that have been marked but whose dependencies have not
   yet been processed.  */
static VEC(rtx,heap) *worklist;

53 54 55 56
/* Bitmap of instructions marked as needed indexed by INSN_UID.  */
static sbitmap marked;

/* Bitmap obstacks used for block processing by the fast algorithm.  */
57 58 59 60
static bitmap_obstack dce_blocks_bitmap_obstack;
static bitmap_obstack dce_tmp_bitmap_obstack;


Richard Sandiford committed
61 62 63
/* A subroutine for which BODY is part of the instruction being tested;
   either the top-level pattern, or an element of a PARALLEL.  The
   instruction is known not to be a bare USE or CLOBBER.  */
64 65

static bool
Richard Sandiford committed
66
deletable_insn_p_1 (rtx body)
67
{
68
  switch (GET_CODE (body))
69 70 71 72 73 74 75 76 77 78 79 80
    {
    case PREFETCH:
    case TRAP_IF:
      /* The UNSPEC case was added here because the ia-64 claims that
	 USEs do not work after reload and generates UNSPECS rather
	 than USEs.  Since dce is run after reload we need to avoid
	 deleting these even if they are dead.  If it turns out that
	 USEs really do work after reload, the ia-64 should be
	 changed, and the UNSPEC case can be removed.  */
    case UNSPEC:
      return false;

Richard Sandiford committed
81
    default:
82
      if (volatile_refs_p (body))
Richard Sandiford committed
83 84 85 86 87 88 89 90 91
	return false;

      if (flag_non_call_exceptions && may_trap_p (body))
	return false;

      return true;
    }
}

92

Richard Sandiford committed
93 94 95 96 97 98 99 100 101
/* Return true if INSN is a normal instruction that can be deleted by
   the DCE pass.  */

static bool
deletable_insn_p (rtx insn, bool fast)
{
  rtx body, x;
  int i;

102 103 104 105 106 107 108
  if (CALL_P (insn)
      /* We cannot delete calls inside of the recursive dce because
	 this may cause basic blocks to be deleted and this messes up
	 the rest of the stack of optimization passes.  */
      && (!df_in_progress)
      /* We cannot delete pure or const sibling calls because it is
	 hard to see the result.  */
Kenneth Zadeck committed
109
      && (!SIBLING_CALL_P (insn))
110 111
      /* We can delete dead const or pure calls as long as they do not
         infinite loop.  */
Kenneth Zadeck committed
112 113 114 115
      && (RTL_CONST_OR_PURE_CALL_P (insn)
	  && !RTL_LOOPING_CONST_OR_PURE_CALL_P (insn)))
    return true;

Richard Sandiford committed
116 117 118 119 120 121 122 123 124
  if (!NONJUMP_INSN_P (insn))
    return false;

  body = PATTERN (insn);
  switch (GET_CODE (body))
    {
    case USE:
      return false;

125 126 127 128 129 130
    case CLOBBER:
      if (fast)
	{
	  /* A CLOBBER of a dead pseudo register serves no purpose.
	     That is not necessarily true for hard registers until
	     after reload.  */
131
	  x = XEXP (body, 0);
132 133
	  return REG_P (x) && (!HARD_REGISTER_P (x) || reload_completed);
	}
Richard Sandiford committed
134
      else
135 136 137 138 139
	/* Because of the way that use-def chains are built, it is not
	   possible to tell if the clobber is dead because it can
	   never be the target of a use-def chain.  */
	return false;

140
    case PARALLEL:
Richard Sandiford committed
141 142 143 144
      for (i = XVECLEN (body, 0) - 1; i >= 0; i--)
	if (!deletable_insn_p_1 (XVECEXP (body, 0, i)))
	  return false;
      return true;
145

146
    default:
Richard Sandiford committed
147
      return deletable_insn_p_1 (body);
148 149 150 151
    }
}


152
/* Return true if INSN has been marked as needed.  */
153 154 155 156

static inline int
marked_insn_p (rtx insn)
{
157 158 159 160
  /* Artificial defs are always needed and they do not have an insn.
     We should never see them here.  */
  gcc_assert (insn);
  return TEST_BIT (marked, INSN_UID (insn));
161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184
}


/* If INSN has not yet been marked as needed, mark it now, and add it to
   the worklist.  */

static void
mark_insn (rtx insn, bool fast)
{
  if (!marked_insn_p (insn))
    {
      if (!fast)
	VEC_safe_push (rtx, heap, worklist, insn);
      SET_BIT (marked, INSN_UID (insn));
      if (dump_file)
	fprintf (dump_file, "  Adding insn %d to worklist\n", INSN_UID (insn));
    }
}


/* A note_stores callback used by mark_nonreg_stores.  DATA is the
   instruction containing DEST.  */

static void
185
mark_nonreg_stores_1 (rtx dest, const_rtx pattern, void *data)
186 187 188 189 190 191 192 193 194 195
{
  if (GET_CODE (pattern) != CLOBBER && !REG_P (dest))
    mark_insn ((rtx) data, true);
}


/* A note_stores callback used by mark_nonreg_stores.  DATA is the
   instruction containing DEST.  */

static void
196
mark_nonreg_stores_2 (rtx dest, const_rtx pattern, void *data)
197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220
{
  if (GET_CODE (pattern) != CLOBBER && !REG_P (dest))
    mark_insn ((rtx) data, false);
}


/* Mark INSN if BODY stores to a non-register destination.  */

static void
mark_nonreg_stores (rtx body, rtx insn, bool fast)
{
  if (fast)
    note_stores (body, mark_nonreg_stores_1, insn);
  else
    note_stores (body, mark_nonreg_stores_2, insn);
}


/* Delete all REG_EQUAL notes of the registers INSN writes, to prevent
   bad dangling REG_EQUAL notes. */

static void
delete_corresponding_reg_eq_notes (rtx insn)
{
221
  df_ref *def_rec;
222 223
  for (def_rec = DF_INSN_DEFS (insn); *def_rec; def_rec++)
    {
224
      df_ref def = *def_rec;
225 226 227 228 229 230 231
      unsigned int regno = DF_REF_REGNO (def);
      /* This loop is a little tricky.  We cannot just go down the
	 chain because it is being modified by the actions in the
	 loop.  So we just get the head.  We plan to drain the list
	 anyway.  */
      while (DF_REG_EQ_USE_CHAIN (regno))
	{
232
	  df_ref eq_use = DF_REG_EQ_USE_CHAIN (regno);
233 234 235 236 237 238 239 240 241 242 243 244 245 246 247
	  rtx noted_insn = DF_REF_INSN (eq_use);
	  rtx note = find_reg_note (noted_insn, REG_EQUAL, NULL_RTX);
	  if (!note)
	    note = find_reg_note (noted_insn, REG_EQUIV, NULL_RTX);

	  /* This assert is generally triggered when someone deletes a
	     REG_EQUAL or REG_EQUIV note by hacking the list manually
	     rather than calling remove_note.  */
	  gcc_assert (note);
	  remove_note (noted_insn, note);
	}
    }
}


248
/* Delete every instruction that hasn't been marked.  */
249 250 251 252 253 254

static void
delete_unmarked_insns (void)
{
  basic_block bb;
  rtx insn, next;
255
  bool must_clean = false;
256 257 258 259 260

  FOR_EACH_BB (bb)
    FOR_BB_INSNS_SAFE (bb, insn, next)
      if (INSN_P (insn))
	{
261
	  /* Always delete no-op moves.  */
262
	  if (noop_move_p (insn))
263 264 265
	    ;

	  /* Otherwise rely only on the DCE algorithm.  */
266 267 268 269 270 271 272 273 274
	  else if (marked_insn_p (insn))
	    continue;

	  if (!dbg_cnt (dce))
	    continue;

	  if (dump_file)
	    fprintf (dump_file, "DCE: Deleting insn %d\n", INSN_UID (insn));

275 276 277
	  /* Before we delete the insn we have to delete REG_EQUAL notes
	     for the destination regs in order to avoid dangling notes.  */
	  delete_corresponding_reg_eq_notes (insn);
278

279 280 281 282 283 284
	  /* If a pure or const call is deleted, this may make the cfg
	     have unreachable blocks.  We rememeber this and call
	     delete_unreachable_blocks at the end.  */
	  if (CALL_P (insn))
	    must_clean = true;

285
	  /* Now delete the insn.  */
286 287
	  delete_insn_and_edges (insn);
	}
288 289 290 291

  /* Deleted a pure or const call.  */
  if (must_clean)
    delete_unreachable_blocks ();
292 293 294 295 296 297 298 299 300 301 302
}


/* Go through the instructions and mark those whose necessity is not
   dependent on inter-instruction information.  Make sure all other
   instructions are not marked.  */

static void
prescan_insns_for_dce (bool fast)
{
  basic_block bb;
303
  rtx insn, next;
304 305 306 307 308
  
  if (dump_file)
    fprintf (dump_file, "Finding needed instructions:\n");
  
  FOR_EACH_BB (bb)
309 310 311
    FOR_BB_INSNS_SAFE (bb, insn, next)
      if (INSN_P (insn))
	{
Steven Bosscher committed
312
	  if (deletable_insn_p (insn, fast))
313 314 315 316
	    mark_nonreg_stores (PATTERN (insn), insn, fast);
	  else
	    mark_insn (insn, fast);
	}
317 318 319 320 321 322 323 324

  if (dump_file)
    fprintf (dump_file, "Finished finding needed instructions:\n");
}


/* UD-based DSE routines. */

325
/* Mark instructions that define artificially-used registers, such as
326 327 328 329 330 331 332
   the frame pointer and the stack pointer.  */

static void
mark_artificial_uses (void)
{
  basic_block bb;
  struct df_link *defs;
333
  df_ref *use_rec;
334 335 336 337 338 339

  FOR_ALL_BB (bb)
    {
      for (use_rec = df_get_artificial_uses (bb->index); 
	   *use_rec; use_rec++)
	for (defs = DF_REF_CHAIN (*use_rec); defs; defs = defs->next)
340 341
	  if (! DF_REF_IS_ARTIFICIAL (defs->ref))
	    mark_insn (DF_REF_INSN (defs->ref), false);
342 343 344
    }
}

345

346 347 348 349 350 351
/* Mark every instruction that defines a register value that INSN uses.  */

static void
mark_reg_dependencies (rtx insn)
{
  struct df_link *defs;
352
  df_ref *use_rec;
353 354 355

  for (use_rec = DF_INSN_USES (insn); *use_rec; use_rec++)
    {
356
      df_ref use = *use_rec;
357 358 359 360 361 362 363
      if (dump_file)
	{
	  fprintf (dump_file, "Processing use of ");
	  print_simple_rtl (dump_file, DF_REF_REG (use));
	  fprintf (dump_file, " in insn %d:\n", INSN_UID (insn));
	}
      for (defs = DF_REF_CHAIN (use); defs; defs = defs->next)
364 365
	if (! DF_REF_IS_ARTIFICIAL (defs->ref))
	  mark_insn (DF_REF_INSN (defs->ref), false);
366 367 368 369
    }
}


370 371
/* Initialize global variables for a new DCE pass.  */

372
static void
373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399
init_dce (bool fast)
{
  if (!df_in_progress)
    {
      if (!fast)
	df_chain_add_problem (DF_UD_CHAIN);
      df_analyze ();
    }

  if (dump_file)
    df_dump (dump_file);

  if (fast)
    {
      bitmap_obstack_initialize (&dce_blocks_bitmap_obstack);
      bitmap_obstack_initialize (&dce_tmp_bitmap_obstack);
    }

  marked = sbitmap_alloc (get_max_uid () + 1);
  sbitmap_zero (marked);
}


/* Free the data allocated by init_dce.  */

static void
fini_dce (bool fast)
400 401
{
  sbitmap_free (marked);
402 403 404 405 406 407

  if (fast)
    {
      bitmap_obstack_release (&dce_blocks_bitmap_obstack);
      bitmap_obstack_release (&dce_tmp_bitmap_obstack);
    }
408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426
}


/* UD-chain based DCE.  */

static unsigned int
rest_of_handle_ud_dce (void)
{
  rtx insn;

  init_dce (false);

  prescan_insns_for_dce (false);
  mark_artificial_uses ();
  while (VEC_length (rtx, worklist) > 0)
    {
      insn = VEC_pop (rtx, worklist);
      mark_reg_dependencies (insn);
    }
427
  VEC_free (rtx, heap, worklist);
428

429 430 431 432 433
  /* Before any insns are deleted, we must remove the chains since
     they are not bidirectional.  */
  df_remove_problem (df_chain);
  delete_unmarked_insns ();

434
  fini_dce (false);
435 436 437 438 439 440 441
  return 0;
}


static bool
gate_ud_dce (void)
{
442 443
  return optimize > 1 && flag_dce
    && dbg_cnt (dce_ud);
444 445
}

446
struct rtl_opt_pass pass_ud_rtl_dce =
447
{
448 449
 {
  RTL_PASS,
450 451 452 453 454 455 456 457 458 459 460 461
  "dce",                                /* name */
  gate_ud_dce,                        /* gate */
  rest_of_handle_ud_dce,              /* execute */
  NULL,                                 /* sub */
  NULL,                                 /* next */
  0,                                    /* static_pass_number */
  TV_DCE,                               /* tv_id */
  0,                                    /* properties_required */
  0,                                    /* properties_provided */
  0,                                    /* properties_destroyed */
  0,                                    /* todo_flags_start */
  TODO_dump_func |
462
  TODO_df_finish | TODO_verify_rtl_sharing |
463 464
  TODO_ggc_collect                     /* todo_flags_finish */
 }
465 466
};

467

468 469 470 471
/* -------------------------------------------------------------------------
   Fast DCE functions
   ------------------------------------------------------------------------- */

472 473 474 475
/* Process basic block BB.  Return true if the live_in set has
   changed. REDO_OUT is true if the info at the bottom of the block
   needs to be recalculated before starting.  AU is the proper set of
   artificial uses. */
476 477

static bool
478
byte_dce_process_block (basic_block bb, bool redo_out, bitmap au)
479 480 481 482
{
  bitmap local_live = BITMAP_ALLOC (&dce_tmp_bitmap_obstack);
  rtx insn;
  bool block_changed;
483
  df_ref *def_rec;
484 485 486 487 488 489 490 491

  if (redo_out)
    {
      /* Need to redo the live_out set of this block if when one of
	 the succs of this block has had a change in it live in
	 set.  */
      edge e;
      edge_iterator ei;
492 493
      df_confluence_function_n con_fun_n = df_byte_lr->problem->con_fun_n;
      bitmap_clear (DF_BYTE_LR_OUT (bb));
494 495 496 497 498 499 500
      FOR_EACH_EDGE (e, ei, bb->succs)
	(*con_fun_n) (e);
    }

  if (dump_file)
    {
      fprintf (dump_file, "processing block %d live out = ", bb->index);
501
      df_print_byte_regset (dump_file, DF_BYTE_LR_OUT (bb));
502 503
    }

504 505 506 507 508 509 510 511 512 513
  bitmap_copy (local_live, DF_BYTE_LR_OUT (bb));

  df_byte_lr_simulate_artificial_refs_at_end (bb, local_live);

  FOR_BB_INSNS_REVERSE (bb, insn)
    if (INSN_P (insn))
      {
	/* The insn is needed if there is someone who uses the output.  */
	for (def_rec = DF_INSN_DEFS (insn); *def_rec; def_rec++)
	  {
514
	    df_ref def = *def_rec;
515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586
	    unsigned int last;
	    unsigned int dregno = DF_REF_REGNO (def);
	    unsigned int start = df_byte_lr_get_regno_start (dregno);
	    unsigned int len = df_byte_lr_get_regno_len (dregno);

	    unsigned int sb;
	    unsigned int lb;
	    /* This is one of the only places where DF_MM_MAY should
	       be used for defs.  Need to make sure that we are
	       checking for all of the bits that may be used.  */

	    if (!df_compute_accessed_bytes (def, DF_MM_MAY, &sb, &lb))
	      {
		start += sb;
		len = lb - sb;
	      }

	    if (bitmap_bit_p (au, dregno))
	      {
		mark_insn (insn, true);
		goto quickexit;
	      }
	    
	    last = start + len;
	    while (start < last)
	      if (bitmap_bit_p (local_live, start++))
		{
		  mark_insn (insn, true);
		  goto quickexit;
		}
	  }
	
      quickexit: 
	
	/* No matter if the instruction is needed or not, we remove
	   any regno in the defs from the live set.  */
	df_byte_lr_simulate_defs (insn, local_live);

	/* On the other hand, we do not allow the dead uses to set
	   anything in local_live.  */
	if (marked_insn_p (insn))
	  df_byte_lr_simulate_uses (insn, local_live);

	if (dump_file)
	  {
	    fprintf (dump_file, "finished processing insn %d live out = ", 
		     INSN_UID (insn));
	    df_print_byte_regset (dump_file, local_live);
	  }
      }
  
  df_byte_lr_simulate_artificial_refs_at_top (bb, local_live);

  block_changed = !bitmap_equal_p (local_live, DF_BYTE_LR_IN (bb));
  if (block_changed)
    bitmap_copy (DF_BYTE_LR_IN (bb), local_live);
  BITMAP_FREE (local_live);
  return block_changed;
}


/* Process basic block BB.  Return true if the live_in set has
   changed. REDO_OUT is true if the info at the bottom of the block
   needs to be recalculated before starting.  AU is the proper set of
   artificial uses. */

static bool
dce_process_block (basic_block bb, bool redo_out, bitmap au)
{
  bitmap local_live = BITMAP_ALLOC (&dce_tmp_bitmap_obstack);
  rtx insn;
  bool block_changed;
587
  df_ref *def_rec;
588

589
  if (redo_out)
590
    {
591 592 593 594 595 596 597 598 599
      /* Need to redo the live_out set of this block if when one of
	 the succs of this block has had a change in it live in
	 set.  */
      edge e;
      edge_iterator ei;
      df_confluence_function_n con_fun_n = df_lr->problem->con_fun_n;
      bitmap_clear (DF_LR_OUT (bb));
      FOR_EACH_EDGE (e, ei, bb->succs)
	(*con_fun_n) (e);
600 601
    }

602
  if (dump_file)
603
    {
604 605
      fprintf (dump_file, "processing block %d live out = ", bb->index);
      df_print_regset (dump_file, DF_LR_OUT (bb));
606 607
    }

608 609 610
  bitmap_copy (local_live, DF_LR_OUT (bb));

  df_simulate_artificial_refs_at_end (bb, local_live);
611

612 613 614
  FOR_BB_INSNS_REVERSE (bb, insn)
    if (INSN_P (insn))
      {
615 616 617 618 619 620 621 622 623 624
	bool needed = false;

	/* The insn is needed if there is someone who uses the output.  */
	for (def_rec = DF_INSN_DEFS (insn); *def_rec; def_rec++)
	  if (bitmap_bit_p (local_live, DF_REF_REGNO (*def_rec))
	      || bitmap_bit_p (au, DF_REF_REGNO (*def_rec)))
	    {
	      needed = true;
	      break;
	    }
625
	    
626 627
	if (needed)
	  mark_insn (insn, true);
628 629 630 631 632 633 634 635 636 637 638
	
	/* No matter if the instruction is needed or not, we remove
	   any regno in the defs from the live set.  */
	df_simulate_defs (insn, local_live);

	/* On the other hand, we do not allow the dead uses to set
	   anything in local_live.  */
	if (marked_insn_p (insn))
	  df_simulate_uses (insn, local_live);
      }
  
639
  df_simulate_artificial_refs_at_top (bb, local_live);
640 641 642 643 644 645 646 647 648

  block_changed = !bitmap_equal_p (local_live, DF_LR_IN (bb));
  if (block_changed)
    bitmap_copy (DF_LR_IN (bb), local_live);

  BITMAP_FREE (local_live);
  return block_changed;
}

649

650 651 652
/* Perform fast DCE once initialization is done.  If BYTE_LEVEL is
   true, use the byte level dce, otherwise do it at the pseudo
   level.  */
653

654
static void
655
fast_dce (bool byte_level)
656 657 658 659 660 661 662 663 664 665
{
  int *postorder = df_get_postorder (DF_BACKWARD);
  int n_blocks = df_get_n_blocks (DF_BACKWARD);
  /* The set of blocks that have been seen on this iteration.  */
  bitmap processed = BITMAP_ALLOC (&dce_blocks_bitmap_obstack);
  /* The set of blocks that need to have the out vectors reset because
     the in of one of their successors has changed.  */
  bitmap redo_out = BITMAP_ALLOC (&dce_blocks_bitmap_obstack);
  bitmap all_blocks = BITMAP_ALLOC (&dce_blocks_bitmap_obstack);
  bool global_changed = true;
666 667 668 669 670 671 672 673

  /* These regs are considered always live so if they end up dying
     because of some def, we need to bring the back again.  Calling
     df_simulate_fixup_sets has the disadvantage of calling
     bb_has_eh_pred once per insn, so we cache the information
     here.  */
  bitmap au = df->regular_block_artificial_uses;
  bitmap au_eh = df->eh_block_artificial_uses;
674
  int i;
675 676 677 678 679 680 681 682 683

  prescan_insns_for_dce (true);

  for (i = 0; i < n_blocks; i++)
    bitmap_set_bit (all_blocks, postorder[i]);

  while (global_changed)
    {
      global_changed = false;
684

685 686 687 688 689 690 691 692 693 694 695 696
      for (i = 0; i < n_blocks; i++)
	{
	  int index = postorder[i];
	  basic_block bb = BASIC_BLOCK (index);
	  bool local_changed;

	  if (index < NUM_FIXED_BLOCKS)
	    {
	      bitmap_set_bit (processed, index);
	      continue;
	    }

697 698 699 700 701 702 703 704
	  if (byte_level)
	    local_changed 
	      = byte_dce_process_block (bb, bitmap_bit_p (redo_out, index),
					  bb_has_eh_pred (bb) ? au_eh : au);
	  else
	    local_changed 
	      = dce_process_block (bb, bitmap_bit_p (redo_out, index),
				   bb_has_eh_pred (bb) ? au_eh : au);
705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739
	  bitmap_set_bit (processed, index);
	  
	  if (local_changed)
	    {
	      edge e;
	      edge_iterator ei;
	      FOR_EACH_EDGE (e, ei, bb->preds)
		if (bitmap_bit_p (processed, e->src->index))
		  /* Be tricky about when we need to iterate the
		     analysis.  We only have redo the analysis if the
		     bitmaps change at the top of a block that is the
		     entry to a loop.  */
		  global_changed = true;
		else
		  bitmap_set_bit (redo_out, e->src->index);
	    }
	}
      
      if (global_changed)
	{
	  /* Turn off the RUN_DCE flag to prevent recursive calls to
	     dce.  */
	  int old_flag = df_clear_flags (DF_LR_RUN_DCE);

	  /* So something was deleted that requires a redo.  Do it on
	     the cheap.  */
	  delete_unmarked_insns ();
	  sbitmap_zero (marked);
	  bitmap_clear (processed);
	  bitmap_clear (redo_out);
	  
	  /* We do not need to rescan any instructions.  We only need
	     to redo the dataflow equations for the blocks that had a
	     change at the top of the block.  Then we need to redo the
	     iteration.  */ 
740 741 742 743
	  if (byte_level)
	    df_analyze_problem (df_byte_lr, all_blocks, postorder, n_blocks);
	  else
	    df_analyze_problem (df_lr, all_blocks, postorder, n_blocks);
744 745 746

	  if (old_flag & DF_LR_RUN_DCE)
	    df_set_flags (DF_LR_RUN_DCE);
747

748 749 750 751 752 753 754 755 756 757 758 759
	  prescan_insns_for_dce (true);
	}
    }

  delete_unmarked_insns ();

  BITMAP_FREE (processed);
  BITMAP_FREE (redo_out);
  BITMAP_FREE (all_blocks);
}


760
/* Fast register level DCE.  */
761 762 763 764 765

static unsigned int
rest_of_handle_fast_dce (void)
{
  init_dce (true);
766 767 768 769 770 771 772 773 774 775 776 777 778 779
  fast_dce (false);
  fini_dce (true);
  return 0;
}


/* Fast byte level DCE.  */

static unsigned int
rest_of_handle_fast_byte_dce (void)
{
  df_byte_lr_add_problem ();
  init_dce (true);
  fast_dce (true);
780
  fini_dce (true);
781 782 783 784 785 786 787 788 789 790 791
  return 0;
}


/* This is an internal call that is used by the df live register
   problem to run fast dce as a side effect of creating the live
   information.  The stack is organized so that the lr problem is run,
   this pass is run, which updates the live info and the df scanning
   info, and then returns to allow the rest of the problems to be run.

   This can be called by elsewhere but it will not update the bit
792
   vectors for any other problems than LR.  */
793 794 795 796 797 798 799 800 801 802 803 804 805 806

void
run_fast_df_dce (void)
{
  if (flag_dce)
    {
      /* If dce is able to delete something, it has to happen
	 immediately.  Otherwise there will be problems handling the
	 eq_notes.  */
      enum df_changeable_flags old_flags 
	= df_clear_flags (DF_DEFER_INSN_RESCAN + DF_NO_INSN_RESCAN);
      
      df_in_progress = true;
      rest_of_handle_fast_dce ();
807 808
      df_in_progress = false;

809 810 811 812
      df_set_flags (old_flags);
    }
}

813

814 815 816 817
/* Run a fast DCE pass.  */

void
run_fast_dce (void)
818
{
819 820
  if (flag_dce)
    rest_of_handle_fast_dce ();
821 822 823
}


824 825
static bool
gate_fast_dce (void)
826
{
827 828
  return optimize > 0 && flag_dce
    && dbg_cnt (dce_fast);
829 830
}

831
struct rtl_opt_pass pass_fast_rtl_dce =
832
{
833 834
 {
  RTL_PASS,
835 836 837 838 839 840 841 842 843 844 845 846
  "dce",                                /* name */
  gate_fast_dce,                        /* gate */
  rest_of_handle_fast_dce,              /* execute */
  NULL,                                 /* sub */
  NULL,                                 /* next */
  0,                                    /* static_pass_number */
  TV_DCE,                               /* tv_id */
  0,                                    /* properties_required */
  0,                                    /* properties_provided */
  0,                                    /* properties_destroyed */
  0,                                    /* todo_flags_start */
  TODO_dump_func |
847
  TODO_df_finish | TODO_verify_rtl_sharing |
848 849
  TODO_ggc_collect                      /* todo_flags_finish */
 }
850
};
851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871

struct rtl_opt_pass pass_fast_rtl_byte_dce =
{
 {
  RTL_PASS,
  "byte-dce",                           /* name */
  gate_fast_dce,                        /* gate */
  rest_of_handle_fast_byte_dce,         /* execute */
  NULL,                                 /* sub */
  NULL,                                 /* next */
  0,                                    /* static_pass_number */
  TV_DCE,                               /* tv_id */
  0,                                    /* properties_required */
  0,                                    /* properties_provided */
  0,                                    /* properties_destroyed */
  0,                                    /* todo_flags_start */
  TODO_dump_func |
  TODO_df_finish | TODO_verify_rtl_sharing |
  TODO_ggc_collect                      /* todo_flags_finish */
 }
};