On April 8, 2016 8:10:16 PM GMT+02:00, Bill Schmidt <wschm...@linux.vnet.ibm.com> wrote: >Hi, > >I ran into a couple of aliasing issues with a project I'm working on, >and have some questions. > >The first is an issue with TOC-relative addresses on PowerPC. These >are >symbolic addresses that are to be loaded from a fixed slot in the table >of contents, as addressed by the TOC pointer (r2). In the RTL phases >prior to register allocation, these are described in an UNSPEC that >looks like this for an example store: > >(set (mem/c:DI (unspec:DI [ > (symbol_ref:DI ("*.LANCHOR0") [flags 0x182]) > (reg:DI 2 2) > ] UNSPEC_TOCREL) [1 svul+0 S8 A128]) > (reg:DI 178)) > >The UNSPEC helps keep track of the r2 reference until this is split >into >two or more insns depending on the memory model. > >I discovered that alias.c:memrefs_conflict_p is unable to make >must-alias decisions about these, because it doesn't see into the >UNSPEC >to find the symbol_ref. Thus it returns -1 (no information) when >comparing the above with: > >(set (reg/f:DI 177) > (unspec:DI [ > (symbol_ref:DI ("*.LANCHOR0") [flags 0x182]) > (reg:DI 2 2) > ] UNSPEC_TOCREL)) >(set (reg:V2DI 159) > (mem:V2DI (and:DI (reg/f:DI 177) > (const_int -16 [0xfffffffffffffff0])) [4 *_11+0 S16 A128])) > >But clearly the two addresses overlap. > >I added the following hack, and the code then returns 1 (must-alias), >without regressing anything in the test suite. > >Index: gcc/alias.c > >=================================================================== >--- gcc/alias.c (revision 234726) > >+++ gcc/alias.c (working copy) > >@@ -2213,6 +2213,12 @@ memrefs_conflict_p (int xsize, rtx x, int ysize, >r >} > >} > > >+ /* Some targets may hide a base address in an UNSPEC. Peel that >away. */ >+ if (GET_CODE (x) == UNSPEC) > >+ return memrefs_conflict_p (xsize, XVECEXP (x, 0, 0), ysize, y, c); > >+ if (GET_CODE (y) == UNSPEC) > >+ return memrefs_conflict_p (xsize, x, ysize, XVECEXP (y, 0, 0), c); > >+ > >if (CONSTANT_P (x)) > >{ > >if (CONST_INT_P (x) && CONST_INT_P (y)) > > >Now, this is probably not right for a real fix, since it assumes that >any UNSPEC is ok for this, and that the base address will be found >recursively in the first position. I don't know whether any other >targets have similar issues. So: > >(1) What is the best way to handle this? Would it be better to have >some sort of target hook? > >(2) Are there other places in the aliasing infrastructure where this >UNSPEC use could be getting us into trouble?
UNSPECs are bad for any middle-end analysis. My suggestion is to try to avoid these. >Another issue I see involves disjoint alias sets. If you look closely >at the rtx's above, they have been marked as disjoint, belonging to >alias sets 1 and 4, respectively: > >[1 svul+0 S8 A128] >[4 *_11+0 S16 A128] > >The gimple involved is: > > svul[0] = 0; > svul[1] = 1; > svul.1_9 = (sizetype) &svul; > _10 = svul.1_9 & 18446744073709551600; // i.e., -16 or 0xfff...f0 > _11 = (__vector unsigned long *) _10; > vul.2_12 = *_11; > >where svul is file-scope: > > static unsigned long long svul[2] __attribute__ ((aligned (16))); The issue is unsigned long long vs. Unsigned long. They do not alias according to TBAA rules. Most x86 builtins carefully use may_alias vector types to side-step this issue. Richard. >Here I am exposing the semantics of the vec_ld built-in, which aligns >the address to a 16-byte boundary by masking the low-order four bits. >But bitwise AND only works in an integer type, so some casting there >may >be responsible for losing track of the fact that *_11 aliases svul. >However, it seems odd to imply that *_11 definitely does not alias >svul. >So: > >(3) Am I doing something wrong to expose the address masking this way? > >(4) Are the alias sets bogus, or am I misinterpreting this? If they >are >wrong, please point me to where they are computed and I can debug >further. > >Thanks for any help! I haven't dug deeply into the aliasing analysis >before. > >Bill