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

Jessica Paquette via llvm-commits llvm-commits at lists.llvm.org
Tue Aug 18 11:07:13 PDT 2020


Author: Jessica Paquette
Date: 2020-08-18T11:06:57-07:00
New Revision: f29e6277ad6bcff36ed950dbf8effddc59ba9c28

URL: https://github.com/llvm/llvm-project/commit/f29e6277ad6bcff36ed950dbf8effddc59ba9c28
DIFF: https://github.com/llvm/llvm-project/commit/f29e6277ad6bcff36ed950dbf8effddc59ba9c28.diff

LOG: [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

Added: 
    llvm/test/CodeGen/AArch64/GlobalISel/call-translator-tail-call-sret.ll

Modified: 
    llvm/lib/CodeGen/GlobalISel/CallLowering.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/lib/CodeGen/GlobalISel/CallLowering.cpp b/llvm/lib/CodeGen/GlobalISel/CallLowering.cpp
index e443f603def6..cf1059c67b4a 100644
--- a/llvm/lib/CodeGen/GlobalISel/CallLowering.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/CallLowering.cpp
@@ -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);
 }

diff  --git a/llvm/test/CodeGen/AArch64/GlobalISel/call-translator-tail-call-sret.ll b/llvm/test/CodeGen/AArch64/GlobalISel/call-translator-tail-call-sret.ll
new file mode 100644
index 000000000000..a9a93d1b7f7a
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/call-translator-tail-call-sret.ll
@@ -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
+}


        


More information about the llvm-commits mailing list