diff options
-rw-r--r-- | llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp | 6 | ||||
-rw-r--r-- | llvm/test/CodeGen/AArch64/fast-isel-tail-call.ll | 23 |
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 +} |