On Thu, 15 Aug 2019, Jan Hubicka wrote: > Hi, > here is updated version. > > > + /* We generally assume that both access paths starts by same sequence > > > + of refs. However if number of array refs is not in sync, try > > > + to recover and pop elts until number match. This helps the case > > > + where one access path starts by array and other by element. */ > > > > I think part of the confusion is that we're doing this in the outer > > while loop, so "starts" applies to all sub-paths we consider? > > > > Or only to the innermost? > > > > So - why's this inside the loop? Some actual access path pair > > examples in the comment would help. And definitely more testcases > > since the single one you add is too simplistic to need all this code ;) > > I have added a testcase. Basically we hope the chain of array refs to > end by same type and in that case we want to peel out the outermost. You > are right that it does not work always especially if the innermost > reference is array (which is rare). > > I suppose one can do type matching once actually have > same_type_for_tbaa_p working on array_ref. > > I have added testcase, if you would preffer to move the logic out of the > walking loop, I can do that. I can also just drop it and handle this > later. > > I put it into inner loop basically to increase chances that we > succesfully walk access paths of different types in situation > -fno-strict-aliasing is used and the type sequences are not fully > compatible. > > I plan to put some love into -fno-strict-aliasing incrementally. > > This patch adds testcase for the access paths of different lengths and > fixes other issues discussed. It is another testcase where fre1 seems to > give up and fre3 is needed. > > Before fre1 we get: > test (int i, int j) > { > int[10][10] * innerptr; > int[10][10][10] * barptr.0_1; > int[10][10][10] * barptr.1_2; > int _9; > > : > innerptr_4 = barptr; > barptr.0_1 = barptr; > (*barptr.0_1)[i_5(D)][2][j_6(D)] = 10; > (*innerptr_4)[3][j_6(D)] = 11; > barptr.1_2 = barptr; > _9 = (*barptr.1_2)[i_5(D)][2][j_6(D)]; > return _9; > > } > > that is optimized to: > test (int i, int j) > { > int[10][10] * innerptr; > int _9; > > : > innerptr_4 = barptr; > MEM[(int[10][10][10] *)innerptr_4][i_5(D)][2][j_6(D)] = 10; > (*innerptr_4)[3][j_6(D)] = 11; > _9 = MEM[(int[10][10][10] *)innerptr_4][i_5(D)][2][j_6(D)]; > return _9; > > } > > before fre3 we get: > test (int i, int j) > { > int[10][10] * innerptr; > int _7; > > [local count: 1073741824]: > innerptr_2 = barptr; > MEM[(int[10][10][10] *)innerptr_2][i_3(D)][2][j_4(D)] = 10; > (*innerptr_2)[3][j_4(D)] = 11; > _7 = MEM[(int[10][10][10] *)innerptr_2][i_3(D)][2][j_4(D)]; > return _7; > > } > and fre3 does: > test (int i, int j) > { > int[10][10] * innerptr; > > [local count: 1073741824]: > innerptr_2 = barptr; > MEM[(int[10][10][10] *)innerptr_2][i_3(D)][2][j_4(D)] = 10; > (*innerptr_2)[3][j_4(D)] = 11; > return 10; > > } This is OK. Thanks and sorry for the delay... Richard. > Honza > > * tree-ssa-alias.c (nonoverlapping_component_refs_since_match_p): > Rename to ... > (nonoverlapping_refs_since_match_p): ... this; handle also > ARRAY_REFs. > (alias_stats): Update stats. > (dump_alias_stats): Likewise. > (cheap_array_ref_low_bound): New function. > (aliasing_matching_component_refs_p): Add partial_overlap > argument; > pass it to nonoverlapping_refs_since_match_p. > (aliasing_component_refs_walk): Update call of > aliasing_matching_component_refs_p > (nonoverlapping_array_refs_p): New function. > (decl_refs_may_alias_p, indirect_ref_may_alias_decl_p, > indirect_refs_may_alias_p): Update calls of > nonoverlapping_refs_since_match_p. > * gcc.dg/tree-ssa/alias-access-path-10.c: New testcase. > > Index: testsuite/gcc.dg/tree-ssa/alias-access-path-10.c > =================================================================== > --- testsuite/gcc.dg/tree-ssa/alias-access-path-10.c (nonexistent) > +++ testsuite/gcc.dg/tree-ssa/alias-access-path-10.c (working copy) > @@ -0,0 +1,12 @@ > +/* { dg-do compile } */ > +/* { dg-options "-O2 -fdump-tree-fre1" } */ > + > +struct a {int array[3];} a[10]; > +int > +test(int i,int j) > +{ > + a[i].array[1]=123; > + a[j].array[2]=2; > + return a[i].array[1]; > +} > +/* { dg-final { scan-tree-dump-times "return 123" 1 "fre1"} } */ > Index: testsuite/gcc.dg/tree-ssa/alias-access-path-11.c > =================================================================== > --- testsuite/gcc.dg/tree-ssa/alias-access-path-11.c (nonexistent) > +++ testsuite/gcc.dg/tree-ssa/alias-access-path-11.c (working copy) > @@ -0,0 +1,15 @@ > +/* { dg-do compile } */ > +/* { dg-options "-O2 -fno-strict-aliasing -fdump-tree-fre3" } */ > +typedef int outerarray[10][10][10]; > +typedef int innerarray[10][10]; > +outerarray *barptr; > + > +int > +test(int i,int j) > +{ > + innerarray *innerptr = (innerarray *)barptr; > + (*barptr)[i][2][j]=10;; > + (*innerptr)[3][j]=11; > + return (*barptr)[i][2][j]; > +} > +/* { dg-final { scan-tree-dump-times "return 10" 1 "fre3"} } */ > Index: tree-ssa-alias.c > =================================================================== > --- tree-ssa-alias.c (revision 274527) > +++ tree-ssa-alias.c (working copy) > @@ -87,7 +87,7 @@ along with GCC; see the file COPYING3. > this file. Low-level disambiguators dealing with points-to > information are in tree-ssa-structalias.c. */ > > -static int nonoverlapping_component_refs_since_match_p (tree, tree, tree, tree); > +static int nonoverlapping_refs_since_match_p (tree, tree, tree, tree, bool); > static bool nonoverlapping_component_refs_p (const_tree, const_tree); > > /* Query statistics for the different low-level disambiguators. > @@ -104,9 +104,9 @@ static struct { > unsigned HOST_WIDE_INT aliasing_component_refs_p_no_alias; > unsigned HOST_WIDE_INT nonoverlapping_component_refs_p_may_alias; > unsigned HOST_WIDE_INT nonoverlapping_component_refs_p_no_alias; > - unsigned HOST_WIDE_INT nonoverlapping_component_refs_since_match_p_may_alias; > - unsigned HOST_WIDE_INT nonoverlapping_component_refs_since_match_p_must_overlap; > - unsigned HOST_WIDE_INT nonoverlapping_component_refs_since_match_p_no_alias; > + unsigned HOST_WIDE_INT nonoverlapping_refs_since_match_p_may_alias; > + unsigned HOST_WIDE_INT nonoverlapping_refs_since_match_p_must_overlap; > + unsigned HOST_WIDE_INT nonoverlapping_refs_since_match_p_no_alias; > } alias_stats; > > void > @@ -137,15 +137,15 @@ dump_alias_stats (FILE *s) > alias_stats.nonoverlapping_component_refs_p_no_alias, > alias_stats.nonoverlapping_component_refs_p_no_alias > + alias_stats.nonoverlapping_component_refs_p_may_alias); > - fprintf (s, " nonoverlapping_component_refs_since_match_p: " > + fprintf (s, " nonoverlapping_refs_since_match_p: " > HOST_WIDE_INT_PRINT_DEC" disambiguations, " > HOST_WIDE_INT_PRINT_DEC" must overlaps, " > HOST_WIDE_INT_PRINT_DEC" queries\n", > - alias_stats.nonoverlapping_component_refs_since_match_p_no_alias, > - alias_stats.nonoverlapping_component_refs_since_match_p_must_overlap, > - alias_stats.nonoverlapping_component_refs_since_match_p_no_alias > - + alias_stats.nonoverlapping_component_refs_since_match_p_may_alias > - + alias_stats.nonoverlapping_component_refs_since_match_p_must_overlap); > + alias_stats.nonoverlapping_refs_since_match_p_no_alias, > + alias_stats.nonoverlapping_refs_since_match_p_must_overlap, > + alias_stats.nonoverlapping_refs_since_match_p_no_alias > + + alias_stats.nonoverlapping_refs_since_match_p_may_alias > + + alias_stats.nonoverlapping_refs_since_match_p_must_overlap); > fprintf (s, " aliasing_component_refs_p: " > HOST_WIDE_INT_PRINT_DEC" disambiguations, " > HOST_WIDE_INT_PRINT_DEC" queries\n", > @@ -856,7 +856,8 @@ type_has_components_p (tree type) > > /* MATCH1 and MATCH2 which are part of access path of REF1 and REF2 > respectively are either pointing to same address or are completely > - disjoint. > + disjoint. If PARITAL_OVERLAP is true, assume that outermost arrays may > + just partly overlap. > > Try to disambiguate using the access path starting from the match > and return false if there is no conflict. > @@ -867,24 +868,27 @@ static bool > aliasing_matching_component_refs_p (tree match1, tree ref1, > poly_int64 offset1, poly_int64 max_size1, > tree match2, tree ref2, > - poly_int64 offset2, poly_int64 max_size2) > + poly_int64 offset2, poly_int64 max_size2, > + bool partial_overlap) > { > poly_int64 offadj, sztmp, msztmp; > bool reverse; > > - > - get_ref_base_and_extent (match2, &offadj, &sztmp, &msztmp, &reverse); > - offset2 -= offadj; > - get_ref_base_and_extent (match1, &offadj, &sztmp, &msztmp, &reverse); > - offset1 -= offadj; > - if (!ranges_maybe_overlap_p (offset1, max_size1, offset2, max_size2)) > + if (!partial_overlap) > { > - ++alias_stats.aliasing_component_refs_p_no_alias; > - return false; > + get_ref_base_and_extent (match2, &offadj, &sztmp, &msztmp, &reverse); > + offset2 -= offadj; > + get_ref_base_and_extent (match1, &offadj, &sztmp, &msztmp, &reverse); > + offset1 -= offadj; > + if (!ranges_maybe_overlap_p (offset1, max_size1, offset2, max_size2)) > + { > + ++alias_stats.aliasing_component_refs_p_no_alias; > + return false; > + } > } > > - int cmp = nonoverlapping_component_refs_since_match_p (match1, ref1, > - match2, ref2); > + int cmp = nonoverlapping_refs_since_match_p (match1, ref1, match2, ref2, > + partial_overlap); > if (cmp == 1 > || (cmp == -1 && nonoverlapping_component_refs_p (ref1, ref2))) > { > @@ -964,6 +968,8 @@ aliasing_component_refs_walk (tree ref1, > } > if (same_p == 1) > { > + bool partial_overlap = false; > + > /* 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 > @@ -973,15 +979,18 @@ aliasing_component_refs_walk (tree ref1, > && (!TYPE_SIZE (TREE_TYPE (base1)) > || TREE_CODE (TYPE_SIZE (TREE_TYPE (base1))) != INTEGER_CST > || ref == base2)) > - /* Setting maybe_match to true triggers > - nonoverlapping_component_refs_p test later that still may do > - useful disambiguation. */ > - *maybe_match = true; > - else > - return aliasing_matching_component_refs_p (base1, ref1, > - offset1, max_size1, > - ref, ref2, > - offset2, max_size2); > + { > + /* Setting maybe_match to true triggers > + nonoverlapping_component_refs_p test later that still may do > + useful disambiguation. */ > + *maybe_match = true; > + partial_overlap = true; > + } > + return aliasing_matching_component_refs_p (base1, ref1, > + offset1, max_size1, > + ref, ref2, > + offset2, max_size2, > + partial_overlap); > } > return -1; > } > @@ -1225,10 +1234,98 @@ nonoverlapping_component_refs_p_1 (const > return -1; > } > > +/* Return low bound of array. Do not produce new trees > + and thus do not care about particular type of integer constant > + and placeholder exprs. */ > + > +static tree > +cheap_array_ref_low_bound (tree ref) > +{ > + tree domain_type = TYPE_DOMAIN (TREE_TYPE (TREE_OPERAND (ref, 0))); > + > + /* Avoid expensive array_ref_low_bound. > + low bound is either stored in operand2, or it is TYPE_MIN_VALUE of domain > + type or it is zero. */ > + if (TREE_OPERAND (ref, 2)) > + return TREE_OPERAND (ref, 2); > + else if (domain_type && TYPE_MIN_VALUE (domain_type)) > + return TYPE_MIN_VALUE (domain_type); > + else > + return integer_zero_node; > +} > + > +/* REF1 and REF2 are ARRAY_REFs with either same base address or which are > + completely disjoint. > + > + Return 1 if the refs are non-overlapping. > + Return 0 if they are possibly overlapping but if so the overlap again > + starts on the same address. > + Return -1 otherwise. */ > + > +int > +nonoverlapping_array_refs_p (tree ref1, tree ref2) > +{ > + tree index1 = TREE_OPERAND (ref1, 1); > + tree index2 = TREE_OPERAND (ref2, 1); > + tree low_bound1 = cheap_array_ref_low_bound(ref1); > + tree low_bound2 = cheap_array_ref_low_bound(ref2); > + > + /* Handle zero offsets first: we do not need to match type size in this > + case. */ > + if (operand_equal_p (index1, low_bound1, 0) > + && operand_equal_p (index2, low_bound2, 0)) > + return 0; > + > + /* If type sizes are different, give up. > + > + Avoid expensive array_ref_element_size. > + If operand 3 is present it denotes size in the alignmnet units. > + Otherwise size is TYPE_SIZE of the element type. > + Handle only common cases where types are of the same "kind". */ > + if ((TREE_OPERAND (ref1, 3) == NULL) != (TREE_OPERAND (ref2, 3) == NULL)) > + return -1; > + > + tree elmt_type1 = TREE_TYPE (TREE_TYPE (TREE_OPERAND (ref1, 0))); > + tree elmt_type2 = TREE_TYPE (TREE_TYPE (TREE_OPERAND (ref2, 0))); > + > + if (TREE_OPERAND (ref1, 3)) > + { > + if (TYPE_ALIGN (elmt_type1) != TYPE_ALIGN (elmt_type2) > + || !operand_equal_p (TREE_OPERAND (ref1, 3), > + TREE_OPERAND (ref2, 3), 0)) > + return -1; > + } > + else > + { > + if (!operand_equal_p (TYPE_SIZE_UNIT (elmt_type1), > + TYPE_SIZE_UNIT (elmt_type2), 0)) > + return -1; > + } > + > + /* Since we know that type sizes are the same, there is no need to return > + -1 after this point. Partial overlap can not be introduced. */ > + > + /* We may need to fold trees in this case. > + TODO: Handle integer constant case at least. */ > + if (!operand_equal_p (low_bound1, low_bound2, 0)) > + return 0; > + > + if (TREE_CODE (index1) == INTEGER_CST && TREE_CODE (index2) == INTEGER_CST) > + { > + if (tree_int_cst_equal (index1, index2)) > + return 0; > + return 1; > + } > + /* TODO: We can use VRP to further disambiguate here. */ > + return 0; > +} > + > /* Try to disambiguate REF1 and REF2 under the assumption that MATCH1 and > MATCH2 either point to the same address or are disjoint. > MATCH1 and MATCH2 are assumed to be ref in the access path of REF1 and REF2 > respectively or NULL in the case we established equivalence of bases. > + If PARTIAL_OVERLAP is true assume that the toplevel arrays may actually > + overlap by exact multiply of their element size. > > This test works by matching the initial segment of the access path > and does not rely on TBAA thus is safe for !flag_strict_aliasing if > @@ -1247,8 +1344,9 @@ nonoverlapping_component_refs_p_1 (const > oracles. */ > > static int > -nonoverlapping_component_refs_since_match_p (tree match1, tree ref1, > - tree match2, tree ref2) > +nonoverlapping_refs_since_match_p (tree match1, tree ref1, > + tree match2, tree ref2, > + bool partial_overlap) > { > /* Early return if there are no references to match, we do not need > to walk the access paths. > @@ -1301,7 +1399,7 @@ nonoverlapping_component_refs_since_matc > && !tree_int_cst_equal (TREE_OPERAND (ref1, 1), > TREE_OPERAND (ref2, 1)))) > { > - ++alias_stats.nonoverlapping_component_refs_since_match_p_may_alias; > + ++alias_stats.nonoverlapping_refs_since_match_p_may_alias; > return -1; > } > > @@ -1318,18 +1416,78 @@ nonoverlapping_component_refs_since_matc > case the return value will precisely be false. */ > while (true) > { > - bool seen_noncomponent_ref_p = false; > + /* Track if we seen unmatched ref with non-zero offset. In this case > + we must look for partial overlaps. */ > + bool seen_unmatched_ref_p = false; > + > + /* First match ARRAY_REFs an try to disambiguate. */ > + if (!component_refs1.is_empty () > + && !component_refs2.is_empty ()) > + { > + unsigned int narray_refs1=0, narray_refs2=0; > + > + /* We generally assume that both access paths starts by same sequence > + of refs. However if number of array refs is not in sync, try > + to recover and pop elts until number match. This helps the case > + where one access path starts by array and other by element. */ > + for (narray_refs1 = 0; narray_refs1 < component_refs1.length (); > + narray_refs1++) > + if (TREE_CODE (component_refs1 [component_refs1.length() > + - 1 - narray_refs1]) != ARRAY_REF) > + break; > + > + for (narray_refs2 = 0; narray_refs2 < component_refs2.length (); > + narray_refs2++) > + if (TREE_CODE (component_refs2 [component_refs2.length() > + - 1 - narray_refs2]) != ARRAY_REF) > + break; > + for (; narray_refs1 > narray_refs2; narray_refs1--) > + { > + ref1 = component_refs1.pop (); > + /* Track whether we possibly introduced partial overlap assuming > + that innermost type sizes does not match. This only can > + happen if the offset introduced by the ARRAY_REF > + is non-zero. */ > + if (!operand_equal_p (TREE_OPERAND (ref1, 1), > + cheap_array_ref_low_bound (ref1), 0)) > + seen_unmatched_ref_p = true; > + } > + for (; narray_refs2 > narray_refs1; narray_refs2--) > + { > + ref2 = component_refs2.pop (); > + if (!operand_equal_p (TREE_OPERAND (ref2, 1), > + cheap_array_ref_low_bound (ref2), 0)) > + seen_unmatched_ref_p = true; > + } > + /* Try to disambiguate matched arrays. */ > + for (unsigned int i = 0; i < narray_refs1; i++) > + { > + int cmp = nonoverlapping_array_refs_p (component_refs1.pop (), > + component_refs2.pop ()); > + if (cmp == 1 && !partial_overlap) > + { > + ++alias_stats > + .nonoverlapping_refs_since_match_p_no_alias; > + return 1; > + } > + partial_overlap = false; > + if (cmp == -1) > + seen_unmatched_ref_p = true; > + } > + } > + > + /* Next look for component_refs. */ > do > { > if (component_refs1.is_empty ()) > { > ++alias_stats > - .nonoverlapping_component_refs_since_match_p_must_overlap; > + .nonoverlapping_refs_since_match_p_must_overlap; > return 0; > } > ref1 = component_refs1.pop (); > if (TREE_CODE (ref1) != COMPONENT_REF) > - seen_noncomponent_ref_p = true; > + seen_unmatched_ref_p = true; > } > while (!RECORD_OR_UNION_TYPE_P (TREE_TYPE (TREE_OPERAND (ref1, 0)))); > > @@ -1338,12 +1496,12 @@ nonoverlapping_component_refs_since_matc > if (component_refs2.is_empty ()) > { > ++alias_stats > - .nonoverlapping_component_refs_since_match_p_must_overlap; > + .nonoverlapping_refs_since_match_p_must_overlap; > return 0; > } > ref2 = component_refs2.pop (); > if (TREE_CODE (ref2) != COMPONENT_REF) > - seen_noncomponent_ref_p = true; > + seen_unmatched_ref_p = true; > } > while (!RECORD_OR_UNION_TYPE_P (TREE_TYPE (TREE_OPERAND (ref2, 0)))); > > @@ -1361,13 +1519,15 @@ nonoverlapping_component_refs_since_matc > tree type1 = DECL_CONTEXT (field1); > tree type2 = DECL_CONTEXT (field2); > > + partial_overlap = false; > + > /* If we skipped array refs on type of different sizes, we can > no longer be sure that there are not partial overlaps. */ > - if (seen_noncomponent_ref_p > + if (seen_unmatched_ref_p > && !operand_equal_p (TYPE_SIZE (type1), TYPE_SIZE (type2), 0)) > { > ++alias_stats > - .nonoverlapping_component_refs_since_match_p_may_alias; > + .nonoverlapping_refs_since_match_p_may_alias; > return -1; > } > > @@ -1375,18 +1535,18 @@ nonoverlapping_component_refs_since_matc > if (cmp == -1) > { > ++alias_stats > - .nonoverlapping_component_refs_since_match_p_may_alias; > + .nonoverlapping_refs_since_match_p_may_alias; > return -1; > } > else if (cmp == 1) > { > ++alias_stats > - .nonoverlapping_component_refs_since_match_p_no_alias; > + .nonoverlapping_refs_since_match_p_no_alias; > return 1; > } > } > > - ++alias_stats.nonoverlapping_component_refs_since_match_p_must_overlap; > + ++alias_stats.nonoverlapping_refs_since_match_p_must_overlap; > return 0; > } > > @@ -1583,8 +1743,7 @@ decl_refs_may_alias_p (tree ref1, tree b > so we disambiguate component references manually. */ > if (ref1 && ref2 > && handled_component_p (ref1) && handled_component_p (ref2) > - && nonoverlapping_component_refs_since_match_p (NULL, ref1, > - NULL, ref2) == 1) > + && nonoverlapping_refs_since_match_p (NULL, ref1, NULL, ref2, false) == 1) > return false; > > return true; > @@ -1709,19 +1868,22 @@ indirect_ref_may_alias_decl_p (tree ref1 > || (!TMR_INDEX (base1) && !TMR_INDEX2 (base1))) > && (TREE_CODE (dbase2) != TARGET_MEM_REF > || (!TMR_INDEX (dbase2) && !TMR_INDEX2 (dbase2)))) > - && 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))) > + && same_type_for_tbaa (TREE_TYPE (base1), TREE_TYPE (dbase2)) == 1) > { > - if (!ranges_maybe_overlap_p (doffset1, max_size1, doffset2, max_size2)) > + bool partial_overlap = (TREE_CODE (TREE_TYPE (base1)) == ARRAY_TYPE > + && (TYPE_SIZE (TREE_TYPE (base1)) > + && TREE_CODE (TYPE_SIZE (TREE_TYPE (base1))) > + != INTEGER_CST)); > + if (!partial_overlap > + && !ranges_maybe_overlap_p (doffset1, max_size1, doffset2, max_size2)) > return false; > if (!ref1 || !ref2 > /* If there is must alias, there is no use disambiguating further. */ > - || (known_eq (size1, max_size1) && known_eq (size2, max_size2))) > + || (!partial_overlap > + && known_eq (size1, max_size1) && known_eq (size2, max_size2))) > return true; > - int res = nonoverlapping_component_refs_since_match_p (base1, ref1, > - base2, ref2); > + int res = nonoverlapping_refs_since_match_p (base1, ref1, base2, ref2, > + partial_overlap); > if (res == -1) > return !nonoverlapping_component_refs_p (ref1, ref2); > return !res; > @@ -1805,8 +1967,8 @@ indirect_refs_may_alias_p (tree ref1 ATT > return true; > if (ref1 && ref2) > { > - int res = nonoverlapping_component_refs_since_match_p (NULL, ref1, > - NULL, ref2); > + int res = nonoverlapping_refs_since_match_p (NULL, ref1, NULL, ref2, > + false); > if (res != -1) > return !res; > } > @@ -1844,19 +2006,22 @@ indirect_refs_may_alias_p (tree ref1 ATT > && (TREE_CODE (base2) != TARGET_MEM_REF > || (!TMR_INDEX (base2) && !TMR_INDEX2 (base2))) > && same_type_for_tbaa (TREE_TYPE (ptrtype1), > - TREE_TYPE (ptrtype2)) == 1 > + 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) > - { > - if (!ranges_maybe_overlap_p (offset1, max_size1, offset2, max_size2)) > + bool partial_overlap = TREE_CODE (TREE_TYPE (ptrtype1)) == ARRAY_TYPE; > + > + if (!partial_overlap > + && !ranges_maybe_overlap_p (offset1, max_size1, offset2, max_size2)) > return false; > if (!ref1 || !ref2 > - || (known_eq (size1, max_size1) && known_eq (size2, max_size2))) > + || (!partial_overlap > + && known_eq (size1, max_size1) && known_eq (size2, max_size2))) > return true; > - int res = nonoverlapping_component_refs_since_match_p (base1, ref1, > - base2, ref2); > + int res = nonoverlapping_refs_since_match_p (base1, ref1, base2, ref2, > + partial_overlap); > if (res == -1) > return !nonoverlapping_component_refs_p (ref1, ref2); > return !res; > -- Richard Biener SUSE Software Solutions Germany GmbH, Maxfeldstrasse 5, 90409 Nuernberg, Germany; GF: Felix Imendörffer; HRB 247165 (AG München)