:D But I don't understand why &c - 8 is invalid? Which rule in C99 it volatile?
That's see the example again with some changes: // Now, I make c point to &c - 8 PB** bar(PB** t) { char* ptr = (char*)t; *t = (PB*)(ptr-8); } void qux(PB* c) { PB* cc; bar(&c); c->f1_ = 0; // invalid cc = c; cc->f1_ = 0; // valid or invalid? } My question is, if &c - 8 is an invalid address, then it looks like cc->f1_ = 0 will be an invalid operation? Or &c - 8 is only invalid in terms of c, not cc? (By the way, we also discuss the pattern in llvm mailing list: https://goo.gl/VHK0dN) 2016-03-19 2:46 GMT+08:00 Richard Biener <richard.guent...@gmail.com>: > 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. >