| ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py |
| ; RUN: llc -mtriple=thumbv7-linux-gnueabihf %s -o - | FileCheck %s |
| ; RUN: llc -mtriple=thumbv7-linux-gnueabi %s -o - | FileCheck -check-prefix=SOFTFLOAT %s |
| ; RUN: llc -mtriple=thumbv7-linux-gnueabihf -disable-tail-calls %s -o - | FileCheck -check-prefix=HF-NOTAIL %s |
| |
| ; On hard-float targets, the register used to store a float return value |
| ; changes if the call signature is varargs. The HF-NOTAIL lines are there to |
| ; easily see when this happens. |
| |
| declare float @callee_float() |
| declare i32 @callee_int() |
| declare float @callee_float_vararg(i32, ...) |
| declare i32 @callee_int_vararg(i32, ...) |
| |
| define float @caller_float__callee_float() { |
| ; CHECK-LABEL: caller_float__callee_float: |
| ; CHECK: @ %bb.0: |
| ; CHECK-NEXT: b callee_float |
| ; |
| ; SOFTFLOAT-LABEL: caller_float__callee_float: |
| ; SOFTFLOAT: @ %bb.0: |
| ; SOFTFLOAT-NEXT: b callee_float |
| ; |
| ; HF-NOTAIL-LABEL: caller_float__callee_float: |
| ; HF-NOTAIL: @ %bb.0: |
| ; HF-NOTAIL-NEXT: .save {r7, lr} |
| ; HF-NOTAIL-NEXT: push {r7, lr} |
| ; HF-NOTAIL-NEXT: bl callee_float |
| ; HF-NOTAIL-NEXT: pop {r7, pc} |
| %r = tail call float @callee_float() |
| ret float %r |
| } |
| |
| define float @caller_float__callee_float_vararg() { |
| ; CHECK-LABEL: caller_float__callee_float_vararg: |
| ; CHECK: @ %bb.0: |
| ; CHECK-NEXT: .save {r7, lr} |
| ; CHECK-NEXT: push {r7, lr} |
| ; CHECK-NEXT: movs r0, #0 |
| ; CHECK-NEXT: bl callee_float_vararg |
| ; CHECK-NEXT: vmov s0, r0 |
| ; CHECK-NEXT: pop {r7, pc} |
| ; |
| ; SOFTFLOAT-LABEL: caller_float__callee_float_vararg: |
| ; SOFTFLOAT: @ %bb.0: |
| ; SOFTFLOAT-NEXT: movs r0, #0 |
| ; SOFTFLOAT-NEXT: b callee_float_vararg |
| ; |
| ; HF-NOTAIL-LABEL: caller_float__callee_float_vararg: |
| ; HF-NOTAIL: @ %bb.0: |
| ; HF-NOTAIL-NEXT: .save {r7, lr} |
| ; HF-NOTAIL-NEXT: push {r7, lr} |
| ; HF-NOTAIL-NEXT: movs r0, #0 |
| ; HF-NOTAIL-NEXT: bl callee_float_vararg |
| ; HF-NOTAIL-NEXT: vmov s0, r0 |
| ; HF-NOTAIL-NEXT: pop {r7, pc} |
| %r = tail call float (i32, ...) @callee_float_vararg(i32 0) |
| ret float %r |
| } |
| |
| define float @caller_float_vararg__callee_float(i32, ...) { |
| ; CHECK-LABEL: caller_float_vararg__callee_float: |
| ; CHECK: @ %bb.0: |
| ; CHECK-NEXT: .save {r7, lr} |
| ; CHECK-NEXT: push {r7, lr} |
| ; CHECK-NEXT: bl callee_float |
| ; CHECK-NEXT: vmov r0, s0 |
| ; CHECK-NEXT: pop {r7, pc} |
| ; |
| ; SOFTFLOAT-LABEL: caller_float_vararg__callee_float: |
| ; SOFTFLOAT: @ %bb.0: |
| ; SOFTFLOAT-NEXT: b callee_float |
| ; |
| ; HF-NOTAIL-LABEL: caller_float_vararg__callee_float: |
| ; HF-NOTAIL: @ %bb.0: |
| ; HF-NOTAIL-NEXT: .save {r7, lr} |
| ; HF-NOTAIL-NEXT: push {r7, lr} |
| ; HF-NOTAIL-NEXT: bl callee_float |
| ; HF-NOTAIL-NEXT: vmov r0, s0 |
| ; HF-NOTAIL-NEXT: pop {r7, pc} |
| %r = tail call float @callee_float() |
| ret float %r |
| } |
| |
| define float @caller_float_vararg__callee_float_vararg(i32, ...) { |
| ; CHECK-LABEL: caller_float_vararg__callee_float_vararg: |
| ; CHECK: @ %bb.0: |
| ; CHECK-NEXT: movs r0, #0 |
| ; CHECK-NEXT: b callee_float_vararg |
| ; |
| ; SOFTFLOAT-LABEL: caller_float_vararg__callee_float_vararg: |
| ; SOFTFLOAT: @ %bb.0: |
| ; SOFTFLOAT-NEXT: movs r0, #0 |
| ; SOFTFLOAT-NEXT: b callee_float_vararg |
| ; |
| ; HF-NOTAIL-LABEL: caller_float_vararg__callee_float_vararg: |
| ; HF-NOTAIL: @ %bb.0: |
| ; HF-NOTAIL-NEXT: .save {r7, lr} |
| ; HF-NOTAIL-NEXT: push {r7, lr} |
| ; HF-NOTAIL-NEXT: movs r0, #0 |
| ; HF-NOTAIL-NEXT: bl callee_float_vararg |
| ; HF-NOTAIL-NEXT: pop {r7, pc} |
| %r = tail call float (i32, ...) @callee_float_vararg(i32 0) |
| ret float %r |
| } |
| |
| define i32 @caller_int__callee_int() { |
| ; CHECK-LABEL: caller_int__callee_int: |
| ; CHECK: @ %bb.0: |
| ; CHECK-NEXT: b callee_int |
| ; |
| ; SOFTFLOAT-LABEL: caller_int__callee_int: |
| ; SOFTFLOAT: @ %bb.0: |
| ; SOFTFLOAT-NEXT: b callee_int |
| ; |
| ; HF-NOTAIL-LABEL: caller_int__callee_int: |
| ; HF-NOTAIL: @ %bb.0: |
| ; HF-NOTAIL-NEXT: .save {r7, lr} |
| ; HF-NOTAIL-NEXT: push {r7, lr} |
| ; HF-NOTAIL-NEXT: bl callee_int |
| ; HF-NOTAIL-NEXT: pop {r7, pc} |
| %r = tail call i32 @callee_int() |
| ret i32 %r |
| } |
| |
| define i32 @caller_int__callee_int_vararg() { |
| ; CHECK-LABEL: caller_int__callee_int_vararg: |
| ; CHECK: @ %bb.0: |
| ; CHECK-NEXT: movs r0, #0 |
| ; CHECK-NEXT: b callee_int_vararg |
| ; |
| ; SOFTFLOAT-LABEL: caller_int__callee_int_vararg: |
| ; SOFTFLOAT: @ %bb.0: |
| ; SOFTFLOAT-NEXT: movs r0, #0 |
| ; SOFTFLOAT-NEXT: b callee_int_vararg |
| ; |
| ; HF-NOTAIL-LABEL: caller_int__callee_int_vararg: |
| ; HF-NOTAIL: @ %bb.0: |
| ; HF-NOTAIL-NEXT: .save {r7, lr} |
| ; HF-NOTAIL-NEXT: push {r7, lr} |
| ; HF-NOTAIL-NEXT: movs r0, #0 |
| ; HF-NOTAIL-NEXT: bl callee_int_vararg |
| ; HF-NOTAIL-NEXT: pop {r7, pc} |
| %r = tail call i32 (i32, ...) @callee_int_vararg(i32 0) |
| ret i32 %r |
| } |
| |
| define i32 @caller_int_vararg__callee_int(i32, ...) { |
| ; CHECK-LABEL: caller_int_vararg__callee_int: |
| ; CHECK: @ %bb.0: |
| ; CHECK-NEXT: b callee_int |
| ; |
| ; SOFTFLOAT-LABEL: caller_int_vararg__callee_int: |
| ; SOFTFLOAT: @ %bb.0: |
| ; SOFTFLOAT-NEXT: b callee_int |
| ; |
| ; HF-NOTAIL-LABEL: caller_int_vararg__callee_int: |
| ; HF-NOTAIL: @ %bb.0: |
| ; HF-NOTAIL-NEXT: .save {r7, lr} |
| ; HF-NOTAIL-NEXT: push {r7, lr} |
| ; HF-NOTAIL-NEXT: bl callee_int |
| ; HF-NOTAIL-NEXT: pop {r7, pc} |
| %r = tail call i32 @callee_int() |
| ret i32 %r |
| } |
| |
| define i32 @caller_int_vararg__callee_int_vararg(i32, ...) { |
| ; CHECK-LABEL: caller_int_vararg__callee_int_vararg: |
| ; CHECK: @ %bb.0: |
| ; CHECK-NEXT: movs r0, #0 |
| ; CHECK-NEXT: b callee_int_vararg |
| ; |
| ; SOFTFLOAT-LABEL: caller_int_vararg__callee_int_vararg: |
| ; SOFTFLOAT: @ %bb.0: |
| ; SOFTFLOAT-NEXT: movs r0, #0 |
| ; SOFTFLOAT-NEXT: b callee_int_vararg |
| ; |
| ; HF-NOTAIL-LABEL: caller_int_vararg__callee_int_vararg: |
| ; HF-NOTAIL: @ %bb.0: |
| ; HF-NOTAIL-NEXT: .save {r7, lr} |
| ; HF-NOTAIL-NEXT: push {r7, lr} |
| ; HF-NOTAIL-NEXT: movs r0, #0 |
| ; HF-NOTAIL-NEXT: bl callee_int_vararg |
| ; HF-NOTAIL-NEXT: pop {r7, pc} |
| %r = tail call i32 (i32, ...) @callee_int_vararg(i32 0) |
| ret i32 %r |
| } |