]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
re PR tree-optimization/41186 (VN doesn't look through non-aliasing by offset memcpy)
authorRichard Guenther <rguenther@suse.de>
Sun, 30 Aug 2009 11:52:13 +0000 (11:52 +0000)
committerRichard Biener <rguenth@gcc.gnu.org>
Sun, 30 Aug 2009 11:52:13 +0000 (11:52 +0000)
2009-08-30  Richard Guenther  <rguenther@suse.de>

PR tree-optimization/41186
* tree-ssa-alias.c (ptr_deref_may_alias_ref_p): Remove.
(ao_ref_init_from_ptr_and_size): New function.
(ref_maybe_used_by_call_p_1): Be more precise tracking
used ranges for builtin functions.
(ref_maybe_used_by_call_p): Adjust.
(call_may_clobber_ref_p_1): Be more precise tracking clobbered
ranges for builtin functions.
* tree-ssa-alias.h (ao_ref_init_from_ptr_and_size): Declare.

* g++.dg/torture/pr41186.C: New testcase.
* g++.dg/tree-ssa/pr41186.C: Likewise.

From-SVN: r151226

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/torture/pr41186.C [new file with mode: 0644]
gcc/testsuite/g++.dg/tree-ssa/pr41186.C [new file with mode: 0644]
gcc/tree-ssa-alias.c
gcc/tree-ssa-alias.h

index 8b58aaaf4cb70c3750c7f6d94922c2c872927894..ec6c3cc3655283f21d08a2987d7a5b13c60295a1 100644 (file)
@@ -1,3 +1,15 @@
+2009-08-30  Richard Guenther  <rguenther@suse.de>
+
+       PR tree-optimization/41186
+       * tree-ssa-alias.c (ptr_deref_may_alias_ref_p): Remove.
+       (ao_ref_init_from_ptr_and_size): New function.
+       (ref_maybe_used_by_call_p_1): Be more precise tracking
+       used ranges for builtin functions.
+       (ref_maybe_used_by_call_p): Adjust.
+       (call_may_clobber_ref_p_1): Be more precise tracking clobbered
+       ranges for builtin functions.
+       * tree-ssa-alias.h (ao_ref_init_from_ptr_and_size): Declare.
+
 2009-08-30  Alan Modra  <amodra@bigpond.net.au>
 
        PR target/41081
index eb4d96c7927145105329946276f36824ab6e30e9..3173f578ce90e1237d4c4233ca74fb12fe8f3a35 100644 (file)
@@ -1,3 +1,9 @@
+2009-08-30  Richard Guenther  <rguenther@suse.de>
+
+       PR tree-optimization/41186
+       * g++.dg/torture/pr41186.C: New testcase.
+       * g++.dg/tree-ssa/pr41186.C: Likewise.
+
 2009-08-30  Dodji Seketeli  <dodji@redhat.com>
 
        PR c++/41187
diff --git a/gcc/testsuite/g++.dg/torture/pr41186.C b/gcc/testsuite/g++.dg/torture/pr41186.C
new file mode 100644 (file)
index 0000000..fdfee2c
--- /dev/null
@@ -0,0 +1,29 @@
+/* { dg-do run } */
+
+struct Foo {
+  Foo() {};
+  int i;
+  short f;
+};
+struct Bar : public Foo {
+  Bar() {};
+  short b;
+};
+
+extern "C" void abort(void);
+
+int main()
+{
+  Bar b1, b2;
+  b2.i = 0;
+  b1.f = 0;
+  b1.b = 1;
+  b2.f = 1;
+  b2.b = 2;
+  static_cast<Foo&>(b1) = static_cast<Foo&>(b2);
+  if (b1.i != 0 || b1.b != 1)
+    abort ();
+  if (b1.f != 1)
+    abort ();
+  return 0;
+}
diff --git a/gcc/testsuite/g++.dg/tree-ssa/pr41186.C b/gcc/testsuite/g++.dg/tree-ssa/pr41186.C
new file mode 100644 (file)
index 0000000..91f21a8
--- /dev/null
@@ -0,0 +1,35 @@
+/* { dg-do compile } */
+/* { dg-options "-O -fdump-tree-fre-details" } */
+
+struct Foo {
+  Foo() {};
+  int i;
+  short f;
+};
+struct Bar : public Foo {
+  Bar() {};
+  short b;
+};
+
+extern "C" void abort(void);
+
+int main()
+{
+  Bar b1, b2;
+  b2.i = 0;
+  b1.f = 0;
+  b1.b = 1;
+  b2.f = 1;
+  b2.b = 2;
+  static_cast<Foo&>(b1) = static_cast<Foo&>(b2);
+  if (b1.i != 0 || b1.b != 1)
+    abort ();
+  if (b1.f != 1)
+    abort ();
+  return 0;
+}
+
+/* { dg-final { scan-tree-dump "Replaced b1.b with 1" "fre" } } */
+/* { dg-final { scan-tree-dump "Replaced b1.i with 0" "fre" { xfail *-*-* } } } */
+/* { dg-final { scan-tree-dump "Replaced b1.f with 1" "fre" { xfail *-*-* } } } */
+/* { dg-final { cleanup-tree-dump "fre" } } */
index acfdcae0c0c937a28fffa1e8d708518bf5b8dd0d..7e83a84b82ce063dac09d617b5aa1c082bd8c269 100644 (file)
@@ -302,14 +302,6 @@ ptr_deref_may_alias_ref_p_1 (tree ptr, ao_ref *ref)
   return true;
 }
 
-static bool
-ptr_deref_may_alias_ref_p (tree ptr, tree ref)
-{
-  ao_ref r;
-  ao_ref_init (&r, ref);
-  return ptr_deref_may_alias_ref_p_1 (ptr, &r);
-}
-
 
 /* Dump alias information on FILE.  */
 
@@ -490,6 +482,34 @@ ao_ref_alias_set (ao_ref *ref)
   return ref->ref_alias_set;
 }
 
+/* Init an alias-oracle reference representation from a gimple pointer
+   PTR and a gimple size SIZE in bytes.  If SIZE is NULL_TREE the the
+   size is assumed to be unknown.  The access is assumed to be only
+   to or after of the pointer target, not before it.  */
+
+void
+ao_ref_init_from_ptr_and_size (ao_ref *ref, tree ptr, tree size)
+{
+  HOST_WIDE_INT t1, t2;
+  ref->ref = NULL_TREE;
+  if (TREE_CODE (ptr) == ADDR_EXPR)
+    ref->base = get_ref_base_and_extent (TREE_OPERAND (ptr, 0),
+                                        &ref->offset, &t1, &t2);
+  else
+    {
+      ref->base = build1 (INDIRECT_REF, char_type_node, ptr);
+      ref->offset = 0;
+    }
+  if (size
+      && host_integerp (size, 0)
+      && TREE_INT_CST_LOW (size) * 8 / 8 == TREE_INT_CST_LOW (size))
+    ref->max_size = ref->size = TREE_INT_CST_LOW (size) * 8;
+  else
+    ref->max_size = ref->size = -1;
+  ref->ref_alias_set = 0;
+  ref->base_alias_set = 0;
+}
+
 /* Return 1 if TYPE1 and TYPE2 are to be considered equivalent for the
    purpose of TBAA.  Return 0 if they are distinct and -1 if we cannot
    decide.  */
@@ -854,7 +874,7 @@ refs_output_dependent_p (tree store1, tree store2)
    otherwise return false.  */
 
 static bool
-ref_maybe_used_by_call_p_1 (gimple call, tree ref)
+ref_maybe_used_by_call_p_1 (gimple call, ao_ref *ref)
 {
   tree base, callee;
   unsigned i;
@@ -865,7 +885,7 @@ ref_maybe_used_by_call_p_1 (gimple call, tree ref)
       && (flags & (ECF_CONST|ECF_NOVOPS)))
     goto process_args;
 
-  base = get_base_address (ref);
+  base = ao_ref_base (ref);
   if (!base)
     return true;
 
@@ -899,8 +919,14 @@ ref_maybe_used_by_call_p_1 (gimple call, tree ref)
        case BUILT_IN_STRCAT:
        case BUILT_IN_STRNCAT:
          {
-           tree src = gimple_call_arg (call, 1);
-           return ptr_deref_may_alias_ref_p (src, ref);
+           ao_ref dref;
+           tree size = NULL_TREE;
+           if (gimple_call_num_args (call) == 3)
+             size = gimple_call_arg (call, 2);
+           ao_ref_init_from_ptr_and_size (&dref,
+                                          gimple_call_arg (call, 1),
+                                          size);
+           return refs_may_alias_p_1 (&dref, ref, false);
          }
        /* The following builtins do not read from memory.  */
        case BUILT_IN_FREE:
@@ -1004,9 +1030,13 @@ process_args:
        op = TREE_OPERAND (op, 0);
 
       if (TREE_CODE (op) != SSA_NAME
-         && !is_gimple_min_invariant (op)
-         && refs_may_alias_p (op, ref))
-       return true;
+         && !is_gimple_min_invariant (op))
+       {
+         ao_ref r;
+         ao_ref_init (&r, op);
+         if (refs_may_alias_p_1 (&r, ref, true))
+           return true;
+       }
     }
 
   return false;
@@ -1015,7 +1045,10 @@ process_args:
 static bool
 ref_maybe_used_by_call_p (gimple call, tree ref)
 {
-  bool res = ref_maybe_used_by_call_p_1 (call, ref);
+  ao_ref r;
+  bool res;
+  ao_ref_init (&r, ref);
+  res = ref_maybe_used_by_call_p_1 (call, &r);
   if (res)
     ++alias_stats.ref_maybe_used_by_call_p_may_alias;
   else
@@ -1106,15 +1139,21 @@ call_may_clobber_ref_p_1 (gimple call, ao_ref *ref)
        case BUILT_IN_STPNCPY:
        case BUILT_IN_STRCAT:
        case BUILT_IN_STRNCAT:
+       case BUILT_IN_MEMSET:
          {
-           tree dest = gimple_call_arg (call, 0);
-           return ptr_deref_may_alias_ref_p_1 (dest, ref);
+           ao_ref dref;
+           tree size = NULL_TREE;
+           if (gimple_call_num_args (call) == 3)
+             size = gimple_call_arg (call, 2);
+           ao_ref_init_from_ptr_and_size (&dref,
+                                          gimple_call_arg (call, 0),
+                                          size);
+           return refs_may_alias_p_1 (&dref, ref, false);
          }
        /* Freeing memory kills the pointed-to memory.  More importantly
           the call has to serve as a barrier for moving loads and stores
-          across it.  Same is true for memset.  */
+          across it.  */
        case BUILT_IN_FREE:
-       case BUILT_IN_MEMSET:
          {
            tree ptr = gimple_call_arg (call, 0);
            return ptr_deref_may_alias_ref_p_1 (ptr, ref);
index 3a08750519958d5fcaaf22e6f57f3a8653fe9958..497069258367f2c1b8c30671c45b6cee0708c2ac 100644 (file)
@@ -88,6 +88,7 @@ typedef struct ao_ref_s
 
 /* In tree-ssa-alias.c  */
 extern void ao_ref_init (ao_ref *, tree);
+extern void ao_ref_init_from_ptr_and_size (ao_ref *, tree, tree);
 extern tree ao_ref_base (ao_ref *);
 extern alias_set_type ao_ref_alias_set (ao_ref *);
 extern bool ptr_deref_may_alias_global_p (tree);