1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py 2; RUN: llc -mtriple=thumbv7-linux-gnueabihf %s -o - | FileCheck %s 3; RUN: llc -mtriple=thumbv7-linux-gnueabi %s -o - | FileCheck -check-prefix=SOFTFLOAT %s 4; RUN: llc -mtriple=thumbv7-linux-gnueabihf -disable-tail-calls %s -o - | FileCheck -check-prefix=HF-NOTAIL %s 5 6; On hard-float targets, the register used to store a float return value 7; changes if the call signature is varargs. The HF-NOTAIL lines are there to 8; easily see when this happens. 9 10declare float @callee_float() 11declare i32 @callee_int() 12declare float @callee_float_vararg(i32, ...) 13declare i32 @callee_int_vararg(i32, ...) 14 15define float @caller_float__callee_float() { 16; CHECK-LABEL: caller_float__callee_float: 17; CHECK: @ %bb.0: 18; CHECK-NEXT: b callee_float 19; 20; SOFTFLOAT-LABEL: caller_float__callee_float: 21; SOFTFLOAT: @ %bb.0: 22; SOFTFLOAT-NEXT: b callee_float 23; 24; HF-NOTAIL-LABEL: caller_float__callee_float: 25; HF-NOTAIL: @ %bb.0: 26; HF-NOTAIL-NEXT: .save {r7, lr} 27; HF-NOTAIL-NEXT: push {r7, lr} 28; HF-NOTAIL-NEXT: bl callee_float 29; HF-NOTAIL-NEXT: pop {r7, pc} 30 %r = tail call float @callee_float() 31 ret float %r 32} 33 34define float @caller_float__callee_float_vararg() { 35; CHECK-LABEL: caller_float__callee_float_vararg: 36; CHECK: @ %bb.0: 37; CHECK-NEXT: .save {r7, lr} 38; CHECK-NEXT: push {r7, lr} 39; CHECK-NEXT: movs r0, #0 40; CHECK-NEXT: bl callee_float_vararg 41; CHECK-NEXT: vmov s0, r0 42; CHECK-NEXT: pop {r7, pc} 43; 44; SOFTFLOAT-LABEL: caller_float__callee_float_vararg: 45; SOFTFLOAT: @ %bb.0: 46; SOFTFLOAT-NEXT: movs r0, #0 47; SOFTFLOAT-NEXT: b callee_float_vararg 48; 49; HF-NOTAIL-LABEL: caller_float__callee_float_vararg: 50; HF-NOTAIL: @ %bb.0: 51; HF-NOTAIL-NEXT: .save {r7, lr} 52; HF-NOTAIL-NEXT: push {r7, lr} 53; HF-NOTAIL-NEXT: movs r0, #0 54; HF-NOTAIL-NEXT: bl callee_float_vararg 55; HF-NOTAIL-NEXT: vmov s0, r0 56; HF-NOTAIL-NEXT: pop {r7, pc} 57 %r = tail call float (i32, ...) @callee_float_vararg(i32 0) 58 ret float %r 59} 60 61define float @caller_float_vararg__callee_float(i32, ...) { 62; CHECK-LABEL: caller_float_vararg__callee_float: 63; CHECK: @ %bb.0: 64; CHECK-NEXT: .save {r7, lr} 65; CHECK-NEXT: push {r7, lr} 66; CHECK-NEXT: bl callee_float 67; CHECK-NEXT: vmov r0, s0 68; CHECK-NEXT: pop {r7, pc} 69; 70; SOFTFLOAT-LABEL: caller_float_vararg__callee_float: 71; SOFTFLOAT: @ %bb.0: 72; SOFTFLOAT-NEXT: b callee_float 73; 74; HF-NOTAIL-LABEL: caller_float_vararg__callee_float: 75; HF-NOTAIL: @ %bb.0: 76; HF-NOTAIL-NEXT: .save {r7, lr} 77; HF-NOTAIL-NEXT: push {r7, lr} 78; HF-NOTAIL-NEXT: bl callee_float 79; HF-NOTAIL-NEXT: vmov r0, s0 80; HF-NOTAIL-NEXT: pop {r7, pc} 81 %r = tail call float @callee_float() 82 ret float %r 83} 84 85define float @caller_float_vararg__callee_float_vararg(i32, ...) { 86; CHECK-LABEL: caller_float_vararg__callee_float_vararg: 87; CHECK: @ %bb.0: 88; CHECK-NEXT: movs r0, #0 89; CHECK-NEXT: b callee_float_vararg 90; 91; SOFTFLOAT-LABEL: caller_float_vararg__callee_float_vararg: 92; SOFTFLOAT: @ %bb.0: 93; SOFTFLOAT-NEXT: movs r0, #0 94; SOFTFLOAT-NEXT: b callee_float_vararg 95; 96; HF-NOTAIL-LABEL: caller_float_vararg__callee_float_vararg: 97; HF-NOTAIL: @ %bb.0: 98; HF-NOTAIL-NEXT: .save {r7, lr} 99; HF-NOTAIL-NEXT: push {r7, lr} 100; HF-NOTAIL-NEXT: movs r0, #0 101; HF-NOTAIL-NEXT: bl callee_float_vararg 102; HF-NOTAIL-NEXT: pop {r7, pc} 103 %r = tail call float (i32, ...) @callee_float_vararg(i32 0) 104 ret float %r 105} 106 107define i32 @caller_int__callee_int() { 108; CHECK-LABEL: caller_int__callee_int: 109; CHECK: @ %bb.0: 110; CHECK-NEXT: b callee_int 111; 112; SOFTFLOAT-LABEL: caller_int__callee_int: 113; SOFTFLOAT: @ %bb.0: 114; SOFTFLOAT-NEXT: b callee_int 115; 116; HF-NOTAIL-LABEL: caller_int__callee_int: 117; HF-NOTAIL: @ %bb.0: 118; HF-NOTAIL-NEXT: .save {r7, lr} 119; HF-NOTAIL-NEXT: push {r7, lr} 120; HF-NOTAIL-NEXT: bl callee_int 121; HF-NOTAIL-NEXT: pop {r7, pc} 122 %r = tail call i32 @callee_int() 123 ret i32 %r 124} 125 126define i32 @caller_int__callee_int_vararg() { 127; CHECK-LABEL: caller_int__callee_int_vararg: 128; CHECK: @ %bb.0: 129; CHECK-NEXT: movs r0, #0 130; CHECK-NEXT: b callee_int_vararg 131; 132; SOFTFLOAT-LABEL: caller_int__callee_int_vararg: 133; SOFTFLOAT: @ %bb.0: 134; SOFTFLOAT-NEXT: movs r0, #0 135; SOFTFLOAT-NEXT: b callee_int_vararg 136; 137; HF-NOTAIL-LABEL: caller_int__callee_int_vararg: 138; HF-NOTAIL: @ %bb.0: 139; HF-NOTAIL-NEXT: .save {r7, lr} 140; HF-NOTAIL-NEXT: push {r7, lr} 141; HF-NOTAIL-NEXT: movs r0, #0 142; HF-NOTAIL-NEXT: bl callee_int_vararg 143; HF-NOTAIL-NEXT: pop {r7, pc} 144 %r = tail call i32 (i32, ...) @callee_int_vararg(i32 0) 145 ret i32 %r 146} 147 148define i32 @caller_int_vararg__callee_int(i32, ...) { 149; CHECK-LABEL: caller_int_vararg__callee_int: 150; CHECK: @ %bb.0: 151; CHECK-NEXT: b callee_int 152; 153; SOFTFLOAT-LABEL: caller_int_vararg__callee_int: 154; SOFTFLOAT: @ %bb.0: 155; SOFTFLOAT-NEXT: b callee_int 156; 157; HF-NOTAIL-LABEL: caller_int_vararg__callee_int: 158; HF-NOTAIL: @ %bb.0: 159; HF-NOTAIL-NEXT: .save {r7, lr} 160; HF-NOTAIL-NEXT: push {r7, lr} 161; HF-NOTAIL-NEXT: bl callee_int 162; HF-NOTAIL-NEXT: pop {r7, pc} 163 %r = tail call i32 @callee_int() 164 ret i32 %r 165} 166 167define i32 @caller_int_vararg__callee_int_vararg(i32, ...) { 168; CHECK-LABEL: caller_int_vararg__callee_int_vararg: 169; CHECK: @ %bb.0: 170; CHECK-NEXT: movs r0, #0 171; CHECK-NEXT: b callee_int_vararg 172; 173; SOFTFLOAT-LABEL: caller_int_vararg__callee_int_vararg: 174; SOFTFLOAT: @ %bb.0: 175; SOFTFLOAT-NEXT: movs r0, #0 176; SOFTFLOAT-NEXT: b callee_int_vararg 177; 178; HF-NOTAIL-LABEL: caller_int_vararg__callee_int_vararg: 179; HF-NOTAIL: @ %bb.0: 180; HF-NOTAIL-NEXT: .save {r7, lr} 181; HF-NOTAIL-NEXT: push {r7, lr} 182; HF-NOTAIL-NEXT: movs r0, #0 183; HF-NOTAIL-NEXT: bl callee_int_vararg 184; HF-NOTAIL-NEXT: pop {r7, pc} 185 %r = tail call i32 (i32, ...) @callee_int_vararg(i32 0) 186 ret i32 %r 187} 188