From fb5e79a577246612a862b9f8342b8348f7d8aa2d Mon Sep 17 00:00:00 2001 From: Ahmed Bougacha Date: Wed, 1 Mar 2017 00:43:42 +0000 Subject: [PATCH] [CodeGen] Remove dead FastISel code after SDAG emitted a tailcall. When SDAGISel (top-down) selects a tail-call, it skips the remainder of the block. If, before that, FastISel (bottom-up) selected some of the (no-op) next few instructions, we can end up with dead instructions following the terminator (selected by SDAGISel). We need to erase them, as we know they aren't necessary (in addition to being incorrect). We already do this when FastISel falls back on the tail-call itself. Also remove the FastISel-emitted code if we fallback on the instructions between the tail-call and the return. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@296552 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp | 6 +++++ test/CodeGen/AArch64/fast-isel-tail-call.ll | 23 +++++++++++++++++++ 2 files changed, 29 insertions(+) create mode 100644 test/CodeGen/AArch64/fast-isel-tail-call.ll diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp index 645c9d2616a..7e876068525 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp +++ b/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/test/CodeGen/AArch64/fast-isel-tail-call.ll b/test/CodeGen/AArch64/fast-isel-tail-call.ll new file mode 100644 index 00000000000..9c66dc41e46 --- /dev/null +++ b/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 +} -- 2.50.1