mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-10-19 11:02:59 +02:00
Move tail call disabling code to target independent code
When the "disable-tail-calls" attribute was added, checks were added for it in various backends. Now this code has proliferated, and it is something the target is responsible for checking. Move that responsibility back to the ISels (fast, global, and SD). There's no major functionality change, except for targets that never implemented this check. This LLVM attribute was originally added in d9699bc7bdf0362173fcd256690f61a4d47429c2 (2015). Reviewers: echristo, MaskRay Differential Revision: https://reviews.llvm.org/D72118
This commit is contained in:
parent
a4fc069a94
commit
e7c2cc0e45
@ -65,7 +65,11 @@ bool CallLowering::lowerCall(MachineIRBuilder &MIRBuilder, ImmutableCallSite CS,
|
||||
Info.SwiftErrorVReg = SwiftErrorVReg;
|
||||
Info.IsMustTailCall = CS.isMustTailCall();
|
||||
Info.IsTailCall = CS.isTailCall() &&
|
||||
isInTailCallPosition(CS, MIRBuilder.getMF().getTarget());
|
||||
isInTailCallPosition(CS, MIRBuilder.getMF().getTarget()) &&
|
||||
(MIRBuilder.getMF()
|
||||
.getFunction()
|
||||
.getFnAttribute("disable-tail-calls")
|
||||
.getValueAsString() != "true");
|
||||
Info.IsVarArg = CS.getFunctionType()->isVarArg();
|
||||
return lowerCall(MIRBuilder, Info);
|
||||
}
|
||||
|
@ -1276,6 +1276,10 @@ bool FastISel::lowerCall(const CallInst *CI) {
|
||||
bool IsTailCall = CI->isTailCall();
|
||||
if (IsTailCall && !isInTailCallPosition(CS, TM))
|
||||
IsTailCall = false;
|
||||
if (IsTailCall && MF->getFunction()
|
||||
.getFnAttribute("disable-tail-calls")
|
||||
.getValueAsString() == "true")
|
||||
IsTailCall = false;
|
||||
|
||||
CallLoweringInfo CLI;
|
||||
CLI.setCallee(RetTy, FuncTy, CI->getCalledValue(), std::move(Args), CS)
|
||||
|
@ -7075,13 +7075,21 @@ void SelectionDAGBuilder::LowerCallTo(ImmutableCallSite CS, SDValue Callee,
|
||||
const Value *SwiftErrorVal = nullptr;
|
||||
const TargetLowering &TLI = DAG.getTargetLoweringInfo();
|
||||
|
||||
// We can't tail call inside a function with a swifterror argument. Lowering
|
||||
// does not support this yet. It would have to move into the swifterror
|
||||
// register before the call.
|
||||
auto *Caller = CS.getInstruction()->getParent()->getParent();
|
||||
if (TLI.supportSwiftError() &&
|
||||
Caller->getAttributes().hasAttrSomewhere(Attribute::SwiftError))
|
||||
isTailCall = false;
|
||||
if (isTailCall) {
|
||||
// Avoid emitting tail calls in functions with the disable-tail-calls
|
||||
// attribute.
|
||||
auto *Caller = CS.getInstruction()->getParent()->getParent();
|
||||
if (Caller->getFnAttribute("disable-tail-calls").getValueAsString() ==
|
||||
"true")
|
||||
isTailCall = false;
|
||||
|
||||
// We can't tail call inside a function with a swifterror argument. Lowering
|
||||
// does not support this yet. It would have to move into the swifterror
|
||||
// register before the call.
|
||||
if (TLI.supportSwiftError() &&
|
||||
Caller->getAttributes().hasAttrSomewhere(Attribute::SwiftError))
|
||||
isTailCall = false;
|
||||
}
|
||||
|
||||
for (ImmutableCallSite::arg_iterator i = CS.arg_begin(), e = CS.arg_end();
|
||||
i != e; ++i) {
|
||||
|
@ -52,6 +52,10 @@ bool TargetLowering::isInTailCallPosition(SelectionDAG &DAG, SDNode *Node,
|
||||
SDValue &Chain) const {
|
||||
const Function &F = DAG.getMachineFunction().getFunction();
|
||||
|
||||
// First, check if tail calls have been disabled in this function.
|
||||
if (F.getFnAttribute("disable-tail-calls").getValueAsString() == "true")
|
||||
return false;
|
||||
|
||||
// Conservatively require the attributes of the call to match those of
|
||||
// the return. Ignore NoAlias and NonNull because they don't affect the
|
||||
// call sequence.
|
||||
|
@ -2671,9 +2671,7 @@ bool SITargetLowering::mayBeEmittedAsTailCall(const CallInst *CI) const {
|
||||
const Function *ParentFn = CI->getParent()->getParent();
|
||||
if (AMDGPU::isEntryFunctionCC(ParentFn->getCallingConv()))
|
||||
return false;
|
||||
|
||||
auto Attr = ParentFn->getFnAttribute("disable-tail-calls");
|
||||
return (Attr.getValueAsString() != "true");
|
||||
return true;
|
||||
}
|
||||
|
||||
// The wave scratch offset register is used as the global base pointer.
|
||||
|
@ -2094,11 +2094,10 @@ ARMTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
|
||||
MachineFunction::CallSiteInfo CSInfo;
|
||||
bool isStructRet = (Outs.empty()) ? false : Outs[0].Flags.isSRet();
|
||||
bool isThisReturn = false;
|
||||
auto Attr = MF.getFunction().getFnAttribute("disable-tail-calls");
|
||||
bool PreferIndirect = false;
|
||||
|
||||
// Disable tail calls if they're not supported.
|
||||
if (!Subtarget->supportsTailCall() || Attr.getValueAsString() == "true")
|
||||
if (!Subtarget->supportsTailCall())
|
||||
isTailCall = false;
|
||||
|
||||
if (isa<GlobalAddressSDNode>(Callee)) {
|
||||
@ -2975,9 +2974,7 @@ bool ARMTargetLowering::mayBeEmittedAsTailCall(const CallInst *CI) const {
|
||||
if (!Subtarget->supportsTailCall())
|
||||
return false;
|
||||
|
||||
auto Attr =
|
||||
CI->getParent()->getParent()->getFnAttribute("disable-tail-calls");
|
||||
if (!CI->isTailCall() || Attr.getValueAsString() == "true")
|
||||
if (!CI->isTailCall())
|
||||
return false;
|
||||
|
||||
return true;
|
||||
|
@ -233,12 +233,7 @@ HexagonTargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv,
|
||||
|
||||
bool HexagonTargetLowering::mayBeEmittedAsTailCall(const CallInst *CI) const {
|
||||
// If either no tail call or told not to tail call at all, don't.
|
||||
auto Attr =
|
||||
CI->getParent()->getParent()->getFnAttribute("disable-tail-calls");
|
||||
if (!CI->isTailCall() || Attr.getValueAsString() == "true")
|
||||
return false;
|
||||
|
||||
return true;
|
||||
return CI->isTailCall();
|
||||
}
|
||||
|
||||
Register HexagonTargetLowering::getRegisterByName(
|
||||
@ -408,10 +403,6 @@ HexagonTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
|
||||
else
|
||||
CCInfo.AnalyzeCallOperands(Outs, CC_Hexagon);
|
||||
|
||||
auto Attr = MF.getFunction().getFnAttribute("disable-tail-calls");
|
||||
if (Attr.getValueAsString() == "true")
|
||||
CLI.IsTailCall = false;
|
||||
|
||||
if (CLI.IsTailCall) {
|
||||
bool StructAttrFlag = MF.getFunction().hasStructRetAttr();
|
||||
CLI.IsTailCall = IsEligibleForTailCallOptimization(Callee, CallConv,
|
||||
|
@ -15640,12 +15640,6 @@ bool PPCTargetLowering::mayBeEmittedAsTailCall(const CallInst *CI) const {
|
||||
if (!CI->isTailCall())
|
||||
return false;
|
||||
|
||||
// If tail calls are disabled for the caller then we are done.
|
||||
const Function *Caller = CI->getParent()->getParent();
|
||||
auto Attr = Caller->getFnAttribute("disable-tail-calls");
|
||||
if (Attr.getValueAsString() == "true")
|
||||
return false;
|
||||
|
||||
// If sibling calls have been disabled and tail-calls aren't guaranteed
|
||||
// there is no reason to duplicate.
|
||||
auto &TM = getTargetMachine();
|
||||
@ -15658,6 +15652,7 @@ bool PPCTargetLowering::mayBeEmittedAsTailCall(const CallInst *CI) const {
|
||||
return false;
|
||||
|
||||
// Make sure the callee and caller calling conventions are eligible for tco.
|
||||
const Function *Caller = CI->getParent()->getParent();
|
||||
if (!areCallingConvEligibleForTCO_64SVR4(Caller->getCallingConv(),
|
||||
CI->getCallingConv()))
|
||||
return false;
|
||||
|
@ -2016,10 +2016,6 @@ bool RISCVTargetLowering::isEligibleForTailCallOptimization(
|
||||
auto &Caller = MF.getFunction();
|
||||
auto CallerCC = Caller.getCallingConv();
|
||||
|
||||
// Do not tail call opt functions with "disable-tail-calls" attribute.
|
||||
if (Caller.getFnAttribute("disable-tail-calls").getValueAsString() == "true")
|
||||
return false;
|
||||
|
||||
// Exception-handling functions need a special set of instructions to
|
||||
// indicate a return to the hardware. Tail-calling another function would
|
||||
// probably break this.
|
||||
|
@ -3161,9 +3161,7 @@ static bool shouldGuaranteeTCO(CallingConv::ID CC, bool GuaranteedTailCallOpt) {
|
||||
}
|
||||
|
||||
bool X86TargetLowering::mayBeEmittedAsTailCall(const CallInst *CI) const {
|
||||
auto Attr =
|
||||
CI->getParent()->getParent()->getFnAttribute("disable-tail-calls");
|
||||
if (!CI->isTailCall() || Attr.getValueAsString() == "true")
|
||||
if (!CI->isTailCall())
|
||||
return false;
|
||||
|
||||
ImmutableCallSite CS(CI);
|
||||
@ -3786,7 +3784,6 @@ X86TargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
|
||||
bool IsGuaranteeTCO = MF.getTarget().Options.GuaranteedTailCallOpt ||
|
||||
CallConv == CallingConv::Tail;
|
||||
X86MachineFunctionInfo *X86Info = MF.getInfo<X86MachineFunctionInfo>();
|
||||
auto Attr = MF.getFunction().getFnAttribute("disable-tail-calls");
|
||||
const auto *CI = dyn_cast_or_null<CallInst>(CLI.CS.getInstruction());
|
||||
const Function *Fn = CI ? CI->getCalledFunction() : nullptr;
|
||||
bool HasNCSR = (CI && CI->hasFnAttr("no_caller_saved_registers")) ||
|
||||
@ -3802,9 +3799,6 @@ X86TargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
|
||||
if (CallConv == CallingConv::X86_INTR)
|
||||
report_fatal_error("X86 interrupts may not be called directly");
|
||||
|
||||
if (Attr.getValueAsString() == "true")
|
||||
isTailCall = false;
|
||||
|
||||
if (Subtarget.isPICStyleGOT() && !IsGuaranteeTCO) {
|
||||
// If we are using a GOT, disable tail calls to external symbols with
|
||||
// default visibility. Tail calling such a symbol requires using a GOT
|
||||
|
@ -93,6 +93,16 @@ define fastcc void @caller_to16_from16([8 x i64], i64 %a, i64 %b) {
|
||||
; COMMON-NEXT: b callee_stack16
|
||||
}
|
||||
|
||||
define fastcc void @disable_tail_calls() nounwind "disable-tail-calls"="true" {
|
||||
; COMMON-LABEL: disable_tail_calls:
|
||||
; COMMON-NEXT: // %bb.
|
||||
|
||||
tail call fastcc void @callee_stack0()
|
||||
ret void
|
||||
|
||||
; COMMON: bl callee_stack0
|
||||
; COMMON: ret
|
||||
}
|
||||
|
||||
; Weakly-referenced extern functions cannot be tail-called, as AAELF does
|
||||
; not define the behaviour of branch instructions to undefined weak symbols.
|
||||
|
@ -158,6 +158,16 @@ entry:
|
||||
ret void
|
||||
}
|
||||
|
||||
; Do not tail call optimize if disabled.
|
||||
define i32 @disable_tail_calls(i32 %i) nounwind "disable-tail-calls"="true" {
|
||||
; CHECK-LABEL: disable_tail_calls:
|
||||
; CHECK-NOT: tail callee_nostruct
|
||||
; CHECK: call callee_tail
|
||||
entry:
|
||||
%rv = tail call i32 @callee_tail(i32 %i)
|
||||
ret i32 %rv
|
||||
}
|
||||
|
||||
!llvm.module.flags = !{!0}
|
||||
!0 = !{i32 1, !"ProfileSummary", !1}
|
||||
!1 = !{!2, !3, !4, !5, !6, !7, !8, !9}
|
||||
|
Loading…
Reference in New Issue
Block a user