diff options
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 7 | ||||
-rw-r--r-- | gcc/tree-ssa-alias.c | 185 |
2 files changed, 135 insertions, 57 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index e7b9ab2..d0232f2 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +2019-05-20 Jan Hubicka <hubicka@ucw.cz> + + * tree-ssa-alias.c (compare_sizes): New function. + (sompare_type_sizes): New function + (aliasing_component_refs_p): Use it. + (indirect_ref_may_alias_decl_p): Likewise. + 2019-05-20 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE> * config/i386/sol2.h (CC1_SPEC): Reject -mx32. diff --git a/gcc/tree-ssa-alias.c b/gcc/tree-ssa-alias.c index 895c038..0fa413a 100644 --- a/gcc/tree-ssa-alias.c +++ b/gcc/tree-ssa-alias.c @@ -735,6 +735,48 @@ ao_ref_init_from_ptr_and_size (ao_ref *ref, tree ptr, tree size) ref->volatile_p = false; } +/* S1 and S2 are TYPE_SIZE or DECL_SIZE. Compare them: + Return -1 if S1 < S2 + Return 1 if S1 > S2 + Return 0 if equal or incomparable. */ + +static int +compare_sizes (tree s1, tree s2) +{ + if (!s1 || !s2) + return 0; + + poly_uint64 size1 = poly_int_tree_p (s1, &size1); + poly_uint64 size2 = poly_int_tree_p (s2, &size2); + + if (!poly_int_tree_p (s1, &size1) || !poly_int_tree_p (s2, &size2)) + return 0; + if (known_lt (size1, size2)) + return -1; + if (known_lt (size2, size1)) + return 1; + return 0; +} + +/* Compare TYPE1 and TYPE2 by its size. + Return -1 if size of TYPE1 < size of TYPE2 + Return 1 if size of TYPE1 > size of TYPE2 + Return 0 if types are of equal sizes or we can not compare them. */ + +static int +compare_type_sizes (tree type1, tree type2) +{ + /* Be conservative for arrays and vectors. We want to support partial + overlap on int[3] and int[3] as tested in gcc.dg/torture/alias-2.c. */ + while (TREE_CODE (type1) == ARRAY_TYPE + || TREE_CODE (type1) == VECTOR_TYPE) + type1 = TREE_TYPE (type1); + while (TREE_CODE (type2) == ARRAY_TYPE + || TREE_CODE (type2) == VECTOR_TYPE) + type2 = TREE_TYPE (type2); + return compare_sizes (TYPE_SIZE (type1), TYPE_SIZE (type2)); +} + /* Return 1 if TYPE1 and TYPE2 are to be considered equivalent for the purpose of TBAA. Return 0 if they are distinct and -1 if we cannot decide. */ @@ -803,7 +845,7 @@ aliasing_component_refs_p (tree ref1, tree base1, base2; tree type1, type2; tree *refp; - int same_p, same_p2; + int same_p1 = 0, same_p2 = 0; /* Choose bases and base types to search for. */ base1 = ref1; @@ -816,82 +858,114 @@ aliasing_component_refs_p (tree ref1, 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. */ - refp = &ref2; - while (handled_component_p (*refp) - && same_type_for_tbaa (TREE_TYPE (*refp), type1) == 0) - refp = &TREE_OPERAND (*refp, 0); - same_p = same_type_for_tbaa (TREE_TYPE (*refp), type1); - if (same_p == 1) + 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) { - poly_int64 offadj, sztmp, msztmp; - bool reverse; - get_ref_base_and_extent (*refp, &offadj, &sztmp, &msztmp, &reverse); - offset2 -= offadj; - get_ref_base_and_extent (base1, &offadj, &sztmp, &msztmp, &reverse); - offset1 -= offadj; - if (ranges_maybe_overlap_p (offset1, max_size1, offset2, max_size2)) + refp = &ref2; + while (true) { - ++alias_stats.aliasing_component_refs_p_may_alias; - return true; + /* 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) + break; + /* If types may be of same size, see if we can decide about their + equality. */ + if (cmp >= 0) + { + same_p2 = same_type_for_tbaa (TREE_TYPE (*refp), type1); + if (same_p2 != 0) + break; + } + if (!handled_component_p (*refp)) + break; + refp = &TREE_OPERAND (*refp, 0); } - else + if (same_p2 == 1) { - ++alias_stats.aliasing_component_refs_p_no_alias; - return false; + poly_int64 offadj, sztmp, msztmp; + bool reverse; + get_ref_base_and_extent (*refp, &offadj, &sztmp, &msztmp, &reverse); + offset2 -= offadj; + get_ref_base_and_extent (base1, &offadj, &sztmp, &msztmp, &reverse); + offset1 -= offadj; + if (ranges_maybe_overlap_p (offset1, max_size1, offset2, max_size2)) + { + ++alias_stats.aliasing_component_refs_p_may_alias; + return true; + } + else + { + ++alias_stats.aliasing_component_refs_p_no_alias; + return false; + } } } /* If we didn't find a common base, try the other way around. */ - refp = &ref1; - while (handled_component_p (*refp) - && same_type_for_tbaa (TREE_TYPE (*refp), type2) == 0) - refp = &TREE_OPERAND (*refp, 0); - same_p2 = same_type_for_tbaa (TREE_TYPE (*refp), type2); - if (same_p2 == 1) + if (cmp_outer <= 0) { - poly_int64 offadj, sztmp, msztmp; - bool reverse; - - get_ref_base_and_extent (*refp, &offadj, &sztmp, &msztmp, &reverse); - offset1 -= offadj; - get_ref_base_and_extent (base2, &offadj, &sztmp, &msztmp, &reverse); - offset2 -= offadj; - if (ranges_maybe_overlap_p (offset1, max_size1, offset2, max_size2)) + refp = &ref1; + while (true) { - ++alias_stats.aliasing_component_refs_p_may_alias; - return true; + int cmp = compare_type_sizes (type2, TREE_TYPE (*refp)); + if (cmp < 0) + break; + /* If types may be of same size, see if we can decide about their + equality. */ + if (cmp >= 0) + { + same_p1 = same_type_for_tbaa (TREE_TYPE (*refp), type2); + if (same_p1 != 0) + break; + } + if (!handled_component_p (*refp)) + break; + refp = &TREE_OPERAND (*refp, 0); } - else + if (same_p1 == 1) { - ++alias_stats.aliasing_component_refs_p_no_alias; - return false; + poly_int64 offadj, sztmp, msztmp; + bool reverse; + + get_ref_base_and_extent (*refp, &offadj, &sztmp, &msztmp, &reverse); + offset1 -= offadj; + get_ref_base_and_extent (base2, &offadj, &sztmp, &msztmp, &reverse); + offset2 -= offadj; + if (ranges_maybe_overlap_p (offset1, max_size1, offset2, max_size2)) + { + ++alias_stats.aliasing_component_refs_p_may_alias; + return true; + } + else + { + ++alias_stats.aliasing_component_refs_p_no_alias; + return false; + } } } - /* In the remaining test we assume that there is no overlapping type - at all. So if we are unsure, we need to give up. */ - if (same_p == -1 || same_p2 == -1) - { - ++alias_stats.aliasing_component_refs_p_may_alias; - return true; - } - /* If we have two type access paths B1.path1 and B2.path2 they may only alias if either B1 is in B2.path2 or B2 is in B1.path1. But we can still have a path that goes B1.path1...B2.path2 with a part that we do not see. So we can only disambiguate now if there is no B2 in the tail of path1 and no B1 on the tail of path2. */ - if (base1_alias_set == ref2_alias_set - || alias_set_subset_of (base1_alias_set, ref2_alias_set)) + if (compare_type_sizes (TREE_TYPE (ref2), type1) >= 0 + && (same_p2 == -1 + || base1_alias_set == ref2_alias_set + || alias_set_subset_of (base1_alias_set, ref2_alias_set))) { ++alias_stats.aliasing_component_refs_p_may_alias; return true; } /* If this is ptr vs. decl then we know there is no ptr ... decl path. */ if (!ref2_is_decl - && (base2_alias_set == ref1_alias_set + && compare_type_sizes (TREE_TYPE (ref1), type2) >= 0 + && (same_p1 == -1 + || base2_alias_set == ref1_alias_set || alias_set_subset_of (base2_alias_set, ref1_alias_set))) { ++alias_stats.aliasing_component_refs_p_may_alias; @@ -1221,16 +1295,13 @@ indirect_ref_may_alias_decl_p (tree ref1 ATTRIBUTE_UNUSED, tree base1, /* If the size of the access relevant for TBAA through the pointer is bigger than the size of the decl we can't possibly access the decl via that pointer. */ - if (DECL_SIZE (base2) && COMPLETE_TYPE_P (TREE_TYPE (ptrtype1)) - && poly_int_tree_p (DECL_SIZE (base2)) - && poly_int_tree_p (TYPE_SIZE (TREE_TYPE (ptrtype1))) - /* ??? This in turn may run afoul when a decl of type T which is + if (/* ??? This in turn may run afoul when a decl of type T which is a member of union type U is accessed through a pointer to type U and sizeof T is smaller than sizeof U. */ - && TREE_CODE (TREE_TYPE (ptrtype1)) != UNION_TYPE + TREE_CODE (TREE_TYPE (ptrtype1)) != UNION_TYPE && TREE_CODE (TREE_TYPE (ptrtype1)) != QUAL_UNION_TYPE - && known_lt (wi::to_poly_widest (DECL_SIZE (base2)), - wi::to_poly_widest (TYPE_SIZE (TREE_TYPE (ptrtype1))))) + && compare_sizes (DECL_SIZE (base2), + TYPE_SIZE (TREE_TYPE (ptrtype1))) < 0) return false; if (!ref2) |