[llvm-bugs] [Bug 42733] New: [GVN] Miscompile: incorrect replacement of redundant load with PHIs

via llvm-bugs llvm-bugs at lists.llvm.org
Wed Jul 24 00:20:20 PDT 2019


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

            Bug ID: 42733
           Summary: [GVN] Miscompile: incorrect replacement of redundant
                    load with PHIs
           Product: libraries
           Version: trunk
          Hardware: PC
                OS: Linux
            Status: NEW
          Severity: normal
          Priority: P
         Component: Scalar Optimizations
          Assignee: unassignedbugs at nondot.org
          Reporter: suc-daniil at yandex.ru
                CC: llvm-bugs at lists.llvm.org

In this case GVN eliminates following load:
  %tmp25 = load atomic i64, i64 addrspace(1)* %tmp24 unordered, align 8

by replacing it with a sequence of PHIs and the problem is that the first phi
in this sequence contains undef: 
  bb6:                                              ; preds = %bb19, %bb
    %tmp251 = phi i64 [ undef, %bb ], [ %tmp252, %bb19 ]


This bug is not reproducible without !tbaa metadata on this load:
  %tmp22 = load atomic i64, i64 addrspace(1)* %tmp21 unordered, align 8, !tbaa
!0
even though only BasicAA is used.

>From what I was able to find, it looks like this PHI contains undef because for
some reason MemoryDependenceAnalysis reports incomplete list of dependencies
for that load.


The reproducer:
========================================================
define i64 @foo(i64 addrspace(1)** %arg, i1 %arg1, i1 %arg2, i1 %arg3, i32
%arg4) {
bb:
  %tmp = load atomic i64 addrspace(1)*, i64 addrspace(1)** %arg unordered,
align 8
  %tmp5 = getelementptr inbounds i64, i64 addrspace(1)* %tmp, i64 8
  store atomic i64 0, i64 addrspace(1)* %tmp5 unordered, align 8
  br label %bb6

bb6:                                              ; preds = %bb19, %bb
  %tmp7 = phi i64 [ 0, %bb ], [ %tmp22, %bb19 ]
  br i1 %arg1, label %bb19, label %bb8

bb8:                                              ; preds = %bb6
  %tmp9 = load atomic i64 addrspace(1)*, i64 addrspace(1)** %arg unordered,
align 8
  br i1 %arg2, label %bb11, label %bb10

bb10:                                             ; preds = %bb8
  br label %bb15

bb11:                                             ; preds = %bb8
  br i1 %arg3, label %bb12, label %bb18

bb12:                                             ; preds = %bb11
  %tmp13 = phi i64 addrspace(1)* [ %tmp9, %bb11 ]
  %tmp14 = getelementptr inbounds i64, i64 addrspace(1)* %tmp13, i64 8
  store atomic i64 1, i64 addrspace(1)* %tmp14 unordered, align 8
  ret i64 0

bb15:                                             ; preds = %bb26, %bb10
  %tmp16 = phi i64 addrspace(1)* [ %tmp9, %bb10 ], [ %tmp27, %bb26 ]
  %tmp17 = phi i64 [ %tmp7, %bb10 ], [ 0, %bb26 ]
  switch i32 %arg4, label %bb19 [
    i32 0, label %bb26
    i32 1, label %bb23
  ]

bb18:                                             ; preds = %bb11
  br label %bb19

bb19:                                             ; preds = %bb18, %bb15, %bb6
  %tmp20 = phi i64 addrspace(1)* [ %tmp16, %bb15 ], [ null, %bb6 ], [ %tmp9,
%bb18 ]
  %tmp21 = getelementptr inbounds i64, i64 addrspace(1)* %tmp20, i64 8
  %tmp22 = load atomic i64, i64 addrspace(1)* %tmp21 unordered, align 8, !tbaa
!0
  br label %bb6

bb23:                                             ; preds = %bb15
  %tmp24 = getelementptr inbounds i64, i64 addrspace(1)* %tmp16, i64 8
  %tmp25 = load atomic i64, i64 addrspace(1)* %tmp24 unordered, align 8
  call void @baz(i64 %tmp25) #0
  ret i64 0

bb26:                                             ; preds = %bb15
  call void @bar()
  %tmp27 = load atomic i64 addrspace(1)*, i64 addrspace(1)** %arg unordered,
align 8
  %tmp28 = getelementptr inbounds i64, i64 addrspace(1)* %tmp27, i64 8
  %tmp29 = load atomic i64, i64 addrspace(1)* %tmp28 unordered, align 8
  %tmp30 = getelementptr inbounds i64, i64 addrspace(1)* %tmp27, i64 40
  store atomic i64 %tmp29, i64 addrspace(1)* %tmp30 unordered, align 4
  br label %bb15
}

declare void @bar()

; Function Attrs: inaccessiblememonly readonly
declare void @baz(i64) #0

attributes #0 = { inaccessiblememonly readonly }

!0 = !{!1, !2, i64 8}
!1 = !{!"Name", !2, i64 8}
!2 = !{!"tbaa_local_fields", !3, i64 0}
!3 = !{!"tbaa-access-type"}
========================================================
$ opt -aa-pipeline=basic-aa -passes=gvn -S repro.ll -debug-only=gvn
GVN iteration: 0
GVN: load i64 addrspace(1)* %tmp has unknown dependence
GVN: load i64 addrspace(1)* %tmp9 is clobbered by   store atomic i64 0, i64
addrspace(1)* %tmp5 unordered, align 8
GVN: load i64 addrspace(1)* %tmp9 is clobbered by   store atomic i64 %tmp29,
i64 addrspace(1)* %tmp30 unordered, align 4
GVN: load i64 addrspace(1)* %tmp27 is clobbered by   call void @bar()
GVN: load i64 %tmp29 is clobbered by   call void @bar()
GVN removed:   %tmp13 = phi i64 addrspace(1)* [ %tmp9, %bb11 ]
GVN: load i64 %tmp22 is clobbered by   store atomic i64 0, i64 addrspace(1)*
%tmp5 unordered, align 8
GVN iteration: 1
GVN: load i64 addrspace(1)* %tmp has unknown dependence
GVN: load i64 addrspace(1)* %tmp9 is clobbered by   store atomic i64 0, i64
addrspace(1)* %tmp5 unordered, align 8
GVN: load i64 addrspace(1)* %tmp9 is clobbered by   store atomic i64 %tmp29,
i64 addrspace(1)* %tmp30 unordered, align 4
GVN REMOVING NONLOCAL LOAD:   %tmp25 = load atomic i64, i64 addrspace(1)*
%tmp24 unordered, align 8
GVN removed:   %0 = load atomic i64, i64 addrspace(1)* %tmp24 unordered, align
8
GVN: load i64 addrspace(1)* %tmp27 is clobbered by   call void @bar()
GVN: load i64 %tmp29 is clobbered by   call void @bar()
GVN: load i64 %tmp22 is clobbered by   store atomic i64 0, i64 addrspace(1)*
%tmp5 unordered, align 8
GVN iteration: 2
GVN: load i64 addrspace(1)* %tmp has unknown dependence
GVN: load i64 addrspace(1)* %tmp9 is clobbered by   store atomic i64 0, i64
addrspace(1)* %tmp5 unordered, align 8
GVN: load i64 addrspace(1)* %tmp9 is clobbered by   store atomic i64 %tmp29,
i64 addrspace(1)* %tmp30 unordered, align 4
GVN: load i64 addrspace(1)* %tmp27 is clobbered by   call void @bar()
GVN: load i64 %tmp29 is clobbered by   call void @bar()
GVN: load i64 %tmp22 is clobbered by   store atomic i64 0, i64 addrspace(1)*
%tmp5 unordered, align 8
; ModuleID = 'repro.ll'
source_filename = "repro.ll"

define i64 @foo(i64 addrspace(1)** %arg, i1 %arg1, i1 %arg2, i1 %arg3, i32
%arg4) {
bb:
  %tmp = load atomic i64 addrspace(1)*, i64 addrspace(1)** %arg unordered,
align 8
  %tmp5 = getelementptr inbounds i64, i64 addrspace(1)* %tmp, i64 8
  store atomic i64 0, i64 addrspace(1)* %tmp5 unordered, align 8
  br label %bb6

bb6:                                              ; preds = %bb19, %bb
  %tmp251 = phi i64 [ undef, %bb ], [ %tmp252, %bb19 ]
  %tmp7 = phi i64 [ 0, %bb ], [ %tmp22, %bb19 ]
  br i1 %arg1, label %bb19, label %bb8

bb8:                                              ; preds = %bb6
  %tmp9 = load atomic i64 addrspace(1)*, i64 addrspace(1)** %arg unordered,
align 8
  br i1 %arg2, label %bb11, label %bb10

bb10:                                             ; preds = %bb8
  br label %bb15

bb11:                                             ; preds = %bb8
  br i1 %arg3, label %bb12, label %bb18

bb12:                                             ; preds = %bb11
  %tmp14 = getelementptr inbounds i64, i64 addrspace(1)* %tmp9, i64 8
  store atomic i64 1, i64 addrspace(1)* %tmp14 unordered, align 8
  ret i64 0

bb15:                                             ; preds = %bb26, %bb10
  %tmp25 = phi i64 [ %tmp251, %bb10 ], [ %tmp29, %bb26 ]
  %tmp16 = phi i64 addrspace(1)* [ %tmp9, %bb10 ], [ %tmp27, %bb26 ]
  %tmp17 = phi i64 [ %tmp7, %bb10 ], [ 0, %bb26 ]
  switch i32 %arg4, label %bb19 [
    i32 0, label %bb26
    i32 1, label %bb23
  ]

bb18:                                             ; preds = %bb11
  br label %bb19

bb19:                                             ; preds = %bb18, %bb15, %bb6
  %tmp252 = phi i64 [ %tmp25, %bb15 ], [ %tmp251, %bb6 ], [ %tmp251, %bb18 ]
  %tmp20 = phi i64 addrspace(1)* [ %tmp16, %bb15 ], [ null, %bb6 ], [ %tmp9,
%bb18 ]
  %tmp21 = getelementptr inbounds i64, i64 addrspace(1)* %tmp20, i64 8
  %tmp22 = load atomic i64, i64 addrspace(1)* %tmp21 unordered, align 8, !tbaa
!0
  br label %bb6

bb23:                                             ; preds = %bb15
  %tmp24 = getelementptr inbounds i64, i64 addrspace(1)* %tmp16, i64 8
  call void @baz(i64 %tmp25) #0
  ret i64 0

bb26:                                             ; preds = %bb15
  call void @bar()
  %tmp27 = load atomic i64 addrspace(1)*, i64 addrspace(1)** %arg unordered,
align 8
  %tmp28 = getelementptr inbounds i64, i64 addrspace(1)* %tmp27, i64 8
  %tmp29 = load atomic i64, i64 addrspace(1)* %tmp28 unordered, align 8
  %tmp30 = getelementptr inbounds i64, i64 addrspace(1)* %tmp27, i64 40
  store atomic i64 %tmp29, i64 addrspace(1)* %tmp30 unordered, align 4
  br label %bb15
}

declare void @bar()

; Function Attrs: inaccessiblememonly readonly
declare void @baz(i64) #0

attributes #0 = { inaccessiblememonly readonly }

!0 = !{!1, !2, i64 8}
!1 = !{!"Name", !2, i64 8}
!2 = !{!"tbaa_local_fields", !3, i64 0}
!3 = !{!"tbaa-access-type"}
========================================================

Any further simplification of the reproducer breaks it.

-- 
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/20190724/d4b0baad/attachment-0001.html>


More information about the llvm-bugs mailing list