aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog7
-rw-r--r--gcc/tree-ssa-alias.c185
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)