alias-access-path-4.c: New testcase.
* gcc.dg/tree-ssa/alias-access-path-4.c: New testcase. * gcc.dg/tree-ssa/alias-access-path-5.c: New testcase. * tree-ssa-alias.c (aliasing_component_refs_p): Watch for arrays at the end of structures. From-SVN: r272357
This commit is contained in:
parent
ce3a201593
commit
8e2d0529d5
@ -1,3 +1,8 @@
|
||||
2019-06-16 Jan Hubicka <hubicka@ucw.cz>
|
||||
|
||||
* tree-ssa-alias.c (aliasing_component_refs_p): Watch for arrays
|
||||
at the end of structures.
|
||||
|
||||
2019-06-16 Iain Sandoe <iain@sandoe.co.uk>
|
||||
|
||||
* config/darwin.c (machopic_indirect_call_target): Use renamed
|
||||
|
@ -1,3 +1,8 @@
|
||||
2019-06-16 Jan Hubicka <hubicka@ucw.cz>
|
||||
|
||||
* gcc.dg/tree-ssa/alias-access-path-4.c: New testcase.
|
||||
* gcc.dg/tree-ssa/alias-access-path-5.c: New testcase.
|
||||
|
||||
2019-06-15 Iain Buclaw <ibuclaw@gdcproject.org>
|
||||
|
||||
PR d/90650
|
||||
|
24
gcc/testsuite/gcc.dg/tree-ssa/alias-access-path-4.c
Normal file
24
gcc/testsuite/gcc.dg/tree-ssa/alias-access-path-4.c
Normal file
@ -0,0 +1,24 @@
|
||||
/* { dg-do compile } */
|
||||
/* { dg-options "-O2 -fdump-tree-optimized" } */
|
||||
|
||||
struct a {int v1;
|
||||
int v2;};
|
||||
struct b {struct a a[0];};
|
||||
union c {struct b b;};
|
||||
|
||||
int
|
||||
test (struct b *bptr1, union c *cptr, int i, int j)
|
||||
{
|
||||
bptr1->a[i].v1=123;
|
||||
cptr->b.a[j].v2=1;
|
||||
return bptr1->a[i].v1;
|
||||
}
|
||||
int
|
||||
test2 (struct b *bptr1, union c *cptr, int i, int j)
|
||||
{
|
||||
bptr1->a[i].v1=124;
|
||||
cptr->b.a[j].v1=1;
|
||||
return bptr1->a[i].v1;
|
||||
}
|
||||
/* { dg-final { scan-tree-dump-times "return 123" 1 "optimized"} } */
|
||||
/* { dg-final { scan-tree-dump-not "return 124" "optimized"} } */
|
25
gcc/testsuite/gcc.dg/tree-ssa/alias-access-path-5.c
Normal file
25
gcc/testsuite/gcc.dg/tree-ssa/alias-access-path-5.c
Normal file
@ -0,0 +1,25 @@
|
||||
|
||||
/* { dg-do compile } */
|
||||
/* { dg-options "-O2 -fdump-tree-optimized" } */
|
||||
|
||||
struct a {int v1;
|
||||
int v2;};
|
||||
struct b {int array[0]; struct a a[];};
|
||||
union c {struct b b;};
|
||||
|
||||
int
|
||||
test (struct b *bptr1, union c *cptr, int i, int j)
|
||||
{
|
||||
bptr1->a[i].v1=123;
|
||||
cptr->b.a[j].v2=1;
|
||||
return bptr1->a[i].v1;
|
||||
}
|
||||
int
|
||||
test2 (struct b *bptr1, union c *cptr, int i, int j)
|
||||
{
|
||||
bptr1->a[i].v1=124;
|
||||
cptr->b.a[j].v1=1;
|
||||
return bptr1->a[i].v1;
|
||||
}
|
||||
/* { dg-final { scan-tree-dump-times "return 123" 1 "optimized"} } */
|
||||
/* { dg-final { scan-tree-dump-not "return 124" "optimized"} } */
|
@ -877,22 +877,62 @@ aliasing_component_refs_p (tree ref1,
|
||||
tree *refp;
|
||||
int same_p1 = 0, same_p2 = 0;
|
||||
bool maybe_match = false;
|
||||
tree end_struct_ref1 = NULL, end_struct_ref2 = NULL;
|
||||
|
||||
/* Choose bases and base types to search for. */
|
||||
base1 = ref1;
|
||||
while (handled_component_p (base1))
|
||||
base1 = TREE_OPERAND (base1, 0);
|
||||
{
|
||||
/* Generally access paths are monotous in the size of object. The
|
||||
exception are trailing arrays of structures. I.e.
|
||||
struct a {int array[0];};
|
||||
or
|
||||
struct a {int array1[0]; int array[];};
|
||||
Such struct has size 0 but accesses to a.array may have non-zero size.
|
||||
In this case the size of TREE_TYPE (base1) is smaller than
|
||||
size of TREE_TYPE (TREE_OPERNAD (base1, 0)).
|
||||
|
||||
Because we compare sizes of arrays just by sizes of their elements,
|
||||
we only need to care about zero sized array fields here. */
|
||||
if (TREE_CODE (base1) == COMPONENT_REF
|
||||
&& TREE_CODE (TREE_TYPE (TREE_OPERAND (base1, 1))) == ARRAY_TYPE
|
||||
&& (!TYPE_SIZE (TREE_TYPE (TREE_OPERAND (base1, 1)))
|
||||
|| integer_zerop (TYPE_SIZE (TREE_TYPE (TREE_OPERAND (base1, 1)))))
|
||||
&& array_at_struct_end_p (base1))
|
||||
{
|
||||
gcc_checking_assert (!end_struct_ref1);
|
||||
end_struct_ref1 = base1;
|
||||
}
|
||||
base1 = TREE_OPERAND (base1, 0);
|
||||
}
|
||||
type1 = TREE_TYPE (base1);
|
||||
base2 = ref2;
|
||||
while (handled_component_p (base2))
|
||||
base2 = TREE_OPERAND (base2, 0);
|
||||
{
|
||||
if (TREE_CODE (base2) == COMPONENT_REF
|
||||
&& TREE_CODE (TREE_TYPE (TREE_OPERAND (base2, 1))) == ARRAY_TYPE
|
||||
&& (!TYPE_SIZE (TREE_TYPE (TREE_OPERAND (base2, 1)))
|
||||
|| integer_zerop (TYPE_SIZE (TREE_TYPE (TREE_OPERAND (base2, 1)))))
|
||||
&& array_at_struct_end_p (base2))
|
||||
{
|
||||
gcc_checking_assert (!end_struct_ref2);
|
||||
end_struct_ref2 = base2;
|
||||
}
|
||||
base2 = TREE_OPERAND (base2, 0);
|
||||
}
|
||||
type2 = TREE_TYPE (base2);
|
||||
|
||||
/* Now search for the type1 in the access path of ref2. This
|
||||
would be a common base for doing offset based disambiguation on.
|
||||
This however only makes sense if type2 is big enough to hold type1. */
|
||||
int cmp_outer = compare_type_sizes (type2, type1);
|
||||
if (cmp_outer >= 0)
|
||||
|
||||
/* If type2 is big enough to contain type1 walk its access path.
|
||||
We also need to care of arrays at the end of structs that may extend
|
||||
beyond the end of structure. */
|
||||
if (cmp_outer >= 0
|
||||
|| (end_struct_ref2
|
||||
&& compare_type_sizes (TREE_TYPE (end_struct_ref2), type1) >= 0))
|
||||
{
|
||||
refp = &ref2;
|
||||
while (true)
|
||||
@ -900,7 +940,11 @@ aliasing_component_refs_p (tree ref1,
|
||||
/* We walk from inner type to the outer types. If type we see is
|
||||
already too large to be part of type1, terminate the search. */
|
||||
int cmp = compare_type_sizes (type1, TREE_TYPE (*refp));
|
||||
if (cmp < 0)
|
||||
|
||||
if (cmp < 0
|
||||
&& (!end_struct_ref1
|
||||
|| compare_type_sizes (TREE_TYPE (end_struct_ref1),
|
||||
TREE_TYPE (*refp)) < 0))
|
||||
break;
|
||||
/* If types may be of same size, see if we can decide about their
|
||||
equality. */
|
||||
@ -957,13 +1001,18 @@ aliasing_component_refs_p (tree ref1,
|
||||
}
|
||||
|
||||
/* If we didn't find a common base, try the other way around. */
|
||||
if (cmp_outer <= 0)
|
||||
if (cmp_outer <= 0
|
||||
|| (end_struct_ref1
|
||||
&& compare_type_sizes (TREE_TYPE (end_struct_ref1), type1) <= 0))
|
||||
{
|
||||
refp = &ref1;
|
||||
while (true)
|
||||
{
|
||||
int cmp = compare_type_sizes (type2, TREE_TYPE (*refp));
|
||||
if (cmp < 0)
|
||||
if (cmp < 0
|
||||
&& (!end_struct_ref2
|
||||
|| compare_type_sizes (TREE_TYPE (end_struct_ref2),
|
||||
TREE_TYPE (*refp)) < 0))
|
||||
break;
|
||||
/* If types may be of same size, see if we can decide about their
|
||||
equality. */
|
||||
@ -1024,6 +1073,9 @@ aliasing_component_refs_p (tree ref1,
|
||||
if there is no B2 in the tail of path1 and no B1 on the
|
||||
tail of path2. */
|
||||
if (compare_type_sizes (TREE_TYPE (ref2), type1) >= 0
|
||||
&& (!end_struct_ref1
|
||||
|| compare_type_sizes (TREE_TYPE (ref2),
|
||||
TREE_TYPE (end_struct_ref1)) >= 0)
|
||||
&& type_has_components_p (TREE_TYPE (ref2))
|
||||
&& (base1_alias_set == ref2_alias_set
|
||||
|| alias_set_subset_of (base1_alias_set, ref2_alias_set)))
|
||||
@ -1034,6 +1086,9 @@ aliasing_component_refs_p (tree ref1,
|
||||
/* If this is ptr vs. decl then we know there is no ptr ... decl path. */
|
||||
if (!ref2_is_decl
|
||||
&& compare_type_sizes (TREE_TYPE (ref1), type2) >= 0
|
||||
&& (!end_struct_ref2
|
||||
|| compare_type_sizes (TREE_TYPE (ref1),
|
||||
TREE_TYPE (end_struct_ref2)) >= 0)
|
||||
&& type_has_components_p (TREE_TYPE (ref1))
|
||||
&& (base2_alias_set == ref1_alias_set
|
||||
|| alias_set_subset_of (base2_alias_set, ref1_alias_set)))
|
||||
@ -1477,8 +1532,9 @@ indirect_ref_may_alias_decl_p (tree ref1 ATTRIBUTE_UNUSED, tree base1,
|
||||
&& same_type_for_tbaa (TREE_TYPE (base1), TREE_TYPE (dbase2)) == 1
|
||||
&& (TREE_CODE (TREE_TYPE (base1)) != ARRAY_TYPE
|
||||
|| (TYPE_SIZE (TREE_TYPE (base1))
|
||||
&& TREE_CODE (TYPE_SIZE (TREE_TYPE (base1))) == INTEGER_CST)))
|
||||
return ranges_maybe_overlap_p (doffset1, max_size1, doffset2, max_size2);
|
||||
&& TREE_CODE (TYPE_SIZE (TREE_TYPE (base1))) == INTEGER_CST))
|
||||
&& !ranges_maybe_overlap_p (doffset1, max_size1, doffset2, max_size2))
|
||||
return false;
|
||||
|
||||
if (ref1 && ref2
|
||||
&& nonoverlapping_component_refs_p (ref1, ref2))
|
||||
@ -1558,8 +1614,9 @@ indirect_refs_may_alias_p (tree ref1 ATTRIBUTE_UNUSED, tree base1,
|
||||
{
|
||||
poly_offset_int moff1 = mem_ref_offset (base1) << LOG2_BITS_PER_UNIT;
|
||||
poly_offset_int moff2 = mem_ref_offset (base2) << LOG2_BITS_PER_UNIT;
|
||||
return ranges_maybe_overlap_p (offset1 + moff1, max_size1,
|
||||
offset2 + moff2, max_size2);
|
||||
if (!ranges_maybe_overlap_p (offset1 + moff1, max_size1,
|
||||
offset2 + moff2, max_size2))
|
||||
return false;
|
||||
}
|
||||
if (!ptr_derefs_may_alias_p (ptr1, ptr2))
|
||||
return false;
|
||||
@ -1598,8 +1655,9 @@ indirect_refs_may_alias_p (tree ref1 ATTRIBUTE_UNUSED, tree base1,
|
||||
/* But avoid treating arrays as "objects", instead assume they
|
||||
can overlap by an exact multiple of their element size.
|
||||
See gcc.dg/torture/alias-2.c. */
|
||||
&& TREE_CODE (TREE_TYPE (ptrtype1)) != ARRAY_TYPE)
|
||||
return ranges_maybe_overlap_p (offset1, max_size1, offset2, max_size2);
|
||||
&& TREE_CODE (TREE_TYPE (ptrtype1)) != ARRAY_TYPE
|
||||
&& !ranges_maybe_overlap_p (offset1, max_size1, offset2, max_size2))
|
||||
return false;
|
||||
|
||||
if (ref1 && ref2
|
||||
&& nonoverlapping_component_refs_p (ref1, ref2))
|
||||
|
Loading…
x
Reference in New Issue
Block a user