1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py 2; RUN: llc < %s -mtriple=sparc -verify-machineinstrs | FileCheck %s 3 4define i32 @simple_leaf(i32 %i) #0 { 5; CHECK-LABEL: simple_leaf: 6; CHECK: ! %bb.0: ! %entry 7; CHECK-NEXT: mov %o7, %g1 8; CHECK-NEXT: call foo 9; CHECK-NEXT: mov %g1, %o7 10entry: 11 %call = tail call i32 @foo(i32 %i) 12 ret i32 %call 13} 14 15define i32 @simple_standard(i32 %i) #1 { 16; CHECK-LABEL: simple_standard: 17; CHECK: ! %bb.0: ! %entry 18; CHECK-NEXT: save %sp, -96, %sp 19; CHECK-NEXT: call foo 20; CHECK-NEXT: restore 21entry: 22 %call = tail call i32 @foo(i32 %i) 23 ret i32 %call 24} 25 26define i32 @extra_arg_leaf(i32 %i) #0 { 27; CHECK-LABEL: extra_arg_leaf: 28; CHECK: ! %bb.0: ! %entry 29; CHECK-NEXT: mov 12, %o1 30; CHECK-NEXT: mov %o7, %g1 31; CHECK-NEXT: call foo2 32; CHECK-NEXT: mov %g1, %o7 33entry: 34 %call = tail call i32 @foo2(i32 %i, i32 12) 35 ret i32 %call 36} 37 38define i32 @extra_arg_standard(i32 %i) #1 { 39; CHECK-LABEL: extra_arg_standard: 40; CHECK: ! %bb.0: ! %entry 41; CHECK-NEXT: save %sp, -96, %sp 42; CHECK-NEXT: call foo2 43; CHECK-NEXT: restore %g0, 12, %o1 44entry: 45 %call = tail call i32 @foo2(i32 %i, i32 12) 46 ret i32 %call 47} 48 49; Perform tail call optimization for external symbol. 50 51define void @caller_extern(i8* %src) optsize #0 { 52; CHECK-LABEL: caller_extern: 53; CHECK: ! %bb.0: ! %entry 54; CHECK-NEXT: sethi %hi(dest), %o1 55; CHECK-NEXT: add %o1, %lo(dest), %o1 56; CHECK-NEXT: mov 7, %o2 57; CHECK-NEXT: mov %o0, %o3 58; CHECK-NEXT: mov %o1, %o0 59; CHECK-NEXT: mov %o3, %o1 60; CHECK-NEXT: mov %o7, %g1 61; CHECK-NEXT: call memcpy 62; CHECK-NEXT: mov %g1, %o7 63entry: 64 tail call void @llvm.memcpy.p0i8.p0i8.i32( 65 i8* getelementptr inbounds ([2 x i8], 66 [2 x i8]* @dest, i32 0, i32 0), 67 i8* %src, i32 7, i1 false) 68 ret void 69} 70 71; Perform tail call optimization for function pointer. 72 73define i32 @func_ptr_test(i32 ()* nocapture %func_ptr) #0 { 74; CHECK-LABEL: func_ptr_test: 75; CHECK: ! %bb.0: ! %entry 76; CHECK-NEXT: jmp %o0 77; CHECK-NEXT: nop 78entry: 79 %call = tail call i32 %func_ptr() #1 80 ret i32 %call 81} 82 83define i32 @func_ptr_test2(i32 (i32, i32, i32)* nocapture %func_ptr, 84; CHECK-LABEL: func_ptr_test2: 85; CHECK: ! %bb.0: ! %entry 86; CHECK-NEXT: save %sp, -96, %sp 87; CHECK-NEXT: mov 10, %i3 88; CHECK-NEXT: mov %i0, %i4 89; CHECK-NEXT: mov %i1, %i0 90; CHECK-NEXT: jmp %i4 91; CHECK-NEXT: restore %g0, %i3, %o1 92 i32 %r, i32 %q) #1 { 93entry: 94 %call = tail call i32 %func_ptr(i32 %r, i32 10, i32 %q) #1 95 ret i32 %call 96} 97 98 99; Do not tail call optimize if stack is used to pass parameters. 100 101define i32 @caller_args() #0 { 102; CHECK-LABEL: caller_args: 103; CHECK: ! %bb.0: ! %entry 104; CHECK-NEXT: save %sp, -104, %sp 105; CHECK-NEXT: mov 6, %i0 106; CHECK-NEXT: mov %g0, %o0 107; CHECK-NEXT: mov 1, %o1 108; CHECK-NEXT: mov 2, %o2 109; CHECK-NEXT: mov 3, %o3 110; CHECK-NEXT: mov 4, %o4 111; CHECK-NEXT: mov 5, %o5 112; CHECK-NEXT: call foo7 113; CHECK-NEXT: st %i0, [%sp+92] 114; CHECK-NEXT: ret 115; CHECK-NEXT: restore %g0, %o0, %o0 116entry: 117 %r = tail call i32 @foo7(i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6) 118 ret i32 %r 119} 120 121; Byval parameters hand the function a pointer directly into the stack area 122; we want to reuse during a tail call. Do not tail call optimize functions with 123; byval parameters. 124 125define i32 @caller_byval() #0 { 126; CHECK-LABEL: caller_byval: 127; CHECK: ! %bb.0: ! %entry 128; CHECK-NEXT: save %sp, -104, %sp 129; CHECK-NEXT: ld [%fp+-4], %i0 130; CHECK-NEXT: st %i0, [%fp+-8] 131; CHECK-NEXT: call callee_byval 132; CHECK-NEXT: add %fp, -8, %o0 133; CHECK-NEXT: ret 134; CHECK-NEXT: restore %g0, %o0, %o0 135entry: 136 %a = alloca i32* 137 %r = tail call i32 @callee_byval(i32** byval(i32*) %a) 138 ret i32 %r 139} 140 141; Perform tail call optimization for sret function. 142 143define void @sret_test(%struct.a* noalias sret(%struct.a) %agg.result) #0 { 144; CHECK-LABEL: sret_test: 145; CHECK: ! %bb.0: ! %entry 146; CHECK-NEXT: mov %o7, %g1 147; CHECK-NEXT: call sret_func 148; CHECK-NEXT: mov %g1, %o7 149entry: 150 tail call void bitcast (void (%struct.a*)* @sret_func to 151 void (%struct.a*)*)(%struct.a* sret(%struct.a) %agg.result) 152 ret void 153} 154 155; Do not tail call if either caller or callee returns 156; a struct and the other does not. Returning a large 157; struct will generate a memcpy as the tail function. 158 159define void @ret_large_struct(%struct.big* noalias sret(%struct.big) %agg.result) #0 { 160; CHECK-LABEL: ret_large_struct: 161; CHECK: ! %bb.0: ! %entry 162; CHECK-NEXT: save %sp, -96, %sp 163; CHECK-NEXT: ld [%fp+64], %i0 164; CHECK-NEXT: sethi %hi(bigstruct), %i1 165; CHECK-NEXT: add %i1, %lo(bigstruct), %o1 166; CHECK-NEXT: mov 400, %o2 167; CHECK-NEXT: call memcpy 168; CHECK-NEXT: mov %i0, %o0 169; CHECK-NEXT: jmp %i7+12 170; CHECK-NEXT: restore 171entry: 172 %0 = bitcast %struct.big* %agg.result to i8* 173 tail call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 4 %0, i8* align 4 bitcast (%struct.big* @bigstruct to i8*), i32 400, i1 false) 174 ret void 175} 176 177; Test register + immediate pattern. 178 179define void @addri_test(i32 %ptr) #0 { 180; CHECK-LABEL: addri_test: 181; CHECK: ! %bb.0: ! %entry 182; CHECK-NEXT: jmp %o0+4 183; CHECK-NEXT: nop 184entry: 185 %add = add nsw i32 %ptr, 4 186 %0 = inttoptr i32 %add to void ()* 187 tail call void %0() #1 188 ret void 189} 190 191%struct.a = type { i32, i32 } 192@dest = global [2 x i8] zeroinitializer 193 194%struct.big = type { [100 x i32] } 195@bigstruct = global %struct.big zeroinitializer 196 197declare void @llvm.memcpy.p0i8.p0i8.i32(i8*, i8*, i32, i1) 198declare void @sret_func(%struct.a* sret(%struct.a)) 199declare i32 @callee_byval(i32** byval(i32*) %a) 200declare i32 @foo(i32) 201declare i32 @foo2(i32, i32) 202declare i32 @foo7(i32, i32, i32, i32, i32, i32, i32) 203 204attributes #0 = { nounwind "disable-tail-calls"="false" 205 "frame-pointer"="none" } 206attributes #1 = { nounwind "disable-tail-calls"="false" 207 "frame-pointer"="all" } 208