[llvm-bugs] [Bug 42151] New: [GVN] Incorrect transformation if there is a !invariant.load

via llvm-bugs llvm-bugs at lists.llvm.org
Thu Jun 6 01:01:54 PDT 2019


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

            Bug ID: 42151
           Summary: [GVN] Incorrect transformation if there is a
                    !invariant.load
           Product: libraries
           Version: trunk
          Hardware: PC
                OS: Windows NT
            Status: NEW
          Severity: enhancement
          Priority: P
         Component: Scalar Optimizations
          Assignee: unassignedbugs at nondot.org
          Reporter: serguei.katkov at azul.com
                CC: llvm-bugs at lists.llvm.org

The following test shows the incorrect transformation done by GVN if there are
two loads of the same memory and one them is marked as invariant.

According to LangRef:
If a load instruction tagged with the !invariant.load metadata is executed, the
optimizer may assume the memory location referenced by the load contains the
same value at all points in the program where the memory location is known to
be dereferenceable; otherwise, the behavior is undefined.

The key words here is "If a load instruction tagged with the !invariant.load
metadata is executed".

In the example below, if incoming %cmp is always true then invariant load is a
dead runtime code and return value is always equal to 0 (this would be correct
transformation).

If I understand implementation correctly the problem is in caching the result.
When Query load is invariant the result is cached and next time when Query load
is not invariant the cached result is used.

However, invariant property affect the way stores are processed.

The reporducer:
========================================================
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128-ni:1"
target triple = "x86_64-unknown-linux-gnu"

declare void @llvm.memset.p0i8.i8(i8*, i8, i32, i1)
declare void @foo(i8*)

define i8 @test(i1 %cmp) {
entry:
  %p = alloca i8
  %addr = getelementptr inbounds i8, i8* %p, i64 1
  store i8 5, i8* %addr
  br label %header
header:
  %i = phi i8 [0, %entry], [%i.inc, %backedge]
  br i1 %cmp, label %alive, label %dead
dead:
  call void @foo(i8* %p)
  %v = load i8, i8* %addr, !invariant.load !1
  %i.1 = add i8 %i, %v
  br label %alive
alive:
  %i.2 = phi i8 [%i, %header], [%i.1, %dead]
  store i8 -5, i8* %addr
  br label %backedge
backedge:
  call void @llvm.memset.p0i8.i8(i8 * align 1 %p, i8 0, i32 2, i1 false)
  %i.inc = add i8 %i.2, 1
  %cmp.loop = icmp ugt i8 %i.inc, 100
  br i1 %cmp.loop, label %exit, label %header
exit:
  %res = load i8, i8* %addr
  ret i8 %res
}

!1 = !{}
========================================================
$ opt -S -passes=gvn ./repro.ll -debug-only=gvn
GVN iteration: 0
GVN REMOVING NONLOCAL LOAD:   %v = load i8, i8* %addr, !invariant.load !0
GVN removed:   %v = load i8, i8* %addr, !invariant.load !0
GVN removed:   %i.1 = add i8 %i, undef
GVN removed:   %i.2 = phi i8 [ %i, %header ], [ undef, %dead ]
GVN REMOVING NONLOCAL LOAD:   %res = load i8, i8* %addr
GVN removed:   %res = load i8, i8* %addr
GVN iteration: 1
; ModuleID = './repro.ll'
source_filename = "./repro.ll"
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128-ni:1"
target triple = "x86_64-unknown-linux-gnu"

declare void @foo(i8*)

define i8 @test(i1 %cmp) {
entry:
  %p = alloca i8
  %addr = getelementptr inbounds i8, i8* %p, i64 1
  store i8 5, i8* %addr
  br label %header

header:                                           ; preds = %alive, %entry
  %i = phi i8 [ 0, %entry ], [ %i.inc, %alive ]
  br i1 %cmp, label %alive, label %dead

dead:                                             ; preds = %header
  call void @foo(i8* %p)
  br label %alive

alive:                                            ; preds = %dead, %header
  store i8 -5, i8* %addr
  call void @llvm.memset.p0i8.i32(i8* align 1 %p, i8 0, i32 2, i1 false)
  %i.inc = add i8 %i, 1
  %cmp.loop = icmp ugt i8 %i.inc, 100
  br i1 %cmp.loop, label %exit, label %header

exit:                                             ; preds = %alive
  ret i8 undef
}

; Function Attrs: argmemonly nounwind
declare void @llvm.memset.p0i8.i32(i8* nocapture writeonly, i8, i32, i1 immarg)
#0

attributes #0 = { argmemonly nounwind }
========================================================

-- 
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/20190606/2fa14979/attachment.html>


More information about the llvm-bugs mailing list