| ; 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 |
| } |