[LLVMbugs] [Bug 23603] New: invalid sinking of invariant loads in codegen

bugzilla-daemon at llvm.org bugzilla-daemon at llvm.org
Wed May 20 16:31:34 PDT 2015


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

            Bug ID: 23603
           Summary: invalid sinking of invariant loads in codegen
           Product: libraries
           Version: trunk
          Hardware: PC
                OS: All
            Status: NEW
          Severity: normal
          Priority: P
         Component: Common Code Generator Code
          Assignee: unassignedbugs at nondot.org
          Reporter: sanjoy at playingwithpointers.com
                CC: llvmbugs at cs.uiuc.edu
    Classification: Unclassified

Currently llc -O3 will codegen

```
declare void @g()

define void @f(i32* %x, i32 %c32, i32* %y) {
 entry:
  %v = load i32, i32* %x, !invariant.load !0
  call void @g()
  %c = icmp ne i32 %c32, 0
  br i1 %c, label %left, label %merge

 left:
  store i32 %v, i32* %y
  br label %merge

 merge:
  ret void
}

!0 = !{}
```


to

```
_f:                                     ## @f
    .cfi_startproc
## BB#0:                                ## %entry
    pushq    %rbp
Ltmp0:
    .cfi_def_cfa_offset 16
    pushq    %r14
Ltmp1:
    .cfi_def_cfa_offset 24
    pushq    %rbx
Ltmp2:
    .cfi_def_cfa_offset 32
Ltmp3:
    .cfi_offset %rbx, -32
Ltmp4:
    .cfi_offset %r14, -24
Ltmp5:
    .cfi_offset %rbp, -16
    movq    %rdx, %r14
    movl    %esi, %ebp
    movq    %rdi, %rbx
    callq    _g
    testl    %ebp, %ebp
    je    LBB0_2
## BB#1:                                ## %left
    movl    (%rbx), %eax  <- %v is loaded after the call to @g
    movl    %eax, (%r14)
LBB0_2:                                 ## %merge
    popq    %rbx
    popq    %r14
    popq    %rbp
    retq
    .cfi_endproc
```

This is problematic because the call to @g could have free'ed the
memory %x is based on.  The problematic predicate that allows this is
MachineInstr::isSafeToMove which returns true for invariant loads.

The fundamental problem seems to be that the MachineInstr /
SelectionDAG notion of invariant load is different from the LLVM
IR notion of invariant load with respect to dereferenceability.  The
IR notion of invariant_load only guarantees that all *non-faulting*
invariant loads result in the same value.  The MI notion of invariant
load guarantees that the load can be legally moved to any location
within its containing function.  The MI notion of invariant_load is
stronger than the IR notion of invariant_load -- an MI invariant_load
is an IR invariant_load + a guarantee that the location being loaded
from is dereferenceable throughout the function's (execution)
lifetime.

I think the right fix is to teach SelectionDAGBuilder to lower IR
invariant_loads to MI invariant_loads only if it can prove that the
location being loaded from is dereferenceable throughout the
function's lifetime.

-- 
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/20150520/2742a359/attachment.html>


More information about the llvm-bugs mailing list