forked from swiftlang/llvm-project
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[AArch64][GlobalISel] Teach AArch64CallLowering to handle basic sibli…
…ng calls This adds support for basic sibling call lowering in AArch64. The intent here is to only handle tail calls which do not change the ABI (hence, sibling calls.) At this point, it is very restricted. It does not handle - Vararg calls. - Calls with outgoing arguments. - Calls whose calling conventions differ from the caller's calling convention. - Tail/sibling calls with BTI enabled. This patch adds - `AArch64CallLowering::isEligibleForTailCallOptimization`, which is equivalent to the same function in AArch64ISelLowering.cpp (albeit with the restrictions above.) - `mayTailCallThisCC` and `canGuaranteeTCO`, which are identical to those in AArch64ISelLowering.cpp. - `getCallOpcode`, which is exactly what it sounds like. Tail/sibling calls are lowered by checking if they pass target-independent tail call positioning checks, and checking if they satisfy `isEligibleForTailCallOptimization`. If they do, then a tail call instruction is emitted instead of a normal call. If we have a sibling call (which is always the case in this patch), then we do not emit any stack adjustment operations. When we go to lower a return, we check if we've already emitted a tail call. If so, then we skip the return lowering. For testing, this patch - Adds call-translator-tail-call.ll to test which tail calls we currently lower, which ones we don't, and which ones we shouldn't. - Updates branch-target-enforcement-indirect-calls.ll to show that we fall back as expected. Differential Revision: https://reviews.llvm.org/D67189 llvm-svn: 370996
- Loading branch information
Jessica Paquette
committed
Sep 4, 2019
1 parent
4be6706
commit b78324f
Showing
7 changed files
with
321 additions
and
9 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
134 changes: 134 additions & 0 deletions
134
llvm/test/CodeGen/AArch64/GlobalISel/call-translator-tail-call.ll
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,134 @@ | ||
; NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py | ||
; RUN: llc %s -stop-after=irtranslator -verify-machineinstrs -mtriple aarch64-apple-darwin -global-isel -o - 2>&1 | FileCheck %s --check-prefixes=DARWIN,COMMON | ||
; RUN: llc %s -stop-after=irtranslator -verify-machineinstrs -mtriple aarch64-windows -global-isel -o - 2>&1 | FileCheck %s --check-prefixes=WINDOWS,COMMON | ||
|
||
declare void @simple_fn() | ||
define void @tail_call() { | ||
; COMMON-LABEL: name: tail_call | ||
; COMMON: bb.1 (%ir-block.0): | ||
; COMMON: TCRETURNdi @simple_fn, 0, csr_aarch64_aapcs, implicit $sp | ||
tail call void @simple_fn() | ||
ret void | ||
} | ||
|
||
; We should get a TCRETURNri here. | ||
; FIXME: We don't need the COPY. | ||
define void @indirect_tail_call(void()* %func) { | ||
; COMMON-LABEL: name: indirect_tail_call | ||
; COMMON: bb.1 (%ir-block.0): | ||
; COMMON: liveins: $x0 | ||
; COMMON: [[COPY:%[0-9]+]]:tcgpr64(p0) = COPY $x0 | ||
; COMMON: TCRETURNri [[COPY]](p0), 0, csr_aarch64_aapcs, implicit $sp | ||
tail call void %func() | ||
ret void | ||
} | ||
|
||
declare void @outgoing_args_fn(i32) | ||
; Right now, callees with outgoing arguments should not be tail called. | ||
; TODO: Support this. | ||
define void @test_outgoing_args(i32 %a) { | ||
; COMMON-LABEL: name: test_outgoing_args | ||
; COMMON: bb.1 (%ir-block.0): | ||
; COMMON: liveins: $w0 | ||
; COMMON: [[COPY:%[0-9]+]]:_(s32) = COPY $w0 | ||
; COMMON: ADJCALLSTACKDOWN 0, 0, implicit-def $sp, implicit $sp | ||
; COMMON: $w0 = COPY [[COPY]](s32) | ||
; COMMON: BL @outgoing_args_fn, csr_aarch64_aapcs, implicit-def $lr, implicit $sp, implicit $w0 | ||
; COMMON: ADJCALLSTACKUP 0, 0, implicit-def $sp, implicit $sp | ||
; COMMON: RET_ReallyLR | ||
tail call void @outgoing_args_fn(i32 %a) | ||
ret void | ||
} | ||
|
||
; Right now, this should not be tail called. | ||
; TODO: Support this. | ||
declare void @varargs(i32, double, i64, ...) | ||
define void @test_varargs() { | ||
; COMMON-LABEL: name: test_varargs | ||
; COMMON: bb.1 (%ir-block.0): | ||
; COMMON: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 42 | ||
; COMMON: [[C1:%[0-9]+]]:_(s64) = G_FCONSTANT double 1.000000e+00 | ||
; COMMON: [[C2:%[0-9]+]]:_(s64) = G_CONSTANT i64 12 | ||
; COMMON: ADJCALLSTACKDOWN 0, 0, implicit-def $sp, implicit $sp | ||
; COMMON: $w0 = COPY [[C]](s32) | ||
; COMMON: $d0 = COPY [[C1]](s64) | ||
; COMMON: $x1 = COPY [[C2]](s64) | ||
; COMMON: BL @varargs, csr_aarch64_aapcs, implicit-def $lr, implicit $sp, implicit $w0, implicit $d0, implicit $x1 | ||
; COMMON: ADJCALLSTACKUP 0, 0, implicit-def $sp, implicit $sp | ||
; COMMON: RET_ReallyLR | ||
tail call void(i32, double, i64, ...) @varargs(i32 42, double 1.0, i64 12) | ||
ret void | ||
} | ||
|
||
; Unsupported calling convention for tail calls. Make sure we never tail call | ||
; it. | ||
declare ghccc void @bad_call_conv_fn() | ||
define void @test_bad_call_conv() { | ||
; COMMON-LABEL: name: test_bad_call_conv | ||
; COMMON: bb.1 (%ir-block.0): | ||
; COMMON: ADJCALLSTACKDOWN 0, 0, implicit-def $sp, implicit $sp | ||
; COMMON: BL @bad_call_conv_fn, csr_aarch64_aapcs, implicit-def $lr, implicit $sp | ||
; COMMON: ADJCALLSTACKUP 0, 0, implicit-def $sp, implicit $sp | ||
; COMMON: RET_ReallyLR | ||
tail call ghccc void @bad_call_conv_fn() | ||
ret void | ||
} | ||
|
||
; Shouldn't tail call when the caller has byval arguments. | ||
define void @test_byval(i8* byval %ptr) { | ||
; COMMON-LABEL: name: test_byval | ||
; COMMON: bb.1 (%ir-block.0): | ||
; COMMON: [[FRAME_INDEX:%[0-9]+]]:_(p0) = G_FRAME_INDEX %fixed-stack.0 | ||
; COMMON: [[LOAD:%[0-9]+]]:_(p0) = G_LOAD [[FRAME_INDEX]](p0) :: (invariant load 8 from %fixed-stack.0, align 1) | ||
; COMMON: ADJCALLSTACKDOWN 0, 0, implicit-def $sp, implicit $sp | ||
; COMMON: BL @simple_fn, csr_aarch64_aapcs, implicit-def $lr, implicit $sp | ||
; COMMON: ADJCALLSTACKUP 0, 0, implicit-def $sp, implicit $sp | ||
; COMMON: RET_ReallyLR | ||
tail call void @simple_fn() | ||
ret void | ||
} | ||
|
||
; Shouldn't tail call when the caller has inreg arguments. | ||
define void @test_inreg(i8* inreg %ptr) { | ||
; COMMON-LABEL: name: test_inreg | ||
; COMMON: bb.1 (%ir-block.0): | ||
; COMMON: liveins: $x0 | ||
; COMMON: [[COPY:%[0-9]+]]:_(p0) = COPY $x0 | ||
; COMMON: ADJCALLSTACKDOWN 0, 0, implicit-def $sp, implicit $sp | ||
; COMMON: BL @simple_fn, csr_aarch64_aapcs, implicit-def $lr, implicit $sp | ||
; COMMON: ADJCALLSTACKUP 0, 0, implicit-def $sp, implicit $sp | ||
; COMMON: RET_ReallyLR | ||
tail call void @simple_fn() | ||
ret void | ||
} | ||
|
||
; Shouldn't tail call when the OS doesn't support it. Windows supports this, | ||
; so we should be able to tail call there. | ||
declare extern_weak void @extern_weak_fn() | ||
define void @test_extern_weak() { | ||
; DARWIN-LABEL: name: test_extern_weak | ||
; DARWIN: bb.1 (%ir-block.0): | ||
; DARWIN: ADJCALLSTACKDOWN 0, 0, implicit-def $sp, implicit $sp | ||
; DARWIN: BL @extern_weak_fn, csr_aarch64_aapcs, implicit-def $lr, implicit $sp | ||
; DARWIN: ADJCALLSTACKUP 0, 0, implicit-def $sp, implicit $sp | ||
; DARWIN: RET_ReallyLR | ||
; WINDOWS-LABEL: name: test_extern_weak | ||
; WINDOWS: bb.1 (%ir-block.0): | ||
; WINDOWS: TCRETURNdi @extern_weak_fn, 0, csr_aarch64_aapcs, implicit $sp | ||
tail call void @extern_weak_fn() | ||
ret void | ||
} | ||
|
||
; Right now, mismatched calling conventions should not be tail called. | ||
; TODO: Support this. | ||
declare fastcc void @fast_fn() | ||
define void @test_mismatched_caller() { | ||
; COMMON-LABEL: name: test_mismatched_caller | ||
; COMMON: bb.1 (%ir-block.0): | ||
; COMMON: ADJCALLSTACKDOWN 0, 0, implicit-def $sp, implicit $sp | ||
; COMMON: BL @fast_fn, csr_aarch64_aapcs, implicit-def $lr, implicit $sp | ||
; COMMON: ADJCALLSTACKUP 0, 0, implicit-def $sp, implicit $sp | ||
; COMMON: RET_ReallyLR | ||
tail call fastcc void @fast_fn() | ||
ret void | ||
} |
Oops, something went wrong.