OSDN Git Service

* tree-ssa-alias.c (count_ptr_derefs): Do not consider
authordnovillo <dnovillo@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 22 Jul 2005 13:39:18 +0000 (13:39 +0000)
committerdnovillo <dnovillo@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 22 Jul 2005 13:39:18 +0000 (13:39 +0000)
        &PTR->FLD a dereference of PTR.
        * tree-ssa-structalias.c (update_alias_info): Consider &PTR->FLD
        a potential dereference of PTR.

testsuite/ChangeLog

        * gcc.dg/tree-ssa/20050719-1.c: New test.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@102283 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/tree-ssa/20050719-1.c [new file with mode: 0644]
gcc/tree-ssa-alias.c
gcc/tree-ssa-structalias.c

index faddc83..e93626f 100644 (file)
@@ -1,3 +1,10 @@
+2005-07-22  Diego Novillo  <dnovillo@redhat.com>
+
+       * tree-ssa-alias.c (count_ptr_derefs): Do not consider
+       &PTR->FLD a dereference of PTR.
+       * tree-ssa-structalias.c (update_alias_info): Consider &PTR->FLD
+       a potential dereference of PTR.
+
 2005-07-22  J"orn Rennecke <joern.rennecke@st.com>
 
        PR rtl-optimization/20370
index a71759e..25db24b 100644 (file)
@@ -1,3 +1,7 @@
+2005-07-22  Diego Novillo  <dnovillo@redhat.com>
+
+       * gcc.dg/tree-ssa/20050719-1.c: New test.
+
 2005-07-22  Bernd Schmidt  <bernd.schmidt@analog.com>
 
        * gcc.dg/bfin-longcall-1.c: New file.
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/20050719-1.c b/gcc/testsuite/gcc.dg/tree-ssa/20050719-1.c
new file mode 100644 (file)
index 0000000..a1c08e3
--- /dev/null
@@ -0,0 +1,37 @@
+/* { dg-do run } */
+/* { dg-options "-O2" } */
+
+extern void abort (void) __attribute__ ((__nothrow__)) __attribute__
+((__noreturn__));
+extern void exit (int __status) __attribute__ ((__nothrow__))
+__attribute__ ((__noreturn__));
+
+struct bootLoader {
+  int x;
+};
+
+void
+zap(struct bootLoader *bootLoader)
+{
+  /* The expression on the RHS of the assignment is *not* a
+     dereference of pointer 'bootLoader'.  It is merely used as an
+     offset calculation.  VRP was erroneously removing the if()
+     because it thought that 'bootLoader' was always dereferenced.  */
+  int *boot = &bootLoader->x;
+
+  if (bootLoader)
+    {
+      useboot (boot);
+    }
+}
+
+int
+useboot (void *boot)
+{
+  abort ();
+}
+
+main()
+{
+  zap (0);
+}
index c65fe8d..76d883a 100644 (file)
@@ -344,12 +344,20 @@ struct count_ptr_d
    (ALIGN/MISALIGNED_)INDIRECT_REF nodes for the pointer passed in DATA.  */
 
 static tree
-count_ptr_derefs (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED, void *data)
+count_ptr_derefs (tree *tp, int *walk_subtrees, void *data)
 {
   struct count_ptr_d *count_p = (struct count_ptr_d *) data;
 
+  /* Do not walk inside ADDR_EXPR nodes.  In the expression &ptr->fld,
+     pointer 'ptr' is *not* dereferenced, it is simply used to compute
+     the address of 'fld' as 'ptr + offsetof(fld)'.  */
+  if (TREE_CODE (*tp) == ADDR_EXPR)
+    {
+      *walk_subtrees = 0;
+      return NULL_TREE;
+    }
+
   if (INDIRECT_REF_P (*tp) && TREE_OPERAND (*tp, 0) == count_p->ptr)
-/*       || (TREE_CODE (*tp) == MEM_REF && MEM_REF_SYMBOL (*tp) == count_p->ptr)) */
     count_p->count++;
 
   return NULL_TREE;
index 867c6a7..2a10a8d 100644 (file)
@@ -2555,7 +2555,7 @@ update_alias_info (tree stmt, struct alias_info *ai)
       tree op, var;
       var_ann_t v_ann;
       struct ptr_info_def *pi;
-      bool is_store;
+      bool is_store, is_potential_deref;
       unsigned num_uses, num_derefs;
 
       op = USE_FROM_PTR (use_p);
@@ -2612,7 +2612,42 @@ update_alias_info (tree stmt, struct alias_info *ai)
         is an escape point, whether OP escapes.  */
       count_uses_and_derefs (op, stmt, &num_uses, &num_derefs, &is_store);
 
-      if (num_derefs > 0)
+      /* Handle a corner case involving address expressions of the
+        form '&PTR->FLD'.  The problem with these expressions is that
+        they do not represent a dereference of PTR.  However, if some
+        other transformation propagates them into an INDIRECT_REF
+        expression, we end up with '*(&PTR->FLD)' which is folded
+        into 'PTR->FLD'.
+
+        So, if the original code had no other dereferences of PTR,
+        the aliaser will not create memory tags for it, and when
+        &PTR->FLD gets propagated to INDIRECT_REF expressions, the
+        memory operations will receive no V_MAY_DEF/VUSE operands.
+
+        One solution would be to have count_uses_and_derefs consider
+        &PTR->FLD a dereference of PTR.  But that is wrong, since it
+        is not really a dereference but an offset calculation.
+
+        What we do here is to recognize these special ADDR_EXPR
+        nodes.  Since these expressions are never GIMPLE values (they
+        are not GIMPLE invariants), they can only appear on the RHS
+        of an assignment and their base address is always an
+        INDIRECT_REF expression.  */
+      is_potential_deref = false;
+      if (TREE_CODE (stmt) == MODIFY_EXPR
+         && TREE_CODE (TREE_OPERAND (stmt, 1)) == ADDR_EXPR
+         && !is_gimple_val (TREE_OPERAND (stmt, 1)))
+       {
+         /* If the RHS if of the form &PTR->FLD and PTR == OP, then
+            this represents a potential dereference of PTR.  */
+         tree rhs = TREE_OPERAND (stmt, 1);
+         tree base = get_base_address (TREE_OPERAND (rhs, 0));
+         if (TREE_CODE (base) == INDIRECT_REF
+             && TREE_OPERAND (base, 0) == op)
+           is_potential_deref = true;
+       }
+
+      if (num_derefs > 0 || is_potential_deref)
        {
          /* Mark OP as dereferenced.  In a subsequent pass,
             dereferenced pointers that point to a set of