Commit 1842e4d4 by Richard Guenther Committed by Richard Biener

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
parent 3f9f2474
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> 2008-05-21 H.J. Lu <hongjiu.lu@intel.com>
* config/i386/i386.c (ix86_expand_vector_init_one_var): Use * config/i386/i386.c (ix86_expand_vector_init_one_var): Use
......
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> 2008-05-22 Arnaud Charlet <charlet@adacore.com>
* gnat.dg/slice5.adb: New test. * gnat.dg/slice5.adb: New test.
......
/* { 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) ...@@ -1041,6 +1041,7 @@ refs_may_alias_p (tree ref1, tree ref2)
HOST_WIDE_INT offset1 = 0, offset2 = 0; HOST_WIDE_INT offset1 = 0, offset2 = 0;
HOST_WIDE_INT size1 = -1, size2 = -1; HOST_WIDE_INT size1 = -1, size2 = -1;
HOST_WIDE_INT max_size1 = -1, max_size2 = -1; HOST_WIDE_INT max_size1 = -1, max_size2 = -1;
bool strict_aliasing_applies;
gcc_assert ((SSA_VAR_P (ref1) gcc_assert ((SSA_VAR_P (ref1)
|| handled_component_p (ref1) || handled_component_p (ref1)
...@@ -1068,19 +1069,78 @@ refs_may_alias_p (tree ref1, tree ref2) ...@@ -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 both references are based on the same variable, they cannot alias if
if the accesses do not overlap. */ if the accesses do not overlap. */
if (SSA_VAR_P (base1) if (SSA_VAR_P (base1)
&& SSA_VAR_P (base2) && SSA_VAR_P (base2))
&& (!operand_equal_p (base1, base2, 0) {
|| !ranges_overlap_p (offset1, max_size1, offset2, max_size2))) if (!operand_equal_p (base1, base2, 0))
return false; return false;
return ranges_overlap_p (offset1, max_size1, offset2, max_size2);
}
/* If both references are through pointers and both pointers are equal /* If one base is a ref-all pointer weird things are allowed. */
then they do not alias if the accesses do not overlap. */ strict_aliasing_applies = (flag_strict_aliasing
if (TREE_CODE (base1) == INDIRECT_REF && get_alias_set (base1) != 0
&& TREE_CODE (base2) == INDIRECT_REF && get_alias_set (base2) != 0);
&& operand_equal_p (TREE_OPERAND (base1, 0),
TREE_OPERAND (base2, 0), 0) /* If both references are through the same type, or if strict aliasing
&& !ranges_overlap_p (offset1, max_size1, offset2, max_size2)) doesn't apply they are through two same pointers, they do not alias
return false; 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; return true;
} }
......
...@@ -1617,41 +1617,13 @@ mem_refs_may_alias_p (tree mem1, tree mem2, struct pointer_map_t **ttae_cache) ...@@ -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 /* 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 object and their offset differ in such a way that the locations cannot
overlap, then they cannot alias. */ overlap, then they cannot alias. */
aff_tree off1, off2;
double_int size1, size2; 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 /* Perform basic offset and type-based disambiguation. */
&& !INDIRECT_REF_P (base1) if (!refs_may_alias_p (mem1, mem2))
&& base2
&& !INDIRECT_REF_P (base2)
&& !operand_equal_p (base1, base2, 0))
return false; 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 expansion of addresses may be a bit expensive, thus we only do
the check at -O2 and higher optimization levels. */ the check at -O2 and higher optimization levels. */
if (optimize < 2) if (optimize < 2)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment