OSDN Git Service

Add file omitted from last checkin.
[pf3gnuchains/gcc-fork.git] / gcc / see.c
index 8e4bd29..6e5260b 100644 (file)
--- a/gcc/see.c
+++ b/gcc/see.c
@@ -1,12 +1,12 @@
 /* Sign extension elimination optimization for GNU compiler.
-   Copyright (C) 2005 Free Software Foundation, Inc.
+   Copyright (C) 2005, 2006, 2007 Free Software Foundation, Inc.
    Contributed by Leehod Baruch <leehod@il.ibm.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
+-Software Foundation; either version 3, or (at your option) any later
 version.
 
 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
@@ -15,9 +15,8 @@ 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.
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.
 
 Problem description:
 --------------------
@@ -479,9 +478,7 @@ The implementation consists of four data structures:
 #include "regs.h"
 #include "timevar.h"
 #include "tree-pass.h"
-
-void
-see_main (void);
+#include "dce.h"
 
 /* Used to classify defs and uses according to relevancy.  */
 enum entry_type {
@@ -536,7 +533,7 @@ struct see_ref_s
   /* The insn of the ref.  */
   rtx insn;
   /* The merged insn that was formed from the reference's insn and extensions.
-     If all merges faile it remains NULL.  */
+     If all merges failed, it remains NULL.  */
   rtx merged_insn;
   /* The def extensions of the reference that were not merged with
      it.  */
@@ -614,9 +611,6 @@ struct see_mentioned_reg_data
   bool mentioned;
 };
 
-/* A data flow object that will be created once and used throughout the
-   optimization.  */
-static struct df *df = NULL;
 /* An array of web_entries.  The i'th definition in the df object is associated
    with def_entry[i]  */
 static struct web_entry *def_entry = NULL;
@@ -659,7 +653,7 @@ static unsigned int uses_num;
 /* Records the number of definitions at the beginning of the optimization.  */
 static unsigned int defs_num;
 
-#define ENTRY_EI(ENTRY) ((struct see_entry_extra_info *)(ENTRY)->extra_info)
+#define ENTRY_EI(ENTRY) ((struct see_entry_extra_info *) (ENTRY)->extra_info)
 \f
 /* Functions implementation.  */
 
@@ -673,12 +667,14 @@ static unsigned int defs_num;
 static rtx
 see_get_extension_reg (rtx extension, bool return_dest_reg)
 {
-  rtx set = NULL;
-  rtx rhs = NULL;
-  rtx lhs = NULL;
+  rtx set, rhs, lhs;
   rtx reg1 = NULL;
   rtx reg2 = NULL;
 
+  /* Parallel pattern for extension not supported for the moment.  */
+  if (GET_CODE (PATTERN (extension)) == PARALLEL)
+    return NULL;
+
   set = single_set (extension);
   if (!set)
     return NULL;
@@ -692,7 +688,7 @@ see_get_extension_reg (rtx extension, bool return_dest_reg)
   else
     return NULL;
 
-  if ((GET_CODE (rhs) != SIGN_EXTEND) && (GET_CODE (rhs) != ZERO_EXTEND))
+  if (GET_CODE (rhs) != SIGN_EXTEND && GET_CODE (rhs) != ZERO_EXTEND)
     return NULL;
 
   rhs = XEXP (rhs, 0);
@@ -719,13 +715,15 @@ see_get_extension_reg (rtx extension, bool return_dest_reg)
 static enum rtx_code
 see_get_extension_data (rtx extension, enum machine_mode *source_mode)
 {
-  rtx rhs = NULL;
-  rtx lhs = NULL;
-  rtx set = NULL;
+  rtx rhs, lhs, set;
 
   if (!extension || !INSN_P (extension))
     return UNKNOWN;
 
+  /* Parallel pattern for extension not supported for the moment.  */
+  if (GET_CODE (PATTERN (extension)) == PARALLEL)
+    return NOT_RELEVANT;
+
   set = single_set (extension);
   if (!set)
     return NOT_RELEVANT;
@@ -737,20 +735,19 @@ see_get_extension_data (rtx extension, enum machine_mode *source_mode)
   if (!REG_P (lhs) && !SUBREG_REG (lhs))
     return UNKNOWN;
 
-  if ((GET_CODE (rhs) != SIGN_EXTEND) && (GET_CODE (rhs) != ZERO_EXTEND))
+  if (GET_CODE (rhs) != SIGN_EXTEND && GET_CODE (rhs) != ZERO_EXTEND)
     return UNKNOWN;
 
   if (!REG_P (XEXP (rhs, 0))
-      && !((GET_CODE (XEXP (rhs, 0)) == SUBREG)
-          && (REG_P (SUBREG_REG (XEXP (rhs, 0))))))
+      && !(GET_CODE (XEXP (rhs, 0)) == SUBREG
+          && REG_P (SUBREG_REG (XEXP (rhs, 0)))))
     return UNKNOWN;
 
   *source_mode = GET_MODE (XEXP (rhs, 0));
 
   if (GET_CODE (rhs) == SIGN_EXTEND)
     return SIGN_EXTEND;
-  else
-    return ZERO_EXTEND;
+  return ZERO_EXTEND;
 }
 
 
@@ -759,20 +756,19 @@ see_get_extension_data (rtx extension, enum machine_mode *source_mode)
    (the register r on both sides of the set is the same register).
    And recognize it.
    If the recognition failed, this is very bad, return NULL (This will abort
-   the entier optimization).
+   the entire optimization).
    Otherwise, return the generated instruction.  */
 
 static rtx
 see_gen_normalized_extension (rtx reg, enum rtx_code extension_code,
                              enum machine_mode mode)
 {
-  rtx subreg = NULL;
+  rtx subreg, insn;
   rtx extension = NULL;
-  rtx insn = NULL;
 
   if (!reg
       || !REG_P (reg)
-      || ((extension_code != SIGN_EXTEND) && (extension_code != ZERO_EXTEND)))
+      || (extension_code != SIGN_EXTEND && extension_code != ZERO_EXTEND))
     return NULL;
 
   subreg = gen_lowpart_SUBREG (mode, reg);
@@ -815,8 +811,7 @@ eq_descriptor_pre_extension (const void *p1, const void *p2)
   const struct see_pre_extension_expr *extension2 = p2;
   rtx set1 = single_set (extension1->se_insn);
   rtx set2 = single_set (extension2->se_insn);
-  rtx rhs1 = NULL;
-  rtx rhs2 = NULL;
+  rtx rhs1, rhs2;
 
   gcc_assert (set1 && set2);
   rhs1 = SET_SRC (set1);
@@ -835,7 +830,7 @@ hash_descriptor_pre_extension (const void *p)
 {
   const struct see_pre_extension_expr *extension = p;
   rtx set = single_set (extension->se_insn);
-  rtx rhs = NULL;
+  rtx rhs;
 
   gcc_assert (set);
   rhs = SET_SRC (set);
@@ -892,7 +887,7 @@ eq_descriptor_properties (const void *p1, const void *p2)
   const struct see_register_properties *curr_prop1 = p1;
   const struct see_register_properties *curr_prop2 = p2;
 
-  return (curr_prop1->regno == curr_prop2->regno);
+  return curr_prop1->regno == curr_prop2->regno;
 }
 
 
@@ -937,12 +932,12 @@ hash_del_properties (void *p)
 static int
 eq_descriptor_extension (const void *p1, const void *p2)
 {
-  const rtx insn = (rtx) p1;
-  const rtx element = (rtx) p2;
+  const_rtx const insn = (const_rtx) p1;
+  const_rtx const element = (const_rtx) p2;
   rtx set1 = single_set (insn);
+  rtx dest_reg1;
   rtx set2 = NULL;
-  rtx dest_reg1 = NULL;
-  rtx dest_reg2 = NULL;
+  const_rtx dest_reg2 = NULL;
 
   gcc_assert (set1 && element && (REG_P (element) || INSN_P (element)));
 
@@ -956,7 +951,7 @@ eq_descriptor_extension (const void *p1, const void *p2)
   else
     dest_reg2 = element;
 
-  return (REGNO (dest_reg1) == REGNO (dest_reg2));
+  return REGNO (dest_reg1) == REGNO (dest_reg2);
 }
 
 
@@ -966,20 +961,17 @@ eq_descriptor_extension (const void *p1, const void *p2)
 static hashval_t
 hash_descriptor_extension (const void *p)
 {
-  const rtx r = (rtx) p;
-  rtx set = NULL;
-  rtx lhs = NULL;
+  const_rtx const r = (const_rtx) p;
+  rtx set, lhs;
 
   if (r && REG_P (r))
     return REGNO (r);
-  else
-    {
-      gcc_assert (r && INSN_P (r));
-      set = single_set (r);
-      gcc_assert (set);
-      lhs = SET_DEST (set);
-      return REGNO (lhs);
-    }
+
+  gcc_assert (r && INSN_P (r));
+  set = single_set (r);
+  gcc_assert (set);
+  lhs = SET_DEST (set);
+  return REGNO (lhs);
 }
 
 
@@ -1017,8 +1009,7 @@ see_free_ref_s (splay_tree_value value)
 static struct see_pre_extension_expr *
 see_seek_pre_extension_expr (rtx extension, enum extension_type type)
 {
-  struct see_pre_extension_expr **slot_pre_exp = NULL;
-  struct see_pre_extension_expr temp_pre_exp;
+  struct see_pre_extension_expr **slot_pre_exp, temp_pre_exp;
   rtx dest_extension_reg = see_get_extension_reg (extension, 1);
   enum rtx_code extension_code;
   enum machine_mode source_extension_mode;
@@ -1065,8 +1056,7 @@ see_seek_pre_extension_expr (rtx extension, enum extension_type type)
 static bool
 see_update_leader_extra_info (struct web_entry *first, struct web_entry *second)
 {
-  struct see_entry_extra_info *first_ei = NULL;
-  struct see_entry_extra_info *second_ei = NULL;
+  struct see_entry_extra_info *first_ei, *second_ei;
 
   first = unionfind_root (first);
   second = unionfind_root (second);
@@ -1074,8 +1064,8 @@ see_update_leader_extra_info (struct web_entry *first, struct web_entry *second)
   if (unionfind_union (first, second))
     return true;
 
-  first_ei = (struct see_entry_extra_info *)first->extra_info;
-  second_ei = (struct see_entry_extra_info *)second->extra_info;
+  first_ei = (struct see_entry_extra_info *) first->extra_info;
+  second_ei = (struct see_entry_extra_info *) second->extra_info;
 
   gcc_assert (first_ei && second_ei);
 
@@ -1087,25 +1077,26 @@ see_update_leader_extra_info (struct web_entry *first, struct web_entry *second)
   switch (first_ei->relevancy)
     {
     case NOT_RELEVANT:
-      return false;
+      break;
     case RELEVANT_USE:
       switch (second_ei->relevancy)
        {
        case RELEVANT_USE:
-         return false;
+         break;
        case EXTENDED_DEF:
          first_ei->relevancy = second_ei->relevancy;
          first_ei->source_mode_signed = second_ei->source_mode_signed;
          first_ei->source_mode_unsigned = second_ei->source_mode_unsigned;
-         return false;
+         break;
        case SIGN_EXTENDED_DEF:
        case ZERO_EXTENDED_DEF:
          first_ei->relevancy = second_ei->relevancy;
          first_ei->source_mode = second_ei->source_mode;
-         return false;
+         break;
        default:
          gcc_unreachable ();
        }
+      break;
     case SIGN_EXTENDED_DEF:
       switch (second_ei->relevancy)
        {
@@ -1114,13 +1105,13 @@ see_update_leader_extra_info (struct web_entry *first, struct web_entry *second)
          first_ei->source_mode =
            (first_ei->source_mode > second_ei->source_mode) ?
            first_ei->source_mode : second_ei->source_mode;
-         return false;
+         break;
        case RELEVANT_USE:
-         return false;
+         break;
        case ZERO_EXTENDED_DEF:
          /* Don't mix webs with zero extend and sign extend.  */
          first_ei->relevancy = NOT_RELEVANT;
-         return false;
+         break;
        case EXTENDED_DEF:
          if (second_ei->source_mode_signed == MAX_MACHINE_MODE)
            first_ei->relevancy = NOT_RELEVANT;
@@ -1129,10 +1120,11 @@ see_update_leader_extra_info (struct web_entry *first, struct web_entry *second)
            first_ei->source_mode =
              (first_ei->source_mode > second_ei->source_mode_signed) ?
              first_ei->source_mode : second_ei->source_mode_signed;
-         return false;
+         break;
        default:
          gcc_unreachable ();
        }
+      break;
     /* This case is similar to the previous one, with little changes.  */
     case ZERO_EXTENDED_DEF:
       switch (second_ei->relevancy)
@@ -1140,15 +1132,15 @@ see_update_leader_extra_info (struct web_entry *first, struct web_entry *second)
        case SIGN_EXTENDED_DEF:
          /* Don't mix webs with zero extend and sign extend.  */
          first_ei->relevancy = NOT_RELEVANT;
-         return false;
+         break;
        case RELEVANT_USE:
-         return false;
+         break;
        case ZERO_EXTENDED_DEF:
          /* The mode of the root should be the wider one in this case.  */
          first_ei->source_mode =
            (first_ei->source_mode > second_ei->source_mode) ?
            first_ei->source_mode : second_ei->source_mode;
-         return false;
+         break;
        case EXTENDED_DEF:
          if (second_ei->source_mode_unsigned == MAX_MACHINE_MODE)
            first_ei->relevancy = NOT_RELEVANT;
@@ -1157,13 +1149,14 @@ see_update_leader_extra_info (struct web_entry *first, struct web_entry *second)
            first_ei->source_mode =
              (first_ei->source_mode > second_ei->source_mode_unsigned) ?
              first_ei->source_mode : second_ei->source_mode_unsigned;
-         return false;
+         break;
        default:
          gcc_unreachable ();
        }
+      break;
     case EXTENDED_DEF:
-      if ((first_ei->source_mode_signed != MAX_MACHINE_MODE)
-         && (first_ei->source_mode_unsigned != MAX_MACHINE_MODE))
+      if (first_ei->source_mode_signed != MAX_MACHINE_MODE
+         && first_ei->source_mode_unsigned != MAX_MACHINE_MODE)
        {
          switch (second_ei->relevancy)
            {
@@ -1172,15 +1165,15 @@ see_update_leader_extra_info (struct web_entry *first, struct web_entry *second)
              first_ei->source_mode =
                (first_ei->source_mode_signed > second_ei->source_mode) ?
                first_ei->source_mode_signed : second_ei->source_mode;
-             return false;
+             break;
            case RELEVANT_USE:
-             return false;
+             break;
            case ZERO_EXTENDED_DEF:
              first_ei->relevancy = ZERO_EXTENDED_DEF;
              first_ei->source_mode =
                (first_ei->source_mode_unsigned > second_ei->source_mode) ?
                first_ei->source_mode_unsigned : second_ei->source_mode;
-             return false;
+             break;
            case EXTENDED_DEF:
              if (second_ei->source_mode_unsigned != MAX_MACHINE_MODE)
                first_ei->source_mode_unsigned =
@@ -1193,7 +1186,7 @@ see_update_leader_extra_info (struct web_entry *first, struct web_entry *second)
                  (first_ei->source_mode_signed >
                  second_ei->source_mode_signed) ?
                  first_ei->source_mode_signed : second_ei->source_mode_signed;
-             return false;
+             break;
            default:
              gcc_unreachable ();
            }
@@ -1205,15 +1198,15 @@ see_update_leader_extra_info (struct web_entry *first, struct web_entry *second)
            {
            case SIGN_EXTENDED_DEF:
              first_ei->relevancy = NOT_RELEVANT;
-             return false;
+             break;
            case RELEVANT_USE:
-             return false;
+             break;
            case ZERO_EXTENDED_DEF:
              first_ei->relevancy = ZERO_EXTENDED_DEF;
              first_ei->source_mode =
                (first_ei->source_mode_unsigned > second_ei->source_mode) ?
                first_ei->source_mode_unsigned : second_ei->source_mode;
-             return false;
+             break;
            case EXTENDED_DEF:
              if (second_ei->source_mode_unsigned == MAX_MACHINE_MODE)
                first_ei->relevancy = NOT_RELEVANT;
@@ -1223,7 +1216,7 @@ see_update_leader_extra_info (struct web_entry *first, struct web_entry *second)
                  second_ei->source_mode_unsigned) ?
                  first_ei->source_mode_unsigned :
                  second_ei->source_mode_unsigned;
-             return false;
+             break;
            default:
              gcc_unreachable ();
            }
@@ -1239,12 +1232,12 @@ see_update_leader_extra_info (struct web_entry *first, struct web_entry *second)
              first_ei->source_mode =
                (first_ei->source_mode_signed > second_ei->source_mode) ?
                first_ei->source_mode_signed : second_ei->source_mode;
-             return false;
+             break;
            case RELEVANT_USE:
-             return false;
+             break;
            case ZERO_EXTENDED_DEF:
              first_ei->relevancy = NOT_RELEVANT;
-             return false;
+             break;
            case EXTENDED_DEF:
              if (second_ei->source_mode_signed == MAX_MACHINE_MODE)
                first_ei->relevancy = NOT_RELEVANT;
@@ -1253,15 +1246,18 @@ see_update_leader_extra_info (struct web_entry *first, struct web_entry *second)
                  (first_ei->source_mode_signed >
                  second_ei->source_mode_signed) ?
                  first_ei->source_mode_signed : second_ei->source_mode_signed;
-             return false;
+             break;
            default:
              gcc_unreachable ();
            }
        }
+      break;
     default:
       /* Unknown patern type.  */
       gcc_unreachable ();
     }
+
+  return false;
 }
 
 
@@ -1331,22 +1327,29 @@ see_free_data_structures (void)
 static void
 see_initialize_data_structures (void)
 {
+  unsigned int max_reg = max_reg_num ();
+  unsigned int i;
+
   /* Build the df object. */
-  df = df_init (DF_HARD_REGS | DF_EQUIV_NOTES |        DF_SUBREGS);
-  df_rd_add_problem (df);
-  /* df_ru_add_problem (df); */
-  df_chain_add_problem (df, DF_DU_CHAIN | DF_UD_CHAIN);
-  df_analyze (df);
+  df_set_flags (DF_EQ_NOTES);
+  df_chain_add_problem (DF_DU_CHAIN + DF_UD_CHAIN);
+  df_analyze ();
+  df_set_flags (DF_DEFER_INSN_RESCAN);
 
   if (dump_file)
-    df_dump (df, dump_file);
+    df_dump (dump_file);
 
   /* Record the last basic block at the beginning of the optimization.  */
   last_bb = last_basic_block;
-  /* Record the number of uses at the beginning of the optimization.  */
-  uses_num = DF_USES_SIZE (df);
-  /* Record the number of definitions at the beginning of the optimization.  */
-  defs_num = DF_DEFS_SIZE (df);
+
+  /* Record the number of uses and defs at the beginning of the optimization.  */
+  uses_num = 0;
+  defs_num = 0;
+  for (i = 0; i < max_reg; i++) 
+    {
+      uses_num += DF_REG_USE_COUNT (i) + DF_REG_EQ_USE_COUNT (i);
+      defs_num += DF_REG_DEF_COUNT (i);
+    }
 
   /*  Allocate web entries array for the union-find data structure.  */
   def_entry = xcalloc (defs_num, sizeof (struct web_entry));
@@ -1362,9 +1365,10 @@ see_initialize_data_structures (void)
 
   /*  Allocate the extension hash.  It will hold the extensions that we want
       to PRE.  */
-  see_pre_extension_hash =
-    htab_create (10, hash_descriptor_pre_extension, eq_descriptor_pre_extension,
-                hash_del_pre_extension);
+  see_pre_extension_hash = htab_create (10, 
+                                       hash_descriptor_pre_extension, 
+                                       eq_descriptor_pre_extension,
+                                       hash_del_pre_extension);
 }
 
 
@@ -1402,7 +1406,7 @@ static bool
 see_want_to_be_merged_with_extension (rtx ref, rtx extension,
                                      enum extension_type type)
 {
-  rtx pat = NULL;
+  rtx pat;
   rtx dest_extension_reg = see_get_extension_reg (extension, 1);
   rtx source_extension_reg = see_get_extension_reg (extension, 0);
   enum rtx_code code;
@@ -1418,16 +1422,16 @@ see_want_to_be_merged_with_extension (rtx ref, rtx extension,
        {
          rtx sub = XVECEXP (pat, 0, i);
 
-         if ((GET_CODE (sub) == SET)
-               && (REG_P (SET_DEST (sub))
-                   || ((GET_CODE (SET_DEST (sub)) == SUBREG)
-                       && (REG_P (SUBREG_REG (SET_DEST (sub))))))
-               && (REG_P (SET_SRC (sub))
-                   || ((GET_CODE (SET_SRC (sub)) == SUBREG)
-                       && (REG_P (SUBREG_REG (SET_SRC (sub)))))))
+         if (GET_CODE (sub) == SET
+             && (REG_P (SET_DEST (sub))
+                 || (GET_CODE (SET_DEST (sub)) == SUBREG
+                     && REG_P (SUBREG_REG (SET_DEST (sub)))))
+             && (REG_P (SET_SRC (sub))
+                 || (GET_CODE (SET_SRC (sub)) == SUBREG
+                     && REG_P (SUBREG_REG (SET_SRC (sub))))))
            {
              /* This is a simple move SET.  */
-             if ((type == DEF_EXTENSION)
+             if (type == DEF_EXTENSION
                  && reg_mentioned_p (source_extension_reg, SET_DEST (sub)))
                return false;
            }
@@ -1450,13 +1454,13 @@ see_want_to_be_merged_with_extension (rtx ref, rtx extension,
     }
   else
     {
-      if ((code == SET)
+      if (code == SET
          && (REG_P (SET_DEST (pat))
-             || ((GET_CODE (SET_DEST (pat)) == SUBREG)
-                 && (REG_P (SUBREG_REG (SET_DEST (pat))))))
+             || (GET_CODE (SET_DEST (pat)) == SUBREG
+                 && REG_P (SUBREG_REG (SET_DEST (pat)))))
          && (REG_P (SET_SRC (pat))
-             || ((GET_CODE (SET_SRC (pat)) == SUBREG)
-                 && (REG_P (SUBREG_REG (SET_SRC (pat)))))))
+             || (GET_CODE (SET_SRC (pat)) == SUBREG
+                 && REG_P (SUBREG_REG (SET_SRC (pat))))))
        /* This is a simple move SET.  */
        return false;
      }
@@ -1581,7 +1585,7 @@ see_emit_use_extension (void **slot, void *b)
       print_rtl_single (dump_file, use_se);
     }
 
-  add_insn_before (use_se, curr_ref_s->insn);
+  add_insn_before (use_se, curr_ref_s->insn, NULL);
 
   return 1;
 }
@@ -1802,11 +1806,6 @@ see_commit_changes (void)
      the first place.  */
   htab_traverse (see_pre_extension_hash, see_pre_delete_extension, NULL);
 
-  /* At this point, we must free the DF object, since the number of basic blocks
-     may change.  */
-  df_finish (df);
-  df = NULL;
-
   /* Insert extensions on edges, according to the LCM result.  */
   did_insert = see_pre_insert_extensions (index_map);
 
@@ -1846,12 +1845,11 @@ see_analyze_merged_def_local_prop (void **slot, void *b)
   rtx def_se = *slot;
   struct see_ref_s *curr_ref_s = (struct see_ref_s *) b;
   rtx ref = curr_ref_s->insn;
-  struct see_pre_extension_expr *extension_expr = NULL;
+  struct see_pre_extension_expr *extension_expr;
   int indx;
   int bb_num = BLOCK_NUM (ref);
-  htab_t curr_bb_hash = NULL;
-  struct see_register_properties *curr_prop = NULL;
-  struct see_register_properties **slot_prop = NULL;
+  htab_t curr_bb_hash;
+  struct see_register_properties *curr_prop, **slot_prop;
   struct see_register_properties temp_prop;
   rtx dest_extension_reg = see_get_extension_reg (def_se, 1);
   struct see_occr *curr_occr = NULL;
@@ -1877,7 +1875,7 @@ see_analyze_merged_def_local_prop (void **slot, void *b)
   /* Reset the killed bit.  */
   RESET_BIT (ae_kill[bb_num], indx);
 
-  if (curr_prop->first_se_after_last_def == DF_INSN_LUID (df, ref))
+  if (curr_prop->first_se_after_last_def == DF_INSN_LUID (ref))
     {
       /* Set the available bit.  */
       SET_BIT (comp[bb_num], indx);
@@ -1915,12 +1913,11 @@ see_analyze_unmerged_def_local_prop (void **slot, void *b)
   rtx def_se = *slot;
   struct see_ref_s *curr_ref_s = (struct see_ref_s *) b;
   rtx ref = curr_ref_s->insn;
-  struct see_pre_extension_expr *extension_expr = NULL;
+  struct see_pre_extension_expr *extension_expr;
   int indx;
   int bb_num = BLOCK_NUM (ref);
-  htab_t curr_bb_hash = NULL;
-  struct see_register_properties *curr_prop = NULL;
-  struct see_register_properties **slot_prop = NULL;
+  htab_t curr_bb_hash;
+  struct see_register_properties *curr_prop, **slot_prop;
   struct see_register_properties temp_prop;
   rtx dest_extension_reg = see_get_extension_reg (def_se, 1);
 
@@ -1964,13 +1961,12 @@ see_analyze_use_local_prop (void **slot, void *b)
   rtx use_se = *slot;
   rtx ref = curr_ref_s->insn;
   rtx dest_extension_reg = see_get_extension_reg (use_se, 1);
-  struct see_pre_extension_expr *extension_expr = NULL;
-  struct see_register_properties *curr_prop = NULL;
-  struct see_register_properties **slot_prop = NULL;
+  struct see_pre_extension_expr *extension_expr;
+  struct see_register_properties *curr_prop, **slot_prop;
   struct see_register_properties temp_prop;
   struct see_occr *curr_occr = NULL;
   struct see_occr *tmp_occr = NULL;
-  htab_t curr_bb_hash = NULL;
+  htab_t curr_bb_hash;
   int indx;
   int bb_num = BLOCK_NUM (ref);
 
@@ -1989,7 +1985,7 @@ see_analyze_use_local_prop (void **slot, void *b)
 
   indx = extension_expr->bitmap_index;
 
-  if (curr_prop->first_se_before_any_def == DF_INSN_LUID (df, ref))
+  if (curr_prop->first_se_before_any_def == DF_INSN_LUID (ref))
     {
       /* Set the anticipatable bit.  */
       SET_BIT (antloc[bb_num], indx);
@@ -2029,7 +2025,7 @@ see_analyze_use_local_prop (void **slot, void *b)
       /* Note: there is no need to reset the killed bit since it must be zero at
         this point.  */
     }
-  else if (curr_prop->first_se_after_last_def == DF_INSN_LUID (df, ref))
+  else if (curr_prop->first_se_after_last_def == DF_INSN_LUID (ref))
     {
       /* Set the available bit.  */
       SET_BIT (comp[bb_num], indx);
@@ -2146,7 +2142,7 @@ see_execute_LCM (void)
 /* In this function we set the register properties for the register that is
    defined and extended in the reference.
    The properties are defined in see_register_properties structure which is
-   allocated per basic bloack and per register.
+   allocated per basic block and per register.
    Later the extension is inserted into the see_pre_extension_hash for the next
    phase of the optimization.
 
@@ -2163,19 +2159,20 @@ see_set_prop_merged_def (void **slot, void *b)
   struct see_ref_s *curr_ref_s = (struct see_ref_s *) b;
   rtx insn = curr_ref_s->insn;
   rtx dest_extension_reg = see_get_extension_reg (def_se, 1);
-  htab_t curr_bb_hash = NULL;
+  htab_t curr_bb_hash;
   struct see_register_properties *curr_prop = NULL;
-  struct see_register_properties **slot_prop = NULL;
+  struct see_register_properties **slot_prop;
   struct see_register_properties temp_prop;
-  int ref_luid = DF_INSN_LUID (df, insn);
+  int ref_luid = DF_INSN_LUID (insn);
 
   curr_bb_hash = see_bb_hash_ar[BLOCK_NUM (curr_ref_s->insn)];
   if (!curr_bb_hash)
     {
       /* The hash doesn't exist yet.  Create it.  */
-      curr_bb_hash =
-       htab_create (10, hash_descriptor_properties, eq_descriptor_properties,
-                    hash_del_properties);
+      curr_bb_hash = htab_create (10, 
+                                 hash_descriptor_properties, 
+                                 eq_descriptor_properties,
+                                 hash_del_properties);
       see_bb_hash_ar[BLOCK_NUM (curr_ref_s->insn)] = curr_bb_hash;
     }
 
@@ -2185,7 +2182,7 @@ see_set_prop_merged_def (void **slot, void *b)
     (struct see_register_properties **) htab_find_slot (curr_bb_hash,
                                                        &temp_prop, INSERT);
 
-  if (slot_prop && (*slot_prop != NULL))
+  if (slot_prop && *slot_prop != NULL)
     {
       /* Property already exists.  */
       curr_prop = *slot_prop;
@@ -2216,7 +2213,7 @@ see_set_prop_merged_def (void **slot, void *b)
 /* In this function we set the register properties for the register that is
    defined but not extended in the reference.
    The properties are defined in see_register_properties structure which is
-   allocated per basic bloack and per register.
+   allocated per basic block and per register.
    Later the extension is inserted into the see_pre_extension_hash for the next
    phase of the optimization.
 
@@ -2233,19 +2230,20 @@ see_set_prop_unmerged_def (void **slot, void *b)
   struct see_ref_s *curr_ref_s = (struct see_ref_s *) b;
   rtx insn = curr_ref_s->insn;
   rtx dest_extension_reg = see_get_extension_reg (def_se, 1);
-  htab_t curr_bb_hash = NULL;
+  htab_t curr_bb_hash;
   struct see_register_properties *curr_prop = NULL;
-  struct see_register_properties **slot_prop = NULL;
+  struct see_register_properties **slot_prop;
   struct see_register_properties temp_prop;
-  int ref_luid = DF_INSN_LUID (df, insn);
+  int ref_luid = DF_INSN_LUID (insn);
 
   curr_bb_hash = see_bb_hash_ar[BLOCK_NUM (curr_ref_s->insn)];
   if (!curr_bb_hash)
     {
       /* The hash doesn't exist yet.  Create it.  */
-      curr_bb_hash =
-       htab_create (10, hash_descriptor_properties, eq_descriptor_properties,
-                    hash_del_properties);
+      curr_bb_hash = htab_create (10, 
+                                 hash_descriptor_properties, 
+                                 eq_descriptor_properties,
+                                 hash_del_properties);
       see_bb_hash_ar[BLOCK_NUM (curr_ref_s->insn)] = curr_bb_hash;
     }
 
@@ -2255,7 +2253,7 @@ see_set_prop_unmerged_def (void **slot, void *b)
     (struct see_register_properties **) htab_find_slot (curr_bb_hash,
                                                        &temp_prop, INSERT);
 
-  if (slot_prop && (*slot_prop != NULL))
+  if (slot_prop && *slot_prop != NULL)
     {
       /* Property already exists.  */
       curr_prop = *slot_prop;
@@ -2286,7 +2284,7 @@ see_set_prop_unmerged_def (void **slot, void *b)
 /* In this function we set the register properties for the register that is used
    in the reference.
    The properties are defined in see_register_properties structure which is
-   allocated per basic bloack and per register.
+   allocated per basic block and per register.
    When a redundant use extension is found it is removed from the hash of the
    reference.
    If the extension is non redundant it is inserted into the
@@ -2305,20 +2303,21 @@ see_set_prop_unmerged_use (void **slot, void *b)
   struct see_ref_s *curr_ref_s = (struct see_ref_s *) b;
   rtx insn = curr_ref_s->insn;
   rtx dest_extension_reg = see_get_extension_reg (use_se, 1);
-  htab_t curr_bb_hash = NULL;
+  htab_t curr_bb_hash;
   struct see_register_properties *curr_prop = NULL;
-  struct see_register_properties **slot_prop = NULL;
+  struct see_register_properties **slot_prop;
   struct see_register_properties temp_prop;
   bool locally_redundant = false;
-  int ref_luid = DF_INSN_LUID (df, insn);
+  int ref_luid = DF_INSN_LUID (insn);
 
   curr_bb_hash = see_bb_hash_ar[BLOCK_NUM (curr_ref_s->insn)];
   if (!curr_bb_hash)
     {
       /* The hash doesn't exist yet.  Create it.  */
-      curr_bb_hash =
-       htab_create (10, hash_descriptor_properties, eq_descriptor_properties,
-                    hash_del_properties);
+      curr_bb_hash = htab_create (10, 
+                                 hash_descriptor_properties, 
+                                 eq_descriptor_properties,
+                                 hash_del_properties);
       see_bb_hash_ar[BLOCK_NUM (curr_ref_s->insn)] = curr_bb_hash;
     }
 
@@ -2328,29 +2327,29 @@ see_set_prop_unmerged_use (void **slot, void *b)
     (struct see_register_properties **) htab_find_slot (curr_bb_hash,
                                                        &temp_prop, INSERT);
 
-  if (slot_prop && (*slot_prop != NULL))
+  if (slot_prop && *slot_prop != NULL)
     {
       /* Property already exists.  */
       curr_prop = *slot_prop;
       gcc_assert (curr_prop->regno == REGNO (dest_extension_reg));
 
 
-      if ((curr_prop->last_def < 0) && (curr_prop->first_se_before_any_def < 0))
+      if (curr_prop->last_def < 0 && curr_prop->first_se_before_any_def < 0)
        curr_prop->first_se_before_any_def = ref_luid;
-      else if ((curr_prop->last_def < 0)
-              && (curr_prop->first_se_before_any_def >= 0))
+      else if (curr_prop->last_def < 0
+              && curr_prop->first_se_before_any_def >= 0)
        {
-         /* In this case the extension is localy redundant.  */
+         /* In this case the extension is locally redundant.  */
          htab_clear_slot (curr_ref_s->use_se_hash, (PTR *)slot);
          locally_redundant = true;
        }
-      else if ((curr_prop->last_def >= 0)
-              && (curr_prop->first_se_after_last_def < 0))
+      else if (curr_prop->last_def >= 0
+              && curr_prop->first_se_after_last_def < 0)
        curr_prop->first_se_after_last_def = ref_luid;
-      else if ((curr_prop->last_def >= 0)
-         && (curr_prop->first_se_after_last_def >= 0))
+      else if (curr_prop->last_def >= 0
+              && curr_prop->first_se_after_last_def >= 0)
        {
-         /* In this case the extension is localy redundant.  */
+         /* In this case the extension is locally redundant.  */
          htab_clear_slot (curr_ref_s->use_se_hash, (PTR *)slot);
          locally_redundant = true;
        }
@@ -2413,6 +2412,41 @@ see_replace_src (rtx *x, void *data)
 }
 
 
+static rtx
+see_copy_insn (rtx insn)
+{
+  rtx pat = copy_insn (PATTERN (insn)), ret;
+
+  if (NONJUMP_INSN_P (insn))
+    ret = make_insn_raw (pat);
+  else if (JUMP_P (insn))
+    ret = make_jump_insn_raw (pat);
+  else if (CALL_P (insn))
+    {
+      start_sequence ();
+      ret = emit_call_insn (pat);
+      end_sequence ();
+      if (CALL_INSN_FUNCTION_USAGE (insn))
+       CALL_INSN_FUNCTION_USAGE (ret)
+         = copy_rtx (CALL_INSN_FUNCTION_USAGE (insn));
+      SIBLING_CALL_P (ret) = SIBLING_CALL_P (insn);
+      RTL_CONST_CALL_P (ret) = RTL_CONST_CALL_P (insn);
+      RTL_PURE_CALL_P (ret) = RTL_PURE_CALL_P (insn);
+      RTL_LOOPING_CONST_OR_PURE_CALL_P (ret) 
+       = RTL_LOOPING_CONST_OR_PURE_CALL_P (insn);
+    }
+  else
+    gcc_unreachable ();
+  if (REG_NOTES (insn))
+    REG_NOTES (ret) = copy_rtx (REG_NOTES (insn));
+  INSN_LOCATOR (ret) = INSN_LOCATOR (insn);
+  RTX_FRAME_RELATED_P (ret) = RTX_FRAME_RELATED_P (insn);
+  PREV_INSN (ret) = NULL_RTX;
+  NEXT_INSN (ret) = NULL_RTX;
+  return ret;
+}
+
+
 /* At this point the pattern is expected to be:
 
    ref:            set (dest_reg) (rhs)
@@ -2444,31 +2478,27 @@ see_def_extension_not_merged (struct see_ref_s *curr_ref_s, rtx def_se)
   struct see_replace_data d;
   /* If the original insn was already merged with an extension before,
      take the merged one.  */
-  rtx ref = (curr_ref_s->merged_insn) ? curr_ref_s->merged_insn :
-                                       curr_ref_s->insn;
-  rtx merged_ref_next = (curr_ref_s->merged_insn) ?
-                       NEXT_INSN (curr_ref_s->merged_insn): NULL_RTX;
-  rtx ref_copy = copy_rtx (ref);
-  rtx dest_reg = NULL;
-  rtx dest_real_reg = NULL;
+  rtx ref = curr_ref_s->merged_insn
+           ? curr_ref_s->merged_insn : curr_ref_s->insn;
+  rtx merged_ref_next = curr_ref_s->merged_insn
+                       ? NEXT_INSN (curr_ref_s->merged_insn) : NULL_RTX;
+  rtx ref_copy = see_copy_insn (ref);
   rtx source_extension_reg = see_get_extension_reg (def_se, 0);
   rtx dest_extension_reg = see_get_extension_reg (def_se, 1);
-  rtx new_pseudo_reg = NULL;
-  rtx subreg = NULL;
-  rtx move_insn = NULL;
-  rtx set = NULL;
-  rtx rhs = NULL;
+  rtx set, rhs;
+  rtx dest_reg, dest_real_reg;
+  rtx new_pseudo_reg, subreg;
   enum machine_mode source_extension_mode = GET_MODE (source_extension_reg);
   enum machine_mode dest_mode;
 
   set = single_set (def_se);
   gcc_assert (set);
   rhs = SET_SRC (set);
-  gcc_assert ((GET_CODE (rhs) == SIGN_EXTEND)
-             || (GET_CODE (rhs) == ZERO_EXTEND));
+  gcc_assert (GET_CODE (rhs) == SIGN_EXTEND
+             || GET_CODE (rhs) == ZERO_EXTEND);
   dest_reg = XEXP (rhs, 0);
   gcc_assert (REG_P (dest_reg)
-             || ((GET_CODE (dest_reg) == SUBREG)
+             || (GET_CODE (dest_reg) == SUBREG
                  && REG_P (SUBREG_REG (dest_reg))));
   dest_real_reg = REG_P (dest_reg) ? dest_reg : SUBREG_REG (dest_reg);
   dest_mode = GET_MODE (dest_reg);
@@ -2481,7 +2511,7 @@ see_def_extension_not_merged (struct see_ref_s *curr_ref_s, rtx def_se)
   d.to = new_pseudo_reg;
   note_uses (&PATTERN (ref_copy), see_replace_src, &d);
   /* Step b: Replace every instance of dest_reg with the subreg.  */
-  ref_copy = replace_rtx (ref_copy, dest_reg, subreg);
+  ref_copy = replace_rtx (ref_copy, dest_reg, copy_rtx (subreg));
 
   /* Step c: Replace every use of the new pseudo register back to
      dest_real_reg.  */
@@ -2493,25 +2523,22 @@ see_def_extension_not_merged (struct see_ref_s *curr_ref_s, rtx def_se)
       || insn_invalid_p (ref_copy))
     {
       /* The manipulation failed.  */
+      df_insn_delete (NULL, INSN_UID (ref_copy));
 
       /* Create a new copy.  */
-      ref_copy = copy_rtx (ref);
+      ref_copy = see_copy_insn (ref);
+
+      if (curr_ref_s->merged_insn)
+        df_insn_delete (NULL, INSN_UID (curr_ref_s->merged_insn));
 
       /* Create a simple move instruction that will replace the def_se.  */
       start_sequence ();
+      emit_insn (ref_copy);
       emit_move_insn (subreg, dest_reg);
-      move_insn = get_insns ();
-      end_sequence ();
-
-      /* Link the manipulated instruction to the newly created move instruction
-        and to the former created move instructions.  */
-      PREV_INSN (ref_copy) = NULL_RTX;
-      NEXT_INSN (ref_copy) = move_insn;
-      PREV_INSN (move_insn) = ref_copy;
-      NEXT_INSN (move_insn) = merged_ref_next;
       if (merged_ref_next != NULL_RTX)
-       PREV_INSN (merged_ref_next) = move_insn;
-      curr_ref_s->merged_insn = ref_copy;
+       emit_insn (merged_ref_next);
+      curr_ref_s->merged_insn = get_insns ();
+      end_sequence ();
 
       if (dump_file)
        {
@@ -2520,7 +2547,7 @@ see_def_extension_not_merged (struct see_ref_s *curr_ref_s, rtx def_se)
          fprintf (dump_file, "Original ref:\n");
          print_rtl_single (dump_file, ref);
          fprintf (dump_file, "Move insn that was added:\n");
-         print_rtl_single (dump_file, move_insn);
+         print_rtl_single (dump_file, NEXT_INSN (curr_ref_s->merged_insn));
        }
       return;
     }
@@ -2530,21 +2557,17 @@ see_def_extension_not_merged (struct see_ref_s *curr_ref_s, rtx def_se)
   /* Try to simplify the new manipulated insn.  */
   validate_simplify_insn (ref_copy);
 
+  if (curr_ref_s->merged_insn)
+    df_insn_delete (NULL, INSN_UID (curr_ref_s->merged_insn));
+
   /* Create a simple move instruction to assure the correctness of the code.  */
   start_sequence ();
+  emit_insn (ref_copy);
   emit_move_insn (dest_reg, subreg);
-  move_insn = get_insns ();
-  end_sequence ();
-
-  /* Link the manipulated instruction to the newly created move instruction and
-     to the former created move instructions.  */
-  PREV_INSN (ref_copy) = NULL_RTX;
-  NEXT_INSN (ref_copy) = move_insn;
-  PREV_INSN (move_insn) = ref_copy;
-  NEXT_INSN (move_insn) = merged_ref_next;
   if (merged_ref_next != NULL_RTX)
-    PREV_INSN (merged_ref_next) = move_insn;
-  curr_ref_s->merged_insn = ref_copy;
+    emit_insn (merged_ref_next);
+  curr_ref_s->merged_insn = get_insns ();
+  end_sequence ();
 
   if (dump_file)
     {
@@ -2552,9 +2575,9 @@ see_def_extension_not_merged (struct see_ref_s *curr_ref_s, rtx def_se)
       fprintf (dump_file, "Original ref:\n");
       print_rtl_single (dump_file, ref);
       fprintf (dump_file, "Transformed ref:\n");
-      print_rtl_single (dump_file, ref_copy);
+      print_rtl_single (dump_file, curr_ref_s->merged_insn);
       fprintf (dump_file, "Move insn that was added:\n");
-      print_rtl_single (dump_file, move_insn);
+      print_rtl_single (dump_file, NEXT_INSN (curr_ref_s->merged_insn));
     }
 }
 
@@ -2586,11 +2609,11 @@ see_merge_one_use_extension (void **slot, void *b)
 {
   struct see_ref_s *curr_ref_s = (struct see_ref_s *) b;
   rtx use_se = *slot;
-  rtx ref = (curr_ref_s->merged_insn) ? curr_ref_s->merged_insn :
-                                       curr_ref_s->insn;
-  rtx merged_ref_next = (curr_ref_s->merged_insn) ?
-                       NEXT_INSN (curr_ref_s->merged_insn): NULL_RTX;
-  rtx ref_copy = copy_rtx (ref);
+  rtx ref = curr_ref_s->merged_insn
+           ? curr_ref_s->merged_insn : curr_ref_s->insn;
+  rtx merged_ref_next = curr_ref_s->merged_insn
+                       ? NEXT_INSN (curr_ref_s->merged_insn) : NULL_RTX;
+  rtx ref_copy = see_copy_insn (ref);
   rtx extension_set = single_set (use_se);
   rtx extension_rhs = NULL;
   rtx dest_extension_reg = see_get_extension_reg (use_se, 1);
@@ -2616,7 +2639,8 @@ see_merge_one_use_extension (void **slot, void *b)
        /* Replacement failed.  Remove the note.  */
        remove_note (ref_copy, note);
       else
-       XEXP (note, 0) = simplified_note;
+       set_unique_reg_note (ref_copy, REG_NOTE_KIND (note),
+                            simplified_note);
     }
 
   if (!see_want_to_be_merged_with_extension (ref, use_se, USE_EXTENSION))
@@ -2629,6 +2653,7 @@ see_merge_one_use_extension (void **slot, void *b)
          print_rtl_single (dump_file, use_se);
          print_rtl_single (dump_file, ref);
        }
+      df_insn_delete (NULL, INSN_UID (ref_copy));
       /* Don't remove the current use_se from the use_se_hash and continue to
         the next extension.  */
       return 1;
@@ -2647,11 +2672,20 @@ see_merge_one_use_extension (void **slot, void *b)
          print_rtl_single (dump_file, ref);
        }
       htab_clear_slot (curr_ref_s->use_se_hash, (PTR *)slot);
-      PREV_INSN (ref_copy) = NULL_RTX;
-      NEXT_INSN (ref_copy) = merged_ref_next;
+
+      if (curr_ref_s->merged_insn)
+       df_insn_delete (NULL, INSN_UID (curr_ref_s->merged_insn));
+
       if (merged_ref_next != NULL_RTX)
-       PREV_INSN (merged_ref_next) = ref_copy;
-      curr_ref_s->merged_insn = ref_copy;
+       {
+         start_sequence ();
+         emit_insn (ref_copy);
+         emit_insn (merged_ref_next);
+         curr_ref_s->merged_insn = get_insns ();
+         end_sequence ();
+       }
+      else
+       curr_ref_s->merged_insn = ref_copy;
       return 1;
     }
 
@@ -2665,6 +2699,7 @@ see_merge_one_use_extension (void **slot, void *b)
          print_rtl_single (dump_file, use_se);
          print_rtl_single (dump_file, ref);
        }
+      df_insn_delete (NULL, INSN_UID (ref_copy));
       /* Don't remove the current use_se from the use_se_hash and continue to
         the next extension.  */
       return 1;
@@ -2675,11 +2710,19 @@ see_merge_one_use_extension (void **slot, void *b)
   /* Try to simplify the new merged insn.  */
   validate_simplify_insn (ref_copy);
 
-  PREV_INSN (ref_copy) = NULL_RTX;
-  NEXT_INSN (ref_copy) = merged_ref_next;
+  if (curr_ref_s->merged_insn)
+    df_insn_delete (NULL, INSN_UID (curr_ref_s->merged_insn));
+
   if (merged_ref_next != NULL_RTX)
-    PREV_INSN (merged_ref_next) = ref_copy;
-  curr_ref_s->merged_insn = ref_copy;
+    {
+      start_sequence ();
+      emit_insn (ref_copy);
+      emit_insn (merged_ref_next);
+      curr_ref_s->merged_insn = get_insns ();
+      end_sequence ();
+    }
+  else
+    curr_ref_s->merged_insn = ref_copy;
 
   if (dump_file)
     {
@@ -2688,7 +2731,7 @@ see_merge_one_use_extension (void **slot, void *b)
       print_rtl_single (dump_file, use_se);
       print_rtl_single (dump_file, ref);
       fprintf (dump_file, "Merged instruction:\n");
-      print_rtl_single (dump_file, ref_copy);
+      print_rtl_single (dump_file, curr_ref_s->merged_insn);
     }
 
   /* Remove the current use_se from the use_se_hash.  This will prevent it from
@@ -2706,7 +2749,7 @@ see_merge_one_use_extension (void **slot, void *b)
    ref:           set (dest_reg) (rhs)
    def_se: set (dest_extension_reg) (sign/zero_extend (source_extension_reg))
 
-   where dest_reg and source_extension_reg can both be subregs (togather)
+   where dest_reg and source_extension_reg can both be subregs (together)
    and (REGNO (dest_reg) == REGNO (source_extension_reg))
 
    The merge is done by generating, simplifying and recognizing the pattern:
@@ -2729,20 +2772,18 @@ see_merge_one_def_extension (void **slot, void *b)
   rtx def_se = *slot;
   /* If the original insn was already merged with an extension before,
      take the merged one.  */
-  rtx ref = (curr_ref_s->merged_insn) ? curr_ref_s->merged_insn :
-                                       curr_ref_s->insn;
-  rtx merged_ref_next = (curr_ref_s->merged_insn) ?
-                       NEXT_INSN (curr_ref_s->merged_insn): NULL_RTX;
-  rtx ref_copy = copy_rtx (ref);
+  rtx ref = curr_ref_s->merged_insn
+           ? curr_ref_s->merged_insn : curr_ref_s->insn;
+  rtx merged_ref_next = curr_ref_s->merged_insn
+                       ? NEXT_INSN (curr_ref_s->merged_insn) : NULL_RTX;
+  rtx ref_copy = see_copy_insn (ref);
   rtx new_set = NULL;
   rtx source_extension_reg = see_get_extension_reg (def_se, 0);
   rtx dest_extension_reg = see_get_extension_reg (def_se, 1);
-  rtx move_insn = NULL;
-  rtx *rtx_slot = NULL;
-  rtx subreg = NULL;
+  rtx *rtx_slot, subreg;
   rtx temp_extension = NULL;
   rtx simplified_temp_extension = NULL;
-  rtx *pat = NULL;
+  rtx *pat;
   enum rtx_code code;
   enum rtx_code extension_code;
   enum machine_mode source_extension_mode;
@@ -2768,6 +2809,7 @@ see_merge_one_def_extension (void **slot, void *b)
          print_rtl_single (dump_file, def_se);
        }
 
+      df_insn_delete (NULL, INSN_UID (ref_copy));
       see_def_extension_not_merged (curr_ref_s, def_se);
       /* Continue to the next extension.  */
       return 1;
@@ -2790,15 +2832,15 @@ see_merge_one_def_extension (void **slot, void *b)
        {
          rtx *sub = &XVECEXP (*pat, 0, i);
 
-         if ((GET_CODE (*sub) == SET)
-             && (GET_MODE (SET_SRC (*sub)) != VOIDmode)
-             && (GET_MODE (SET_DEST (*sub)) == source_mode)
+         if (GET_CODE (*sub) == SET
+             && GET_MODE (SET_SRC (*sub)) != VOIDmode
+             && GET_MODE (SET_DEST (*sub)) == source_mode
              && ((REG_P (SET_DEST (*sub))
-                 && (REGNO (SET_DEST (*sub)) == REGNO (source_extension_reg)))
-                || ((GET_CODE (SET_DEST (*sub)) == SUBREG)
-                    && (REG_P (SUBREG_REG (SET_DEST (*sub))))
-                    && (REGNO (SUBREG_REG (SET_DEST (*sub))) ==
-                        REGNO (source_extension_reg)))))
+                  && REGNO (SET_DEST (*sub)) == REGNO (source_extension_reg))
+                 || (GET_CODE (SET_DEST (*sub)) == SUBREG
+                     && REG_P (SUBREG_REG (SET_DEST (*sub)))
+                     && (REGNO (SUBREG_REG (SET_DEST (*sub))) ==
+                         REGNO (source_extension_reg)))))
            {
              rtx orig_src = SET_SRC (*sub);
 
@@ -2822,13 +2864,13 @@ see_merge_one_def_extension (void **slot, void *b)
        if (apply_change_group ())
          merge_success = true;
     }
-  else if ((code == SET)
-          && (GET_MODE (SET_SRC (*pat)) != VOIDmode)
-          && (GET_MODE (SET_DEST (*pat)) == source_mode)
+  else if (code == SET
+          && GET_MODE (SET_SRC (*pat)) != VOIDmode
+          && GET_MODE (SET_DEST (*pat)) == source_mode
           && ((REG_P (SET_DEST (*pat))
                && REGNO (SET_DEST (*pat)) == REGNO (source_extension_reg))
-              || ((GET_CODE (SET_DEST (*pat)) == SUBREG)
-                  && (REG_P (SUBREG_REG (SET_DEST (*pat))))
+              || (GET_CODE (SET_DEST (*pat)) == SUBREG
+                  && REG_P (SUBREG_REG (SET_DEST (*pat)))
                   && (REGNO (SUBREG_REG (SET_DEST (*pat))) ==
                       REGNO (source_extension_reg)))))
     {
@@ -2856,29 +2898,25 @@ see_merge_one_def_extension (void **slot, void *b)
          print_rtl_single (dump_file, def_se);
        }
 
+      df_insn_delete (NULL, INSN_UID (ref_copy));
       see_def_extension_not_merged (curr_ref_s, def_se);
       /* Continue to the next extension.  */
       return 1;
     }
 
   /* The merge succeeded!  */
+  if (curr_ref_s->merged_insn)
+    df_insn_delete (NULL, INSN_UID (curr_ref_s->merged_insn));
 
   /* Create a simple move instruction to assure the correctness of the code.  */
   subreg = gen_lowpart_SUBREG (source_extension_mode, dest_extension_reg);
   start_sequence ();
+  emit_insn (ref_copy);
   emit_move_insn (source_extension_reg, subreg);
-  move_insn = get_insns ();
-  end_sequence ();
-
-  /* Link the merged instruction to the newly created move instruction and
-     to the former created move instructions.  */
-  PREV_INSN (ref_copy) = NULL_RTX;
-  NEXT_INSN (ref_copy) = move_insn;
-  PREV_INSN (move_insn) = ref_copy;
-  NEXT_INSN (move_insn) = merged_ref_next;
   if (merged_ref_next != NULL_RTX)
-    PREV_INSN (merged_ref_next) = move_insn;
-  curr_ref_s->merged_insn = ref_copy;
+    emit_insn (merged_ref_next);
+  curr_ref_s->merged_insn = get_insns ();
+  end_sequence ();
 
   if (dump_file)
     {
@@ -2887,18 +2925,19 @@ see_merge_one_def_extension (void **slot, void *b)
       print_rtl_single (dump_file, ref);
       print_rtl_single (dump_file, def_se);
       fprintf (dump_file, "Merged instruction:\n");
-      print_rtl_single (dump_file, ref_copy);
+      print_rtl_single (dump_file, curr_ref_s->merged_insn);
       fprintf (dump_file, "Move instruction that was added:\n");
-      print_rtl_single (dump_file, move_insn);
+      print_rtl_single (dump_file, NEXT_INSN (curr_ref_s->merged_insn));
     }
 
   /* Remove the current def_se from the unmerged_def_se_hash and insert it to
      the merged_def_se_hash.  */
   htab_clear_slot (curr_ref_s->unmerged_def_se_hash, (PTR *)slot);
   if (!curr_ref_s->merged_def_se_hash)
-    curr_ref_s->merged_def_se_hash =
-      htab_create (10, hash_descriptor_extension, eq_descriptor_extension,
-                  NULL);
+    curr_ref_s->merged_def_se_hash = htab_create (10, 
+                                                 hash_descriptor_extension, 
+                                                 eq_descriptor_extension,
+                                                 NULL);
   rtx_slot = (rtx *) htab_find_slot (curr_ref_s->merged_def_se_hash,
                                     dest_extension_reg, INSERT);
   gcc_assert (*rtx_slot == NULL);
@@ -2932,7 +2971,7 @@ see_handle_extensions_for_one_ref (splay_tree_node stn,
   htab_t use_se_hash = ((struct see_ref_s *) (stn->value))->use_se_hash;
   htab_t unmerged_def_se_hash =
     ((struct see_ref_s *) (stn->value))->unmerged_def_se_hash;
-  htab_t merged_def_se_hash = NULL;
+  htab_t merged_def_se_hash;
   rtx ref = ((struct see_ref_s *) (stn->value))->insn;
 
   if (dump_file)
@@ -3037,7 +3076,7 @@ static bool
 see_store_reference_and_extension (rtx ref_insn, rtx se_insn,
                                   enum extension_type type)
 {
-  rtx *rtx_slot = NULL;
+  rtx *rtx_slot;
   int curr_bb_num;
   splay_tree_node stn = NULL;
   htab_t se_hash = NULL;
@@ -3049,7 +3088,7 @@ see_store_reference_and_extension (rtx ref_insn, rtx se_insn,
     return false;
 
   curr_bb_num = BLOCK_NUM (ref_insn);
-  gcc_assert ((curr_bb_num < last_bb) && (curr_bb_num >= 0));
+  gcc_assert (curr_bb_num < last_bb && curr_bb_num >= 0);
 
   /* Insert the reference to the splay tree of its basic block.  */
   if (!see_bb_splay_ar[curr_bb_num])
@@ -3061,45 +3100,49 @@ see_store_reference_and_extension (rtx ref_insn, rtx se_insn,
        in it.  */
     {
       stn = splay_tree_lookup (see_bb_splay_ar[curr_bb_num],
-                              DF_INSN_LUID (df, ref_insn));
+                              DF_INSN_LUID (ref_insn));
       if (stn)
-       {
-         switch (type)
-           {
-           case EXPLICIT_DEF_EXTENSION:
-             se_hash =
-               ((struct see_ref_s *) (stn->value))->unmerged_def_se_hash;
-             if (!se_hash)
-               {
-                 se_hash = htab_create (10, hash_descriptor_extension,
-                                        eq_descriptor_extension, NULL);
-                 ((struct see_ref_s *) (stn->value))->unmerged_def_se_hash =
-                   se_hash;
-               }
-             break;
-           case IMPLICIT_DEF_EXTENSION:
-             se_hash = ((struct see_ref_s *) (stn->value))->merged_def_se_hash;
-             if (!se_hash)
-               {
-                 se_hash = htab_create (10, hash_descriptor_extension,
-                                        eq_descriptor_extension, NULL);
-                 ((struct see_ref_s *) (stn->value))->merged_def_se_hash =
-                   se_hash;
-               }
-             break;
-           case USE_EXTENSION:
-             se_hash = ((struct see_ref_s *) (stn->value))->use_se_hash;
-             if (!se_hash)
-               {
-                 se_hash = htab_create (10, hash_descriptor_extension,
-                                        eq_descriptor_extension, NULL);
-                 ((struct see_ref_s *) (stn->value))->use_se_hash = se_hash;
-               }
-             break;
-           default:
-             gcc_unreachable ();
-           }
-       }
+       switch (type)
+         {
+         case EXPLICIT_DEF_EXTENSION:
+           se_hash =
+             ((struct see_ref_s *) (stn->value))->unmerged_def_se_hash;
+           if (!se_hash)
+             {
+               se_hash = htab_create (10, 
+                                      hash_descriptor_extension,
+                                      eq_descriptor_extension, 
+                                      NULL);
+               ((struct see_ref_s *) (stn->value))->unmerged_def_se_hash =
+                 se_hash;
+             }
+           break;
+         case IMPLICIT_DEF_EXTENSION:
+           se_hash = ((struct see_ref_s *) (stn->value))->merged_def_se_hash;
+           if (!se_hash)
+             {
+               se_hash = htab_create (10, 
+                                      hash_descriptor_extension,
+                                      eq_descriptor_extension, 
+                                      NULL);
+               ((struct see_ref_s *) (stn->value))->merged_def_se_hash =
+                 se_hash;
+             }
+           break;
+         case USE_EXTENSION:
+           se_hash = ((struct see_ref_s *) (stn->value))->use_se_hash;
+           if (!se_hash)
+             {
+               se_hash = htab_create (10, 
+                                      hash_descriptor_extension,
+                                      eq_descriptor_extension, 
+                                      NULL);
+               ((struct see_ref_s *) (stn->value))->use_se_hash = se_hash;
+             }
+           break;
+         default:
+           gcc_unreachable ();
+         }
     }
 
   /* Initialize a new see_ref_s structure and insert it to the splay
@@ -3107,7 +3150,7 @@ see_store_reference_and_extension (rtx ref_insn, rtx se_insn,
   if (!stn)
     {
       ref_s = xmalloc (sizeof (struct see_ref_s));
-      ref_s->luid = DF_INSN_LUID (df, ref_insn);
+      ref_s->luid = DF_INSN_LUID (ref_insn);
       ref_s->insn = ref_insn;
       ref_s->merged_insn = NULL;
 
@@ -3115,25 +3158,28 @@ see_store_reference_and_extension (rtx ref_insn, rtx se_insn,
       switch (type)
        {
        case EXPLICIT_DEF_EXTENSION:
-         ref_s->unmerged_def_se_hash =
-           htab_create (10, hash_descriptor_extension, eq_descriptor_extension,
-                        NULL);
+         ref_s->unmerged_def_se_hash = htab_create (10, 
+                                                    hash_descriptor_extension, 
+                                                    eq_descriptor_extension,
+                                                    NULL);
          se_hash = ref_s->unmerged_def_se_hash;
          ref_s->merged_def_se_hash = NULL;
          ref_s->use_se_hash = NULL;
          break;
        case IMPLICIT_DEF_EXTENSION:
-         ref_s->merged_def_se_hash =
-           htab_create (10, hash_descriptor_extension, eq_descriptor_extension,
-                        NULL);
+         ref_s->merged_def_se_hash = htab_create (10, 
+                                                  hash_descriptor_extension, 
+                                                  eq_descriptor_extension,
+                                                  NULL);
          se_hash = ref_s->merged_def_se_hash;
          ref_s->unmerged_def_se_hash = NULL;
          ref_s->use_se_hash = NULL;
          break;
        case USE_EXTENSION:
-         ref_s->use_se_hash =
-           htab_create (10, hash_descriptor_extension, eq_descriptor_extension,
-                        NULL);
+         ref_s->use_se_hash = htab_create (10, 
+                                           hash_descriptor_extension, 
+                                           eq_descriptor_extension,
+                                           NULL);
          se_hash = ref_s->use_se_hash;
          ref_s->unmerged_def_se_hash = NULL;
          ref_s->merged_def_se_hash = NULL;
@@ -3157,7 +3203,7 @@ see_store_reference_and_extension (rtx ref_insn, rtx se_insn,
   /* If this is a new reference, insert it into the splay_tree.  */
   if (!stn)
     splay_tree_insert (see_bb_splay_ar[curr_bb_num],
-                      DF_INSN_LUID (df, ref_insn), (splay_tree_value) ref_s);
+                      DF_INSN_LUID (ref_insn), (splay_tree_value) ref_s);
   return true;
 }
 
@@ -3167,90 +3213,73 @@ see_store_reference_and_extension (rtx ref_insn, rtx se_insn,
 
    A definition is relevant if its root has
    ((entry_type == SIGN_EXTENDED_DEF) || (entry_type == ZERO_EXTENDED_DEF)) and
-   his source_mode is not narrower then the the roots source_mode.
+   his source_mode is not narrower then the roots source_mode.
 
    Return the number of relevant defs or negative number if something bad had
    happened and the optimization should be aborted.  */
 
 static int
-see_handle_relevant_defs (void)
+see_handle_relevant_defs (struct df_ref *ref, rtx insn)
 {
-  rtx insn = NULL;
-  rtx se_insn = NULL;
-  rtx reg = NULL;
-  rtx ref_insn = NULL;
   struct web_entry *root_entry = NULL;
-  unsigned int i;
-  int num_relevant_defs = 0;
+  rtx se_insn = NULL;
   enum rtx_code extension_code;
+  rtx reg = DF_REF_REAL_REG (ref);
+  rtx ref_insn = NULL;
+  unsigned int i = DF_REF_ID (ref);
 
-  for (i = 0; i < defs_num; i++)
-    {
-      insn = DF_REF_INSN (DF_DEFS_GET (df, i));
-      reg = DF_REF_REAL_REG (DF_DEFS_GET (df, i));
-
-      if (!insn)
-       continue;
-
-      if (!INSN_P (insn))
-       continue;
-
-      root_entry = unionfind_root (&def_entry[i]);
-
-      if ((ENTRY_EI (root_entry)->relevancy != SIGN_EXTENDED_DEF)
-         && (ENTRY_EI (root_entry)->relevancy != ZERO_EXTENDED_DEF))
-       /* The current web is not relevant.  Continue to the next def.  */
-       continue;
+  root_entry = unionfind_root (&def_entry[DF_REF_ID (ref)]);
 
-      if (root_entry->reg)
-       /* It isn't possible to have two different register for the same
-          web.  */
-       gcc_assert (rtx_equal_p (root_entry->reg, reg));
+  if (ENTRY_EI (root_entry)->relevancy != SIGN_EXTENDED_DEF
+      && ENTRY_EI (root_entry)->relevancy != ZERO_EXTENDED_DEF)
+    /* The current web is not relevant.  Continue to the next def.  */
+    return 0;
+  
+  if (root_entry->reg)
+    /* It isn't possible to have two different register for the same
+       web.  */
+    gcc_assert (rtx_equal_p (root_entry->reg, reg));
+  else
+    root_entry->reg = reg;
+  
+  /* The current definition is an EXTENDED_DEF or a definition that its
+     source_mode is narrower then its web's source_mode.
+     This means that we need to generate the implicit extension explicitly
+     and store it in the current reference's merged_def_se_hash.  */
+  if (ENTRY_EI (&def_entry[i])->local_relevancy == EXTENDED_DEF
+      || (ENTRY_EI (&def_entry[i])->local_source_mode <
+         ENTRY_EI (root_entry)->source_mode))
+    {
+      
+      if (ENTRY_EI (root_entry)->relevancy == SIGN_EXTENDED_DEF)
+       extension_code = SIGN_EXTEND;
       else
-       root_entry->reg = reg;
-
-      /* The current definition is an EXTENDED_DEF or a definition that its
-        source_mode is narrower then its web's source_mode.
-        This means that we need to generate the implicit extension explicitly
-        and store it in the current reference's merged_def_se_hash.  */
-      if ((ENTRY_EI (&def_entry[i])->local_relevancy == EXTENDED_DEF)
-         || (ENTRY_EI (&def_entry[i])->local_source_mode <
-             ENTRY_EI (root_entry)->source_mode))
-       {
-         num_relevant_defs++;
-
-         if (ENTRY_EI (root_entry)->relevancy == SIGN_EXTENDED_DEF)
-           extension_code = SIGN_EXTEND;
-         else
-           extension_code = ZERO_EXTEND;
-
-         se_insn =
-           see_gen_normalized_extension (reg, extension_code,
-                                         ENTRY_EI (root_entry)->source_mode);
-
-         /* This is a dummy extension, mark it as deleted.  */
-         INSN_DELETED_P (se_insn) = 1;
-
-         if (!see_store_reference_and_extension (insn, se_insn,
-                                                 IMPLICIT_DEF_EXTENSION))
-           /* Something bad happened.  Abort the optimization.  */
-           return -1;
-         continue;
-       }
-
-      ref_insn = PREV_INSN (insn);
-      gcc_assert (BLOCK_NUM (ref_insn) == BLOCK_NUM (insn));
-
-      num_relevant_defs++;
-
-      if (!see_store_reference_and_extension (ref_insn, insn,
-                                             EXPLICIT_DEF_EXTENSION))
+       extension_code = ZERO_EXTEND;
+      
+      se_insn =
+       see_gen_normalized_extension (reg, extension_code,
+                                     ENTRY_EI (root_entry)->source_mode);
+      
+      /* This is a dummy extension, mark it as deleted.  */
+      INSN_DELETED_P (se_insn) = 1;
+      
+      if (!see_store_reference_and_extension (insn, se_insn,
+                                             IMPLICIT_DEF_EXTENSION))
        /* Something bad happened.  Abort the optimization.  */
        return -1;
+      return 1;
     }
-   return num_relevant_defs;
-}
+  
+  ref_insn = PREV_INSN (insn);
+  gcc_assert (BLOCK_NUM (ref_insn) == BLOCK_NUM (insn));
+  
+  if (!see_store_reference_and_extension (ref_insn, insn,
+                                         EXPLICIT_DEF_EXTENSION))
+    /* Something bad happened.  Abort the optimization.  */
+    return -1;
 
+  return 0;
+}
 
 /* Go over all the uses, for each use in relevant web store its instruction as
    a reference and generate an extension before it.
@@ -3259,120 +3288,122 @@ see_handle_relevant_defs (void)
    happened and the optimization should be aborted.  */
 
 static int
-see_handle_relevant_uses (void)
+see_handle_relevant_uses (struct df_ref *ref, rtx insn)
 {
-  rtx insn = NULL;
-  rtx reg = NULL;
   struct web_entry *root_entry = NULL;
   rtx se_insn = NULL;
-  unsigned int i;
-  int num_relevant_uses = 0;
   enum rtx_code extension_code;
+  rtx reg = DF_REF_REAL_REG (ref);
 
-  for (i = 0; i < uses_num; i++)
-    {
-      insn = DF_REF_INSN (DF_USES_GET (df, i));
-      reg = DF_REF_REAL_REG (DF_USES_GET (df, i));
-
-      if (!insn)
-       continue;
-
-      if (!INSN_P (insn))
-       continue;
-
-      root_entry = unionfind_root (&use_entry[i]);
-
-      if ((ENTRY_EI (root_entry)->relevancy != SIGN_EXTENDED_DEF)
-         && (ENTRY_EI (root_entry)->relevancy != ZERO_EXTENDED_DEF))
-       /* The current web is not relevant.  Continue to the next use.  */
-       continue;
-
-      if (root_entry->reg)
-       /* It isn't possible to have two different register for the same
-          web.  */
-       gcc_assert (rtx_equal_p (root_entry->reg, reg));
-      else
-       root_entry->reg = reg;
-
-      /* Generate the use extension.  */
-      if (ENTRY_EI (root_entry)->relevancy == SIGN_EXTENDED_DEF)
-       extension_code = SIGN_EXTEND;
-      else
-       extension_code = ZERO_EXTEND;
+  root_entry = unionfind_root (&use_entry[DF_REF_ID (ref)]);
+  
+  if (ENTRY_EI (root_entry)->relevancy != SIGN_EXTENDED_DEF
+      && ENTRY_EI (root_entry)->relevancy != ZERO_EXTENDED_DEF)
+    /* The current web is not relevant.  Continue to the next use.  */
+    return 0;
+  
+  if (root_entry->reg)
+    /* It isn't possible to have two different register for the same
+       web.  */
+    gcc_assert (rtx_equal_p (root_entry->reg, reg));
+  else
+    root_entry->reg = reg;
+  
+  /* Generate the use extension.  */
+  if (ENTRY_EI (root_entry)->relevancy == SIGN_EXTENDED_DEF)
+    extension_code = SIGN_EXTEND;
+  else
+    extension_code = ZERO_EXTEND;
+  
+  se_insn =
+    see_gen_normalized_extension (reg, extension_code,
+                                 ENTRY_EI (root_entry)->source_mode);
+  if (!se_insn)
+    /* This is very bad, abort the transformation.  */
+    return -1;
+  
+  if (!see_store_reference_and_extension (insn, se_insn,
+                                         USE_EXTENSION))
+    /* Something bad happened.  Abort the optimization.  */
+    return -1;
+  return 1;
+}
 
-      se_insn =
-       see_gen_normalized_extension (reg, extension_code,
-                                     ENTRY_EI (root_entry)->source_mode);
-      if (!se_insn)
-       /* This is very bad, abort the transformation.  */
-       return -1;
+static int
+see_handle_relevant_refs (void)
+{
+  int num_relevant_refs = 0;
+  basic_block bb;
 
-      num_relevant_uses++;
+  FOR_ALL_BB (bb)
+    {
+      rtx insn;
+      FOR_BB_INSNS (bb, insn)
+       {
+         unsigned int uid = INSN_UID (insn);
 
-      if (!see_store_reference_and_extension (insn, se_insn,
-                                             USE_EXTENSION))
-       /* Something bad happened.  Abort the optimization.  */
-       return -1;
+         if (INSN_P (insn))
+           {
+             struct df_ref **use_rec;
+             struct df_ref **def_rec;
+             
+             for (use_rec = DF_INSN_UID_USES (uid); *use_rec; use_rec++)
+               {
+                 struct df_ref *use = *use_rec;
+                 int result = see_handle_relevant_uses (use, insn);
+                 if (result == -1)
+                   return -1;
+                 num_relevant_refs += result;
+               }
+             for (use_rec = DF_INSN_UID_EQ_USES (uid); *use_rec; use_rec++)
+               {
+                 struct df_ref *use = *use_rec;
+                 int result = see_handle_relevant_uses (use, insn);
+                 if (result == -1)
+                   return -1;
+                 num_relevant_refs += result;
+               }
+             for (def_rec = DF_INSN_UID_DEFS (uid); *def_rec; def_rec++)
+               {
+                 struct df_ref *def = *def_rec;
+                 int result = see_handle_relevant_defs (def, insn);
+                 if (result == -1)
+                   return -1;
+                 num_relevant_refs += result;
+               }
+           }
+       }
     }
-
-  return num_relevant_uses;
+   return num_relevant_refs;
 }
 
 
-/* Updates the relevancy of all the uses.
-   The information of the i'th use is stored in use_entry[i].
-   Currently all the uses are relevant for the optimization except for uses that
-   are in LIBCALL or RETVAL instructions.  */
+/* Initialized the use_entry field for REF in INSN at INDEX with ET.  */
 
 static void
-see_update_uses_relevancy (void)
+see_update_uses_relevancy (rtx insn, struct df_ref *ref, 
+                          enum entry_type et, unsigned int index)
 {
-  rtx insn = NULL;
-  rtx reg = NULL;
   struct see_entry_extra_info *curr_entry_extra_info;
-  enum entry_type et;
-  unsigned int i;
-
-  if (!df || !use_entry)
-    return;
 
-  for (i = 0; i < uses_num; i++)
+  if (dump_file)
     {
-
-      insn = DF_REF_INSN (DF_USES_GET (df, i));
-      reg = DF_REF_REAL_REG (DF_USES_GET (df, i));
-
-      et = RELEVANT_USE;
-
-      if (insn) 
-       {
-         if (!INSN_P (insn))
-           et = NOT_RELEVANT;
-         if (insn && find_reg_note (insn, REG_LIBCALL, NULL_RTX))
-           et = NOT_RELEVANT;
-         if (find_reg_note (insn, REG_RETVAL, NULL_RTX))
-           et = NOT_RELEVANT;
-       }
+      rtx reg = DF_REF_REAL_REG (ref);
+      fprintf (dump_file, "u%i insn %i reg %i ", 
+              index, (insn ? INSN_UID (insn) : -1), REGNO (reg));
+      if (et == NOT_RELEVANT)
+       fprintf (dump_file, "NOT RELEVANT \n");
       else
-       et = NOT_RELEVANT;
-
-      if (dump_file)
-       {
-         fprintf (dump_file, "u%i insn %i reg %i ", 
-          i, (insn ? INSN_UID (insn) : -1), REGNO (reg));
-         if (et == NOT_RELEVANT)
-           fprintf (dump_file, "NOT RELEVANT \n");
-         else
-           fprintf (dump_file, "RELEVANT USE \n");
-       }
-
-      curr_entry_extra_info = xmalloc (sizeof (struct see_entry_extra_info));
-      curr_entry_extra_info->relevancy = et;
-      curr_entry_extra_info->local_relevancy = et;
-      use_entry[i].extra_info = curr_entry_extra_info;
-      use_entry[i].reg = NULL;
-      use_entry[i].pred = NULL;
+       fprintf (dump_file, "RELEVANT USE \n");
     }
+
+  DF_REF_ID (ref) = index;
+  curr_entry_extra_info = xmalloc (sizeof (struct see_entry_extra_info));
+  curr_entry_extra_info->relevancy = et;
+  curr_entry_extra_info->local_relevancy = et;
+  use_entry[index].extra_info = curr_entry_extra_info;
+  use_entry[index].reg = NULL;
+  use_entry[index].pred = NULL;
 }
 
 
@@ -3431,12 +3462,6 @@ see_analyze_one_def (rtx insn, enum machine_mode *source_mode,
   *source_mode = MAX_MACHINE_MODE;
   *source_mode_unsigned = MAX_MACHINE_MODE;
 
-  if (!insn)
-    return NOT_RELEVANT;
-
-  if (!INSN_P (insn))
-    return NOT_RELEVANT;
-
   extension_code = see_get_extension_data (insn, source_mode);
   switch (extension_code)
     {
@@ -3460,16 +3485,16 @@ see_analyze_one_def (rtx insn, enum machine_mode *source_mode,
        return NOT_RELEVANT;
 
       /* If we can't use copy_rtx on the reference it can't be a reference.  */
-      if ((GET_CODE (PATTERN (prev_insn)) == PARALLEL)
-          && (asm_noperands (PATTERN (prev_insn)) >= 0))
+      if (GET_CODE (PATTERN (prev_insn)) == PARALLEL
+          && asm_noperands (PATTERN (prev_insn)) >= 0)
        return NOT_RELEVANT;
 
       /* Now, check if this extension is a reference itself.  If so, it is not
         relevant.  Handling this extension as relevant would make things much
         more complicated.  */
       next_insn = NEXT_INSN (insn);
-      if (prev_insn
-         && INSN_P (prev_insn)
+      if (next_insn
+         && INSN_P (next_insn)
          && (see_get_extension_data (next_insn, &next_source_mode) !=
              NOT_RELEVANT))
        {
@@ -3503,15 +3528,15 @@ see_analyze_one_def (rtx insn, enum machine_mode *source_mode,
 
       switch (GET_CODE (rhs))
        {
-       case (SIGN_EXTEND):
+       case SIGN_EXTEND:
          *source_mode = GET_MODE (XEXP (rhs, 0));
          *source_mode_unsigned = MAX_MACHINE_MODE;
          return EXTENDED_DEF;
-       case (ZERO_EXTEND):
+       case ZERO_EXTEND:
          *source_mode = MAX_MACHINE_MODE;
          *source_mode_unsigned = GET_MODE (XEXP (rhs, 0));
          return EXTENDED_DEF;
-       case (CONST_INT):
+       case CONST_INT:
 
          val = INTVAL (rhs);
 
@@ -3521,17 +3546,17 @@ see_analyze_one_def (rtx insn, enum machine_mode *source_mode,
               mode = GET_MODE_WIDER_MODE (mode), i++)
            {
              val2 = trunc_int_for_mode (val, mode);
-             if ((val2 == val) && (*source_mode == MAX_MACHINE_MODE))
+             if (val2 == val && *source_mode == MAX_MACHINE_MODE)
                *source_mode = mode;
-             if ((val == (val & (HOST_WIDE_INT)GET_MODE_MASK (mode)))
-                 && (*source_mode_unsigned == MAX_MACHINE_MODE))
+             if (val == (val & (HOST_WIDE_INT)GET_MODE_MASK (mode))
+                 && *source_mode_unsigned == MAX_MACHINE_MODE)
                *source_mode_unsigned = mode;
-             if ((*source_mode != MAX_MACHINE_MODE)
-                 && (*source_mode_unsigned !=MAX_MACHINE_MODE))
+             if (*source_mode != MAX_MACHINE_MODE
+                 && *source_mode_unsigned !=MAX_MACHINE_MODE)
                return EXTENDED_DEF;
            }
-         if ((*source_mode != MAX_MACHINE_MODE)
-             || (*source_mode_unsigned !=MAX_MACHINE_MODE))
+         if (*source_mode != MAX_MACHINE_MODE
+             || *source_mode_unsigned !=MAX_MACHINE_MODE)
            return EXTENDED_DEF;
          return NOT_RELEVANT;
        default:
@@ -3543,93 +3568,162 @@ see_analyze_one_def (rtx insn, enum machine_mode *source_mode,
 }
 
 
-/* Updates the relevancy and source_mode of all the definitions.
-   The information of the i'th definition is stored in def_entry[i].  */
+/* Initialized the def_entry field for REF in INSN at INDEX with ET.  */
 
 static void
-see_update_defs_relevancy (void)
+see_update_defs_relevancy (rtx insn, struct df_ref *ref,
+                          enum entry_type et,
+                          enum machine_mode source_mode,
+                          enum machine_mode source_mode_unsigned,
+                          unsigned int index)
 {
-  struct see_entry_extra_info *curr_entry_extra_info;
-  unsigned int i;
-  rtx insn = NULL;
-  rtx reg = NULL;
-  enum entry_type et;
-  enum machine_mode source_mode;
-  enum machine_mode source_mode_unsigned;
+  struct see_entry_extra_info *curr_entry_extra_info 
+    = xmalloc (sizeof (struct see_entry_extra_info));
+  curr_entry_extra_info->relevancy = et;
+  curr_entry_extra_info->local_relevancy = et;
 
-  if (!df || !def_entry)
-    return;
+  DF_REF_ID (ref) = index;
 
-  for (i = 0; i < defs_num; i++)
+  if (et != EXTENDED_DEF)
     {
-      insn = DF_REF_INSN (DF_DEFS_GET (df, i));
-      reg = DF_REF_REAL_REG (DF_DEFS_GET (df, i));
-
-      et = see_analyze_one_def (insn, &source_mode, &source_mode_unsigned);
-
-      curr_entry_extra_info = xmalloc (sizeof (struct see_entry_extra_info));
-      curr_entry_extra_info->relevancy = et;
-      curr_entry_extra_info->local_relevancy = et;
-      if (et != EXTENDED_DEF)
+      curr_entry_extra_info->source_mode = source_mode;
+      curr_entry_extra_info->local_source_mode = source_mode;
+    }
+  else
+    {
+      curr_entry_extra_info->source_mode_signed = source_mode;
+      curr_entry_extra_info->source_mode_unsigned = source_mode_unsigned;
+    }
+  def_entry[index].extra_info = curr_entry_extra_info;
+  def_entry[index].reg = NULL;
+  def_entry[index].pred = NULL;
+  
+  if (dump_file)
+    {
+      rtx reg = DF_REF_REAL_REG (ref);
+      if (et == NOT_RELEVANT)
        {
-         curr_entry_extra_info->source_mode = source_mode;
-         curr_entry_extra_info->local_source_mode = source_mode;
+         fprintf (dump_file, "d%i insn %i reg %i ",
+                  index, (insn ? INSN_UID (insn) : -1), REGNO (reg));
+         fprintf (dump_file, "NOT RELEVANT \n");
        }
       else
        {
-         curr_entry_extra_info->source_mode_signed = source_mode;
-         curr_entry_extra_info->source_mode_unsigned = source_mode_unsigned;
+         fprintf (dump_file, "d%i insn %i reg %i ",
+                  index, INSN_UID (insn), REGNO (reg));
+         fprintf (dump_file, "RELEVANT - ");
+         switch (et)
+           {
+           case SIGN_EXTENDED_DEF :
+             fprintf (dump_file, "SIGN_EXTENDED_DEF, source_mode = %s\n",
+                      GET_MODE_NAME (source_mode));
+             break;
+           case ZERO_EXTENDED_DEF :
+             fprintf (dump_file, "ZERO_EXTENDED_DEF, source_mode = %s\n",
+                      GET_MODE_NAME (source_mode));
+             break;
+           case EXTENDED_DEF :
+             fprintf (dump_file, "EXTENDED_DEF, ");
+             if (source_mode != MAX_MACHINE_MODE
+                 && source_mode_unsigned != MAX_MACHINE_MODE)
+               {
+                 fprintf (dump_file, "positive const, ");
+                 fprintf (dump_file, "source_mode_signed = %s, ",
+                          GET_MODE_NAME (source_mode));
+                 fprintf (dump_file, "source_mode_unsigned = %s\n",
+                          GET_MODE_NAME (source_mode_unsigned));
+               }
+             else if (source_mode != MAX_MACHINE_MODE)
+               fprintf (dump_file, "source_mode_signed = %s\n",
+                        GET_MODE_NAME (source_mode));
+             else
+               fprintf (dump_file, "source_mode_unsigned = %s\n",
+                        GET_MODE_NAME (source_mode_unsigned));
+             break;
+           default :
+             gcc_unreachable ();
+           }
        }
-      def_entry[i].extra_info = curr_entry_extra_info;
-      def_entry[i].reg = NULL;
-      def_entry[i].pred = NULL;
+    }
+}
 
-      if (dump_file)
+
+/* Updates the relevancy of all the uses and all defs.  
+
+   The information of the u'th use is stored in use_entry[u] and the
+   information of the d'th definition is stored in def_entry[d].
+
+   Currently all the uses are relevant for the optimization except for
+   uses that are in LIBCALL or RETVAL instructions.  */
+
+static void
+see_update_relevancy (void)
+{
+  unsigned int d = 0;
+  unsigned int u = 0;
+  enum entry_type et;
+  enum machine_mode source_mode;
+  enum machine_mode source_mode_unsigned;
+  basic_block bb;
+
+  if (!def_entry)
+    return;
+
+  FOR_ALL_BB (bb)
+    {
+      struct df_ref **use_rec;
+      struct df_ref **def_rec;
+      rtx insn;
+      FOR_BB_INSNS (bb, insn)
        {
-         if (et == NOT_RELEVANT)
-           {
-             fprintf (dump_file, "d%i insn %i reg %i ",
-              i, (insn ? INSN_UID (insn) : -1), REGNO (reg));
-             fprintf (dump_file, "NOT RELEVANT \n");
-           }
-         else
+         unsigned int uid = INSN_UID (insn);
+         if (INSN_P (insn))
            {
-             fprintf (dump_file, "d%i insn %i reg %i ",
-                      i ,INSN_UID (insn), REGNO (reg));
-             fprintf (dump_file, "RELEVANT - ");
-             switch (et)
+             if (find_reg_note (insn, REG_LIBCALL, NULL_RTX)
+                 || find_reg_note (insn, REG_RETVAL, NULL_RTX))
+               et = NOT_RELEVANT;
+             else
+               et = RELEVANT_USE;
+
+             for (use_rec = DF_INSN_UID_USES (uid); *use_rec; use_rec++)
                {
-               case SIGN_EXTENDED_DEF :
-                 fprintf (dump_file, "SIGN_EXTENDED_DEF, source_mode = %s\n",
-                          GET_MODE_NAME (source_mode));
-                 break;
-               case ZERO_EXTENDED_DEF :
-                 fprintf (dump_file, "ZERO_EXTENDED_DEF, source_mode = %s\n",
-                          GET_MODE_NAME (source_mode));
-                 break;
-               case EXTENDED_DEF :
-                 fprintf (dump_file, "EXTENDED_DEF, ");
-                 if ((source_mode != MAX_MACHINE_MODE)
-                     && (source_mode_unsigned != MAX_MACHINE_MODE))
-                   {
-                     fprintf (dump_file, "positive const, ");
-                     fprintf (dump_file, "source_mode_signed = %s, ",
-                              GET_MODE_NAME (source_mode));
-                     fprintf (dump_file, "source_mode_unsigned = %s\n",
-                              GET_MODE_NAME (source_mode_unsigned));
-                   }
-                 else if (source_mode != MAX_MACHINE_MODE)
-                   fprintf (dump_file, "source_mode_signed = %s\n",
-                            GET_MODE_NAME (source_mode));
-                 else
-                   fprintf (dump_file, "source_mode_unsigned = %s\n",
-                            GET_MODE_NAME (source_mode_unsigned));
-                 break;
-               default :
-                 gcc_unreachable ();
+                 struct df_ref *use = *use_rec;
+                 see_update_uses_relevancy (insn, use, et, u);
+                 u++;
+               }
+             
+             for (use_rec = DF_INSN_UID_EQ_USES (uid); *use_rec; use_rec++)
+               {
+                 struct df_ref *use = *use_rec;
+                 see_update_uses_relevancy (insn, use, et, u);
+                 u++;
+               }
+
+             et = see_analyze_one_def (insn, &source_mode, &source_mode_unsigned);
+             for (def_rec = DF_INSN_UID_DEFS (uid); *def_rec; def_rec++)
+               {
+                 struct df_ref *def = *def_rec;
+                 see_update_defs_relevancy (insn, def, et, source_mode, 
+                                              source_mode_unsigned, d);
+                 d++;
                }
            }
        }
+      
+      for (use_rec = df_get_artificial_uses (bb->index); *use_rec; use_rec++)
+       {
+         struct df_ref *use = *use_rec;
+         see_update_uses_relevancy (NULL, use, NOT_RELEVANT, u);
+         u++;
+       }
+
+      for (def_rec = df_get_artificial_defs (bb->index); *def_rec; def_rec++)
+       {
+         struct df_ref *def = *def_rec;
+         see_update_defs_relevancy (NULL, def, NOT_RELEVANT, 
+                                      MAX_MACHINE_MODE, MAX_MACHINE_MODE, d);
+         d++;
+       }
     }
 }
 
@@ -3645,49 +3739,62 @@ see_update_defs_relevancy (void)
 static bool
 see_propagate_extensions_to_uses (void)
 {
-  unsigned int i = 0;
-  int num_relevant_uses;
-  int num_relevant_defs;
+  int num_relevant_refs;
+  basic_block bb;
 
   if (dump_file)
     fprintf (dump_file,
       "* Phase 1: Propagate extensions to uses.  *\n");
 
   /* Update the relevancy of references using the DF object.  */
-  see_update_defs_relevancy ();
-  see_update_uses_relevancy ();
+  see_update_relevancy ();
 
   /* Produce the webs and update the extra_info of the root.
      In general, a web is relevant if all its definitions and uses are relevant
      and there is at least one definition that was marked as SIGN_EXTENDED_DEF
      or ZERO_EXTENDED_DEF.  */
-  for (i = 0; i < uses_num; i++)
+  FOR_ALL_BB (bb)
     {
-      union_defs (df, DF_USES_GET (df, i), def_entry, use_entry,
-                 see_update_leader_extra_info);
-    }
+      rtx insn;
+      struct df_ref **use_rec;
 
-  /* Generate use extensions for references and insert these
-     references to see_bb_splay_ar data structure.    */
-  num_relevant_uses = see_handle_relevant_uses ();
+      FOR_BB_INSNS (bb, insn)
+       {
+         unsigned int uid = INSN_UID (insn);
+         if (INSN_P (insn))
+           {
+             for (use_rec = DF_INSN_UID_USES (uid); *use_rec; use_rec++)
+               {
+                 struct df_ref *use = *use_rec;
+                 union_defs (use, def_entry, use_entry, see_update_leader_extra_info);
+               }
+             
+             for (use_rec = DF_INSN_UID_EQ_USES (uid); *use_rec; use_rec++)
+               {
+                 struct df_ref *use = *use_rec;
+                 union_defs (use, def_entry, use_entry, see_update_leader_extra_info);
+               }
+           }
+       }
 
-  if (num_relevant_uses < 0)
-    return false;
+      for (use_rec = df_get_artificial_uses (bb->index); *use_rec; use_rec++)
+       {
+         struct df_ref *use = *use_rec;
+         union_defs (use, def_entry, use_entry, see_update_leader_extra_info);
+       }
+    }
 
-  /* Store the def extensions in their references structures and insert these
+  /* Generate use extensions for references and insert these
      references to see_bb_splay_ar data structure.    */
-  num_relevant_defs = see_handle_relevant_defs ();
-
-  if (num_relevant_defs < 0)
-    return false;
+  num_relevant_refs = see_handle_relevant_refs ();
 
-  return ((num_relevant_uses > 0) || (num_relevant_defs > 0));
+  return num_relevant_refs > 0;
 }
 
 
 /* Main entry point for the sign extension elimination optimization.  */
 
-void
+static void
 see_main (void)
 {
   bool cont = false;
@@ -3742,29 +3849,23 @@ see_main (void)
 static bool
 gate_handle_see (void)
 {
-  return ((optimize > 1) && flag_see);
+  return optimize > 1 && flag_see;
 }
 
 static unsigned int
 rest_of_handle_see (void)
 {
-  int no_new_pseudos_bcp = no_new_pseudos;
-
-  no_new_pseudos = 0;
   see_main ();
-  no_new_pseudos = no_new_pseudos_bcp;
-  
-  delete_trivially_dead_insns (get_insns (), max_reg_num ());
-  update_life_info_in_dirty_blocks (UPDATE_LIFE_GLOBAL_RM_NOTES, 
-                                   (PROP_DEATH_NOTES));
-  cleanup_cfg (CLEANUP_EXPENSIVE);
-  reg_scan (get_insns (), max_reg_num ());
-
+  df_clear_flags (DF_DEFER_INSN_RESCAN);
+  df_process_deferred_rescans ();
+  run_fast_dce ();
   return 0;
 }
 
-struct tree_opt_pass pass_see =
+struct rtl_opt_pass pass_see =
 {
+ {
+  RTL_PASS,
   "see",                               /* name */
   gate_handle_see,                     /* gate */
   rest_of_handle_see,                  /* execute */
@@ -3776,7 +3877,9 @@ struct tree_opt_pass pass_see =
   0,                                   /* properties_provided */
   0,                                   /* properties_destroyed */
   0,                                   /* todo_flags_start */
-  TODO_dump_func,                      /* todo_flags_finish */
-  'u'                                  /* letter */
+  TODO_df_verify |
+  TODO_df_finish | TODO_verify_rtl_sharing |
+  TODO_dump_func                       /* todo_flags_finish */
+ }
 };