]> oss.titaniummirror.com Git - msp430-gcc.git/blobdiff - gcc/ssa-dce.c
Imported gcc-4.4.3
[msp430-gcc.git] / gcc / ssa-dce.c
diff --git a/gcc/ssa-dce.c b/gcc/ssa-dce.c
deleted file mode 100644 (file)
index 83b4e44..0000000
+++ /dev/null
@@ -1,742 +0,0 @@
-/* Dead-code elimination pass for the GNU compiler.
-   Copyright (C) 2000, 2001, 2002 Free Software Foundation, Inc.
-   Written by Jeffrey D. Oldham <oldham@codesourcery.com>.
-
-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.  */
-
-/* Dead-code elimination is the removal of instructions which have no
-   impact on the program's output.  "Dead instructions" have no impact
-   on the program's output, while "necessary instructions" may have
-   impact on the output.
-
-   The algorithm consists of three phases:
-   1) marking as necessary all instructions known to be necessary,
-      e.g., writing a value to memory,
-   2) propagating necessary instructions, e.g., the instructions
-      giving values to operands in necessary instructions, and
-   3) removing dead instructions (except replacing dead conditionals
-      with unconditional jumps).
-
-   Side Effects:
-   The last step can require adding labels, deleting insns, and
-   modifying basic block structures.  Some conditional jumps may be
-   converted to unconditional jumps so the control-flow graph may be
-   out-of-date.
-
-   Edges from some infinite loops to the exit block can be added to
-   the control-flow graph, but will be removed after this pass is
-   complete.
-
-   It Does Not Perform:
-   We decided to not simultaneously perform jump optimization and dead
-   loop removal during dead-code elimination.  Thus, all jump
-   instructions originally present remain after dead-code elimination
-   but 1) unnecessary conditional jump instructions are changed to
-   unconditional jump instructions and 2) all unconditional jump
-   instructions remain.
-
-   Assumptions:
-   1) SSA has been performed.
-   2) The basic block and control-flow graph structures are accurate.
-   3) The flow graph permits constructing an edge_list.
-   4) note rtxes should be saved.
-
-   Unfinished:
-   When replacing unnecessary conditional jumps with unconditional
-   jumps, the control-flow graph is not updated.  It should be.
-
-   References:
-   Building an Optimizing Compiler
-   Robert Morgan
-   Butterworth-Heinemann, 1998
-   Section 8.9
-*/
-
-#include "config.h"
-#include "system.h"
-
-#include "rtl.h"
-#include "hard-reg-set.h"
-#include "basic-block.h"
-#include "ssa.h"
-#include "insn-config.h"
-#include "recog.h"
-#include "output.h"
-
-\f
-/* A map from blocks to the edges on which they are control dependent.  */
-typedef struct {
-  /* An dynamically allocated array.  The Nth element corresponds to
-     the block with index N + 2.  The Ith bit in the bitmap is set if
-     that block is dependent on the Ith edge.  */
-  bitmap *data;
-  /* The number of elements in the array.  */
-  int length;
-} control_dependent_block_to_edge_map_s, *control_dependent_block_to_edge_map;
-
-/* Local function prototypes.  */
-static control_dependent_block_to_edge_map control_dependent_block_to_edge_map_create
-  PARAMS((size_t num_basic_blocks));
-static void set_control_dependent_block_to_edge_map_bit
-  PARAMS ((control_dependent_block_to_edge_map c, basic_block bb,
-          int edge_index));
-static void control_dependent_block_to_edge_map_free
-  PARAMS ((control_dependent_block_to_edge_map c));
-static void find_all_control_dependences
-  PARAMS ((struct edge_list *el, int *pdom,
-          control_dependent_block_to_edge_map cdbte));
-static void find_control_dependence
-  PARAMS ((struct edge_list *el, int edge_index, int *pdom,
-          control_dependent_block_to_edge_map cdbte));
-static basic_block find_pdom
-  PARAMS ((int *pdom, basic_block block));
-static int inherently_necessary_register_1
-  PARAMS ((rtx *current_rtx, void *data));
-static int inherently_necessary_register
-  PARAMS ((rtx current_rtx));
-static int find_inherently_necessary
-  PARAMS ((rtx current_rtx));
-static int propagate_necessity_through_operand
-  PARAMS ((rtx *current_rtx, void *data));
-static void note_inherently_necessary_set
-  PARAMS ((rtx, rtx, void *));
-\f
-/* Unnecessary insns are indicated using insns' in_struct bit.  */
-
-/* Indicate INSN is dead-code; returns nothing.  */
-#define KILL_INSN(INSN)                INSN_DEAD_CODE_P(INSN) = 1
-/* Indicate INSN is necessary, i.e., not dead-code; returns nothing.  */
-#define RESURRECT_INSN(INSN)   INSN_DEAD_CODE_P(INSN) = 0
-/* Return nonzero if INSN is unnecessary.  */
-#define UNNECESSARY_P(INSN)    INSN_DEAD_CODE_P(INSN)
-static void mark_all_insn_unnecessary
-  PARAMS ((void));
-/* Execute CODE with free variable INSN for all unnecessary insns in
-   an unspecified order, producing no output.  */
-#define EXECUTE_IF_UNNECESSARY(INSN, CODE)     \
-{                                                              \
-  rtx INSN;                                                    \
-                                                               \
-  for (INSN = get_insns (); INSN != NULL_RTX; INSN = NEXT_INSN (INSN)) \
-    if (INSN_DEAD_CODE_P (INSN)) {                             \
-      CODE;                                                    \
-    }                                                          \
-}
-/* Find the label beginning block BB.  */
-static rtx find_block_label
-  PARAMS ((basic_block bb));
-/* Remove INSN, updating its basic block structure.  */
-static void delete_insn_bb
-  PARAMS ((rtx insn));
-\f
-/* Recording which blocks are control dependent on which edges.  We
-   expect each block to be control dependent on very few edges so we
-   use a bitmap for each block recording its edges.  An array holds
-   the bitmap.  Its position 0 entry holds the bitmap for block
-   INVALID_BLOCK+1 so that all blocks, including the entry and exit
-   blocks can participate in the data structure.  */
-
-/* Create a control_dependent_block_to_edge_map, given the number
-   NUM_BASIC_BLOCKS of non-entry, non-exit basic blocks, e.g.,
-   n_basic_blocks.  This memory must be released using
-   control_dependent_block_to_edge_map_free ().  */
-
-static control_dependent_block_to_edge_map
-control_dependent_block_to_edge_map_create (num_basic_blocks)
-     size_t num_basic_blocks;
-{
-  int i;
-  control_dependent_block_to_edge_map c
-    = xmalloc (sizeof (control_dependent_block_to_edge_map_s));
-  c->length = num_basic_blocks - (INVALID_BLOCK+1);
-  c->data = xmalloc ((size_t) c->length*sizeof (bitmap));
-  for (i = 0; i < c->length; ++i)
-    c->data[i] = BITMAP_XMALLOC ();
-
-  return c;
-}
-
-/* Indicate block BB is control dependent on an edge with index
-   EDGE_INDEX in the mapping C of blocks to edges on which they are
-   control-dependent.  */
-
-static void
-set_control_dependent_block_to_edge_map_bit (c, bb, edge_index)
-     control_dependent_block_to_edge_map c;
-     basic_block bb;
-     int edge_index;
-{
-  if (bb->index - (INVALID_BLOCK+1) >= c->length)
-    abort ();
-
-  bitmap_set_bit (c->data[bb->index - (INVALID_BLOCK+1)],
-                 edge_index);
-}
-
-/* Execute CODE for each edge (given number EDGE_NUMBER within the
-   CODE) for which the block containing INSN is control dependent,
-   returning no output.  CDBTE is the mapping of blocks to edges on
-   which they are control-dependent.  */
-
-#define EXECUTE_IF_CONTROL_DEPENDENT(CDBTE, INSN, EDGE_NUMBER, CODE) \
-       EXECUTE_IF_SET_IN_BITMAP \
-         (CDBTE->data[BLOCK_NUM (INSN) - (INVALID_BLOCK+1)], 0, \
-         EDGE_NUMBER, CODE)
-
-/* Destroy a control_dependent_block_to_edge_map C.  */
-
-static void
-control_dependent_block_to_edge_map_free (c)
-     control_dependent_block_to_edge_map c;
-{
-  int i;
-  for (i = 0; i < c->length; ++i)
-    BITMAP_XFREE (c->data[i]);
-  free ((PTR) c);
-}
-
-/* Record all blocks' control dependences on all edges in the edge
-   list EL, ala Morgan, Section 3.6.  The mapping PDOM of blocks to
-   their postdominators are used, and results are stored in CDBTE,
-   which should be empty.  */
-
-static void
-find_all_control_dependences (el, pdom, cdbte)
-   struct edge_list *el;
-   int *pdom;
-   control_dependent_block_to_edge_map cdbte;
-{
-  int i;
-
-  for (i = 0; i < NUM_EDGES (el); ++i)
-    find_control_dependence (el, i, pdom, cdbte);
-}
-
-/* Determine all blocks' control dependences on the given edge with
-   edge_list EL index EDGE_INDEX, ala Morgan, Section 3.6.  The
-   mapping PDOM of blocks to their postdominators are used, and
-   results are stored in CDBTE, which is assumed to be initialized
-   with zeros in each (block b', edge) position.  */
-
-static void
-find_control_dependence (el, edge_index, pdom, cdbte)
-   struct edge_list *el;
-   int edge_index;
-   int *pdom;
-   control_dependent_block_to_edge_map cdbte;
-{
-  basic_block current_block;
-  basic_block ending_block;
-
-  if (INDEX_EDGE_PRED_BB (el, edge_index) == EXIT_BLOCK_PTR)
-    abort ();
-  ending_block =
-    (INDEX_EDGE_PRED_BB (el, edge_index) == ENTRY_BLOCK_PTR)
-    ? BASIC_BLOCK (0)
-    : find_pdom (pdom, INDEX_EDGE_PRED_BB (el, edge_index));
-
-  for (current_block = INDEX_EDGE_SUCC_BB (el, edge_index);
-       current_block != ending_block && current_block != EXIT_BLOCK_PTR;
-       current_block = find_pdom (pdom, current_block))
-    {
-      set_control_dependent_block_to_edge_map_bit (cdbte,
-                                                  current_block,
-                                                  edge_index);
-    }
-}
-\f
-/* Find the immediate postdominator PDOM of the specified basic block
-   BLOCK.  This function is necessary because some blocks have
-   negative numbers.  */
-
-static basic_block
-find_pdom (pdom, block)
-     int *pdom;
-     basic_block block;
-{
-  if (!block)
-    abort ();
-  if (block->index == INVALID_BLOCK)
-    abort ();
-
-  if (block == ENTRY_BLOCK_PTR)
-    return BASIC_BLOCK (0);
-  else if (block == EXIT_BLOCK_PTR || pdom[block->index] == EXIT_BLOCK)
-    return EXIT_BLOCK_PTR;
-  else
-    return BASIC_BLOCK (pdom[block->index]);
-}
-
-/* Determine if the given CURRENT_RTX uses a hard register not
-   converted to SSA.  Returns nonzero only if it uses such a hard
-   register.  DATA is not used.
-
-   The program counter (PC) is not considered inherently necessary
-   since code should be position-independent and thus not depend on
-   particular PC values.  */
-
-static int
-inherently_necessary_register_1 (current_rtx, data)
-     rtx *current_rtx;
-     void *data ATTRIBUTE_UNUSED;
-{
-  rtx x = *current_rtx;
-
-  if (x == NULL_RTX)
-    return 0;
-  switch (GET_CODE (x))
-    {
-    case CLOBBER:
-      /* Do not traverse the rest of the clobber.  */
-      return -1;
-      break;
-    case PC:
-      return 0;
-      break;
-    case REG:
-      if (CONVERT_REGISTER_TO_SSA_P (REGNO (x)) || x == pc_rtx)
-       return 0;
-      else
-       return !0;
-      break;
-    default:
-      return 0;
-      break;
-    }
-}
-
-/* Return nonzero if the insn CURRENT_RTX is inherently necessary.  */
-
-static int
-inherently_necessary_register (current_rtx)
-     rtx current_rtx;
-{
-  return for_each_rtx (&current_rtx,
-                      &inherently_necessary_register_1, NULL);
-}
-
-
-/* Called via note_stores for each store in an insn.  Note whether
-   or not a particular store is inherently necessary.  Store a
-   nonzero value in inherently_necessary_p if such a store is found.  */
-
-static void
-note_inherently_necessary_set (dest, set, data)
-     rtx set ATTRIBUTE_UNUSED;
-     rtx dest;
-     void *data;
-{
-  int *inherently_necessary_set_p = (int *) data;
-
-  while (GET_CODE (dest) == SUBREG
-        || GET_CODE (dest) == STRICT_LOW_PART
-        || GET_CODE (dest) == ZERO_EXTRACT
-        || GET_CODE (dest) == SIGN_EXTRACT)
-    dest = XEXP (dest, 0);
-
-  if (GET_CODE (dest) == MEM
-      || GET_CODE (dest) == UNSPEC
-      || GET_CODE (dest) == UNSPEC_VOLATILE)
-    *inherently_necessary_set_p = 1;
-}
-
-/* Mark X as inherently necessary if appropriate.  For example,
-   function calls and storing values into memory are inherently
-   necessary.  This function is to be used with for_each_rtx ().
-   Return nonzero iff inherently necessary.  */
-
-static int
-find_inherently_necessary (x)
-     rtx x;
-{
-  if (x == NULL_RTX)
-    return 0;
-  else if (inherently_necessary_register (x))
-    return !0;
-  else
-    switch (GET_CODE (x))
-      {  
-      case CALL_INSN:
-      case BARRIER:
-      case PREFETCH:
-       return !0;
-      case CODE_LABEL:
-      case NOTE:
-       return 0;
-      case JUMP_INSN:
-       return JUMP_TABLE_DATA_P (x) || computed_jump_p (x) != 0;
-      case INSN:
-       {
-         int inherently_necessary_set = 0;
-         note_stores (PATTERN (x),
-                      note_inherently_necessary_set,
-                      &inherently_necessary_set);
-
-         /* If we found an inherently necessary set or an asm
-            instruction, then we consider this insn inherently
-            necessary.  */
-         return (inherently_necessary_set
-                 || GET_CODE (PATTERN (x)) == ASM_INPUT
-                 || asm_noperands (PATTERN (x)) >= 0);
-       }
-      default:
-       /* Found an impossible insn type.  */
-       abort ();
-       break;
-      }
-}
-
-/* Propagate necessity through REG and SUBREG operands of CURRENT_RTX.
-   This function is called with for_each_rtx () on necessary
-   instructions.  The DATA must be a varray of unprocessed
-   instructions.  */
-
-static int
-propagate_necessity_through_operand (current_rtx, data)
-     rtx *current_rtx;
-     void *data;
-{
-  rtx x = *current_rtx;
-  varray_type *unprocessed_instructions = (varray_type *) data;
-
-  if (x == NULL_RTX)
-    return 0;
-  switch ( GET_CODE (x))
-    {
-    case REG:
-      if (CONVERT_REGISTER_TO_SSA_P (REGNO (x)))
-       {
-         rtx insn = VARRAY_RTX (ssa_definition, REGNO (x));
-         if (insn != NULL_RTX && UNNECESSARY_P (insn))
-           {
-             RESURRECT_INSN (insn);
-             VARRAY_PUSH_RTX (*unprocessed_instructions, insn);
-           }
-       }
-      return 0;
-
-    default:
-      return 0;
-    }
-}
-
-/* Indicate all insns initially assumed to be unnecessary.  */
-
-static void
-mark_all_insn_unnecessary ()
-{
-  rtx insn;
-  for (insn = get_insns (); insn != NULL_RTX; insn = NEXT_INSN (insn))
-    KILL_INSN (insn);
-}
-
-/* Find the label beginning block BB, adding one if necessary.  */
-
-static rtx
-find_block_label (bb)
-     basic_block bb;
-{
-  rtx insn = bb->head;
-  if (LABEL_P (insn))
-    return insn;
-  else
-    {
-      rtx new_label = emit_label_before (gen_label_rtx (), insn);
-      if (insn == bb->head)
-       bb->head = new_label;
-      return new_label;
-    }
-}
-
-/* Remove INSN, updating its basic block structure.  */
-
-static void
-delete_insn_bb (insn)
-     rtx insn;
-{
-  if (!insn)
-    abort ();
-
-  /* Do not actually delete anything that is not an INSN.
-
-     We can get here because we only consider INSNs as
-     potentially necessary.  We leave it to later passes
-     to remove unnecessary notes, unused labels, etc.  */
-  if (! INSN_P (insn))
-    return;
-
-  delete_insn (insn);
-}
-\f
-/* Perform the dead-code elimination.  */
-
-void
-ssa_eliminate_dead_code ()
-{
-  int i;
-  rtx insn;
-  /* Necessary instructions with operands to explore.  */
-  varray_type unprocessed_instructions;
-  /* Map element (b,e) is nonzero if the block is control dependent on
-     edge.  "cdbte" abbreviates control dependent block to edge.  */
-  control_dependent_block_to_edge_map cdbte;
- /* Element I is the immediate postdominator of block I.  */
-  int *pdom;
-  struct edge_list *el;
-
-  int max_insn_uid = get_max_uid ();
-
-  /* Initialize the data structures.  */
-  mark_all_insn_unnecessary ();
-  VARRAY_RTX_INIT (unprocessed_instructions, 64,
-                  "unprocessed instructions");
-  cdbte = control_dependent_block_to_edge_map_create (n_basic_blocks);
-
-  /* Prepare for use of BLOCK_NUM ().  */
-  connect_infinite_loops_to_exit ();
-   /* Be careful not to clear the added edges.  */
-  compute_bb_for_insn (max_insn_uid);
-
-  /* Compute control dependence.  */
-  pdom = (int *) xmalloc (n_basic_blocks * sizeof (int));
-  for (i = 0; i < n_basic_blocks; ++i)
-    pdom[i] = INVALID_BLOCK;
-  calculate_dominance_info (pdom, NULL, CDI_POST_DOMINATORS);
-  /* Assume there is a path from each node to the exit block.  */
-  for (i = 0; i < n_basic_blocks; ++i)
-    if (pdom[i] == INVALID_BLOCK)
-      pdom[i] = EXIT_BLOCK;
-  el = create_edge_list ();
-  find_all_control_dependences (el, pdom, cdbte);
-
-  /* Find inherently necessary instructions.  */
-  for (insn = get_insns (); insn != NULL_RTX; insn = NEXT_INSN (insn))
-    if (find_inherently_necessary (insn))
-      {
-       RESURRECT_INSN (insn);
-       VARRAY_PUSH_RTX (unprocessed_instructions, insn);
-      }
-
-  /* Propagate necessity using the operands of necessary instructions.  */
-  while (VARRAY_ACTIVE_SIZE (unprocessed_instructions) > 0)
-    {
-      rtx current_instruction;
-      int edge_number;
-
-      current_instruction = VARRAY_TOP_RTX (unprocessed_instructions);
-      VARRAY_POP (unprocessed_instructions);
-
-      /* Make corresponding control dependent edges necessary.  */
-      /* Assume the only JUMP_INSN is the block's last insn.  It appears
-        that the last instruction of the program need not be a
-        JUMP_INSN.  */
-
-      if (INSN_P (current_instruction)
-         && !JUMP_TABLE_DATA_P (current_instruction))
-       {
-         /* Notes and labels contain no interesting operands.  */
-         EXECUTE_IF_CONTROL_DEPENDENT
-           (cdbte, current_instruction, edge_number,
-           {
-             rtx jump_insn = (INDEX_EDGE_PRED_BB (el, edge_number))->end;
-             if (GET_CODE (jump_insn) == JUMP_INSN
-                 && UNNECESSARY_P (jump_insn))
-               {
-                 RESURRECT_INSN (jump_insn);
-                 VARRAY_PUSH_RTX (unprocessed_instructions, jump_insn);
-               }
-           });
-
-         /* Propagate through the operands.  */
-         for_each_rtx (&current_instruction,
-                       &propagate_necessity_through_operand,
-                       (PTR) &unprocessed_instructions);
-
-         /* PHI nodes are somewhat special in that each PHI alternative
-            has data and control dependencies.  The data dependencies
-            are handled via propagate_necessity_through_operand.  We
-            handle the control dependency here.
-
-            We consider the control dependent edges leading to the
-            predecessor block associated with each PHI alternative
-            as necessary.  */
-         if (PHI_NODE_P (current_instruction))
-           {
-             rtvec phi_vec = XVEC (SET_SRC (PATTERN (current_instruction)), 0);
-             int num_elem = GET_NUM_ELEM (phi_vec);
-             int v;
-
-             for (v = num_elem - 2; v >= 0; v -= 2)
-               {
-                 basic_block bb;
-
-                 bb = BASIC_BLOCK (INTVAL (RTVEC_ELT (phi_vec, v + 1)));
-                 EXECUTE_IF_CONTROL_DEPENDENT
-                   (cdbte, bb->end, edge_number,
-                   {
-                     rtx jump_insn;
-
-                     jump_insn = (INDEX_EDGE_PRED_BB (el, edge_number))->end;
-                     if (((GET_CODE (jump_insn) == JUMP_INSN))
-                         && UNNECESSARY_P (jump_insn))
-                       {
-                         RESURRECT_INSN (jump_insn);
-                         VARRAY_PUSH_RTX (unprocessed_instructions, jump_insn);
-                       }
-                   });
-
-               }
-           }
-       }
-    }
-
-  /* Remove the unnecessary instructions.  */
-  EXECUTE_IF_UNNECESSARY (insn,
-  {
-    if (any_condjump_p (insn))
-      {
-       basic_block bb = BLOCK_FOR_INSN (insn);
-       basic_block pdom_bb = find_pdom (pdom, bb);
-       rtx lbl;
-       edge e;
-
-       /* Egad.  The immediate post dominator is the exit block.  We
-          would like to optimize this conditional jump to jump directly
-          to the exit block.  That can be difficult as we may not have
-          a suitable CODE_LABEL that allows us to fall unmolested into
-          the exit block.
-
-          So, we just delete the conditional branch by turning it into
-          a deleted note.   That is safe, but just not as optimal as
-          it could be.  */
-       if (pdom_bb == EXIT_BLOCK_PTR)
-         {
-           /* Since we're going to just delete the branch, we need
-              look at all the edges and remove all those which are not
-              a fallthru edge.  */
-           e = bb->succ;
-           while (e)
-             {
-               edge temp = e;
-
-               e = e->succ_next;
-               if ((temp->flags & EDGE_FALLTHRU) == 0)
-                 {
-                   /* We've found a non-fallthru edge, find any PHI nodes
-                      at the target and clean them up.  */
-                   if (temp->dest != EXIT_BLOCK_PTR)
-                     {
-                       rtx insn
-                         = first_insn_after_basic_block_note (temp->dest);
-
-                       while (PHI_NODE_P (insn))
-                         {
-                           remove_phi_alternative (PATTERN (insn), temp->src);
-                           insn = NEXT_INSN (insn);
-                         }
-                     }
-
-                   remove_edge (temp);
-                 }
-             }
-
-           /* Now "delete" the conditional jump.  */
-           PUT_CODE (insn, NOTE);
-           NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
-           continue;
-         }
-
-       /* We've found a conditional branch that is unnecessary.
-
-          First, remove all outgoing edges from this block, updating
-          PHI nodes as appropriate.  */
-       e = bb->succ;
-       while (e)
-         {
-           edge temp = e;
-
-           e = e->succ_next;
-
-           if (temp->flags & EDGE_ABNORMAL)
-             continue;
-
-           /* We found an edge that is not executable.  First simplify
-              the PHI nodes in the target block.  */
-           if (temp->dest != EXIT_BLOCK_PTR)
-             {
-               rtx insn = first_insn_after_basic_block_note (temp->dest);
-
-               while (PHI_NODE_P (insn))
-                 {
-                   remove_phi_alternative (PATTERN (insn), temp->src);
-                   insn = NEXT_INSN (insn);
-                 }
-             }
-
-           remove_edge (temp);
-         }
-
-       /* Create an edge from this block to the post dominator.  
-          What about the PHI nodes at the target?  */
-       make_edge (bb, pdom_bb, 0);
-
-       /* Third, transform this insn into an unconditional
-          jump to the label for the immediate postdominator.  */
-       lbl = find_block_label (pdom_bb);
-       SET_SRC (PATTERN (insn)) = gen_rtx_LABEL_REF (VOIDmode, lbl);
-       INSN_CODE (insn) = -1;
-       JUMP_LABEL (insn) = lbl;
-       LABEL_NUSES (lbl)++;
-
-       /* A barrier must follow any unconditional jump.  Barriers
-          are not in basic blocks so this must occur after
-          deleting the conditional jump.  */
-       emit_barrier_after (insn);
-      }
-    else if (!JUMP_P (insn))
-      delete_insn_bb (insn);
-  });
-  
-  /* Remove fake edges from the CFG.  */
-  remove_fake_edges ();
-
-  /* Find any blocks with no successors and ensure they are followed
-     by a BARRIER.  delete_insn has the nasty habit of deleting barriers
-     when deleting insns.  */
-  for (i = 0; i < n_basic_blocks; i++)
-    {
-      basic_block bb = BASIC_BLOCK (i);
-
-      if (bb->succ == NULL)
-       {
-         rtx next = NEXT_INSN (bb->end);
-
-         if (!next || GET_CODE (next) != BARRIER)
-           emit_barrier_after (bb->end);
-       }
-    }
-  /* Release allocated memory.  */
-  for (insn = get_insns (); insn != NULL_RTX; insn = NEXT_INSN (insn))
-    RESURRECT_INSN (insn);
-  if (VARRAY_ACTIVE_SIZE (unprocessed_instructions) != 0)
-    abort ();
-  VARRAY_FREE (unprocessed_instructions);
-  control_dependent_block_to_edge_map_free (cdbte);
-  free ((PTR) pdom);
-  free_edge_list (el);
-}