Allow all types of callee's to be tail called. But avoid automatic tailcall if the...
[oota-llvm.git] / lib / Target / X86 / X86ISelLowering.cpp
index f868b75bd8b6e7b69253e041abc65dc40c9b5f37..9d6b5a39b2a0be14f19ee68074d7a1bebbbcbcc4 100644 (file)
@@ -1471,13 +1471,17 @@ X86TargetLowering::LowerMemArgument(SDValue Chain,
   // changed with more analysis.
   // In case of tail call optimization mark all arguments mutable. Since they
   // could be overwritten by lowering of arguments in case of a tail call.
-  int FI = MFI->CreateFixedObject(ValVT.getSizeInBits()/8,
-                                  VA.getLocMemOffset(), isImmutable, false);
-  SDValue FIN = DAG.getFrameIndex(FI, getPointerTy());
-  if (Flags.isByVal())
-    return FIN;
-  return DAG.getLoad(ValVT, dl, Chain, FIN,
-                     PseudoSourceValue::getFixedStack(FI), 0);
+  if (Flags.isByVal()) {
+    int FI = MFI->CreateFixedObject(Flags.getByValSize(),
+                                    VA.getLocMemOffset(), isImmutable, false);
+    return DAG.getFrameIndex(FI, getPointerTy());
+  } else {
+    int FI = MFI->CreateFixedObject(ValVT.getSizeInBits()/8,
+                                    VA.getLocMemOffset(), isImmutable, false);
+    SDValue FIN = DAG.getFrameIndex(FI, getPointerTy());
+    return DAG.getLoad(ValVT, dl, Chain, FIN,
+                       PseudoSourceValue::getFixedStack(FI), 0);
+  }
 }
 
 SDValue
@@ -1807,6 +1811,10 @@ X86TargetLowering::LowerCall(SDValue Chain, SDValue Callee,
   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) {
@@ -1976,9 +1984,11 @@ X86TargetLowering::LowerCall(SDValue Chain, SDValue Callee,
     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;
@@ -2246,27 +2256,74 @@ X86TargetLowering::IsEligibleForTailCallOptimization(SDValue Callee,
                                     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();
+  // Look for obvious safe cases to perform tail call optimization that does not
+  // requite ABI changes. This is what gcc calls sibcall.
 
-  return false;
+  // 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;
+        }
+      }
+    }
+  }
+
+  return true;
 }
 
 FastISel *