OSDN Git Service

2008-03-26 Ed Schonberg <schonberg@adacore.com>
[pf3gnuchains/gcc-fork.git] / gcc / see.c
index 603d72e..c6f584c 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.  */
@@ -567,7 +564,7 @@ struct see_register_properties
 };
 
 /* Occurrence of an expression.
-   There must be at most one available occurance and at most one anticipatable
+   There must be at most one available occurrence and at most one anticipatable
    occurrence per basic block.  */
 struct see_occr
 {
@@ -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;
 }
 
 
@@ -925,7 +920,7 @@ hash_del_properties (void *p)
    set ((reg:WIDEmode r1) (sign_extend:WIDEmode (reg:NARROWmode r2)))
 
    The value of the key is (REGNO (reg:WIDEmode r1))
-   It is posibble to search this hash in two ways:
+   It is possible to search this hash in two ways:
    1.  By a register rtx. The Value that is been compared to the keys is the
        REGNO of it.
    2.  By an insn with the above pattern. The Value that is been compared to
@@ -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;
 }
@@ -1648,7 +1652,7 @@ see_commit_ref_changes (splay_tree_node stn,
    redundant.
 
    INDEX_MAP is a mapping of an index to an expression.
-   Return true if an instruction was insertedon an edge.
+   Return true if an instruction was inserted on an edge.
    Otherwise, return false.  */
 
 static bool
@@ -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,38 @@ 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);
+      CONST_OR_PURE_CALL_P (ret) = 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)
@@ -2424,7 +2455,7 @@ see_replace_src (rtx *x, void *data)
    set (subreg (dest_extension_reg)) (rhs)
 
    We do this in 4 steps:
-   a. Replace every use of dest_reg with a new preudo register.
+   a. Replace every use of dest_reg with a new pseudo register.
    b. Replace every instance of dest_reg with the subreg.
    c. Replace every use of the new pseudo register back to dest_reg.
    d. Try to recognize and simplify.
@@ -2444,31 +2475,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);
@@ -2476,12 +2503,12 @@ see_def_extension_not_merged (struct see_ref_s *curr_ref_s, rtx def_se)
   subreg = gen_lowpart_SUBREG (dest_mode, dest_extension_reg);
   new_pseudo_reg = gen_reg_rtx (source_extension_mode);
 
-  /* Step a: Replace every use of dest_real_reg with a new preudo register.  */
+  /* Step a: Replace every use of dest_real_reg with a new pseudo register.  */
   d.from = dest_real_reg;
   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 +2520,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 +2544,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 +2554,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 +2572,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 +2606,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 +2636,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 +2650,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 +2669,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 +2696,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 +2707,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 +2728,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 +2746,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 +2769,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 +2806,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 +2829,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 +2861,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 +2895,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 +2922,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 +2968,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 +3073,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 +3085,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 +3097,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 +3147,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 +3155,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 +3200,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 +3210,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 +3285,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 +3459,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 +3482,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 +3525,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 +3543,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 +3565,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 +3736,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 +3846,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 +3874,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 */
+ }
 };