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.
|
/// into the current block.
|
||||||
void recomputeInsertPt();
|
void recomputeInsertPt();
|
||||||
|
|
||||||
|
/// removeDeadCode - Remove all dead instructions between the I and E.
|
||||||
|
void removeDeadCode(MachineBasicBlock::iterator I,
|
||||||
|
MachineBasicBlock::iterator E);
|
||||||
|
|
||||||
struct SavePoint {
|
struct SavePoint {
|
||||||
MachineBasicBlock::iterator InsertPt;
|
MachineBasicBlock::iterator InsertPt;
|
||||||
DebugLoc DL;
|
DebugLoc DL;
|
||||||
|
@ -395,10 +399,6 @@ private:
|
||||||
|
|
||||||
/// hasTrivialKill - Test whether the given value has exactly one use.
|
/// hasTrivialKill - Test whether the given value has exactly one use.
|
||||||
bool hasTrivialKill(const Value *V) const;
|
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))
|
!isInTailCallPosition(CS, CS.getAttributes().getRetAttributes(), TLI))
|
||||||
isTailCall = false;
|
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::
|
TargetLowering::
|
||||||
CallLoweringInfo CLI(getRoot(), RetTy, FTy, isTailCall, Callee, Args, DAG,
|
CallLoweringInfo CLI(getRoot(), RetTy, FTy, isTailCall, Callee, Args, DAG,
|
||||||
getCurDebugLoc(), CS);
|
getCurDebugLoc(), CS);
|
||||||
|
|
|
@ -1113,19 +1113,21 @@ void SelectionDAGISel::SelectAllBasicBlocks(const Function &Fn) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool HadTailCall = false;
|
bool HadTailCall = false;
|
||||||
|
MachineBasicBlock::iterator SavedInsertPt = FuncInfo->InsertPt;
|
||||||
SelectBasicBlock(Inst, BI, HadTailCall);
|
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
|
// Recompute NumFastIselRemaining as Selection DAG instruction
|
||||||
// selection may have handled the call, input args, etc.
|
// selection may have handled the call, input args, etc.
|
||||||
unsigned RemainingNow = std::distance(Begin, BI);
|
unsigned RemainingNow = std::distance(Begin, BI);
|
||||||
NumFastIselFailures += NumFastIselRemaining - RemainingNow;
|
NumFastIselFailures += NumFastIselRemaining - RemainingNow;
|
||||||
|
|
||||||
// If the call was emitted as a tail call, we're done with the block.
|
|
||||||
if (HadTailCall) {
|
|
||||||
--BI;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
NumFastIselRemaining = RemainingNow;
|
NumFastIselRemaining = RemainingNow;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2284,6 +2284,9 @@ bool ARMFastISel::SelectCall(const Instruction *I,
|
||||||
// Can't handle inline asm.
|
// Can't handle inline asm.
|
||||||
if (isa<InlineAsm>(Callee)) return false;
|
if (isa<InlineAsm>(Callee)) return false;
|
||||||
|
|
||||||
|
// Allow SelectionDAG isel to handle tail calls.
|
||||||
|
if (CI->isTailCall()) return false;
|
||||||
|
|
||||||
// Check the calling convention.
|
// Check the calling convention.
|
||||||
ImmutableCallSite CS(CI);
|
ImmutableCallSite CS(CI);
|
||||||
CallingConv::ID CC = CS.getCallingConv();
|
CallingConv::ID CC = CS.getCallingConv();
|
||||||
|
|
|
@ -1529,6 +1529,10 @@ bool X86FastISel::X86SelectCall(const Instruction *I) {
|
||||||
if (const IntrinsicInst *II = dyn_cast<IntrinsicInst>(CI))
|
if (const IntrinsicInst *II = dyn_cast<IntrinsicInst>(CI))
|
||||||
return X86VisitIntrinsicCall(*II);
|
return X86VisitIntrinsicCall(*II);
|
||||||
|
|
||||||
|
// Allow SelectionDAG isel to handle tail calls.
|
||||||
|
if (cast<CallInst>(I)->isTailCall())
|
||||||
|
return false;
|
||||||
|
|
||||||
return DoSelectCall(I, 0);
|
return DoSelectCall(I, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,12 +1,11 @@
|
||||||
; RUN: llc < %s -march=x86-64 -tailcallopt -fast-isel | not grep TAILCALL
|
; RUN: llc < %s -march=x86-64 -tailcallopt -fast-isel -fast-isel-abort | FileCheck %s
|
||||||
|
|
||||||
; Fast-isel shouldn't attempt to cope with tail calls.
|
|
||||||
|
|
||||||
%0 = type { i64, i32, i8* }
|
%0 = type { i64, i32, i8* }
|
||||||
|
|
||||||
define fastcc i8* @"visit_array_aux<`Reference>"(%0 %arg, i32 %arg1) nounwind {
|
define fastcc i8* @"visit_array_aux<`Reference>"(%0 %arg, i32 %arg1) nounwind {
|
||||||
fail: ; preds = %entry
|
fail: ; preds = %entry
|
||||||
%tmp20 = tail call fastcc i8* @"visit_array_aux<`Reference>"(%0 %arg, i32 undef) ; <i8*> [#uses=1]
|
%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
|
ret i8* %tmp20
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue