Markus Trippelsdorf via llvm-dev
2016-Mar-18 08:28 UTC
[llvm-dev] Redundant load in llvm's codegen compares to gcc when accessing escaped pointer?
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
David Blaikie via llvm-dev
2016-Mar-18 15:24 UTC
[llvm-dev] Redundant load in llvm's codegen compares to gcc when accessing escaped pointer?
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/99583b7e/attachment.html>
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>
Daniel Berlin via llvm-dev
2016-Mar-18 15:46 UTC
[llvm-dev] Redundant load in llvm's codegen compares to gcc when accessing escaped pointer?
I *think the argument* goes that this is a 20 or 24 byte object, so if you *could* put something of type PB at c-8, you'd illegally overlap with the object at c. Thus, there can't be an object of type PB at c-8. (IE any valid object must be sizeof(PB) away in either direction, which means it's not possible for c->f1_ to clobber c no matter what bar does) On Fri, Mar 18, 2016 at 8:24 AM, David Blaikie via llvm-dev < llvm-dev at lists.llvm.org> 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/0a45d7dd/attachment.html>