Kevin Choi via llvm-dev
2016-Jul-20 16:56 UTC
[llvm-dev] load instruction erroneously removed by GVN v2
Hello to whom this may concern,
Versioned this as I saw identical title before. I'm compiling a clang
project where I'm seeing GVN mess up and replace a load with a wrong def
value. I am using LLVM-3.5, but the problem has been observed upto 3.8.
To illustrate the problem,
define i32 @main
scalar.ph:
<initialize [80 x i16] %dest>
...
preheader:
%index=0
br test, loop1, bb2
loop1:
... write to %dest in increasing index // ptr-based while loop
%ptr++;
br test, loop1, bb2
bb2:
%lcssa = phi [%ptr, loop1], [%ptr, preheader]
store i16 0, i16* %lcssa !dbg !20094 !tbaa 20030 // write null byte at
end
%76 = getelementptr inbounds [80 x i16]* %dest, i64 0, i64 7, !dbg !20095
// load addr of null byte (7th index)
%77 = load i16* %76, align 2, !dbg !20095, !tbaa !20010
%78 = icmp eq i16 %77, 0, !dbg !20095
br i1 %78, label %80, label %79, !dbg !20095
GVN calls processNonLocalLoad() on "%77 = load..." and replaces it
with
init value from scalar.ph.
bb2:
%lcssa = phi [%ptr, loop1], [%ptr, preheader]
store i16 0, i16* %lcssa, !dbg !20094, !tbaa !20030
%76 = getelementptr inbounds [80 x i16]* %dest, i64 0, i64 7, !dbg !20095
br i1 icmp eq (i16 trunc (i128 lshr (i128 bitcast (<8 x i16> <i16 120,
i16
120, i16 120, i16 120, i16 120, i16 120, i16 120, i16 120> to i128), i128
96) to i16), i16 0), label %78, label %77, !dbg !20095 // simplifies to
"icmp eq (i16 120, i16 0) --> false"
I first suspected problem might be TBAA; invoking clang with
-fno-strict-aliasing makes the test pass (similarly, opt with -basicaa does
not make GVN transform the load). When I look at the C/C++ source code, I
cannot find any type-based aliasing violations from eyeballing.
I started looking at the aliasing and landed at
getNonLocalPointerDepFromBB(), in which the worklist algorithm to find
MemDep reported the result from the init block, ignoring all the kills
after it. I did see one of the parm was SkipFirstBlock and this appears to
ignore the store %ptr above the load. Is there a reason why it skips first
block? Shouldn't it look at the preceding instructions in the same block as
they could contain kill points? I am still unfamiliar with the algorithm
used here and would very much appreciate if someone could educate or point
me towards right direction.
Regards,
Kevin
-------------- next part --------------
An HTML attachment was scrubbed...
URL:
<http://lists.llvm.org/pipermail/llvm-dev/attachments/20160720/8d497ed2/attachment.html>
Daniel Berlin via llvm-dev
2016-Jul-20 18:06 UTC
[llvm-dev] load instruction erroneously removed by GVN v2
On Wed, Jul 20, 2016 at 9:56 AM, Kevin Choi via llvm-dev < llvm-dev at lists.llvm.org> wrote:> Hello to whom this may concern, > > Versioned this as I saw identical title before. I'm compiling a clang > project where I'm seeing GVN mess up and replace a load with a wrong def > value. >Do you have a c testcase or a .ll file i can actually compile?> I am using LLVM-3.5, but the problem has been observed upto 3.8. > To illustrate the problem, > > define i32 @main > scalar.ph: > <initialize [80 x i16] %dest> > ... > preheader: > %index=0 > br test, loop1, bb2 > loop1: > ... write to %dest in increasing index // ptr-based while loop > %ptr++; > br test, loop1, bb2 > bb2: > %lcssa = phi [%ptr, loop1], [%ptr, preheader] > store i16 0, i16* %lcssa !dbg !20094 !tbaa 20030 // write null byte at > end > %76 = getelementptr inbounds [80 x i16]* %dest, i64 0, i64 7, !dbg > !20095 // load addr of null byte (7th index) > %77 = load i16* %76, align 2, !dbg !20095, !tbaa !20010 > %78 = icmp eq i16 %77, 0, !dbg !20095 > br i1 %78, label %80, label %79, !dbg !20095 > > GVN calls processNonLocalLoad() on "%77 = load..." and replaces it with > init value from scalar.ph. > >> bb2: > %lcssa = phi [%ptr, loop1], [%ptr, preheader] > store i16 0, i16* %lcssa, !dbg !20094, !tbaa !20030 > %76 = getelementptr inbounds [80 x i16]* %dest, i64 0, i64 7, !dbg !20095 > br i1 icmp eq (i16 trunc (i128 lshr (i128 bitcast (<8 x i16> <i16 120, i16 > 120, i16 120, i16 120, i16 120, i16 120, i16 120, i16 120> to i128), i128 > 96) to i16), i16 0), label %78, label %77, !dbg !20095 // simplifies to > "icmp eq (i16 120, i16 0) --> false" > > I first suspected problem might be TBAA; invoking clang with > -fno-strict-aliasing makes the test pass (similarly, opt with -basicaa does > not make GVN transform the load). When I look at the C/C++ source code, I > cannot find any type-based aliasing violations from eyeballing. >Can you excerpt the actual source code?> > I started looking at the aliasing and landed at > getNonLocalPointerDepFromBB(), in which the worklist algorithm to find > MemDep reported the result from the init block, ignoring all the kills > after it. I did see one of the parm was SkipFirstBlock and this appears to > ignore the store %ptr above the load. Is there a reason why it skips first > block? >Yes. It is looking for *non-local* dependences. The block it should skip is bb2, not loop1. There is another call for local dependences. If you ask for local dependences, then non-local ones, as GVN does, there is no point in having it go and look at the local ones again :) Look at how GVN calls this: MemDepResult Dep = MD->getDependency(L); // If it is defined in another block, try harder. if (Dep.isNonLocal()) return processNonLocalLoad(L); (IE get local dependence, if there is none, go looking at non-local dependences). The list of non-local dependences it includes should definitely include the one from block "loop1", and if it is ignoring it, it is most likely thinks it does not alias for some reason. -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20160720/5e79a231/attachment.html>
Kevin Choi via llvm-dev
2016-Jul-20 18:24 UTC
[llvm-dev] load instruction erroneously removed by GVN v2
Thanks for quick reply Daniel, I tried to make a simple C testcase, but could not reproduce the same condition with output from Clang. I suppose I could modify the C code to make it look similar with TBAA's; I may be able to provide this by eod.> store %ptr above the load.My mistake; I was referring to the store $lcssa in bb2. Looking at the C source code, it should definitely alias with %dest. I will try and see if I can find out why it thinks there is no local dependence. Thanks, Kevin On 20 July 2016 at 11:06, Daniel Berlin <dberlin at dberlin.org> wrote:> > > On Wed, Jul 20, 2016 at 9:56 AM, Kevin Choi via llvm-dev < > llvm-dev at lists.llvm.org> wrote: > >> Hello to whom this may concern, >> >> Versioned this as I saw identical title before. I'm compiling a clang >> project where I'm seeing GVN mess up and replace a load with a wrong def >> value. >> > > > Do you have a c testcase or a .ll file i can actually compile? > > >> I am using LLVM-3.5, but the problem has been observed upto 3.8. >> To illustrate the problem, >> >> define i32 @main >> scalar.ph: >> <initialize [80 x i16] %dest> >> ... >> preheader: >> %index=0 >> br test, loop1, bb2 >> loop1: >> ... write to %dest in increasing index // ptr-based while loop >> %ptr++; >> br test, loop1, bb2 >> bb2: >> %lcssa = phi [%ptr, loop1], [%ptr, preheader] >> store i16 0, i16* %lcssa !dbg !20094 !tbaa 20030 // write null byte at >> end >> %76 = getelementptr inbounds [80 x i16]* %dest, i64 0, i64 7, !dbg >> !20095 // load addr of null byte (7th index) >> %77 = load i16* %76, align 2, !dbg !20095, !tbaa !20010 >> %78 = icmp eq i16 %77, 0, !dbg !20095 >> br i1 %78, label %80, label %79, !dbg !20095 >> >> GVN calls processNonLocalLoad() on "%77 = load..." and replaces it with >> init value from scalar.ph. >> >> > > >> bb2: >> %lcssa = phi [%ptr, loop1], [%ptr, preheader] >> store i16 0, i16* %lcssa, !dbg !20094, !tbaa !20030 >> %76 = getelementptr inbounds [80 x i16]* %dest, i64 0, i64 7, !dbg !20095 >> br i1 icmp eq (i16 trunc (i128 lshr (i128 bitcast (<8 x i16> <i16 120, >> i16 120, i16 120, i16 120, i16 120, i16 120, i16 120, i16 120> to i128), >> i128 96) to i16), i16 0), label %78, label %77, !dbg !20095 // simplifies >> to "icmp eq (i16 120, i16 0) --> false" >> >> I first suspected problem might be TBAA; invoking clang with >> -fno-strict-aliasing makes the test pass (similarly, opt with -basicaa does >> not make GVN transform the load). When I look at the C/C++ source code, I >> cannot find any type-based aliasing violations from eyeballing. >> > > Can you excerpt the actual source code? > >> >> I started looking at the aliasing and landed at >> getNonLocalPointerDepFromBB(), in which the worklist algorithm to find >> MemDep reported the result from the init block, ignoring all the kills >> after it. I did see one of the parm was SkipFirstBlock and this appears to >> ignore the store %ptr above the load. Is there a reason why it skips first >> block? >> > > > Yes. It is looking for *non-local* dependences. The block it should skip > is bb2, not loop1. > There is another call for local dependences. If you ask for local > dependences, then non-local ones, as GVN does, there is no point in having > it go and look at the local ones again :) > > Look at how GVN calls this: > MemDepResult Dep = MD->getDependency(L); > > // If it is defined in another block, try harder. > if (Dep.isNonLocal()) > return processNonLocalLoad(L); > > (IE get local dependence, if there is none, go looking at non-local > dependences). > > > The list of non-local dependences it includes should definitely include > the one from block "loop1", and if it is ignoring it, it is most likely > thinks it does not alias for some reason. > >-------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20160720/0e1418d9/attachment.html>