Skip to content

Commit 385faf9

Browse files
authored
[ARM/X86] Standardize the isEligibleForTailCallOptimization prototypes (#90688)
Pass in CallLoweringInfo (CLI) instead of passing in the various fields directly. Also pass in CCState (CCInfo), which is computed in both the caller and the callee for a minor efficiency saving. There may also be a small correctness improvement for sibcalls with vectorcall, which has an odd way of recomputing argument locations. This is a step towards improving the handling of musttail on armv7, which we have numerous issues filed about in our tracker. I took inspiration for this from the RISCV tail call eligibility check, which uses a similar prototype.
1 parent 9620d3e commit 385faf9

File tree

4 files changed

+62
-74
lines changed

4 files changed

+62
-74
lines changed

llvm/lib/Target/ARM/ARMISelLowering.cpp

Lines changed: 22 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -2366,6 +2366,12 @@ ARMTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
23662366
bool PreferIndirect = false;
23672367
bool GuardWithBTI = false;
23682368

2369+
// Analyze operands of the call, assigning locations to each operand.
2370+
SmallVector<CCValAssign, 16> ArgLocs;
2371+
CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), ArgLocs,
2372+
*DAG.getContext());
2373+
CCInfo.AnalyzeCallOperands(Outs, CCAssignFnForCall(CallConv, isVarArg));
2374+
23692375
// Lower 'returns_twice' calls to a pseudo-instruction.
23702376
if (CLI.CB && CLI.CB->getAttributes().hasFnAttr(Attribute::ReturnsTwice) &&
23712377
!Subtarget->noBTIAtReturnTwice())
@@ -2401,10 +2407,8 @@ ARMTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
24012407
}
24022408
if (isTailCall) {
24032409
// Check if it's really possible to do a tail call.
2404-
isTailCall = IsEligibleForTailCallOptimization(
2405-
Callee, CallConv, isVarArg, isStructRet,
2406-
MF.getFunction().hasStructRetAttr(), Outs, OutVals, Ins, DAG,
2407-
PreferIndirect);
2410+
isTailCall =
2411+
IsEligibleForTailCallOptimization(CLI, CCInfo, ArgLocs, PreferIndirect);
24082412

24092413
if (isTailCall && !getTargetMachine().Options.GuaranteedTailCallOpt &&
24102414
CallConv != CallingConv::Tail && CallConv != CallingConv::SwiftTail)
@@ -2419,11 +2423,6 @@ ARMTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
24192423
if (!isTailCall && CLI.CB && CLI.CB->isMustTailCall())
24202424
report_fatal_error("failed to perform tail call elimination on a call "
24212425
"site marked musttail");
2422-
// Analyze operands of the call, assigning locations to each operand.
2423-
SmallVector<CCValAssign, 16> ArgLocs;
2424-
CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), ArgLocs,
2425-
*DAG.getContext());
2426-
CCInfo.AnalyzeCallOperands(Outs, CCAssignFnForCall(CallConv, isVarArg));
24272426

24282427
// Get a count of how many bytes are to be pushed on the stack.
24292428
unsigned NumBytes = CCInfo.getStackSize();
@@ -2985,14 +2984,19 @@ bool MatchingStackOffset(SDValue Arg, unsigned Offset, ISD::ArgFlagsTy Flags,
29852984

29862985
/// IsEligibleForTailCallOptimization - Check whether the call is eligible
29872986
/// for tail call optimization. Targets which want to do tail call
2988-
/// optimization should implement this function.
2987+
/// optimization should implement this function. Note that this function also
2988+
/// processes musttail calls, so when this function returns false on a valid
2989+
/// musttail call, a fatal backend error occurs.
29892990
bool ARMTargetLowering::IsEligibleForTailCallOptimization(
2990-
SDValue Callee, CallingConv::ID CalleeCC, bool isVarArg,
2991-
bool isCalleeStructRet, bool isCallerStructRet,
2992-
const SmallVectorImpl<ISD::OutputArg> &Outs,
2993-
const SmallVectorImpl<SDValue> &OutVals,
2994-
const SmallVectorImpl<ISD::InputArg> &Ins, SelectionDAG &DAG,
2995-
const bool isIndirect) const {
2991+
TargetLowering::CallLoweringInfo &CLI, CCState &CCInfo,
2992+
SmallVectorImpl<CCValAssign> &ArgLocs, const bool isIndirect) const {
2993+
CallingConv::ID CalleeCC = CLI.CallConv;
2994+
SDValue Callee = CLI.Callee;
2995+
bool isVarArg = CLI.IsVarArg;
2996+
const SmallVectorImpl<ISD::OutputArg> &Outs = CLI.Outs;
2997+
const SmallVectorImpl<SDValue> &OutVals = CLI.OutVals;
2998+
const SmallVectorImpl<ISD::InputArg> &Ins = CLI.Ins;
2999+
const SelectionDAG &DAG = CLI.DAG;
29963000
MachineFunction &MF = DAG.getMachineFunction();
29973001
const Function &CallerF = MF.getFunction();
29983002
CallingConv::ID CallerCC = CallerF.getCallingConv();
@@ -3028,6 +3032,8 @@ bool ARMTargetLowering::IsEligibleForTailCallOptimization(
30283032

30293033
// Also avoid sibcall optimization if either caller or callee uses struct
30303034
// return semantics.
3035+
bool isCalleeStructRet = Outs.empty() ? false : Outs[0].Flags.isSRet();
3036+
bool isCallerStructRet = MF.getFunction().hasStructRetAttr();
30313037
if (isCalleeStructRet || isCallerStructRet)
30323038
return false;
30333039

@@ -3073,11 +3079,6 @@ bool ARMTargetLowering::IsEligibleForTailCallOptimization(
30733079
// If the callee takes no arguments then go on to check the results of the
30743080
// call.
30753081
if (!Outs.empty()) {
3076-
// Check if stack adjustment is needed. For now, do not do this if any
3077-
// argument is passed on the stack.
3078-
SmallVector<CCValAssign, 16> ArgLocs;
3079-
CCState CCInfo(CalleeCC, isVarArg, MF, ArgLocs, C);
3080-
CCInfo.AnalyzeCallOperands(Outs, CCAssignFnForCall(CalleeCC, isVarArg));
30813082
if (CCInfo.getStackSize()) {
30823083
// Check if the arguments are already laid out in the right way as
30833084
// the caller's fixed stack objects.

llvm/lib/Target/ARM/ARMISelLowering.h

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -943,12 +943,8 @@ class VectorType;
943943
/// for tail call optimization. Targets which want to do tail call
944944
/// optimization should implement this function.
945945
bool IsEligibleForTailCallOptimization(
946-
SDValue Callee, CallingConv::ID CalleeCC, bool isVarArg,
947-
bool isCalleeStructRet, bool isCallerStructRet,
948-
const SmallVectorImpl<ISD::OutputArg> &Outs,
949-
const SmallVectorImpl<SDValue> &OutVals,
950-
const SmallVectorImpl<ISD::InputArg> &Ins, SelectionDAG &DAG,
951-
const bool isIndirect) const;
946+
TargetLowering::CallLoweringInfo &CLI, CCState &CCInfo,
947+
SmallVectorImpl<CCValAssign> &ArgLocs, const bool isIndirect) const;
952948

953949
bool CanLowerReturn(CallingConv::ID CallConv,
954950
MachineFunction &MF, bool isVarArg,

llvm/lib/Target/X86/X86ISelLowering.h

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1632,10 +1632,8 @@ namespace llvm {
16321632
/// Check whether the call is eligible for tail call optimization. Targets
16331633
/// that want to do tail call optimization should implement this function.
16341634
bool IsEligibleForTailCallOptimization(
1635-
SDValue Callee, CallingConv::ID CalleeCC, bool IsCalleeStackStructRet,
1636-
bool isVarArg, Type *RetTy, const SmallVectorImpl<ISD::OutputArg> &Outs,
1637-
const SmallVectorImpl<SDValue> &OutVals,
1638-
const SmallVectorImpl<ISD::InputArg> &Ins, SelectionDAG &DAG) const;
1635+
TargetLowering::CallLoweringInfo &CLI, CCState &CCInfo,
1636+
SmallVectorImpl<CCValAssign> &ArgLocs, bool IsCalleePopSRet) const;
16391637
SDValue EmitTailCallLoadRetAddr(SelectionDAG &DAG, SDValue &OutRetAddr,
16401638
SDValue Chain, bool IsTailCall,
16411639
bool Is64Bit, int FPDiff,

llvm/lib/Target/X86/X86ISelLoweringCall.cpp

Lines changed: 36 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -2021,6 +2021,22 @@ X86TargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
20212021
if (CallConv == CallingConv::X86_INTR)
20222022
report_fatal_error("X86 interrupts may not be called directly");
20232023

2024+
// Analyze operands of the call, assigning locations to each operand.
2025+
SmallVector<CCValAssign, 16> ArgLocs;
2026+
CCState CCInfo(CallConv, isVarArg, MF, ArgLocs, *DAG.getContext());
2027+
2028+
// Allocate shadow area for Win64.
2029+
if (IsWin64)
2030+
CCInfo.AllocateStack(32, Align(8));
2031+
2032+
CCInfo.AnalyzeArguments(Outs, CC_X86);
2033+
2034+
// In vectorcall calling convention a second pass is required for the HVA
2035+
// types.
2036+
if (CallingConv::X86_VectorCall == CallConv) {
2037+
CCInfo.AnalyzeArgumentsSecondPass(Outs, CC_X86);
2038+
}
2039+
20242040
bool IsMustTail = CLI.CB && CLI.CB->isMustTailCall();
20252041
if (Subtarget.isPICStyleGOT() && !IsGuaranteeTCO && !IsMustTail) {
20262042
// If we are using a GOT, disable tail calls to external symbols with
@@ -2036,9 +2052,8 @@ X86TargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
20362052

20372053
if (isTailCall && !IsMustTail) {
20382054
// Check if it's really possible to do a tail call.
2039-
isTailCall = IsEligibleForTailCallOptimization(
2040-
Callee, CallConv, IsCalleePopSRet, isVarArg, CLI.RetTy, Outs, OutVals,
2041-
Ins, DAG);
2055+
isTailCall = IsEligibleForTailCallOptimization(CLI, CCInfo, ArgLocs,
2056+
IsCalleePopSRet);
20422057

20432058
// Sibcalls are automatically detected tailcalls which do not require
20442059
// ABI changes.
@@ -2056,22 +2071,6 @@ X86TargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
20562071
assert(!(isVarArg && canGuaranteeTCO(CallConv)) &&
20572072
"Var args not supported with calling convention fastcc, ghc or hipe");
20582073

2059-
// Analyze operands of the call, assigning locations to each operand.
2060-
SmallVector<CCValAssign, 16> ArgLocs;
2061-
CCState CCInfo(CallConv, isVarArg, MF, ArgLocs, *DAG.getContext());
2062-
2063-
// Allocate shadow area for Win64.
2064-
if (IsWin64)
2065-
CCInfo.AllocateStack(32, Align(8));
2066-
2067-
CCInfo.AnalyzeArguments(Outs, CC_X86);
2068-
2069-
// In vectorcall calling convention a second pass is required for the HVA
2070-
// types.
2071-
if (CallingConv::X86_VectorCall == CallConv) {
2072-
CCInfo.AnalyzeArgumentsSecondPass(Outs, CC_X86);
2073-
}
2074-
20752074
// Get a count of how many bytes are to be pushed on the stack.
20762075
unsigned NumBytes = CCInfo.getAlignedCallFrameSize();
20772076
if (IsSibcall)
@@ -2723,11 +2722,20 @@ bool MatchingStackOffset(SDValue Arg, unsigned Offset, ISD::ArgFlagsTy Flags,
27232722

27242723
/// Check whether the call is eligible for tail call optimization. Targets
27252724
/// that want to do tail call optimization should implement this function.
2725+
/// Note that the x86 backend does not check musttail calls for eligibility! The
2726+
/// rest of x86 tail call lowering must be prepared to forward arguments of any
2727+
/// type.
27262728
bool X86TargetLowering::IsEligibleForTailCallOptimization(
2727-
SDValue Callee, CallingConv::ID CalleeCC, bool IsCalleePopSRet,
2728-
bool isVarArg, Type *RetTy, const SmallVectorImpl<ISD::OutputArg> &Outs,
2729-
const SmallVectorImpl<SDValue> &OutVals,
2730-
const SmallVectorImpl<ISD::InputArg> &Ins, SelectionDAG &DAG) const {
2729+
TargetLowering::CallLoweringInfo &CLI, CCState &CCInfo,
2730+
SmallVectorImpl<CCValAssign> &ArgLocs, bool IsCalleePopSRet) const {
2731+
SelectionDAG &DAG = CLI.DAG;
2732+
const SmallVectorImpl<ISD::OutputArg> &Outs = CLI.Outs;
2733+
const SmallVectorImpl<SDValue> &OutVals = CLI.OutVals;
2734+
const SmallVectorImpl<ISD::InputArg> &Ins = CLI.Ins;
2735+
SDValue Callee = CLI.Callee;
2736+
CallingConv::ID CalleeCC = CLI.CallConv;
2737+
bool isVarArg = CLI.IsVarArg;
2738+
27312739
if (!mayTailCallThisCC(CalleeCC))
27322740
return false;
27332741

@@ -2738,7 +2746,7 @@ bool X86TargetLowering::IsEligibleForTailCallOptimization(
27382746
// If the function return type is x86_fp80 and the callee return type is not,
27392747
// then the FP_EXTEND of the call result is not a nop. It's not safe to
27402748
// perform a tailcall optimization here.
2741-
if (CallerF.getReturnType()->isX86_FP80Ty() && !RetTy->isX86_FP80Ty())
2749+
if (CallerF.getReturnType()->isX86_FP80Ty() && !CLI.RetTy->isX86_FP80Ty())
27422750
return false;
27432751

27442752
CallingConv::ID CallerCC = CallerF.getCallingConv();
@@ -2791,9 +2799,6 @@ bool X86TargetLowering::IsEligibleForTailCallOptimization(
27912799
if (IsCalleeWin64 || IsCallerWin64)
27922800
return false;
27932801

2794-
SmallVector<CCValAssign, 16> ArgLocs;
2795-
CCState CCInfo(CalleeCC, isVarArg, MF, ArgLocs, C);
2796-
CCInfo.AnalyzeCallOperands(Outs, CC_X86);
27972802
for (const auto &VA : ArgLocs)
27982803
if (!VA.isRegLoc())
27992804
return false;
@@ -2811,8 +2816,8 @@ bool X86TargetLowering::IsEligibleForTailCallOptimization(
28112816
}
28122817
if (Unused) {
28132818
SmallVector<CCValAssign, 16> RVLocs;
2814-
CCState CCInfo(CalleeCC, false, MF, RVLocs, C);
2815-
CCInfo.AnalyzeCallResult(Ins, RetCC_X86);
2819+
CCState RVCCInfo(CalleeCC, false, MF, RVLocs, C);
2820+
RVCCInfo.AnalyzeCallResult(Ins, RetCC_X86);
28162821
for (const auto &VA : RVLocs) {
28172822
if (VA.getLocReg() == X86::FP0 || VA.getLocReg() == X86::FP1)
28182823
return false;
@@ -2832,24 +2837,12 @@ bool X86TargetLowering::IsEligibleForTailCallOptimization(
28322837
return false;
28332838
}
28342839

2835-
unsigned StackArgsSize = 0;
2840+
unsigned StackArgsSize = CCInfo.getStackSize();
28362841

28372842
// If the callee takes no arguments then go on to check the results of the
28382843
// call.
28392844
if (!Outs.empty()) {
2840-
// Check if stack adjustment is needed. For now, do not do this if any
2841-
// argument is passed on the stack.
2842-
SmallVector<CCValAssign, 16> ArgLocs;
2843-
CCState CCInfo(CalleeCC, isVarArg, MF, ArgLocs, C);
2844-
2845-
// Allocate shadow area for Win64
2846-
if (IsCalleeWin64)
2847-
CCInfo.AllocateStack(32, Align(8));
2848-
2849-
CCInfo.AnalyzeCallOperands(Outs, CC_X86);
2850-
StackArgsSize = CCInfo.getStackSize();
2851-
2852-
if (CCInfo.getStackSize()) {
2845+
if (StackArgsSize > 0) {
28532846
// Check if the arguments are already laid out in the right way as
28542847
// the caller's fixed stack objects.
28552848
MachineFrameInfo &MFI = MF.getFrameInfo();

0 commit comments

Comments
 (0)