]> granicus.if.org Git - llvm/commitdiff
[CodeGen] Remove dead FastISel code after SDAG emitted a tailcall.
authorAhmed Bougacha <ahmed.bougacha@gmail.com>
Wed, 1 Mar 2017 00:43:42 +0000 (00:43 +0000)
committerAhmed Bougacha <ahmed.bougacha@gmail.com>
Wed, 1 Mar 2017 00:43:42 +0000 (00:43 +0000)
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
test/CodeGen/AArch64/fast-isel-tail-call.ll [new file with mode: 0644]

index 645c9d2616a1367b561cf3d43e44da37469c3d68..7e87606852522e6db492f00e32d5328693d23a49 100644 (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();
diff --git a/test/CodeGen/AArch64/fast-isel-tail-call.ll b/test/CodeGen/AArch64/fast-isel-tail-call.ll
new file mode 100644 (file)
index 0000000..9c66dc4
--- /dev/null
@@ -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
+}