1; RUN: llc %s -o - -mtriple=thumbv8m.base | FileCheck %s 2 3declare i32 @g(...) 4 5declare i32 @h0(i32, i32, i32, i32) 6define hidden i32 @f0() { 7 %1 = tail call i32 bitcast (i32 (...)* @g to i32 ()*)() 8 %2 = tail call i32 @h0(i32 %1, i32 1, i32 2, i32 3) 9 ret i32 %2 10; CHECK-LABEL: f0 11; CHECK: ldr [[POP:r[4567]]], [sp, #4] 12; CHECK-NEXT: mov lr, [[POP]] 13; CHECK-NEXT: pop {{.*}}[[POP]] 14; CHECK-NEXT: add sp, #4 15; CHECK-NEXT: b h0 16} 17 18declare i32 @h1(i32) 19define hidden i32 @f1() { 20 %1 = tail call i32 bitcast (i32 (...)* @g to i32 ()*)() 21 %2 = tail call i32 @h1(i32 %1) 22 ret i32 %2 23; CHECK-LABEL: f1 24; CHECK: pop {r7} 25; CHECK: pop {r1} 26; CHECK: mov lr, r1 27; CHECK: b h1 28} 29 30declare i32 @h2(i32, i32, i32, i32, i32) 31define hidden i32 @f2(i32, i32, i32, i32, i32) { 32 %6 = tail call i32 bitcast (i32 (...)* @g to i32 ()*)() 33 %7 = icmp eq i32 %6, 0 34 br i1 %7, label %10, label %8 35 36 %9 = tail call i32 @h2(i32 %6, i32 %1, i32 %2, i32 %3, i32 %4) 37 br label %10 38 39 %11 = phi i32 [ %9, %8 ], [ -1, %5 ] 40 ret i32 %11 41; CHECK-LABEL: f2 42; CHECK: ldr [[POP:r[4567]]], [sp, #12] 43; CHECK-NEXT: mov lr, [[POP]] 44; CHECK-NEXT: pop {{.*}}[[POP]] 45; CHECK-NEXT: add sp, #4 46; CHECK-NEXT: b h2 47} 48 49; Make sure that tail calls to function pointers that require r0-r3 for argument 50; passing do not break the compiler. 51@fnptr = global i32 (i32, i32, i32, i32)* null 52define i32 @test3() { 53; CHECK-LABEL: test3: 54; CHECK: blx {{r[0-9]+}} 55 %1 = load i32 (i32, i32, i32, i32)*, i32 (i32, i32, i32, i32)** @fnptr 56 %2 = tail call i32 %1(i32 1, i32 2, i32 3, i32 4) 57 ret i32 %2 58} 59 60@fnptr2 = global i32 (i32, i32, i64)* null 61define i32 @test4() { 62; CHECK-LABEL: test4: 63; CHECK: blx {{r[0-9]+}} 64 %1 = load i32 (i32, i32, i64)*, i32 (i32, i32, i64)** @fnptr2 65 %2 = tail call i32 %1(i32 1, i32 2, i64 3) 66 ret i32 %2 67} 68 69; Check that tail calls to function pointers where not all of r0-r3 are used for 70; parameter passing are tail-call optimized. 71; test5: params in r0, r1. r2 & r3 are free. 72@fnptr3 = global i32 (i32, i32)* null 73define i32 @test5() { 74; CHECK-LABEL: test5: 75; CHECK: ldr [[REG:r[0-9]+]] 76; CHECK: bx [[REG]] 77; CHECK-NOT: blx [[REG]] 78 %1 = load i32 (i32, i32)*, i32 (i32, i32)** @fnptr3 79 %2 = tail call i32 %1(i32 1, i32 2) 80 ret i32 %2 81} 82 83; test6: params in r0 and r2-r3. r1 is free. 84@fnptr4 = global i32 (i32, i64)* null 85define i32 @test6() { 86; CHECK-LABEL: test6: 87; CHECK: ldr [[REG:r[0-9]+]] 88; CHECK: bx [[REG]] 89; CHECK-NOT: blx [[REG]] 90 %1 = load i32 (i32, i64)*, i32 (i32, i64)** @fnptr4 91 %2 = tail call i32 %1(i32 1, i64 2) 92 ret i32 %2 93} 94 95; Check that tail calls to functions other than function pointers are 96; tail-call optimized. 97define i32 @test7() { 98; CHECK-LABEL: test7: 99; CHECK: b bar 100; CHECK-NOT: bl bar 101 %tail = tail call i32 @bar(i32 1, i32 2, i32 3, i32 4) 102 ret i32 %tail 103} 104 105declare i32 @bar(i32, i32, i32, i32) 106 107; Regression test for failure to load indirect branch target (class tcGPR) from 108; a stack slot. 109%struct.S = type { i32 } 110 111define void @test8(i32 (i32, i32, i32)* nocapture %fn, i32 %x) local_unnamed_addr { 112entry: 113 %call = tail call %struct.S* bitcast (%struct.S* (...)* @test8_u to %struct.S* ()*)() 114 %a = getelementptr inbounds %struct.S, %struct.S* %call, i32 0, i32 0 115 %0 = load i32, i32* %a, align 4 116 %call1 = tail call i32 @test8_h(i32 0) 117 %call2 = tail call i32 @test8_g(i32 %0, i32 %call1, i32 0) 118 store i32 %x, i32* %a, align 4 119 %call4 = tail call i32 %fn(i32 1, i32 2, i32 3) 120 ret void 121} 122 123declare %struct.S* @test8_u(...) 124 125declare i32 @test8_g(i32, i32, i32) 126 127declare i32 @test8_h(i32) 128; CHECK: str r0, [sp] @ 4-byte Spill 129; CHECK: ldr r3, [sp] @ 4-byte Reload 130; CHECK: bx r3 131