OSDN Git Service

PR c++/35546
[pf3gnuchains/gcc-fork.git] / gcc / tree-ssa-copy.c
index 9f58087..bc8a874 100644 (file)
@@ -1,5 +1,5 @@
 /* Copy propagation and SSA_NAME replacement support routines.
-   Copyright (C) 2004, 2005, 2007 Free Software Foundation, Inc.
+   Copyright (C) 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -62,6 +62,17 @@ may_propagate_copy (tree dest, tree orig)
   tree type_d = TREE_TYPE (dest);
   tree type_o = TREE_TYPE (orig);
 
+  /* If ORIG flows in from an abnormal edge, it cannot be propagated.  */
+  if (TREE_CODE (orig) == SSA_NAME
+      && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (orig))
+    return false;
+
+  /* If DEST is an SSA_NAME that flows from an abnormal edge, then it
+     cannot be replaced.  */
+  if (TREE_CODE (dest) == SSA_NAME
+      && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (dest))
+    return false;
+
   /* For memory partitions, copies are OK as long as the memory symbol
      belongs to the partition.  */
   if (TREE_CODE (dest) == SSA_NAME
@@ -129,11 +140,14 @@ may_propagate_copy (tree dest, tree orig)
       tree mt_orig = symbol_mem_tag (SSA_NAME_VAR (orig));
       if (mt_dest && mt_orig && mt_dest != mt_orig)
        return false;
-      else if (!useless_type_conversion_p (type_d, type_o))
-       return false;
       else if (get_alias_set (TREE_TYPE (type_d)) != 
               get_alias_set (TREE_TYPE (type_o)))
        return false;
+      else if (!MTAG_P (SSA_NAME_VAR (dest))
+              && !MTAG_P (SSA_NAME_VAR (orig))
+              && (DECL_NO_TBAA_P (SSA_NAME_VAR (dest))
+                  != DECL_NO_TBAA_P (SSA_NAME_VAR (orig))))
+       return false;
 
       /* Also verify flow-sensitive information is compatible.  */
       if (SSA_NAME_PTR_INFO (orig) && SSA_NAME_PTR_INFO (dest))
@@ -166,17 +180,6 @@ may_propagate_copy (tree dest, tree orig)
       return false;
     }
 
-  /* If ORIG flows in from an abnormal edge, it cannot be propagated.  */
-  if (TREE_CODE (orig) == SSA_NAME
-      && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (orig))
-    return false;
-
-  /* If DEST is an SSA_NAME that flows from an abnormal edge, then it
-     cannot be replaced.  */
-  if (TREE_CODE (dest) == SSA_NAME
-      && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (dest))
-    return false;
-
   /* Anything else is OK.  */
   return true;
 }
@@ -217,31 +220,13 @@ merge_alias_info (tree orig_name, tree new_name)
       return;
     }
 
-  gcc_assert (POINTER_TYPE_P (TREE_TYPE (orig_name)));
-  gcc_assert (POINTER_TYPE_P (TREE_TYPE (new_name)));
+  gcc_assert (POINTER_TYPE_P (TREE_TYPE (orig_name))
+             && POINTER_TYPE_P (TREE_TYPE (new_name)));
 
 #if defined ENABLE_CHECKING
   gcc_assert (useless_type_conversion_p (TREE_TYPE (orig_name),
                                        TREE_TYPE (new_name)));
 
-  /* If the pointed-to alias sets are different, these two pointers
-     would never have the same memory tag.  In this case, NEW should
-     not have been propagated into ORIG.  */
-  gcc_assert (get_alias_set (TREE_TYPE (TREE_TYPE (new_sym)))
-             == get_alias_set (TREE_TYPE (TREE_TYPE (orig_sym))));
-#endif
-
-  /* Synchronize the symbol tags.  If both pointers had a tag and they
-     are different, then something has gone wrong.  Symbol tags can
-     always be merged because they are flow insensitive, all the SSA
-     names of the same base DECL share the same symbol tag.  */
-  if (new_ann->symbol_mem_tag == NULL_TREE)
-    new_ann->symbol_mem_tag = orig_ann->symbol_mem_tag;
-  else if (orig_ann->symbol_mem_tag == NULL_TREE)
-    orig_ann->symbol_mem_tag = new_ann->symbol_mem_tag;
-  else
-    gcc_assert (new_ann->symbol_mem_tag == orig_ann->symbol_mem_tag);
-
   /* Check that flow-sensitive information is compatible.  Notice that
      we may not merge flow-sensitive information here.  This function
      is called when propagating equivalences dictated by the IL, like
@@ -257,7 +242,11 @@ merge_alias_info (tree orig_name, tree new_name)
 
      Since we cannot distinguish one case from another in this
      function, we can only make sure that if P_i and Q_j have
-     flow-sensitive information, they should be compatible.  */
+     flow-sensitive information, they should be compatible.
+
+     As callers of merge_alias_info are supposed to call may_propagate_copy
+     first, the following check is redundant.  Thus, only do it if checking
+     is enabled.  */
   if (SSA_NAME_PTR_INFO (orig_name) && SSA_NAME_PTR_INFO (new_name))
     {
       struct ptr_info_def *orig_ptr_info = SSA_NAME_PTR_INFO (orig_name);
@@ -278,7 +267,33 @@ merge_alias_info (tree orig_name, tree new_name)
        gcc_assert (bitmap_intersect_p (new_ptr_info->pt_vars,
                                        orig_ptr_info->pt_vars));
     }
-}   
+#endif
+
+  /* Synchronize the symbol tags.  If both pointers had a tag and they
+     are different, then something has gone wrong.  Symbol tags can
+     always be merged because they are flow insensitive, all the SSA
+     names of the same base DECL share the same symbol tag.  */
+  if (new_ann->symbol_mem_tag == NULL_TREE)
+    new_ann->symbol_mem_tag = orig_ann->symbol_mem_tag;
+  else if (orig_ann->symbol_mem_tag == NULL_TREE)
+    orig_ann->symbol_mem_tag = new_ann->symbol_mem_tag;
+  else
+    gcc_assert (new_ann->symbol_mem_tag == orig_ann->symbol_mem_tag);
+
+  /* Copy flow-sensitive alias information in case that NEW_NAME
+     didn't get a NMT but was set to pt_anything for optimization
+     purposes.  In case ORIG_NAME has a NMT we can safely use its
+     flow-sensitive alias information as a conservative estimate.  */
+  if (SSA_NAME_PTR_INFO (orig_name)
+      && SSA_NAME_PTR_INFO (orig_name)->name_mem_tag
+      && (!SSA_NAME_PTR_INFO (new_name)
+         || !SSA_NAME_PTR_INFO (new_name)->name_mem_tag))
+    {
+      struct ptr_info_def *orig_ptr_info = SSA_NAME_PTR_INFO (orig_name);
+      struct ptr_info_def *new_ptr_info = get_ptr_info (new_name);
+      memcpy (new_ptr_info, orig_ptr_info, sizeof (struct ptr_info_def));
+    }
+}
 
 
 /* Common code for propagate_value and replace_exp.
@@ -1047,8 +1062,10 @@ gate_copy_prop (void)
   return flag_tree_copy_prop != 0;
 }
 
-struct tree_opt_pass pass_copy_prop =
+struct gimple_opt_pass pass_copy_prop =
 {
+ {
+  GIMPLE_PASS,
   "copyprop",                          /* name */
   gate_copy_prop,                      /* gate */
   execute_copy_prop,                   /* execute */
@@ -1064,7 +1081,7 @@ struct tree_opt_pass pass_copy_prop =
     | TODO_dump_func
     | TODO_ggc_collect
     | TODO_verify_ssa
-    | TODO_update_ssa,                 /* todo_flags_finish */
-  0                                    /* letter */
+    | TODO_update_ssa                  /* todo_flags_finish */
+ }
 };