From 371a73ce70ef606152dc6243936448d4ca92a8ab Mon Sep 17 00:00:00 2001 From: hubicka Date: Sun, 16 Jun 2019 17:59:02 +0000 Subject: [PATCH] * 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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@272357 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/ChangeLog | 5 ++ gcc/testsuite/ChangeLog | 5 ++ .../gcc.dg/tree-ssa/alias-access-path-4.c | 24 ++++++ .../gcc.dg/tree-ssa/alias-access-path-5.c | 25 ++++++ gcc/tree-ssa-alias.c | 82 ++++++++++++++++--- 5 files changed, 129 insertions(+), 12 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/alias-access-path-4.c create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/alias-access-path-5.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 89bb8c550ffe..05c18aa64795 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,8 @@ +2019-06-16 Jan Hubicka + + * tree-ssa-alias.c (aliasing_component_refs_p): Watch for arrays + at the end of structures. + 2019-06-16 Iain Sandoe * config/darwin.c (machopic_indirect_call_target): Use renamed diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index db2175048755..51861120f8fe 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2019-06-16 Jan Hubicka + + * 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 PR d/90650 diff --git a/gcc/testsuite/gcc.dg/tree-ssa/alias-access-path-4.c b/gcc/testsuite/gcc.dg/tree-ssa/alias-access-path-4.c new file mode 100644 index 000000000000..641ef89cbb8a --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/alias-access-path-4.c @@ -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"} } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/alias-access-path-5.c b/gcc/testsuite/gcc.dg/tree-ssa/alias-access-path-5.c new file mode 100644 index 000000000000..412f99e7c550 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/alias-access-path-5.c @@ -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"} } */ diff --git a/gcc/tree-ssa-alias.c b/gcc/tree-ssa-alias.c index 9cd39a2b6af2..52f9270c6045 100644 --- a/gcc/tree-ssa-alias.c +++ b/gcc/tree-ssa-alias.c @@ -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)) -- 2.39.2