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
This commit is contained in:
parent
6c202d9dc6
commit
06dd9b3d4e
|
@ -1,3 +1,13 @@
|
||||||
|
2019-06-07 Jan Hubicka <hubicka@ucw.cz>
|
||||||
|
|
||||||
|
* 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 <richard.sandiford@arm.com>
|
2019-06-07 Richard Sandiford <richard.sandiford@arm.com>
|
||||||
|
|
||||||
* fwprop.c (propagate_rtx): Fix call to paradoxical_subreg_p.
|
* fwprop.c (propagate_rtx): Fix call to paradoxical_subreg_p.
|
||||||
|
|
|
@ -1,3 +1,7 @@
|
||||||
|
2019-06-07 Jan Hubicka <hubicka@ucw.cz>
|
||||||
|
|
||||||
|
* gcc.dg/lto/alias-access-path-2.0.c: New testcase.
|
||||||
|
|
||||||
2019-06-07 Martin Liska <mliska@suse.cz>
|
2019-06-07 Martin Liska <mliska@suse.cz>
|
||||||
|
|
||||||
PR tree-optimization/78902
|
PR tree-optimization/78902
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
|
@ -860,6 +860,7 @@ aliasing_component_refs_p (tree ref1,
|
||||||
tree type1, type2;
|
tree type1, type2;
|
||||||
tree *refp;
|
tree *refp;
|
||||||
int same_p1 = 0, same_p2 = 0;
|
int same_p1 = 0, same_p2 = 0;
|
||||||
|
bool maybe_match = false;
|
||||||
|
|
||||||
/* Choose bases and base types to search for. */
|
/* Choose bases and base types to search for. */
|
||||||
base1 = ref1;
|
base1 = ref1;
|
||||||
|
@ -890,8 +891,14 @@ aliasing_component_refs_p (tree ref1,
|
||||||
if (cmp == 0)
|
if (cmp == 0)
|
||||||
{
|
{
|
||||||
same_p2 = same_type_for_tbaa (TREE_TYPE (*refp), type1);
|
same_p2 = same_type_for_tbaa (TREE_TYPE (*refp), type1);
|
||||||
if (same_p2 != 0)
|
if (same_p2 == 1)
|
||||||
break;
|
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))
|
if (!handled_component_p (*refp))
|
||||||
break;
|
break;
|
||||||
|
@ -901,6 +908,21 @@ aliasing_component_refs_p (tree ref1,
|
||||||
{
|
{
|
||||||
poly_int64 offadj, sztmp, msztmp;
|
poly_int64 offadj, sztmp, msztmp;
|
||||||
bool reverse;
|
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);
|
get_ref_base_and_extent (*refp, &offadj, &sztmp, &msztmp, &reverse);
|
||||||
offset2 -= offadj;
|
offset2 -= offadj;
|
||||||
get_ref_base_and_extent (base1, &offadj, &sztmp, &msztmp, &reverse);
|
get_ref_base_and_extent (base1, &offadj, &sztmp, &msztmp, &reverse);
|
||||||
|
@ -932,8 +954,10 @@ aliasing_component_refs_p (tree ref1,
|
||||||
if (cmp == 0)
|
if (cmp == 0)
|
||||||
{
|
{
|
||||||
same_p1 = same_type_for_tbaa (TREE_TYPE (*refp), type2);
|
same_p1 = same_type_for_tbaa (TREE_TYPE (*refp), type2);
|
||||||
if (same_p1 != 0)
|
if (same_p1 == 1)
|
||||||
break;
|
break;
|
||||||
|
if (same_p1 == -1)
|
||||||
|
maybe_match = true;
|
||||||
}
|
}
|
||||||
if (!handled_component_p (*refp))
|
if (!handled_component_p (*refp))
|
||||||
break;
|
break;
|
||||||
|
@ -944,6 +968,15 @@ aliasing_component_refs_p (tree ref1,
|
||||||
poly_int64 offadj, sztmp, msztmp;
|
poly_int64 offadj, sztmp, msztmp;
|
||||||
bool reverse;
|
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);
|
get_ref_base_and_extent (*refp, &offadj, &sztmp, &msztmp, &reverse);
|
||||||
offset1 -= offadj;
|
offset1 -= offadj;
|
||||||
get_ref_base_and_extent (base2, &offadj, &sztmp, &msztmp, &reverse);
|
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
|
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,
|
continuation of another. If we was not able to decide about equivalence,
|
||||||
we need to give up. */
|
we need to give up. */
|
||||||
if (same_p1 == -1 || same_p2 == -1)
|
if (maybe_match)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
/* If we have two type access paths B1.path1 and B2.path2 they may
|
/* 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
|
For MEM_REFs we require that the component-ref offset we computed
|
||||||
is relative to the start of the type which we ensure by
|
is relative to the start of the type which we ensure by
|
||||||
comparing rvalue and access type and disregarding the constant
|
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
|
if ((TREE_CODE (base1) != TARGET_MEM_REF
|
||||||
|| (!TMR_INDEX (base1) && !TMR_INDEX2 (base1)))
|
|| (!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);
|
return ranges_maybe_overlap_p (doffset1, max_size1, doffset2, max_size2);
|
||||||
|
|
||||||
if (ref1 && ref2
|
if (ref1 && ref2
|
||||||
|
@ -1446,22 +1486,6 @@ indirect_refs_may_alias_p (tree ref1 ATTRIBUTE_UNUSED, tree base1,
|
||||||
|| base2_alias_set == 0)
|
|| base2_alias_set == 0)
|
||||||
return true;
|
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. */
|
|
||||||
if ((TREE_CODE (base1) != TARGET_MEM_REF
|
|
||||||
|| (!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. */
|
|
||||||
&& TREE_CODE (TREE_TYPE (ptrtype1)) != ARRAY_TYPE)
|
|
||||||
return ranges_maybe_overlap_p (offset1, max_size1, offset2, max_size2);
|
|
||||||
|
|
||||||
/* Do type-based disambiguation. */
|
/* Do type-based disambiguation. */
|
||||||
if (base1_alias_set != base2_alias_set
|
if (base1_alias_set != base2_alias_set
|
||||||
&& !alias_sets_conflict_p (base1_alias_set, base2_alias_set))
|
&& !alias_sets_conflict_p (base1_alias_set, base2_alias_set))
|
||||||
|
@ -1472,6 +1496,21 @@ indirect_refs_may_alias_p (tree ref1 ATTRIBUTE_UNUSED, tree base1,
|
||||||
|| same_type_for_tbaa (TREE_TYPE (base2), TREE_TYPE (ptrtype2)) != 1)
|
|| same_type_for_tbaa (TREE_TYPE (base2), TREE_TYPE (ptrtype2)) != 1)
|
||||||
return true;
|
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. */
|
||||||
|
if ((TREE_CODE (base1) != TARGET_MEM_REF
|
||||||
|
|| (!TMR_INDEX (base1) && !TMR_INDEX2 (base1)))
|
||||||
|
&& (TREE_CODE (base2) != TARGET_MEM_REF
|
||||||
|
|| (!TMR_INDEX (base2) && !TMR_INDEX2 (base2)))
|
||||||
|
&& 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.
|
||||||
|
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);
|
||||||
|
|
||||||
if (ref1 && ref2
|
if (ref1 && ref2
|
||||||
&& nonoverlapping_component_refs_p (ref1, ref2))
|
&& nonoverlapping_component_refs_p (ref1, ref2))
|
||||||
return false;
|
return false;
|
||||||
|
|
Loading…
Reference in New Issue