From e6c961dde1572f17ecb50594c5858ab22c92d4a0 Mon Sep 17 00:00:00 2001
From: irar <irar@138bc75d-0d04-0410-961f-82ee72b054a4>
Date: Sun, 17 Sep 2006 09:17:51 +0000
Subject: [PATCH]         PR tree-opt/21591         * tree-data-ref.c
 (ptr_decl_may_alias_p): Look for the name memory         tag first.        
 (ptr_ptr_may_alias_p): Likewise.         (record_record_differ_p): New
 function.         (base_object_differ_p): Call record_record_differ_p.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@117003 138bc75d-0d04-0410-961f-82ee72b054a4
---
 gcc/ChangeLog                       |  9 ++++
 gcc/testsuite/ChangeLog             |  5 ++
 gcc/testsuite/gcc.dg/vect/pr21591.c | 35 ++++++++++++
 gcc/tree-data-ref.c                 | 84 +++++++++++++++++++++++------
 4 files changed, 118 insertions(+), 15 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/vect/pr21591.c

diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 5c2cf3d8b2c4..261926af016e 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,12 @@
+2006-09-17  Ira Rosen  <irar@il.ibm.com>
+
+        PR tree-opt/21591
+	* tree-data-ref.c (ptr_decl_may_alias_p): Look for the name memory
+        tag first.
+        (ptr_ptr_may_alias_p): Likewise.
+        (record_record_differ_p): New function.
+        (base_object_differ_p): Call record_record_differ_p.
+
 2006-09-16  Andrew Pinski  <pinskia@physics.uc.edu>
 
 	PR tree-opt/29059
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 6a27b73c1344..89cc01b37f17 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2006-09-17  Ira Rosen  <irar@il.ibm.com>
+
+        PR tree-opt/21591
+        * gcc.dg/vect/pr21591.c: New test.
+
 2006-09-16  Andrew Pinski  <pinskia@physics.uc.edu>
 
 	PR tree-opt/29059
diff --git a/gcc/testsuite/gcc.dg/vect/pr21591.c b/gcc/testsuite/gcc.dg/vect/pr21591.c
new file mode 100644
index 000000000000..8a8e30f52062
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/pr21591.c
@@ -0,0 +1,35 @@
+/* { dg-do compile } */
+
+struct a
+{
+  int length;
+  int a1[256];
+};
+
+struct a *malloc1(__SIZE_TYPE__) __attribute__((malloc));
+void free(void*);
+
+void f(void)
+{
+   struct a *a = malloc1(sizeof(struct a));
+   struct a *b = malloc1(sizeof(struct a));
+   struct a *c = malloc1(sizeof(struct a));
+   int i;
+
+   for (i = 0; i < 256; i++) 
+   {
+      b->a1[i] = i;
+      c->a1[i] = i;
+   }
+   for (i = 0; i < 256; i++) 
+   {
+      a->a1[i] = b->a1[i] + c->a1[i];
+   }
+   free(a);
+   free(b);
+   free(c);
+}
+
+/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" } } */
+/* { dg-final { cleanup-tree-dump "vect" } } */
+
diff --git a/gcc/tree-data-ref.c b/gcc/tree-data-ref.c
index d3758ef1ae56..30d745a4238e 100644
--- a/gcc/tree-data-ref.c
+++ b/gcc/tree-data-ref.c
@@ -140,16 +140,20 @@ ptr_decl_may_alias_p (tree ptr, tree decl,
 		      struct data_reference *ptr_dr, 
 		      bool *aliased)
 {
-  tree tag;
-   
+  tree tag = NULL_TREE;
+  struct ptr_info_def *pi = DR_PTR_INFO (ptr_dr);  
+
   gcc_assert (TREE_CODE (ptr) == SSA_NAME && DECL_P (decl));
 
-  tag = get_var_ann (SSA_NAME_VAR (ptr))->symbol_mem_tag;
+  if (pi)
+    tag = pi->name_mem_tag;
+  if (!tag)
+    tag = get_var_ann (SSA_NAME_VAR (ptr))->symbol_mem_tag;
   if (!tag)
     tag = DR_MEMTAG (ptr_dr);
   if (!tag)
     return false;
-  
+   
   *aliased = is_aliased_with (tag, decl);      
   return true;
 }
@@ -164,18 +168,29 @@ ptr_ptr_may_alias_p (tree ptr_a, tree ptr_b,
 		     struct data_reference *drb, 
 		     bool *aliased)
 {  
-  tree tag_a, tag_b;
+  tree tag_a = NULL_TREE, tag_b = NULL_TREE;
+  struct ptr_info_def *pi_a = DR_PTR_INFO (dra);  
+  struct ptr_info_def *pi_b = DR_PTR_INFO (drb);  
 
-  tag_a = get_var_ann (SSA_NAME_VAR (ptr_a))->symbol_mem_tag;
-  if (!tag_a)
-    tag_a = DR_MEMTAG (dra);
-  if (!tag_a)
-    return false;
-  tag_b = get_var_ann (SSA_NAME_VAR (ptr_b))->symbol_mem_tag;
-  if (!tag_b)
-    tag_b = DR_MEMTAG (drb);
-  if (!tag_b)
-    return false;
+  if (pi_a && pi_a->name_mem_tag && pi_b && pi_b->name_mem_tag)
+    {
+      tag_a = pi_a->name_mem_tag;
+      tag_b = pi_b->name_mem_tag;
+    }
+  else
+    {
+      tag_a = get_var_ann (SSA_NAME_VAR (ptr_a))->symbol_mem_tag;
+      if (!tag_a)
+	tag_a = DR_MEMTAG (dra);
+      if (!tag_a)
+	return false;
+      
+      tag_b = get_var_ann (SSA_NAME_VAR (ptr_b))->symbol_mem_tag;
+      if (!tag_b)
+	tag_b = DR_MEMTAG (drb);
+      if (!tag_b)
+	return false;
+    }
   *aliased = (tag_a == tag_b);
   return true;
 }
@@ -244,6 +259,38 @@ record_ptr_differ_p (struct data_reference *dra,
     return false;
 }
 
+/* Determine if two record/union accesses are aliased. Return TRUE if they 
+   differ.  */
+static bool
+record_record_differ_p (struct data_reference *dra,
+			struct data_reference *drb)
+{
+  bool aliased;
+  tree base_a = DR_BASE_OBJECT (dra);
+  tree base_b = DR_BASE_OBJECT (drb);
+
+  if (TREE_CODE (base_b) != COMPONENT_REF 
+      || TREE_CODE (base_a) != COMPONENT_REF)
+    return false;
+
+  /* Peel COMPONENT_REFs to get to the base. Do not peel INDIRECT_REFs.
+     For a.b.c.d[i] we will get a, and for a.b->c.d[i] we will get a.b.  
+     Probably will be unnecessary with struct alias analysis.  */
+  while (TREE_CODE (base_b) == COMPONENT_REF)
+    base_b = TREE_OPERAND (base_b, 0);
+  while (TREE_CODE (base_a) == COMPONENT_REF)
+    base_a = TREE_OPERAND (base_a, 0);
+
+  if (TREE_CODE (base_a) == INDIRECT_REF
+      && TREE_CODE (base_b) == INDIRECT_REF
+      && ptr_ptr_may_alias_p (TREE_OPERAND (base_a, 0), 
+			      TREE_OPERAND (base_b, 0), 
+			      dra, drb, &aliased)
+      && !aliased)
+    return true;
+  else
+    return false;
+}
     
 /* Determine if an array access (BASE_A) and a record/union access (BASE_B)
    are not aliased. Return TRUE if they differ.  */
@@ -408,6 +455,13 @@ base_object_differ_p (struct data_reference *a,
       return true;
     }
 
+  /* Compare two record/union accesses (b.c[i] or p->c[i]).  */
+  if (record_record_differ_p (a, b))
+    {
+      *differ_p = true;
+      return true;
+    }
+
   return false;
 }
 
-- 
GitLab