[llvm-dev] Aliasing rules difference between GCC and Clang

Matthieu Brucher via llvm-dev llvm-dev at lists.llvm.org
Fri Sep 21 00:39:17 PDT 2018


There are many discussions about the strict aliasing undefined behavior:
https://en.wikipedia.org/wiki/Pointer_aliasing
https://gist.github.com/shafik/848ae25ee209f698763cffee272a58f8
https://stackoverflow.com/questions/98650/what-is-the-strict-aliasing-rule
There is also mention of this on cppreference:
https://en.cppreference.com/w/cpp/language/reinterpret_cast

Cheers,

Matthieu

Le ven. 21 sept. 2018 à 08:32, Jonas Paulsson <paulsson at linux.vnet.ibm.com>
a écrit :

> Hi Matthieu,
>
>
>
> Oh indeed, sorry, you are doing an outer product on a and b, storing the
> result in c, and these cannot alias (or they should not, if you do make
> they alias, it's your responsibility and I think you can get UB).
> So clang should do better indeed.
>
> It would be very nice if you could motivate this in detail with references
> to the standard. Is it enough that the two struct types have different
> tags? It might possibly be argued that the matrix contains the vector
> struct type, and therefore they may alias.
>  Why do you think this is not the case in this example?
>
> /Jonas
>
>
>
> Regards,
>
>
> Le ven. 21 sept. 2018 à 08:21, Jonas Paulsson <paulsson at linux.vnet.ibm.com>
> a écrit :
>
>>
>>
>> I would say that GCC is wrong and should also have a version where a
>> could be equal to b. There is no restrict keyword, so they could be equal.
>>
>> This was between a/b and c, not between a and b. Could you explain your
>> opinion a bit more in detail, please?
>>
>> /Jonas
>>
>> Cheers,
>>
>> Matthieu
>>
>> Le jeu. 20 sept. 2018 à 16:56, Jonas Paulsson via llvm-dev <
>> llvm-dev at lists.llvm.org> a écrit :
>>
>>> Hi,
>>>
>>> I found a difference between Clang and GCC in alias handling. This was
>>> with a benchmark where Clang was considerably slower, and in a hot function
>>> which does many more loads from the same address due to stores between the
>>> uses. In other words, a value is loaded and used, another value is stored,
>>> and then the first value is loaded once again before its second use. This
>>> happens many times, with three loads instead of one for each value. GCC
>>> only emits one load.
>>>
>>> The values are the arguments to this function:
>>> void su3_projector( su3_vector *a, su3_vector *b, su3_matrix *c ){
>>> register int i,j;
>>> register double tmp,tmp2;
>>>     for(i=0;i<3;i++)for(j=0;j<3;j++){
>>>         tmp2 = a->c[i].real * b->c[j].real;
>>>         tmp = a->c[i].imag * b->c[j].imag;
>>>         c->e[i][j].real = tmp + tmp2;
>>>         tmp2 = a->c[i].real * b->c[j].imag;
>>>         tmp = a->c[i].imag * b->c[j].real;
>>>         c->e[i][j].imag = tmp - tmp2;
>>>     }
>>> }
>>>
>>> The types are:
>>> typedef struct { complex e[3][3]; } su3_matrix;
>>> typedef struct { complex c[3]; } su3_vector;
>>>
>>> So the question here is if the su3_vector and su3_matrix pointers may
>>> alias? If they may alias, then clang is right in reloading after each
>>> store. If the standard says they cannot alias, then gcc is right in only
>>> loading the values once each.
>>>
>>> It seems to me that either GCC is too aggressive or LLVM is too
>>> conservative, but I don't know which one it is... As far as I understand,
>>> there is the fact of the different struct types of the arguments (which
>>> means they cannot alias), but also the question if su3_vector is included
>>> in su3_matrix (which would mean they may alias).
>>>
>>> I made a reduced test case, where the same difference seems to be
>>> present. It has just one struct type which contains a matrix of double:s. A
>>> store to an element of the struct via a pointer is surrounded with two
>>> loads of a global double variable. Only Clang emits two loads.
>>>
>>> typedef struct {
>>>   double c[3][3];
>>> } STRUCT_TY;
>>>
>>> double e = 0.0;
>>> STRUCT_TY *f;
>>> int g = 0;
>>> void h() {
>>>   int i = e;
>>>   f->c[0][i] = g;
>>>   g = e;
>>> }
>>>
>>> clang -O3-march=z13 :
>>>
>>> h:                                      # @h
>>> # %bb.0:                                # %entry
>>>         larl    %r1, e
>>>         ld      %f0, 0(%r1)        // LOAD E
>>>         lrl     %r2, g
>>>         cfdbr   %r0, 5, %f0        // CONVERT E
>>>         lgfr    %r0, %r0           // EXTEND E
>>>         cdfbr   %f0, %r2
>>>         lgrl    %r2, f
>>>         sllg    %r3, %r0, 3
>>>         std     %f0, 0(%r3,%r2)    // STORE F ELEMENT
>>>         ld      %f0, 0(%r1)        // 2nd LOAD E        <<<<<<<
>>>         cfdbr   %r0, 5, %f0        // CONVERT
>>>         strl    %r0, g             // 2nd USE
>>>         br      %r14
>>>
>>> gcc -O3-march=z13 :
>>>
>>> h:
>>> .LFB0:
>>>         .cfi_startproc
>>>         larl    %r1,e
>>>         ld      %f0,0(%r1)        // LOAD E
>>>         lrl     %r2,g
>>>         lgrl    %r3,f
>>>         cfdbr   %r1,5,%f0         // CONVERT E
>>>         cdfbr   %f0,%r2
>>>         lgfr    %r2,%r1           // EXTEND E
>>>         sllg    %r2,%r2,3
>>>         std     %f0,0(%r2,%r3)    // STORE F ELEMENT
>>>         strl    %r1,g             // 2nd USE
>>>         br      %r14
>>>
>>> I hope somebody with enough experience and knowledge can guide the way
>>> here as this seems to be quite important.
>>>
>>> /Jonas
>>>
>>>
>>>
>>> _______________________________________________
>>> LLVM Developers mailing list
>>> llvm-dev at lists.llvm.org
>>> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev
>>>
>>
>>
>> --
>> Quantitative analyst, Ph.D.
>> Blog: http://blog.audio-tk.com/
>> LinkedIn: http://www.linkedin.com/in/matthieubrucher
>>
>>
>>
>
> --
> Quantitative analyst, Ph.D.
> Blog: http://blog.audio-tk.com/
> LinkedIn: http://www.linkedin.com/in/matthieubrucher
>
>
>

-- 
Quantitative analyst, Ph.D.
Blog: http://blog.audio-tk.com/
LinkedIn: http://www.linkedin.com/in/matthieubrucher
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20180921/415bc165/attachment.html>


More information about the llvm-dev mailing list