re PR tree-optimization/41186 (VN doesn't look through non-aliasing by offset memcpy)
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
This commit is contained in:
parent
01d93568e8
commit
a778c4e721
6 changed files with 142 additions and 20 deletions
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
29
gcc/testsuite/g++.dg/torture/pr41186.C
Normal file
29
gcc/testsuite/g++.dg/torture/pr41186.C
Normal file
|
@ -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;
|
||||
}
|
35
gcc/testsuite/g++.dg/tree-ssa/pr41186.C
Normal file
35
gcc/testsuite/g++.dg/tree-ssa/pr41186.C
Normal file
|
@ -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" } } */
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Add table
Reference in a new issue