1; Test the 'call' instruction and the tailcall variant. 2 3; RUN: llc -march=mips -mcpu=mips32 -relocation-model=pic -mips-tail-calls=1 < %s | FileCheck %s -check-prefixes=ALL,O32,NOT-R6C 4; RUN: llc -march=mips -mcpu=mips32r2 -relocation-model=pic -mips-tail-calls=1 < %s | FileCheck %s -check-prefixes=ALL,O32,NOT-R6C 5; RUN: llc -march=mips -mcpu=mips32r3 -relocation-model=pic -mips-tail-calls=1 < %s | FileCheck %s -check-prefixes=ALL,O32,NOT-R6C 6; RUN: llc -march=mips -mcpu=mips32r5 -relocation-model=pic -mips-tail-calls=1 < %s | FileCheck %s -check-prefixes=ALL,O32,NOT-R6C 7; RUN: llc -march=mips -mcpu=mips32r6 -relocation-model=pic -disable-mips-delay-filler -mips-tail-calls=1 < %s | FileCheck %s -check-prefixes=ALL,O32,R6C 8; RUN: llc -march=mips -mcpu=mips32r6 -relocation-model=pic -mattr=+fp64,+nooddspreg -disable-mips-delay-filler -mips-tail-calls=1 < %s | FileCheck %s -check-prefixes=ALL,O32,R6C 9; RUN: llc -march=mips64 -mcpu=mips4 -relocation-model=pic -mips-tail-calls=1 < %s | FileCheck %s -check-prefixes=ALL,N64,NOT-R6C 10; RUN: llc -march=mips64 -mcpu=mips64 -relocation-model=pic -mips-tail-calls=1 < %s | FileCheck %s -check-prefixes=ALL,N64,NOT-R6C 11; RUN: llc -march=mips64 -mcpu=mips64r2 -relocation-model=pic -mips-tail-calls=1 < %s | FileCheck %s -check-prefixes=ALL,N64,NOT-R6C 12; RUN: llc -march=mips64 -mcpu=mips64r3 -relocation-model=pic -mips-tail-calls=1 < %s | FileCheck %s -check-prefixes=ALL,N64,NOT-R6C 13; RUN: llc -march=mips64 -mcpu=mips64r5 -relocation-model=pic -mips-tail-calls=1 < %s | FileCheck %s -check-prefixes=ALL,N64,NOT-R6C 14; RUN: llc -march=mips64 -mcpu=mips64r6 -relocation-model=pic -disable-mips-delay-filler -mips-tail-calls=1 < %s | FileCheck %s -check-prefixes=ALL,N64,R6C 15; RUN: llc -march=mips -mcpu=mips32 -relocation-model=pic -mips-tail-calls=1 < %s | FileCheck %s -check-prefix=ALL -check-prefix=O32 -check-prefix=NOT-R6C 16; RUN: llc -march=mips -mcpu=mips32r2 -relocation-model=pic -mips-tail-calls=1 < %s | FileCheck %s -check-prefix=ALL -check-prefix=O32 -check-prefix=NOT-R6C 17; RUN: llc -march=mips -mcpu=mips32r3 -relocation-model=pic -mips-tail-calls=1 < %s | FileCheck %s -check-prefix=ALL -check-prefix=O32 -check-prefix=NOT-R6C 18; RUN: llc -march=mips -mcpu=mips32r5 -relocation-model=pic -mips-tail-calls=1 < %s | FileCheck %s -check-prefix=ALL -check-prefix=O32 -check-prefix=NOT-R6C 19; RUN: llc -march=mips -mcpu=mips32r6 -relocation-model=pic -disable-mips-delay-filler -mips-tail-calls=1 < %s | FileCheck %s -check-prefix=ALL -check-prefix=O32 -check-prefix=R6C 20; RUN: llc -march=mips -mcpu=mips32r6 -relocation-model=pic -mattr=+fp64,+nooddspreg -disable-mips-delay-filler -mips-tail-calls=1 < %s | FileCheck %s -check-prefix=ALL -check-prefix=O32 -check-prefix=R6C 21; RUN: llc -march=mips64 -mcpu=mips4 -relocation-model=pic -mips-tail-calls=1 < %s | FileCheck %s -check-prefix=ALL -check-prefix=N64 -check-prefix=NOT-R6C 22; RUN: llc -march=mips64 -mcpu=mips64 -relocation-model=pic -mips-tail-calls=1 < %s | FileCheck %s -check-prefix=ALL -check-prefix=N64 -check-prefix=NOT-R6C 23; RUN: llc -march=mips64 -mcpu=mips64r2 -relocation-model=pic -mips-tail-calls=1 < %s | FileCheck %s -check-prefix=ALL -check-prefix=N64 -check-prefix=NOT-R6C 24; RUN: llc -march=mips64 -mcpu=mips64r3 -relocation-model=pic -mips-tail-calls=1 < %s | FileCheck %s -check-prefix=ALL -check-prefix=N64 -check-prefix=NOT-R6C 25; RUN: llc -march=mips64 -mcpu=mips64r5 -relocation-model=pic -mips-tail-calls=1 < %s | FileCheck %s -check-prefix=ALL -check-prefix=N64 -check-prefix=NOT-R6C 26; RUN: llc -march=mips64 -mcpu=mips64r6 -relocation-model=pic -disable-mips-delay-filler -mips-tail-calls=1 < %s | FileCheck %s -check-prefix=ALL -check-prefix=N64 -check-prefix=R6C 27 28declare void @extern_void_void() 29declare i32 @extern_i32_void() 30declare float @extern_float_void() 31 32define i32 @call_void_void() { 33; ALL-LABEL: call_void_void: 34 35; O32: lw $[[TGT:[0-9]+]], %call16(extern_void_void)($gp) 36 37; N64: ld $[[TGT:[0-9]+]], %call16(extern_void_void)($gp) 38 39; NOT-R6C: jalr $[[TGT]] 40; R6C: jalrc $[[TGT]] 41 42 call void @extern_void_void() 43; R6C: jrc $ra 44 ret i32 0 45} 46 47define i32 @call_i32_void() { 48; ALL-LABEL: call_i32_void: 49 50; O32: lw $[[TGT:[0-9]+]], %call16(extern_i32_void)($gp) 51 52; N64: ld $[[TGT:[0-9]+]], %call16(extern_i32_void)($gp) 53 54; NOT-R6C: jalr $[[TGT]] 55; R6C: jalrc $[[TGT]] 56 57 %1 = call i32 @extern_i32_void() 58 %2 = add i32 %1, 1 59; R6C: jrc $ra 60 ret i32 %2 61} 62 63define float @call_float_void() { 64; ALL-LABEL: call_float_void: 65 66; FIXME: Not sure why we don't use $gp directly on such a simple test. We should 67; look into it at some point. 68; O32: addu $[[GP:[0-9]+]], ${{[0-9]+}}, $25 69; O32: lw $[[TGT:[0-9]+]], %call16(extern_float_void)($[[GP]]) 70 71; N64: ld $[[TGT:[0-9]+]], %call16(extern_float_void)($gp) 72 73; NOT-R6C: jalr $[[TGT]] 74; R6C: jalrc $[[TGT]] 75 76 77 %1 = call float @extern_float_void() 78 %2 = fadd float %1, 1.0 79; R6C: jrc $ra 80 ret float %2 81} 82 83define i32 @indirect_call_void_void(void ()* %addr) { 84; ALL-LABEL: indirect_call_void_void: 85 86; ALL: move $25, $4 87; NOT-R6C: jalr $25 88; R6C: jalrc $25 89 90 call void %addr() 91; R6C: jrc $ra 92 ret i32 0 93} 94 95define i32 @indirect_call_i32_void(i32 ()* %addr) { 96; ALL-LABEL: indirect_call_i32_void: 97 98; ALL: move $25, $4 99; NOT-R6C: jalr $25 100; R6C: jalrc $25 101 102 103 %1 = call i32 %addr() 104 %2 = add i32 %1, 1 105; R6C: jrc $ra 106 ret i32 %2 107} 108 109define float @indirect_call_float_void(float ()* %addr) { 110; ALL-LABEL: indirect_call_float_void: 111 112; ALL: move $25, $4 113; NOT-R6C: jalr $25 114; R6C: jalrc $25 115 116 117 %1 = call float %addr() 118 %2 = fadd float %1, 1.0 119; R6C: jrc $ra 120 ret float %2 121} 122 123; We can't use 'musttail' here because the verifier is too conservative and 124; prohibits any prototype difference. 125define void @tail_indirect_call_void_void(void ()* %addr) { 126; ALL-LABEL: tail_indirect_call_void_void: 127 128; ALL: move $25, $4 129; NOT-R6C: jr $[[TGT]] 130; R6C: jrc $[[TGT]] 131 132 tail call void %addr() 133 ret void 134} 135 136define i32 @tail_indirect_call_i32_void(i32 ()* %addr) { 137; ALL-LABEL: tail_indirect_call_i32_void: 138 139; ALL: move $25, $4 140; NOT-R6C: jr $[[TGT]] 141; R6C: jrc $[[TGT]] 142 143 %1 = tail call i32 %addr() 144 ret i32 %1 145} 146 147define float @tail_indirect_call_float_void(float ()* %addr) { 148; ALL-LABEL: tail_indirect_call_float_void: 149 150; ALL: move $25, $4 151; NOT-R6C: jr $[[TGT]] 152; R6C: jrc $[[TGT]] 153 154 %1 = tail call float %addr() 155 ret float %1 156} 157 158; Check that passing undef as a double value doesn't cause machine code errors 159; for FP64. 160declare hidden void @undef_double(i32 %this, double %volume) unnamed_addr align 2 161 162define hidden void @thunk_undef_double(i32 %this, double %volume) unnamed_addr align 2 { 163; ALL-LABEL: thunk_undef_double: 164; O32: # implicit-def: $a2 165; O32: # implicit-def: $a3 166; NOT-R6C: jr $[[TGT]] 167; R6C: jrc $[[TGT]] 168 169 tail call void @undef_double(i32 undef, double undef) #8 170 ret void 171} 172 173; Check that immediate addresses do not use jal. 174define i32 @jal_only_allows_symbols() { 175; ALL-LABEL: jal_only_allows_symbols: 176 177; ALL-NOT: {{jal }} 178; ALL: addiu $[[TGT:[0-9]+]], $zero, 1234 179; ALL-NOT: {{jal }} 180; NOT-R6C: jalr $[[TGT]] 181; R6C: jalrc $[[TGT]] 182; ALL-NOT: {{jal }} 183 184 call void () inttoptr (i32 1234 to void ()*)() 185; R6C: jrc $ra 186 ret i32 0 187} 188 189