[llvm] r287219 - [ARM] Relax restriction on variadic functions for tailcall optimization

Pablo Barrio via llvm-commits llvm-commits at lists.llvm.org
Thu Nov 17 02:56:59 PST 2016


Author: pabbar01
Date: Thu Nov 17 04:56:58 2016
New Revision: 287219

URL: http://llvm.org/viewvc/llvm-project?rev=287219&view=rev
Log:
[ARM] Relax restriction on variadic functions for tailcall optimization

Summary:
Variadic functions can be treated in the same way as normal functions
with respect to the number and types of parameters.

Reviewers: grosbach, olista01, t.p.northover, rengolin

Subscribers: javed.absar, aemerson, llvm-commits

Differential Revision: https://reviews.llvm.org/D26748

Added:
    llvm/trunk/test/CodeGen/ARM/tail-call-float.ll
Modified:
    llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp
    llvm/trunk/test/CodeGen/ARM/tail-call.ll

Modified: llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp?rev=287219&r1=287218&r2=287219&view=diff
==============================================================================
--- llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp (original)
+++ llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp Thu Nov 17 04:56:58 2016
@@ -2314,11 +2314,6 @@ ARMTargetLowering::IsEligibleForTailCall
   // Look for obvious safe cases to perform tail call optimization that do not
   // require ABI changes. This is what gcc calls sibcall.
 
-  // Do not sibcall optimize vararg calls unless the call site is not passing
-  // any arguments.
-  if (isVarArg && !Outs.empty())
-    return false;
-
   // Exception-handling functions need a special set of instructions to indicate
   // a return to the hardware. Tail-calling another function would probably
   // break this.

Added: llvm/trunk/test/CodeGen/ARM/tail-call-float.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/ARM/tail-call-float.ll?rev=287219&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/ARM/tail-call-float.ll (added)
+++ llvm/trunk/test/CodeGen/ARM/tail-call-float.ll Thu Nov 17 04:56:58 2016
@@ -0,0 +1,49 @@
+; RUN: llc -mtriple armv7 -target-abi aapcs -float-abi soft -O0 -o - < %s \
+; RUN:   | FileCheck %s -check-prefix CHECK-SOFT -check-prefix CHECK
+; RUN: llc -mtriple armv7 -target-abi aapcs -float-abi hard -O0 -o - < %s \
+; RUN:   | FileCheck %s -check-prefix CHECK-HARD -check-prefix CHECK
+
+; Tests for passing floating-point regs. Variadic functions will always use
+; general-purpose registers. Standard functions will use the floating-point
+; registers if there is hardware FP available.
+
+declare i1 @non_variadic(float, float, float, float)
+declare i1 @non_variadic_big(float, float, float, float, float, float)
+declare i1 @variadic(float, ...)
+
+define void @non_variadic_fp(float %x, float %y) {
+; CHECK-LABEL: non_variadic_fp:
+; CHECK: b non_variadic
+entry:
+  %call = tail call i1 (float, float, float, float) @non_variadic(float %y, float %x, float %x, float %y)
+  ret void
+}
+
+define void @variadic_fp(float %x, float %y) {
+; CHECK-LABEL: variadic_fp:
+; CHECK: b variadic
+entry:
+  %call = tail call i1 (float, ...) @variadic(float %y, float %x, float %x, float %y)
+  ret void
+}
+
+; With soft-float, general-purpose registers are used and there are not enough
+; of them to handle the 6 arguments. With hard-float, we have plenty of regs
+; (s0-s15) to pass FP arguments.
+define void @non_variadic_fp_big(float %x, float %y) {
+; CHECK-LABEL: non_variadic_fp_big:
+; CHECK-SOFT: bl non_variadic_big
+; CHECK-HARD: b non_variadic_big
+entry:
+  %call = tail call i1 (float, float, float, float, float, float) @non_variadic_big(float %y, float %x, float %x, float %y, float %x, float %y)
+  ret void
+}
+
+; Variadic functions cannot use FP regs to pass arguments; only GP regs.
+define void @variadic_fp_big(float %x, float %y) {
+; CHECK-LABEL: variadic_fp_big:
+; CHECK: bl variadic
+entry:
+  %call = tail call i1 (float, ...) @variadic(float %y, float %x, float %x, float %y, float %x, float %y)
+  ret void
+}

Modified: llvm/trunk/test/CodeGen/ARM/tail-call.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/ARM/tail-call.ll?rev=287219&r1=287218&r2=287219&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/ARM/tail-call.ll (original)
+++ llvm/trunk/test/CodeGen/ARM/tail-call.ll Thu Nov 17 04:56:58 2016
@@ -1,7 +1,9 @@
 ; RUN: llc -mtriple armv7 -target-abi apcs -O0 -o - < %s \
-; RUN:   | FileCheck %s -check-prefix CHECK-TAIL
+; RUN:   | FileCheck %s -check-prefix CHECK-TAIL -check-prefix CHECK
 ; RUN: llc -mtriple armv7 -target-abi apcs -O0 -disable-tail-calls -o - < %s \
-; RUN:   | FileCheck %s -check-prefix CHECK-NO-TAIL
+; RUN:   | FileCheck %s -check-prefix CHECK-NO-TAIL -check-prefix CHECK
+; RUN: llc -mtriple armv7 -target-abi aapcs -O0 -o - < %s \
+; RUN:   | FileCheck %s -check-prefix CHECK-TAIL-AAPCS -check-prefix CHECK
 
 declare i32 @callee(i32 %i)
 declare extern_weak fastcc void @callee_weak()
@@ -30,3 +32,69 @@ define fastcc void @caller_weak() {
   tail call void @callee_weak()
   ret void
 }
+
+; A tail call can be optimized if all the arguments can be passed in registers
+; R0-R3, or the remaining arguments are already in the caller's parameter area
+; in the stack. Variadic functions are no different.
+declare i32 @variadic(i32, ...)
+
+; e.g. four integers
+define void @v_caller_ints1(i32 %a, i32 %b) {
+; CHECK-LABEL: v_caller_ints1:
+; CHECK-TAIL: b variadic
+; CHECK-TAIL-AAPCS: b variadic
+; CHECK-NO-TAIL: bl variadic
+entry:
+  %call = tail call i32 (i32, ...) @variadic(i32 %a, i32 %b, i32 %b, i32 %a)
+  ret void
+}
+
+; e.g. two 32-bit integers, one 64-bit integer (needs to span two regs)
+define void @v_caller_ints2(i32 %y, i64 %z) {
+; CHECK-LABEL: v_caller_ints2:
+; CHECK-TAIL: b variadic
+; CHECK-TAIL-AAPCS: b variadic
+; CHECK-NO-TAIL: bl variadic
+entry:
+  %call = tail call i32 (i32, ...) @variadic(i32 %y, i32 %y, i64 %z)
+  ret void
+}
+
+; e.g. two 32-bit integers, one 64-bit integer (needs to span two regs). Notice
+; that %z is passed in r1-r2 if APCS is used, contrary to AAPCS where r2-r3
+; would be used (since double-word types must start at an even register). In the
+; latter case, the third argument needs to be passed through the stack.
+define void @v_caller_ints3(i32 %y, i64 %z) {
+; CHECK-LABEL: v_caller_ints3:
+; CHECK-TAIL: b variadic
+; CHECK-TAIL-AAPCS: bl variadic
+; CHECK-NO-TAIL: bl variadic
+entry:
+  %call = tail call i32 (i32, ...) @variadic(i32 %y, i64 %z, i32 %y)
+  ret void
+}
+
+; e.g. two 32-bit integers, one 64-bit integer and another 64-bit integer that
+; doesn't fit in r0-r3 but comes from the caller argument list and is in the
+; same position.
+define void @v_caller_ints4(i64 %a, i32 %b, i32 %c, i64 %d) {
+; CHECK-LABEL: v_caller_ints4:
+; CHECK-TAIL: b variadic
+; CHECK-TAIL-AAPCS: b variadic
+; CHECK-NO-TAIL: bl variadic
+entry:
+  %call = tail call i32 (i32, ...) @variadic(i32 %b, i32 %c, i64 %a, i64 %d)
+  ret void
+}
+
+; If the arguments do not fit in r0-r3 and the existing parameters cannot be
+; taken from the caller's parameter region, the optimization is not supported.
+
+; e.g. one 32-bit integer, two 64-bit integers
+define void @v_caller_ints_fail(i32 %y, i64 %z) {
+; CHECK-LABEL: v_caller_ints_fail:
+; CHECK: bl variadic
+entry:
+  %call = tail call i32 (i32, ...) @variadic(i32 %y, i64 %z, i64 %z)
+  ret void
+}




More information about the llvm-commits mailing list