1; Test the 'call' instruction and the tailcall variant. 2 3; FIXME: We should remove the need for -enable-mips-tail-calls 4; RUN: llc -march=mips -mcpu=mips32 -enable-mips-tail-calls < %s | FileCheck %s -check-prefix=ALL -check-prefix=O32 5; RUN: llc -march=mips -mcpu=mips32r2 -enable-mips-tail-calls < %s | FileCheck %s -check-prefix=ALL -check-prefix=O32 6; RUN: llc -march=mips -mcpu=mips32r3 -enable-mips-tail-calls < %s | FileCheck %s -check-prefix=ALL -check-prefix=O32 7; RUN: llc -march=mips -mcpu=mips32r5 -enable-mips-tail-calls < %s | FileCheck %s -check-prefix=ALL -check-prefix=O32 8; RUN: llc -march=mips -mcpu=mips32r6 -enable-mips-tail-calls < %s | FileCheck %s -check-prefix=ALL -check-prefix=O32 9; RUN: llc -march=mips64 -mcpu=mips4 -enable-mips-tail-calls < %s | FileCheck %s -check-prefix=ALL -check-prefix=N64 10; RUN: llc -march=mips64 -mcpu=mips64 -enable-mips-tail-calls < %s | FileCheck %s -check-prefix=ALL -check-prefix=N64 11; RUN: llc -march=mips64 -mcpu=mips64r2 -enable-mips-tail-calls < %s | FileCheck %s -check-prefix=ALL -check-prefix=N64 12; RUN: llc -march=mips64 -mcpu=mips64r3 -enable-mips-tail-calls < %s | FileCheck %s -check-prefix=ALL -check-prefix=N64 13; RUN: llc -march=mips64 -mcpu=mips64r5 -enable-mips-tail-calls < %s | FileCheck %s -check-prefix=ALL -check-prefix=N64 14; RUN: llc -march=mips64 -mcpu=mips64r6 -enable-mips-tail-calls < %s | FileCheck %s -check-prefix=ALL -check-prefix=N64 15 16declare void @extern_void_void() 17declare i32 @extern_i32_void() 18declare float @extern_float_void() 19 20define i32 @call_void_void() { 21; ALL-LABEL: call_void_void: 22 23; O32: lw $[[TGT:[0-9]+]], %call16(extern_void_void)($gp) 24 25; N64: ld $[[TGT:[0-9]+]], %call16(extern_void_void)($gp) 26 27; ALL: jalr $[[TGT]] 28 29 call void @extern_void_void() 30 ret i32 0 31} 32 33define i32 @call_i32_void() { 34; ALL-LABEL: call_i32_void: 35 36; O32: lw $[[TGT:[0-9]+]], %call16(extern_i32_void)($gp) 37 38; N64: ld $[[TGT:[0-9]+]], %call16(extern_i32_void)($gp) 39 40; ALL: jalr $[[TGT]] 41 42 %1 = call i32 @extern_i32_void() 43 %2 = add i32 %1, 1 44 ret i32 %2 45} 46 47define float @call_float_void() { 48; ALL-LABEL: call_float_void: 49 50; FIXME: Not sure why we don't use $gp directly on such a simple test. We should 51; look into it at some point. 52; O32: addu $[[GP:[0-9]+]], ${{[0-9]+}}, $25 53; O32: lw $[[TGT:[0-9]+]], %call16(extern_float_void)($[[GP]]) 54 55; N64: ld $[[TGT:[0-9]+]], %call16(extern_float_void)($gp) 56 57; ALL: jalr $[[TGT]] 58 59; O32: move $gp, $[[GP]] 60 61 %1 = call float @extern_float_void() 62 %2 = fadd float %1, 1.0 63 ret float %2 64} 65 66define void @musttail_call_void_void() { 67; ALL-LABEL: musttail_call_void_void: 68 69; O32: lw $[[TGT:[0-9]+]], %call16(extern_void_void)($gp) 70 71; N64: ld $[[TGT:[0-9]+]], %call16(extern_void_void)($gp) 72 73; NOT-R6: jr $[[TGT]] 74; R6: r6.jr $[[TGT]] 75 76 musttail call void @extern_void_void() 77 ret void 78} 79 80define i32 @musttail_call_i32_void() { 81; ALL-LABEL: musttail_call_i32_void: 82 83; O32: lw $[[TGT:[0-9]+]], %call16(extern_i32_void)($gp) 84 85; N64: ld $[[TGT:[0-9]+]], %call16(extern_i32_void)($gp) 86 87; NOT-R6: jr $[[TGT]] 88; R6: r6.jr $[[TGT]] 89 90 %1 = musttail call i32 @extern_i32_void() 91 ret i32 %1 92} 93 94define float @musttail_call_float_void() { 95; ALL-LABEL: musttail_call_float_void: 96 97; O32: lw $[[TGT:[0-9]+]], %call16(extern_float_void)($gp) 98 99; N64: ld $[[TGT:[0-9]+]], %call16(extern_float_void)($gp) 100 101; NOT-R6: jr $[[TGT]] 102; R6: r6.jr $[[TGT]] 103 104 %1 = musttail call float @extern_float_void() 105 ret float %1 106} 107 108define i32 @indirect_call_void_void(void ()* %addr) { 109; ALL-LABEL: indirect_call_void_void: 110 111; ALL: move $25, $4 112; ALL: jalr $25 113 114 call void %addr() 115 ret i32 0 116} 117 118define i32 @indirect_call_i32_void(i32 ()* %addr) { 119; ALL-LABEL: indirect_call_i32_void: 120 121; ALL: move $25, $4 122; ALL: jalr $25 123 124 %1 = call i32 %addr() 125 %2 = add i32 %1, 1 126 ret i32 %2 127} 128 129define float @indirect_call_float_void(float ()* %addr) { 130; ALL-LABEL: indirect_call_float_void: 131 132; ALL: move $25, $4 133; ALL: jalr $25 134 135 %1 = call float %addr() 136 %2 = fadd float %1, 1.0 137 ret float %2 138} 139 140; We can't use 'musttail' here because the verifier is too conservative and 141; prohibits any prototype difference. 142define void @tail_indirect_call_void_void(void ()* %addr) { 143; ALL-LABEL: tail_indirect_call_void_void: 144 145; ALL: move $25, $4 146; ALL: jr $25 147 148 tail call void %addr() 149 ret void 150} 151 152define i32 @tail_indirect_call_i32_void(i32 ()* %addr) { 153; ALL-LABEL: tail_indirect_call_i32_void: 154 155; ALL: move $25, $4 156; ALL: jr $25 157 158 %1 = tail call i32 %addr() 159 ret i32 %1 160} 161 162define float @tail_indirect_call_float_void(float ()* %addr) { 163; ALL-LABEL: tail_indirect_call_float_void: 164 165; ALL: move $25, $4 166; ALL: jr $25 167 168 %1 = tail call float %addr() 169 ret float %1 170} 171