[llvm-dev] load instruction erroneously removed by GVN v2

Kevin Choi via llvm-dev llvm-dev at lists.llvm.org
Wed Jul 20 09:56:18 PDT 2016

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
    <initialize [80 x i16] %dest>
br test, loop1, bb2
  ... write to %dest in increasing index // ptr-based while loop
  br test, loop1, bb2
  %lcssa = phi [%ptr, loop1], [%ptr, preheader]
  store i16 0, i16* %lcssa !dbg !20094 !tbaa 20030  // write null byte at
  %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.

%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.

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20160720/8d497ed2/attachment.html>

More information about the llvm-dev mailing list