summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--llvm/lib/Target/X86/X86ISelLowering.cpp55
-rw-r--r--llvm/test/CodeGen/X86/tailcall2.ll13
2 files changed, 62 insertions, 6 deletions
diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp
index a8308b80a96..d05de21be3d 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.cpp
+++ b/llvm/lib/Target/X86/X86ISelLowering.cpp
@@ -1807,6 +1807,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 +1980,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;
@@ -2259,11 +2265,14 @@ X86TargetLowering::IsEligibleForTailCallOptimization(SDValue Callee,
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;
- // Look for obvious safe cases to perform tail call optimization.
// If the callee takes no arguments then go on to check the results of the
// call.
if (!Outs.empty()) {
@@ -2273,8 +2282,42 @@ X86TargetLowering::IsEligibleForTailCallOptimization(SDValue Callee,
CCState CCInfo(CalleeCC, isVarArg, getTargetMachine(),
ArgLocs, *DAG.getContext());
CCInfo.AnalyzeCallOperands(Outs, CCAssignFnForNode(CalleeCC));
- if (CCInfo.getNextStackOffset())
- return false;
+ 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.
diff --git a/llvm/test/CodeGen/X86/tailcall2.ll b/llvm/test/CodeGen/X86/tailcall2.ll
index 1e288f57651..e41e3da4f80 100644
--- a/llvm/test/CodeGen/X86/tailcall2.ll
+++ b/llvm/test/CodeGen/X86/tailcall2.ll
@@ -89,3 +89,16 @@ bb1:
}
declare i32 @bar(i32)
+
+define i32 @t7(i32 %a, i32 %b, i32 %c) nounwind ssp {
+entry:
+; 32: t7:
+; 32: jmp {{_?}}bar2
+
+; 64: t7:
+; 64: jmp {{_?}}bar2
+ %0 = tail call i32 @bar2(i32 %a, i32 %b, i32 %c) nounwind
+ ret i32 %0
+}
+
+declare i32 @bar2(i32, i32, i32)
OpenPOWER on IntegriCloud