forked from OSchip/llvm-project
Fall back to the selection dag isel to select tail calls.
This shouldn't affect codegen for -O0 compiles as tail call markers are not emitted in unoptimized compiles. Testing with the external/internal nightly test suite reveals no change in compile time performance. Testing with -O1, -O2 and -O3 with fast-isel enabled did not cause any compile-time or execution-time failures. All tests were performed on my x86 machine. I'll monitor our arm testers to ensure no regressions occur there. In an upcoming clang patch I will be marking the objc_autoreleaseReturnValue and objc_retainAutoreleaseReturnValue as tail calls unconditionally. While it's theoretically true that this is just an optimization, it's an optimization that we very much want to happen even at -O0, or else ARC applications become substantially harder to debug. Part of rdar://12553082 llvm-svn: 169796
This commit is contained in:
parent
a7b1c47c1a
commit
df42cf39ab
|
@ -131,6 +131,10 @@ public:
|
|||
/// into the current block.
|
||||
void recomputeInsertPt();
|
||||
|
||||
/// removeDeadCode - Remove all dead instructions between the I and E.
|
||||
void removeDeadCode(MachineBasicBlock::iterator I,
|
||||
MachineBasicBlock::iterator E);
|
||||
|
||||
struct SavePoint {
|
||||
MachineBasicBlock::iterator InsertPt;
|
||||
DebugLoc DL;
|
||||
|
@ -395,10 +399,6 @@ private:
|
|||
|
||||
/// hasTrivialKill - Test whether the given value has exactly one use.
|
||||
bool hasTrivialKill(const Value *V) const;
|
||||
|
||||
/// removeDeadCode - Remove all dead instructions between the I and E.
|
||||
void removeDeadCode(MachineBasicBlock::iterator I,
|
||||
MachineBasicBlock::iterator E);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -5273,11 +5273,6 @@ void SelectionDAGBuilder::LowerCallTo(ImmutableCallSite CS, SDValue Callee,
|
|||
!isInTailCallPosition(CS, CS.getAttributes().getRetAttributes(), TLI))
|
||||
isTailCall = false;
|
||||
|
||||
// If there's a possibility that fast-isel has already selected some amount
|
||||
// of the current basic block, don't emit a tail call.
|
||||
if (isTailCall && TM.Options.EnableFastISel)
|
||||
isTailCall = false;
|
||||
|
||||
TargetLowering::
|
||||
CallLoweringInfo CLI(getRoot(), RetTy, FTy, isTailCall, Callee, Args, DAG,
|
||||
getCurDebugLoc(), CS);
|
||||
|
|
|
@ -1113,19 +1113,21 @@ void SelectionDAGISel::SelectAllBasicBlocks(const Function &Fn) {
|
|||
}
|
||||
|
||||
bool HadTailCall = false;
|
||||
MachineBasicBlock::iterator SavedInsertPt = FuncInfo->InsertPt;
|
||||
SelectBasicBlock(Inst, BI, HadTailCall);
|
||||
|
||||
// If the call was emitted as a tail call, we're done with the block.
|
||||
// We also need to delete any previously emitted instructions.
|
||||
if (HadTailCall) {
|
||||
FastIS->removeDeadCode(SavedInsertPt, FuncInfo->MBB->end());
|
||||
--BI;
|
||||
break;
|
||||
}
|
||||
|
||||
// Recompute NumFastIselRemaining as Selection DAG instruction
|
||||
// selection may have handled the call, input args, etc.
|
||||
unsigned RemainingNow = std::distance(Begin, BI);
|
||||
NumFastIselFailures += NumFastIselRemaining - RemainingNow;
|
||||
|
||||
// If the call was emitted as a tail call, we're done with the block.
|
||||
if (HadTailCall) {
|
||||
--BI;
|
||||
break;
|
||||
}
|
||||
|
||||
NumFastIselRemaining = RemainingNow;
|
||||
continue;
|
||||
}
|
||||
|
|
|
@ -2284,6 +2284,9 @@ bool ARMFastISel::SelectCall(const Instruction *I,
|
|||
// Can't handle inline asm.
|
||||
if (isa<InlineAsm>(Callee)) return false;
|
||||
|
||||
// Allow SelectionDAG isel to handle tail calls.
|
||||
if (CI->isTailCall()) return false;
|
||||
|
||||
// Check the calling convention.
|
||||
ImmutableCallSite CS(CI);
|
||||
CallingConv::ID CC = CS.getCallingConv();
|
||||
|
|
|
@ -1529,6 +1529,10 @@ bool X86FastISel::X86SelectCall(const Instruction *I) {
|
|||
if (const IntrinsicInst *II = dyn_cast<IntrinsicInst>(CI))
|
||||
return X86VisitIntrinsicCall(*II);
|
||||
|
||||
// Allow SelectionDAG isel to handle tail calls.
|
||||
if (cast<CallInst>(I)->isTailCall())
|
||||
return false;
|
||||
|
||||
return DoSelectCall(I, 0);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,12 +1,11 @@
|
|||
; RUN: llc < %s -march=x86-64 -tailcallopt -fast-isel | not grep TAILCALL
|
||||
|
||||
; Fast-isel shouldn't attempt to cope with tail calls.
|
||||
; RUN: llc < %s -march=x86-64 -tailcallopt -fast-isel -fast-isel-abort | FileCheck %s
|
||||
|
||||
%0 = type { i64, i32, i8* }
|
||||
|
||||
define fastcc i8* @"visit_array_aux<`Reference>"(%0 %arg, i32 %arg1) nounwind {
|
||||
fail: ; preds = %entry
|
||||
%tmp20 = tail call fastcc i8* @"visit_array_aux<`Reference>"(%0 %arg, i32 undef) ; <i8*> [#uses=1]
|
||||
; CHECK: jmp "_visit_array_aux<`Reference>" ## TAILCALL
|
||||
ret i8* %tmp20
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue