Chuang-Yu Cheng via llvm-dev
2016-Mar-18 15:33 UTC
[llvm-dev] Redundant load in llvm's codegen compares to gcc when accessing escaped pointer?
1. Same question as David, why &c - 8 is invalid? Is it related to below statements In C99 standard? 6.5.3.3: "Among the invalid values for dereferencing a pointer by the unary * operator are a null pointer, an address inappropriately aligned for the type of object pointed to, and the address of an object after the end of its lifetime." 2. We are trying to preserve 1st load and remove other loads now, because our test pattern can not get rid of "-fno-strict-aliasing", and additional loads hurt performance. We did some change in SROA::runOnAlloca, we try to do something like this: void qux(PB* _c) { PB* c; <= insert this for original code bar(&_c); c = _c; <= insert this for original code c->f1_ = 0; c->f2_ = 0.f; } Any opinions please let us know. Thanks! CY On Fri, Mar 18, 2016 at 11:24 PM, David Blaikie <dblaikie at gmail.com> wrote:> Why would computing that pointer be invalid? > > (I could imagine, if there was no object behind c to point to it would be > invalid - but that's a dynamic property of the program that the compiler, > given this code, can't prove /isn't true/ (the programmer might've > constructed the caller such that it does always have an object behind 'c' > to point to)) > > On Fri, Mar 18, 2016 at 1:28 AM, Markus Trippelsdorf via llvm-dev < > llvm-dev at lists.llvm.org> wrote: > >> On 2016.03.17 at 16:35 -0700, Chris Lattner via llvm-dev wrote: >> > >> > > On Mar 15, 2016, at 7:58 AM, Chuang-Yu Cheng via llvm-dev < >> llvm-dev at lists.llvm.org> 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 >> > > movl $0, 8(%rax) >> > > movl $0x00000000, 12(%rax) >> > > >> > > // llvm 3.9.0 with -fno-strict-aliasing -O2 on x86 >> > > callq bar >> > > movq (%rsp), %rax >> > > movl $0, 8(%rax) >> > > movq (%rsp), %rax >> > > movl $0, 12(%rax) >> > > >> > > You can see that llvm load "c" twice, but gcc only load "c" once. >> > > Of course, in bar function, you may do something very dangerous, e.g. >> > > >> > > PB** bar(PB** t) { >> > > *t = (PB*) t; >> > > } >> > > >> > > But gcc doesn't care bar's definition. >> > > Is llvm too conservative, or gcc too aggressive in this pattern? >> > >> > In my opinion, in the face of -fno-strict-aliasing, GCC is being too >> > aggressive. It would be interesting to hear what they think. >> >> We discussed this issue briefly on the #gcc IRC channel. >> 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. >> >> -- >> Markus >> _______________________________________________ >> LLVM Developers mailing list >> llvm-dev at lists.llvm.org >> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev >> > >-------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20160318/aed6d43f/attachment.html>
David Blaikie via llvm-dev
2016-Mar-18 15:47 UTC
[llvm-dev] Redundant load in llvm's codegen compares to gcc when accessing escaped pointer?
On Fri, Mar 18, 2016 at 8:33 AM, Chuang-Yu Cheng < cycheng at multicorewareinc.com> wrote:> 1. Same question as David, why &c - 8 is invalid? Is it related to below > statements In C99 standard? > > 6.5.3.3: > "Among the invalid values for dereferencing a pointer by the unary * > operator are a null pointer, an > address inappropriately aligned for the type of object pointed to, and the > address of an object after the > end of its lifetime." > > 2. We are trying to preserve 1st load and remove other loads now, because > our test pattern can not get rid of "-fno-strict-aliasing", and additional > loads hurt performance. We did some change in SROA::runOnAlloca, we try to > do something like this: > > void qux(PB* _c) { > PB* c; <= insert this for original code > bar(&_c); > > c = _c; <= insert this for original code > c->f1_ = 0; > c->f2_ = 0.f; > } >Not sure I quite understand the question - if we believe GCC's interpretation to be incorrect/Clang's to be correct, there's nothing our optimizers can do to correct the code & free us up to do the optimization GCC does here. If you're talking about modifying your code to allow Clang to optimize it better - yes, it seems like if you copy the pointer: void qux(PB* _c) { bar(&_c); PB *c; c->f1_ = 0; c->f2_ = 0.f; } Should do the right optimization, because there's no way that 'bar' could give _c an address that would alias 'c' in any way. I'm not sure what you're referring to when you mention making changes to SROA. - Dave> > Any opinions please let us know. > Thanks! > > CY > > On Fri, Mar 18, 2016 at 11:24 PM, David Blaikie <dblaikie at gmail.com> > wrote: > >> Why would computing that pointer be invalid? >> >> (I could imagine, if there was no object behind c to point to it would be >> invalid - but that's a dynamic property of the program that the compiler, >> given this code, can't prove /isn't true/ (the programmer might've >> constructed the caller such that it does always have an object behind 'c' >> to point to)) >> >> On Fri, Mar 18, 2016 at 1:28 AM, Markus Trippelsdorf via llvm-dev < >> llvm-dev at lists.llvm.org> wrote: >> >>> On 2016.03.17 at 16:35 -0700, Chris Lattner via llvm-dev wrote: >>> > >>> > > On Mar 15, 2016, at 7:58 AM, Chuang-Yu Cheng via llvm-dev < >>> llvm-dev at lists.llvm.org> 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 >>> > > movl $0, 8(%rax) >>> > > movl $0x00000000, 12(%rax) >>> > > >>> > > // llvm 3.9.0 with -fno-strict-aliasing -O2 on x86 >>> > > callq bar >>> > > movq (%rsp), %rax >>> > > movl $0, 8(%rax) >>> > > movq (%rsp), %rax >>> > > movl $0, 12(%rax) >>> > > >>> > > You can see that llvm load "c" twice, but gcc only load "c" once. >>> > > Of course, in bar function, you may do something very dangerous, e.g. >>> > > >>> > > PB** bar(PB** t) { >>> > > *t = (PB*) t; >>> > > } >>> > > >>> > > But gcc doesn't care bar's definition. >>> > > Is llvm too conservative, or gcc too aggressive in this pattern? >>> > >>> > In my opinion, in the face of -fno-strict-aliasing, GCC is being too >>> > aggressive. It would be interesting to hear what they think. >>> >>> We discussed this issue briefly on the #gcc IRC channel. >>> 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. >>> >>> -- >>> Markus >>> _______________________________________________ >>> LLVM Developers mailing list >>> llvm-dev at lists.llvm.org >>> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev >>> >> >> >-------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20160318/f2122bbc/attachment.html>
Chuang-Yu Cheng via llvm-dev
2016-Mar-18 16:29 UTC
[llvm-dev] Redundant load in llvm's codegen compares to gcc when accessing escaped pointer?
We are making experimental changes to SROA. CY On Fri, Mar 18, 2016 at 11:47 PM, David Blaikie <dblaikie at gmail.com> wrote:> > > On Fri, Mar 18, 2016 at 8:33 AM, Chuang-Yu Cheng < > cycheng at multicorewareinc.com> wrote: > >> 1. Same question as David, why &c - 8 is invalid? Is it related to below >> statements In C99 standard? >> >> 6.5.3.3: >> "Among the invalid values for dereferencing a pointer by the unary * >> operator are a null pointer, an >> address inappropriately aligned for the type of object pointed to, and >> the address of an object after the >> end of its lifetime." >> >> 2. We are trying to preserve 1st load and remove other loads now, because >> our test pattern can not get rid of "-fno-strict-aliasing", and additional >> loads hurt performance. We did some change in SROA::runOnAlloca, we try to >> do something like this: >> >> void qux(PB* _c) { >> PB* c; <= insert this for original code >> bar(&_c); >> >> c = _c; <= insert this for original code >> c->f1_ = 0; >> c->f2_ = 0.f; >> } >> > > Not sure I quite understand the question - if we believe GCC's > interpretation to be incorrect/Clang's to be correct, there's nothing our > optimizers can do to correct the code & free us up to do the optimization > GCC does here. > > If you're talking about modifying your code to allow Clang to optimize it > better - yes, it seems like if you copy the pointer: > > void qux(PB* _c) { > bar(&_c); > PB *c; > c->f1_ = 0; > c->f2_ = 0.f; > } > > Should do the right optimization, because there's no way that 'bar' could > give _c an address that would alias 'c' in any way. > > I'm not sure what you're referring to when you mention making changes to > SROA. > > - Dave > > >> >> Any opinions please let us know. >> Thanks! >> >> CY >> >> On Fri, Mar 18, 2016 at 11:24 PM, David Blaikie <dblaikie at gmail.com> >> wrote: >> >>> Why would computing that pointer be invalid? >>> >>> (I could imagine, if there was no object behind c to point to it would >>> be invalid - but that's a dynamic property of the program that the >>> compiler, given this code, can't prove /isn't true/ (the programmer >>> might've constructed the caller such that it does always have an object >>> behind 'c' to point to)) >>> >>> On Fri, Mar 18, 2016 at 1:28 AM, Markus Trippelsdorf via llvm-dev < >>> llvm-dev at lists.llvm.org> wrote: >>> >>>> On 2016.03.17 at 16:35 -0700, Chris Lattner via llvm-dev wrote: >>>> > >>>> > > On Mar 15, 2016, at 7:58 AM, Chuang-Yu Cheng via llvm-dev < >>>> llvm-dev at lists.llvm.org> 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 >>>> > > movl $0, 8(%rax) >>>> > > movl $0x00000000, 12(%rax) >>>> > > >>>> > > // llvm 3.9.0 with -fno-strict-aliasing -O2 on x86 >>>> > > callq bar >>>> > > movq (%rsp), %rax >>>> > > movl $0, 8(%rax) >>>> > > movq (%rsp), %rax >>>> > > movl $0, 12(%rax) >>>> > > >>>> > > You can see that llvm load "c" twice, but gcc only load "c" once. >>>> > > Of course, in bar function, you may do something very dangerous, >>>> e.g. >>>> > > >>>> > > PB** bar(PB** t) { >>>> > > *t = (PB*) t; >>>> > > } >>>> > > >>>> > > But gcc doesn't care bar's definition. >>>> > > Is llvm too conservative, or gcc too aggressive in this pattern? >>>> > >>>> > In my opinion, in the face of -fno-strict-aliasing, GCC is being too >>>> > aggressive. It would be interesting to hear what they think. >>>> >>>> We discussed this issue briefly on the #gcc IRC channel. >>>> 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. >>>> >>>> -- >>>> Markus >>>> _______________________________________________ >>>> LLVM Developers mailing list >>>> llvm-dev at lists.llvm.org >>>> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev >>>> >>> >>> >> >-------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20160319/6679b5d3/attachment.html>
Daniel Berlin via llvm-dev
2016-Mar-18 17:25 UTC
[llvm-dev] Redundant load in llvm's codegen compares to gcc when accessing escaped pointer?
I suspect you should just go ask #1 on the gcc mailing list and see what the answer is. We are basically trying to figure out their reasoning, but we should instead just go ask what it is :) On Fri, Mar 18, 2016 at 8:33 AM, Chuang-Yu Cheng via llvm-dev < llvm-dev at lists.llvm.org> wrote:> 1. Same question as David, why &c - 8 is invalid? Is it related to below > statements In C99 standard? > > 6.5.3.3: > "Among the invalid values for dereferencing a pointer by the unary * > operator are a null pointer, an > address inappropriately aligned for the type of object pointed to, and the > address of an object after the > end of its lifetime." > > 2. We are trying to preserve 1st load and remove other loads now, because > our test pattern can not get rid of "-fno-strict-aliasing", and additional > loads hurt performance. We did some change in SROA::runOnAlloca, we try to > do something like this: > > void qux(PB* _c) { > PB* c; <= insert this for original code > bar(&_c); > > c = _c; <= insert this for original code > c->f1_ = 0; > c->f2_ = 0.f; > } > > Any opinions please let us know. > Thanks! > > CY > > On Fri, Mar 18, 2016 at 11:24 PM, David Blaikie <dblaikie at gmail.com> > wrote: > >> Why would computing that pointer be invalid? >> >> (I could imagine, if there was no object behind c to point to it would be >> invalid - but that's a dynamic property of the program that the compiler, >> given this code, can't prove /isn't true/ (the programmer might've >> constructed the caller such that it does always have an object behind 'c' >> to point to)) >> >> On Fri, Mar 18, 2016 at 1:28 AM, Markus Trippelsdorf via llvm-dev < >> llvm-dev at lists.llvm.org> wrote: >> >>> On 2016.03.17 at 16:35 -0700, Chris Lattner via llvm-dev wrote: >>> > >>> > > On Mar 15, 2016, at 7:58 AM, Chuang-Yu Cheng via llvm-dev < >>> llvm-dev at lists.llvm.org> 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 >>> > > movl $0, 8(%rax) >>> > > movl $0x00000000, 12(%rax) >>> > > >>> > > // llvm 3.9.0 with -fno-strict-aliasing -O2 on x86 >>> > > callq bar >>> > > movq (%rsp), %rax >>> > > movl $0, 8(%rax) >>> > > movq (%rsp), %rax >>> > > movl $0, 12(%rax) >>> > > >>> > > You can see that llvm load "c" twice, but gcc only load "c" once. >>> > > Of course, in bar function, you may do something very dangerous, e.g. >>> > > >>> > > PB** bar(PB** t) { >>> > > *t = (PB*) t; >>> > > } >>> > > >>> > > But gcc doesn't care bar's definition. >>> > > Is llvm too conservative, or gcc too aggressive in this pattern? >>> > >>> > In my opinion, in the face of -fno-strict-aliasing, GCC is being too >>> > aggressive. It would be interesting to hear what they think. >>> >>> We discussed this issue briefly on the #gcc IRC channel. >>> 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. >>> >>> -- >>> Markus >>> _______________________________________________ >>> LLVM Developers mailing list >>> llvm-dev at lists.llvm.org >>> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev >>> >> >> > > _______________________________________________ > LLVM Developers mailing list > llvm-dev at lists.llvm.org > http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev > >-------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20160318/1f2e1c8b/attachment.html>
Chuang-Yu Cheng via llvm-dev
2016-Mar-19 02:37 UTC
[llvm-dev] Redundant load in llvm's codegen compares to gcc when accessing escaped pointer?
Agree, and I did : ) Please refer to this mailing list: https://gcc.gnu.org/ml/gcc/2016-03/msg00179.html On Sat, Mar 19, 2016 at 1:25 AM, Daniel Berlin <dberlin at dberlin.org> wrote:> I suspect you should just go ask #1 on the gcc mailing list and see what > the answer is. > We are basically trying to figure out their reasoning, but we should > instead just go ask what it is :) > > > On Fri, Mar 18, 2016 at 8:33 AM, Chuang-Yu Cheng via llvm-dev < > llvm-dev at lists.llvm.org> wrote: > >> 1. Same question as David, why &c - 8 is invalid? Is it related to below >> statements In C99 standard? >> >> 6.5.3.3: >> "Among the invalid values for dereferencing a pointer by the unary * >> operator are a null pointer, an >> address inappropriately aligned for the type of object pointed to, and >> the address of an object after the >> end of its lifetime." >> >> 2. We are trying to preserve 1st load and remove other loads now, because >> our test pattern can not get rid of "-fno-strict-aliasing", and additional >> loads hurt performance. We did some change in SROA::runOnAlloca, we try to >> do something like this: >> >> void qux(PB* _c) { >> PB* c; <= insert this for original code >> bar(&_c); >> >> c = _c; <= insert this for original code >> c->f1_ = 0; >> c->f2_ = 0.f; >> } >> >> Any opinions please let us know. >> Thanks! >> >> CY >> >> On Fri, Mar 18, 2016 at 11:24 PM, David Blaikie <dblaikie at gmail.com> >> wrote: >> >>> Why would computing that pointer be invalid? >>> >>> (I could imagine, if there was no object behind c to point to it would >>> be invalid - but that's a dynamic property of the program that the >>> compiler, given this code, can't prove /isn't true/ (the programmer >>> might've constructed the caller such that it does always have an object >>> behind 'c' to point to)) >>> >>> On Fri, Mar 18, 2016 at 1:28 AM, Markus Trippelsdorf via llvm-dev < >>> llvm-dev at lists.llvm.org> wrote: >>> >>>> On 2016.03.17 at 16:35 -0700, Chris Lattner via llvm-dev wrote: >>>> > >>>> > > On Mar 15, 2016, at 7:58 AM, Chuang-Yu Cheng via llvm-dev < >>>> llvm-dev at lists.llvm.org> 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 >>>> > > movl $0, 8(%rax) >>>> > > movl $0x00000000, 12(%rax) >>>> > > >>>> > > // llvm 3.9.0 with -fno-strict-aliasing -O2 on x86 >>>> > > callq bar >>>> > > movq (%rsp), %rax >>>> > > movl $0, 8(%rax) >>>> > > movq (%rsp), %rax >>>> > > movl $0, 12(%rax) >>>> > > >>>> > > You can see that llvm load "c" twice, but gcc only load "c" once. >>>> > > Of course, in bar function, you may do something very dangerous, >>>> e.g. >>>> > > >>>> > > PB** bar(PB** t) { >>>> > > *t = (PB*) t; >>>> > > } >>>> > > >>>> > > But gcc doesn't care bar's definition. >>>> > > Is llvm too conservative, or gcc too aggressive in this pattern? >>>> > >>>> > In my opinion, in the face of -fno-strict-aliasing, GCC is being too >>>> > aggressive. It would be interesting to hear what they think. >>>> >>>> We discussed this issue briefly on the #gcc IRC channel. >>>> 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. >>>> >>>> -- >>>> Markus >>>> _______________________________________________ >>>> LLVM Developers mailing list >>>> llvm-dev at lists.llvm.org >>>> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev >>>> >>> >>> >> >> _______________________________________________ >> LLVM Developers mailing list >> llvm-dev at lists.llvm.org >> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev >> >> >-------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20160319/31a52696/attachment.html>