; 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) { ; MIPS32-LABEL: callee_args: ; MIPS32: # %bb.0: ; MIPS32-NEXT: jr $ra ; MIPS32-NEXT: move $2, $4 ; ; MIPS64-LABEL: callee_args: ; MIPS64: # %bb.0: ; MIPS64-NEXT: jr $ra ; MIPS64-NEXT: sll $2, $4, 0 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) { ; MIPS32-LABEL: many_args_callee: ; MIPS32: # %bb.0: ; MIPS32-NEXT: jr $ra ; MIPS32-NEXT: move $2, $4 ; ; MIPS64-LABEL: many_args_callee: ; MIPS64: # %bb.0: ; MIPS64-NEXT: jr $ra ; MIPS64-NEXT: sll $2, $4, 0 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) { ; MIPS32-LABEL: callee_with_struct: ; MIPS32: # %bb.0: ; MIPS32-NEXT: lw $2, 32($sp) ; MIPS32-NEXT: jr $ra ; MIPS32-NEXT: nop ; ; MIPS64-LABEL: callee_with_struct: ; MIPS64: # %bb.0: ; MIPS64-NEXT: lw $2, 4($sp) ; MIPS64-NEXT: jr $ra ; MIPS64-NEXT: nop 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) { ; MIPS32-LABEL: mixed_args_callee: ; MIPS32: # %bb.0: ; MIPS32-NEXT: jr $ra ; MIPS32-NEXT: mtc1 $5, $f0 ; ; MIPS64-LABEL: mixed_args_callee: ; MIPS64: # %bb.0: ; MIPS64-NEXT: jr $ra ; MIPS64-NEXT: mov.s $f0, $f13 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 }