OSDN Git Service

* Makefile.in (INSTALL_CPP, UNINSTALL_CPP): Remove.
[pf3gnuchains/gcc-fork.git] / gcc / gcse.c
index 928b639..4d7c154 100644 (file)
@@ -159,6 +159,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include "output.h"
 #include "function.h"
 #include "expr.h" 
+#include "except.h"
 #include "ggc.h"
 #include "params.h"
 
@@ -540,7 +541,7 @@ static sbitmap *ae_kill, *ae_gen, *ae_in, *ae_out;
 struct null_pointer_info
 {
   /* The basic block being processed.  */
-  int current_block;
+  basic_block current_block;
   /* The first register to be handled in this pass.  */
   unsigned int min_reg;
   /* One greater than the last register to be handled in this pass.  */
@@ -696,8 +697,10 @@ static void delete_store           PARAMS ((struct ls_expr *,
                                                 basic_block));
 static void free_store_memory          PARAMS ((void));
 static void store_motion               PARAMS ((void));
+static void free_insn_expr_list_list   PARAMS ((rtx *));
 static void clear_modify_mem_tables    PARAMS ((void));
 static void free_modify_mem_tables     PARAMS ((void));
+static rtx gcse_emit_move_after                PARAMS ((rtx, rtx, rtx));
 \f
 /* Entry point for global common subexpression elimination.
    F is the first instruction in the function.  */
@@ -832,11 +835,11 @@ gcse_main (f, file)
            {
              free_modify_mem_tables ();
              modify_mem_list
-               = (rtx *) gmalloc (n_basic_blocks * sizeof (rtx));
+               = (rtx *) gmalloc (last_basic_block * sizeof (rtx));
              canon_modify_mem_list
-               = (rtx *) gmalloc (n_basic_blocks * sizeof (rtx));
-             memset ((char *) modify_mem_list, 0, n_basic_blocks * sizeof (rtx));
-             memset ((char *) canon_modify_mem_list, 0, n_basic_blocks * sizeof (rtx));
+               = (rtx *) gmalloc (last_basic_block * sizeof (rtx));
+             memset ((char *) modify_mem_list, 0, last_basic_block * sizeof (rtx));
+             memset ((char *) canon_modify_mem_list, 0, last_basic_block * sizeof (rtx));
              orig_bb_count = n_basic_blocks;
            }
          free_reg_set_mem ();
@@ -903,7 +906,8 @@ gcse_main (f, file)
   end_alias_analysis ();
   allocate_reg_info (max_reg_num (), FALSE, FALSE);
 
-  if (!optimize_size && flag_gcse_sm)
+  /* Store motion disabled until it is fixed.  */
+  if (0 && !optimize_size && flag_gcse_sm)
     store_motion ();
   /* Record where pseudo-registers are set.  */
   return run_jump_opt_after_gcse;
@@ -1016,14 +1020,14 @@ alloc_gcse_mem (f)
   reg_set_bitmap = BITMAP_XMALLOC ();
 
   /* Allocate vars to track sets of regs, memory per block.  */
-  reg_set_in_block = (sbitmap *) sbitmap_vector_alloc (n_basic_blocks,
+  reg_set_in_block = (sbitmap *) sbitmap_vector_alloc (last_basic_block,
                                                       max_gcse_regno);
   /* Allocate array to keep a list of insns which modify memory in each
      basic block.  */
-  modify_mem_list = (rtx *) gmalloc (n_basic_blocks * sizeof (rtx));
-  canon_modify_mem_list = (rtx *) gmalloc (n_basic_blocks * sizeof (rtx));
-  memset ((char *) modify_mem_list, 0, n_basic_blocks * sizeof (rtx));
-  memset ((char *) canon_modify_mem_list, 0, n_basic_blocks * sizeof (rtx));
+  modify_mem_list = (rtx *) gmalloc (last_basic_block * sizeof (rtx));
+  canon_modify_mem_list = (rtx *) gmalloc (last_basic_block * sizeof (rtx));
+  memset ((char *) modify_mem_list, 0, last_basic_block * sizeof (rtx));
+  memset ((char *) canon_modify_mem_list, 0, last_basic_block * sizeof (rtx));
   modify_mem_list_set = BITMAP_XMALLOC ();
   canon_modify_mem_list_set = BITMAP_XMALLOC ();
 }
@@ -1129,15 +1133,15 @@ compute_local_properties (transp, comp, antloc, setp)
   if (transp)
     {
       if (setp)
-       sbitmap_vector_zero (transp, n_basic_blocks);
+       sbitmap_vector_zero (transp, last_basic_block);
       else
-       sbitmap_vector_ones (transp, n_basic_blocks);
+       sbitmap_vector_ones (transp, last_basic_block);
     }
 
   if (comp)
-    sbitmap_vector_zero (comp, n_basic_blocks);
+    sbitmap_vector_zero (comp, last_basic_block);
   if (antloc)
-    sbitmap_vector_zero (antloc, n_basic_blocks);
+    sbitmap_vector_zero (antloc, last_basic_block);
 
   /* We use the same code for cprop, pre and hoisting.  For cprop
      we care about the set hash table, for pre and hoisting we
@@ -1289,13 +1293,13 @@ compute_sets (f)
 
 struct reg_avail_info
 {
-  int last_bb;
+  basic_block last_bb;
   int first_set;
   int last_set;
 };
 
 static struct reg_avail_info *reg_avail_info;
-static int current_bb;
+static basic_block current_bb;
 
 
 /* See whether X, the source of a set, is something we want to consider for
@@ -1315,6 +1319,7 @@ want_to_gcse_p (x)
     case SUBREG:
     case CONST_INT:
     case CONST_DOUBLE:
+    case CONST_VECTOR:
     case CALL:
       return 0;
 
@@ -1381,7 +1386,7 @@ oprs_unchanged_p (x, insn, avail_p)
       }
 
     case MEM:
-      if (load_killed_in_block_p (BASIC_BLOCK (current_bb), INSN_CUID (insn),
+      if (load_killed_in_block_p (current_bb, INSN_CUID (insn),
                                  x, avail_p))
        return 0;
       else
@@ -1400,6 +1405,7 @@ oprs_unchanged_p (x, insn, avail_p)
     case CONST:
     case CONST_INT:
     case CONST_DOUBLE:
+    case CONST_VECTOR:
     case SYMBOL_REF:
     case LABEL_REF:
     case ADDR_VEC:
@@ -1635,6 +1641,22 @@ hash_expr_1 (x, mode, do_not_record_p)
                 + (unsigned int) CONST_DOUBLE_HIGH (x));
       return hash;
 
+    case CONST_VECTOR:
+      {
+       int units;
+       rtx elt;
+
+       units = CONST_VECTOR_NUNITS (x);
+
+       for (i = 0; i < units; ++i)
+         {
+           elt = CONST_VECTOR_ELT (x, i);
+           hash += hash_expr_1 (elt, GET_MODE (elt), do_not_record_p);
+         }
+
+       return hash;
+      }
+
       /* Assume there is only one rtx object for any given label.  */
     case LABEL_REF:
       /* We don't hash on the address of the CODE_LABEL to avoid bootstrap
@@ -1668,7 +1690,9 @@ hash_expr_1 (x, mode, do_not_record_p)
        }
 
       hash += (unsigned int) MEM;
-      hash += MEM_ALIAS_SET (x);
+      /* We used alias set for hashing, but this is not good, since the alias
+        set may differ in -fprofile-arcs and -fbranch-probabilities compilation
+        causing the profiles to fail to match.  */
       x = XEXP (x, 0);
       goto repeat;
 
@@ -2171,6 +2195,10 @@ hash_scan_set (pat, insn, set_p)
          && regno >= FIRST_PSEUDO_REGISTER
          /* Don't GCSE something if we can't do a reg/reg copy.  */
          && can_copy_p [GET_MODE (dest)]
+         /* GCSE commonly inserts instruction after the insn.  We can't
+            do that easily for EH_REGION notes so disable GCSE on these
+            for now.  */
+         && !find_reg_note (insn, REG_EH_REGION, NULL_RTX)
          /* Is SET_SRC something we want to gcse?  */
          && want_to_gcse_p (src)
          /* Don't CSE a nop.  */
@@ -2348,7 +2376,7 @@ record_last_reg_set_info (insn, regno)
     {
       info->last_bb = current_bb;
       info->first_set = cuid;
-      SET_BIT (reg_set_in_block[current_bb], regno);
+      SET_BIT (reg_set_in_block[current_bb->index], regno);
     }
 }
 
@@ -2364,6 +2392,7 @@ canon_list_insert (dest, unused1, v_insn)
      void * v_insn;
 {
   rtx dest_addr, insn;
+  int bb;
 
   while (GET_CODE (dest) == SUBREG
       || GET_CODE (dest) == ZERO_EXTRACT
@@ -2381,12 +2410,13 @@ canon_list_insert (dest, unused1, v_insn)
   dest_addr = get_addr (XEXP (dest, 0));
   dest_addr = canon_rtx (dest_addr);
   insn = (rtx) v_insn;  
+  bb = BLOCK_NUM (insn);
 
-  canon_modify_mem_list[BLOCK_NUM (insn)] = 
-    alloc_INSN_LIST (dest_addr, canon_modify_mem_list[BLOCK_NUM (insn)]);
-  canon_modify_mem_list[BLOCK_NUM (insn)] = 
-    alloc_INSN_LIST (dest, canon_modify_mem_list[BLOCK_NUM (insn)]);
-  bitmap_set_bit (canon_modify_mem_list_set, BLOCK_NUM (insn));
+  canon_modify_mem_list[bb] = 
+    alloc_EXPR_LIST (VOIDmode, dest_addr, canon_modify_mem_list[bb]);
+  canon_modify_mem_list[bb] = 
+    alloc_EXPR_LIST (VOIDmode, dest, canon_modify_mem_list[bb]);
+  bitmap_set_bit (canon_modify_mem_list_set, bb);
 }
 
 /* Record memory modification information for INSN.  We do not actually care
@@ -2397,23 +2427,24 @@ static void
 record_last_mem_set_info (insn)
      rtx insn;
 {
+  int bb = BLOCK_NUM (insn);
+
   /* load_killed_in_block_p will handle the case of calls clobbering
      everything.  */
-  modify_mem_list[BLOCK_NUM (insn)] = 
-    alloc_INSN_LIST (insn, modify_mem_list[BLOCK_NUM (insn)]);
-  bitmap_set_bit (modify_mem_list_set, BLOCK_NUM (insn));
+  modify_mem_list[bb] = alloc_INSN_LIST (insn, modify_mem_list[bb]);
+  bitmap_set_bit (modify_mem_list_set, bb);
 
   if (GET_CODE (insn) == CALL_INSN)
     {
       /* Note that traversals of this loop (other than for free-ing)
         will break after encountering a CALL_INSN.  So, there's no
         need to insert a pair of items, as canon_list_insert does.  */
-      canon_modify_mem_list[BLOCK_NUM (insn)] = 
-        alloc_INSN_LIST (insn, canon_modify_mem_list[BLOCK_NUM (insn)]);
-      bitmap_set_bit (canon_modify_mem_list_set, BLOCK_NUM (insn));
+      canon_modify_mem_list[bb] = 
+        alloc_INSN_LIST (insn, canon_modify_mem_list[bb]);
+      bitmap_set_bit (canon_modify_mem_list_set, bb);
     }
   else
-    note_stores (PATTERN (insn), canon_list_insert, (void*) insn );
+    note_stores (PATTERN (insn), canon_list_insert, (void*) insn);
 }
 
 /* Called from compute_hash_table via note_stores to handle one
@@ -2465,7 +2496,7 @@ compute_hash_table (set_p)
      registers are set in which blocks.
      ??? This isn't needed during const/copy propagation, but it's cheap to
      compute.  Later.  */
-  sbitmap_vector_zero (reg_set_in_block, n_basic_blocks);
+  sbitmap_vector_zero (reg_set_in_block, last_basic_block);
 
   /* re-Cache any INSN_LIST nodes we have allocated.  */
   clear_modify_mem_tables ();
@@ -2474,9 +2505,9 @@ compute_hash_table (set_p)
     gmalloc (max_gcse_regno * sizeof (struct reg_avail_info));
 
   for (i = 0; i < max_gcse_regno; ++i)
-    reg_avail_info[i].last_bb = NEVER_SET;
+    reg_avail_info[i].last_bb = NULL;
 
-  for (current_bb = 0; current_bb < n_basic_blocks; current_bb++)
+  FOR_EACH_BB (current_bb)
     {
       rtx insn;
       unsigned int regno;
@@ -2487,8 +2518,8 @@ compute_hash_table (set_p)
         ??? hard-reg reg_set_in_block computation
         could be moved to compute_sets since they currently don't change.  */
 
-      for (insn = BLOCK_HEAD (current_bb);
-          insn && insn != NEXT_INSN (BLOCK_END (current_bb));
+      for (insn = current_bb->head;
+          insn && insn != NEXT_INSN (current_bb->end);
           insn = NEXT_INSN (insn))
        {
          if (! INSN_P (insn))
@@ -2516,8 +2547,8 @@ compute_hash_table (set_p)
 
       /* The next pass builds the hash table.  */
 
-      for (insn = BLOCK_HEAD (current_bb), in_libcall_block = 0;
-          insn && insn != NEXT_INSN (BLOCK_END (current_bb));
+      for (insn = current_bb->head, in_libcall_block = 0;
+          insn && insn != NEXT_INSN (current_bb->end);
           insn = NEXT_INSN (insn))
        if (INSN_P (insn))
          {
@@ -2689,6 +2720,27 @@ next_set (regno, expr)
   return expr;
 }
 
+/* Like free_INSN_LIST_list or free_EXPR_LIST_list, except that the node
+   types may be mixed.  */
+
+static void
+free_insn_expr_list_list (listp)
+     rtx *listp;
+{
+  rtx list, next;
+
+  for (list = *listp; list ; list = next)
+    {
+      next = XEXP (list, 1);
+      if (GET_CODE (list) == EXPR_LIST)
+       free_EXPR_LIST_node (list);
+      else
+       free_INSN_LIST_node (list);
+    }
+
+  *listp = NULL;
+}
+
 /* Clear canon_modify_mem_list and modify_mem_list tables.  */
 static void
 clear_modify_mem_tables ()
@@ -2696,14 +2748,13 @@ clear_modify_mem_tables ()
   int i;
 
   EXECUTE_IF_SET_IN_BITMAP
-    (canon_modify_mem_list_set, 0, i,
-     free_INSN_LIST_list (modify_mem_list + i));
-  bitmap_clear (canon_modify_mem_list_set);
+    (modify_mem_list_set, 0, i, free_INSN_LIST_list (modify_mem_list + i));
+  bitmap_clear (modify_mem_list_set);
 
   EXECUTE_IF_SET_IN_BITMAP
     (canon_modify_mem_list_set, 0, i,
-     free_INSN_LIST_list (canon_modify_mem_list + i));
-  bitmap_clear (modify_mem_list_set);
+     free_insn_expr_list_list (canon_modify_mem_list + i));
+  bitmap_clear (canon_modify_mem_list_set);
 }
 
 /* Release memory used by modify_mem_list_set and canon_modify_mem_list_set.  */
@@ -2756,6 +2807,7 @@ oprs_not_set_p (x, insn)
     case CONST:
     case CONST_INT:
     case CONST_DOUBLE:
+    case CONST_VECTOR:
     case SYMBOL_REF:
     case LABEL_REF:
     case ADDR_VEC:
@@ -2889,16 +2941,16 @@ alloc_rd_mem (n_blocks, n_insns)
      int n_blocks, n_insns;
 {
   rd_kill = (sbitmap *) sbitmap_vector_alloc (n_blocks, n_insns);
-  sbitmap_vector_zero (rd_kill, n_basic_blocks);
+  sbitmap_vector_zero (rd_kill, n_blocks);
 
   rd_gen = (sbitmap *) sbitmap_vector_alloc (n_blocks, n_insns);
-  sbitmap_vector_zero (rd_gen, n_basic_blocks);
+  sbitmap_vector_zero (rd_gen, n_blocks);
 
   reaching_defs = (sbitmap *) sbitmap_vector_alloc (n_blocks, n_insns);
-  sbitmap_vector_zero (reaching_defs, n_basic_blocks);
+  sbitmap_vector_zero (reaching_defs, n_blocks);
 
   rd_out = (sbitmap *) sbitmap_vector_alloc (n_blocks, n_insns);
-  sbitmap_vector_zero (rd_out, n_basic_blocks);
+  sbitmap_vector_zero (rd_out, n_blocks);
 }
 
 /* Free reaching def variables.  */
@@ -2932,9 +2984,10 @@ handle_rd_kill_set (insn, regno, bb)
 static void
 compute_kill_rd ()
 {
-  int bb, cuid;
+  int cuid;
   unsigned int regno;
   int i;
+  basic_block bb;
 
   /* For each block
        For each set bit in `gen' of the block (i.e each insn which
@@ -2944,9 +2997,9 @@ compute_kill_rd ()
         For each setting of regx in the linked list, which is not in
             this block
           Set the bit in `kill' corresponding to that insn.  */
-  for (bb = 0; bb < n_basic_blocks; bb++)
+  FOR_EACH_BB (bb)
     for (cuid = 0; cuid < max_cuid; cuid++)
-      if (TEST_BIT (rd_gen[bb], cuid))
+      if (TEST_BIT (rd_gen[bb->index], cuid))
        {
          rtx insn = CUID_INSN (cuid);
          rtx pat = PATTERN (insn);
@@ -2955,7 +3008,7 @@ compute_kill_rd ()
            {
              for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
                if (TEST_HARD_REG_BIT (regs_invalidated_by_call, regno))
-                 handle_rd_kill_set (insn, regno, BASIC_BLOCK (bb));
+                 handle_rd_kill_set (insn, regno, bb);
            }
 
          if (GET_CODE (pat) == PARALLEL)
@@ -2968,13 +3021,13 @@ compute_kill_rd ()
                      && GET_CODE (XEXP (XVECEXP (pat, 0, i), 0)) == REG)
                    handle_rd_kill_set (insn,
                                        REGNO (XEXP (XVECEXP (pat, 0, i), 0)),
-                                       BASIC_BLOCK (bb));
+                                       bb);
                }
            }
          else if (GET_CODE (pat) == SET && GET_CODE (SET_DEST (pat)) == REG)
            /* Each setting of this register outside of this block
               must be marked in the set of kills in this block.  */
-           handle_rd_kill_set (insn, REGNO (SET_DEST (pat)), BASIC_BLOCK (bb));
+           handle_rd_kill_set (insn, REGNO (SET_DEST (pat)), bb);
        }
 }
 
@@ -2986,21 +3039,22 @@ compute_kill_rd ()
 static void
 compute_rd ()
 {
-  int bb, changed, passes;
+  int changed, passes;
+  basic_block bb;
 
-  for (bb = 0; bb < n_basic_blocks; bb++)
-    sbitmap_copy (rd_out[bb] /*dst*/, rd_gen[bb] /*src*/);
+  FOR_EACH_BB (bb)
+    sbitmap_copy (rd_out[bb->index] /*dst*/, rd_gen[bb->index] /*src*/);
 
   passes = 0;
   changed = 1;
   while (changed)
     {
       changed = 0;
-      for (bb = 0; bb < n_basic_blocks; bb++)
+      FOR_EACH_BB (bb)
        {
-         sbitmap_union_of_preds (reaching_defs[bb], rd_out, bb);
-         changed |= sbitmap_union_of_diff (rd_out[bb], rd_gen[bb],
-                                           reaching_defs[bb], rd_kill[bb]);
+         sbitmap_union_of_preds (reaching_defs[bb->index], rd_out, bb->index);
+         changed |= sbitmap_union_of_diff_cg (rd_out[bb->index], rd_gen[bb->index],
+                                              reaching_defs[bb->index], rd_kill[bb->index]);
        }
       passes++;
     }
@@ -3018,16 +3072,16 @@ alloc_avail_expr_mem (n_blocks, n_exprs)
      int n_blocks, n_exprs;
 {
   ae_kill = (sbitmap *) sbitmap_vector_alloc (n_blocks, n_exprs);
-  sbitmap_vector_zero (ae_kill, n_basic_blocks);
+  sbitmap_vector_zero (ae_kill, n_blocks);
 
   ae_gen = (sbitmap *) sbitmap_vector_alloc (n_blocks, n_exprs);
-  sbitmap_vector_zero (ae_gen, n_basic_blocks);
+  sbitmap_vector_zero (ae_gen, n_blocks);
 
   ae_in = (sbitmap *) sbitmap_vector_alloc (n_blocks, n_exprs);
-  sbitmap_vector_zero (ae_in, n_basic_blocks);
+  sbitmap_vector_zero (ae_in, n_blocks);
 
   ae_out = (sbitmap *) sbitmap_vector_alloc (n_blocks, n_exprs);
-  sbitmap_vector_zero (ae_out, n_basic_blocks);
+  sbitmap_vector_zero (ae_out, n_blocks);
 }
 
 static void
@@ -3089,6 +3143,7 @@ expr_killed_p (x, bb)
     case CONST:
     case CONST_INT:
     case CONST_DOUBLE:
+    case CONST_VECTOR:
     case SYMBOL_REF:
     case LABEL_REF:
     case ADDR_VEC:
@@ -3126,20 +3181,20 @@ static void
 compute_ae_kill (ae_gen, ae_kill)
      sbitmap *ae_gen, *ae_kill;
 {
-  int bb;
+  basic_block bb;
   unsigned int i;
   struct expr *expr;
 
-  for (bb = 0; bb < n_basic_blocks; bb++)
+  FOR_EACH_BB (bb)
     for (i = 0; i < expr_hash_table_size; i++)
       for (expr = expr_hash_table[i]; expr; expr = expr->next_same_hash)
        {
          /* Skip EXPR if generated in this block.  */
-         if (TEST_BIT (ae_gen[bb], expr->bitmap_index))
+         if (TEST_BIT (ae_gen[bb->index], expr->bitmap_index))
            continue;
 
-         if (expr_killed_p (expr->expr, BASIC_BLOCK (bb)))
-           SET_BIT (ae_kill[bb], expr->bitmap_index);
+         if (expr_killed_p (expr->expr, bb))
+           SET_BIT (ae_kill[bb->index], expr->bitmap_index);
        }
 }
 \f
@@ -3231,7 +3286,7 @@ expr_reaches_here_p (occr, expr, bb, check_self_loop)
      int check_self_loop;
 {
   int rval;
-  char *visited = (char *) xcalloc (n_basic_blocks, 1);
+  char *visited = (char *) xcalloc (last_basic_block, 1);
 
   rval = expr_reaches_here_p_work (occr, expr, bb, check_self_loop, visited);
   
@@ -3555,20 +3610,24 @@ handle_avail_expr (insn, expr)
 static int
 classic_gcse ()
 {
-  int bb, changed;
+  int changed;
   rtx insn;
+  basic_block bb;
 
   /* Note we start at block 1.  */
 
+  if (ENTRY_BLOCK_PTR->next_bb == EXIT_BLOCK_PTR)
+    return 0;
+
   changed = 0;
-  for (bb = 1; bb < n_basic_blocks; bb++)
+  FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR->next_bb->next_bb, EXIT_BLOCK_PTR, next_bb)
     {
       /* Reset tables used to keep track of what's still valid [since the
         start of the block].  */
       reset_opr_set_tables ();
 
-      for (insn = BLOCK_HEAD (bb);
-          insn != NULL && insn != NEXT_INSN (BLOCK_END (bb));
+      for (insn = bb->head;
+          insn != NULL && insn != NEXT_INSN (bb->end);
           insn = NEXT_INSN (insn))
        {
          /* Is insn of form (set (pseudo-reg) ...)?  */
@@ -3586,7 +3645,7 @@ classic_gcse ()
                  && ((expr = lookup_expr (src)) != NULL)
                  /* Is the expression available [at the start of the
                     block]?  */
-                 && TEST_BIT (ae_in[bb], expr->bitmap_index)
+                 && TEST_BIT (ae_in[bb->index], expr->bitmap_index)
                  /* Are the operands unchanged since the start of the
                     block?  */
                  && oprs_not_set_p (src, insn))
@@ -3617,7 +3676,7 @@ one_classic_gcse_pass (pass)
   gcse_create_count = 0;
 
   alloc_expr_hash_table (max_cuid);
-  alloc_rd_mem (n_basic_blocks, max_cuid);
+  alloc_rd_mem (last_basic_block, max_cuid);
   compute_expr_hash_table ();
   if (gcse_file)
     dump_hash_table (gcse_file, "Expression", expr_hash_table,
@@ -3627,7 +3686,7 @@ one_classic_gcse_pass (pass)
     {
       compute_kill_rd ();
       compute_rd ();
-      alloc_avail_expr_mem (n_basic_blocks, n_exprs);
+      alloc_avail_expr_mem (last_basic_block, n_exprs);
       compute_ae_gen ();
       compute_ae_kill (ae_gen, ae_kill);
       compute_available (ae_gen, ae_kill, ae_out, ae_in);
@@ -3697,7 +3756,8 @@ compute_transp (x, indx, bmap, set_p)
      sbitmap *bmap;
      int set_p;
 {
-  int bb, i, j;
+  int i, j;
+  basic_block bb;
   enum rtx_code code;
   reg_set *r;
   const char *fmt;
@@ -3717,9 +3777,9 @@ compute_transp (x, indx, bmap, set_p)
        {
          if (REGNO (x) < FIRST_PSEUDO_REGISTER)
            {
-             for (bb = 0; bb < n_basic_blocks; bb++)
-               if (TEST_BIT (reg_set_in_block[bb], REGNO (x)))
-                 SET_BIT (bmap[bb], indx);
+             FOR_EACH_BB (bb)
+               if (TEST_BIT (reg_set_in_block[bb->index], REGNO (x)))
+                 SET_BIT (bmap[bb->index], indx);
            }
          else
            {
@@ -3731,9 +3791,9 @@ compute_transp (x, indx, bmap, set_p)
        {
          if (REGNO (x) < FIRST_PSEUDO_REGISTER)
            {
-             for (bb = 0; bb < n_basic_blocks; bb++)
-               if (TEST_BIT (reg_set_in_block[bb], REGNO (x)))
-                 RESET_BIT (bmap[bb], indx);
+             FOR_EACH_BB (bb)
+               if (TEST_BIT (reg_set_in_block[bb->index], REGNO (x)))
+                 RESET_BIT (bmap[bb->index], indx);
            }
          else
            {
@@ -3745,9 +3805,9 @@ compute_transp (x, indx, bmap, set_p)
       return;
 
     case MEM:
-      for (bb = 0; bb < n_basic_blocks; bb++)
+      FOR_EACH_BB (bb)
        {
-         rtx list_entry = canon_modify_mem_list[bb];
+         rtx list_entry = canon_modify_mem_list[bb->index];
 
          while (list_entry)
            {
@@ -3756,9 +3816,9 @@ compute_transp (x, indx, bmap, set_p)
              if (GET_CODE (XEXP (list_entry, 0)) == CALL_INSN)
                {
                  if (set_p)
-                   SET_BIT (bmap[bb], indx);
+                   SET_BIT (bmap[bb->index], indx);
                  else
-                   RESET_BIT (bmap[bb], indx);
+                   RESET_BIT (bmap[bb->index], indx);
                  break;
                }
              /* LIST_ENTRY must be an INSN of some kind that sets memory.
@@ -3772,9 +3832,9 @@ compute_transp (x, indx, bmap, set_p)
                                         x, rtx_addr_varies_p))
                {
                  if (set_p)
-                   SET_BIT (bmap[bb], indx);
+                   SET_BIT (bmap[bb->index], indx);
                  else
-                   RESET_BIT (bmap[bb], indx);
+                   RESET_BIT (bmap[bb->index], indx);
                  break;
                }
              list_entry = XEXP (list_entry, 1);
@@ -3789,6 +3849,7 @@ compute_transp (x, indx, bmap, set_p)
     case CONST:
     case CONST_INT:
     case CONST_DOUBLE:
+    case CONST_VECTOR:
     case SYMBOL_REF:
     case LABEL_REF:
     case ADDR_VEC:
@@ -4237,24 +4298,31 @@ static int
 cprop (alter_jumps)
      int alter_jumps;
 {
-  int bb, changed;
+  int changed;
+  basic_block bb;
   rtx insn;
 
   /* Note we start at block 1.  */
+  if (ENTRY_BLOCK_PTR->next_bb == EXIT_BLOCK_PTR)
+    {
+      if (gcse_file != NULL)
+       fprintf (gcse_file, "\n");
+      return 0;
+    }
 
   changed = 0;
-  for (bb = 1; bb < n_basic_blocks; bb++)
+  FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR->next_bb->next_bb, EXIT_BLOCK_PTR, next_bb)
     {
       /* Reset tables used to keep track of what's still valid [since the
         start of the block].  */
       reset_opr_set_tables ();
 
-      for (insn = BLOCK_HEAD (bb);
-          insn != NULL && insn != NEXT_INSN (BLOCK_END (bb));
+      for (insn = bb->head;
+          insn != NULL && insn != NEXT_INSN (bb->end);
           insn = NEXT_INSN (insn))
        if (INSN_P (insn))
          {
-           changed |= cprop_insn (BASIC_BLOCK (bb), insn, alter_jumps);
+           changed |= cprop_insn (bb, insn, alter_jumps);
 
            /* Keep track of everything modified by this insn.  */
            /* ??? Need to be careful w.r.t. mods done to INSN.  Don't
@@ -4291,7 +4359,7 @@ one_cprop_pass (pass, alter_jumps)
                     n_sets);
   if (n_sets > 0)
     {
-      alloc_cprop_mem (n_basic_blocks, n_sets);
+      alloc_cprop_mem (last_basic_block, n_sets);
       compute_cprop_data ();
       changed = cprop (alter_jumps);
       free_cprop_mem ();
@@ -4401,11 +4469,11 @@ static void
 compute_pre_data ()
 {
   sbitmap trapping_expr;
-  int i;
+  basic_block bb;
   unsigned int ui;
 
   compute_local_properties (transp, comp, antloc, 0);
-  sbitmap_vector_zero (ae_kill, n_basic_blocks);
+  sbitmap_vector_zero (ae_kill, last_basic_block);
 
   /* Collect expressions which might trap.  */
   trapping_expr = sbitmap_alloc (n_exprs);
@@ -4424,7 +4492,7 @@ compute_pre_data ()
 
      This is significantly faster than compute_ae_kill.  */
 
-  for (i = 0; i < n_basic_blocks; i++)
+  FOR_EACH_BB (bb)
     {
       edge e;
 
@@ -4432,16 +4500,16 @@ compute_pre_data ()
         kill all trapping expressions because we won't be able to properly
         place the instruction on the edge.  So make them neither
         anticipatable nor transparent.  This is fairly conservative.  */
-      for (e = BASIC_BLOCK (i)->pred; e ; e = e->pred_next)
+      for (e = bb->pred; e ; e = e->pred_next)
        if (e->flags & EDGE_ABNORMAL)
          {
-           sbitmap_difference (antloc[i], antloc[i], trapping_expr);
-           sbitmap_difference (transp[i], transp[i], trapping_expr);
+           sbitmap_difference (antloc[bb->index], antloc[bb->index], trapping_expr);
+           sbitmap_difference (transp[bb->index], transp[bb->index], trapping_expr);
            break;
          }
 
-      sbitmap_a_or_b (ae_kill[i], transp[i], comp[i]);
-      sbitmap_not (ae_kill[i], ae_kill[i]);
+      sbitmap_a_or_b (ae_kill[bb->index], transp[bb->index], comp[bb->index]);
+      sbitmap_not (ae_kill[bb->index], ae_kill[bb->index]);
     }
 
   edge_list = pre_edge_lcm (gcse_file, n_exprs, transp, comp, antloc,
@@ -4524,7 +4592,7 @@ pre_expr_reaches_here_p (occr_bb, expr, bb)
      basic_block bb;
 {
   int rval;
-  char *visited = (char *) xcalloc (n_basic_blocks, 1);
+  char *visited = (char *) xcalloc (last_basic_block, 1);
 
   rval = pre_expr_reaches_here_p_work (occr_bb, expr, bb, visited);
 
@@ -4588,13 +4656,23 @@ insert_insn_end_bb (expr, bb, pre)
   pat = process_insert_insn (expr);
 
   /* If the last insn is a jump, insert EXPR in front [taking care to
-     handle cc0, etc. properly].  */
+     handle cc0, etc. properly].  Similary we need to care trapping
+     instructions in presence of non-call exceptions.  */
 
-  if (GET_CODE (insn) == JUMP_INSN)
+  if (GET_CODE (insn) == JUMP_INSN
+      || (GET_CODE (insn) == INSN
+         && (bb->succ->succ_next || (bb->succ->flags & EDGE_ABNORMAL))))
     {
 #ifdef HAVE_cc0
       rtx note;
 #endif
+      /* It should always be the case that we can put these instructions
+        anywhere in the basic block with performing PRE optimizations.
+        Check this.  */
+      if (GET_CODE (insn) == INSN && pre
+         && !TEST_BIT (antloc[bb->index], expr->bitmap_index)
+          && !TEST_BIT (transp[bb->index], expr->bitmap_index))
+       abort ();
 
       /* If this is a jump table, then we can't insert stuff here.  Since
         we know the previous real insn must be the tablejump, we insert
@@ -4624,7 +4702,8 @@ insert_insn_end_bb (expr, bb, pre)
 
   /* Likewise if the last insn is a call, as will happen in the presence
      of exception handling.  */
-  else if (GET_CODE (insn) == CALL_INSN)
+  else if (GET_CODE (insn) == CALL_INSN
+          && (bb->succ->succ_next || (bb->succ->flags & EDGE_ABNORMAL)))
     {
       /* Keeping in mind SMALL_REGISTER_CLASSES and parameters in registers,
         we search backward and place the instructions before the first
@@ -4870,6 +4949,33 @@ pre_insert_copies ()
       }
 }
 
+/* Emit move from SRC to DEST noting the equivalence with expression computed
+   in INSN.  */
+static rtx
+gcse_emit_move_after (src, dest, insn)
+     rtx src, dest, insn;
+{
+  rtx new;
+  rtx set = single_set (insn);
+  rtx note;
+  rtx eqv;
+
+  /* This should never fail since we're creating a reg->reg copy
+     we've verified to be valid.  */
+
+  new = emit_insn_after (gen_rtx_SET (VOIDmode, dest, src), insn);
+
+  /* Note the equivalence for local CSE pass.  */
+  if ((note = find_reg_equal_equiv_note (insn)))
+    eqv = XEXP (note, 0);
+  else
+    eqv = SET_SRC (set);
+
+  set_unique_reg_note (new, REG_EQUAL, copy_insn_1 (src));
+
+  return new;
+}
+
 /* Delete redundant computations.
    Deletion is done by changing the insn to copy the `reaching_reg' of
    the expression into the result of the SET.  It is left to later passes
@@ -4913,21 +5019,12 @@ pre_delete ()
                  expr->reaching_reg
                    = gen_reg_rtx (GET_MODE (SET_DEST (set)));
 
-               /* In theory this should never fail since we're creating
-                  a reg->reg copy.
-
-                  However, on the x86 some of the movXX patterns actually
-                  contain clobbers of scratch regs.  This may cause the
-                  insn created by validate_change to not match any pattern
-                  and thus cause validate_change to fail.  */
-               if (validate_change (insn, &SET_SRC (set),
-                                    expr->reaching_reg, 0))
-                 {
-                   occr->deleted_p = 1;
-                   SET_BIT (pre_redundant_insns, INSN_CUID (insn));
-                   changed = 1;
-                   gcse_subst_count++;
-                 }
+               gcse_emit_move_after (expr->reaching_reg, SET_DEST (set), insn);
+               delete_insn (insn);
+               occr->deleted_p = 1;
+               SET_BIT (pre_redundant_insns, INSN_CUID (insn));
+               changed = 1;
+               gcse_subst_count++;
 
                if (gcse_file)
                  {
@@ -5033,7 +5130,7 @@ one_pre_gcse_pass (pass)
 
   if (n_exprs > 0)
     {
-      alloc_pre_mem (n_basic_blocks, n_exprs);
+      alloc_pre_mem (last_basic_block, n_exprs);
       compute_pre_data ();
       changed |= pre_gcse ();
       free_edge_list (edge_list);
@@ -5117,18 +5214,18 @@ add_label_notes (x, insn)
 static void
 compute_transpout ()
 {
-  int bb;
+  basic_block bb;
   unsigned int i;
   struct expr *expr;
 
-  sbitmap_vector_ones (transpout, n_basic_blocks);
+  sbitmap_vector_ones (transpout, last_basic_block);
 
-  for (bb = 0; bb < n_basic_blocks; ++bb)
+  FOR_EACH_BB (bb)
     {
       /* Note that flow inserted a nop a the end of basic blocks that
         end in call instructions for reasons other than abnormal
         control flow.  */
-      if (GET_CODE (BLOCK_END (bb)) != CALL_INSN)
+      if (GET_CODE (bb->end) != CALL_INSN)
        continue;
 
       for (i = 0; i < expr_hash_table_size; i++)
@@ -5142,7 +5239,7 @@ compute_transpout ()
              /* ??? Optimally, we would use interprocedural alias
                 analysis to determine if this mem is actually killed
                 by this call.  */
-             RESET_BIT (transpout[bb], expr->bitmap_index);
+             RESET_BIT (transpout[bb->index], expr->bitmap_index);
            }
     }
 }
@@ -5175,8 +5272,8 @@ invalidate_nonnull_info (x, setter, data)
 
   regno = REGNO (x) - npi->min_reg;
 
-  RESET_BIT (npi->nonnull_local[npi->current_block], regno);
-  SET_BIT (npi->nonnull_killed[npi->current_block], regno);
+  RESET_BIT (npi->nonnull_local[npi->current_block->index], regno);
+  SET_BIT (npi->nonnull_killed[npi->current_block->index], regno);
 }
 
 /* Do null-pointer check elimination for the registers indicated in
@@ -5191,8 +5288,7 @@ delete_null_pointer_checks_1 (block_reg, nonnull_avin,
      sbitmap *nonnull_avout;
      struct null_pointer_info *npi;
 {
-  int bb;
-  int current_block;
+  basic_block bb, current_block;
   sbitmap *nonnull_local = npi->nonnull_local;
   sbitmap *nonnull_killed = npi->nonnull_killed;
   
@@ -5204,10 +5300,10 @@ delete_null_pointer_checks_1 (block_reg, nonnull_avin,
      Note that a register can have both properties in a single block.  That
      indicates that it's killed, then later in the block a new value is
      computed.  */
-  sbitmap_vector_zero (nonnull_local, n_basic_blocks);
-  sbitmap_vector_zero (nonnull_killed, n_basic_blocks);
+  sbitmap_vector_zero (nonnull_local, last_basic_block);
+  sbitmap_vector_zero (nonnull_killed, last_basic_block);
 
-  for (current_block = 0; current_block < n_basic_blocks; current_block++)
+  FOR_EACH_BB (current_block)
     {
       rtx insn, stop_insn;
 
@@ -5216,8 +5312,8 @@ delete_null_pointer_checks_1 (block_reg, nonnull_avin,
 
       /* Scan each insn in the basic block looking for memory references and
         register sets.  */
-      stop_insn = NEXT_INSN (BLOCK_END (current_block));
-      for (insn = BLOCK_HEAD (current_block);
+      stop_insn = NEXT_INSN (current_block->end);
+      for (insn = current_block->head;
           insn != stop_insn;
           insn = NEXT_INSN (insn))
        {
@@ -5245,7 +5341,7 @@ delete_null_pointer_checks_1 (block_reg, nonnull_avin,
              && GET_CODE ((reg = XEXP (SET_SRC (set), 0))) == REG
              && REGNO (reg) >= npi->min_reg
              && REGNO (reg) < npi->max_reg)
-           SET_BIT (nonnull_local[current_block],
+           SET_BIT (nonnull_local[current_block->index],
                     REGNO (reg) - npi->min_reg);
 
          /* Now invalidate stuff clobbered by this insn.  */
@@ -5258,7 +5354,7 @@ delete_null_pointer_checks_1 (block_reg, nonnull_avin,
              && GET_CODE ((reg = XEXP (SET_DEST (set), 0))) == REG
              && REGNO (reg) >= npi->min_reg
              && REGNO (reg) < npi->max_reg)
-           SET_BIT (nonnull_local[current_block],
+           SET_BIT (nonnull_local[current_block->index],
                     REGNO (reg) - npi->min_reg);
        }
     }
@@ -5270,17 +5366,17 @@ delete_null_pointer_checks_1 (block_reg, nonnull_avin,
 
   /* Now look at each bb and see if it ends with a compare of a value
      against zero.  */
-  for (bb = 0; bb < n_basic_blocks; bb++)
+  FOR_EACH_BB (bb)
     {
-      rtx last_insn = BLOCK_END (bb);
+      rtx last_insn = bb->end;
       rtx condition, earliest;
       int compare_and_branch;
 
       /* Since MIN_REG is always at least FIRST_PSEUDO_REGISTER, and
         since BLOCK_REG[BB] is zero if this block did not end with a
         comparison against zero, this condition works.  */
-      if (block_reg[bb] < npi->min_reg
-         || block_reg[bb] >= npi->max_reg)
+      if (block_reg[bb->index] < npi->min_reg
+         || block_reg[bb->index] >= npi->max_reg)
        continue;
 
       /* LAST_INSN is a conditional jump.  Get its condition.  */
@@ -5291,7 +5387,7 @@ delete_null_pointer_checks_1 (block_reg, nonnull_avin,
        continue;
 
       /* Is the register known to have a nonzero value?  */
-      if (!TEST_BIT (nonnull_avout[bb], block_reg[bb] - npi->min_reg))
+      if (!TEST_BIT (nonnull_avout[bb->index], block_reg[bb->index] - npi->min_reg))
        continue;
 
       /* Try to compute whether the compare/branch at the loop end is one or
@@ -5309,8 +5405,8 @@ delete_null_pointer_checks_1 (block_reg, nonnull_avin,
        {
          rtx new_jump;
 
-         new_jump = emit_jump_insn_before (gen_jump (JUMP_LABEL (last_insn)),
-                                           last_insn);
+         new_jump = emit_jump_insn_after (gen_jump (JUMP_LABEL (last_insn)),
+                                          last_insn);
          JUMP_LABEL (new_jump) = JUMP_LABEL (last_insn);
          LABEL_NUSES (JUMP_LABEL (new_jump))++;
          emit_barrier_after (new_jump);
@@ -5319,12 +5415,12 @@ delete_null_pointer_checks_1 (block_reg, nonnull_avin,
       delete_insn (last_insn);
       if (compare_and_branch == 2)
         delete_insn (earliest);
-      purge_dead_edges (BASIC_BLOCK (bb));
+      purge_dead_edges (bb);
 
       /* Don't check this block again.  (Note that BLOCK_END is
         invalid here; we deleted the last instruction in the 
         block.)  */
-      block_reg[bb] = 0;
+      block_reg[bb->index] = 0;
     }
 }
 
@@ -5358,7 +5454,7 @@ delete_null_pointer_checks (f)
 {
   sbitmap *nonnull_avin, *nonnull_avout;
   unsigned int *block_reg;
-  int bb;
+  basic_block bb;
   int reg;
   int regs_per_pass;
   int max_reg;
@@ -5382,21 +5478,21 @@ delete_null_pointer_checks (f)
   /* We need four bitmaps, each with a bit for each register in each
      basic block.  */
   max_reg = max_reg_num ();
-  regs_per_pass = get_bitmap_width (4, n_basic_blocks, max_reg);
+  regs_per_pass = get_bitmap_width (4, last_basic_block, max_reg);
 
   /* Allocate bitmaps to hold local and global properties.  */
-  npi.nonnull_local = sbitmap_vector_alloc (n_basic_blocks, regs_per_pass);
-  npi.nonnull_killed = sbitmap_vector_alloc (n_basic_blocks, regs_per_pass);
-  nonnull_avin = sbitmap_vector_alloc (n_basic_blocks, regs_per_pass);
-  nonnull_avout = sbitmap_vector_alloc (n_basic_blocks, regs_per_pass);
+  npi.nonnull_local = sbitmap_vector_alloc (last_basic_block, regs_per_pass);
+  npi.nonnull_killed = sbitmap_vector_alloc (last_basic_block, regs_per_pass);
+  nonnull_avin = sbitmap_vector_alloc (last_basic_block, regs_per_pass);
+  nonnull_avout = sbitmap_vector_alloc (last_basic_block, regs_per_pass);
 
   /* Go through the basic blocks, seeing whether or not each block
      ends with a conditional branch whose condition is a comparison
      against zero.  Record the register compared in BLOCK_REG.  */
-  block_reg = (unsigned int *) xcalloc (n_basic_blocks, sizeof (int));
-  for (bb = 0; bb < n_basic_blocks; bb++)
+  block_reg = (unsigned int *) xcalloc (last_basic_block, sizeof (int));
+  FOR_EACH_BB (bb)
     {
-      rtx last_insn = BLOCK_END (bb);
+      rtx last_insn = bb->end;
       rtx condition, earliest, reg;
 
       /* We only want conditional branches.  */
@@ -5422,7 +5518,7 @@ delete_null_pointer_checks (f)
       if (GET_CODE (reg) != REG)
        continue;
 
-      block_reg[bb] = REGNO (reg);
+      block_reg[bb->index] = REGNO (reg);
     }
 
   /* Go through the algorithm for each block of registers.  */
@@ -5506,10 +5602,11 @@ free_code_hoist_mem ()
 static void
 compute_code_hoist_vbeinout ()
 {
-  int bb, changed, passes;
+  int changed, passes;
+  basic_block bb;
 
-  sbitmap_vector_zero (hoist_vbeout, n_basic_blocks);
-  sbitmap_vector_zero (hoist_vbein, n_basic_blocks);
+  sbitmap_vector_zero (hoist_vbeout, last_basic_block);
+  sbitmap_vector_zero (hoist_vbein, last_basic_block);
 
   passes = 0;
   changed = 1;
@@ -5520,12 +5617,12 @@ compute_code_hoist_vbeinout ()
 
       /* We scan the blocks in the reverse order to speed up
         the convergence.  */
-      for (bb = n_basic_blocks - 1; bb >= 0; bb--)
+      FOR_EACH_BB_REVERSE (bb)
        {
-         changed |= sbitmap_a_or_b_and_c (hoist_vbein[bb], antloc[bb],
-                                          hoist_vbeout[bb], transp[bb]);
-         if (bb != n_basic_blocks - 1)
-           sbitmap_intersection_of_succs (hoist_vbeout[bb], hoist_vbein, bb);
+         changed |= sbitmap_a_or_b_and_c_cg (hoist_vbein[bb->index], antloc[bb->index],
+                                             hoist_vbeout[bb->index], transp[bb->index]);
+         if (bb->next_bb != EXIT_BLOCK_PTR)
+           sbitmap_intersection_of_succs (hoist_vbeout[bb->index], hoist_vbein, bb->index);
        }
 
       passes++;
@@ -5575,7 +5672,7 @@ hoist_expr_reaches_here_p (expr_bb, expr_index, bb, visited)
   if (visited == NULL)
     {
       visited_allocated_locally = 1;
-      visited = xcalloc (n_basic_blocks, 1);
+      visited = xcalloc (last_basic_block, 1);
     }
 
   for (pred = bb->pred; pred != NULL; pred = pred->pred_next)
@@ -5613,12 +5710,12 @@ hoist_expr_reaches_here_p (expr_bb, expr_index, bb, visited)
 static void
 hoist_code ()
 {
-  int bb, dominated;
+  basic_block bb, dominated;
   unsigned int i;
   struct expr **index_map;
   struct expr *expr;
 
-  sbitmap_vector_zero (hoist_exprs, n_basic_blocks);
+  sbitmap_vector_zero (hoist_exprs, last_basic_block);
 
   /* Compute a mapping from expression number (`bitmap_index') to
      hash table entry.  */
@@ -5630,33 +5727,33 @@ hoist_code ()
 
   /* Walk over each basic block looking for potentially hoistable
      expressions, nothing gets hoisted from the entry block.  */
-  for (bb = 0; bb < n_basic_blocks; bb++)
+  FOR_EACH_BB (bb)
     {
       int found = 0;
       int insn_inserted_p;
 
       /* Examine each expression that is very busy at the exit of this
         block.  These are the potentially hoistable expressions.  */
-      for (i = 0; i < hoist_vbeout[bb]->n_bits; i++)
+      for (i = 0; i < hoist_vbeout[bb->index]->n_bits; i++)
        {
          int hoistable = 0;
 
-         if (TEST_BIT (hoist_vbeout[bb], i) && TEST_BIT (transpout[bb], i))
+         if (TEST_BIT (hoist_vbeout[bb->index], i) && TEST_BIT (transpout[bb->index], i))
            {
              /* We've found a potentially hoistable expression, now
                 we look at every block BB dominates to see if it
                 computes the expression.  */
-             for (dominated = 0; dominated < n_basic_blocks; dominated++)
+             FOR_EACH_BB (dominated)
                {
                  /* Ignore self dominance.  */
                  if (bb == dominated
-                     || ! TEST_BIT (dominators[dominated], bb))
+                     || ! TEST_BIT (dominators[dominated->index], bb->index))
                    continue;
 
                  /* We've found a dominated block, now see if it computes
                     the busy expression and whether or not moving that
                     expression to the "beginning" of that block is safe.  */
-                 if (!TEST_BIT (antloc[dominated], i))
+                 if (!TEST_BIT (antloc[dominated->index], i))
                    continue;
 
                  /* Note if the expression would reach the dominated block
@@ -5664,8 +5761,7 @@ hoist_code ()
 
                     Keep track of how many times this expression is hoistable
                     from a dominated block into BB.  */
-                 if (hoist_expr_reaches_here_p (BASIC_BLOCK (bb), i, 
-                                                BASIC_BLOCK (dominated), NULL))
+                 if (hoist_expr_reaches_here_p (bb, i, dominated, NULL))
                    hoistable++;
                }
 
@@ -5681,7 +5777,7 @@ hoist_code ()
                 to nullify any benefit we get from code hoisting.  */
              if (hoistable > 1)
                {
-                 SET_BIT (hoist_exprs[bb], i);
+                 SET_BIT (hoist_exprs[bb->index], i);
                  found = 1;
                }
            }
@@ -5692,29 +5788,29 @@ hoist_code ()
        continue;
 
       /* Loop over all the hoistable expressions.  */
-      for (i = 0; i < hoist_exprs[bb]->n_bits; i++)
+      for (i = 0; i < hoist_exprs[bb->index]->n_bits; i++)
        {
          /* We want to insert the expression into BB only once, so
             note when we've inserted it.  */
          insn_inserted_p = 0;
 
          /* These tests should be the same as the tests above.  */
-         if (TEST_BIT (hoist_vbeout[bb], i))
+         if (TEST_BIT (hoist_vbeout[bb->index], i))
            {
              /* We've found a potentially hoistable expression, now
                 we look at every block BB dominates to see if it
                 computes the expression.  */
-             for (dominated = 0; dominated < n_basic_blocks; dominated++)
+             FOR_EACH_BB (dominated)
                {
                  /* Ignore self dominance.  */
                  if (bb == dominated
-                     || ! TEST_BIT (dominators[dominated], bb))
+                     || ! TEST_BIT (dominators[dominated->index], bb->index))
                    continue;
 
                  /* We've found a dominated block, now see if it computes
                     the busy expression and whether or not moving that
                     expression to the "beginning" of that block is safe.  */
-                 if (!TEST_BIT (antloc[dominated], i))
+                 if (!TEST_BIT (antloc[dominated->index], i))
                    continue;
 
                  /* The expression is computed in the dominated block and
@@ -5722,8 +5818,7 @@ hoist_code ()
                     dominated block.  Now we have to determine if the
                     expression would reach the dominated block if it was
                     placed at the end of BB.  */
-                 if (hoist_expr_reaches_here_p (BASIC_BLOCK (bb), i, 
-                                                BASIC_BLOCK (dominated), NULL))
+                 if (hoist_expr_reaches_here_p (bb, i, dominated, NULL))
                    {
                      struct expr *expr = index_map[i];
                      struct occr *occr = expr->antic_occr;
@@ -5731,7 +5826,7 @@ hoist_code ()
                      rtx set;
 
                      /* Find the right occurrence of this expression.  */
-                     while (BLOCK_NUM (occr->insn) != dominated && occr)
+                     while (BLOCK_FOR_INSN (occr->insn) != dominated && occr)
                        occr = occr->next;
 
                      /* Should never happen.  */
@@ -5751,24 +5846,13 @@ hoist_code ()
                        expr->reaching_reg
                          = gen_reg_rtx (GET_MODE (SET_DEST (set)));
 
-                     /* In theory this should never fail since we're creating
-                        a reg->reg copy.
-
-                        However, on the x86 some of the movXX patterns
-                        actually contain clobbers of scratch regs.  This may
-                        cause the insn created by validate_change to not
-                        match any pattern and thus cause validate_change to
-                        fail.  */
-                     if (validate_change (insn, &SET_SRC (set),
-                                          expr->reaching_reg, 0))
+                     gcse_emit_move_after (expr->reaching_reg, SET_DEST (set), insn);
+                     delete_insn (insn);
+                     occr->deleted_p = 1;
+                     if (!insn_inserted_p)
                        {
-                         occr->deleted_p = 1;
-                         if (!insn_inserted_p)
-                           {
-                             insert_insn_end_bb (index_map[i], 
-                                                 BASIC_BLOCK (bb), 0);
-                             insn_inserted_p = 1;
-                           }
+                         insert_insn_end_bb (index_map[i], bb, 0);
+                         insn_inserted_p = 1;
                        }
                    }
                }
@@ -5796,7 +5880,7 @@ one_code_hoisting_pass ()
 
   if (n_exprs > 0)
     {
-      alloc_code_hoist_mem (n_basic_blocks, n_exprs);
+      alloc_code_hoist_mem (last_basic_block, n_exprs);
       compute_code_hoist_data ();
       hoist_code ();
       free_code_hoist_mem ();
@@ -6046,15 +6130,15 @@ static void
 compute_ld_motion_mems ()
 {
   struct ls_expr * ptr;
-  int bb;
+  basic_block bb;
   rtx insn;
   
   pre_ldst_mems = NULL;
 
-  for (bb = 0; bb < n_basic_blocks; bb++)
+  FOR_EACH_BB (bb)
     {
-      for (insn = BLOCK_HEAD (bb);
-          insn && insn != NEXT_INSN (BLOCK_END (bb));
+      for (insn = bb->head;
+          insn && insn != NEXT_INSN (bb->end);
           insn = NEXT_INSN (insn))
        {
          if (GET_RTX_CLASS (GET_CODE (insn)) == 'i')
@@ -6289,6 +6373,7 @@ store_ops_ok (x, bb)
     case CONST:
     case CONST_INT:
     case CONST_DOUBLE:
+    case CONST_VECTOR:
     case SYMBOL_REF:
     case LABEL_REF:
     case ADDR_VEC:
@@ -6370,23 +6455,24 @@ find_moveable_store (insn)
 static int
 compute_store_table ()
 {
-  int bb, ret;
+  int ret;
+  basic_block bb;
   unsigned regno;
   rtx insn, pat;
 
   max_gcse_regno = max_reg_num ();
 
-  reg_set_in_block = (sbitmap *) sbitmap_vector_alloc (n_basic_blocks,
+  reg_set_in_block = (sbitmap *) sbitmap_vector_alloc (last_basic_block,
                                                       max_gcse_regno);
-  sbitmap_vector_zero (reg_set_in_block, n_basic_blocks);
+  sbitmap_vector_zero (reg_set_in_block, last_basic_block);
   pre_ldst_mems = 0;
 
   /* Find all the stores we care about.  */
-  for (bb = 0; bb < n_basic_blocks; bb++)
+  FOR_EACH_BB (bb)
     {
-      regvec = & (reg_set_in_block[bb]);
-      for (insn = BLOCK_END (bb);
-          insn && insn != PREV_INSN (BLOCK_HEAD (bb));
+      regvec = & (reg_set_in_block[bb->index]);
+      for (insn = bb->end;
+          insn && insn != PREV_INSN (bb->end);
           insn = PREV_INSN (insn))
        {
          /* Ignore anything that is not a normal insn.  */
@@ -6405,7 +6491,7 @@ compute_store_table ()
              for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
                if (clobbers_all
                    || TEST_HARD_REG_BIT (regs_invalidated_by_call, regno))
-                 SET_BIT (reg_set_in_block[bb], regno);
+                 SET_BIT (reg_set_in_block[bb->index], regno);
            }
          
          pat = PATTERN (insn);
@@ -6490,21 +6576,7 @@ store_killed_in_insn (x, insn)
     {
       /* A normal or pure call might read from pattern,
         but a const call will not.  */
-      if (CONST_OR_PURE_CALL_P (insn))
-       {
-         rtx link;
-
-         for (link = CALL_INSN_FUNCTION_USAGE (insn);
-              link;
-              link = XEXP (link, 1))
-           if (GET_CODE (XEXP (link, 0)) == USE
-               && GET_CODE (XEXP (XEXP (link, 0), 0)) == MEM
-               && GET_CODE (XEXP (XEXP (XEXP (link, 0), 0), 0)) == SCRATCH)
-             return 1;
-         return 0;
-       }
-      else
-       return 1;
+      return ! CONST_OR_PURE_CALL_P (insn) || pure_call_p (insn);
     }
   
   if (GET_CODE (PATTERN (insn)) == SET)
@@ -6585,18 +6657,17 @@ store_killed_before (x, insn, bb)
 static void
 build_store_vectors () 
 {
-  basic_block bb;
-  int b;
+  basic_block bb, b;
   rtx insn, st;
   struct ls_expr * ptr;
 
   /* Build the gen_vector. This is any store in the table which is not killed
      by aliasing later in its block.  */
-  ae_gen = (sbitmap *) sbitmap_vector_alloc (n_basic_blocks, num_stores);
-  sbitmap_vector_zero (ae_gen, n_basic_blocks);
+  ae_gen = (sbitmap *) sbitmap_vector_alloc (last_basic_block, num_stores);
+  sbitmap_vector_zero (ae_gen, last_basic_block);
 
-  st_antloc = (sbitmap *) sbitmap_vector_alloc (n_basic_blocks, num_stores);
-  sbitmap_vector_zero (st_antloc, n_basic_blocks);
+  st_antloc = (sbitmap *) sbitmap_vector_alloc (last_basic_block, num_stores);
+  sbitmap_vector_zero (st_antloc, last_basic_block);
 
   for (ptr = first_ls_expr (); ptr != NULL; ptr = next_ls_expr (ptr))
     { 
@@ -6651,16 +6722,16 @@ build_store_vectors ()
       free_INSN_LIST_list (&store_list);
     }
          
-  ae_kill = (sbitmap *) sbitmap_vector_alloc (n_basic_blocks, num_stores);
-  sbitmap_vector_zero (ae_kill, n_basic_blocks);
+  ae_kill = (sbitmap *) sbitmap_vector_alloc (last_basic_block, num_stores);
+  sbitmap_vector_zero (ae_kill, last_basic_block);
 
-  transp = (sbitmap *) sbitmap_vector_alloc (n_basic_blocks, num_stores);
-  sbitmap_vector_zero (transp, n_basic_blocks);
+  transp = (sbitmap *) sbitmap_vector_alloc (last_basic_block, num_stores);
+  sbitmap_vector_zero (transp, last_basic_block);
 
   for (ptr = first_ls_expr (); ptr != NULL; ptr = next_ls_expr (ptr))
-    for (b = 0; b < n_basic_blocks; b++)
+    FOR_EACH_BB (b)
       {
-       if (store_killed_after (ptr->pattern, BLOCK_HEAD (b), BASIC_BLOCK (b)))
+       if (store_killed_after (ptr->pattern, b->head, b))
          {
            /* The anticipatable expression is not killed if it's gen'd.  */
            /*
@@ -6678,10 +6749,10 @@ build_store_vectors ()
              If we always kill it in this case, we'll sometimes do
              uneccessary work, but it shouldn't actually hurt anything.
            if (!TEST_BIT (ae_gen[b], ptr->index)).  */
-           SET_BIT (ae_kill[b], ptr->index);
+           SET_BIT (ae_kill[b->index], ptr->index);
          }
        else
-         SET_BIT (transp[b], ptr->index);
+         SET_BIT (transp[b->index], ptr->index);
       }
 
   /* Any block with no exits calls some non-returning function, so
@@ -6692,10 +6763,10 @@ build_store_vectors ()
     {
       fprintf (gcse_file, "ST_avail and ST_antic (shown under loads..)\n");
       print_ldst_list (gcse_file);
-      dump_sbitmap_vector (gcse_file, "st_antloc", "", st_antloc, n_basic_blocks);
-      dump_sbitmap_vector (gcse_file, "st_kill", "", ae_kill, n_basic_blocks);
-      dump_sbitmap_vector (gcse_file, "Transpt", "", transp, n_basic_blocks);
-      dump_sbitmap_vector (gcse_file, "st_avloc", "", ae_gen, n_basic_blocks);
+      dump_sbitmap_vector (gcse_file, "st_antloc", "", st_antloc, last_basic_block);
+      dump_sbitmap_vector (gcse_file, "st_kill", "", ae_kill, last_basic_block);
+      dump_sbitmap_vector (gcse_file, "Transpt", "", transp, last_basic_block);
+      dump_sbitmap_vector (gcse_file, "st_avloc", "", ae_gen, last_basic_block);
     }
 }
 
@@ -6890,6 +6961,7 @@ free_store_memory ()
 static void
 store_motion ()
 {
+  basic_block bb;
   int x;
   struct ls_expr * ptr;
   int update_flow = 0;
@@ -6923,9 +6995,9 @@ store_motion ()
   /* Now we want to insert the new stores which are going to be needed.  */
   for (ptr = first_ls_expr (); ptr != NULL; ptr = next_ls_expr (ptr))
     {
-      for (x = 0; x < n_basic_blocks; x++)
-       if (TEST_BIT (pre_delete_map[x], ptr->index))
-         delete_store (ptr, BASIC_BLOCK (x));
+      FOR_EACH_BB (bb)
+       if (TEST_BIT (pre_delete_map[bb->index], ptr->index))
+         delete_store (ptr, bb);
 
       for (x = 0; x < NUM_EDGES (edge_list); x++)
        if (TEST_BIT (pre_insert_map[x], ptr->index))