[llvm-dev] MemorySSA question
Daniel Berlin via llvm-dev
llvm-dev at lists.llvm.org
Tue Dec 19 09:17:38 PST 2017
On Tue, Dec 19, 2017 at 3:13 AM, Venugopal Raghavan via llvm-dev <
llvm-dev at lists.llvm.org> wrote:
> Hi,
>
> I am new to MemorySSA and wanted to understand its capabilities. Hence I
> wrote the following program (test.c):
>
> int N;
>
> void test(int *restrict a, int *restrict b, int *restrict c, int *restrict
> d, int *restrict e) {
> int i;
> for (i = 0; i < N; i = i + 5) {
> a[i] = b[i] + c[i];
> }
>
> for (i = 0; i < N - 5; i = i + 5) {
> e[i] = a[i] * d[i];
> }
> }
>
> I compiled this program using the following commands:
>
> clang -c -o test_clang_out.ll -emit-llvm -O3 test.c
> opt -o test_opt_out.ll -O3 -passes='print<memoryssa>' -disable-output
> test_clang_out.ll > out 2>&1
>
> The relevant parts of the file "out" are shown below:
> .
> .
> .
>
> for.body: ; preds = %
> for.body.lr.ph, %for.body
> ; 3 = MemoryPhi({for.body.lr.ph,liveOnEntry},{for.body,1})
> %indvars.iv35 = phi i64 [ 0, %for.body.lr.ph ], [ %indvars.iv.next36,
> %for.body ]
> %arrayidx = getelementptr inbounds i32, i32* %b, i64 %indvars.iv35
> ; MemoryUse(3)
> %2 = load i32, i32* %arrayidx, align 4, !tbaa !2
> %arrayidx2 = getelementptr inbounds i32, i32* %c, i64 %indvars.iv35
> ; MemoryUse(3)
> %3 = load i32, i32* %arrayidx2, align 4, !tbaa !2
> %add = add nsw i32 %3, %2
> %arrayidx4 = getelementptr inbounds i32, i32* %a, i64 %indvars.iv35
> *; 1 = MemoryDef(3)*
> store i32 %add, i32* %arrayidx4, align 4, !tbaa !2
> %indvars.iv.next36 = add nuw nsw i64 %indvars.iv35, 5
> %cmp = icmp slt i64 %indvars.iv.next36, %1
> br i1 %cmp, label %for.body, label %for.end
>
> for.end: ; preds = %for.body
> %cmp729 = icmp sgt i32 %0, 5
> br i1 %cmp729, label %for.body8.lr.ph, label %for.end17
>
> for.body8.lr.ph: ; preds = %for.end
> %sub = add nsw i32 %0, -5
> %4 = sext i32 %sub to i64
> br label %for.body8
>
> for.body8: ; preds = %
> for.body8.lr.ph, %for.body8
> *; 4 = MemoryPhi({for.body8.lr.ph
> <http://for.body8.lr.ph>,1},{for.body8,2})*
> %indvars.iv = phi i64 [ 0, %for.body8.lr.ph ], [ %indvars.iv.next,
> %for.body8 ]
> %arrayidx10 = getelementptr inbounds i32, i32* %a, i64 %indvars.iv
> *; MemoryUse(4)*
> %5 = load i32, i32* %arrayidx10, align 4, !tbaa !2
> %arrayidx12 = getelementptr inbounds i32, i32* %d, i64 %indvars.iv
> ; MemoryUse(4)
> %6 = load i32, i32* %arrayidx12, align 4, !tbaa !2
> %mul = mul nsw i32 %6, %5
> %arrayidx14 = getelementptr inbounds i32, i32* %e, i64 %indvars.iv
> *; 2 = MemoryDef(4)*
> store i32 %mul, i32* %arrayidx14, align 4, !tbaa !2
> %indvars.iv.next = add nuw nsw i64 %indvars.iv, 5
> %cmp7 = icmp slt i64 %indvars.iv.next, %4
> br i1 %cmp7, label %for.body8, label %for.end17
>
>
>
> I have highlighted the interesting lines in bold.
>
> I was interested in the use of array "a" in the second loop and and wanted
> to check if memorySSA would show the reaching definitions for these uses to
> emanate from the definitions in 1 = MemoryDef(3) and, indeed, the
> MemoryUse(4) corresponding to the use of "a" shows the reaching definition
> to be from the MemoryPhi node 4, which, in turn has one of its reaching
> definitions as 1 = MemoryDef(3). But this MemoryPHi node also has another
> reaching definition which is 2 = MemoryDef(4) which corresponds to the
> definition of array e in the second loop.
>
> Yes, that is correct.
> This seems to make the MemorySSA form imprecise because it seems to
> indicate that the use of "a" in the second loop could be having a reaching
> definition from the definition of "a" in the first loop or the definition
> of "e" in the second loop (through the MemoryPhi). I would have expected
> only the first reaching definition to be inferred.
>
If AA could prove it, MemorySSA would have a MemoryUse(1) instead.
>
> Am I mis-interpreting the information here or mis-understanding the
> capabilities of MemorySSA? If not, can someone explain why the information
> is imprecise? Maybe the underlying alias analysis is unable to disambiguate
> the different arrays? But I would have thought that this would not be a
> difficult case for alias analysis.
>
Here, the underlying AA is unable to distinguish, AFAICT, after some
transformation.
clang -c -o test_clang_out.ll -emit-llvm -O3 test.c -S
bin/opt -print-memoryssa -debug test_clang_out.ll
(note lack of other passes):
; <label>:15: ; preds = %15, %8
; 3 = MemoryPhi({%8,liveOnEntry},{%15,1})
%16 = phi i64 [ 0, %8 ], [ %23, %15 ]
%17 = getelementptr inbounds i32, i32* %1, i64 %16
; MemoryUse(liveOnEntry)
%18 = load i32, i32* %17, align 4, !tbaa !2
%19 = getelementptr inbounds i32, i32* %2, i64 %16
; MemoryUse(liveOnEntry)
%20 = load i32, i32* %19, align 4, !tbaa !2
%21 = add nsw i32 %20, %18
%22 = getelementptr inbounds i32, i32* %0, i64 %16
; 1 = MemoryDef(3)
store i32 %21, i32* %22, align 4, !tbaa !2
%23 = add nuw nsw i64 %16, 5
%24 = icmp slt i64 %23, %9
br i1 %24, label %15, label %10
; <label>:25: ; preds = %25, %12
; 4 = MemoryPhi({%12,1},{%25,2})
%26 = phi i64 [ 0, %12 ], [ %33, %25 ]
%27 = getelementptr inbounds i32, i32* %0, i64 %26
; MemoryUse(1)
%28 = load i32, i32* %27, align 4, !tbaa !2
%29 = getelementptr inbounds i32, i32* %3, i64 %26
; MemoryUse(liveOnEntry)
%30 = load i32, i32* %29, align 4, !tbaa !2
%31 = mul nsw i32 %30, %28
%32 = getelementptr inbounds i32, i32* %4, i64 %26
; 2 = MemoryDef(4)
store i32 %31, i32* %32, align 4, !tbaa !2
%33 = add nuw nsw i64 %26, 5
%34 = icmp slt i64 %33, %14
br i1 %34, label %25, label %35
Note memoryuse reaching back through memoryphi.
MemorySSA is deliberately imprecise for def-def relationships, but this is
not the cause of your issue. Yours is caused by AA not being able to
distinguish anymore.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20171219/b2c2f1c0/attachment.html>
More information about the llvm-dev
mailing list