blob: b96cb2b92398410b771eee16b426bcbc5cd39c8c [file] [log] [blame] [edit]
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: llc -mtriple=mips-unknown-linux-gnu -mips-tail-calls=1 < %s | FileCheck %s --check-prefix=MIPS32
; RUN: llc -mtriple=mips64-unknown-linux-gnu -mips-tail-calls=1 < %s | FileCheck %s --check-prefix=MIPS64
; Test musttail support for MIPS
define dso_local i32 @callee_args(i32 %a, i32 %b, i32 %c) {
ret i32 %a;
}
define i32 @test_musttail_args(i32 %x, i32 %y, i32 %z) {
; MIPS32-LABEL: test_musttail_args:
; MIPS32: # %bb.0:
; MIPS32-NEXT: j callee_args
; MIPS32-NEXT: nop
;
; MIPS64-LABEL: test_musttail_args:
; MIPS64: # %bb.0:
; MIPS64-NEXT: j callee_args
; MIPS64-NEXT: nop
%ret = musttail call i32 @callee_args(i32 %x, i32 %y, i32 %z)
ret i32 %ret
}
; Test musttail with many arguments that spill to stack (involves memory)
; MIPS O32 ABI: first 4 args in $a0-$a3, rest on stack
define hidden i32 @many_args_callee(i32 %a, i32 %b, i32 %c, i32 %d, i32 %e, i32 %f, i32 %g, i32 %h) {
ret i32 %a
}
define i32 @test_musttail_many_args(i32 %a, i32 %b, i32 %c, i32 %d, i32 %e, i32 %f, i32 %g, i32 %h) {
; MIPS32-LABEL: test_musttail_many_args:
; MIPS32: # %bb.0:
; MIPS32-NEXT: lw $1, 24($sp)
; MIPS32-NEXT: lw $2, 20($sp)
; MIPS32-NEXT: lw $3, 16($sp)
; MIPS32-NEXT: sw $3, 16($sp)
; MIPS32-NEXT: sw $2, 20($sp)
; MIPS32-NEXT: sw $1, 24($sp)
; MIPS32-NEXT: lw $1, 28($sp)
; MIPS32-NEXT: j many_args_callee
; MIPS32-NEXT: sw $1, 28($sp)
;
; MIPS64-LABEL: test_musttail_many_args:
; MIPS64: # %bb.0:
; MIPS64-NEXT: j many_args_callee
; MIPS64-NEXT: nop
%ret = musttail call i32 @many_args_callee(i32 %a, i32 %b, i32 %c, i32 %d, i32 %e, i32 %f, i32 %g, i32 %h)
ret i32 %ret
}
; Test musttail with large struct passed by value (involves memory)
%struct.large = type { i32, i32, i32, i32, i32, i32, i32, i32 }
define hidden i32 @callee_with_struct(%struct.large %s, i32 %x) {
ret i32 %x
}
define i32 @test_musttail_struct(%struct.large %s, i32 %x) {
; MIPS32-LABEL: test_musttail_struct:
; MIPS32: # %bb.0:
; MIPS32-NEXT: lw $1, 28($sp)
; MIPS32-NEXT: lw $2, 24($sp)
; MIPS32-NEXT: lw $3, 20($sp)
; MIPS32-NEXT: lw $8, 16($sp)
; MIPS32-NEXT: sw $8, 16($sp)
; MIPS32-NEXT: sw $3, 20($sp)
; MIPS32-NEXT: sw $2, 24($sp)
; MIPS32-NEXT: sw $1, 28($sp)
; MIPS32-NEXT: lw $1, 32($sp)
; MIPS32-NEXT: j callee_with_struct
; MIPS32-NEXT: sw $1, 32($sp)
;
; MIPS64-LABEL: test_musttail_struct:
; MIPS64: # %bb.0:
; MIPS64-NEXT: ld $1, 0($sp)
; MIPS64-NEXT: j callee_with_struct
; MIPS64-NEXT: sd $1, 0($sp)
%ret = musttail call i32 @callee_with_struct(%struct.large %s, i32 %x)
ret i32 %ret
}
; Test musttail with mixed int and float arguments that use stack
define hidden float @mixed_args_callee(i32 %a, float %b, i32 %c, float %d, i32 %e, float %f) {
ret float %b
}
define float @test_musttail_mixed_args(i32 %a, float %b, i32 %c, float %d, i32 %e, float %f) {
; MIPS32-LABEL: test_musttail_mixed_args:
; MIPS32: # %bb.0:
; MIPS32-NEXT: lw $1, 16($sp)
; MIPS32-NEXT: sw $1, 16($sp)
; MIPS32-NEXT: lwc1 $f0, 20($sp)
; MIPS32-NEXT: j mixed_args_callee
; MIPS32-NEXT: swc1 $f0, 20($sp)
;
; MIPS64-LABEL: test_musttail_mixed_args:
; MIPS64: # %bb.0:
; MIPS64-NEXT: j mixed_args_callee
; MIPS64-NEXT: nop
%ret = musttail call float @mixed_args_callee(i32 %a, float %b, i32 %c, float %d, i32 %e, float %f)
ret float %ret
}
; Test musttail with indirect call
define i32 @test_musttail_fptr(ptr %fptr, i32 %x) {
; MIPS32-LABEL: test_musttail_fptr:
; MIPS32: # %bb.0:
; MIPS32-NEXT: move $25, $4
; MIPS32-NEXT: jr $25
; MIPS32-NEXT: nop
;
; MIPS64-LABEL: test_musttail_fptr:
; MIPS64: # %bb.0:
; MIPS64-NEXT: move $25, $4
; MIPS64-NEXT: jr $25
; MIPS64-NEXT: nop
%ret = musttail call i32 %fptr(ptr %fptr, i32 %x)
ret i32 %ret
}