[llvm-dev] Aliasing rules difference between GCC and Clang (original) (raw)

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 su3projector( su3vector *a, su3vector *b, su3matrix *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]; } su3matrix; >> typedef struct { complex c[3]; } su3vector; >>>>> So the question here is if the su3vector and su3matrix 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 su3vector is included >> in su3matrix (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]; >> } STRUCTTY; >>>>> double e = 0.0; >> STRUCTTY *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: >> .cfistartproc >> 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