On March 18, 2016 3:26:37 PM GMT+01:00, Markus Trippelsdorf <mar...@trippelsdorf.de> wrote: >On 2016.03.18 at 22:05 +0800, Cy Cheng wrote: >> Hi, >> >> Please look at this c code: >> >> typedef struct _PB { >> void* data; /* required.*/ >> int f1_; >> float f2_; >> } PB; >> >> PB** bar(PB** t); >> >> void qux(PB* c) { >> bar(&c); /* c is escaped because of bar */ >> c->f1_ = 0; >> c->f2_ = 0.f; >> } >> >> // gcc-5.2.1 with -fno-strict-aliasing -O2 on x86 >> call bar >> movq 8(%rsp), %rax <= load pointer c >> movl $0, 8(%rax) >> movl $0x00000000, 12(%rax) >> >> // intel-icc-13.0.1 with -fno-strict-aliasing -O2 on x86 >> call bar(_PB**) >> movq (%rsp), %rdx <= load pointer c >> movl %ecx, 8(%rdx) >> movq (%rsp), %rsi <= load pointer c >> movl %ecx, 12(%rsi) >> >> GCC only load pointer c once, but if I implement bar in such way: >> PB** bar(PB** t) { >> char* ptr = (char*)t; >> *t = (PB*)(ptr-8); >> return t; >> } >> >> Does this volatile C99 standard rule >> (http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf): >> >> 6.5.16 Assignment operators >> >> "3. ... The side effect of updating the stored value of the left >operand >> shall occur between the previous and the next sequence point." > >No. We discussed this on IRC today and Richard Biener pointed out that >bar cannot make c point to &c - 8, because computing that pointer would >be invalid. So c->f1_ cannot clobber c itself.
Nice to see that only GCC gets this optimization opportunity :) Richard.