diff options
-rw-r--r-- | gcc/ChangeLog | 12 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/torture/pr41186.C | 29 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/tree-ssa/pr41186.C | 35 | ||||
-rw-r--r-- | gcc/tree-ssa-alias.c | 79 | ||||
-rw-r--r-- | gcc/tree-ssa-alias.h | 1 |
6 files changed, 142 insertions, 20 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 8b58aaaf4cb..ec6c3cc3655 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -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 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index eb4d96c7927..3173f578ce9 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -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 index 00000000000..fdfee2cd373 --- /dev/null +++ b/gcc/testsuite/g++.dg/torture/pr41186.C @@ -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 index 00000000000..91f21a8c643 --- /dev/null +++ b/gcc/testsuite/g++.dg/tree-ssa/pr41186.C @@ -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" } } */ diff --git a/gcc/tree-ssa-alias.c b/gcc/tree-ssa-alias.c index acfdcae0c0c..7e83a84b82c 100644 --- a/gcc/tree-ssa-alias.c +++ b/gcc/tree-ssa-alias.c @@ -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); diff --git a/gcc/tree-ssa-alias.h b/gcc/tree-ssa-alias.h index 3a087505199..49706925836 100644 --- a/gcc/tree-ssa-alias.h +++ b/gcc/tree-ssa-alias.h @@ -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); |