This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Fix 18291


When a pointer Q_j is copy-propagated into another P_i, all uses
of P_i are rewritten to use Q_j and we call merge_alias_info to
make sure that Q_j has the appropriate name tags (needed to
propagate into INDIRECT_REF sites).

What we do for type tags is to make sure that both VAR_DECLs P
and Q have the same type tag.  However, the same approach doesn't
work for name tags.  We used to test that both P_i and Q_j had
the exact same name tag, but that is not necessarily right
because P_i and Q_j could actually be pointing to different
variables.

In this case, the pointed-to sets will never be completely
different, they will always intersect because we are reaching
this point after copy-propagation, so the two pointers must have
something in common.

So, if Q_j already has a name tag (i.e., it has been
dereferenced), we just continue to use it.  Otherwise, we give
Q_j the same name tag that P_i had.  There is no real need of
updating P_i's information, since the pointer is being discarded
by the propagation (the same is not true of the type-based
information, which is associated to the VAR_DECL not the
SSA_NAME).

Bootstrapped and tested x86, x86-64 and ppc.


Diego.



	PR tree-optimization/18291
	* tree-ssa-copy.c (merge_alias_info): Fix merging of
	flow-sensitive alias information.  If the new pointer has no
	name tag, copy it from the original pointer.  Otherwise, make
	sure that the pointed-to sets have a common intersection.

testsuite/ChangeLog

	PR tree-optimization/18291
	* testsuite/gcc.c-torture/compile/pr18291.c: New test.

Index: tree-ssa-copy.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-ssa-copy.c,v
retrieving revision 2.20
diff -d -c -p -u -r2.20 tree-ssa-copy.c
--- tree-ssa-copy.c	14 Nov 2004 23:35:02 -0000	2.20
+++ tree-ssa-copy.c	1 Dec 2004 16:24:16 -0000
@@ -178,7 +178,6 @@ merge_alias_info (tree orig, tree new)
   tree orig_sym = SSA_NAME_VAR (orig);
   var_ann_t new_ann = var_ann (new_sym);
   var_ann_t orig_ann = var_ann (orig_sym);
-  struct ptr_info_def *new_ptr_info;
   struct ptr_info_def *orig_ptr_info;
 
   gcc_assert (POINTER_TYPE_P (TREE_TYPE (orig)));
@@ -203,18 +202,41 @@ merge_alias_info (tree orig, tree new)
   else
     gcc_assert (new_ann->type_mem_tag == orig_ann->type_mem_tag);
 
-  /* Synchronize flow sensitive alias information.  If both pointers
-     had flow information and they are inconsistent, then something
-     has gone wrong.  */
-  new_ptr_info = get_ptr_info (new);
-  orig_ptr_info = get_ptr_info (orig);
+  orig_ptr_info = SSA_NAME_PTR_INFO (orig);
+  if (orig_ptr_info && orig_ptr_info->name_mem_tag)
+    {
+      struct ptr_info_def *new_ptr_info = get_ptr_info (new);
 
-  if (new_ptr_info->name_mem_tag == NULL_TREE)
-    memcpy (new_ptr_info, orig_ptr_info, sizeof (*new_ptr_info));
-  else if (orig_ptr_info->name_mem_tag == NULL_TREE)
-    memcpy (orig_ptr_info, new_ptr_info, sizeof (*orig_ptr_info));
-  else if (orig_ptr_info->name_mem_tag != new_ptr_info->name_mem_tag)
-    abort ();
+      if (new_ptr_info->name_mem_tag == NULL_TREE)
+	{
+	  /* If ORIG had a name tag, it means that was dereferenced in
+	     the code, and since pointer NEW will now replace every
+	     occurrence of ORIG, we have to make sure that NEW has an
+	     appropriate tag.  If, NEW did not have a name tag, get it
+	     from ORIG.  */
+	  memcpy (new_ptr_info, orig_ptr_info, sizeof (*new_ptr_info));
+	  new_ptr_info->pt_vars = BITMAP_GGC_ALLOC ();
+	  bitmap_copy (new_ptr_info->pt_vars, orig_ptr_info->pt_vars);
+	  new_ptr_info->name_mem_tag = orig_ptr_info->name_mem_tag;
+	}
+      else
+	{
+	  /* If NEW already had a name tag, nothing needs to be done.
+	     Note that pointer NEW may actually have a different set of
+	     pointed-to variables.
+	     
+	     However, since NEW is being copy-propagated into ORIG, it must
+	     always be true that the pointed-to set for pointer NEW is the
+	     same, or a subset, of the pointed-to set for pointer ORIG.  If
+	     this isn't the case, we shouldn't have been able to do the
+	     propagation of NEW into ORIG.  */
+#if defined ENABLE_CHECKING
+	  if (orig_ptr_info->pt_vars && new_ptr_info->pt_vars)
+	    gcc_assert (bitmap_intersect_p (new_ptr_info->pt_vars,
+					    orig_ptr_info->pt_vars));
+#endif
+	}
+    }
 }   
 
 
Index: testsuite/gcc.c-torture/compile/pr18291.c
===================================================================
RCS file: testsuite/gcc.c-torture/compile/pr18291.c
diff -N testsuite/gcc.c-torture/compile/pr18291.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ testsuite/gcc.c-torture/compile/pr18291.c	1 Dec 2004 16:24:18 -0000
@@ -0,0 +1,12 @@
+int baz(int k2)
+{
+  int i, j, *p, k = 1, k1 = 0;
+  if (k2)
+    p = &j;
+  else
+    p = &i;
+  if (k1)
+    *p = 0 , p = &k;
+  *p = 1;
+  return k;
+}


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]