summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp6
-rw-r--r--llvm/test/CodeGen/AArch64/fast-isel-tail-call.ll23
2 files changed, 29 insertions, 0 deletions
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
index 645c9d2616a..7e876068525 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
@@ -1684,6 +1684,12 @@ void SelectionDAGISel::SelectAllBasicBlocks(const Function &Fn) {
// block.
bool HadTailCall;
SelectBasicBlock(Begin, BI, HadTailCall);
+
+ // But if FastISel was run, we already selected some of the block.
+ // If we emitted a tail-call, we need to delete any previously emitted
+ // instruction that follows it.
+ if (HadTailCall && FuncInfo->InsertPt != FuncInfo->MBB->end())
+ FastIS->removeDeadCode(FuncInfo->InsertPt, FuncInfo->MBB->end());
}
FinishBasicBlock();
diff --git a/llvm/test/CodeGen/AArch64/fast-isel-tail-call.ll b/llvm/test/CodeGen/AArch64/fast-isel-tail-call.ll
new file mode 100644
index 00000000000..9c66dc41e46
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/fast-isel-tail-call.ll
@@ -0,0 +1,23 @@
+; RUN: llc -fast-isel -fast-isel-verbose -mtriple arm64-- < %s 2> %t | FileCheck %s
+; RUN: cat %t | FileCheck %s --check-prefix MISSED
+
+%struct = type { [4 x i32] }
+
+declare %struct @external()
+
+; Check that, when fastisel falls back to SDAG, we don't emit instructions
+; that follow a tail-call and would have been dropped by pure SDAGISel.
+
+; Here, the %struct extractvalue should fail FastISel.
+
+; MISSED: FastISel miss: %tmp1 = extractvalue %struct %tmp0, 0
+
+; CHECK-LABEL: test:
+; CHECK: b external
+; CHECK-NEXT: .Lfunc_end0:
+define i32 @test() nounwind {
+ %tmp0 = tail call %struct @external()
+ %tmp1 = extractvalue %struct %tmp0, 0
+ %tmp2 = extractvalue [4 x i32] %tmp1, 0
+ ret i32 %tmp2
+}
OpenPOWER on IntegriCloud