1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-10-19 02:52:53 +02:00

[GlobalISel][CallLowering] Don't tail call with non-forwarded explicit sret

Similar to this commit:

faf8065a99817bcb10e6f09b558fe3e0972c35ce

Testcase is pretty much the same as

test/CodeGen/AArch64/tailcall-explicit-sret.ll

Except it uses i64 (since we don't handle the i1024 return values yet), and
doesn't have indirect tail call testcases (because we can't translate those
yet).

Differential Revision: https://reviews.llvm.org/D86148
This commit is contained in:
Jessica Paquette 2020-08-18 09:23:48 -07:00
parent 418515b7d0
commit 761fea8dc0
2 changed files with 113 additions and 6 deletions

View File

@ -65,6 +65,12 @@ bool CallLowering::lowerCall(MachineIRBuilder &MIRBuilder, const CallBase &CB,
std::function<unsigned()> GetCalleeReg) const {
CallLoweringInfo Info;
const DataLayout &DL = MIRBuilder.getDataLayout();
MachineFunction &MF = MIRBuilder.getMF();
bool CanBeTailCalled = CB.isTailCall() &&
isInTailCallPosition(CB, MF.getTarget()) &&
(MF.getFunction()
.getFnAttribute("disable-tail-calls")
.getValueAsString() != "true");
// First step is to marshall all the function's parameters into the correct
// physregs and memory locations. Gather the sequence of argument types that
@ -75,6 +81,12 @@ bool CallLowering::lowerCall(MachineIRBuilder &MIRBuilder, const CallBase &CB,
ArgInfo OrigArg{ArgRegs[i], Arg->getType(), getAttributesForArgIdx(CB, i),
i < NumFixedArgs};
setArgFlags(OrigArg, i + AttributeList::FirstArgIndex, DL, CB);
// If we have an explicit sret argument that is an Instruction, (i.e., it
// might point to function-local memory), we can't meaningfully tail-call.
if (OrigArg.Flags[0].isSRet() && isa<Instruction>(&Arg))
CanBeTailCalled = false;
Info.OrigArgs.push_back(OrigArg);
++i;
}
@ -91,16 +103,11 @@ bool CallLowering::lowerCall(MachineIRBuilder &MIRBuilder, const CallBase &CB,
if (!Info.OrigRet.Ty->isVoidTy())
setArgFlags(Info.OrigRet, AttributeList::ReturnIndex, DL, CB);
MachineFunction &MF = MIRBuilder.getMF();
Info.KnownCallees = CB.getMetadata(LLVMContext::MD_callees);
Info.CallConv = CB.getCallingConv();
Info.SwiftErrorVReg = SwiftErrorVReg;
Info.IsMustTailCall = CB.isMustTailCall();
Info.IsTailCall =
CB.isTailCall() && isInTailCallPosition(CB, MF.getTarget()) &&
(MF.getFunction()
.getFnAttribute("disable-tail-calls")
.getValueAsString() != "true");
Info.IsTailCall = CanBeTailCalled;
Info.IsVarArg = CB.getFunctionType()->isVarArg();
return lowerCall(MIRBuilder, Info);
}

View File

@ -0,0 +1,100 @@
; NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
; RUN: llc < %s -mtriple arm64-apple-darwin -global-isel -stop-after=irtranslator -verify-machineinstrs | FileCheck %s
; Check that we don't try to tail-call with a non-forwarded sret parameter.
declare void @test_explicit_sret(i64* sret)
; Forwarded explicit sret pointer => we can tail call.
define void @can_tail_call_forwarded_explicit_sret_ptr(i64* sret %arg) {
; CHECK-LABEL: name: can_tail_call_forwarded_explicit_sret_ptr
; CHECK: bb.1 (%ir-block.0):
; CHECK: liveins: $x8
; CHECK: [[COPY:%[0-9]+]]:_(p0) = COPY $x8
; CHECK: $x8 = COPY [[COPY]](p0)
; CHECK: TCRETURNdi @test_explicit_sret, 0, csr_darwin_aarch64_aapcs, implicit $sp, implicit $x8
tail call void @test_explicit_sret(i64* %arg)
ret void
}
; Not marked as tail, so don't tail call.
define void @test_call_explicit_sret(i64* sret %arg) {
; CHECK-LABEL: name: test_call_explicit_sret
; CHECK: bb.1 (%ir-block.0):
; CHECK: liveins: $x8
; CHECK: [[COPY:%[0-9]+]]:_(p0) = COPY $x8
; CHECK: ADJCALLSTACKDOWN 0, 0, implicit-def $sp, implicit $sp
; CHECK: $x8 = COPY [[COPY]](p0)
; CHECK: BL @test_explicit_sret, csr_darwin_aarch64_aapcs, implicit-def $lr, implicit $sp, implicit $x8
; CHECK: ADJCALLSTACKUP 0, 0, implicit-def $sp, implicit $sp
; CHECK: RET_ReallyLR
call void @test_explicit_sret(i64* %arg)
ret void
}
define void @dont_tail_call_explicit_sret_alloca_unused() {
; CHECK-LABEL: name: dont_tail_call_explicit_sret_alloca_unused
; CHECK: bb.1 (%ir-block.0):
; CHECK: [[FRAME_INDEX:%[0-9]+]]:_(p0) = G_FRAME_INDEX %stack.0.l
; CHECK: ADJCALLSTACKDOWN 0, 0, implicit-def $sp, implicit $sp
; CHECK: $x8 = COPY [[FRAME_INDEX]](p0)
; CHECK: BL @test_explicit_sret, csr_darwin_aarch64_aapcs, implicit-def $lr, implicit $sp, implicit $x8
; CHECK: ADJCALLSTACKUP 0, 0, implicit-def $sp, implicit $sp
; CHECK: RET_ReallyLR
%l = alloca i64, align 8
tail call void @test_explicit_sret(i64* %l)
ret void
}
define void @dont_tail_call_explicit_sret_alloca_dummyusers(i64* %ptr) {
; CHECK-LABEL: name: dont_tail_call_explicit_sret_alloca_dummyusers
; CHECK: bb.1 (%ir-block.0):
; CHECK: liveins: $x0
; CHECK: [[COPY:%[0-9]+]]:_(p0) = COPY $x0
; CHECK: [[FRAME_INDEX:%[0-9]+]]:_(p0) = G_FRAME_INDEX %stack.0.l
; CHECK: [[LOAD:%[0-9]+]]:_(s64) = G_LOAD [[COPY]](p0) :: (load 8 from %ir.ptr)
; CHECK: G_STORE [[LOAD]](s64), [[FRAME_INDEX]](p0) :: (store 8 into %ir.l)
; CHECK: ADJCALLSTACKDOWN 0, 0, implicit-def $sp, implicit $sp
; CHECK: $x8 = COPY [[FRAME_INDEX]](p0)
; CHECK: BL @test_explicit_sret, csr_darwin_aarch64_aapcs, implicit-def $lr, implicit $sp, implicit $x8
; CHECK: ADJCALLSTACKUP 0, 0, implicit-def $sp, implicit $sp
; CHECK: RET_ReallyLR
%l = alloca i64, align 8
%r = load i64, i64* %ptr, align 8
store i64 %r, i64* %l, align 8
tail call void @test_explicit_sret(i64* %l)
ret void
}
define void @dont_tail_call_tailcall_explicit_sret_gep(i64* %ptr) {
; CHECK-LABEL: name: dont_tail_call_tailcall_explicit_sret_gep
; CHECK: bb.1 (%ir-block.0):
; CHECK: liveins: $x0
; CHECK: [[COPY:%[0-9]+]]:_(p0) = COPY $x0
; CHECK: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 8
; CHECK: [[PTR_ADD:%[0-9]+]]:_(p0) = G_PTR_ADD [[COPY]], [[C]](s64)
; CHECK: ADJCALLSTACKDOWN 0, 0, implicit-def $sp, implicit $sp
; CHECK: $x8 = COPY [[PTR_ADD]](p0)
; CHECK: BL @test_explicit_sret, csr_darwin_aarch64_aapcs, implicit-def $lr, implicit $sp, implicit $x8
; CHECK: ADJCALLSTACKUP 0, 0, implicit-def $sp, implicit $sp
; CHECK: RET_ReallyLR
%ptr2 = getelementptr i64, i64* %ptr, i32 1
tail call void @test_explicit_sret(i64* %ptr2)
ret void
}
define i64 @dont_tail_call_sret_alloca_returned() {
; CHECK-LABEL: name: dont_tail_call_sret_alloca_returned
; CHECK: bb.1 (%ir-block.0):
; CHECK: [[FRAME_INDEX:%[0-9]+]]:_(p0) = G_FRAME_INDEX %stack.0.l
; CHECK: ADJCALLSTACKDOWN 0, 0, implicit-def $sp, implicit $sp
; CHECK: $x8 = COPY [[FRAME_INDEX]](p0)
; CHECK: BL @test_explicit_sret, csr_darwin_aarch64_aapcs, implicit-def $lr, implicit $sp, implicit $x8
; CHECK: ADJCALLSTACKUP 0, 0, implicit-def $sp, implicit $sp
; CHECK: [[LOAD:%[0-9]+]]:_(s64) = G_LOAD [[FRAME_INDEX]](p0) :: (dereferenceable load 8 from %ir.l)
; CHECK: $x0 = COPY [[LOAD]](s64)
; CHECK: RET_ReallyLR implicit $x0
%l = alloca i64, align 8
tail call void @test_explicit_sret(i64* %l)
%r = load i64, i64* %l, align 8
ret i64 %r
}