@@ -31,6 +31,8 @@ using namespace llvm;
31
31
32
32
#define DEBUG_TYPE " loongarch-isel-lowering"
33
33
34
+ STATISTIC (NumTailCalls, " Number of tail calls" );
35
+
34
36
static cl::opt<bool > ZeroDivCheck (
35
37
" loongarch-check-zero-division" , cl::Hidden,
36
38
cl::desc (" Trap on integer division by zero." ),
@@ -1334,6 +1336,7 @@ const char *LoongArchTargetLowering::getTargetNodeName(unsigned Opcode) const {
1334
1336
// TODO: Add more target-dependent nodes later.
1335
1337
NODE_NAME_CASE (CALL)
1336
1338
NODE_NAME_CASE (RET)
1339
+ NODE_NAME_CASE (TAIL)
1337
1340
NODE_NAME_CASE (SLL_W)
1338
1341
NODE_NAME_CASE (SRA_W)
1339
1342
NODE_NAME_CASE (SRL_W)
@@ -1808,6 +1811,48 @@ SDValue LoongArchTargetLowering::LowerFormalArguments(
1808
1811
return Chain;
1809
1812
}
1810
1813
1814
+ // Check whether the call is eligible for tail call optimization.
1815
+ bool LoongArchTargetLowering::isEligibleForTailCallOptimization (
1816
+ CCState &CCInfo, CallLoweringInfo &CLI, MachineFunction &MF,
1817
+ const SmallVectorImpl<CCValAssign> &ArgLocs) const {
1818
+
1819
+ auto CalleeCC = CLI.CallConv ;
1820
+ auto &Outs = CLI.Outs ;
1821
+ auto &Caller = MF.getFunction ();
1822
+ auto CallerCC = Caller.getCallingConv ();
1823
+
1824
+ // Do not tail call opt if the stack is used to pass parameters.
1825
+ if (CCInfo.getNextStackOffset () != 0 )
1826
+ return false ;
1827
+
1828
+ // Do not tail call opt if any parameters need to be passed indirectly.
1829
+ for (auto &VA : ArgLocs)
1830
+ if (VA.getLocInfo () == CCValAssign::Indirect)
1831
+ return false ;
1832
+
1833
+ // Do not tail call opt if either caller or callee uses struct return
1834
+ // semantics.
1835
+ auto IsCallerStructRet = Caller.hasStructRetAttr ();
1836
+ auto IsCalleeStructRet = Outs.empty () ? false : Outs[0 ].Flags .isSRet ();
1837
+ if (IsCallerStructRet || IsCalleeStructRet)
1838
+ return false ;
1839
+
1840
+ // Do not tail call opt if either the callee or caller has a byval argument.
1841
+ for (auto &Arg : Outs)
1842
+ if (Arg.Flags .isByVal ())
1843
+ return false ;
1844
+
1845
+ // The callee has to preserve all registers the caller needs to preserve.
1846
+ const LoongArchRegisterInfo *TRI = Subtarget.getRegisterInfo ();
1847
+ const uint32_t *CallerPreserved = TRI->getCallPreservedMask (MF, CallerCC);
1848
+ if (CalleeCC != CallerCC) {
1849
+ const uint32_t *CalleePreserved = TRI->getCallPreservedMask (MF, CalleeCC);
1850
+ if (!TRI->regmaskSubsetEqual (CallerPreserved, CalleePreserved))
1851
+ return false ;
1852
+ }
1853
+ return true ;
1854
+ }
1855
+
1811
1856
static Align getPrefTypeAlign (EVT VT, SelectionDAG &DAG) {
1812
1857
return DAG.getDataLayout ().getPrefTypeAlign (
1813
1858
VT.getTypeForEVT (*DAG.getContext ()));
@@ -1829,7 +1874,7 @@ LoongArchTargetLowering::LowerCall(CallLoweringInfo &CLI,
1829
1874
bool IsVarArg = CLI.IsVarArg ;
1830
1875
EVT PtrVT = getPointerTy (DAG.getDataLayout ());
1831
1876
MVT GRLenVT = Subtarget.getGRLenVT ();
1832
- CLI. IsTailCall = false ;
1877
+ bool & IsTailCall = CLI. IsTailCall ;
1833
1878
1834
1879
MachineFunction &MF = DAG.getMachineFunction ();
1835
1880
@@ -1839,6 +1884,16 @@ LoongArchTargetLowering::LowerCall(CallLoweringInfo &CLI,
1839
1884
1840
1885
analyzeOutputArgs (MF, ArgCCInfo, Outs, /* IsRet=*/ false , &CLI, CC_LoongArch);
1841
1886
1887
+ // Check if it's really possible to do a tail call.
1888
+ if (IsTailCall)
1889
+ IsTailCall = isEligibleForTailCallOptimization (ArgCCInfo, CLI, MF, ArgLocs);
1890
+
1891
+ if (IsTailCall)
1892
+ ++NumTailCalls;
1893
+ else if (CLI.CB && CLI.CB ->isMustTailCall ())
1894
+ report_fatal_error (" failed to perform tail call elimination on a call "
1895
+ " site marked musttail" );
1896
+
1842
1897
// Get a count of how many bytes are to be pushed on the stack.
1843
1898
unsigned NumBytes = ArgCCInfo.getNextStackOffset ();
1844
1899
@@ -1860,12 +1915,13 @@ LoongArchTargetLowering::LowerCall(CallLoweringInfo &CLI,
1860
1915
1861
1916
Chain = DAG.getMemcpy (Chain, DL, FIPtr, Arg, SizeNode, Alignment,
1862
1917
/* IsVolatile=*/ false ,
1863
- /* AlwaysInline=*/ false , /* isTailCall=*/ false ,
1918
+ /* AlwaysInline=*/ false , /* isTailCall=*/ IsTailCall ,
1864
1919
MachinePointerInfo (), MachinePointerInfo ());
1865
1920
ByValArgs.push_back (FIPtr);
1866
1921
}
1867
1922
1868
- Chain = DAG.getCALLSEQ_START (Chain, NumBytes, 0 , CLI.DL );
1923
+ if (!IsTailCall)
1924
+ Chain = DAG.getCALLSEQ_START (Chain, NumBytes, 0 , CLI.DL );
1869
1925
1870
1926
// Copy argument values to their designated locations.
1871
1927
SmallVector<std::pair<Register, SDValue>> RegsToPass;
@@ -1932,6 +1988,8 @@ LoongArchTargetLowering::LowerCall(CallLoweringInfo &CLI,
1932
1988
RegsToPass.push_back (std::make_pair (VA.getLocReg (), ArgValue));
1933
1989
} else {
1934
1990
assert (VA.isMemLoc () && " Argument not register or memory" );
1991
+ assert (!IsTailCall && " Tail call not allowed if stack is used "
1992
+ " for passing parameters" );
1935
1993
1936
1994
// Work out the address of the stack slot.
1937
1995
if (!StackPtr.getNode ())
@@ -1986,11 +2044,13 @@ LoongArchTargetLowering::LowerCall(CallLoweringInfo &CLI,
1986
2044
for (auto &Reg : RegsToPass)
1987
2045
Ops.push_back (DAG.getRegister (Reg.first , Reg.second .getValueType ()));
1988
2046
1989
- // Add a register mask operand representing the call-preserved registers.
1990
- const TargetRegisterInfo *TRI = Subtarget.getRegisterInfo ();
1991
- const uint32_t *Mask = TRI->getCallPreservedMask (MF, CallConv);
1992
- assert (Mask && " Missing call preserved mask for calling convention" );
1993
- Ops.push_back (DAG.getRegisterMask (Mask));
2047
+ if (!IsTailCall) {
2048
+ // Add a register mask operand representing the call-preserved registers.
2049
+ const TargetRegisterInfo *TRI = Subtarget.getRegisterInfo ();
2050
+ const uint32_t *Mask = TRI->getCallPreservedMask (MF, CallConv);
2051
+ assert (Mask && " Missing call preserved mask for calling convention" );
2052
+ Ops.push_back (DAG.getRegisterMask (Mask));
2053
+ }
1994
2054
1995
2055
// Glue the call to the argument copies, if any.
1996
2056
if (Glue.getNode ())
@@ -1999,6 +2059,11 @@ LoongArchTargetLowering::LowerCall(CallLoweringInfo &CLI,
1999
2059
// Emit the call.
2000
2060
SDVTList NodeTys = DAG.getVTList (MVT::Other, MVT::Glue);
2001
2061
2062
+ if (IsTailCall) {
2063
+ MF.getFrameInfo ().setHasTailCall ();
2064
+ return DAG.getNode (LoongArchISD::TAIL, DL, NodeTys, Ops);
2065
+ }
2066
+
2002
2067
Chain = DAG.getNode (LoongArchISD::CALL, DL, NodeTys, Ops);
2003
2068
DAG.addNoMergeSiteInfo (Chain.getNode (), CLI.NoMerge );
2004
2069
Glue = Chain.getValue (1 );
0 commit comments