[llvm-bugs] [Bug 47058] New: musttail emits wrong code for byval

via llvm-bugs llvm-bugs at lists.llvm.org
Sat Aug 8 17:17:53 PDT 2020


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

            Bug ID: 47058
           Summary: musttail emits wrong code for byval
           Product: libraries
           Version: 10.0
          Hardware: PC
                OS: Linux
            Status: NEW
          Severity: enhancement
          Priority: P
         Component: Backend: X86
          Assignee: unassignedbugs at nondot.org
          Reporter: yyc1992 at gmail.com
                CC: craig.topper at gmail.com, llvm-bugs at lists.llvm.org,
                    llvm-dev at redking.me.uk, spatel+llvm at rotateright.com

With the following IR:

```
target datalayout =
"e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-pc-linux-gnu"

%struct.A = type { i32, i32, i32, i32, i32, i32, i8*, i8*, i8*, i8*, i8*, i8*,
i8* }

define dso_local i32 @g(i32 %0, i32 %1, i32 %2, i8* %3, %struct.A*
byval(%struct.A) align 8 %4) local_unnamed_addr {
  %6 = tail call i32 @k(i32 %0)
  %7 = tail call i32 @f(i32 %0, i32 %1, i32 %2, i8* %3, %struct.A* nonnull
byval(%struct.A) align 8 %4)
  ret i32 %7
}

declare i32 @k(i32)

declare i32 @f(i32, i32, i32, i8*, %struct.A* byval(%struct.A) align 8)
```

the emitted assembly with `llc` is (unwind info stripped out)

```
        pushq   %rbp
        pushq   %r15
        pushq   %r14
        pushq   %rbx
        pushq   %rax
        movq    %rcx, %r14
        movl    %edx, %r15d
        movl    %esi, %ebx
        movl    %edi, %ebp
        callq   k
        movl    %ebp, %edi
        movl    %ebx, %esi
        movl    %r15d, %edx
        movq    %r14, %rcx
        addq    $8, %rsp
        popq    %rbx
        popq    %r14
        popq    %r15
        popq    %rbp
        jmp     f                       # TAILCALL
```

which seems correct and is actually a tail call.

However, if `musttail` is used, i.e.

```
target datalayout =
"e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-pc-linux-gnu"

%struct.A = type { i32, i32, i32, i32, i32, i32, i8*, i8*, i8*, i8*, i8*, i8*,
i8* }

define dso_local i32 @g(i32 %0, i32 %1, i32 %2, i8* %3, %struct.A*
byval(%struct.A) align 8 %4) local_unnamed_addr {
  %6 = tail call i32 @k(i32 %0)
  %7 = musttail call i32 @f(i32 %0, i32 %1, i32 %2, i8* %3, %struct.A* nonnull
byval(%struct.A) align 8 %4)
  ret i32 %7
}

declare i32 @k(i32)

declare i32 @f(i32, i32, i32, i8*, %struct.A* byval(%struct.A) align 8)
```

The code produced is then,

```
        pushq   %rbp
        pushq   %r15
        pushq   %r14
        pushq   %rbx
        pushq   %rax
        movq    %rcx, %r14
        movl    %edx, %r15d
        movl    %esi, %ebx
        movl    %edi, %ebp
        callq   k
        leaq    48(%rsp), %rsi
        movl    $10, %ecx
        movq    %rsp, %rdi
        rep;movsq (%rsi), %es:(%rdi)
        leaq    48(%rsp), %rdi
        movl    $10, %ecx
        movq    %rsp, %rsi
        rep;movsq (%rsi), %es:(%rdi)
        movl    %ebp, %edi
        movl    %ebx, %esi
        movl    %r15d, %edx
        movq    %r14, %rcx
        addq    $8, %rsp
        popq    %rbx
        popq    %r14
        popq    %r15
        popq    %rbp
        jmp     f                       # TAILCALL
```

which tries to copy 80 bytes of data from the argument memory onto 48 bytes of
reserved stack space that overwrites the saved register values as well as the
argument values before copying them back causing more damange......

This bug seems to be superficially similar to gcc's
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96539 though gcc merely produced
inefficient code whereas the code produced here is wrong.

-----

`llc -O0` (rather than the default optimization level) produces something worse

```
        subq    $56, %rsp
        .cfi_def_cfa_offset 64
        leaq    64(%rsp), %rax
        movl    %edi, 52(%rsp)          # 4-byte Spill
        movq    %rcx, 40(%rsp)          # 8-byte Spill
        movl    %edx, 36(%rsp)          # 4-byte Spill
        movl    %esi, 32(%rsp)          # 4-byte Spill
        movq    %rax, 24(%rsp)          # 8-byte Spill
        callq   k
        movq    %rsp, %rcx
        movl    $10, %r8d
        movq    %rcx, 16(%rsp)          # 8-byte Spill
        movq    %r8, %rcx
        movq    16(%rsp), %rdi          # 8-byte Reload
        movq    24(%rsp), %rsi          # 8-byte Reload
        rep;movsq (%rsi), %es:(%rdi)
        leaq    64(%rsp), %rdi
        movq    %r8, %rcx
        movq    16(%rsp), %rsi          # 8-byte Reload
        rep;movsq (%rsi), %es:(%rdi)
        movl    52(%rsp), %edi          # 4-byte Reload
        movl    32(%rsp), %esi          # 4-byte Reload
        movl    36(%rsp), %edx          # 4-byte Reload
        movq    40(%rsp), %rcx          # 8-byte Reload
        movl    %eax, 12(%rsp)          # 4-byte Spill
        addq    $56, %rsp
        .cfi_def_cfa_offset 8
        jmp     f                       # TAILCALL
```

which seems to got the source address for the first copy wrong, in additional
to the aliasing issue and the unnecessary copy itself...

-- 
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/20200809/8f59c232/attachment.html>


More information about the llvm-bugs mailing list