}
SDValue
-X86TargetLowering::LowerCall(SDValue Chain, SDValue Callee,
+X86TargetLowering::LowerCall(SDValue Chain, SDValue Callee, const Type *RetTy,
CallingConv::ID CallConv, bool isVarArg,
bool &isTailCall,
const SmallVectorImpl<ISD::OutputArg> &Outs,
if (isTailCall)
// Check if it's really possible to do a tail call.
- isTailCall = IsEligibleForTailCallOptimization(Callee, CallConv, isVarArg,
- Outs, Ins, DAG);
+ isTailCall = IsEligibleForTailCallOptimization(Callee, RetTy, CallConv,
+ isVarArg, Outs, Ins, DAG);
assert(!(isVarArg && CallConv == CallingConv::Fast) &&
"Var args not supported with calling convention fastcc");
unsigned NumBytes = CCInfo.getNextStackOffset();
if (FuncIsMadeTailCallSafe(CallConv))
NumBytes = GetAlignedArgumentStackSize(NumBytes, DAG);
+ else if (isTailCall && !PerformTailCallOpt)
+ // This is a sibcall. The memory operands are available in caller's
+ // own caller's stack.
+ NumBytes = 0;
int FPDiff = 0;
if (isTailCall) {
int FI = 0;
// Do not flag preceeding copytoreg stuff together with the following stuff.
InFlag = SDValue();
- for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
- CCValAssign &VA = ArgLocs[i];
- if (!VA.isRegLoc()) {
+ if (PerformTailCallOpt) {
+ for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
+ CCValAssign &VA = ArgLocs[i];
+ if (VA.isRegLoc())
+ continue;
assert(VA.isMemLoc());
SDValue Arg = Outs[i].Val;
ISD::ArgFlagsTy Flags = Outs[i].Flags;
/// optimization should implement this function.
bool
X86TargetLowering::IsEligibleForTailCallOptimization(SDValue Callee,
+ const Type *RetTy,
CallingConv::ID CalleeCC,
bool isVarArg,
const SmallVectorImpl<ISD::OutputArg> &Outs,
const SmallVectorImpl<ISD::InputArg> &Ins,
SelectionDAG& DAG) const {
- // If -tailcallopt is specified, make fastcc functions tail-callable.
- const Function *F = DAG.getMachineFunction().getFunction();
- if (PerformTailCallOpt &&
- CalleeCC == CallingConv::Fast && F->getCallingConv() == CalleeCC)
- return true;
-
if (CalleeCC != CallingConv::Fast &&
CalleeCC != CallingConv::C)
return false;
- // Look for obvious safe cases to perform tail call optimization.
- // For now, only consider callees which take no arguments and no return
- // values.
- if (!Outs.empty())
+ // If -tailcallopt is specified, make fastcc functions tail-callable.
+ const Function *CallerF = DAG.getMachineFunction().getFunction();
+ if (PerformTailCallOpt) {
+ if (CalleeCC == CallingConv::Fast &&
+ CallerF->getCallingConv() == CalleeCC)
+ return true;
return false;
+ }
- if (Ins.empty())
- // If the caller does not return a value, then this is obviously safe.
- return F->getReturnType()->isVoidTy();
- return false;
+ // Look for obvious safe cases to perform tail call optimization that does not
+ // requite ABI changes. This is what gcc calls sibcall.
+
+ // Do not tail call optimize vararg calls for now.
+ if (isVarArg)
+ return false;
+
+ // If the callee takes no arguments then go on to check the results of the
+ // call.
+ if (!Outs.empty()) {
+ // Check if stack adjustment is needed. For now, do not do this if any
+ // argument is passed on the stack.
+ SmallVector<CCValAssign, 16> ArgLocs;
+ CCState CCInfo(CalleeCC, isVarArg, getTargetMachine(),
+ ArgLocs, *DAG.getContext());
+ CCInfo.AnalyzeCallOperands(Outs, CCAssignFnForNode(CalleeCC));
+ if (CCInfo.getNextStackOffset()) {
+ MachineFunction &MF = DAG.getMachineFunction();
+ if (MF.getInfo<X86MachineFunctionInfo>()->getBytesToPopOnReturn())
+ return false;
+ if (Subtarget->isTargetWin64())
+ // Win64 ABI has additional complications.
+ return false;
+
+ // Check if the arguments are already laid out in the right way as
+ // the caller's fixed stack objects.
+ MachineFrameInfo *MFI = MF.getFrameInfo();
+ for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
+ CCValAssign &VA = ArgLocs[i];
+ EVT RegVT = VA.getLocVT();
+ SDValue Arg = Outs[i].Val;
+ ISD::ArgFlagsTy Flags = Outs[i].Flags;
+ if (Flags.isByVal())
+ return false; // TODO
+ if (VA.getLocInfo() == CCValAssign::Indirect)
+ return false;
+ if (!VA.isRegLoc()) {
+ LoadSDNode *Ld = dyn_cast<LoadSDNode>(Arg);
+ if (!Ld)
+ return false;
+ SDValue Ptr = Ld->getBasePtr();
+ FrameIndexSDNode *FINode = dyn_cast<FrameIndexSDNode>(Ptr);
+ if (!FINode)
+ return false;
+ int FI = FINode->getIndex();
+ if (!MFI->isFixedObjectIndex(FI))
+ return false;
+ if (VA.getLocMemOffset() != MFI->getObjectOffset(FI))
+ return false;
+ }
+ }
+ }
+ }
+
+ // If the caller does not return a value, then this is obviously safe.
+ // This is one case where it's safe to perform this optimization even
+ // if the return types do not match.
+ const Type *CallerRetTy = CallerF->getReturnType();
+ if (CallerRetTy->isVoidTy())
+ return true;
+
+ // If the return types match, then it's safe.
+ return CallerRetTy == RetTy;
}
FastISel *
N2C && N2C->isNullValue() &&
RHSC && RHSC->isNullValue()) {
SDValue CmpOp0 = Cmp.getOperand(0);
- Cmp = DAG.getNode(X86ISD::CMP, dl, Op.getValueType(),
+ Cmp = DAG.getNode(X86ISD::CMP, dl, CmpOp0.getValueType(),
CmpOp0, DAG.getConstant(1, CmpOp0.getValueType()));
return DAG.getNode(X86ISD::SETCC_CARRY, dl, Op.getValueType(),
DAG.getConstant(X86::COND_B, MVT::i8), Cmp);