> 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.

OK too, thanks!
Honza
> 
> 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)

Reply via email to