summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
authorPablo Barrio <pablo.barrio@arm.com>2017-12-04 16:55:49 +0000
committerPablo Barrio <pablo.barrio@arm.com>2017-12-04 16:55:49 +0000
commit93356784e0e357e3f1f74d565480cc9c25ea4bc9 (patch)
treecf9bae09ce0e9c8c265005c595bd3675310a9c30 /test
parent3f2a29c060fb22c270cbfb4f6ad62b614d59ed13 (diff)
Fix function pointer tail calls in armv8-M.base
Summary: The compiler fails with the following error message: fatal error: error in backend: ran out of registers during register allocation Tail call optimization for Armv8-M.base fails to meet all the required constraints when handling calls to function pointers where the arguments take up r0-r3. This is because the pointer to the function to be called can only be stored in r0-r3, but these are all occupied by arguments. This patch makes sure that tail call optimization does not try to handle this type of calls. Reviewers: chill, MatzeB, olista01, rengolin, efriedma Reviewed By: olista01, efriedma Subscribers: efriedma, aemerson, javed.absar, llvm-commits, kristof.beyls Differential Revision: https://reviews.llvm.org/D40706 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@319664 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'test')
-rw-r--r--test/CodeGen/ARM/v8m-tail-call.ll58
1 files changed, 58 insertions, 0 deletions
diff --git a/test/CodeGen/ARM/v8m-tail-call.ll b/test/CodeGen/ARM/v8m-tail-call.ll
index c369df0c022..96438dc5e64 100644
--- a/test/CodeGen/ARM/v8m-tail-call.ll
+++ b/test/CodeGen/ARM/v8m-tail-call.ll
@@ -45,3 +45,61 @@ define hidden i32 @f2(i32, i32, i32, i32, i32) {
; CHECK-NEXT: add sp, #4
; CHECK-NEXT: b h2
}
+
+; Make sure that tail calls to function pointers that require r0-r3 for argument
+; passing do not break the compiler.
+@fnptr = global i32 (i32, i32, i32, i32)* null
+define i32 @test3() {
+; CHECK-LABEL: test3:
+; CHECK: blx {{r[0-9]+}}
+ %1 = load i32 (i32, i32, i32, i32)*, i32 (i32, i32, i32, i32)** @fnptr
+ %2 = tail call i32 %1(i32 1, i32 2, i32 3, i32 4)
+ ret i32 %2
+}
+
+@fnptr2 = global i32 (i32, i32, i64)* null
+define i32 @test4() {
+; CHECK-LABEL: test4:
+; CHECK: blx {{r[0-9]+}}
+ %1 = load i32 (i32, i32, i64)*, i32 (i32, i32, i64)** @fnptr2
+ %2 = tail call i32 %1(i32 1, i32 2, i64 3)
+ ret i32 %2
+}
+
+; Check that tail calls to function pointers where not all of r0-r3 are used for
+; parameter passing are tail-call optimized.
+; test5: params in r0, r1. r2 & r3 are free.
+@fnptr3 = global i32 (i32, i32)* null
+define i32 @test5() {
+; CHECK-LABEL: test5:
+; CHECK: ldr [[REG:r[0-9]+]]
+; CHECK: bx [[REG]]
+; CHECK-NOT: blx [[REG]]
+ %1 = load i32 (i32, i32)*, i32 (i32, i32)** @fnptr3
+ %2 = tail call i32 %1(i32 1, i32 2)
+ ret i32 %2
+}
+
+; test6: params in r0 and r2-r3. r1 is free.
+@fnptr4 = global i32 (i32, i64)* null
+define i32 @test6() {
+; CHECK-LABEL: test6:
+; CHECK: ldr [[REG:r[0-9]+]]
+; CHECK: bx [[REG]]
+; CHECK-NOT: blx [[REG]]
+ %1 = load i32 (i32, i64)*, i32 (i32, i64)** @fnptr4
+ %2 = tail call i32 %1(i32 1, i64 2)
+ ret i32 %2
+}
+
+; Check that tail calls to functions other than function pointers are
+; tail-call optimized.
+define i32 @test7() {
+; CHECK-LABEL: test7:
+; CHECK: b bar
+; CHECK-NOT: bl bar
+ %tail = tail call i32 @bar(i32 1, i32 2, i32 3, i32 4)
+ ret i32 %tail
+}
+
+declare i32 @bar(i32, i32, i32, i32)