[llvm-bugs] [Bug 39282] New: Loop unrolling incorrectly duplicates noalias metadata

via llvm-bugs llvm-bugs at lists.llvm.org
Sat Oct 13 15:57:40 PDT 2018


https://bugs.llvm.org/show_bug.cgi?id=39282

            Bug ID: 39282
           Summary: Loop unrolling incorrectly duplicates noalias metadata
           Product: libraries
           Version: trunk
          Hardware: All
                OS: All
            Status: NEW
          Severity: enhancement
          Priority: P
         Component: Loop Optimizer
          Assignee: unassignedbugs at nondot.org
          Reporter: nikita.ppv at gmail.com
                CC: llvm-bugs at lists.llvm.org

The loop unrolling pass currently duplicates instructions carrying !noalias and
!alias.scope metadata without adjustments. This may lead to miscompilations,
because the aliasing information may not necessarily be valid across multiple
loop iterations.

The following C code demonstrates such a miscompilation:

#include "stdio.h"

void copy(int * restrict to, int * restrict from) {
        *to = *from;
}

void test(int *a, int *b) {
        for (int i = 0; i < 4; i++) {
                copy(&b[i & 1], &a[i & 1]);
        }
}

int main() {
        int ary[] = {0, 1, 2};
        test(&ary[1], &ary[0]);
        printf("%d %d %d\n", ary[0], ary[1], ary[2]);
        return 1;
}

Compiled using clang with -O0 the result is "2 2 2" (which is correct).
Compiled at -O3 the result is "1 2 2".

The following LLVM IR shows approximately the same situation as the above code
post-inlining:

define void @test(i32* %addr1, i32* %addr2) {
start:
    br label %body

body:
    %i = phi i32 [ 0, %start ], [ %i2, %body ]
    %j = and i32 %i, 1
    %addr1i = getelementptr inbounds i32, i32* %addr1, i32 %j
    %addr2i = getelementptr inbounds i32, i32* %addr2, i32 %j

    %x = load i32, i32* %addr1i, !alias.scope !2
    store i32 %x, i32* %addr2i, !noalias !2

    %i2 = add i32 %i, 1
    %cmp = icmp slt i32 %i2, 4
    br i1 %cmp, label %body, label %end

end:
    ret void
}

!0 = !{!0}
!1 = !{!1, !0}
!2 = !{!1}

The aliasing information here is valid within one loop iteration. Running this
through opt -loop-unrolling yields:

define void @test(i32* %addr1, i32* %addr2) {
start:
  br label %body

body:                                             ; preds = %start
  %x = load i32, i32* %addr1, !alias.scope !0
  store i32 %x, i32* %addr2, !noalias !0
  %addr1i.1 = getelementptr inbounds i32, i32* %addr1, i32 1
  %addr2i.1 = getelementptr inbounds i32, i32* %addr2, i32 1
  %x.1 = load i32, i32* %addr1i.1, !alias.scope !0
  store i32 %x.1, i32* %addr2i.1, !noalias !0
  %x.2 = load i32, i32* %addr1, !alias.scope !0
  store i32 %x.2, i32* %addr2, !noalias !0
  %addr1i.3 = getelementptr inbounds i32, i32* %addr1, i32 1
  %addr2i.3 = getelementptr inbounds i32, i32* %addr2, i32 1
  %x.3 = load i32, i32* %addr1i.3, !alias.scope !0
  store i32 %x.3, i32* %addr2i.3, !noalias !0
  ret void
}

!0 = !{!1}
!1 = distinct !{!1, !2}
!2 = distinct !{!2}

The loop was fully unrolled, and instructions carrying !noalias and
!alias.scope metadata were duplicated. With this IR, stores from *different*
iterations no longer alias with loads from *different* iterations, which does
not match the original semantics. A miscompile can then be caused by running
through -scoped-noalias -gvn.

The inlining pass has to deal with a similar issue. It has special code to
duplicate !noalias and !alias.scope metadata:
https://github.com/llvm-mirror/llvm/blob/54d4881c352796b18bfe7314662a294754e3a752/lib/Transforms/Utils/InlineFunction.cpp#L801
Something similar is likely necessary in loop unrolling.

Context: This issue has been diagnosed in
https://github.com/rust-lang/rust/issues/54878. Rustc has temporarily disabled
the emission of noalias metadata for mutable references to work around this
problem, see https://github.com/rust-lang/rust/pull/54639.

-- 
You are receiving this mail because:
You are on the CC list for the bug.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-bugs/attachments/20181013/12fff94e/attachment.html>


More information about the llvm-bugs mailing list