summaryrefslogtreecommitdiffstats
path: root/llvm
diff options
context:
space:
mode:
Diffstat (limited to 'llvm')
-rw-r--r--llvm/include/llvm/CodeGen/GlobalISel/IRTranslator.h4
-rw-r--r--llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp17
-rw-r--r--llvm/lib/Target/AArch64/AArch64CallLowering.cpp11
-rw-r--r--llvm/test/CodeGen/AArch64/GlobalISel/call-translator-tail-call.ll30
4 files changed, 50 insertions, 12 deletions
diff --git a/llvm/include/llvm/CodeGen/GlobalISel/IRTranslator.h b/llvm/include/llvm/CodeGen/GlobalISel/IRTranslator.h
index 2e405ba7ec0..bdb92aa4689 100644
--- a/llvm/include/llvm/CodeGen/GlobalISel/IRTranslator.h
+++ b/llvm/include/llvm/CodeGen/GlobalISel/IRTranslator.h
@@ -518,6 +518,10 @@ private:
// function has the optnone attribute.
bool EnableOpts = false;
+ /// True when the block contains a tail call. This allows the IRTranslator to
+ /// stop translating such blocks early.
+ bool HasTailCall = false;
+
/// Switch analysis and optimization.
class GISelSwitchLowering : public SwitchCG::SwitchLowering {
public:
diff --git a/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp b/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
index 0a06d8aa172..66082df0108 100644
--- a/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
@@ -32,6 +32,7 @@
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/StackProtector.h"
#include "llvm/CodeGen/TargetFrameLowering.h"
+#include "llvm/CodeGen/TargetInstrInfo.h"
#include "llvm/CodeGen/TargetLowering.h"
#include "llvm/CodeGen/TargetPassConfig.h"
#include "llvm/CodeGen/TargetRegisterInfo.h"
@@ -1568,6 +1569,13 @@ bool IRTranslator::translateCallSite(const ImmutableCallSite &CS,
CLI->lowerCall(MIRBuilder, CS, Res, Args, SwiftErrorVReg,
[&]() { return getOrCreateVReg(*CS.getCalledValue()); });
+ // Check if we just inserted a tail call.
+ if (Success) {
+ assert(!HasTailCall && "Can't tail call return twice from block?");
+ const TargetInstrInfo *TII = MF->getSubtarget().getInstrInfo();
+ HasTailCall = TII->isTailCall(*std::prev(MIRBuilder.getInsertPt()));
+ }
+
return Success;
}
@@ -2276,8 +2284,15 @@ bool IRTranslator::runOnMachineFunction(MachineFunction &CurMF) {
// Set the insertion point of all the following translations to
// the end of this basic block.
CurBuilder->setMBB(MBB);
-
+ HasTailCall = false;
for (const Instruction &Inst : *BB) {
+ // If we translated a tail call in the last step, then we know
+ // everything after the call is either a return, or something that is
+ // handled by the call itself. (E.g. a lifetime marker or assume
+ // intrinsic.) In this case, we should stop translating the block and
+ // move on.
+ if (HasTailCall)
+ break;
#ifndef NDEBUG
Verifier.setCurrentInst(&Inst);
#endif // ifndef NDEBUG
diff --git a/llvm/lib/Target/AArch64/AArch64CallLowering.cpp b/llvm/lib/Target/AArch64/AArch64CallLowering.cpp
index 64e1c84d98d..77944186c45 100644
--- a/llvm/lib/Target/AArch64/AArch64CallLowering.cpp
+++ b/llvm/lib/Target/AArch64/AArch64CallLowering.cpp
@@ -233,17 +233,6 @@ bool AArch64CallLowering::lowerReturn(MachineIRBuilder &MIRBuilder,
const Value *Val,
ArrayRef<Register> VRegs,
Register SwiftErrorVReg) const {
-
- // Check if a tail call was lowered in this block. If so, we already handled
- // the terminator.
- MachineFunction &MF = MIRBuilder.getMF();
- if (MF.getFrameInfo().hasTailCall()) {
- MachineBasicBlock &MBB = MIRBuilder.getMBB();
- auto FirstTerm = MBB.getFirstTerminator();
- if (FirstTerm != MBB.end() && FirstTerm->isCall())
- return true;
- }
-
auto MIB = MIRBuilder.buildInstrNoInsert(AArch64::RET_ReallyLR);
assert(((Val && !VRegs.empty()) || (!Val && VRegs.empty())) &&
"Return value without a vreg");
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/call-translator-tail-call.ll b/llvm/test/CodeGen/AArch64/GlobalISel/call-translator-tail-call.ll
index d253c54c1bb..c9ace6f4de1 100644
--- a/llvm/test/CodeGen/AArch64/GlobalISel/call-translator-tail-call.ll
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/call-translator-tail-call.ll
@@ -183,3 +183,33 @@ define void @test_mismatched_caller() {
tail call fastcc void @fast_fn()
ret void
}
+
+; Verify that lifetime markers and llvm.assume don't impact tail calling.
+declare void @llvm.assume(i1)
+define void @test_assume() local_unnamed_addr {
+ ; COMMON-LABEL: name: test_assume
+ ; COMMON: bb.1.entry:
+ ; COMMON: TCRETURNdi @nonvoid_ret, 0, csr_aarch64_aapcs, implicit $sp
+entry:
+ %x = tail call i32 @nonvoid_ret()
+ %y = icmp ne i32 %x, 0
+ tail call void @llvm.assume(i1 %y)
+ ret void
+}
+
+declare void @llvm.lifetime.start.p0i8(i64, i8* nocapture)
+declare void @llvm.lifetime.end.p0i8(i64, i8* nocapture)
+define void @test_lifetime() local_unnamed_addr {
+ ; COMMON-LABEL: name: test_lifetime
+ ; COMMON: bb.1.entry:
+ ; COMMON: [[FRAME_INDEX:%[0-9]+]]:_(p0) = G_FRAME_INDEX %stack.0.t
+ ; COMMON: LIFETIME_START %stack.0.t
+ ; COMMON: TCRETURNdi @nonvoid_ret, 0, csr_aarch64_aapcs, implicit $sp
+entry:
+ %t = alloca i8, align 1
+ call void @llvm.lifetime.start.p0i8(i64 1, i8* %t)
+ %x = tail call i32 @nonvoid_ret()
+ %y = icmp ne i32 %x, 0
+ tail call void @llvm.lifetime.end.p0i8(i64 1, i8* %t)
+ ret void
+}
OpenPOWER on IntegriCloud