This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Some aliasing questions


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?

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)));

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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]