[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
This commit is contained in:
Ahmed Bougacha 2017-03-01 00:43:42 +00:00
parent 67d1c7c3c2
commit 20b3e9a835
2 changed files with 29 additions and 0 deletions

View File

@ -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();

View File

@ -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
}