On Wed, Feb 19, 2020 at 1:19 PM Richard Sandiford <richard.sandif...@arm.com> wrote: > > What should we do about this? The PR is a wrong-code regression from > GCC 9 and it doesn't look like we can remove the second offset_overlap_p > check, given how many cases currently rely on it.
Did you check whether we eventually disambiguate those via rtx_refs_may_alias_p (so using MEM_EXPR)? I would guess all but those that have no MEM_EXPR? Ideally we'd rely more on MEM_EXPR for alias disambiguation than the ad-hoc ways of recovering "details" from the actual MEM. If numbers are still in the same ballpark when factoring in alias disambiguations run after memrefs_conflict_p calls then let's go with your patch, it looks technically correct if all the facts about section anchors are correct (where I know not very much about them or representational issues wrt aliasing). Thanks, Richard. > Thanks, > Richard > > Richard Sandiford <richard.sandif...@arm.com> writes: > > Richard Biener <richard.guent...@gmail.com> writes: > >> On Tue, Feb 4, 2020 at 6:44 PM Richard Sandiford > >> <richard.sandif...@arm.com> wrote: > >>> > >>> Richard Sandiford <richard.sandif...@arm.com> writes: > >>> > [...] > >>> >> I'm not sure given the issues you've introduced if I could actually > >>> >> fill out the matrix of answers without more underlying information. > >>> >> ie, when can we get symbols without source level decls, > >>> >> anchors+interposition issues, etc. > >>> > > >>> > OK. In that case, I wonder whether it would be safer to have a > >>> > fourth state on top of the three above: > >>> > > >>> > - known distance apart > >>> > - independent > >>> > - known distance apart or independent > >>> > - don't know > >>> > > >>> > with "don't know" being anything that involves bare symbols? > >>> > > >>> > Richard > >>> > >>> How does this look? Tested on aarch64-linux-gnu and > >>> x86_64-linux-gnu. > >>> > >>> Full description from scratch: > >>> > >>> memrefs_conflict_p has a slightly odd structure. It first checks > >>> whether two addresses based on SYMBOL_REFs refer to the same object, > >>> with a tristate result: > >>> > >>> int cmp = compare_base_symbol_refs (x,y); > >>> > >>> If the addresses do refer to the same object, we can use offset-based > >>> checks: > >>> > >>> /* If both decls are the same, decide by offsets. */ > >>> if (cmp == 1) > >>> return offset_overlap_p (c, xsize, ysize); > >>> > >>> But then, apart from the special case of forced address alignment, > >>> we use an offset-based check even if we don't know whether the > >>> addresses refer to the same object: > >>> > >>> /* 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 > >>> other. */ > >>> if (maybe_lt (xsize, 0) || maybe_lt (ysize, 0)) > >>> 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)) > >>> return 0; > >>> > >>> This somewhat contradicts: > >>> > >>> /* In general we assume that memory locations pointed to by different > >>> labels > >>> may overlap in undefined ways. */ > >> > >> Sorry for not chiming in earlier but isn't the bug that > >> > >> > >> > >>> at the end of compare_base_symbol_refs. In other words, we're taking -1 > >>> to mean that either (a) the symbols are equal (via aliasing) or (b) the > >>> references access non-overlapping objects. > >>> > >>> But even assuming that's true for normal symbols, it doesn't cope > >>> correctly with section anchors. If a symbol X at ANCHOR+OFFSET > >>> is preemptible, either (a) X = ANDHOR+OFFSET or (b) X and ANCHOR > >>> reference non-overlapping objects. > >>> > >>> And an offset-based comparison makes no sense for an anchor symbol > >>> vs. a bare symbol with no decl. If the bare symbol is allowed to > >>> alias other symbols then it can surely alias any symbol in the > >>> anchor's block, so there are multiple anchor offsets that might > >>> induce an alias. > >> > >> But then isn't the simple fix to honor the -1 and do > >> > >> diff --git a/gcc/alias.c b/gcc/alias.c > >> index 3794f9b6a9e..bf13d37c0f7 100644 > >> --- a/gcc/alias.c > >> +++ b/gcc/alias.c > >> @@ -2490,9 +2490,8 @@ memrefs_conflict_p (poly_int64 xsize, rtx x, > >> poly_int64 ysize, rtx y, > >> other. */ > >> if (maybe_lt (xsize, 0) || maybe_lt (ysize, 0)) > >> 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 decls are different, we win. */ > >> + if (cmp == 0) > >> return 0; > >> /* Decls may or may not be different and offsets overlap....*/ > >> return -1; > >> > >> ? > > > > The code was deliberately written this way from the ouset though > > (rather than it ending up like this through many cuts). It was > > added in g:54363f8a92920f5559c83ddd53e480a27205e6b7: > > > > 2015-12-08 Jan Hubicka <hubi...@ucw.cz> > > > > PR ipa/61886 > > PR middle-end/25140 > > * tree-ssa-alias.c (ptr_deref_may_alias_decl_p): Use > > compare_base_decls > > (nonoverlapping_component_refs_of_decl_p): Update sanity check. > > (decl_refs_may_alias_p): Use compare_base_decls. > > * alias.c: Include cgraph.h > > (get_alias_set): Add cut-off for recursion. > > (rtx_equal_for_memref_p): Use rtx_equal_for_memref_p. > > (compare_base_decls): New function. > > (base_alias_check): Likewise. > > (memrefs_conflict_p): Likewise. > > (nonoverlapping_memrefs_p): Likewise. > > * alias.h (compare_base_decls): Declare. > > > > which included: > > > > - if (rtx_equal_for_memref_p (x, y)) > > + if (GET_CODE (x) == SYMBOL_REF && GET_CODE (y) == SYMBOL_REF) > > + { > > + tree x_decl = SYMBOL_REF_DECL (x); > > + tree y_decl = SYMBOL_REF_DECL (y); > > + int cmp; > > + > > + if (!x_decl || !y_decl) > > + { > > + /* Label and normal symbol are never the same. */ > > + if (x_decl != y_decl) > > + return 0; > > + return offset_overlap_p (c, xsize, ysize); > > + } > > + else > > + cmp = compare_base_decls (x_decl, y_decl); > > + > > + /* If both decls are the same, decide by offsets. */ > > + if (cmp == 1) > > + return offset_overlap_p (c, xsize, ysize); > > + /* If decls are different or we know by offsets that there is no > > overlap, > > + we win. */ > > + if (!cmp || !offset_overlap_p (c, xsize, ysize)) > > + return 0; > > + /* Decls may or may not be different and offsets overlap....*/ > > + return -1; > > + } > > + else if (rtx_equal_for_memref_p (x, y)) > > > > The only significant change since them was to add compare_base_symbol_refs > > (g:73e48cb322152bf504ced8694fa748544ecaa6eb): > > > > if (GET_CODE (x) == SYMBOL_REF && GET_CODE (y) == SYMBOL_REF) > > { > > - tree x_decl = SYMBOL_REF_DECL (x); > > - tree y_decl = SYMBOL_REF_DECL (y); > > - int cmp; > > - > > - if (!x_decl || !y_decl) > > - { > > - /* Label and normal symbol are never the same. */ > > - if (x_decl != y_decl) > > - return 0; > > - return offset_overlap_p (c, xsize, ysize); > > - } > > - else > > - cmp = compare_base_decls (x_decl, y_decl); > > + int cmp = compare_base_symbol_refs (x,y); > > > >>> This patch therefore replaces the current tristate: > >>> > >>> - known equal > >>> - known independent (two accesses can't alias) > >>> - equal or independent > >>> > >>> with: > >>> > >>> - known distance apart > >>> - known independent (two accesses can't alias) > >>> - known distance apart or independent > >>> - don't know > >>> > >>> For safety, the patch puts all bare symbols in the "don't know" > >>> category. If that turns out to be too conservative, we at least > >>> need that behaviour for combinations involving a bare symbol > >>> and a section anchor. > >> > >> This sounds complicated (for this stage). Do you have any statistics as > >> to how it affects actual alias queries (thus outcome in > >> {true,...}_dependence) > >> when you do the "simple" fix? > > > > For a stage3 build of gcc on aarch64-linux-gnu I get: > > > > ("positive" == conflict, "negative" == no conflict) > > > > 16191 cmp == 1, disjoint offsets : true negative > > 19698 cmp == 1, overlapping offsets : true positive > > 79363 cmp == -1, disjoint offsets : true negative > > 6965 cmp == -1, disjoint offsets : false negative <== bug > > 48 cmp == -1, overlapping offsets : true positive > > 928 cmp == -1, overlapping offsets : false positive <== missed opt > > 123193 total queries > > > > where the cmp == -1 cases are divided into true and false results > > according to whether we get the same answer when taking the (hopefully) > > correct offset into account. cmp == 0 and what would be cmp == -2 never > > occured. > > > > So it looks like we're relying on the cmp == -1 offset_overlap_p > > check to get true "no conflict" results for ~64% of all queries > > (or ~83% of all true "no conflict" results). I expect this is > > very dependent on the fact that the port uses section anchors. > > > > The number of buggy cases seems surprisingly high, but I've tried > > to re-check it a couple of times and it looks to be accurate. > > They come from cases where we compare things like: > > > > x: (symbol_ref:DI ("*.LANCHOR0") [flags 0x182]) > > y: (symbol_ref:DI ("_ZL23yy_last_accepting_state") [flags 0x82] <var_decl > > ... yy_last_accepting_state>) > > c: -48 > > > > where yy_last_accepting_state is at offset 48 from the anchor. > > I haven't checked where the buggy queries are coming from though; > > might be debug-related and so hard to spot. > > > > Thanks, > > Richard