On Mon, 18 Jan 2021, Richard Sandiford wrote: > Jan Hubicka <hubi...@ucw.cz> writes: > >> >> > >> >> Well, in tree-ssa code we do assume these to be either disjoint objects > >> >> or equal (in decl_refs_may_alias_p that continues in case > >> >> compare_base_decls is -1). I am not sure if we win much by threating > >> >> them differently on RTL level. I would preffer staying consistent here. > >> > >> Yeah, I see your point. My concern here was that the fallback case > >> applies to SYMBOL_REFs without decls, which might not have been visible > >> at the tree-ssa level. E.g. they might be ABI-defined symbols that have > >> no known relation to source-level constructs. > >> > >> E.g. the small-data base symbol _gp on MIPS points at a fixed offset > >> from the start of the small-data area (0x7ff0 IIRC). If the target > >> generated rtl code that used _gp directly, we could wrongly assume > >> that _gp+X can't alias BASE+Y when X != Y, even though the real test > >> for small-data BASEs would be whether X + 0x7ff0 != Y. > >> > >> I don't think that could occur in tree-ssa. No valid C code would > >> be able to refer directly to _gp in this way. > >> > >> On the other hand, I don't have a specific example of where this does > >> go wrong, it's just a feeling that it might. I can drop it if you > >> think that's better. > > > > I would lean towards not disabling optimization when we have no good > > reason for that - we already did it bit too many times in aliasing code > > and it is hard to figure out what optimizations are missed purposefully > > and what are missed just as omission. > > > > We already comitted to a very conservative assumption that every > > external symbol can be alias of another. I think we should have > > originally required units that reffers to same memory location via > > different symbols to declare it explicitly (i.e. make external alias to > > external symbol), but we do not even allow external aliases (symtab > > supports that though) and also it may depend on use of the module what > > symbols are aliased. > > > > We also decided to disable TBAA for direct accesses to decls to allow > > type punning using unions. > > > > This keeps the offset+range check to be only means of disambiguation. > > While for modern programs global arrays are not common, for Fortran > > stuff they are, so I would preffer to not cripple them even more. > > (I am not sure how often the arrays are external though) > > OK, the version below drops the new -2 return value and tries to > clarify the comments in compare_base_symbol_refs. > > Lightly tested on aarch64-linux-gnu so far. Does it look OK if > full tests pass?
OK from my side. Richard. > Thanks, > Richard > > ---- > > memrefs_conflict_p assumes that: > > [XB + XO, XB + XO + XS) > > does not alias > > [YB + YO, YB + YO + YS) > > whenever: > > [XO, XO + XS) > > does not intersect > > [YO, YO + YS) > > In other words, the accesses can alias only if XB == YB at runtime. > > However, this doesn't cope correctly with section anchors. > For example, if XB is an anchor symbol and YB is at offset > XO from the anchor, then: > > [XB + XO, XB + XO + XS) > > overlaps > > [YB, YB + YS) > > whatever the value of XO is. In other words, when doing the > alias check for two symbols whose local definitions are in > the same block, we should apply the known difference between > their block offsets to the intersection test above. > > gcc/ > PR rtl-optimization/92294 > * alias.c (compare_base_symbol_refs): Take an extra parameter > and add the distance between two symbols to it. Enshrine in > comments that -1 means "either 0 or 1, but we can't tell > which at compile time". > (memrefs_conflict_p): Update call accordingly. > (rtx_equal_for_memref_p): Likewise. Take the distance between symbols > into account. > --- > gcc/alias.c | 47 +++++++++++++++++++++++++++++++---------------- > 1 file changed, 31 insertions(+), 16 deletions(-) > > diff --git a/gcc/alias.c b/gcc/alias.c > index 8d3575e4e27..69e1eb89ac6 100644 > --- a/gcc/alias.c > +++ b/gcc/alias.c > @@ -159,7 +159,8 @@ static tree decl_for_component_ref (tree); > static int write_dependence_p (const_rtx, > const_rtx, machine_mode, rtx, > bool, bool, bool); > -static int compare_base_symbol_refs (const_rtx, const_rtx); > +static int compare_base_symbol_refs (const_rtx, const_rtx, > + HOST_WIDE_INT * = NULL); > > static void memory_modified_1 (rtx, const_rtx, void *); > > @@ -1837,7 +1838,11 @@ rtx_equal_for_memref_p (const_rtx x, const_rtx y) > return label_ref_label (x) == label_ref_label (y); > > case SYMBOL_REF: > - return compare_base_symbol_refs (x, y) == 1; > + { > + HOST_WIDE_INT distance = 0; > + return (compare_base_symbol_refs (x, y, &distance) == 1 > + && distance == 0); > + } > > case ENTRY_VALUE: > /* This is magic, don't go through canonicalization et al. */ > @@ -2172,10 +2177,20 @@ compare_base_decls (tree base1, tree base2) > return ret; > } > > -/* Same as compare_base_decls but for SYMBOL_REF. */ > +/* Compare SYMBOL_REFs X_BASE and Y_BASE. > + > + - Return 1 if Y_BASE - X_BASE is constant, adding that constant > + to *DISTANCE if DISTANCE is nonnull. > + > + - Return 0 if no accesses based on X_BASE can alias Y_BASE. > + > + - Return -1 if one of the two results applies, but we can't tell > + which at compile time. Update DISTANCE in the same way as > + for a return value of 1, for the case in which that holds. */ > > static int > -compare_base_symbol_refs (const_rtx x_base, const_rtx y_base) > +compare_base_symbol_refs (const_rtx x_base, const_rtx y_base, > + HOST_WIDE_INT *distance) > { > tree x_decl = SYMBOL_REF_DECL (x_base); > tree y_decl = SYMBOL_REF_DECL (y_base); > @@ -2192,8 +2207,8 @@ compare_base_symbol_refs (const_rtx x_base, const_rtx > y_base) > std::swap (x_decl, y_decl); > std::swap (x_base, y_base); > } > - /* We handle specially only section anchors and assume that other > - labels may overlap with user variables in an arbitrary way. */ > + /* We handle specially only section anchors. Other symbols are > + either equal (via aliasing) or refer to different objects. */ > if (!SYMBOL_REF_HAS_BLOCK_INFO_P (y_base)) > return -1; > /* Anchors contains static VAR_DECLs and CONST_DECLs. We are safe > @@ -2222,14 +2237,13 @@ compare_base_symbol_refs (const_rtx x_base, const_rtx > y_base) > { > if (SYMBOL_REF_BLOCK (x_base) != SYMBOL_REF_BLOCK (y_base)) > return 0; > - if (SYMBOL_REF_BLOCK_OFFSET (x_base) == SYMBOL_REF_BLOCK_OFFSET > (y_base)) > - return binds_def ? 1 : -1; > - if (SYMBOL_REF_ANCHOR_P (x_base) != SYMBOL_REF_ANCHOR_P (y_base)) > - return -1; > - return 0; > + if (distance) > + *distance += (SYMBOL_REF_BLOCK_OFFSET (y_base) > + - SYMBOL_REF_BLOCK_OFFSET (x_base)); > + return binds_def ? 1 : -1; > } > - /* In general we assume that memory locations pointed to by different > labels > - may overlap in undefined ways. */ > + /* Either the symbols are equal (via aliasing) or they refer to > + different objects. */ > return -1; > } > > @@ -2513,11 +2527,12 @@ memrefs_conflict_p (poly_int64 xsize, rtx x, > poly_int64 ysize, rtx y, > > if (GET_CODE (x) == SYMBOL_REF && GET_CODE (y) == SYMBOL_REF) > { > - int cmp = compare_base_symbol_refs (x,y); > + HOST_WIDE_INT distance = 0; > + int cmp = compare_base_symbol_refs (x, y, &distance); > > /* If both decls are the same, decide by offsets. */ > if (cmp == 1) > - return offset_overlap_p (c, xsize, ysize); > + return offset_overlap_p (c + distance, xsize, ysize); > /* Assume a potential overlap for symbolic addresses that went > through alignment adjustments (i.e., that have negative > sizes), because we can't know how far they are from each > @@ -2526,7 +2541,7 @@ memrefs_conflict_p (poly_int64 xsize, rtx x, poly_int64 > ysize, rtx y, > return -1; > /* If decls are different or we know by offsets that there is no > overlap, > we win. */ > - if (!cmp || !offset_overlap_p (c, xsize, ysize)) > + if (!cmp || !offset_overlap_p (c + distance, xsize, ysize)) > return 0; > /* Decls may or may not be different and offsets overlap....*/ > return -1; > -- Richard Biener <rguent...@suse.de> SUSE Software Solutions Germany GmbH, Maxfeldstrasse 5, 90409 Nuernberg, Germany; GF: Felix Imendörffer; HRB 36809 (AG Nuernberg)