mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-08-26 07:29:55 +00:00
Currently, musttail codegen is relying on sibcall optimization, and reporting a fatal error if fails. Sibcall optimization fails when stack arguments need to be modified, which is insufficient for musttail. The logic for moving arguments in memory safely is already implemented for GuaranteedTailCallOpt. This change merely arranges for musttail calls to use it. No functional change for GuaranteedTailCallOpt. Reviewers: espindola Differential Revision: http://reviews.llvm.org/D3493 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@207598 91177308-0d34-0410-b5e6-96231b3b80d8
91 lines
2.3 KiB
LLVM
91 lines
2.3 KiB
LLVM
; RUN: llc -march=x86 < %s | FileCheck %s
|
|
; RUN: llc -march=x86 -O0 < %s | FileCheck %s
|
|
; RUN: llc -march=x86 -disable-tail-calls < %s | FileCheck %s
|
|
|
|
declare void @t1_callee(i8*)
|
|
define void @t1(i32* %a) {
|
|
; CHECK-LABEL: t1:
|
|
; CHECK: jmp {{_?}}t1_callee
|
|
%b = bitcast i32* %a to i8*
|
|
musttail call void @t1_callee(i8* %b)
|
|
ret void
|
|
}
|
|
|
|
declare i8* @t2_callee()
|
|
define i32* @t2() {
|
|
; CHECK-LABEL: t2:
|
|
; CHECK: jmp {{_?}}t2_callee
|
|
%v = musttail call i8* @t2_callee()
|
|
%w = bitcast i8* %v to i32*
|
|
ret i32* %w
|
|
}
|
|
|
|
; Complex frame layout: stack realignment with dynamic alloca.
|
|
define void @t3(i32 %n) alignstack(32) nounwind {
|
|
entry:
|
|
; CHECK: t3:
|
|
; CHECK: pushl %ebp
|
|
; CHECK: pushl %esi
|
|
; CHECK: andl $-32, %esp
|
|
; CHECK: movl %esp, %esi
|
|
; CHECK: popl %esi
|
|
; CHECK: popl %ebp
|
|
; CHECK-NEXT: jmp {{_?}}t3_callee
|
|
%a = alloca i8, i32 %n
|
|
call void @capture(i8* %a)
|
|
musttail call void @t3_callee(i32 %n) nounwind
|
|
ret void
|
|
}
|
|
|
|
declare void @capture(i8*)
|
|
declare void @t3_callee(i32)
|
|
|
|
; Test that we actually copy in and out stack arguments that aren't forwarded
|
|
; without modification.
|
|
define i32 @t4({}* %fn, i32 %n, i32 %r) {
|
|
; CHECK-LABEL: t4:
|
|
; CHECK: incl %[[r:.*]]
|
|
; CHECK: decl %[[n:.*]]
|
|
; CHECK: movl %[[r]], {{[0-9]+}}(%esp)
|
|
; CHECK: movl %[[n]], {{[0-9]+}}(%esp)
|
|
; CHECK: jmpl *%{{.*}}
|
|
|
|
entry:
|
|
%r1 = add i32 %r, 1
|
|
%n1 = sub i32 %n, 1
|
|
%fn_cast = bitcast {}* %fn to i32 ({}*, i32, i32)*
|
|
%r2 = musttail call i32 %fn_cast({}* %fn, i32 %n1, i32 %r1)
|
|
ret i32 %r2
|
|
}
|
|
|
|
; Combine the complex stack frame with the parameter modification.
|
|
define i32 @t5({}* %fn, i32 %n, i32 %r) alignstack(32) {
|
|
; CHECK-LABEL: t5:
|
|
; CHECK: pushl %ebp
|
|
; CHECK: movl %esp, %ebp
|
|
; CHECK: pushl %esi
|
|
; Align the stack.
|
|
; CHECK: andl $-32, %esp
|
|
; CHECK: movl %esp, %esi
|
|
; Modify the args.
|
|
; CHECK: incl %[[r:.*]]
|
|
; CHECK: decl %[[n:.*]]
|
|
; Store them through ebp, since that's the only stable arg pointer.
|
|
; CHECK: movl %[[r]], {{[0-9]+}}(%ebp)
|
|
; CHECK: movl %[[n]], {{[0-9]+}}(%ebp)
|
|
; Epilogue.
|
|
; CHECK: leal {{[-0-9]+}}(%ebp), %esp
|
|
; CHECK: popl %esi
|
|
; CHECK: popl %ebp
|
|
; CHECK: jmpl *%{{.*}}
|
|
|
|
entry:
|
|
%a = alloca i8, i32 %n
|
|
call void @capture(i8* %a)
|
|
%r1 = add i32 %r, 1
|
|
%n1 = sub i32 %n, 1
|
|
%fn_cast = bitcast {}* %fn to i32 ({}*, i32, i32)*
|
|
%r2 = musttail call i32 %fn_cast({}* %fn, i32 %n1, i32 %r1)
|
|
ret i32 %r2
|
|
}
|