tree-dfa.c (refs_may_alias_p): Exit early if possible.
2008-05-22 Richard Guenther <rguenther@suse.de> * tree-dfa.c (refs_may_alias_p): Exit early if possible. Handle more cases of offset disambiguation that is possible if strict-aliasing rules apply. * tree-ssa-loop-im.c (mem_refs_may_alias_p): Use refs_may_alias_p for basic offset and type-based disambiguation. * gcc.dg/tree-ssa/alias-18.c: New testcase. From-SVN: r135754
This commit is contained in:
parent
3f9f247417
commit
1842e4d44e
5 changed files with 177 additions and 43 deletions
|
@ -1,3 +1,11 @@
|
|||
2008-05-22 Richard Guenther <rguenther@suse.de>
|
||||
|
||||
* tree-dfa.c (refs_may_alias_p): Exit early if possible. Handle
|
||||
more cases of offset disambiguation that is possible if
|
||||
strict-aliasing rules apply.
|
||||
* tree-ssa-loop-im.c (mem_refs_may_alias_p): Use refs_may_alias_p
|
||||
for basic offset and type-based disambiguation.
|
||||
|
||||
2008-05-21 H.J. Lu <hongjiu.lu@intel.com>
|
||||
|
||||
* config/i386/i386.c (ix86_expand_vector_init_one_var): Use
|
||||
|
|
|
@ -1,3 +1,7 @@
|
|||
2008-05-22 Richard Guenther <rguenther@suse.de>
|
||||
|
||||
* gcc.dg/tree-ssa/alias-18.c: New testcase.
|
||||
|
||||
2008-05-22 Arnaud Charlet <charlet@adacore.com>
|
||||
|
||||
* gnat.dg/slice5.adb: New test.
|
||||
|
|
90
gcc/testsuite/gcc.dg/tree-ssa/alias-18.c
Normal file
90
gcc/testsuite/gcc.dg/tree-ssa/alias-18.c
Normal file
|
@ -0,0 +1,90 @@
|
|||
/* { dg-do compile } */
|
||||
/* { dg-options "-O2 -fdump-tree-fre-details -fdump-tree-optimized --param max-aliased-vops=0" } */
|
||||
|
||||
struct A {
|
||||
int i;
|
||||
int j;
|
||||
float x;
|
||||
};
|
||||
struct B {
|
||||
struct A a;
|
||||
int k;
|
||||
};
|
||||
|
||||
int g;
|
||||
|
||||
int test0 (struct A *p, struct A *q)
|
||||
{
|
||||
p->i = 0;
|
||||
q->j = -1;
|
||||
return p->i;
|
||||
}
|
||||
|
||||
int test1 (struct A *p, struct B *q)
|
||||
{
|
||||
p->i = 1;
|
||||
q->k = -1;
|
||||
return p->i;
|
||||
}
|
||||
|
||||
int test2 (struct A *p, struct B *q)
|
||||
{
|
||||
p->i = 2;
|
||||
q->a.i = -1;
|
||||
return p->i;
|
||||
}
|
||||
|
||||
int test3 (struct A *p, struct B *q)
|
||||
{
|
||||
p->i = 3;
|
||||
q->a.j = -1;
|
||||
return p->i;
|
||||
}
|
||||
|
||||
int test4 (struct A *p)
|
||||
{
|
||||
g = 4;
|
||||
p->i = -1;
|
||||
return g;
|
||||
}
|
||||
|
||||
int test5 (struct A *p)
|
||||
{
|
||||
p->i = 5;
|
||||
g = -1;
|
||||
return p->i;
|
||||
}
|
||||
|
||||
int test6 (struct A *p, int *q)
|
||||
{
|
||||
p->i = 6;
|
||||
*q = -1;
|
||||
return p->i;
|
||||
}
|
||||
|
||||
int test7 (struct A *p, int *q)
|
||||
{
|
||||
p->j = 7;
|
||||
*q = -1;
|
||||
return p->j;
|
||||
}
|
||||
|
||||
int test8 (struct A *p, int *q)
|
||||
{
|
||||
*q = 8;
|
||||
p->x = -1;
|
||||
return *q;
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump "with 0" "fre" } } */
|
||||
/* { dg-final { scan-tree-dump "with 1" "fre" { xfail *-*-* } } } */
|
||||
/* { dg-final { scan-tree-dump "with 3" "fre" } } */
|
||||
/* { dg-final { scan-tree-dump "with 4" "fre" } } */
|
||||
/* { dg-final { scan-tree-dump "with 5" "fre" } } */
|
||||
/* { dg-final { scan-tree-dump "with 8" "fre" } } */
|
||||
/* { dg-final { scan-tree-dump-not "return 2;" "optimized" } } */
|
||||
/* { dg-final { scan-tree-dump-not "return 6;" "optimized" } } */
|
||||
/* { dg-final { scan-tree-dump-not "return 7;" "optimized" } } */
|
||||
/* { dg-final { scan-tree-dump-not "return -1;" "optimized" } } */
|
||||
/* { dg-final { cleanup-tree-dump "fre" } } */
|
||||
/* { dg-final { cleanup-tree-dump "optimized" } } */
|
|
@ -1041,6 +1041,7 @@ refs_may_alias_p (tree ref1, tree ref2)
|
|||
HOST_WIDE_INT offset1 = 0, offset2 = 0;
|
||||
HOST_WIDE_INT size1 = -1, size2 = -1;
|
||||
HOST_WIDE_INT max_size1 = -1, max_size2 = -1;
|
||||
bool strict_aliasing_applies;
|
||||
|
||||
gcc_assert ((SSA_VAR_P (ref1)
|
||||
|| handled_component_p (ref1)
|
||||
|
@ -1068,19 +1069,78 @@ refs_may_alias_p (tree ref1, tree ref2)
|
|||
If both references are based on the same variable, they cannot alias if
|
||||
if the accesses do not overlap. */
|
||||
if (SSA_VAR_P (base1)
|
||||
&& SSA_VAR_P (base2)
|
||||
&& (!operand_equal_p (base1, base2, 0)
|
||||
|| !ranges_overlap_p (offset1, max_size1, offset2, max_size2)))
|
||||
return false;
|
||||
&& SSA_VAR_P (base2))
|
||||
{
|
||||
if (!operand_equal_p (base1, base2, 0))
|
||||
return false;
|
||||
return ranges_overlap_p (offset1, max_size1, offset2, max_size2);
|
||||
}
|
||||
|
||||
/* If both references are through pointers and both pointers are equal
|
||||
then they do not alias if the accesses do not overlap. */
|
||||
if (TREE_CODE (base1) == INDIRECT_REF
|
||||
&& TREE_CODE (base2) == INDIRECT_REF
|
||||
&& operand_equal_p (TREE_OPERAND (base1, 0),
|
||||
TREE_OPERAND (base2, 0), 0)
|
||||
&& !ranges_overlap_p (offset1, max_size1, offset2, max_size2))
|
||||
return false;
|
||||
/* If one base is a ref-all pointer weird things are allowed. */
|
||||
strict_aliasing_applies = (flag_strict_aliasing
|
||||
&& get_alias_set (base1) != 0
|
||||
&& get_alias_set (base2) != 0);
|
||||
|
||||
/* If both references are through the same type, or if strict aliasing
|
||||
doesn't apply they are through two same pointers, they do not alias
|
||||
if the accesses do not overlap. */
|
||||
if ((strict_aliasing_applies
|
||||
&& (TYPE_MAIN_VARIANT (TREE_TYPE (base1))
|
||||
== TYPE_MAIN_VARIANT (TREE_TYPE (base2))))
|
||||
|| (TREE_CODE (base1) == INDIRECT_REF
|
||||
&& TREE_CODE (base2) == INDIRECT_REF
|
||||
&& operand_equal_p (TREE_OPERAND (base1, 0),
|
||||
TREE_OPERAND (base2, 0), 0)))
|
||||
return ranges_overlap_p (offset1, max_size1, offset2, max_size2);
|
||||
|
||||
/* If both are component references through pointers try to find a
|
||||
common base and apply offset based disambiguation. This handles
|
||||
for example
|
||||
struct A { int i; int j; } *q;
|
||||
struct B { struct A a; int k; } *p;
|
||||
disambiguating q->i and p->a.j. */
|
||||
if (strict_aliasing_applies
|
||||
&& (TREE_CODE (base1) == INDIRECT_REF
|
||||
|| TREE_CODE (base2) == INDIRECT_REF)
|
||||
&& handled_component_p (ref1)
|
||||
&& handled_component_p (ref2))
|
||||
{
|
||||
tree *refp;
|
||||
/* Now search for the type of base1 in the access path of ref2. This
|
||||
would be a common base for doing offset based disambiguation on. */
|
||||
refp = &ref2;
|
||||
while (handled_component_p (*refp)
|
||||
/* Note that the following is only conservative if there are
|
||||
never copies of types appearing as sub-structures. */
|
||||
&& (TYPE_MAIN_VARIANT (TREE_TYPE (*refp))
|
||||
!= TYPE_MAIN_VARIANT (TREE_TYPE (base1))))
|
||||
refp = &TREE_OPERAND (*refp, 0);
|
||||
if (TYPE_MAIN_VARIANT (TREE_TYPE (*refp))
|
||||
== TYPE_MAIN_VARIANT (TREE_TYPE (base1)))
|
||||
{
|
||||
HOST_WIDE_INT offadj, sztmp, msztmp;
|
||||
get_ref_base_and_extent (*refp, &offadj, &sztmp, &msztmp);
|
||||
offset2 -= offadj;
|
||||
return ranges_overlap_p (offset1, max_size1, offset2, max_size2);
|
||||
}
|
||||
/* The other way around. */
|
||||
refp = &ref1;
|
||||
while (handled_component_p (*refp)
|
||||
&& (TYPE_MAIN_VARIANT (TREE_TYPE (*refp))
|
||||
!= TYPE_MAIN_VARIANT (TREE_TYPE (base2))))
|
||||
refp = &TREE_OPERAND (*refp, 0);
|
||||
if (TYPE_MAIN_VARIANT (TREE_TYPE (*refp))
|
||||
== TYPE_MAIN_VARIANT (TREE_TYPE (base2)))
|
||||
{
|
||||
HOST_WIDE_INT offadj, sztmp, msztmp;
|
||||
get_ref_base_and_extent (*refp, &offadj, &sztmp, &msztmp);
|
||||
offset1 -= offadj;
|
||||
return ranges_overlap_p (offset1, max_size1, offset2, max_size2);
|
||||
}
|
||||
/* If we can be sure to catch all equivalent types in the search
|
||||
for the common base then we could return false here. In that
|
||||
case we would be able to disambiguate q->i and p->k. */
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -1617,41 +1617,13 @@ mem_refs_may_alias_p (tree mem1, tree mem2, struct pointer_map_t **ttae_cache)
|
|||
/* Perform BASE + OFFSET analysis -- if MEM1 and MEM2 are based on the same
|
||||
object and their offset differ in such a way that the locations cannot
|
||||
overlap, then they cannot alias. */
|
||||
aff_tree off1, off2;
|
||||
double_int size1, size2;
|
||||
tree base1, base2;
|
||||
aff_tree off1, off2;
|
||||
|
||||
/* If MEM1 and MEM2 are based on different variables, they cannot alias. */
|
||||
base1 = get_base_address (mem1);
|
||||
base2 = get_base_address (mem2);
|
||||
|
||||
if (base1
|
||||
&& !INDIRECT_REF_P (base1)
|
||||
&& base2
|
||||
&& !INDIRECT_REF_P (base2)
|
||||
&& !operand_equal_p (base1, base2, 0))
|
||||
/* Perform basic offset and type-based disambiguation. */
|
||||
if (!refs_may_alias_p (mem1, mem2))
|
||||
return false;
|
||||
|
||||
/* With strict aliasing, it is impossible to access a scalar variable through
|
||||
anything but a pointer dereference or through a union (gcc extension). */
|
||||
if (flag_strict_aliasing)
|
||||
{
|
||||
if (!INDIRECT_REF_P (mem1)
|
||||
&& base1
|
||||
&& TREE_CODE (TREE_TYPE (base1)) != UNION_TYPE
|
||||
&& SSA_VAR_P (mem2)
|
||||
&& !AGGREGATE_TYPE_P (TREE_TYPE (mem2)))
|
||||
return false;
|
||||
if (!INDIRECT_REF_P (mem2)
|
||||
&& base2
|
||||
&& TREE_CODE (TREE_TYPE (base2)) != UNION_TYPE
|
||||
&& SSA_VAR_P (mem1)
|
||||
&& !AGGREGATE_TYPE_P (TREE_TYPE (mem1)))
|
||||
return false;
|
||||
if (!alias_sets_conflict_p (get_alias_set (mem1), get_alias_set (mem2)))
|
||||
return false;
|
||||
}
|
||||
|
||||
/* The expansion of addresses may be a bit expensive, thus we only do
|
||||
the check at -O2 and higher optimization levels. */
|
||||
if (optimize < 2)
|
||||
|
|
Loading…
Add table
Reference in a new issue