From 20b3e9a8355311aae1ca2f491b1eb2dd5ec44b84 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. llvm-svn: 296552 --- .../CodeGen/SelectionDAG/SelectionDAGISel.cpp | 6 +++++ .../CodeGen/AArch64/fast-isel-tail-call.ll | 23 +++++++++++++++++++ 2 files changed, 29 insertions(+) create mode 100644 llvm/test/CodeGen/AArch64/fast-isel-tail-call.ll diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp index 645c9d2616a1..7e8760685252 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 000000000000..9c66dc41e467 --- /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 +}