From 06dd9b3d4e86b2c12ba55144147272ac05eeed40 Mon Sep 17 00:00:00 2001 From: Jan Hubicka Date: Fri, 7 Jun 2019 10:14:04 +0200 Subject: [PATCH] Make aliasing_component_refs_p to work harder when same_type_for_tbaa returns -1 * tree-ssa-alias.c (aliasing_component_refs_p): Do not give up immediately after same_types_for_tbaa_p returns -1 and continue looking for possible exact match; if matching types are arrays watch for partial overlaps. (indirect_ref_may_alias_decl_p): Watch for partial array overlaps. (indirect_refs_may_alias_p): Do type based disambiguation first; update comment. * gcc.dg/lto/alias-access-path-2.0.c: New testcase. From-SVN: r272036 --- gcc/ChangeLog | 10 +++ gcc/testsuite/ChangeLog | 4 + .../gcc.dg/lto/alias-access-path-2_0.c | 38 ++++++++++ gcc/tree-ssa-alias.c | 75 ++++++++++++++----- 4 files changed, 109 insertions(+), 18 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/lto/alias-access-path-2_0.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index add02bbb990..dbe6909a765 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,13 @@ +2019-06-07 Jan Hubicka + + * tree-ssa-alias.c (aliasing_component_refs_p): Do not give up + immediately after same_types_for_tbaa_p returns -1 and continue + looking for possible exact match; if matching types are arrays + watch for partial overlaps. + (indirect_ref_may_alias_decl_p): Watch for partial array overlaps. + (indirect_refs_may_alias_p): Do type based disambiguation first; + update comment. + 2019-06-07 Richard Sandiford * fwprop.c (propagate_rtx): Fix call to paradoxical_subreg_p. diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index d5f5cd469f0..9410686a9f7 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2019-06-07 Jan Hubicka + + * gcc.dg/lto/alias-access-path-2.0.c: New testcase. + 2019-06-07 Martin Liska PR tree-optimization/78902 diff --git a/gcc/testsuite/gcc.dg/lto/alias-access-path-2_0.c b/gcc/testsuite/gcc.dg/lto/alias-access-path-2_0.c new file mode 100644 index 00000000000..7a53a1a8328 --- /dev/null +++ b/gcc/testsuite/gcc.dg/lto/alias-access-path-2_0.c @@ -0,0 +1,38 @@ +/* { dg-lto-do run } */ +/* { dg-lto-options { { -O3 -flto -fno-early-inlining } } } */ + +/* In this test the access patch orracle (aliasing_component_refs_p) + can disambiguage array[0] from array[1] by base+offset but it needs to be + able to find the common type and not give up by not being able to compare + types earlier. */ + +typedef int (*fnptr) (); + +__attribute__ ((used)) +struct a +{ + void *array[2]; +} a, *aptr = &a; + +__attribute__ ((used)) +struct b +{ + struct a a; +} *bptr; + +static void +inline_me_late (int argc) +{ + if (argc == -1) + bptr->a.array[1] = bptr; +} + +int +main (int argc) +{ + aptr->array[0] = 0; + inline_me_late (argc); + if (!__builtin_constant_p (aptr->array[0] == 0)) + __builtin_abort (); + return 0; +} diff --git a/gcc/tree-ssa-alias.c b/gcc/tree-ssa-alias.c index 429288b6ca5..ebe05544bad 100644 --- a/gcc/tree-ssa-alias.c +++ b/gcc/tree-ssa-alias.c @@ -860,6 +860,7 @@ aliasing_component_refs_p (tree ref1, tree type1, type2; tree *refp; int same_p1 = 0, same_p2 = 0; + bool maybe_match = false; /* Choose bases and base types to search for. */ base1 = ref1; @@ -890,8 +891,14 @@ aliasing_component_refs_p (tree ref1, if (cmp == 0) { same_p2 = same_type_for_tbaa (TREE_TYPE (*refp), type1); - if (same_p2 != 0) + if (same_p2 == 1) break; + /* In case we can't decide whether types are same try to + continue looking for the exact match. + Remember however that we possibly saw a match + to bypass the access path continuations tests we do later. */ + if (same_p2 == -1) + maybe_match = true; } if (!handled_component_p (*refp)) break; @@ -901,6 +908,21 @@ aliasing_component_refs_p (tree ref1, { poly_int64 offadj, sztmp, msztmp; bool reverse; + + /* We assume that arrays can overlap by multiple of their elements + size as tested in gcc.dg/torture/alias-2.c. + This partial overlap happen only when both arrays are bases of + the access and not contained within another component ref. + To be safe we also assume partial overlap for VLAs. */ + if (TREE_CODE (TREE_TYPE (base1)) == ARRAY_TYPE + && (!TYPE_SIZE (TREE_TYPE (base1)) + || TREE_CODE (TYPE_SIZE (TREE_TYPE (base1))) != INTEGER_CST + || (*refp == base2 && !ref2_is_decl))) + { + ++alias_stats.aliasing_component_refs_p_may_alias; + return true; + } + get_ref_base_and_extent (*refp, &offadj, &sztmp, &msztmp, &reverse); offset2 -= offadj; get_ref_base_and_extent (base1, &offadj, &sztmp, &msztmp, &reverse); @@ -932,8 +954,10 @@ aliasing_component_refs_p (tree ref1, if (cmp == 0) { same_p1 = same_type_for_tbaa (TREE_TYPE (*refp), type2); - if (same_p1 != 0) + if (same_p1 == 1) break; + if (same_p1 == -1) + maybe_match = true; } if (!handled_component_p (*refp)) break; @@ -944,6 +968,15 @@ aliasing_component_refs_p (tree ref1, poly_int64 offadj, sztmp, msztmp; bool reverse; + if (TREE_CODE (TREE_TYPE (base2)) == ARRAY_TYPE + && (!TYPE_SIZE (TREE_TYPE (base2)) + || TREE_CODE (TYPE_SIZE (TREE_TYPE (base2))) != INTEGER_CST + || (*refp == base1 && !ref2_is_decl))) + { + ++alias_stats.aliasing_component_refs_p_may_alias; + return true; + } + get_ref_base_and_extent (*refp, &offadj, &sztmp, &msztmp, &reverse); offset1 -= offadj; get_ref_base_and_extent (base2, &offadj, &sztmp, &msztmp, &reverse); @@ -965,7 +998,7 @@ aliasing_component_refs_p (tree ref1, paths do not overlap and thus accesses alias only if one path can be continuation of another. If we was not able to decide about equivalence, we need to give up. */ - if (same_p1 == -1 || same_p2 == -1) + if (maybe_match) return true; /* If we have two type access paths B1.path1 and B2.path2 they may @@ -1350,10 +1383,17 @@ indirect_ref_may_alias_decl_p (tree ref1 ATTRIBUTE_UNUSED, tree base1, For MEM_REFs we require that the component-ref offset we computed is relative to the start of the type which we ensure by comparing rvalue and access type and disregarding the constant - pointer offset. */ + pointer offset. + + But avoid treating variable length arrays as "objects", instead assume they + can overlap by an exact multiple of their element size. + See gcc.dg/torture/alias-2.c. */ if ((TREE_CODE (base1) != TARGET_MEM_REF || (!TMR_INDEX (base1) && !TMR_INDEX2 (base1))) - && same_type_for_tbaa (TREE_TYPE (base1), TREE_TYPE (dbase2)) == 1) + && 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); if (ref1 && ref2 @@ -1446,6 +1486,16 @@ indirect_refs_may_alias_p (tree ref1 ATTRIBUTE_UNUSED, tree base1, || base2_alias_set == 0) return true; + /* Do type-based disambiguation. */ + if (base1_alias_set != base2_alias_set + && !alias_sets_conflict_p (base1_alias_set, base2_alias_set)) + return false; + + /* If either reference is view-converted, give up now. */ + if (same_type_for_tbaa (TREE_TYPE (base1), TREE_TYPE (ptrtype1)) != 1 + || same_type_for_tbaa (TREE_TYPE (base2), TREE_TYPE (ptrtype2)) != 1) + return true; + /* If both references are through the same type, they do not alias if the accesses do not overlap. This does extra disambiguation for mixed/pointer accesses but requires strict aliasing. */ @@ -1453,25 +1503,14 @@ indirect_refs_may_alias_p (tree ref1 ATTRIBUTE_UNUSED, tree base1, || (!TMR_INDEX (base1) && !TMR_INDEX2 (base1))) && (TREE_CODE (base2) != TARGET_MEM_REF || (!TMR_INDEX (base2) && !TMR_INDEX2 (base2))) - && same_type_for_tbaa (TREE_TYPE (base1), TREE_TYPE (ptrtype1)) == 1 - && same_type_for_tbaa (TREE_TYPE (base2), TREE_TYPE (ptrtype2)) == 1 && same_type_for_tbaa (TREE_TYPE (ptrtype1), TREE_TYPE (ptrtype2)) == 1 /* But avoid treating arrays as "objects", instead assume they - can overlap by an exact multiple of their element size. */ + 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); - /* Do type-based disambiguation. */ - if (base1_alias_set != base2_alias_set - && !alias_sets_conflict_p (base1_alias_set, base2_alias_set)) - return false; - - /* If either reference is view-converted, give up now. */ - if (same_type_for_tbaa (TREE_TYPE (base1), TREE_TYPE (ptrtype1)) != 1 - || same_type_for_tbaa (TREE_TYPE (base2), TREE_TYPE (ptrtype2)) != 1) - return true; - if (ref1 && ref2 && nonoverlapping_component_refs_p (ref1, ref2)) return false; -- 2.30.2