OSDN Git Service

2008-05-23 Rafael Espindola <espindola@google.com>
[pf3gnuchains/gcc-fork.git] / gcc / see.c
index c58e8dd..dce5169 100644 (file)
--- a/gcc/see.c
+++ b/gcc/see.c
@@ -6,7 +6,7 @@ This file is part of GCC.
 
 GCC is free software; you can redistribute it and/or modify it under
 the terms of the GNU General Public License as published by the Free
--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:
 --------------------
@@ -733,7 +732,7 @@ see_get_extension_data (rtx extension, enum machine_mode *source_mode)
 
   /* Don't handle extensions to something other then register or
      subregister.  */
-  if (!REG_P (lhs) && !SUBREG_REG (lhs))
+  if (!REG_P (lhs) && GET_CODE (lhs) != SUBREG)
     return UNKNOWN;
 
   if (GET_CODE (rhs) != SIGN_EXTEND && GET_CODE (rhs) != ZERO_EXTEND)
@@ -1687,7 +1686,7 @@ see_pre_insert_extensions (struct see_pre_extension_expr **index_map)
                edge eg = INDEX_EDGE (edge_list, e);
 
                start_sequence ();
-               emit_insn (PATTERN (expr->se_insn));
+               emit_insn (copy_insn (PATTERN (expr->se_insn)));
                se_insn = get_insns ();
                end_sequence ();
 
@@ -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,14 +2478,13 @@ 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 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 move_insn = NULL;
   rtx set, rhs;
   rtx dest_reg, dest_real_reg;
   rtx new_pseudo_reg, subreg;
@@ -2478,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.  */
@@ -2490,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)
        {
@@ -2517,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;
     }
@@ -2527,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)
     {
@@ -2549,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));
     }
 }
 
@@ -2583,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);
@@ -2627,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;
@@ -2645,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;
     }
 
@@ -2663,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;
@@ -2673,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)
     {
@@ -2686,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
@@ -2727,15 +2772,15 @@ 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, *rtx_slot, subreg;
+  rtx *rtx_slot, subreg;
   rtx temp_extension = NULL;
   rtx simplified_temp_extension = NULL;
   rtx *pat;
@@ -2764,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;
@@ -2852,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)
     {
@@ -2883,9 +2925,9 @@ 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
@@ -3481,7 +3523,7 @@ see_analyze_one_def (rtx insn, enum machine_mode *source_mode,
 
       /* Don't handle extensions to something other then register or
         subregister.  */
-      if (!REG_P (lhs) && !SUBREG_REG (lhs))
+      if (!REG_P (lhs) && GET_CODE (lhs) != SUBREG)
        return NOT_RELEVANT;
 
       switch (GET_CODE (rhs))
@@ -3610,9 +3652,9 @@ see_update_defs_relevancy (rtx insn, struct df_ref *ref,
 
    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 instructions.  */
+   uses that are in LIBCALL or RETVAL instructions.  */
 
 static void
 see_update_relevancy (void)
@@ -3637,13 +3679,12 @@ see_update_relevancy (void)
          unsigned int uid = INSN_UID (insn);
          if (INSN_P (insn))
            {
-             
-             /* If this is an insn in a libcall, do not touch the uses.  */
-             if (find_reg_note (insn, REG_LIBCALL_ID, NULL_RTX))
+             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++)
                {
                  struct df_ref *use = *use_rec;
@@ -3815,12 +3856,16 @@ static unsigned int
 rest_of_handle_see (void)
 {
   see_main ();
+  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 */
@@ -3832,8 +3877,9 @@ struct tree_opt_pass pass_see =
   0,                                   /* properties_provided */
   0,                                   /* properties_destroyed */
   0,                                   /* todo_flags_start */
-  TODO_df_finish |
-  TODO_dump_func,                      /* todo_flags_finish */
-  'u'                                  /* letter */
+  TODO_df_verify |
+  TODO_df_finish | TODO_verify_rtl_sharing |
+  TODO_dump_func                       /* todo_flags_finish */
+ }
 };